diff options
71 files changed, 1059 insertions, 789 deletions
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp index c18d3f5021..50c2cd8be2 100644 --- a/cmds/idlcli/Android.bp +++ b/cmds/idlcli/Android.bp @@ -24,7 +24,7 @@ package { cc_defaults { name: "idlcli-defaults", shared_libs: [ - "android.hardware.vibrator-V2-ndk", + "android.hardware.vibrator-V3-ndk", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h index e100eacdd5..b9434950f6 100644 --- a/cmds/idlcli/vibrator.h +++ b/cmds/idlcli/vibrator.h @@ -49,7 +49,7 @@ inline ndk::ScopedAStatus NullptrStatus() { template <typename I> inline auto getService(std::string name) { const auto instance = std::string() + I::descriptor + "/" + name; - auto vibBinder = ndk::SpAIBinder(AServiceManager_getService(instance.c_str())); + auto vibBinder = ndk::SpAIBinder(AServiceManager_checkService(instance.c_str())); return I::fromBinder(vibBinder); } diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index 0f251d2b2a..c44e540c6d 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -29,6 +29,7 @@ #include <thread> #if !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) +#include "perfetto/public/protos/trace/android/android_track_event.pzc.h" #include "perfetto/public/te_category_macros.h" #include "perfetto/public/te_macros.h" #endif // !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) @@ -57,6 +58,12 @@ PERFETTO_TE_CATEGORIES_DEFINE(PERFETTO_SM_CATEGORIES); #define SM_PERFETTO_TRACE_FUNC(...) \ PERFETTO_TE_SCOPED(servicemanager, PERFETTO_TE_SLICE_BEGIN(__func__) __VA_OPT__(, ) __VA_ARGS__) +constexpr uint32_t kProtoServiceName = + perfetto_protos_AndroidTrackEvent_binder_service_name_field_number; +constexpr uint32_t kProtoInterfaceName = + perfetto_protos_AndroidTrackEvent_binder_interface_name_field_number; +constexpr uint32_t kProtoApexName = perfetto_protos_AndroidTrackEvent_apex_name_field_number; + #endif // !(defined(VENDORSERVICEMANAGER) || defined(__ANDROID_RECOVERY__)) bool is_multiuser_uid_isolated(uid_t uid) { @@ -112,13 +119,15 @@ struct AidlName { std::string iface; std::string instance; - static bool fill(const std::string& name, AidlName* aname) { + static bool fill(const std::string& name, AidlName* aname, bool logError) { size_t firstSlash = name.find('/'); size_t lastDot = name.rfind('.', firstSlash); if (firstSlash == std::string::npos || lastDot == std::string::npos) { - ALOGE("VINTF HALs require names in the format type/instance (e.g. " - "some.package.foo.IFoo/default) but got: %s", - name.c_str()); + if (logError) { + ALOGE("VINTF HALs require names in the format type/instance (e.g. " + "some.package.foo.IFoo/default) but got: %s", + name.c_str()); + } return false; } aname->package = name.substr(0, lastDot); @@ -151,7 +160,7 @@ static bool isVintfDeclared(const Access::CallingContext& ctx, const std::string } AidlName aname; - if (!AidlName::fill(name, &aname)) return false; + if (!AidlName::fill(name, &aname, true)) return false; bool found = forEachManifest([&](const ManifestWithDescription& mwd) { if (mwd.manifest->hasAidlInstance(aname.package, aname.iface, aname.instance)) { @@ -209,7 +218,7 @@ static std::optional<std::string> getVintfUpdatableApex(const std::string& name) } AidlName aname; - if (!AidlName::fill(name, &aname)) return std::nullopt; + if (!AidlName::fill(name, &aname, true)) return std::nullopt; std::optional<std::string> updatableViaApex; @@ -251,7 +260,7 @@ static std::vector<std::string> getVintfUpdatableNames(const std::string& apexNa static std::optional<std::string> getVintfAccessorName(const std::string& name) { AidlName aname; - if (!AidlName::fill(name, &aname)) return std::nullopt; + if (!AidlName::fill(name, &aname, false)) return std::nullopt; std::optional<std::string> accessor; forEachManifest([&](const ManifestWithDescription& mwd) { @@ -270,7 +279,7 @@ static std::optional<std::string> getVintfAccessorName(const std::string& name) static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) { AidlName aname; - if (!AidlName::fill(name, &aname)) return std::nullopt; + if (!AidlName::fill(name, &aname, true)) return std::nullopt; std::optional<std::string> ip; std::optional<uint64_t> port; @@ -384,7 +393,8 @@ ServiceManager::~ServiceManager() { } Status ServiceManager::getService(const std::string& name, os::Service* outService) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); *outService = tryGetService(name, true); // returns ok regardless of result for legacy reasons @@ -392,7 +402,8 @@ Status ServiceManager::getService(const std::string& name, os::Service* outServi } Status ServiceManager::checkService(const std::string& name, os::Service* outService) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); *outService = tryGetService(name, false); // returns ok regardless of result for legacy reasons @@ -417,7 +428,8 @@ os::Service ServiceManager::tryGetService(const std::string& name, bool startIfN } sp<IBinder> ServiceManager::tryGetBinder(const std::string& name, bool startIfNotFound) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); auto ctx = mAccess->getCallingContext(); @@ -457,7 +469,8 @@ sp<IBinder> ServiceManager::tryGetBinder(const std::string& name, bool startIfNo } bool isValidServiceName(const std::string& name) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); if (name.size() == 0) return false; if (name.size() > 127) return false; @@ -474,7 +487,8 @@ bool isValidServiceName(const std::string& name) { } Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); auto ctx = mAccess->getCallingContext(); @@ -597,7 +611,8 @@ Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::strin Status ServiceManager::registerForNotifications( const std::string& name, const sp<IServiceCallback>& callback) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); auto ctx = mAccess->getCallingContext(); @@ -648,7 +663,8 @@ Status ServiceManager::registerForNotifications( } Status ServiceManager::unregisterForNotifications( const std::string& name, const sp<IServiceCallback>& callback) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); auto ctx = mAccess->getCallingContext(); @@ -674,7 +690,8 @@ Status ServiceManager::unregisterForNotifications( } Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); auto ctx = mAccess->getCallingContext(); @@ -692,7 +709,8 @@ Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) { } binder::Status ServiceManager::getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("interface", interface.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoInterfaceName, interface.c_str()))); auto ctx = mAccess->getCallingContext(); @@ -720,7 +738,8 @@ binder::Status ServiceManager::getDeclaredInstances(const std::string& interface Status ServiceManager::updatableViaApex(const std::string& name, std::optional<std::string>* outReturn) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); auto ctx = mAccess->getCallingContext(); @@ -739,7 +758,8 @@ Status ServiceManager::updatableViaApex(const std::string& name, Status ServiceManager::getUpdatableNames([[maybe_unused]] const std::string& apexName, std::vector<std::string>* outReturn) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("apexName", apexName.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoApexName, apexName.c_str()))); auto ctx = mAccess->getCallingContext(); @@ -765,7 +785,8 @@ Status ServiceManager::getUpdatableNames([[maybe_unused]] const std::string& ape Status ServiceManager::getConnectionInfo(const std::string& name, std::optional<ConnectionInfo>* outReturn) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); auto ctx = mAccess->getCallingContext(); @@ -850,7 +871,8 @@ void ServiceManager::tryStartService(const Access::CallingContext& ctx, const st Status ServiceManager::registerClientCallback(const std::string& name, const sp<IBinder>& service, const sp<IClientCallback>& cb) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); if (cb == nullptr) { return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Callback null."); @@ -1012,7 +1034,8 @@ void ServiceManager::sendClientCallbackNotifications(const std::string& serviceN } Status ServiceManager::tryUnregisterService(const std::string& name, const sp<IBinder>& binder) { - SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS( + PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str()))); if (binder == nullptr) { return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Null service."); diff --git a/include/ftl/fake_guard.h b/include/ftl/fake_guard.h index e6012516fc..0bf2870b69 100644 --- a/include/ftl/fake_guard.h +++ b/include/ftl/fake_guard.h @@ -76,12 +76,8 @@ struct [[clang::scoped_lockable]] FakeGuard final { FTL_ATTRIBUTE(release_capability(mutex)) #endif -// The parentheses around `expr` are needed to deduce an lvalue or rvalue reference. -#define FTL_FAKE_GUARD2(mutex, expr) \ - [&]() -> decltype(auto) { \ - const android::ftl::FakeGuard guard(mutex); \ - return (expr); \ - }() +#define FTL_FAKE_GUARD2(mutex, expr) \ + (android::ftl::FakeGuard(mutex), expr) #define FTL_MAKE_FAKE_GUARD(arg1, arg2, guard, ...) guard diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index 4c7684ccb7..dd50fbdc38 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -235,6 +235,16 @@ cc_defaults { "binder_test_defaults", ], + compile_multilib: "both", + multilib: { + lib32: { + suffix: "32", + }, + lib64: { + suffix: "64", + }, + }, + static_libs: [ "libbinder_test_utils", "libbinder_tls_static", @@ -267,7 +277,6 @@ cc_defaults { defaults: [ "binderRpcTest_common_defaults", ], - compile_multilib: "first", srcs: [ "binderRpcTest.cpp", diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 3efd84f145..cd78e82322 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -19,6 +19,12 @@ #include <aidl/IBinderRpcTest.h> #endif +#if defined(__LP64__) +#define TEST_FILE_SUFFIX "64" +#else +#define TEST_FILE_SUFFIX "32" +#endif + #include <chrono> #include <cstdlib> #include <iostream> @@ -259,7 +265,8 @@ std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc( std::string path = GetExecutableDirectory(); auto servicePath = path + "/binder_rpc_test_service" + - (singleThreaded ? "_single_threaded" : "") + (noKernel ? "_no_kernel" : ""); + (singleThreaded ? "_single_threaded" : "") + (noKernel ? "_no_kernel" : "") + + TEST_FILE_SUFFIX; unique_fd bootstrapClientFd, socketFd; diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp index 81f6a585ab..44cdc02c0e 100644 --- a/libs/cputimeinstate/testtimeinstate.cpp +++ b/libs/cputimeinstate/testtimeinstate.cpp @@ -41,7 +41,7 @@ static constexpr uint64_t NSEC_PER_SEC = 1000000000; static constexpr uint64_t NSEC_PER_YEAR = NSEC_PER_SEC * 60 * 60 * 24 * 365; // Declare busy loop variable globally to prevent removal during optimization -static long sum __attribute__((used)) = 0; +static volatile long sum __attribute__((used)) = 1; using std::vector; @@ -579,8 +579,8 @@ uint64_t timeNanos() { // Keeps CPU busy with some number crunching void useCpu() { - sum = 0; - for (int i = 0; i < 100000; i++) { + sum = 1; + for (int i = 1; i < 100000; i++) { sum *= i; } } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index ff6b558d41..269936858a 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -62,7 +62,7 @@ public: status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, - const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, + Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, InputWindowCommands commands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId, diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS index 070f6bf532..5a9644b77f 100644 --- a/libs/gui/OWNERS +++ b/libs/gui/OWNERS @@ -9,10 +9,10 @@ per-file EndToEndNativeInputTest.cpp = svv@google.com # BufferQueue is feature-frozen per-file BufferQueue* = set noparent -per-file BufferQueue* = jreck@google.com, sumir@google.com, alecmouri@google.com +per-file BufferQueue* = jreck@google.com, sumir@google.com, alecmouri@google.com, jshargo@google.com, carlosmr@google.com per-file IGraphicBuffer* = set noparent -per-file IGraphicBuffer* = jreck@google.com, sumir@google.com, alecmouri@google.com +per-file IGraphicBuffer* = jreck@google.com, sumir@google.com, alecmouri@google.com, jshargo@google.com, carlosmr@google.com per-file include/gui/BufferQueue* = set noparent -per-file include/gui/BufferQueue* = jreck@google.com, sumir@google.com, alecmouri@google.com +per-file include/gui/BufferQueue* = jreck@google.com, sumir@google.com, alecmouri@google.com, jshargo@google.com, carlosmr@google.com per-file include/gui/IGraphicBuffer* = set noparent -per-file include/gui/IGraphicBuffer* = jreck@google.com, sumir@google.com, alecmouri@google.com +per-file include/gui/IGraphicBuffer* = jreck@google.com, sumir@google.com, alecmouri@google.com, jshargo@google.com, carlosmr@google.com diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 87fd448f0c..eb9faf584b 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -21,6 +21,8 @@ #include <gui/Surface.h> #include <condition_variable> +#include <cstddef> +#include <cstdint> #include <deque> #include <mutex> #include <thread> @@ -44,8 +46,6 @@ #include <gui/AidlStatusUtil.h> #include <gui/BufferItem.h> -#include <gui/IProducerListener.h> - #include <gui/ISurfaceComposer.h> #include <gui/LayerState.h> #include <private/gui/ComposerService.h> @@ -163,6 +163,12 @@ void Surface::allocateBuffers() { mReqFormat, mReqUsage); } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) +status_t Surface::allowAllocation(bool allowAllocation) { + return mGraphicBufferProducer->allowAllocation(allowAllocation); +} +#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) + status_t Surface::setGenerationNumber(uint32_t generation) { status_t result = mGraphicBufferProducer->setGenerationNumber(generation); if (result == NO_ERROR) { @@ -695,6 +701,50 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { return OK; } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) + +status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer, sp<Fence>* outFence) { + if (buffer == nullptr || outFence == nullptr) { + return BAD_VALUE; + } + + android_native_buffer_t* anb; + int fd = -1; + status_t res = dequeueBuffer(&anb, &fd); + *buffer = GraphicBuffer::from(anb); + *outFence = sp<Fence>::make(fd); + return res; +} + +status_t Surface::queueBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& fd) { + if (buffer == nullptr) { + return BAD_VALUE; + } + return queueBuffer(buffer.get(), fd ? fd->get() : -1); +} + +status_t Surface::detachBuffer(const sp<GraphicBuffer>& buffer) { + if (nullptr == buffer) { + return BAD_VALUE; + } + + Mutex::Autolock lock(mMutex); + + uint64_t bufferId = buffer->getId(); + for (int slot = 0; slot < Surface::NUM_BUFFER_SLOTS; ++slot) { + auto& bufferSlot = mSlots[slot]; + if (bufferSlot.buffer != nullptr && bufferSlot.buffer->getId() == bufferId) { + bufferSlot.buffer = nullptr; + bufferSlot.dirtyRegion = Region::INVALID_REGION; + return mGraphicBufferProducer->detachBuffer(slot); + } + } + + return BAD_VALUE; +} + +#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) + int Surface::dequeueBuffers(std::vector<BatchBuffer>* buffers) { using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput; using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput; @@ -1860,30 +1910,31 @@ bool Surface::transformToDisplayInverse() const { } int Surface::connect(int api) { - static sp<IProducerListener> listener = new StubProducerListener(); + static sp<SurfaceListener> listener = new StubSurfaceListener(); return connect(api, listener); } -int Surface::connect(int api, const sp<IProducerListener>& listener) { +int Surface::connect(int api, const sp<SurfaceListener>& listener) { return connect(api, listener, false); } int Surface::connect( int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) { - if (sListener != nullptr) { - mListenerProxy = new ProducerListenerProxy(this, sListener); - } - return connect(api, mListenerProxy, reportBufferRemoval); + return connect(api, sListener, reportBufferRemoval); } -int Surface::connect( - int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) { +int Surface::connect(int api, const sp<SurfaceListener>& listener, bool reportBufferRemoval) { ATRACE_CALL(); ALOGV("Surface::connect"); Mutex::Autolock lock(mMutex); IGraphicBufferProducer::QueueBufferOutput output; mReportRemovedBuffers = reportBufferRemoval; - int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output); + if (listener != nullptr) { + mListenerProxy = new ProducerListenerProxy(this, listener); + } + + int err = + mGraphicBufferProducer->connect(mListenerProxy, api, mProducerControlledByApp, &output); if (err == NO_ERROR) { mDefaultWidth = output.width; mDefaultHeight = output.height; @@ -1911,7 +1962,6 @@ int Surface::connect( return err; } - int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) { ATRACE_CALL(); ALOGV("Surface::disconnect"); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2821b510c3..e86e13d3ee 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1174,7 +1174,8 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.token = BufferCache::getInstance().getToken(); uncacheBuffer.id = cacheId; Vector<ComposerState> composerStates; - status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, {}, + Vector<DisplayState> displayStates; + status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, displayStates, ISurfaceComposer::eOneWay, Transaction::getDefaultApplyToken(), {}, systemTime(), true, {uncacheBuffer}, false, {}, generateId(), {}); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index eb4a802c17..1ecc216dff 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -112,7 +112,7 @@ public: /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, - const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, + Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index bdcaaf2866..d07e121d6e 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -18,6 +18,7 @@ #define ANDROID_GUI_SURFACE_H #include <android/gui/FrameTimelineInfo.h> +#include <com_android_graphics_libgui_flags.h> #include <gui/BufferQueueDefs.h> #include <gui/HdrMetadata.h> #include <gui/IGraphicBufferProducer.h> @@ -35,6 +36,8 @@ namespace android { +class GraphicBuffer; + namespace gui { class ISurfaceComposer; } // namespace gui @@ -56,6 +59,16 @@ public: virtual bool needsReleaseNotify() = 0; virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) = 0; + virtual void onBufferDetached(int slot) = 0; +}; + +class StubSurfaceListener : public SurfaceListener { +public: + virtual ~StubSurfaceListener() {} + virtual void onBufferReleased() override {} + virtual bool needsReleaseNotify() { return false; } + virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& /*buffers*/) override {} + virtual void onBufferDetached(int /*slot*/) override {} }; /* @@ -154,6 +167,11 @@ public: */ virtual void allocateBuffers(); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) + // See IGraphicBufferProducer::allowAllocation + status_t allowAllocation(bool allowAllocation); +#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) + /* Sets the generation number on the IGraphicBufferProducer and updates the * generation number on any buffers attached to the Surface after this call. * See IGBP::setGenerationNumber for more information. */ @@ -357,15 +375,13 @@ public: virtual int unlockAndPost(); virtual int query(int what, int* value) const; - virtual int connect(int api, const sp<IProducerListener>& listener); + virtual int connect(int api, const sp<SurfaceListener>& listener); // When reportBufferRemoval is true, clients must call getAndFlushRemovedBuffers to fetch // GraphicBuffers removed from this surface after a dequeueBuffer, detachNextBuffer or // attachBuffer call. This allows clients with their own buffer caches to free up buffers no // longer in use by this surface. - virtual int connect( - int api, const sp<IProducerListener>& listener, - bool reportBufferRemoval); + virtual int connect(int api, const sp<SurfaceListener>& listener, bool reportBufferRemoval); virtual int detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence); virtual int attachBuffer(ANativeWindowBuffer*); @@ -387,6 +403,20 @@ public: static status_t attachAndQueueBufferWithDataspace(Surface* surface, sp<GraphicBuffer> buffer, ui::Dataspace dataspace); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) + // Dequeues a buffer and its outFence, which must be signalled before the buffer can be used. + status_t dequeueBuffer(sp<GraphicBuffer>* buffer, sp<Fence>* outFence); + + // Queues a buffer, with an optional fd fence that captures pending work on the buffer. This + // buffer must have been returned by dequeueBuffer or associated with this Surface via an + // attachBuffer operation. + status_t queueBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& fd = Fence::NO_FENCE); + + // Detaches this buffer, dissociating it from this Surface. This buffer must have been returned + // by queueBuffer or associated with this Surface via an attachBuffer operation. + status_t detachBuffer(const sp<GraphicBuffer>& buffer); +#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) + // Batch version of dequeueBuffer, cancelBuffer and queueBuffer // Note that these batched operations are not supported when shared buffer mode is being used. struct BatchBuffer { @@ -422,6 +452,8 @@ protected: return mSurfaceListener->needsReleaseNotify(); } + virtual void onBufferDetached(int slot) { mSurfaceListener->onBufferDetached(slot); } + virtual void onBuffersDiscarded(const std::vector<int32_t>& slots); private: wp<Surface> mParent; diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig index 74d806ec79..c79a2b7569 100644 --- a/libs/gui/libgui_flags.aconfig +++ b/libs/gui/libgui_flags.aconfig @@ -45,9 +45,33 @@ flag { } # wb_platform_api_improvements flag { + name: "wb_stream_splitter" + namespace: "core_graphics" + description: "Removes IGBP/IGBCs from Camera3StreamSplitter as part of BufferQueue refactors" + bug: "340933206" + is_fixed_read_only: true +} # wb_stream_splitter + +flag { name: "edge_extension_shader" namespace: "windowing_frontend" description: "Enable edge extension via shader" bug: "322036393" is_fixed_read_only: true } # edge_extension_shader + +flag { + name: "buffer_release_channel" + namespace: "window_surfaces" + description: "Enable BufferReleaseChannel to optimize buffer releases" + bug: "294133380" + is_fixed_read_only: true +} # buffer_release_channel + +flag { + name: "wb_surface_connect_methods" + namespace: "core_graphics" + description: "Remove redundant connect methods in Surface." + bug: "354273690" + is_fixed_read_only: true +} # wb_surface_connect_methods diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp index ea8acbbb72..b342a7db0d 100644 --- a/libs/gui/tests/Android.bp +++ b/libs/gui/tests/Android.bp @@ -25,6 +25,7 @@ cc_test { "-Wthread-safety", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_SETFRAMERATE=true", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_EXTENDEDALLOCATE=true", + "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_WB_PLATFORM_API_IMPROVEMENTS=true", ], srcs: [ diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 946ff058cf..6852589e32 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -1269,6 +1269,20 @@ public: } }; +class TestSurfaceListener : public SurfaceListener { +public: + sp<IGraphicBufferProducer> mIgbp; + TestSurfaceListener(const sp<IGraphicBufferProducer>& igbp) : mIgbp(igbp) {} + void onBufferReleased() override { + sp<GraphicBuffer> buffer; + sp<Fence> fence; + mIgbp->detachNextBuffer(&buffer, &fence); + } + bool needsReleaseNotify() override { return true; } + void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& /*buffers*/) override {} + void onBufferDetached(int /*slot*/) {} +}; + TEST_F(BLASTBufferQueueTest, CustomProducerListener) { BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); sp<IGraphicBufferProducer> igbProducer = adapter.getIGraphicBufferProducer(); @@ -1327,7 +1341,7 @@ TEST_F(BLASTBufferQueueTest, TransformHint) { ASSERT_EQ(ui::Transform::ROT_0, static_cast<ui::Transform::RotationFlags>(transformHint)); ASSERT_EQ(NO_ERROR, - surface->connect(NATIVE_WINDOW_API_CPU, new TestProducerListener(igbProducer))); + surface->connect(NATIVE_WINDOW_API_CPU, new TestSurfaceListener(igbProducer))); // After connecting to the surface, we should get the correct hint. surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ace442339d..8d6917f3a6 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -24,24 +24,26 @@ #include <android/gui/ISurfaceComposer.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <binder/ProcessState.h> +#include <com_android_graphics_libgui_flags.h> #include <configstore/Utils.h> #include <gui/AidlStatusUtil.h> #include <gui/BufferItemConsumer.h> -#include <gui/IProducerListener.h> +#include <gui/CpuConsumer.h> #include <gui/ISurfaceComposer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <gui/SyncScreenCaptureListener.h> -#include <inttypes.h> #include <private/gui/ComposerService.h> #include <private/gui/ComposerServiceAIDL.h> #include <sys/types.h> #include <ui/BufferQueueDefs.h> #include <ui/DisplayMode.h> +#include <ui/GraphicBuffer.h> #include <ui/Rect.h> #include <utils/Errors.h> #include <utils/String8.h> +#include <cstddef> #include <limits> #include <thread> @@ -82,7 +84,7 @@ public: virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) { mDiscardedBuffers.insert(mDiscardedBuffers.end(), buffers.begin(), buffers.end()); } - + virtual void onBufferDetached(int /*slot*/) {} int getReleaseNotifyCount() const { return mBuffersReleased; } @@ -491,7 +493,7 @@ TEST_F(SurfaceTest, GetAndFlushRemovedBuffers) { sp<Surface> surface = new Surface(producer); sp<ANativeWindow> window(surface); - sp<StubProducerListener> listener = new StubProducerListener(); + sp<StubSurfaceListener> listener = new StubSurfaceListener(); ASSERT_EQ(OK, surface->connect( NATIVE_WINDOW_API_CPU, /*listener*/listener, @@ -636,7 +638,7 @@ public: status_t setTransactionState( const FrameTimelineInfo& /*frameTimelineInfo*/, Vector<ComposerState>& /*state*/, - const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/, + Vector<DisplayState>& /*displays*/, uint32_t /*flags*/, const sp<IBinder>& /*applyToken*/, InputWindowCommands /*inputWindowCommands*/, int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const std::vector<client_cache_t>& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, @@ -2154,7 +2156,7 @@ TEST_F(SurfaceTest, BatchOperations) { sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1); sp<Surface> surface = new Surface(producer); sp<ANativeWindow> window(surface); - sp<StubProducerListener> listener = new StubProducerListener(); + sp<StubSurfaceListener> listener = new StubSurfaceListener(); ASSERT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, /*listener*/listener, /*reportBufferRemoval*/false)); @@ -2206,7 +2208,7 @@ TEST_F(SurfaceTest, BatchIllegalOperations) { sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1); sp<Surface> surface = new Surface(producer); sp<ANativeWindow> window(surface); - sp<StubProducerListener> listener = new StubProducerListener(); + sp<StubSurfaceListener> listener = new StubSurfaceListener(); ASSERT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, /*listener*/listener, /*reportBufferRemoval*/false)); @@ -2226,4 +2228,90 @@ TEST_F(SurfaceTest, BatchIllegalOperations) { ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU)); } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) + +TEST_F(SurfaceTest, PlatformBufferMethods) { + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + + sp<CpuConsumer> cpuConsumer = sp<CpuConsumer>::make(consumer, 1); + sp<Surface> surface = sp<Surface>::make(producer); + sp<StubSurfaceListener> listener = sp<StubSurfaceListener>::make(); + sp<GraphicBuffer> buffer; + sp<Fence> fence; + + EXPECT_EQ(OK, + surface->connect(NATIVE_WINDOW_API_CPU, listener, /* reportBufferRemoval */ false)); + + // + // Verify nullptrs are handled safely: + // + + EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer((sp<GraphicBuffer>*)nullptr, nullptr)); + EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer((sp<GraphicBuffer>*)nullptr, &fence)); + EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer(&buffer, nullptr)); + EXPECT_EQ(BAD_VALUE, surface->queueBuffer(nullptr, nullptr)); + EXPECT_EQ(BAD_VALUE, surface->detachBuffer(nullptr)); + + // + // Verify dequeue/queue: + // + + EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)); + EXPECT_NE(nullptr, buffer); + EXPECT_EQ(OK, surface->queueBuffer(buffer, fence)); + + // + // Verify dequeue/detach: + // + + wp<GraphicBuffer> weakBuffer; + { + EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)); + + EXPECT_EQ(OK, surface->detachBuffer(buffer)); + + weakBuffer = buffer; + buffer = nullptr; + } + EXPECT_EQ(nullptr, weakBuffer.promote()) << "Weak buffer still held by Surface."; + + // + // Verify detach without borrowing the buffer does not work: + // + + sp<GraphicBuffer> heldTooLongBuffer; + EXPECT_EQ(OK, surface->dequeueBuffer(&heldTooLongBuffer, &fence)); + EXPECT_EQ(OK, surface->queueBuffer(heldTooLongBuffer)); + EXPECT_EQ(BAD_VALUE, surface->detachBuffer(heldTooLongBuffer)); +} + +TEST_F(SurfaceTest, AllowAllocation) { + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + + // controlledByApp must be true to disable blocking + sp<CpuConsumer> cpuConsumer = sp<CpuConsumer>::make(consumer, 1, /*controlledByApp*/ true); + sp<Surface> surface = sp<Surface>::make(producer, /*controlledByApp*/ true); + sp<StubSurfaceListener> listener = sp<StubSurfaceListener>::make(); + sp<GraphicBuffer> buffer; + sp<Fence> fence; + + EXPECT_EQ(OK, + surface->connect(NATIVE_WINDOW_API_CPU, listener, /* reportBufferRemoval */ false)); + EXPECT_EQ(OK, surface->allowAllocation(false)); + + EXPECT_EQ(OK, surface->setDequeueTimeout(-1)); + EXPECT_EQ(WOULD_BLOCK, surface->dequeueBuffer(&buffer, &fence)); + + EXPECT_EQ(OK, surface->setDequeueTimeout(10)); + EXPECT_EQ(TIMED_OUT, surface->dequeueBuffer(&buffer, &fence)); + + EXPECT_EQ(OK, surface->allowAllocation(true)); + EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)); +} +#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) + } // namespace android diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index e48e94f372..e11adb8c76 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -517,10 +517,10 @@ ftl::Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, // --- RawAbsoluteAxisInfo --- -std::ostream& operator<<(std::ostream& out, const RawAbsoluteAxisInfo& info) { - if (info.valid) { - out << "min=" << info.minValue << ", max=" << info.maxValue << ", flat=" << info.flat - << ", fuzz=" << info.fuzz << ", resolution=" << info.resolution; +std::ostream& operator<<(std::ostream& out, const std::optional<RawAbsoluteAxisInfo>& info) { + if (info) { + out << "min=" << info->minValue << ", max=" << info->maxValue << ", flat=" << info->flat + << ", fuzz=" << info->fuzz << ", resolution=" << info->resolution; } else { out << "unknown range"; } @@ -649,7 +649,6 @@ void EventHub::Device::populateAbsoluteAxisStates() { continue; } auto& [axisInfo, value] = absState[axis]; - axisInfo.valid = true; axisInfo.minValue = info.minimum; axisInfo.maxValue = info.maximum; axisInfo.flat = info.flat; diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index feae6b6afc..657126a825 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -71,18 +71,14 @@ struct RawEvent { /* Describes an absolute axis. */ struct RawAbsoluteAxisInfo { - bool valid{false}; // true if the information is valid, false otherwise - int32_t minValue{}; // minimum value int32_t maxValue{}; // maximum value int32_t flat{}; // center flat position, eg. flat == 8 means center is between -8 and 8 int32_t fuzz{}; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise int32_t resolution{}; // resolution in units per mm or radians per mm - - inline void clear() { *this = RawAbsoluteAxisInfo(); } }; -std::ostream& operator<<(std::ostream& out, const RawAbsoluteAxisInfo& info); +std::ostream& operator<<(std::ostream& out, const std::optional<RawAbsoluteAxisInfo>& info); /* * Input device classes. diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 086c26f5e2..1aed8a8394 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -43,7 +43,7 @@ class InputDevice { public: InputDevice(InputReaderContext* context, int32_t id, int32_t generation, const InputDeviceIdentifier& identifier); - ~InputDevice(); + virtual ~InputDevice(); inline InputReaderContext* getContext() { return mContext; } inline int32_t getId() const { return mId; } @@ -56,7 +56,7 @@ public: } inline const std::string getLocation() const { return mIdentifier.location; } inline ftl::Flags<InputDeviceClass> getClasses() const { return mClasses; } - inline uint32_t getSources() const { return mSources; } + inline virtual uint32_t getSources() const { return mSources; } inline bool hasEventHubDevices() const { return !mDevices.empty(); } inline bool isExternal() { return mIsExternal; } @@ -132,7 +132,7 @@ public: [[nodiscard]] NotifyDeviceResetArgs notifyReset(nsecs_t when); - inline const PropertyMap& getConfiguration() { return mConfiguration; } + inline virtual const PropertyMap& getConfiguration() const { return mConfiguration; } inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } std::optional<ui::LogicalDisplayId> getAssociatedDisplayId(); @@ -299,28 +299,24 @@ public: inline ftl::Flags<InputDeviceClass> getDeviceClasses() const { return mEventHub->getDeviceClasses(mId); } + inline uint32_t getDeviceSources() const { return mDevice.getSources(); } inline InputDeviceIdentifier getDeviceIdentifier() const { return mEventHub->getDeviceIdentifier(mId); } inline int32_t getDeviceControllerNumber() const { return mEventHub->getDeviceControllerNumber(mId); } - inline status_t getAbsoluteAxisInfo(int32_t code, RawAbsoluteAxisInfo* axisInfo) const { + inline std::optional<RawAbsoluteAxisInfo> getAbsoluteAxisInfo(int32_t code) const { std::optional<RawAbsoluteAxisInfo> info = mEventHub->getAbsoluteAxisInfo(mId, code); - if (!info.has_value()) { - axisInfo->clear(); - return NAME_NOT_FOUND; - } - *axisInfo = *info; // Validate axis info for InputDevice. - if (axisInfo->valid && axisInfo->minValue == axisInfo->maxValue) { + if (info && info->minValue == info->maxValue) { // Historically, we deem axes with the same min and max values as invalid to avoid // dividing by zero when scaling by max - min. // TODO(b/291772515): Perform axis info validation on a per-axis basis when it is used. - axisInfo->valid = false; + return std::nullopt; } - return OK; + return info; } inline bool hasRelativeAxis(int32_t code) const { return mEventHub->hasRelativeAxis(mId, code); @@ -435,8 +431,7 @@ public: } inline bool hasAbsoluteAxis(int32_t code) const { - std::optional<RawAbsoluteAxisInfo> info = mEventHub->getAbsoluteAxisInfo(mId, code); - return info.has_value() && info->valid; + return mEventHub->getAbsoluteAxisInfo(mId, code).has_value(); } inline bool isKeyPressed(int32_t scanCode) const { return mEventHub->getScanCodeState(mId, scanCode) == AKEY_STATE_DOWN; diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp index 90685dec2b..c8e7790c86 100644 --- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp +++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp @@ -16,6 +16,7 @@ #include "CapturedTouchpadEventConverter.h" +#include <optional> #include <sstream> #include <android-base/stringprintf.h> @@ -53,32 +54,33 @@ CapturedTouchpadEventConverter::CapturedTouchpadEventConverter( mMotionAccumulator(motionAccumulator), mHasTouchMinor(deviceContext.hasAbsoluteAxis(ABS_MT_TOUCH_MINOR)), mHasToolMinor(deviceContext.hasAbsoluteAxis(ABS_MT_WIDTH_MINOR)) { - RawAbsoluteAxisInfo orientationInfo; - deviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &orientationInfo); - if (orientationInfo.valid) { - if (orientationInfo.maxValue > 0) { - mOrientationScale = M_PI_2 / orientationInfo.maxValue; - } else if (orientationInfo.minValue < 0) { - mOrientationScale = -M_PI_2 / orientationInfo.minValue; + if (std::optional<RawAbsoluteAxisInfo> orientation = + deviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION); + orientation) { + if (orientation->maxValue > 0) { + mOrientationScale = M_PI_2 / orientation->maxValue; + } else if (orientation->minValue < 0) { + mOrientationScale = -M_PI_2 / orientation->minValue; } } // TODO(b/275369880): support touch.pressure.calibration and .scale properties when captured. - RawAbsoluteAxisInfo pressureInfo; - deviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE, &pressureInfo); - if (pressureInfo.valid && pressureInfo.maxValue > 0) { - mPressureScale = 1.0 / pressureInfo.maxValue; + if (std::optional<RawAbsoluteAxisInfo> pressure = + deviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE); + pressure && pressure->maxValue > 0) { + mPressureScale = 1.0 / pressure->maxValue; } - RawAbsoluteAxisInfo touchMajorInfo, toolMajorInfo; - deviceContext.getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &touchMajorInfo); - deviceContext.getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &toolMajorInfo); - mHasTouchMajor = touchMajorInfo.valid; - mHasToolMajor = toolMajorInfo.valid; - if (mHasTouchMajor && touchMajorInfo.maxValue != 0) { - mSizeScale = 1.0f / touchMajorInfo.maxValue; - } else if (mHasToolMajor && toolMajorInfo.maxValue != 0) { - mSizeScale = 1.0f / toolMajorInfo.maxValue; + std::optional<RawAbsoluteAxisInfo> touchMajor = + deviceContext.getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR); + std::optional<RawAbsoluteAxisInfo> toolMajor = + deviceContext.getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR); + mHasTouchMajor = touchMajor.has_value(); + mHasToolMajor = toolMajor.has_value(); + if (mHasTouchMajor && touchMajor->maxValue != 0) { + mSizeScale = 1.0f / touchMajor->maxValue; + } else if (mHasToolMajor && toolMajor->maxValue != 0) { + mSizeScale = 1.0f / toolMajor->maxValue; } } @@ -113,15 +115,13 @@ void CapturedTouchpadEventConverter::populateMotionRanges(InputDeviceInfo& info) tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MAJOR, ABS_MT_WIDTH_MAJOR); tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MINOR, ABS_MT_WIDTH_MINOR); - RawAbsoluteAxisInfo pressureInfo; - mDeviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE, &pressureInfo); - if (pressureInfo.valid) { + if (mDeviceContext.hasAbsoluteAxis(ABS_MT_PRESSURE)) { info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, SOURCE, 0, 1, 0, 0, 0); } - RawAbsoluteAxisInfo orientationInfo; - mDeviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &orientationInfo); - if (orientationInfo.valid && (orientationInfo.maxValue > 0 || orientationInfo.minValue < 0)) { + if (std::optional<RawAbsoluteAxisInfo> orientation = + mDeviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION); + orientation && (orientation->maxValue > 0 || orientation->minValue < 0)) { info.addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, SOURCE, -M_PI_2, M_PI_2, 0, 0, 0); } @@ -133,11 +133,10 @@ void CapturedTouchpadEventConverter::populateMotionRanges(InputDeviceInfo& info) void CapturedTouchpadEventConverter::tryAddRawMotionRange(InputDeviceInfo& deviceInfo, int32_t androidAxis, int32_t evdevAxis) const { - RawAbsoluteAxisInfo info; - mDeviceContext.getAbsoluteAxisInfo(evdevAxis, &info); - if (info.valid) { - deviceInfo.addMotionRange(androidAxis, SOURCE, info.minValue, info.maxValue, info.flat, - info.fuzz, info.resolution); + std::optional<RawAbsoluteAxisInfo> info = mDeviceContext.getAbsoluteAxisInfo(evdevAxis); + if (info) { + deviceInfo.addMotionRange(androidAxis, SOURCE, info->minValue, info->maxValue, info->flat, + info->fuzz, info->resolution); } } diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp index 3af1d04073..7cc8940379 100644 --- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp +++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp @@ -33,7 +33,7 @@ uint32_t ExternalStylusInputMapper::getSources() const { void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo& info) { InputMapper::populateDeviceInfo(info); - if (mRawPressureAxis.valid) { + if (mRawPressureAxis) { info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); } @@ -50,7 +50,7 @@ void ExternalStylusInputMapper::dump(std::string& dump) { std::list<NotifyArgs> ExternalStylusInputMapper::reconfigure(nsecs_t when, const InputReaderConfiguration& config, ConfigurationChanges changes) { - getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis); + mRawPressureAxis = getAbsoluteAxisInfo(ABS_PRESSURE); mTouchButtonAccumulator.configure(); return {}; } @@ -82,10 +82,10 @@ std::list<NotifyArgs> ExternalStylusInputMapper::sync(nsecs_t when) { mStylusState.toolType = ToolType::STYLUS; } - if (mRawPressureAxis.valid) { + if (mRawPressureAxis) { auto rawPressure = static_cast<float>(mSingleTouchMotionAccumulator.getAbsolutePressure()); - mStylusState.pressure = (rawPressure - mRawPressureAxis.minValue) / - static_cast<float>(mRawPressureAxis.maxValue - mRawPressureAxis.minValue); + mStylusState.pressure = (rawPressure - mRawPressureAxis->minValue) / + static_cast<float>(mRawPressureAxis->maxValue - mRawPressureAxis->minValue); } else if (mTouchButtonAccumulator.hasButtonTouch()) { mStylusState.pressure = mTouchButtonAccumulator.isHovering() ? 0.0f : 1.0f; } diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h index c040a7b996..d48fd9b469 100644 --- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h +++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h @@ -16,6 +16,8 @@ #pragma once +#include <optional> + #include "InputMapper.h" #include "SingleTouchMotionAccumulator.h" @@ -43,7 +45,7 @@ public: private: SingleTouchMotionAccumulator mSingleTouchMotionAccumulator; - RawAbsoluteAxisInfo mRawPressureAxis; + std::optional<RawAbsoluteAxisInfo> mRawPressureAxis; TouchButtonAccumulator mTouchButtonAccumulator; StylusState mStylusState; diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp index b6c5c9806c..c44c48c0bf 100644 --- a/services/inputflinger/reader/mapper/InputMapper.cpp +++ b/services/inputflinger/reader/mapper/InputMapper.cpp @@ -18,6 +18,7 @@ #include "InputMapper.h" +#include <optional> #include <sstream> #include <ftl/enum.h> @@ -116,15 +117,16 @@ std::list<NotifyArgs> InputMapper::updateExternalStylusState(const StylusState& return {}; } -status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) { - return getDeviceContext().getAbsoluteAxisInfo(axis, axisInfo); +std::optional<RawAbsoluteAxisInfo> InputMapper::getAbsoluteAxisInfo(int32_t axis) { + return getDeviceContext().getAbsoluteAxisInfo(axis); } void InputMapper::bumpGeneration() { getDeviceContext().bumpGeneration(); } -void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis, +void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump, + const std::optional<RawAbsoluteAxisInfo>& axis, const char* name) { std::stringstream out; out << INDENT4 << name << ": " << axis << "\n"; diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h index 2c51448b4e..e5afcc798e 100644 --- a/services/inputflinger/reader/mapper/InputMapper.h +++ b/services/inputflinger/reader/mapper/InputMapper.h @@ -16,6 +16,8 @@ #pragma once +#include <optional> + #include "EventHub.h" #include "InputDevice.h" #include "InputListener.h" @@ -126,10 +128,11 @@ protected: explicit InputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig); - status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo); + std::optional<RawAbsoluteAxisInfo> getAbsoluteAxisInfo(int32_t axis); void bumpGeneration(); - static void dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis, + static void dumpRawAbsoluteAxisInfo(std::string& dump, + const std::optional<RawAbsoluteAxisInfo>& axis, const char* name); static void dumpStylusState(std::string& dump, const StylusState& state); }; diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp index 41e018d392..3091714e00 100644 --- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp +++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp @@ -117,9 +117,8 @@ std::list<NotifyArgs> JoystickInputMapper::reconfigure(nsecs_t when, continue; // axis must be claimed by a different device } - RawAbsoluteAxisInfo rawAxisInfo; - getAbsoluteAxisInfo(abs, &rawAxisInfo); - if (rawAxisInfo.valid) { + if (std::optional<RawAbsoluteAxisInfo> rawAxisInfo = getAbsoluteAxisInfo(abs); + rawAxisInfo) { // Map axis. AxisInfo axisInfo; const bool explicitlyMapped = !getDeviceContext().mapAxis(abs, &axisInfo); @@ -129,7 +128,7 @@ std::list<NotifyArgs> JoystickInputMapper::reconfigure(nsecs_t when, axisInfo.mode = AxisInfo::MODE_NORMAL; axisInfo.axis = -1; } - mAxes.insert({abs, createAxis(axisInfo, rawAxisInfo, explicitlyMapped)}); + mAxes.insert({abs, createAxis(axisInfo, rawAxisInfo.value(), explicitlyMapped)}); } } diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index 4a21e48f8f..38dcd65a81 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -98,10 +98,10 @@ static bool isMediaKey(int32_t keyCode) { KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig, uint32_t source) - : InputMapper(deviceContext, readerConfig), mSource(source) {} + : InputMapper(deviceContext, readerConfig), mMapperSource(source) {} uint32_t KeyboardInputMapper::getSources() const { - return mSource; + return mMapperSource; } ui::Rotation KeyboardInputMapper::getOrientation() { @@ -351,8 +351,8 @@ std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t read policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT; } - out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, deviceId, mSource, - getDisplayId(), policyFlags, + out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, deviceId, + getEventSource(), getDisplayId(), policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, flags, keyCode, scanCode, keyMetaState, downTime)); return out; @@ -478,12 +478,12 @@ std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) { std::list<NotifyArgs> out; size_t n = mKeyDowns.size(); for (size_t i = 0; i < n; i++) { - out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, - systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), mSource, - getDisplayId(), /*policyFlags=*/0, AKEY_EVENT_ACTION_UP, - mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED, - mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE, - mKeyDowns[i].downTime)); + out.emplace_back( + NotifyKeyArgs(getContext()->getNextId(), when, systemTime(SYSTEM_TIME_MONOTONIC), + getDeviceId(), getEventSource(), getDisplayId(), /*policyFlags=*/0, + AKEY_EVENT_ACTION_UP, mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED, + mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE, + mKeyDowns[i].downTime)); } mKeyDowns.clear(); mMetaState = AMETA_NONE; @@ -495,4 +495,14 @@ void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) { context.setLastKeyDownTimestamp(downTime); } +uint32_t KeyboardInputMapper::getEventSource() const { + // For all input events generated by this mapper, use the source that's shared across all + // KeyboardInputMappers for this device in case there are more than one. + static constexpr auto ALL_KEYBOARD_SOURCES = + AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD; + const auto deviceSources = getDeviceContext().getDeviceSources(); + LOG_ALWAYS_FATAL_IF((deviceSources & mMapperSource) != mMapperSource); + return deviceSources & ALL_KEYBOARD_SOURCES; +} + } // namespace android diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h index c7df558caf..2df0b85e21 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h @@ -60,7 +60,10 @@ private: int32_t flags{}; }; - uint32_t mSource{}; + // The keyboard source for this mapper. Events generated should use the source shared + // by all KeyboardInputMappers for this input device. + uint32_t mMapperSource{}; + std::optional<KeyboardLayoutInfo> mKeyboardLayoutInfo; std::vector<KeyDown> mKeyDowns{}; // keys that are down @@ -106,6 +109,7 @@ private: std::optional<DisplayViewport> findViewport(const InputReaderConfiguration& readerConfig); [[nodiscard]] std::list<NotifyArgs> cancelAllDownKeys(nsecs_t when); void onKeyDownProcessed(nsecs_t downTime); + uint32_t getEventSource() const; }; } // namespace android diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp index 1986fe286a..fd8224a608 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp @@ -133,7 +133,7 @@ void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { bool isHovering = mTouchButtonAccumulator.getToolType() != ToolType::MOUSE && (mTouchButtonAccumulator.isHovering() || - (mRawPointerAxes.pressure.valid && inSlot.getPressure() <= 0)); + (mRawPointerAxes.pressure && inSlot.getPressure() <= 0)); outPointer.isHovering = isHovering; // Assign pointer id using tracking id if available. @@ -189,21 +189,27 @@ std::list<NotifyArgs> MultiTouchInputMapper::reconfigure(nsecs_t when, void MultiTouchInputMapper::configureRawPointerAxes() { TouchInputMapper::configureRawPointerAxes(); - getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x); - getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y); - getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor); - getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor); - getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor); - getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor); - getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation); - getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure); - getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance); - getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId); - getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot); - - if (mRawPointerAxes.trackingId.valid && mRawPointerAxes.slot.valid && - mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) { - size_t slotCount = mRawPointerAxes.slot.maxValue + 1; + // TODO(b/351870641): Investigate why we are sometime not getting valid axis infos for the x/y + // axes, even though those axes are required to be supported. + if (const auto xInfo = getAbsoluteAxisInfo(ABS_MT_POSITION_X); xInfo.has_value()) { + mRawPointerAxes.x = *xInfo; + } + if (const auto yInfo = getAbsoluteAxisInfo(ABS_MT_POSITION_Y); yInfo.has_value()) { + mRawPointerAxes.y = *yInfo; + } + mRawPointerAxes.touchMajor = getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR); + mRawPointerAxes.touchMinor = getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR); + mRawPointerAxes.toolMajor = getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR); + mRawPointerAxes.toolMinor = getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR); + mRawPointerAxes.orientation = getAbsoluteAxisInfo(ABS_MT_ORIENTATION); + mRawPointerAxes.pressure = getAbsoluteAxisInfo(ABS_MT_PRESSURE); + mRawPointerAxes.distance = getAbsoluteAxisInfo(ABS_MT_DISTANCE); + mRawPointerAxes.trackingId = getAbsoluteAxisInfo(ABS_MT_TRACKING_ID); + mRawPointerAxes.slot = getAbsoluteAxisInfo(ABS_MT_SLOT); + + if (mRawPointerAxes.trackingId && mRawPointerAxes.slot && mRawPointerAxes.slot->minValue == 0 && + mRawPointerAxes.slot->maxValue > 0) { + size_t slotCount = mRawPointerAxes.slot->maxValue + 1; if (slotCount > MAX_SLOTS) { ALOGW("MultiTouch Device %s reported %zu slots but the framework " "only supports a maximum of %zu slots at this time.", diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp index d7f2993daa..4233f789d6 100644 --- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp @@ -133,9 +133,8 @@ std::list<NotifyArgs> SensorInputMapper::reconfigure(nsecs_t when, .test(InputDeviceClass::SENSOR))) { continue; } - RawAbsoluteAxisInfo rawAxisInfo; - getAbsoluteAxisInfo(abs, &rawAxisInfo); - if (rawAxisInfo.valid) { + if (std::optional<RawAbsoluteAxisInfo> rawAxisInfo = getAbsoluteAxisInfo(abs); + rawAxisInfo) { AxisInfo axisInfo; // Axis doesn't need to be mapped, as sensor mapper doesn't generate any motion // input events @@ -146,7 +145,7 @@ std::list<NotifyArgs> SensorInputMapper::reconfigure(nsecs_t when, if (ret.ok()) { InputDeviceSensorType sensorType = (*ret).first; int32_t sensorDataIndex = (*ret).second; - const Axis& axis = createAxis(axisInfo, rawAxisInfo); + const Axis& axis = createAxis(axisInfo, rawAxisInfo.value()); parseSensorConfiguration(sensorType, abs, sensorDataIndex, axis); mAxes.insert({abs, axis}); diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp index 140bb0c4ed..cef18375d4 100644 --- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp @@ -44,7 +44,7 @@ void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { bool isHovering = mTouchButtonAccumulator.getToolType() != ToolType::MOUSE && (mTouchButtonAccumulator.isHovering() || - (mRawPointerAxes.pressure.valid && + (mRawPointerAxes.pressure && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0)); outState->rawPointerData.markIdBit(0, isHovering); @@ -72,13 +72,19 @@ void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { void SingleTouchInputMapper::configureRawPointerAxes() { TouchInputMapper::configureRawPointerAxes(); - getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x); - getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y); - getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure); - getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor); - getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance); - getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX); - getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY); + // TODO(b/351870641): Investigate why we are sometime not getting valid axis infos for the x/y + // axes, even though those axes are required to be supported. + if (const auto xInfo = getAbsoluteAxisInfo(ABS_X); xInfo.has_value()) { + mRawPointerAxes.x = *xInfo; + } + if (const auto yInfo = getAbsoluteAxisInfo(ABS_Y); yInfo.has_value()) { + mRawPointerAxes.y = *yInfo; + } + mRawPointerAxes.pressure = getAbsoluteAxisInfo(ABS_PRESSURE); + mRawPointerAxes.toolMajor = getAbsoluteAxisInfo(ABS_TOOL_WIDTH); + mRawPointerAxes.distance = getAbsoluteAxisInfo(ABS_DISTANCE); + mRawPointerAxes.tiltX = getAbsoluteAxisInfo(ABS_TILT_X); + mRawPointerAxes.tiltY = getAbsoluteAxisInfo(ABS_TILT_Y); } bool SingleTouchInputMapper::hasStylus() const { diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 2d892087f6..984e217efc 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -600,10 +600,10 @@ void TouchInputMapper::initializeSizeRanges() { const float diagonalSize = hypotf(mDisplayBounds.width, mDisplayBounds.height); // Size factors. - if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.touchMajor.maxValue != 0) { - mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue; - } else if (mRawPointerAxes.toolMajor.valid && mRawPointerAxes.toolMajor.maxValue != 0) { - mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue; + if (mRawPointerAxes.touchMajor && mRawPointerAxes.touchMajor->maxValue != 0) { + mSizeScale = 1.0f / mRawPointerAxes.touchMajor->maxValue; + } else if (mRawPointerAxes.toolMajor && mRawPointerAxes.toolMajor->maxValue != 0) { + mSizeScale = 1.0f / mRawPointerAxes.toolMajor->maxValue; } else { mSizeScale = 0.0f; } @@ -618,18 +618,18 @@ void TouchInputMapper::initializeSizeRanges() { .resolution = 0, }; - if (mRawPointerAxes.touchMajor.valid) { - mRawPointerAxes.touchMajor.resolution = - clampResolution("touchMajor", mRawPointerAxes.touchMajor.resolution); - mOrientedRanges.touchMajor->resolution = mRawPointerAxes.touchMajor.resolution; + if (mRawPointerAxes.touchMajor) { + mRawPointerAxes.touchMajor->resolution = + clampResolution("touchMajor", mRawPointerAxes.touchMajor->resolution); + mOrientedRanges.touchMajor->resolution = mRawPointerAxes.touchMajor->resolution; } mOrientedRanges.touchMinor = mOrientedRanges.touchMajor; mOrientedRanges.touchMinor->axis = AMOTION_EVENT_AXIS_TOUCH_MINOR; - if (mRawPointerAxes.touchMinor.valid) { - mRawPointerAxes.touchMinor.resolution = - clampResolution("touchMinor", mRawPointerAxes.touchMinor.resolution); - mOrientedRanges.touchMinor->resolution = mRawPointerAxes.touchMinor.resolution; + if (mRawPointerAxes.touchMinor) { + mRawPointerAxes.touchMinor->resolution = + clampResolution("touchMinor", mRawPointerAxes.touchMinor->resolution); + mOrientedRanges.touchMinor->resolution = mRawPointerAxes.touchMinor->resolution; } mOrientedRanges.toolMajor = InputDeviceInfo::MotionRange{ @@ -641,18 +641,18 @@ void TouchInputMapper::initializeSizeRanges() { .fuzz = 0, .resolution = 0, }; - if (mRawPointerAxes.toolMajor.valid) { - mRawPointerAxes.toolMajor.resolution = - clampResolution("toolMajor", mRawPointerAxes.toolMajor.resolution); - mOrientedRanges.toolMajor->resolution = mRawPointerAxes.toolMajor.resolution; + if (mRawPointerAxes.toolMajor) { + mRawPointerAxes.toolMajor->resolution = + clampResolution("toolMajor", mRawPointerAxes.toolMajor->resolution); + mOrientedRanges.toolMajor->resolution = mRawPointerAxes.toolMajor->resolution; } mOrientedRanges.toolMinor = mOrientedRanges.toolMajor; mOrientedRanges.toolMinor->axis = AMOTION_EVENT_AXIS_TOOL_MINOR; - if (mRawPointerAxes.toolMinor.valid) { - mRawPointerAxes.toolMinor.resolution = - clampResolution("toolMinor", mRawPointerAxes.toolMinor.resolution); - mOrientedRanges.toolMinor->resolution = mRawPointerAxes.toolMinor.resolution; + if (mRawPointerAxes.toolMinor) { + mRawPointerAxes.toolMinor->resolution = + clampResolution("toolMinor", mRawPointerAxes.toolMinor->resolution); + mOrientedRanges.toolMinor->resolution = mRawPointerAxes.toolMinor->resolution; } if (mCalibration.sizeCalibration == Calibration::SizeCalibration::GEOMETRIC) { @@ -704,9 +704,10 @@ void TouchInputMapper::initializeOrientedRanges() { mCalibration.pressureCalibration == Calibration::PressureCalibration::AMPLITUDE) { if (mCalibration.pressureScale) { mPressureScale = *mCalibration.pressureScale; - pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue; - } else if (mRawPointerAxes.pressure.valid && mRawPointerAxes.pressure.maxValue != 0) { - mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue; + pressureMax = mPressureScale * + (mRawPointerAxes.pressure ? mRawPointerAxes.pressure->maxValue : 0); + } else if (mRawPointerAxes.pressure && mRawPointerAxes.pressure->maxValue != 0) { + mPressureScale = 1.0f / mRawPointerAxes.pressure->maxValue; } } @@ -725,18 +726,18 @@ void TouchInputMapper::initializeOrientedRanges() { mTiltXScale = 0; mTiltYCenter = 0; mTiltYScale = 0; - mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid; + mHaveTilt = mRawPointerAxes.tiltX && mRawPointerAxes.tiltY; if (mHaveTilt) { - mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue, mRawPointerAxes.tiltX.maxValue); - mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue, mRawPointerAxes.tiltY.maxValue); + mTiltXCenter = avg(mRawPointerAxes.tiltX->minValue, mRawPointerAxes.tiltX->maxValue); + mTiltYCenter = avg(mRawPointerAxes.tiltY->minValue, mRawPointerAxes.tiltY->maxValue); mTiltXScale = M_PI / 180; mTiltYScale = M_PI / 180; - if (mRawPointerAxes.tiltX.resolution) { - mTiltXScale = 1.0 / mRawPointerAxes.tiltX.resolution; + if (mRawPointerAxes.tiltX->resolution) { + mTiltXScale = 1.0 / mRawPointerAxes.tiltX->resolution; } - if (mRawPointerAxes.tiltY.resolution) { - mTiltYScale = 1.0 / mRawPointerAxes.tiltY.resolution; + if (mRawPointerAxes.tiltY->resolution) { + mTiltYScale = 1.0 / mRawPointerAxes.tiltY->resolution; } mOrientedRanges.tilt = InputDeviceInfo::MotionRange{ @@ -766,11 +767,11 @@ void TouchInputMapper::initializeOrientedRanges() { } else if (mCalibration.orientationCalibration != Calibration::OrientationCalibration::NONE) { if (mCalibration.orientationCalibration == Calibration::OrientationCalibration::INTERPOLATED) { - if (mRawPointerAxes.orientation.valid) { - if (mRawPointerAxes.orientation.maxValue > 0) { - mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue; - } else if (mRawPointerAxes.orientation.minValue < 0) { - mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue; + if (mRawPointerAxes.orientation) { + if (mRawPointerAxes.orientation->maxValue > 0) { + mOrientationScale = M_PI_2 / mRawPointerAxes.orientation->maxValue; + } else if (mRawPointerAxes.orientation->minValue < 0) { + mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation->minValue; } else { mOrientationScale = 0; } @@ -795,14 +796,14 @@ void TouchInputMapper::initializeOrientedRanges() { mDistanceScale = mCalibration.distanceScale.value_or(1.0f); } + const bool hasDistance = mRawPointerAxes.distance.has_value(); mOrientedRanges.distance = InputDeviceInfo::MotionRange{ - .axis = AMOTION_EVENT_AXIS_DISTANCE, .source = mSource, - .min = mRawPointerAxes.distance.minValue * mDistanceScale, - .max = mRawPointerAxes.distance.maxValue * mDistanceScale, + .min = hasDistance ? mRawPointerAxes.distance->minValue * mDistanceScale : 0, + .max = hasDistance ? mRawPointerAxes.distance->maxValue * mDistanceScale : 0, .flat = 0, - .fuzz = mRawPointerAxes.distance.fuzz * mDistanceScale, + .fuzz = hasDistance ? mRawPointerAxes.distance->fuzz * mDistanceScale : 0, .resolution = 0, }; } @@ -943,12 +944,7 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) const std::optional<DisplayViewport> newViewportOpt = findViewport(); // Ensure the device is valid and can be used. - if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) { - ALOGW("Touch device '%s' did not report support for X or Y axis! " - "The device will be inoperable.", - getDeviceName().c_str()); - mDeviceMode = DeviceMode::DISABLED; - } else if (!newViewportOpt) { + if (!newViewportOpt) { ALOGI("Touch device '%s' could not query the properties of its associated " "display. The device will be inoperable until the display size " "becomes available.", @@ -1237,7 +1233,7 @@ void TouchInputMapper::parseCalibration() { void TouchInputMapper::resolveCalibration() { // Size - if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) { + if (mRawPointerAxes.touchMajor || mRawPointerAxes.toolMajor) { if (mCalibration.sizeCalibration == Calibration::SizeCalibration::DEFAULT) { mCalibration.sizeCalibration = Calibration::SizeCalibration::GEOMETRIC; } @@ -1246,7 +1242,7 @@ void TouchInputMapper::resolveCalibration() { } // Pressure - if (mRawPointerAxes.pressure.valid) { + if (mRawPointerAxes.pressure) { if (mCalibration.pressureCalibration == Calibration::PressureCalibration::DEFAULT) { mCalibration.pressureCalibration = Calibration::PressureCalibration::PHYSICAL; } @@ -1255,7 +1251,7 @@ void TouchInputMapper::resolveCalibration() { } // Orientation - if (mRawPointerAxes.orientation.valid) { + if (mRawPointerAxes.orientation) { if (mCalibration.orientationCalibration == Calibration::OrientationCalibration::DEFAULT) { mCalibration.orientationCalibration = Calibration::OrientationCalibration::INTERPOLATED; } @@ -1264,7 +1260,7 @@ void TouchInputMapper::resolveCalibration() { } // Distance - if (mRawPointerAxes.distance.valid) { + if (mRawPointerAxes.distance) { if (mCalibration.distanceCalibration == Calibration::DistanceCalibration::DEFAULT) { mCalibration.distanceCalibration = Calibration::DistanceCalibration::SCALED; } @@ -2251,25 +2247,25 @@ void TouchInputMapper::cookPointerData() { case Calibration::SizeCalibration::DIAMETER: case Calibration::SizeCalibration::BOX: case Calibration::SizeCalibration::AREA: - if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) { + if (mRawPointerAxes.touchMajor && mRawPointerAxes.toolMajor) { touchMajor = in.touchMajor; - touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor; + touchMinor = mRawPointerAxes.touchMinor ? in.touchMinor : in.touchMajor; toolMajor = in.toolMajor; - toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor; - size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor) - : in.touchMajor; - } else if (mRawPointerAxes.touchMajor.valid) { + toolMinor = mRawPointerAxes.toolMinor ? in.toolMinor : in.toolMajor; + size = mRawPointerAxes.touchMinor ? avg(in.touchMajor, in.touchMinor) + : in.touchMajor; + } else if (mRawPointerAxes.touchMajor) { toolMajor = touchMajor = in.touchMajor; toolMinor = touchMinor = - mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor; - size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor) - : in.touchMajor; - } else if (mRawPointerAxes.toolMajor.valid) { + mRawPointerAxes.touchMinor ? in.touchMinor : in.touchMajor; + size = mRawPointerAxes.touchMinor ? avg(in.touchMajor, in.touchMinor) + : in.touchMajor; + } else if (mRawPointerAxes.toolMajor) { touchMajor = toolMajor = in.toolMajor; touchMinor = toolMinor = - mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor; - size = mRawPointerAxes.toolMinor.valid ? avg(in.toolMajor, in.toolMinor) - : in.toolMajor; + mRawPointerAxes.toolMinor ? in.toolMinor : in.toolMajor; + size = mRawPointerAxes.toolMinor ? avg(in.toolMajor, in.toolMinor) + : in.toolMajor; } else { ALOG_ASSERT(false, "No touch or tool axes. " diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index a9a0190bce..87b72afe7c 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -61,17 +61,17 @@ static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); struct RawPointerAxes { RawAbsoluteAxisInfo x{}; RawAbsoluteAxisInfo y{}; - RawAbsoluteAxisInfo pressure{}; - RawAbsoluteAxisInfo touchMajor{}; - RawAbsoluteAxisInfo touchMinor{}; - RawAbsoluteAxisInfo toolMajor{}; - RawAbsoluteAxisInfo toolMinor{}; - RawAbsoluteAxisInfo orientation{}; - RawAbsoluteAxisInfo distance{}; - RawAbsoluteAxisInfo tiltX{}; - RawAbsoluteAxisInfo tiltY{}; - RawAbsoluteAxisInfo trackingId{}; - RawAbsoluteAxisInfo slot{}; + std::optional<RawAbsoluteAxisInfo> pressure{}; + std::optional<RawAbsoluteAxisInfo> touchMajor{}; + std::optional<RawAbsoluteAxisInfo> touchMinor{}; + std::optional<RawAbsoluteAxisInfo> toolMajor{}; + std::optional<RawAbsoluteAxisInfo> toolMinor{}; + std::optional<RawAbsoluteAxisInfo> orientation{}; + std::optional<RawAbsoluteAxisInfo> distance{}; + std::optional<RawAbsoluteAxisInfo> tiltX{}; + std::optional<RawAbsoluteAxisInfo> tiltY{}; + std::optional<RawAbsoluteAxisInfo> trackingId{}; + std::optional<RawAbsoluteAxisInfo> slot{}; inline int32_t getRawWidth() const { return x.maxValue - x.minValue + 1; } inline int32_t getRawHeight() const { return y.maxValue - y.minValue + 1; } diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp index 128f5153a0..5c5fd3fb5f 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp @@ -240,14 +240,15 @@ TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext, mGestureConverter(*getContext(), deviceContext, getDeviceId()), mCapturedEventConverter(*getContext(), deviceContext, mMotionAccumulator, getDeviceId()), mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())) { - RawAbsoluteAxisInfo slotAxisInfo; - deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo); - if (!slotAxisInfo.valid || slotAxisInfo.maxValue < 0) { + if (std::optional<RawAbsoluteAxisInfo> slotAxis = + deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT); + slotAxis && slotAxis->maxValue >= 0) { + mMotionAccumulator.configure(deviceContext, slotAxis->maxValue + 1, true); + } else { 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, 1, true); } - mMotionAccumulator.configure(deviceContext, slotAxisInfo.maxValue + 1, true); mGestureInterpreter->Initialize(GESTURES_DEVCLASS_TOUCHPAD); mGestureInterpreter->SetHardwareProperties(createHardwareProperties(deviceContext)); diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp index e8e7376e92..9924d0d491 100644 --- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp +++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp @@ -66,10 +66,11 @@ GestureConverter::GestureConverter(InputReaderContext& readerContext, const InputDeviceContext& deviceContext, int32_t deviceId) : mDeviceId(deviceId), mReaderContext(readerContext), - mEnableFlingStop(input_flags::enable_touchpad_fling_stop()) { - deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mXAxisInfo); - deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mYAxisInfo); -} + mEnableFlingStop(input_flags::enable_touchpad_fling_stop()), + // We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub + // won't classify a device as a touchpad if they're not present. + mXAxisInfo(deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X).value()), + mYAxisInfo(deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y).value()) {} std::string GestureConverter::dump() const { std::stringstream out; diff --git a/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp b/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp index 04655dc439..d8a1f501d1 100644 --- a/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp +++ b/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp @@ -16,6 +16,8 @@ #include "HardwareProperties.h" +#include <optional> + namespace android { namespace { @@ -33,26 +35,34 @@ unsigned short getMaxTouchCount(const InputDeviceContext& context) { HardwareProperties createHardwareProperties(const InputDeviceContext& context) { HardwareProperties props; - RawAbsoluteAxisInfo absMtPositionX; - context.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &absMtPositionX); + // We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub won't + // classify a device as a touchpad if they're not present. + RawAbsoluteAxisInfo absMtPositionX = context.getAbsoluteAxisInfo(ABS_MT_POSITION_X).value(); props.left = absMtPositionX.minValue; props.right = absMtPositionX.maxValue; props.res_x = absMtPositionX.resolution; - RawAbsoluteAxisInfo absMtPositionY; - context.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &absMtPositionY); + RawAbsoluteAxisInfo absMtPositionY = context.getAbsoluteAxisInfo(ABS_MT_POSITION_Y).value(); props.top = absMtPositionY.minValue; props.bottom = absMtPositionY.maxValue; props.res_y = absMtPositionY.resolution; - RawAbsoluteAxisInfo absMtOrientation; - context.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &absMtOrientation); - props.orientation_minimum = absMtOrientation.minValue; - props.orientation_maximum = absMtOrientation.maxValue; + if (std::optional<RawAbsoluteAxisInfo> absMtOrientation = + context.getAbsoluteAxisInfo(ABS_MT_ORIENTATION); + absMtOrientation) { + props.orientation_minimum = absMtOrientation->minValue; + props.orientation_maximum = absMtOrientation->maxValue; + } else { + props.orientation_minimum = 0; + props.orientation_maximum = 0; + } - RawAbsoluteAxisInfo absMtSlot; - context.getAbsoluteAxisInfo(ABS_MT_SLOT, &absMtSlot); - props.max_finger_cnt = absMtSlot.maxValue - absMtSlot.minValue + 1; + if (std::optional<RawAbsoluteAxisInfo> absMtSlot = context.getAbsoluteAxisInfo(ABS_MT_SLOT); + absMtSlot) { + props.max_finger_cnt = absMtSlot->maxValue - absMtSlot->minValue + 1; + } else { + props.max_finger_cnt = 1; + } props.max_touch_cnt = getMaxTouchCount(context); // T5R2 ("Track 5, Report 2") is a feature of some old Synaptics touchpads that could track 5 @@ -71,9 +81,7 @@ HardwareProperties createHardwareProperties(const InputDeviceContext& context) { // are haptic. props.is_haptic_pad = false; - RawAbsoluteAxisInfo absMtPressure; - context.getAbsoluteAxisInfo(ABS_MT_PRESSURE, &absMtPressure); - props.reports_pressure = absMtPressure.valid; + props.reports_pressure = context.hasAbsoluteAxis(ABS_MT_PRESSURE); return props; } diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index ab50646a68..95283ba6ab 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -70,6 +70,7 @@ cc_test { "InputTraceSession.cpp", "InputTracingTest.cpp", "InstrumentedInputReader.cpp", + "JoystickInputMapper_test.cpp", "LatencyTracker_test.cpp", "MultiTouchMotionAccumulator_test.cpp", "NotifyArgs_test.cpp", diff --git a/services/inputflinger/tests/CursorInputMapper_test.cpp b/services/inputflinger/tests/CursorInputMapper_test.cpp index 727237f287..846eced2ab 100644 --- a/services/inputflinger/tests/CursorInputMapper_test.cpp +++ b/services/inputflinger/tests/CursorInputMapper_test.cpp @@ -163,7 +163,6 @@ protected: } void createMapper() { - createDevice(); mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration); } @@ -542,7 +541,6 @@ TEST_F(CursorInputMapperUnitTest, ProcessShouldNotRotateMotionsWhenOrientationAw // need to be rotated. mPropertyMap.addProperty("cursor.mode", "navigation"); mPropertyMap.addProperty("cursor.orientationAware", "1"); - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, ui::Rotation::Rotation90); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -560,7 +558,6 @@ TEST_F(CursorInputMapperUnitTest, ProcessShouldRotateMotionsWhenNotOrientationAw // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. mPropertyMap.addProperty("cursor.mode", "navigation"); - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, ui::Rotation::Rotation0); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -652,7 +649,6 @@ TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdWithAssociatedViewport) { mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport}); // Set up the secondary display as the display on which the pointer should be shown. // The InputDevice is not associated with any display. - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -673,7 +669,6 @@ TEST_F(CursorInputMapperUnitTest, DisplayViewport secondaryViewport = createSecondaryViewport(); mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport}); // Set up the primary display as the display on which the pointer should be shown. - createDevice(); // Associate the InputDevice with the secondary display. ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -1032,7 +1027,6 @@ TEST_F(CursorInputMapperUnitTestWithNewBallistics, ConfigureAccelerationWithAsso mPropertyMap.addProperty("cursor.mode", "pointer"); DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation0); mReaderConfiguration.setDisplayViewports({primaryViewport}); - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, primaryViewport); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -1070,7 +1064,6 @@ TEST_F(CursorInputMapperUnitTestWithNewBallistics, ConfigureAccelerationOnDispla mReaderConfiguration.setDisplayViewports({primaryViewport}); // Disable acceleration for the display. mReaderConfiguration.displaysWithMousePointerAccelerationDisabled.emplace(DISPLAY_ID); - createDevice(); // Don't associate the device with the display yet. ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp index 99db99996b..31fbf209a3 100644 --- a/services/inputflinger/tests/FakeEventHub.cpp +++ b/services/inputflinger/tests/FakeEventHub.cpp @@ -101,7 +101,6 @@ void FakeEventHub::addAbsoluteAxis(int32_t deviceId, int axis, int32_t minValue, Device* device = getDevice(deviceId); RawAbsoluteAxisInfo info; - info.valid = true; info.minValue = minValue; info.maxValue = maxValue; info.flat = flat; diff --git a/services/inputflinger/tests/HardwareProperties_test.cpp b/services/inputflinger/tests/HardwareProperties_test.cpp index 643fab6d44..e87f8228c8 100644 --- a/services/inputflinger/tests/HardwareProperties_test.cpp +++ b/services/inputflinger/tests/HardwareProperties_test.cpp @@ -50,7 +50,6 @@ protected: void setupValidAxis(int axis, int32_t min, int32_t max, int32_t resolution) { EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis)) .WillRepeatedly(Return(std::optional<RawAbsoluteAxisInfo>{{ - .valid = true, .minValue = min, .maxValue = max, .flat = 0, diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp index 7e96d5f5d7..7dff144f87 100644 --- a/services/inputflinger/tests/InputMapperTest.cpp +++ b/services/inputflinger/tests/InputMapperTest.cpp @@ -26,7 +26,9 @@ namespace android { using testing::_; +using testing::NiceMock; using testing::Return; +using testing::ReturnRef; void InputMapperUnitTest::SetUpWithBus(int bus) { mFakePolicy = sp<FakeInputReaderPolicy>::make(); @@ -43,23 +45,17 @@ void InputMapperUnitTest::SetUpWithBus(int bus) { EXPECT_CALL(mMockEventHub, getConfiguration(EVENTHUB_ID)).WillRepeatedly([&](int32_t) { return mPropertyMap; }); -} -void InputMapperUnitTest::createDevice() { - mDevice = std::make_unique<InputDevice>(&mMockInputReaderContext, DEVICE_ID, - /*generation=*/2, mIdentifier); - mDevice->addEmptyEventHubDevice(EVENTHUB_ID); + mDevice = std::make_unique<NiceMock<MockInputDevice>>(&mMockInputReaderContext, DEVICE_ID, + /*generation=*/2, mIdentifier); + ON_CALL((*mDevice), getConfiguration).WillByDefault(ReturnRef(mPropertyMap)); mDeviceContext = std::make_unique<InputDeviceContext>(*mDevice, EVENTHUB_ID); - std::list<NotifyArgs> args = - mDevice->configure(systemTime(), mReaderConfiguration, /*changes=*/{}); - ASSERT_THAT(args, testing::ElementsAre(testing::VariantWith<NotifyDeviceResetArgs>(_))); } void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution) { EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis)) .WillRepeatedly(Return(valid ? std::optional<RawAbsoluteAxisInfo>{{ - .valid = true, .minValue = min, .maxValue = max, .flat = 0, diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h index 88057dc497..fc27e4fefd 100644 --- a/services/inputflinger/tests/InputMapperTest.h +++ b/services/inputflinger/tests/InputMapperTest.h @@ -43,13 +43,6 @@ protected: virtual void SetUp() override { SetUpWithBus(0); } virtual void SetUpWithBus(int bus); - /** - * Initializes mDevice and mDeviceContext. When this happens, mDevice takes a copy of - * mPropertyMap, so tests that need to set configuration properties should do so before calling - * this. Others will most likely want to call it in their SetUp method. - */ - void createDevice(); - void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution); void expectScanCodes(bool present, std::set<int> scanCodes); @@ -67,7 +60,7 @@ protected: MockEventHubInterface mMockEventHub; sp<FakeInputReaderPolicy> mFakePolicy; MockInputReaderContext mMockInputReaderContext; - std::unique_ptr<InputDevice> mDevice; + std::unique_ptr<MockInputDevice> mDevice; std::unique_ptr<InputDeviceContext> mDeviceContext; InputReaderConfiguration mReaderConfiguration; @@ -123,11 +116,12 @@ protected: T& constructAndAddMapper(Args... args) { // ensure a device entry exists for this eventHubId mDevice->addEmptyEventHubDevice(EVENTHUB_ID); - // configure the empty device - configureDevice(/*changes=*/{}); - return mDevice->constructAndAddMapper<T>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), - args...); + auto& mapper = + mDevice->constructAndAddMapper<T>(EVENTHUB_ID, + mFakePolicy->getReaderConfiguration(), args...); + configureDevice(/*changes=*/{}); + return mapper; } void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height, diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 267c4002b0..48fd717631 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -24,7 +24,6 @@ #include <InputReader.h> #include <InputReaderBase.h> #include <InputReaderFactory.h> -#include <JoystickInputMapper.h> #include <KeyboardInputMapper.h> #include <MultiTouchInputMapper.h> #include <NotifyArgsBuilders.h> @@ -4040,6 +4039,51 @@ TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) { ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags); } +/** + * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce + * events that use the shared keyboard source across all mappers. This is to ensure that each + * input device generates key events in a consistent manner, regardless of which mapper produces + * the event. + */ +TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) { + mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE); + + // Add a mapper with SOURCE_KEYBOARD + KeyboardInputMapper& keyboardMapper = + constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD); + + process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1); + ASSERT_NO_FATAL_FAILURE( + mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD))); + process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0); + ASSERT_NO_FATAL_FAILURE( + mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD))); + + // Add a mapper with SOURCE_DPAD + KeyboardInputMapper& dpadMapper = + constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD); + for (auto* mapper : {&keyboardMapper, &dpadMapper}) { + process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( + WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD))); + process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( + WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD))); + } + + // Add a mapper with SOURCE_GAMEPAD + KeyboardInputMapper& gamepadMapper = + constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD); + for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) { + process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( + WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD))); + process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( + WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD))); + } +} + // --- KeyboardInputMapperTest_ExternalAlphabeticDevice --- class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest { @@ -10018,67 +10062,6 @@ TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGesture ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } -// --- JoystickInputMapperTest --- - -class JoystickInputMapperTest : public InputMapperTest { -protected: - static const int32_t RAW_X_MIN; - static const int32_t RAW_X_MAX; - static const int32_t RAW_Y_MIN; - static const int32_t RAW_Y_MAX; - - void SetUp() override { - InputMapperTest::SetUp(InputDeviceClass::JOYSTICK | InputDeviceClass::EXTERNAL); - } - void prepareAxes() { - mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0); - mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0); - } - - void processAxis(JoystickInputMapper& mapper, int32_t axis, int32_t value) { - process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, axis, value); - } - - void processSync(JoystickInputMapper& mapper) { - process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); - } - - void prepareVirtualDisplay(ui::Rotation orientation) { - setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, - VIRTUAL_DISPLAY_HEIGHT, orientation, VIRTUAL_DISPLAY_UNIQUE_ID, - NO_PORT, ViewportType::VIRTUAL); - } -}; - -const int32_t JoystickInputMapperTest::RAW_X_MIN = -32767; -const int32_t JoystickInputMapperTest::RAW_X_MAX = 32767; -const int32_t JoystickInputMapperTest::RAW_Y_MIN = -32767; -const int32_t JoystickInputMapperTest::RAW_Y_MAX = 32767; - -TEST_F(JoystickInputMapperTest, Configure_AssignsDisplayUniqueId) { - prepareAxes(); - JoystickInputMapper& mapper = constructAndAddMapper<JoystickInputMapper>(); - - mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID); - - prepareVirtualDisplay(ui::ROTATION_0); - - // Send an axis event - processAxis(mapper, ABS_X, 100); - processSync(mapper); - - NotifyMotionArgs args; - ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); - ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId); - - // Send another axis event - processAxis(mapper, ABS_Y, 100); - processSync(mapper); - - ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); - ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId); -} - // --- PeripheralControllerTest --- class PeripheralControllerTest : public testing::Test { diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h index 48e0b4f516..d51c708adb 100644 --- a/services/inputflinger/tests/InterfaceMocks.h +++ b/services/inputflinger/tests/InterfaceMocks.h @@ -26,6 +26,7 @@ #include <vector> #include <EventHub.h> +#include <InputDevice.h> #include <InputReaderBase.h> #include <InputReaderContext.h> #include <NotifyArgs.h> @@ -59,7 +60,7 @@ public: MOCK_METHOD(void, requestTimeoutAtTime, (nsecs_t when), (override)); int32_t bumpGeneration() override { return ++mGeneration; } - MOCK_METHOD(void, getExternalStylusDevices, (std::vector<InputDeviceInfo> & outDevices), + MOCK_METHOD(void, getExternalStylusDevices, (std::vector<InputDeviceInfo>& outDevices), (override)); MOCK_METHOD(std::list<NotifyArgs>, dispatchExternalStylusState, (const StylusState& outState), (override)); @@ -172,7 +173,7 @@ public: MOCK_METHOD(void, requestReopenDevices, (), (override)); MOCK_METHOD(void, wake, (), (override)); - MOCK_METHOD(void, dump, (std::string & dump), (const, override)); + MOCK_METHOD(void, dump, (std::string& dump), (const, override)); MOCK_METHOD(void, monitor, (), (const, override)); MOCK_METHOD(bool, isDeviceEnabled, (int32_t deviceId), (const, override)); MOCK_METHOD(status_t, enableDevice, (int32_t deviceId), (override)); @@ -190,4 +191,75 @@ public: MOCK_METHOD(void, notifyMouseCursorFadedOnTyping, (), (override)); }; +class MockInputDevice : public InputDevice { +public: + MockInputDevice(InputReaderContext* context, int32_t id, int32_t generation, + const InputDeviceIdentifier& identifier) + : InputDevice(context, id, generation, identifier) {} + + MOCK_METHOD(uint32_t, getSources, (), (const, override)); + MOCK_METHOD(bool, isEnabled, (), ()); + + MOCK_METHOD(void, dump, (std::string& dump, const std::string& eventHubDevStr), ()); + MOCK_METHOD(void, addEmptyEventHubDevice, (int32_t eventHubId), ()); + MOCK_METHOD(std::list<NotifyArgs>, addEventHubDevice, + (nsecs_t when, int32_t eventHubId, const InputReaderConfiguration& readerConfig), + ()); + MOCK_METHOD(void, removeEventHubDevice, (int32_t eventHubId), ()); + MOCK_METHOD(std::list<NotifyArgs>, configure, + (nsecs_t when, const InputReaderConfiguration& readerConfig, + ConfigurationChanges changes), + ()); + MOCK_METHOD(std::list<NotifyArgs>, reset, (nsecs_t when), ()); + MOCK_METHOD(std::list<NotifyArgs>, process, (const RawEvent* rawEvents, size_t count), ()); + MOCK_METHOD(std::list<NotifyArgs>, timeoutExpired, (nsecs_t when), ()); + MOCK_METHOD(std::list<NotifyArgs>, updateExternalStylusState, (const StylusState& state), ()); + + MOCK_METHOD(InputDeviceInfo, getDeviceInfo, (), ()); + MOCK_METHOD(int32_t, getKeyCodeState, (uint32_t sourceMask, int32_t keyCode), ()); + MOCK_METHOD(int32_t, getScanCodeState, (uint32_t sourceMask, int32_t scanCode), ()); + MOCK_METHOD(int32_t, getSwitchState, (uint32_t sourceMask, int32_t switchCode), ()); + MOCK_METHOD(int32_t, getKeyCodeForKeyLocation, (int32_t locationKeyCode), (const)); + MOCK_METHOD(bool, markSupportedKeyCodes, + (uint32_t sourceMask, const std::vector<int32_t>& keyCodes, uint8_t* outFlags), ()); + MOCK_METHOD(std::list<NotifyArgs>, vibrate, + (const VibrationSequence& sequence, ssize_t repeat, int32_t token), ()); + MOCK_METHOD(std::list<NotifyArgs>, cancelVibrate, (int32_t token), ()); + MOCK_METHOD(bool, isVibrating, (), ()); + MOCK_METHOD(std::vector<int32_t>, getVibratorIds, (), ()); + MOCK_METHOD(std::list<NotifyArgs>, cancelTouch, (nsecs_t when, nsecs_t readTime), ()); + MOCK_METHOD(bool, enableSensor, + (InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency), + ()); + + MOCK_METHOD(void, disableSensor, (InputDeviceSensorType sensorType), ()); + MOCK_METHOD(void, flushSensor, (InputDeviceSensorType sensorType), ()); + + MOCK_METHOD(std::optional<int32_t>, getBatteryEventHubId, (), (const)); + + MOCK_METHOD(bool, setLightColor, (int32_t lightId, int32_t color), ()); + MOCK_METHOD(bool, setLightPlayerId, (int32_t lightId, int32_t playerId), ()); + MOCK_METHOD(std::optional<int32_t>, getLightColor, (int32_t lightId), ()); + MOCK_METHOD(std::optional<int32_t>, getLightPlayerId, (int32_t lightId), ()); + + MOCK_METHOD(int32_t, getMetaState, (), ()); + MOCK_METHOD(void, updateMetaState, (int32_t keyCode), ()); + + MOCK_METHOD(void, addKeyRemapping, (int32_t fromKeyCode, int32_t toKeyCode), ()); + + MOCK_METHOD(void, setKeyboardType, (KeyboardType keyboardType), ()); + + MOCK_METHOD(void, bumpGeneration, (), ()); + + MOCK_METHOD(const PropertyMap&, getConfiguration, (), (const, override)); + + MOCK_METHOD(NotifyDeviceResetArgs, notifyReset, (nsecs_t when), ()); + + MOCK_METHOD(std::optional<ui::LogicalDisplayId>, getAssociatedDisplayId, (), ()); + + MOCK_METHOD(void, updateLedState, (bool reset), ()); + + MOCK_METHOD(size_t, getMapperCount, (), ()); +}; } // namespace android diff --git a/services/inputflinger/tests/JoystickInputMapper_test.cpp b/services/inputflinger/tests/JoystickInputMapper_test.cpp new file mode 100644 index 0000000000..ec7019256f --- /dev/null +++ b/services/inputflinger/tests/JoystickInputMapper_test.cpp @@ -0,0 +1,103 @@ +/* + * Copyright 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 "JoystickInputMapper.h" + +#include <optional> + +#include <EventHub.h> +#include <NotifyArgs.h> +#include <ftl/flags.h> +#include <gtest/gtest.h> +#include <input/DisplayViewport.h> +#include <linux/input-event-codes.h> +#include <ui/LogicalDisplayId.h> + +#include "InputMapperTest.h" +#include "TestConstants.h" + +namespace android { + +namespace { + +using namespace ftl::flag_operators; + +} // namespace + +class JoystickInputMapperTest : public InputMapperTest { +protected: + static const int32_t RAW_X_MIN; + static const int32_t RAW_X_MAX; + static const int32_t RAW_Y_MIN; + static const int32_t RAW_Y_MAX; + + static constexpr ui::LogicalDisplayId VIRTUAL_DISPLAY_ID = ui::LogicalDisplayId{1}; + static const char* const VIRTUAL_DISPLAY_UNIQUE_ID; + + void SetUp() override { + InputMapperTest::SetUp(InputDeviceClass::JOYSTICK | InputDeviceClass::EXTERNAL); + } + void prepareAxes() { + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0); + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0); + } + + void processAxis(JoystickInputMapper& mapper, int32_t axis, int32_t value) { + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, axis, value); + } + + void processSync(JoystickInputMapper& mapper) { + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); + } + + void prepareVirtualDisplay(ui::Rotation orientation) { + setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, /*width=*/400, /*height=*/500, orientation, + VIRTUAL_DISPLAY_UNIQUE_ID, /*physicalPort=*/std::nullopt, + ViewportType::VIRTUAL); + } +}; + +const int32_t JoystickInputMapperTest::RAW_X_MIN = -32767; +const int32_t JoystickInputMapperTest::RAW_X_MAX = 32767; +const int32_t JoystickInputMapperTest::RAW_Y_MIN = -32767; +const int32_t JoystickInputMapperTest::RAW_Y_MAX = 32767; +const char* const JoystickInputMapperTest::VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1"; + +TEST_F(JoystickInputMapperTest, Configure_AssignsDisplayUniqueId) { + prepareAxes(); + JoystickInputMapper& mapper = constructAndAddMapper<JoystickInputMapper>(); + + mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID); + + prepareVirtualDisplay(ui::ROTATION_0); + + // Send an axis event + processAxis(mapper, ABS_X, 100); + processSync(mapper); + + NotifyMotionArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId); + + // Send another axis event + processAxis(mapper, ABS_Y, 100); + processSync(mapper); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId); +} + +} // namespace android diff --git a/services/inputflinger/tests/KeyboardInputMapper_test.cpp b/services/inputflinger/tests/KeyboardInputMapper_test.cpp index d3e8dee4a0..88c25d302a 100644 --- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp +++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp @@ -55,7 +55,6 @@ protected: void SetUp() override { InputMapperUnitTest::SetUp(); - createDevice(); // set key-codes expected in tests for (const auto& [scanCode, outKeycode] : mKeyCodeMap) { @@ -66,6 +65,8 @@ protected: mFakePolicy = sp<FakeInputReaderPolicy>::make(); EXPECT_CALL(mMockInputReaderContext, getPolicy).WillRepeatedly(Return(mFakePolicy.get())); + ON_CALL((*mDevice), getSources).WillByDefault(Return(AINPUT_SOURCE_KEYBOARD)); + mMapper = createInputMapper<KeyboardInputMapper>(*mDeviceContext, mReaderConfiguration, AINPUT_SOURCE_KEYBOARD); } diff --git a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp index d4d3c3857f..9a6b266b21 100644 --- a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp +++ b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp @@ -109,7 +109,6 @@ protected: mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0, /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL); - createDevice(); mMapper = createInputMapper<MultiTouchInputMapper>(*mDeviceContext, mFakePolicy->getReaderConfiguration()); } diff --git a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp index b441a23803..9ddb8c138d 100644 --- a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp +++ b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp @@ -23,10 +23,7 @@ class MultiTouchMotionAccumulatorTest : public InputMapperUnitTest { protected: static constexpr size_t SLOT_COUNT = 8; - void SetUp() override { - InputMapperUnitTest::SetUp(); - createDevice(); - } + void SetUp() override { InputMapperUnitTest::SetUp(); } MultiTouchMotionAccumulator mMotionAccumulator; diff --git a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp index 366b3dcdd0..a796c49dbe 100644 --- a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp +++ b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp @@ -138,7 +138,6 @@ TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdWithAssociatedViewport) { mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport}); // Set up the secondary display as the associated viewport of the mapper. - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport); mMapper = createInputMapper<RotaryEncoderInputMapper>(deviceContext, mReaderConfiguration); @@ -159,7 +158,6 @@ TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdNoAssociatedViewport) { mFakePolicy->addDisplayViewport(createPrimaryViewport()); // Set up the mapper with no associated viewport. - createDevice(); mMapper = createInputMapper<RotaryEncoderInputMapper>(*mDeviceContext, mReaderConfiguration); // Ensure input events are generated without display ID @@ -174,7 +172,6 @@ TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdNoAssociatedViewport) { } TEST_F(RotaryEncoderInputMapperTest, ProcessRegularScroll) { - createDevice(); mMapper = createInputMapper<RotaryEncoderInputMapper>(*mDeviceContext, mReaderConfiguration); std::list<NotifyArgs> args; @@ -191,7 +188,6 @@ TEST_F(RotaryEncoderInputMapperTest, ProcessHighResScroll) { vd_flags::high_resolution_scroll(true); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) .WillRepeatedly(Return(true)); - createDevice(); mMapper = createInputMapper<RotaryEncoderInputMapper>(*mDeviceContext, mReaderConfiguration); std::list<NotifyArgs> args; @@ -208,7 +204,6 @@ TEST_F(RotaryEncoderInputMapperTest, HighResScrollIgnoresRegularScroll) { vd_flags::high_resolution_scroll(true); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) .WillRepeatedly(Return(true)); - createDevice(); mMapper = createInputMapper<RotaryEncoderInputMapper>(*mDeviceContext, mReaderConfiguration); std::list<NotifyArgs> args; diff --git a/services/inputflinger/tests/SwitchInputMapper_test.cpp b/services/inputflinger/tests/SwitchInputMapper_test.cpp index 4020e78701..ebbf10b8db 100644 --- a/services/inputflinger/tests/SwitchInputMapper_test.cpp +++ b/services/inputflinger/tests/SwitchInputMapper_test.cpp @@ -33,7 +33,6 @@ class SwitchInputMapperTest : public InputMapperUnitTest { protected: void SetUp() override { InputMapperUnitTest::SetUp(); - createDevice(); mMapper = createInputMapper<SwitchInputMapper>(*mDeviceContext, mFakePolicy->getReaderConfiguration()); } diff --git a/services/inputflinger/tests/TouchpadInputMapper_test.cpp b/services/inputflinger/tests/TouchpadInputMapper_test.cpp index 1afb4f090a..fc8a7dafb0 100644 --- a/services/inputflinger/tests/TouchpadInputMapper_test.cpp +++ b/services/inputflinger/tests/TouchpadInputMapper_test.cpp @@ -109,7 +109,6 @@ protected: .WillRepeatedly([]() -> base::Result<std::vector<int32_t>> { return base::ResultError("Axis not supported", NAME_NOT_FOUND); }); - createDevice(); mMapper = createInputMapper<TouchpadInputMapper>(*mDeviceContext, mReaderConfiguration); } }; diff --git a/services/inputflinger/tests/VibratorInputMapper_test.cpp b/services/inputflinger/tests/VibratorInputMapper_test.cpp index aa4a6bb382..6e3344c345 100644 --- a/services/inputflinger/tests/VibratorInputMapper_test.cpp +++ b/services/inputflinger/tests/VibratorInputMapper_test.cpp @@ -36,7 +36,6 @@ class VibratorInputMapperTest : public InputMapperUnitTest { protected: void SetUp() override { InputMapperUnitTest::SetUp(); - createDevice(); EXPECT_CALL(mMockEventHub, getDeviceClasses(EVENTHUB_ID)) .WillRepeatedly(testing::Return(InputDeviceClass::VIBRATOR)); EXPECT_CALL(mMockEventHub, getVibratorIds(EVENTHUB_ID)) diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index bf56d3aac2..fea0d9a1c1 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -129,7 +129,6 @@ public: } if (mFdp->ConsumeBool()) { return std::optional<RawAbsoluteAxisInfo>({ - .valid = mFdp->ConsumeBool(), .minValue = mFdp->ConsumeIntegral<int32_t>(), .maxValue = mFdp->ConsumeIntegral<int32_t>(), .flat = mFdp->ConsumeIntegral<int32_t>(), diff --git a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp index c620032eef..ebbb311512 100644 --- a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp @@ -34,7 +34,6 @@ void setAxisInfo(ThreadSafeFuzzedDataProvider& fdp, FuzzEventHub& eventHub, int3 if (fdp.ConsumeBool()) { eventHub.setAbsoluteAxisInfo(id, axis, RawAbsoluteAxisInfo{ - .valid = fdp.ConsumeBool(), .minValue = fdp.ConsumeIntegral<int32_t>(), .maxValue = fdp.ConsumeIntegral<int32_t>(), .flat = fdp.ConsumeIntegral<int32_t>(), diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a6d2b1529a..0eb6cc32c5 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2540,10 +2540,6 @@ bool Layer::hasInputInfo() const { compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( const DisplayDevice* display) const { if (!display) return nullptr; - if (!mFlinger->mLayerLifecycleManagerEnabled) { - return display->getCompositionDisplay()->getOutputLayerForLayer( - getCompositionEngineLayerFE()); - } sp<LayerFE> layerFE; frontend::LayerHierarchy::TraversalPath path{.id = static_cast<uint32_t>(sequence)}; for (auto& [p, layer] : mLayerFEs) { @@ -2559,10 +2555,6 @@ compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( const DisplayDevice* display, const frontend::LayerHierarchy::TraversalPath& path) const { if (!display) return nullptr; - if (!mFlinger->mLayerLifecycleManagerEnabled) { - return display->getCompositionDisplay()->getOutputLayerForLayer( - getCompositionEngineLayerFE()); - } sp<LayerFE> layerFE; for (auto& [p, layer] : mLayerFEs) { if (p == path) { diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h index 6f9c146dea..998b1b81b1 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h @@ -321,7 +321,10 @@ public: RefreshRateSelector(const RefreshRateSelector&) = delete; RefreshRateSelector& operator=(const RefreshRateSelector&) = delete; - const DisplayModes& displayModes() const { return mDisplayModes; } + DisplayModes displayModes() const { + std::lock_guard lock(mLock); + return mDisplayModes; + } // Returns whether switching modes (refresh rate or resolution) is possible. // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp index ee7eda1354..04491a25c3 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp @@ -452,7 +452,7 @@ Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentT const auto currentPeriod = mRateMap.find(idealPeriod())->second.slope; const auto threshold = currentPeriod / 2; - const auto minFramePeriod = minFramePeriodLocked().ns(); + const auto minFramePeriod = minFramePeriodLocked(); auto prev = lastConfirmedPresentTime.ns(); for (auto& current : mPastExpectedPresentTimes) { @@ -463,10 +463,10 @@ Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentT 1e6f); } - const auto minPeriodViolation = current.ns() - prev + threshold < minFramePeriod; + const auto minPeriodViolation = current.ns() - prev + threshold < minFramePeriod.ns(); if (minPeriodViolation) { SFTRACE_NAME("minPeriodViolation"); - current = TimePoint::fromNs(prev + minFramePeriod); + current = TimePoint::fromNs(prev + minFramePeriod.ns()); prev = current.ns(); } else { break; @@ -477,7 +477,7 @@ Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentT const auto phase = Duration(mPastExpectedPresentTimes.back() - expectedPresentTime); if (phase > 0ns) { for (auto& timeline : mTimelines) { - timeline.shiftVsyncSequence(phase); + timeline.shiftVsyncSequence(phase, minFramePeriod); } mPastExpectedPresentTimes.clear(); return phase; @@ -778,8 +778,15 @@ bool VSyncPredictor::VsyncTimeline::isVSyncInPhase(Model model, nsecs_t vsync, F return vsyncSequence.seq % divisor == 0; } -void VSyncPredictor::VsyncTimeline::shiftVsyncSequence(Duration phase) { +void VSyncPredictor::VsyncTimeline::shiftVsyncSequence(Duration phase, Period minFramePeriod) { if (mLastVsyncSequence) { + const auto renderRate = mRenderRateOpt.value_or(Fps::fromPeriodNsecs(mIdealPeriod.ns())); + const auto threshold = mIdealPeriod.ns() / 2; + if (renderRate.getPeriodNsecs() - phase.ns() + threshold >= minFramePeriod.ns()) { + SFTRACE_FORMAT_INSTANT("Not-Adjusting vsync by %.2f", + static_cast<float>(phase.ns()) / 1e6f); + return; + } SFTRACE_FORMAT_INSTANT("adjusting vsync by %.2f", static_cast<float>(phase.ns()) / 1e6f); mLastVsyncSequence->vsyncTime += phase.ns(); } diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h index 9e1c90bbef..6c8a2f29f9 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.h +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h @@ -104,7 +104,7 @@ private: void freeze(TimePoint lastVsync); std::optional<TimePoint> validUntil() const { return mValidUntil; } bool isVSyncInPhase(Model, nsecs_t vsync, Fps frameRate); - void shiftVsyncSequence(Duration phase); + void shiftVsyncSequence(Duration phase, Period minFramePeriod); void setRenderRate(std::optional<Fps> renderRateOpt) { mRenderRateOpt = renderRateOpt; } enum class VsyncOnTimeline { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b2fe5ae5a6..299f70bf97 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -534,9 +534,6 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI mIgnoreHdrCameraLayers = ignore_hdr_camera_layers(false); - mLayerLifecycleManagerEnabled = - base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, true); - // These are set by the HWC implementation to indicate that they will use the workarounds. mIsHotplugErrViaNegVsync = base::GetBoolProperty("debug.sf.hwc_hotplug_error_via_neg_vsync"s, false); @@ -2679,11 +2676,8 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded); bool transactionsAreEmpty = false; - if (mLayerLifecycleManagerEnabled) { - mustComposite |= - updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(), - flushTransactions, transactionsAreEmpty); - } + mustComposite |= updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(), + flushTransactions, transactionsAreEmpty); // Tell VsyncTracker that we are going to present this frame before scheduling // setTransactionFlags which will schedule another SF frame. This was if the tracker @@ -2717,9 +2711,7 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, mUpdateAttachedChoreographer = false; Mutex::Autolock lock(mStateLock); - mScheduler->chooseRefreshRateForContent(mLayerLifecycleManagerEnabled - ? &mLayerHierarchyBuilder.getHierarchy() - : nullptr, + mScheduler->chooseRefreshRateForContent(&mLayerHierarchyBuilder.getHierarchy(), updateAttachedChoreographer); if (FlagManager::getInstance().connected_display()) { @@ -2840,7 +2832,7 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( constexpr bool kCursorOnly = false; const auto layers = moveSnapshotsToCompositionArgs(refreshArgs, kCursorOnly); - if (mLayerLifecycleManagerEnabled && !mVisibleRegionsDirty) { + if (!mVisibleRegionsDirty) { for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { auto compositionDisplay = display->getCompositionDisplay(); if (!compositionDisplay->getState().isEnabled) continue; @@ -3259,28 +3251,20 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, } }; - if (mLayerLifecycleManagerEnabled) { - mLayerSnapshotBuilder.forEachVisibleSnapshot( - [&, compositionDisplay = compositionDisplay]( - std::unique_ptr<frontend::LayerSnapshot>& - snapshot) FTL_FAKE_GUARD(kMainThreadContext) { - auto it = mLegacyLayers.find(snapshot->sequence); - LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(), - "Couldnt find layer object for %s", - snapshot->getDebugString().c_str()); - auto& legacyLayer = it->second; - sp<LayerFE> layerFe = - legacyLayer->getCompositionEngineLayerFE(snapshot->path); - - updateInfoFn(compositionDisplay, *snapshot, layerFe); - }); - } else { - mDrawingState.traverse([&, compositionDisplay = compositionDisplay](Layer* layer) { - const auto layerFe = layer->getCompositionEngineLayerFE(); - const frontend::LayerSnapshot& snapshot = *layer->getLayerSnapshot(); - updateInfoFn(compositionDisplay, snapshot, layerFe); - }); - } + mLayerSnapshotBuilder.forEachVisibleSnapshot( + [&, compositionDisplay = compositionDisplay]( + std::unique_ptr<frontend::LayerSnapshot>& snapshot) + FTL_FAKE_GUARD(kMainThreadContext) { + auto it = mLegacyLayers.find(snapshot->sequence); + LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(), + "Couldnt find layer object for %s", + snapshot->getDebugString().c_str()); + auto& legacyLayer = it->second; + sp<LayerFE> layerFe = + legacyLayer->getCompositionEngineLayerFE(snapshot->path); + + updateInfoFn(compositionDisplay, *snapshot, layerFe); + }); listener->dispatchHdrLayerInfo(info); } } @@ -3326,9 +3310,8 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, if (!layer->hasTrustedPresentationListener()) { return; } - const frontend::LayerSnapshot* snapshot = mLayerLifecycleManagerEnabled - ? mLayerSnapshotBuilder.getSnapshot(layer->sequence) - : layer->getLayerSnapshot(); + const frontend::LayerSnapshot* snapshot = + mLayerSnapshotBuilder.getSnapshot(layer->sequence); std::optional<const DisplayDevice*> displayOpt = std::nullopt; if (snapshot) { displayOpt = layerStackToDisplay.get(snapshot->outputFilter.layerStack); @@ -4053,13 +4036,6 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { // Commit display transactions. const bool displayTransactionNeeded = transactionFlags & eDisplayTransactionNeeded; mFrontEndDisplayInfosChanged = displayTransactionNeeded; - if (displayTransactionNeeded && !mLayerLifecycleManagerEnabled) { - processDisplayChangesLocked(); - mFrontEndDisplayInfos.clear(); - for (const auto& [_, display] : mDisplays) { - mFrontEndDisplayInfos.try_emplace(display->getLayerStack(), display->getFrontEndInfo()); - } - } mForceTransactionDisplayChange = displayTransactionNeeded; if (mSomeChildrenChanged) { @@ -4240,23 +4216,10 @@ void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos, outWindowInfos.reserve(sNumWindowInfos); sNumWindowInfos = 0; - if (mLayerLifecycleManagerEnabled) { - mLayerSnapshotBuilder.forEachInputSnapshot( - [&outWindowInfos](const frontend::LayerSnapshot& snapshot) { - outWindowInfos.push_back(snapshot.inputInfo); - }); - } else { - mDrawingState.traverseInReverseZOrder([&](Layer* layer) FTL_FAKE_GUARD(kMainThreadContext) { - if (!layer->needsInputInfo()) return; - const auto opt = - mFrontEndDisplayInfos.get(layer->getLayerStack()) - .transform([](const frontend::DisplayInfo& info) { - return Layer::InputDisplayArgs{&info.transform, info.isSecure}; - }); - - outWindowInfos.push_back(layer->fillInputInfo(opt.value_or(Layer::InputDisplayArgs{}))); - }); - } + mLayerSnapshotBuilder.forEachInputSnapshot( + [&outWindowInfos](const frontend::LayerSnapshot& snapshot) { + outWindowInfos.push_back(snapshot.inputInfo); + }); sNumWindowInfos = outWindowInfos.size(); @@ -4330,10 +4293,8 @@ void SurfaceFlinger::notifyCpuLoadUp() { void SurfaceFlinger::onChoreographerAttached() { SFTRACE_CALL(); - if (mLayerLifecycleManagerEnabled) { - mUpdateAttachedChoreographer = true; - scheduleCommit(FrameHint::kNone); - } + mUpdateAttachedChoreographer = true; + scheduleCommit(FrameHint::kNone); } void SurfaceFlinger::onExpectedPresentTimePosted(TimePoint expectedPresentTime, @@ -4877,101 +4838,6 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyTimelin return TransactionReadiness::Ready; } -TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferCheckLegacy( - const TransactionHandler::TransactionFlushState& flushState) { - using TransactionReadiness = TransactionHandler::TransactionReadiness; - auto ready = TransactionReadiness::Ready; - flushState.transaction->traverseStatesWithBuffersWhileTrue([&](const ResolvedComposerState& - resolvedState) -> bool { - sp<Layer> layer = LayerHandle::getLayer(resolvedState.state.surface); - - const auto& transaction = *flushState.transaction; - const auto& s = resolvedState.state; - // check for barrier frames - if (s.bufferData->hasBarrier) { - // The current producerId is already a newer producer than the buffer that has a - // barrier. This means the incoming buffer is older and we can release it here. We - // don't wait on the barrier since we know that's stale information. - if (layer->getDrawingState().barrierProducerId > s.bufferData->producerId) { - layer->callReleaseBufferCallback(s.bufferData->releaseBufferListener, - resolvedState.externalTexture->getBuffer(), - s.bufferData->frameNumber, - s.bufferData->acquireFence); - // Delete the entire state at this point and not just release the buffer because - // everything associated with the Layer in this Transaction is now out of date. - SFTRACE_FORMAT("DeleteStaleBuffer %s barrierProducerId:%d > %d", - layer->getDebugName(), layer->getDrawingState().barrierProducerId, - s.bufferData->producerId); - return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL; - } - - if (layer->getDrawingState().barrierFrameNumber < s.bufferData->barrierFrameNumber) { - const bool willApplyBarrierFrame = - flushState.bufferLayersReadyToPresent.contains(s.surface.get()) && - ((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >= - s.bufferData->barrierFrameNumber)); - if (!willApplyBarrierFrame) { - SFTRACE_FORMAT("NotReadyBarrier %s barrierFrameNumber:%" PRId64 " > %" PRId64, - layer->getDebugName(), - layer->getDrawingState().barrierFrameNumber, - s.bufferData->barrierFrameNumber); - ready = TransactionReadiness::NotReadyBarrier; - return TraverseBuffersReturnValues::STOP_TRAVERSAL; - } - } - } - - // If backpressure is enabled and we already have a buffer to commit, keep - // the transaction in the queue. - const bool hasPendingBuffer = - flushState.bufferLayersReadyToPresent.contains(s.surface.get()); - if (layer->backpressureEnabled() && hasPendingBuffer && transaction.isAutoTimestamp) { - SFTRACE_FORMAT("hasPendingBuffer %s", layer->getDebugName()); - ready = TransactionReadiness::NotReady; - return TraverseBuffersReturnValues::STOP_TRAVERSAL; - } - - const bool acquireFenceAvailable = s.bufferData && - s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) && - s.bufferData->acquireFence; - const bool fenceSignaled = !acquireFenceAvailable || - s.bufferData->acquireFence->getStatus() != Fence::Status::Unsignaled; - if (!fenceSignaled) { - // check fence status - const bool allowLatchUnsignaled = shouldLatchUnsignaled(s, transaction.states.size(), - flushState.firstTransaction) && - layer->isSimpleBufferUpdate(s); - - if (allowLatchUnsignaled) { - SFTRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s", - layer->getDebugName()); - ready = TransactionReadiness::NotReadyUnsignaled; - } else { - ready = TransactionReadiness::NotReady; - auto& listener = s.bufferData->releaseBufferListener; - if (listener && - (flushState.queueProcessTime - transaction.postTime) > - std::chrono::nanoseconds(4s).count()) { - // Used to add a stalled transaction which uses an internal lock. - ftl::FakeGuard guard(kMainThreadContext); - mTransactionHandler - .onTransactionQueueStalled(transaction.id, - {.pid = layer->getOwnerPid(), - .layerId = static_cast<uint32_t>( - layer->getSequence()), - .layerName = layer->getDebugName(), - .bufferId = s.bufferData->getId(), - .frameNumber = s.bufferData->frameNumber}); - } - SFTRACE_FORMAT("fence unsignaled %s", layer->getDebugName()); - return TraverseBuffersReturnValues::STOP_TRAVERSAL; - } - } - return TraverseBuffersReturnValues::CONTINUE_TRAVERSAL; - }); - return ready; -} - TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferCheck( const TransactionHandler::TransactionFlushState& flushState) { using TransactionReadiness = TransactionHandler::TransactionReadiness; @@ -5083,15 +4949,8 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC void SurfaceFlinger::addTransactionReadyFilters() { mTransactionHandler.addTransactionReadyFilter( std::bind(&SurfaceFlinger::transactionReadyTimelineCheck, this, std::placeholders::_1)); - if (mLayerLifecycleManagerEnabled) { - mTransactionHandler.addTransactionReadyFilter( - std::bind(&SurfaceFlinger::transactionReadyBufferCheck, this, - std::placeholders::_1)); - } else { - mTransactionHandler.addTransactionReadyFilter( - std::bind(&SurfaceFlinger::transactionReadyBufferCheckLegacy, this, - std::placeholders::_1)); - } + mTransactionHandler.addTransactionReadyFilter( + std::bind(&SurfaceFlinger::transactionReadyBufferCheck, this, std::placeholders::_1)); } // For tests only @@ -5187,7 +5046,7 @@ bool SurfaceFlinger::shouldLatchUnsignaled(const layer_state_t& state, size_t nu status_t SurfaceFlinger::setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states, - const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, + Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId, @@ -5202,7 +5061,7 @@ status_t SurfaceFlinger::setTransactionState( composerState.state.sanitize(permissions); } - for (DisplayState display : displays) { + for (DisplayState& display : displays) { display.sanitize(permissions); } @@ -5323,11 +5182,6 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid, uint64_t transactionId) { uint32_t transactionFlags = 0; - if (!mLayerLifecycleManagerEnabled) { - for (DisplayState& display : displays) { - transactionFlags |= setDisplayStateLocked(display); - } - } // start and end registration for listeners w/ no surface so they can get their callback. Note // that listeners with SurfaceControls will start registration during setClientStateLocked @@ -5335,27 +5189,11 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin for (const auto& listener : listenerCallbacks) { mTransactionCallbackInvoker.addEmptyTransaction(listener); } - nsecs_t now = systemTime(); uint32_t clientStateFlags = 0; for (auto& resolvedState : states) { clientStateFlags |= updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState, desiredPresentTime, isAutoTimestamp, postTime, transactionId); - if (!mLayerLifecycleManagerEnabled) { - if ((flags & eAnimation) && resolvedState.state.surface) { - if (const auto layer = LayerHandle::getLayer(resolvedState.state.surface)) { - const auto layerProps = scheduler::LayerProps{ - .visible = layer->isVisible(), - .bounds = layer->getBounds(), - .transform = layer->getTransform(), - .setFrameRateVote = layer->getFrameRateForLayerTree(), - .frameRateSelectionPriority = layer->getFrameRateSelectionPriority(), - .isFrontBuffered = layer->isFrontBuffered(), - }; - layer->recordLayerHistoryAnimationTx(layerProps, now); - } - } - } } transactionFlags |= clientStateFlags; @@ -6667,53 +6505,35 @@ void SurfaceFlinger::dumpFrontEnd(std::string& result) { } void SurfaceFlinger::dumpVisibleFrontEnd(std::string& result) { - if (!mLayerLifecycleManagerEnabled) { - StringAppendF(&result, "Composition layers\n"); - mDrawingState.traverseInZOrder([&](Layer* layer) { - auto* compositionState = layer->getCompositionState(); - if (!compositionState || !compositionState->isVisible) return; - android::base::StringAppendF(&result, "* Layer %p (%s)\n", layer, - layer->getDebugName() ? layer->getDebugName() - : "<unknown>"); - compositionState->dump(result); - }); - - StringAppendF(&result, "Offscreen Layers\n"); - for (Layer* offscreenLayer : mOffscreenLayers) { - offscreenLayer->traverse(LayerVector::StateSet::Drawing, - [&](Layer* layer) { layer->dumpOffscreenDebugInfo(result); }); - } - } else { - std::ostringstream out; - out << "\nComposition list\n"; - ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; - mLayerSnapshotBuilder.forEachVisibleSnapshot( - [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) { - if (snapshot->hasSomethingToDraw()) { - if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) { - lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack; - out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; - } - out << " " << *snapshot << "\n"; + std::ostringstream out; + out << "\nComposition list\n"; + ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; + mLayerSnapshotBuilder.forEachVisibleSnapshot( + [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) { + if (snapshot->hasSomethingToDraw()) { + if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) { + lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack; + out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; } - }); + out << " " << *snapshot << "\n"; + } + }); - out << "\nInput list\n"; - lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; - mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) { - if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { - lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; - out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; - } - out << " " << snapshot << "\n"; - }); + out << "\nInput list\n"; + lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; + mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) { + if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { + lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; + out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; + } + out << " " << snapshot << "\n"; + }); - out << "\nLayer Hierarchy\n" - << mLayerHierarchyBuilder.getHierarchy() << "\nOffscreen Hierarchy\n" - << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n"; - result = out.str(); - dumpHwcLayersMinidump(result); - } + out << "\nLayer Hierarchy\n" + << mLayerHierarchyBuilder.getHierarchy() << "\nOffscreen Hierarchy\n" + << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n"; + result = out.str(); + dumpHwcLayersMinidump(result); } perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { @@ -6816,28 +6636,8 @@ void SurfaceFlinger::dumpOffscreenLayers(std::string& result) { result.append(future.get()); } -void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) const { - for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { - const auto displayId = HalDisplayId::tryCast(display->getId()); - if (!displayId) { - continue; - } - - StringAppendF(&result, "Display %s (%s) HWC layers:\n", to_string(*displayId).c_str(), - displayId == mActiveDisplayId ? "active" : "inactive"); - Layer::miniDumpHeader(result); - - const DisplayDevice& ref = *display; - mDrawingState.traverseInZOrder([&](Layer* layer) { layer->miniDumpLegacy(result, ref); }); - result.append("\n"); - } -} - void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { - if (!mLayerLifecycleManagerEnabled) { - return dumpHwcLayersMinidumpLockedLegacy(result); - } - for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { + for (const auto& [token, display] : mDisplays) { const auto displayId = HalDisplayId::tryCast(display->getId()); if (!displayId) { continue; @@ -6916,8 +6716,7 @@ void SurfaceFlinger::dumpAll(const DumpArgs& args, const std::string& compositio * Dump the visible layer list */ colorizer.bold(result); - StringAppendF(&result, "SurfaceFlinger New Frontend Enabled:%s\n", - mLayerLifecycleManagerEnabled ? "true" : "false"); + StringAppendF(&result, "SurfaceFlinger New Frontend Enabled:%s\n", "true"); StringAppendF(&result, "Active Layers - layers with client handles (count = %zu)\n", mNumLayers.load()); colorizer.reset(result); @@ -8641,12 +8440,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( } void SurfaceFlinger::traverseLegacyLayers(const LayerVector::Visitor& visitor) const { - if (mLayerLifecycleManagerEnabled) { - for (auto& layer : mLegacyLayers) { - visitor(layer.second.get()); - } - } else { - mDrawingState.traverse(visitor); + for (auto& layer : mLegacyLayers) { + visitor(layer.second.get()); } } @@ -8664,42 +8459,6 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& layersSortedByZ.traverseInReverseZOrder(stateSet, visitor); } -void SurfaceFlinger::traverseLayersInLayerStack(ui::LayerStack layerStack, const int32_t uid, - std::unordered_set<uint32_t> excludeLayerIds, - const LayerVector::Visitor& visitor) { - // We loop through the first level of layers without traversing, - // as we need to determine which layers belong to the requested display. - for (const auto& layer : mDrawingState.layersSortedByZ) { - if (layer->getLayerStack() != layerStack) { - continue; - } - // relative layers are traversed in Layer::traverseInZOrder - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - if (layer->isInternalDisplayOverlay()) { - return; - } - if (!layer->isVisible()) { - return; - } - if (uid != CaptureArgs::UNSET_UID && layer->getOwnerUid() != uid) { - return; - } - - if (!excludeLayerIds.empty()) { - auto p = sp<Layer>::fromExisting(layer); - while (p != nullptr) { - if (excludeLayerIds.count(p->sequence) != 0) { - return; - } - p = p->getParent(); - } - } - - visitor(layer); - }); - } -} - ftl::Optional<scheduler::FrameRateMode> SurfaceFlinger::getPreferredDisplayMode( PhysicalDisplayId displayId, DisplayModeId defaultModeId) const { if (const auto schedulerMode = mScheduler->getPreferredDisplayMode(); @@ -9363,89 +9122,49 @@ void SurfaceFlinger::updateLayerMetadataSnapshot() { void SurfaceFlinger::moveSnapshotsFromCompositionArgs( compositionengine::CompositionRefreshArgs& refreshArgs, const std::vector<std::pair<Layer*, LayerFE*>>& layers) { - if (mLayerLifecycleManagerEnabled) { - std::vector<std::unique_ptr<frontend::LayerSnapshot>>& snapshots = - mLayerSnapshotBuilder.getSnapshots(); - for (auto [_, layerFE] : layers) { - auto i = layerFE->mSnapshot->globalZ; - snapshots[i] = std::move(layerFE->mSnapshot); - } - } - if (!mLayerLifecycleManagerEnabled) { - for (auto [layer, layerFE] : layers) { - layer->updateLayerSnapshot(std::move(layerFE->mSnapshot)); - } + std::vector<std::unique_ptr<frontend::LayerSnapshot>>& snapshots = + mLayerSnapshotBuilder.getSnapshots(); + for (auto [_, layerFE] : layers) { + auto i = layerFE->mSnapshot->globalZ; + snapshots[i] = std::move(layerFE->mSnapshot); } } std::vector<std::pair<Layer*, LayerFE*>> SurfaceFlinger::moveSnapshotsToCompositionArgs( compositionengine::CompositionRefreshArgs& refreshArgs, bool cursorOnly) { std::vector<std::pair<Layer*, LayerFE*>> layers; - if (mLayerLifecycleManagerEnabled) { - nsecs_t currentTime = systemTime(); - const bool needsMetadata = mCompositionEngine->getFeatureFlags().test( - compositionengine::Feature::kSnapshotLayerMetadata); - mLayerSnapshotBuilder.forEachSnapshot( - [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) FTL_FAKE_GUARD( - kMainThreadContext) { - if (cursorOnly && - snapshot->compositionType != - aidl::android::hardware::graphics::composer3::Composition::CURSOR) { - return; - } - - if (!snapshot->hasSomethingToDraw()) { - return; - } - - auto it = mLegacyLayers.find(snapshot->sequence); - LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(), - "Couldnt find layer object for %s", - snapshot->getDebugString().c_str()); - auto& legacyLayer = it->second; - sp<LayerFE> layerFE = legacyLayer->getCompositionEngineLayerFE(snapshot->path); - snapshot->fps = getLayerFramerate(currentTime, snapshot->sequence); - layerFE->mSnapshot = std::move(snapshot); - refreshArgs.layers.push_back(layerFE); - layers.emplace_back(legacyLayer.get(), layerFE.get()); - }, - [needsMetadata](const frontend::LayerSnapshot& snapshot) { - return snapshot.isVisible || - (needsMetadata && - snapshot.changes.test( - frontend::RequestedLayerState::Changes::Metadata)); - }); - } - if (!mLayerLifecycleManagerEnabled) { - auto moveSnapshots = [&layers, &refreshArgs, cursorOnly](Layer* layer) { - if (const auto& layerFE = layer->getCompositionEngineLayerFE()) { + nsecs_t currentTime = systemTime(); + const bool needsMetadata = mCompositionEngine->getFeatureFlags().test( + compositionengine::Feature::kSnapshotLayerMetadata); + mLayerSnapshotBuilder.forEachSnapshot( + [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) FTL_FAKE_GUARD( + kMainThreadContext) { if (cursorOnly && - layer->getLayerSnapshot()->compositionType != - aidl::android::hardware::graphics::composer3::Composition::CURSOR) + snapshot->compositionType != + aidl::android::hardware::graphics::composer3::Composition::CURSOR) { return; - layer->updateSnapshot(refreshArgs.updatingGeometryThisFrame); - layerFE->mSnapshot = layer->stealLayerSnapshot(); - refreshArgs.layers.push_back(layerFE); - layers.emplace_back(layer, layerFE.get()); - } - }; + } - if (cursorOnly || !mVisibleRegionsDirty) { - // for hot path avoid traversals by walking though the previous composition list - for (sp<Layer> layer : mPreviouslyComposedLayers) { - moveSnapshots(layer.get()); - } - } else { - mPreviouslyComposedLayers.clear(); - mDrawingState.traverseInZOrder( - [&moveSnapshots](Layer* layer) { moveSnapshots(layer); }); - mPreviouslyComposedLayers.reserve(layers.size()); - for (auto [layer, _] : layers) { - mPreviouslyComposedLayers.push_back(sp<Layer>::fromExisting(layer)); - } - } - } + if (!snapshot->hasSomethingToDraw()) { + return; + } + auto it = mLegacyLayers.find(snapshot->sequence); + LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(), + "Couldnt find layer object for %s", + snapshot->getDebugString().c_str()); + auto& legacyLayer = it->second; + sp<LayerFE> layerFE = legacyLayer->getCompositionEngineLayerFE(snapshot->path); + snapshot->fps = getLayerFramerate(currentTime, snapshot->sequence); + layerFE->mSnapshot = std::move(snapshot); + refreshArgs.layers.push_back(layerFE); + layers.emplace_back(legacyLayer.get(), layerFE.get()); + }, + [needsMetadata](const frontend::LayerSnapshot& snapshot) { + return snapshot.isVisible || + (needsMetadata && + snapshot.changes.test(frontend::RequestedLayerState::Changes::Metadata)); + }); return layers; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 7263aaaaca..157b72244f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -560,7 +560,7 @@ private: sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const; status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, - const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, + Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, @@ -827,9 +827,6 @@ private: TransactionHandler::TransactionReadiness transactionReadyTimelineCheck( const TransactionHandler::TransactionFlushState& flushState) REQUIRES(kMainThreadContext); - TransactionHandler::TransactionReadiness transactionReadyBufferCheckLegacy( - const TransactionHandler::TransactionFlushState& flushState) - REQUIRES(kMainThreadContext); TransactionHandler::TransactionReadiness transactionReadyBufferCheck( const TransactionHandler::TransactionFlushState& flushState) REQUIRES(kMainThreadContext); @@ -935,12 +932,6 @@ private: std::vector<std::pair<Layer*, sp<LayerFE>>>& layers, std::vector<sp<LayerFE>>& layerFEs); - // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a - // matching ownerUid - void traverseLayersInLayerStack(ui::LayerStack, const int32_t uid, - std::unordered_set<uint32_t> excludeLayerIds, - const LayerVector::Visitor&); - void readPersistentProperties(); uint32_t getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const; @@ -1157,7 +1148,6 @@ private: void dumpAll(const DumpArgs& args, const std::string& compositionLayers, std::string& result) const EXCLUDES(mStateLock); void dumpHwcLayersMinidump(std::string& result) const REQUIRES(mStateLock, kMainThreadContext); - void dumpHwcLayersMinidumpLockedLegacy(std::string& result) const REQUIRES(mStateLock); void appendSfConfigString(std::string& result) const; void listLayers(std::string& result) const REQUIRES(kMainThreadContext); @@ -1506,8 +1496,6 @@ private: } bool mPowerHintSessionEnabled; - - bool mLayerLifecycleManagerEnabled = true; // Whether a display should be turned on when initialized bool mSkipPowerOnForQuiescent; diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index ebe11fb0f3..d355e720d1 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -26,6 +26,7 @@ #include <private/android_filesystem_config.h> #include <private/gui/ComposerServiceAIDL.h> #include <ui/DisplayMode.h> +#include <ui/DisplayState.h> #include <ui/DynamicDisplayInfo.h> #include <utils/String8.h> #include <functional> @@ -276,7 +277,7 @@ TEST_F(CredentialsTest, CreateDisplayTest) { TEST_F(CredentialsTest, CaptureLayersTest) { setupBackgroundSurface(); sp<GraphicBuffer> outBuffer; - std::function<status_t()> condition = [=]() { + std::function<status_t()> condition = [=, this]() { LayerCaptureArgs captureArgs; captureArgs.layerHandle = mBGSurfaceControl->getHandle(); captureArgs.sourceCrop = {0, 0, 1, 1}; @@ -396,6 +397,56 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { } } +TEST_F(CredentialsTest, DisplayTransactionPermissionTest) { + const auto display = getFirstDisplayToken(); + + ui::DisplayState displayState; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + const ui::Rotation initialOrientation = displayState.orientation; + + // Set display orientation from an untrusted process. This should fail silently. + { + UIDFaker f{AID_BIN}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90, + layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + + // Verify that the display orientation did not change. + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation, displayState.orientation); + + // Set display orientation from a trusted process. + { + UIDFaker f{AID_SYSTEM}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90, + layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + + // Verify that the display orientation did change. + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation + ui::ROTATION_90, displayState.orientation); + + // Reset orientation + { + UIDFaker f{AID_SYSTEM}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation, layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation, displayState.orientation); +} + } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index e3b2af1972..5e81b35e0c 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -528,7 +528,7 @@ public: auto setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states, - const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, + Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, std::vector<ListenerCallbacks>& listenerCallbacks, diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp index 8690dba041..7c678bd811 100644 --- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp @@ -1055,6 +1055,36 @@ TEST_F(VSyncPredictorTest, timelineNotAdjustedForEarlyPresent) { EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1400, 1000)); EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 1000)); } + +TEST_F(VSyncPredictorTest, adjustsOnlyMinFrameViolatingVrrTimeline) { + const auto refreshRate = Fps::fromPeriodNsecs(500); + auto minFrameRate = Fps::fromPeriodNsecs(1000); + hal::VrrConfig vrrConfig{.minFrameIntervalNs = + static_cast<int32_t>(minFrameRate.getPeriodNsecs())}; + ftl::NonNull<DisplayModePtr> mode = + ftl::as_non_null(createVrrDisplayMode(DisplayModeId(0), refreshRate, vrrConfig)); + VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), mode, kHistorySize, + kMinimumSamplesForPrediction, kOutlierTolerancePercent}; + vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false); + vrrTracker.addVsyncTimestamp(0); + + EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700)); + EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000)); + auto lastConfirmedSignalTime = TimePoint::fromNs(1500); + auto lastConfirmedExpectedPresentTime = TimePoint::fromNs(1000); + vrrTracker.onFrameBegin(TimePoint::fromNs(2000), + {lastConfirmedSignalTime, lastConfirmedExpectedPresentTime}); + EXPECT_EQ(3500, vrrTracker.nextAnticipatedVSyncTimeFrom(3000, 1500)); + + minFrameRate = Fps::fromPeriodNsecs(2000); + vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false); + lastConfirmedSignalTime = TimePoint::fromNs(2500); + lastConfirmedExpectedPresentTime = TimePoint::fromNs(2500); + vrrTracker.onFrameBegin(TimePoint::fromNs(3000), + {lastConfirmedSignalTime, lastConfirmedExpectedPresentTime}); + // Enough time without adjusting vsync to present with new rate on time, no need of adjustment + EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 3500)); +} } // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp index 503587f8ac..4735ae5897 100644 --- a/services/vibratorservice/Android.bp +++ b/services/vibratorservice/Android.bp @@ -45,7 +45,7 @@ cc_library_shared { "libhidlbase", "liblog", "libutils", - "android.hardware.vibrator-V2-ndk", + "android.hardware.vibrator-V3-ndk", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp index abe78f0ef0..c97f4014eb 100644 --- a/services/vibratorservice/VibratorHalWrapper.cpp +++ b/services/vibratorservice/VibratorHalWrapper.cpp @@ -32,6 +32,7 @@ using aidl::android::hardware::vibrator::CompositePrimitive; using aidl::android::hardware::vibrator::Effect; using aidl::android::hardware::vibrator::EffectStrength; using aidl::android::hardware::vibrator::PrimitivePwle; +using aidl::android::hardware::vibrator::VendorEffect; using std::chrono::milliseconds; @@ -96,6 +97,11 @@ Info HalWrapper::getInfo() { return mInfoCache.get(); } +HalResult<void> HalWrapper::performVendorEffect(const VendorEffect&, const std::function<void()>&) { + ALOGV("Skipped performVendorEffect because it's not available in Vibrator HAL"); + return HalResult<void>::unsupported(); +} + HalResult<milliseconds> HalWrapper::performComposedEffect(const std::vector<CompositeEffect>&, const std::function<void()>&) { ALOGV("Skipped performComposedEffect because it's not available in Vibrator HAL"); @@ -271,6 +277,13 @@ HalResult<milliseconds> AidlHalWrapper::performEffect( return ret; } +HalResult<void> AidlHalWrapper::performVendorEffect( + const VendorEffect& effect, const std::function<void()>& completionCallback) { + // This method should always support callbacks, so no need to double check. + auto cb = ndk::SharedRefBase::make<HalCallbackWrapper>(completionCallback); + return HalResultFactory::fromStatus(getHal()->performVendorEffect(effect, cb)); +} + HalResult<milliseconds> AidlHalWrapper::performComposedEffect( const std::vector<CompositeEffect>& primitives, const std::function<void()>& completionCallback) { @@ -351,7 +364,7 @@ HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsIntern } if (halResult.isFailed()) { // Fail entire request if one request has failed. - return HalResult<std::vector<milliseconds>>::failed(status.getMessage()); + return HalResult<std::vector<milliseconds>>::failed(halResult.errorMessage()); } durations[primitiveIdx] = milliseconds(duration); } diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp index 5bb8cebe49..915d6c7bc3 100644 --- a/services/vibratorservice/benchmarks/Android.bp +++ b/services/vibratorservice/benchmarks/Android.bp @@ -33,7 +33,7 @@ cc_benchmark { "liblog", "libutils", "libvibratorservice", - "android.hardware.vibrator-V2-ndk", + "android.hardware.vibrator-V3-ndk", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h index d4f7f1d387..20979bdcd8 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h +++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h @@ -349,6 +349,7 @@ class HalWrapper { public: using Effect = aidl::android::hardware::vibrator::Effect; using EffectStrength = aidl::android::hardware::vibrator::EffectStrength; + using VendorEffect = aidl::android::hardware::vibrator::VendorEffect; using CompositePrimitive = aidl::android::hardware::vibrator::CompositePrimitive; using CompositeEffect = aidl::android::hardware::vibrator::CompositeEffect; using Braking = aidl::android::hardware::vibrator::Braking; @@ -380,6 +381,9 @@ public: Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) = 0; + virtual HalResult<void> performVendorEffect(const VendorEffect& effect, + const std::function<void()>& completionCallback); + virtual HalResult<std::chrono::milliseconds> performComposedEffect( const std::vector<CompositeEffect>& primitives, const std::function<void()>& completionCallback); @@ -455,6 +459,10 @@ public: Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) override final; + HalResult<void> performVendorEffect( + const VendorEffect& effect, + const std::function<void()>& completionCallback) override final; + HalResult<std::chrono::milliseconds> performComposedEffect( const std::vector<CompositeEffect>& primitives, const std::function<void()>& completionCallback) override final; diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp index cd051232cc..92527eb5cf 100644 --- a/services/vibratorservice/test/Android.bp +++ b/services/vibratorservice/test/Android.bp @@ -49,7 +49,7 @@ cc_test { "liblog", "libvibratorservice", "libutils", - "android.hardware.vibrator-V2-ndk", + "android.hardware.vibrator-V3-ndk", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp index 91717f635d..7bcc59ac01 100644 --- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp +++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "VibratorHalWrapperAidlTest" #include <aidl/android/hardware/vibrator/IVibrator.h> +#include <android/persistable_bundle_aidl.h> #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -38,6 +39,8 @@ using aidl::android::hardware::vibrator::EffectStrength; using aidl::android::hardware::vibrator::IVibrator; using aidl::android::hardware::vibrator::IVibratorCallback; using aidl::android::hardware::vibrator::PrimitivePwle; +using aidl::android::hardware::vibrator::VendorEffect; +using aidl::android::os::PersistableBundle; using namespace android; using namespace std::chrono_literals; @@ -489,6 +492,42 @@ TEST_F(VibratorHalWrapperAidlTest, TestPerformEffectWithoutCallbackSupport) { ASSERT_EQ(1, *callbackCounter.get()); } +TEST_F(VibratorHalWrapperAidlTest, TestPerformVendorEffect) { + PersistableBundle vendorData; + vendorData.putInt("key", 1); + VendorEffect vendorEffect; + vendorEffect.vendorData = vendorData; + vendorEffect.strength = EffectStrength::MEDIUM; + vendorEffect.scale = 0.5f; + + { + InSequence seq; + EXPECT_CALL(*mMockHal.get(), performVendorEffect(_, _)) + .Times(Exactly(3)) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()), + Return(ndk::ScopedAStatus::ok()))); + } + + std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); + auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); + + auto result = mWrapper->performVendorEffect(vendorEffect, callback); + ASSERT_TRUE(result.isUnsupported()); + // Callback not triggered on failure + ASSERT_EQ(0, *callbackCounter.get()); + + result = mWrapper->performVendorEffect(vendorEffect, callback); + ASSERT_TRUE(result.isFailed()); + // Callback not triggered for unsupported + ASSERT_EQ(0, *callbackCounter.get()); + + result = mWrapper->performVendorEffect(vendorEffect, callback); + ASSERT_TRUE(result.isOk()); + ASSERT_EQ(1, *callbackCounter.get()); +} + TEST_F(VibratorHalWrapperAidlTest, TestPerformComposedEffect) { std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK, CompositePrimitive::SPIN, diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp index dd590935c4..9a7c69d0d1 100644 --- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp +++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "VibratorHalWrapperHidlV1_0Test" #include <aidl/android/hardware/vibrator/IVibrator.h> +#include <android/persistable_bundle_aidl.h> #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -39,6 +40,8 @@ using aidl::android::hardware::vibrator::Effect; using aidl::android::hardware::vibrator::EffectStrength; using aidl::android::hardware::vibrator::IVibrator; using aidl::android::hardware::vibrator::PrimitivePwle; +using aidl::android::hardware::vibrator::VendorEffect; +using aidl::android::os::PersistableBundle; using namespace android; using namespace std::chrono_literals; @@ -317,6 +320,22 @@ TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformEffectUnsupported) { ASSERT_EQ(0, *callbackCounter.get()); } +TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformVendorEffectUnsupported) { + PersistableBundle vendorData; // empty + VendorEffect vendorEffect; + vendorEffect.vendorData = vendorData; + vendorEffect.strength = EffectStrength::LIGHT; + vendorEffect.scale = 1.0f; + + std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); + auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); + + ASSERT_TRUE(mWrapper->performVendorEffect(vendorEffect, callback).isUnsupported()); + + // No callback is triggered. + ASSERT_EQ(0, *callbackCounter.get()); +} + TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformComposedEffectUnsupported) { std::vector<CompositeEffect> emptyEffects, singleEffect, multipleEffects; singleEffect.push_back( diff --git a/services/vibratorservice/test/test_mocks.h b/services/vibratorservice/test/test_mocks.h index 7882186b40..2f9451e1ae 100644 --- a/services/vibratorservice/test/test_mocks.h +++ b/services/vibratorservice/test/test_mocks.h @@ -41,6 +41,7 @@ using aidl::android::hardware::vibrator::EffectStrength; using aidl::android::hardware::vibrator::IVibrator; using aidl::android::hardware::vibrator::IVibratorCallback; using aidl::android::hardware::vibrator::PrimitivePwle; +using aidl::android::hardware::vibrator::VendorEffect; // ------------------------------------------------------------------------------------------------- @@ -56,6 +57,8 @@ public: (Effect e, EffectStrength s, const std::shared_ptr<IVibratorCallback>& cb, int32_t* ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, performVendorEffect, + (const VendorEffect& e, const std::shared_ptr<IVibratorCallback>& cb), (override)); MOCK_METHOD(ndk::ScopedAStatus, getSupportedEffects, (std::vector<Effect> * ret), (override)); MOCK_METHOD(ndk::ScopedAStatus, setAmplitude, (float amplitude), (override)); MOCK_METHOD(ndk::ScopedAStatus, setExternalControl, (bool enabled), (override)); |