diff options
119 files changed, 2287 insertions, 1346 deletions
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 6ee3070306..8f163b94d6 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -1955,7 +1955,6 @@ binder::Status InstalldNativeService::freeCache(const std::optional<std::string> return error("Failed to determine free space for " + data_path); } - int64_t cleared = 0; int64_t needed = targetFreeBytes - free; if (!defy_target) { LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested " @@ -2056,7 +2055,6 @@ binder::Status InstalldNativeService::freeCache(const std::optional<std::string> // 2. Populate tracker stats and insert into priority queue ATRACE_BEGIN("populate"); - int64_t cacheTotal = 0; auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) { return (left->getCacheRatio() < right->getCacheRatio()); }; @@ -2065,7 +2063,6 @@ binder::Status InstalldNativeService::freeCache(const std::optional<std::string> for (const auto& it : trackers) { it.second->loadStats(); queue.push(it.second); - cacheTotal += it.second->cacheUsed; } ATRACE_END(); @@ -2111,7 +2108,6 @@ binder::Status InstalldNativeService::freeCache(const std::optional<std::string> } active->cacheUsed -= item->size; needed -= item->size; - cleared += item->size; } if (!defy_target) { diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index 4d9b71016e..ffc082d5b2 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -523,7 +523,6 @@ int calculate_tree_size(const std::string& path, int64_t* size, */ bool is_valid_package_name(const std::string& packageName) { // This logic is borrowed from PackageParser.java - bool hasSep = false; bool front = true; auto it = packageName.begin(); @@ -539,7 +538,6 @@ bool is_valid_package_name(const std::string& packageName) { } } if (c == '.') { - hasSep = true; front = true; continue; } diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 3f7c7d6a7b..44235ccdef 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -464,7 +464,6 @@ void Replayer::setPosition(SurfaceComposerClient::Transaction& t, void Replayer::setSize(SurfaceComposerClient::Transaction& t, layer_id id, const SizeChange& sc) { ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h()); - t.setSize(mLayers[id], sc.w(), sc.h()); } void Replayer::setLayer(SurfaceComposerClient::Transaction& t, diff --git a/include/android/choreographer.h b/include/android/choreographer.h index 63aa7ff6c0..cd8e63dec2 100644 --- a/include/android/choreographer.h +++ b/include/android/choreographer.h @@ -16,6 +16,28 @@ /** * @addtogroup Choreographer + * + * Choreographer coordinates the timing of frame rendering. This is the C version of the + * android.view.Choreographer object in Java. + * + * As of API level 33, apps can follow proper frame pacing and even choose a future frame to render. + * The API is used as follows: + * 1. The app posts an {@link AChoreographer_vsyncCallback} to Choreographer to run on the next + * frame. + * 2. The callback is called when it is the time to start the frame with an {@link + * AChoreographerFrameCallbackData} payload: information about multiple possible frame + * timelines. + * 3. Apps can choose a frame timeline from the {@link + * AChoreographerFrameCallbackData} payload, depending on the frame deadline they can meet when + * rendering the frame and their desired presentation time, and subsequently + * {@link ASurfaceTransaction_setFrameTimeline notify SurfaceFlinger} + * of the choice. Alternatively, for apps that do not choose a frame timeline, their frame would be + * presented at the earliest possible timeline. + * - The preferred frame timeline is the default frame + * timeline that the platform scheduled for the app, based on device configuration. + * 4. SurfaceFlinger attempts to follow the chosen frame timeline, by not applying transactions or + * latching buffers before the desired presentation time. + * * @{ */ @@ -47,7 +69,8 @@ typedef int64_t AVsyncId; struct AChoreographerFrameCallbackData; /** - * Opaque type that provides access to an AChoreographerFrameCallbackData object. + * Opaque type that provides access to an AChoreographerFrameCallbackData object, which contains + * various methods to extract frame information. */ typedef struct AChoreographerFrameCallbackData AChoreographerFrameCallbackData; @@ -73,8 +96,9 @@ typedef void (*AChoreographer_frameCallback64)(int64_t frameTimeNanos, void* dat /** * Prototype of the function that is called when a new frame is being rendered. - * It's passed the frame data that should not outlive the callback, as well as the data pointer - * provided by the application that registered a callback. + * It is called with \c callbackData describing multiple frame timelines, as well as the \c data + * pointer provided by the application that registered a callback. The \c callbackData does not + * outlive the callback. */ typedef void (*AChoreographer_vsyncCallback)( const AChoreographerFrameCallbackData* callbackData, void* data); @@ -110,7 +134,7 @@ void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer, __DEPRECATED_IN(29); /** - * Power a callback to be run on the next frame. The data pointer provided will + * Post a callback to be run on the next frame. The data pointer provided will * be passed to the callback function when it's called. * * Available since API level 29. @@ -131,8 +155,10 @@ void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer, uint32_t delayMillis) __INTRODUCED_IN(29); /** - * Posts a callback to run on the next frame. The data pointer provided will + * Posts a callback to be run on the next frame. The data pointer provided will * be passed to the callback function when it's called. + * + * Available since API level 33. */ void AChoreographer_postVsyncCallback(AChoreographer* choreographer, AChoreographer_vsyncCallback callback, void* data) @@ -189,7 +215,10 @@ void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, __INTRODUCED_IN(30); /** - * The time in nanoseconds when the frame started being rendered. + * The time in nanoseconds at which the frame started being rendered. + * + * Note that this time should \b not be used to advance animation clocks. + * Instead, see AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(). */ int64_t AChoreographerFrameCallbackData_getFrameTimeNanos( const AChoreographerFrameCallbackData* data) __INTRODUCED_IN(33); @@ -201,25 +230,38 @@ size_t AChoreographerFrameCallbackData_getFrameTimelinesLength( const AChoreographerFrameCallbackData* data) __INTRODUCED_IN(33); /** - * Get index of the platform-preferred FrameTimeline. + * Gets the index of the platform-preferred frame timeline. + * The preferred frame timeline is the default + * by which the platform scheduled the app, based on the device configuration. */ size_t AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex( const AChoreographerFrameCallbackData* data) __INTRODUCED_IN(33); /** - * The vsync ID token used to map Choreographer data. + * Gets the token used by the platform to identify the frame timeline at the given \c index. + * + * \param index index of a frame timeline, in \f( [0, FrameTimelinesLength) \f). See + * AChoreographerFrameCallbackData_getFrameTimelinesLength() */ AVsyncId AChoreographerFrameCallbackData_getFrameTimelineVsyncId( const AChoreographerFrameCallbackData* data, size_t index) __INTRODUCED_IN(33); /** - * The time in nanoseconds which the frame at given index is expected to be presented. + * Gets the time in nanoseconds at which the frame described at the given \c index is expected to + * be presented. This time should be used to advance any animation clocks. + * + * \param index index of a frame timeline, in \f( [0, FrameTimelinesLength) \f). See + * AChoreographerFrameCallbackData_getFrameTimelinesLength() */ int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos( const AChoreographerFrameCallbackData* data, size_t index) __INTRODUCED_IN(33); /** - * The time in nanoseconds which the frame at given index needs to be ready by. + * Gets the time in nanoseconds at which the frame described at the given \c index needs to be + * ready by in order to be presented on time. + * + * \param index index of a frame timeline, in \f( [0, FrameTimelinesLength) \f). See + * AChoreographerFrameCallbackData_getFrameTimelinesLength() */ int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos( const AChoreographerFrameCallbackData* data, size_t index) __INTRODUCED_IN(33); diff --git a/include/android/surface_control.h b/include/android/surface_control.h index 9a36ecb537..6223ef7f82 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -597,20 +597,20 @@ void ASurfaceTransaction_setEnableBackPressure(ASurfaceTransaction* transaction, __INTRODUCED_IN(31); /** - * Sets the frame timeline to use in Surface Flinger. + * Sets the frame timeline to use in SurfaceFlinger. * - * A frame timeline should be chosen based on what frame deadline the application - * can meet when rendering the frame and the application's desired present time. - * By setting a frame timeline, Surface Flinger tries to present the frame at the corresponding - * expected present time. + * A frame timeline should be chosen based on the frame deadline the application + * can meet when rendering the frame and the application's desired presentation time. + * By setting a frame timeline, SurfaceFlinger tries to present the frame at the corresponding + * expected presentation time. * * To receive frame timelines, a callback must be posted to Choreographer using - * AChoreographer_postExtendedFrameCallback(). The \a vsnycId can then be extracted from the + * AChoreographer_postVsyncCallback(). The \c vsyncId can then be extracted from the * callback payload using AChoreographerFrameCallbackData_getFrameTimelineVsyncId(). * - * \param vsyncId The vsync ID received from AChoreographer, setting the frame's present target to - * the corresponding expected present time and deadline from the frame to be rendered. A stale or - * invalid value will be ignored. + * \param vsyncId The vsync ID received from AChoreographer, setting the frame's presentation target + * to the corresponding expected presentation time and deadline from the frame to be rendered. A + * stale or invalid value will be ignored. */ void ASurfaceTransaction_setFrameTimeline(ASurfaceTransaction* transaction, AVsyncId vsyncId) __INTRODUCED_IN(33); diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 3585392c2b..d51d6a722a 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -23,6 +23,8 @@ #include <unordered_map> #include <vector> +#include "android/hardware/input/InputDeviceCountryCode.h" + namespace android { /* @@ -210,8 +212,10 @@ public: }; void initialize(int32_t id, int32_t generation, int32_t controllerNumber, - const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal, - bool hasMic); + const InputDeviceIdentifier& identifier, const std::string& alias, + bool isExternal, bool hasMic, + hardware::input::InputDeviceCountryCode countryCode = + hardware::input::InputDeviceCountryCode::INVALID); inline int32_t getId() const { return mId; } inline int32_t getControllerNumber() const { return mControllerNumber; } @@ -223,6 +227,7 @@ public: } inline bool isExternal() const { return mIsExternal; } inline bool hasMic() const { return mHasMic; } + inline hardware::input::InputDeviceCountryCode getCountryCode() const { return mCountryCode; } inline uint32_t getSources() const { return mSources; } const MotionRange* getMotionRange(int32_t axis, uint32_t source) const; @@ -274,9 +279,11 @@ private: std::string mAlias; bool mIsExternal; bool mHasMic; + hardware::input::InputDeviceCountryCode mCountryCode; uint32_t mSources; int32_t mKeyboardType; std::shared_ptr<KeyCharacterMap> mKeyCharacterMap; + bool mHasVibrator; bool mHasBattery; bool mHasButtonUnderPad; diff --git a/include/input/KeyLayoutMap.h b/include/input/KeyLayoutMap.h index 1da78aa0c1..a6c696df26 100644 --- a/include/input/KeyLayoutMap.h +++ b/include/input/KeyLayoutMap.h @@ -78,7 +78,7 @@ public: std::optional<AxisInfo> mapAxis(int32_t scanCode) const; const std::string getLoadFileName() const; // Return pair of sensor type and sensor data index, for the input device abs code - base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t absCode); + base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t absCode) const; virtual ~KeyLayoutMap(); diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 6f505b44fb..364937d92c 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -71,15 +71,9 @@ filegroup { } cc_defaults { - name: "libbinder_defaults", + name: "libbinder_common_defaults", host_supported: true, - // TODO(b/31559095): get headers from bionic on host - include_dirs: [ - "bionic/libc/kernel/android/uapi/", - "bionic/libc/kernel/uapi/", - ], - srcs: [ "Binder.cpp", "BpBinder.cpp", @@ -87,19 +81,45 @@ cc_defaults { "FdTrigger.cpp", "IInterface.cpp", "IResultReceiver.cpp", - "OS.cpp", "Parcel.cpp", "ParcelFileDescriptor.cpp", "RpcSession.cpp", "RpcServer.cpp", "RpcState.cpp", - "RpcTransportRaw.cpp", "Stability.cpp", "Status.cpp", "TextOutput.cpp", "Utils.cpp", ], + shared_libs: [ + "libcutils", + "libutils", + ], + + static_libs: [ + "libbase", + ], + + header_libs: [ + "libbinder_headers", + ], +} + +cc_defaults { + name: "libbinder_android_defaults", + + // TODO(b/31559095): get headers from bionic on host + include_dirs: [ + "bionic/libc/kernel/android/uapi/", + "bionic/libc/kernel/uapi/", + ], + + srcs: [ + "OS.cpp", + "RpcTransportRaw.cpp", + ], + target: { host: { srcs: [ @@ -133,16 +153,9 @@ cc_defaults { shared_libs: [ "liblog", - "libcutils", - "libutils", - ], - - static_libs: [ - "libbase", ], header_libs: [ - "libbinder_headers", "libandroid_runtime_vm_headers", ], @@ -177,6 +190,48 @@ cc_defaults { ], } +cc_library_shared { + name: "libbinder_on_trusty_mock", + defaults: ["libbinder_common_defaults"], + + srcs: [ + // Trusty-specific files + "trusty/logging.cpp", + "trusty/OS.cpp", + "trusty/RpcServerTrusty.cpp", + "trusty/RpcTransportTipcTrusty.cpp", + "trusty/TrustyStatus.cpp", + "trusty/socket.cpp", + ], + + cflags: [ + "-DBINDER_RPC_SINGLE_THREADED", + // Trusty libbinder uses vendor stability for its binders + "-D__ANDROID_VNDK__", + "-U__ANDROID__", + "-D__TRUSTY__", + "-DTRUSTY_USERSPACE", + // Flags from the Trusty build system + "-Werror", + "-Wsign-compare", + "-Wno-unused-function", + "-Wno-unused-label", + "-fno-common", + "-fno-omit-frame-pointer", + "-fno-threadsafe-statics", + ], + rtti: false, + + local_include_dirs: [ + "trusty/include", + "trusty/include_mock", + ], + + visibility: [ + ":__subpackages__", + ], +} + cc_defaults { name: "libbinder_kernel_defaults", srcs: [ @@ -208,7 +263,8 @@ cc_defaults { cc_library { name: "libbinder", defaults: [ - "libbinder_defaults", + "libbinder_common_defaults", + "libbinder_android_defaults", "libbinder_kernel_defaults", ], @@ -264,7 +320,10 @@ cc_library { cc_library_static { name: "libbinder_rpc_no_kernel", - defaults: ["libbinder_defaults"], + defaults: [ + "libbinder_common_defaults", + "libbinder_android_defaults", + ], visibility: [ ":__subpackages__", ], @@ -273,7 +332,8 @@ cc_library_static { cc_library_static { name: "libbinder_rpc_single_threaded", defaults: [ - "libbinder_defaults", + "libbinder_common_defaults", + "libbinder_android_defaults", "libbinder_kernel_defaults", ], cflags: [ @@ -286,7 +346,10 @@ cc_library_static { cc_library_static { name: "libbinder_rpc_single_threaded_no_kernel", - defaults: ["libbinder_defaults"], + defaults: [ + "libbinder_common_defaults", + "libbinder_android_defaults", + ], cflags: [ "-DBINDER_RPC_SINGLE_THREADED", ], @@ -440,6 +503,7 @@ cc_library { // This library is intentionally limited to these targets, and it will be removed later. // Do not expand the visibility. visibility: [ + ":__subpackages__", "//packages/modules/Virtualization:__subpackages__", ], } diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index 1dc62334cb..402995717c 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -283,11 +283,9 @@ status_t BBinder::pingBinder() const String16& BBinder::getInterfaceDescriptor() const { - // This is a local static rather than a global static, - // to avoid static initializer ordering issues. - static String16 sEmptyDescriptor; - ALOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this); - return sEmptyDescriptor; + static StaticString16 sBBinder(u"BBinder"); + ALOGW("Reached BBinder::getInterfaceDescriptor (this=%p). Override?", this); + return sBBinder; } // NOLINTNEXTLINE(google-default-arguments) diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp index d123fd1f2b..8ee6cb0615 100644 --- a/libs/binder/FdTrigger.cpp +++ b/libs/binder/FdTrigger.cpp @@ -22,6 +22,7 @@ #include <poll.h> #include <android-base/macros.h> +#include <android-base/scopeguard.h> #include "RpcState.h" namespace android { @@ -53,25 +54,34 @@ bool FdTrigger::isTriggered() { #endif } -status_t FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) { +status_t FdTrigger::triggerablePoll(const android::RpcTransportFd& transportFd, int16_t event) { #ifdef BINDER_RPC_SINGLE_THREADED if (mTriggered) { return DEAD_OBJECT; } #endif - LOG_ALWAYS_FATAL_IF(event == 0, "triggerablePoll %d with event 0 is not allowed", fd.get()); + LOG_ALWAYS_FATAL_IF(event == 0, "triggerablePoll %d with event 0 is not allowed", + transportFd.fd.get()); pollfd pfd[]{ - {.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0}, + {.fd = transportFd.fd.get(), .events = static_cast<int16_t>(event), .revents = 0}, #ifndef BINDER_RPC_SINGLE_THREADED {.fd = mRead.get(), .events = 0, .revents = 0}, #endif }; + + LOG_ALWAYS_FATAL_IF(transportFd.isInPollingState() == true, + "Only one thread should be polling on Fd!"); + + transportFd.setPollingState(true); + auto pollingStateGuard = + android::base::make_scope_guard([&]() { transportFd.setPollingState(false); }); + int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1)); if (ret < 0) { return -errno; } - LOG_ALWAYS_FATAL_IF(ret == 0, "poll(%d) returns 0 with infinite timeout", fd.get()); + LOG_ALWAYS_FATAL_IF(ret == 0, "poll(%d) returns 0 with infinite timeout", transportFd.fd.get()); // At least one FD has events. Check them. diff --git a/libs/binder/FdTrigger.h b/libs/binder/FdTrigger.h index a25dc117f3..5fbf2908ad 100644 --- a/libs/binder/FdTrigger.h +++ b/libs/binder/FdTrigger.h @@ -21,6 +21,8 @@ #include <android-base/unique_fd.h> #include <utils/Errors.h> +#include <binder/RpcTransport.h> + namespace android { /** This is not a pipe. */ @@ -53,7 +55,8 @@ public: * true - time to read! * false - trigger happened */ - [[nodiscard]] status_t triggerablePoll(base::borrowed_fd fd, int16_t event); + [[nodiscard]] status_t triggerablePoll(const android::RpcTransportFd& transportFd, + int16_t event); private: #ifdef BINDER_RPC_SINGLE_THREADED diff --git a/libs/binder/OS.cpp b/libs/binder/OS.cpp index cc4a03ba67..24ce2bb465 100644 --- a/libs/binder/OS.cpp +++ b/libs/binder/OS.cpp @@ -17,6 +17,7 @@ #include "OS.h" #include <android-base/file.h> +#include <binder/RpcTransportRaw.h> #include <string.h> using android::base::ErrnoError; @@ -58,4 +59,8 @@ status_t dupFileDescriptor(int oldFd, int* newFd) { return OK; } +std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory() { + return RpcTransportCtxFactoryRaw::make(); +} + } // namespace android diff --git a/libs/binder/OS.h b/libs/binder/OS.h index d6e1c78ae9..5ab8bab0e7 100644 --- a/libs/binder/OS.h +++ b/libs/binder/OS.h @@ -20,6 +20,7 @@ #include <android-base/result.h> #include <android-base/unique_fd.h> +#include <binder/RpcTransport.h> #include <utils/Errors.h> namespace android { @@ -30,4 +31,6 @@ status_t getRandomBytes(uint8_t* data, size_t size); status_t dupFileDescriptor(int oldFd, int* newFd); +std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory(); + } // namespace android diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index 49be4dd9eb..0ee5f05030 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -55,7 +55,7 @@ RpcServer::~RpcServer() { sp<RpcServer> RpcServer::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) { // Default is without TLS. if (rpcTransportCtxFactory == nullptr) - rpcTransportCtxFactory = RpcTransportCtxFactoryRaw::make(); + rpcTransportCtxFactory = makeDefaultRpcTransportCtxFactory(); auto ctx = rpcTransportCtxFactory->newServerCtx(); if (ctx == nullptr) return nullptr; return sp<RpcServer>::make(std::move(ctx)); @@ -86,7 +86,7 @@ status_t RpcServer::setupInetServer(const char* address, unsigned int port, LOG_ALWAYS_FATAL_IF(socketAddress.addr()->sa_family != AF_INET, "expecting inet"); sockaddr_in addr{}; socklen_t len = sizeof(addr); - if (0 != getsockname(mServer.get(), reinterpret_cast<sockaddr*>(&addr), &len)) { + if (0 != getsockname(mServer.fd.get(), reinterpret_cast<sockaddr*>(&addr), &len)) { int savedErrno = errno; ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(), strerror(savedErrno)); @@ -181,7 +181,7 @@ void RpcServer::join() { { RpcMutexLockGuard _l(mLock); - LOG_ALWAYS_FATAL_IF(!mServer.ok(), "RpcServer must be setup to join."); + LOG_ALWAYS_FATAL_IF(!mServer.fd.ok(), "RpcServer must be setup to join."); LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined"); mJoinThreadRunning = true; mShutdownTrigger = FdTrigger::make(); @@ -194,24 +194,24 @@ void RpcServer::join() { static_assert(addr.size() >= sizeof(sockaddr_storage), "kRpcAddressSize is too small"); socklen_t addrLen = addr.size(); - unique_fd clientFd( - TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(addr.data()), - &addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK))); + RpcTransportFd clientSocket(unique_fd(TEMP_FAILURE_RETRY( + accept4(mServer.fd.get(), reinterpret_cast<sockaddr*>(addr.data()), &addrLen, + SOCK_CLOEXEC | SOCK_NONBLOCK)))); LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(sockaddr_storage)), "Truncated address"); - if (clientFd < 0) { + if (clientSocket.fd < 0) { ALOGE("Could not accept4 socket: %s", strerror(errno)); continue; } - LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); + LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get()); { RpcMutexLockGuard _l(mLock); RpcMaybeThread thread = RpcMaybeThread(&RpcServer::establishConnection, - sp<RpcServer>::fromExisting(this), std::move(clientFd), addr, + sp<RpcServer>::fromExisting(this), std::move(clientSocket), addr, addrLen, RpcSession::join); auto& threadRef = mConnectingThreads[thread.get_id()]; @@ -296,7 +296,7 @@ size_t RpcServer::numUninitializedSessions() { } void RpcServer::establishConnection( - sp<RpcServer>&& server, base::unique_fd clientFd, std::array<uint8_t, kRpcAddressSize> addr, + sp<RpcServer>&& server, RpcTransportFd clientFd, std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen, std::function<void(sp<RpcSession>&&, RpcSession::PreJoinSetupResult&&)>&& joinFn) { // mShutdownTrigger can only be cleared once connection threads have joined. @@ -306,7 +306,7 @@ void RpcServer::establishConnection( status_t status = OK; - int clientFdForLog = clientFd.get(); + int clientFdForLog = clientFd.fd.get(); auto client = server->mCtx->newTransport(std::move(clientFd), server->mShutdownTrigger.get()); if (client == nullptr) { ALOGE("Dropping accept4()-ed socket because sslAccept fails"); @@ -488,15 +488,15 @@ status_t RpcServer::setupSocketServer(const RpcSocketAddress& addr) { LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str()); LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server."); - unique_fd serverFd(TEMP_FAILURE_RETRY( - socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); - if (serverFd == -1) { + RpcTransportFd transportFd(unique_fd(TEMP_FAILURE_RETRY( + socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)))); + if (!transportFd.fd.ok()) { int savedErrno = errno; ALOGE("Could not create socket: %s", strerror(savedErrno)); return -savedErrno; } - if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) { + if (0 != TEMP_FAILURE_RETRY(bind(transportFd.fd.get(), addr.addr(), addr.addrSize()))) { int savedErrno = errno; ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return -savedErrno; @@ -506,7 +506,7 @@ status_t RpcServer::setupSocketServer(const RpcSocketAddress& addr) { // the backlog is increased to a large number. // TODO(b/189955605): Once we create threads dynamically & lazily, the backlog can be reduced // to 1. - if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 50 /*backlog*/))) { + if (0 != TEMP_FAILURE_RETRY(listen(transportFd.fd.get(), 50 /*backlog*/))) { int savedErrno = errno; ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return -savedErrno; @@ -514,7 +514,7 @@ status_t RpcServer::setupSocketServer(const RpcSocketAddress& addr) { LOG_RPC_DETAIL("Successfully setup socket server %s", addr.toString().c_str()); - if (status_t status = setupExternalServer(std::move(serverFd)); status != OK) { + if (status_t status = setupExternalServer(std::move(transportFd.fd)); status != OK) { ALOGE("Another thread has set up server while calling setupSocketServer. Race?"); return status; } @@ -542,17 +542,17 @@ void RpcServer::onSessionIncomingThreadEnded() { bool RpcServer::hasServer() { RpcMutexLockGuard _l(mLock); - return mServer.ok(); + return mServer.fd.ok(); } unique_fd RpcServer::releaseServer() { RpcMutexLockGuard _l(mLock); - return std::move(mServer); + return std::move(mServer.fd); } status_t RpcServer::setupExternalServer(base::unique_fd serverFd) { RpcMutexLockGuard _l(mLock); - if (mServer.ok()) { + if (mServer.fd.ok()) { ALOGE("Each RpcServer can only have one server."); return INVALID_OPERATION; } diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp index 8ddfa93c00..bef2ed63c7 100644 --- a/libs/binder/RpcSession.cpp +++ b/libs/binder/RpcSession.cpp @@ -68,7 +68,7 @@ RpcSession::~RpcSession() { sp<RpcSession> RpcSession::make() { // Default is without TLS. - return make(RpcTransportCtxFactoryRaw::make()); + return make(makeDefaultRpcTransportCtxFactory()); } sp<RpcSession> RpcSession::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) { @@ -162,7 +162,8 @@ status_t RpcSession::setupInetClient(const char* addr, unsigned int port) { return NAME_NOT_FOUND; } -status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) { +status_t RpcSession::setupPreconnectedClient(base::unique_fd fd, + std::function<unique_fd()>&& request) { return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) -> status_t { if (!fd.ok()) { fd = request(); @@ -172,7 +173,9 @@ status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_ ALOGE("setupPreconnectedClient: %s", res.error().message().c_str()); return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code(); } - status_t status = initAndAddConnection(std::move(fd), sessionId, incoming); + + RpcTransportFd transportFd(std::move(fd)); + status_t status = initAndAddConnection(std::move(transportFd), sessionId, incoming); fd = unique_fd(); // Explicitly reset after move to avoid analyzer warning. return status; }); @@ -190,7 +193,8 @@ status_t RpcSession::addNullDebuggingClient() { return -savedErrno; } - auto server = mCtx->newTransport(std::move(serverFd), mShutdownTrigger.get()); + RpcTransportFd transportFd(std::move(serverFd)); + auto server = mCtx->newTransport(std::move(transportFd), mShutdownTrigger.get()); if (server == nullptr) { ALOGE("Unable to set up RpcTransport"); return UNKNOWN_ERROR; @@ -572,12 +576,14 @@ status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr, return -savedErrno; } - if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) { + RpcTransportFd transportFd(std::move(serverFd)); + + if (0 != TEMP_FAILURE_RETRY(connect(transportFd.fd.get(), addr.addr(), addr.addrSize()))) { int connErrno = errno; if (connErrno == EAGAIN || connErrno == EINPROGRESS) { // For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or // EINPROGRESS (for others). Call poll() and getsockopt() to get the error. - status_t pollStatus = mShutdownTrigger->triggerablePoll(serverFd, POLLOUT); + status_t pollStatus = mShutdownTrigger->triggerablePoll(transportFd, POLLOUT); if (pollStatus != OK) { ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s", statusToString(pollStatus).c_str()); @@ -585,8 +591,8 @@ status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr, } // Set connErrno to the errno that connect() would have set if the fd were blocking. socklen_t connErrnoLen = sizeof(connErrno); - int ret = - getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &connErrno, &connErrnoLen); + int ret = getsockopt(transportFd.fd.get(), SOL_SOCKET, SO_ERROR, &connErrno, + &connErrnoLen); if (ret == -1) { int savedErrno = errno; ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s. " @@ -608,16 +614,17 @@ status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr, return -connErrno; } } - LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get()); + LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), + transportFd.fd.get()); - return initAndAddConnection(std::move(serverFd), sessionId, incoming); + return initAndAddConnection(std::move(transportFd), sessionId, incoming); } ALOGE("Ran out of retries to connect to %s", addr.toString().c_str()); return UNKNOWN_ERROR; } -status_t RpcSession::initAndAddConnection(unique_fd fd, const std::vector<uint8_t>& sessionId, +status_t RpcSession::initAndAddConnection(RpcTransportFd fd, const std::vector<uint8_t>& sessionId, bool incoming) { LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr); auto server = mCtx->newTransport(std::move(fd), mShutdownTrigger.get()); diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp index 51326f6346..65e8fac341 100644 --- a/libs/binder/RpcTransportRaw.cpp +++ b/libs/binder/RpcTransportRaw.cpp @@ -36,11 +36,11 @@ constexpr size_t kMaxFdsPerMsg = 253; // RpcTransport with TLS disabled. class RpcTransportRaw : public RpcTransport { public: - explicit RpcTransportRaw(android::base::unique_fd socket) : mSocket(std::move(socket)) {} + explicit RpcTransportRaw(android::RpcTransportFd socket) : mSocket(std::move(socket)) {} status_t pollRead(void) override { uint8_t buf; ssize_t ret = TEMP_FAILURE_RETRY( - ::recv(mSocket.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT)); + ::recv(mSocket.fd.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT)); if (ret < 0) { int savedErrno = errno; if (savedErrno == EAGAIN || savedErrno == EWOULDBLOCK) { @@ -100,7 +100,7 @@ public: msg.msg_controllen = CMSG_SPACE(fdsByteSize); ssize_t processedSize = TEMP_FAILURE_RETRY( - sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC)); + sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC)); if (processedSize > 0) { sentFds = true; } @@ -113,10 +113,10 @@ public: // non-negative int and can be cast to either. .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs), }; - return TEMP_FAILURE_RETRY(sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL)); + return TEMP_FAILURE_RETRY(sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL)); }; - return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, send, "sendmsg", - POLLOUT, altPoll); + return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, send, "sendmsg", POLLOUT, + altPoll); } status_t interruptableReadFully( @@ -135,7 +135,7 @@ public: .msg_controllen = sizeof(msgControlBuf), }; ssize_t processSize = - TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL)); + TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL)); if (processSize < 0) { return -1; } @@ -171,21 +171,23 @@ public: // non-negative int and can be cast to either. .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs), }; - return TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL)); + return TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL)); }; - return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, recv, "recvmsg", - POLLIN, altPoll); + return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN, + altPoll); } + virtual bool isWaiting() { return mSocket.isInPollingState(); } + private: - base::unique_fd mSocket; + android::RpcTransportFd mSocket; }; // RpcTransportCtx with TLS disabled. class RpcTransportCtxRaw : public RpcTransportCtx { public: - std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, FdTrigger*) const { - return std::make_unique<RpcTransportRaw>(std::move(fd)); + std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd socket, FdTrigger*) const { + return std::make_unique<RpcTransportRaw>(std::move(socket)); } std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; } }; diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp index c82201b28b..453279c0a5 100644 --- a/libs/binder/RpcTransportTipcAndroid.cpp +++ b/libs/binder/RpcTransportTipcAndroid.cpp @@ -36,8 +36,7 @@ namespace { // RpcTransport for writing Trusty IPC clients in Android. class RpcTransportTipcAndroid : public RpcTransport { public: - explicit RpcTransportTipcAndroid(android::base::unique_fd socket) - : mSocket(std::move(socket)) {} + explicit RpcTransportTipcAndroid(android::RpcTransportFd socket) : mSocket(std::move(socket)) {} status_t pollRead() override { if (mReadBufferPos < mReadBufferSize) { @@ -46,7 +45,7 @@ public: } // Trusty IPC device is not a socket, so MSG_PEEK is not available - pollfd pfd{.fd = mSocket.get(), .events = static_cast<int16_t>(POLLIN), .revents = 0}; + pollfd pfd{.fd = mSocket.fd.get(), .events = static_cast<int16_t>(POLLIN), .revents = 0}; ssize_t ret = TEMP_FAILURE_RETRY(::poll(&pfd, 1, 0)); if (ret < 0) { int savedErrno = errno; @@ -84,9 +83,9 @@ public: // to send any. LOG_ALWAYS_FATAL_IF(ancillaryFds != nullptr && !ancillaryFds->empty(), "File descriptors are not supported on Trusty yet"); - return TEMP_FAILURE_RETRY(tipc_send(mSocket.get(), iovs, niovs, nullptr, 0)); + return TEMP_FAILURE_RETRY(tipc_send(mSocket.fd.get(), iovs, niovs, nullptr, 0)); }; - return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, writeFn, "tipc_send", + return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, writeFn, "tipc_send", POLLOUT, altPoll); } @@ -120,10 +119,12 @@ public: return processSize; }; - return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, readFn, "read", - POLLIN, altPoll); + return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, readFn, "read", POLLIN, + altPoll); } + bool isWaiting() override { return mSocket.isInPollingState(); } + private: status_t fillReadBuffer() { if (mReadBufferPos < mReadBufferSize) { @@ -146,8 +147,8 @@ private: mReadBufferSize = 0; while (true) { - ssize_t processSize = - TEMP_FAILURE_RETRY(read(mSocket.get(), mReadBuffer.get(), mReadBufferCapacity)); + ssize_t processSize = TEMP_FAILURE_RETRY( + read(mSocket.fd.get(), mReadBuffer.get(), mReadBufferCapacity)); if (processSize == 0) { return DEAD_OBJECT; } else if (processSize < 0) { @@ -173,7 +174,7 @@ private: } } - base::unique_fd mSocket; + RpcTransportFd mSocket; // For now, we copy all the input data into a temporary buffer because // we might get multiple interruptableReadFully calls per message, but @@ -192,7 +193,7 @@ private: // RpcTransportCtx for Trusty. class RpcTransportCtxTipcAndroid : public RpcTransportCtx { public: - std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, + std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd fd, FdTrigger*) const override { return std::make_unique<RpcTransportTipcAndroid>(std::move(fd)); } diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp index 09b5c17152..3e98ecca9b 100644 --- a/libs/binder/RpcTransportTls.cpp +++ b/libs/binder/RpcTransportTls.cpp @@ -182,8 +182,8 @@ public: // If |sslError| is WANT_READ / WANT_WRITE, poll for POLLIN / POLLOUT respectively. Otherwise // return error. Also return error if |fdTrigger| is triggered before or during poll(). status_t pollForSslError( - android::base::borrowed_fd fd, int sslError, FdTrigger* fdTrigger, const char* fnString, - int additionalEvent, + const android::RpcTransportFd& fd, int sslError, FdTrigger* fdTrigger, + const char* fnString, int additionalEvent, const std::optional<android::base::function_ref<status_t()>>& altPoll) { switch (sslError) { case SSL_ERROR_WANT_READ: @@ -198,7 +198,7 @@ public: private: bool mHandled = false; - status_t handlePoll(int event, android::base::borrowed_fd fd, FdTrigger* fdTrigger, + status_t handlePoll(int event, const android::RpcTransportFd& fd, FdTrigger* fdTrigger, const char* fnString, const std::optional<android::base::function_ref<status_t()>>& altPoll) { status_t ret; @@ -277,7 +277,7 @@ private: class RpcTransportTls : public RpcTransport { public: - RpcTransportTls(android::base::unique_fd socket, Ssl ssl) + RpcTransportTls(RpcTransportFd socket, Ssl ssl) : mSocket(std::move(socket)), mSsl(std::move(ssl)) {} status_t pollRead(void) override; status_t interruptableWriteFully( @@ -290,8 +290,10 @@ public: const std::optional<android::base::function_ref<status_t()>>& altPoll, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override; + bool isWaiting() { return mSocket.isInPollingState(); }; + private: - android::base::unique_fd mSocket; + android::RpcTransportFd mSocket; Ssl mSsl; }; @@ -350,7 +352,7 @@ status_t RpcTransportTls::interruptableWriteFully( int sslError = mSsl.getError(writeSize); // TODO(b/195788248): BIO should contain the FdTrigger, and send(2) / recv(2) should be // triggerablePoll()-ed. Then additionalEvent is no longer necessary. - status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger, + status_t pollStatus = errorQueue.pollForSslError(mSocket, sslError, fdTrigger, "SSL_write", POLLIN, altPoll); if (pollStatus != OK) return pollStatus; // Do not advance buffer. Try SSL_write() again. @@ -398,7 +400,7 @@ status_t RpcTransportTls::interruptableReadFully( return DEAD_OBJECT; } int sslError = mSsl.getError(readSize); - status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger, + status_t pollStatus = errorQueue.pollForSslError(mSocket, sslError, fdTrigger, "SSL_read", 0, altPoll); if (pollStatus != OK) return pollStatus; // Do not advance buffer. Try SSL_read() again. @@ -409,8 +411,8 @@ status_t RpcTransportTls::interruptableReadFully( } // For |ssl|, set internal FD to |fd|, and do handshake. Handshake is triggerable by |fdTrigger|. -bool setFdAndDoHandshake(Ssl* ssl, android::base::borrowed_fd fd, FdTrigger* fdTrigger) { - bssl::UniquePtr<BIO> bio = newSocketBio(fd); +bool setFdAndDoHandshake(Ssl* ssl, const android::RpcTransportFd& socket, FdTrigger* fdTrigger) { + bssl::UniquePtr<BIO> bio = newSocketBio(socket.fd); TEST_AND_RETURN(false, bio != nullptr); auto [_, errorQueue] = ssl->call(SSL_set_bio, bio.get(), bio.get()); (void)bio.release(); // SSL_set_bio takes ownership. @@ -430,7 +432,7 @@ bool setFdAndDoHandshake(Ssl* ssl, android::base::borrowed_fd fd, FdTrigger* fdT return false; } int sslError = ssl->getError(ret); - status_t pollStatus = errorQueue.pollForSslError(fd, sslError, fdTrigger, + status_t pollStatus = errorQueue.pollForSslError(socket, sslError, fdTrigger, "SSL_do_handshake", 0, std::nullopt); if (pollStatus != OK) return false; } @@ -442,7 +444,7 @@ public: typename = std::enable_if_t<std::is_base_of_v<RpcTransportCtxTls, Impl>>> static std::unique_ptr<RpcTransportCtxTls> create( std::shared_ptr<RpcCertificateVerifier> verifier, RpcAuth* auth); - std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, + std::unique_ptr<RpcTransport> newTransport(RpcTransportFd fd, FdTrigger* fdTrigger) const override; std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override; @@ -513,15 +515,15 @@ std::unique_ptr<RpcTransportCtxTls> RpcTransportCtxTls::create( return ret; } -std::unique_ptr<RpcTransport> RpcTransportCtxTls::newTransport(android::base::unique_fd fd, +std::unique_ptr<RpcTransport> RpcTransportCtxTls::newTransport(android::RpcTransportFd socket, FdTrigger* fdTrigger) const { bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get())); TEST_AND_RETURN(nullptr, ssl != nullptr); Ssl wrapped(std::move(ssl)); preHandshake(&wrapped); - TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, fd, fdTrigger)); - return std::make_unique<RpcTransportTls>(std::move(fd), std::move(wrapped)); + TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, socket, fdTrigger)); + return std::make_unique<RpcTransportTls>(std::move(socket), std::move(wrapped)); } class RpcTransportCtxTlsServer : public RpcTransportCtxTls { diff --git a/libs/binder/RpcTransportUtils.h b/libs/binder/RpcTransportUtils.h index 00cb2af8c3..32f0db805d 100644 --- a/libs/binder/RpcTransportUtils.h +++ b/libs/binder/RpcTransportUtils.h @@ -25,8 +25,8 @@ namespace android { template <typename SendOrReceive> status_t interruptableReadOrWrite( - int socketFd, FdTrigger* fdTrigger, iovec* iovs, int niovs, SendOrReceive sendOrReceiveFun, - const char* funName, int16_t event, + const android::RpcTransportFd& socket, FdTrigger* fdTrigger, iovec* iovs, int niovs, + SendOrReceive sendOrReceiveFun, const char* funName, int16_t event, const std::optional<android::base::function_ref<status_t()>>& altPoll) { MAYBE_WAIT_IN_FLAKE_MODE; @@ -99,7 +99,7 @@ status_t interruptableReadOrWrite( return DEAD_OBJECT; } } else { - if (status_t status = fdTrigger->triggerablePoll(socketFd, event); status != OK) + if (status_t status = fdTrigger->triggerablePoll(socket, event); status != OK) return status; if (!havePolled) havePolled = true; } diff --git a/libs/binder/binder_module.h b/libs/binder/binder_module.h index 7574c29e8b..793795e1d4 100644 --- a/libs/binder/binder_module.h +++ b/libs/binder/binder_module.h @@ -100,23 +100,4 @@ struct binder_frozen_status_info { #define BINDER_ENABLE_ONEWAY_SPAM_DETECTION _IOW('b', 16, __u32) #endif // BINDER_ENABLE_ONEWAY_SPAM_DETECTION -#ifndef BINDER_GET_EXTENDED_ERROR -/* struct binder_extened_error - extended error information - * @id: identifier for the failed operation - * @command: command as defined by binder_driver_return_protocol - * @param: parameter holding a negative errno value - * - * Used with BINDER_GET_EXTENDED_ERROR. This extends the error information - * returned by the driver upon a failed operation. Userspace can pull this - * data to properly handle specific error scenarios. - */ -struct binder_extended_error { - __u32 id; - __u32 command; - __s32 param; -}; - -#define BINDER_GET_EXTENDED_ERROR _IOWR('b', 17, struct binder_extended_error) -#endif // BINDER_GET_EXTENDED_ERROR - #endif // _BINDER_MODULE_H_ diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h index 52bda0e8ed..ca02ab2a78 100644 --- a/libs/binder/include/binder/RpcServer.h +++ b/libs/binder/include/binder/RpcServer.h @@ -199,7 +199,7 @@ private: static constexpr size_t kRpcAddressSize = 128; static void establishConnection( - sp<RpcServer>&& server, base::unique_fd clientFd, + sp<RpcServer>&& server, RpcTransportFd clientFd, std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen, std::function<void(sp<RpcSession>&&, RpcSession::PreJoinSetupResult&&)>&& joinFn); [[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address); @@ -210,7 +210,7 @@ private: // A mode is supported if the N'th bit is on, where N is the mode enum's value. std::bitset<8> mSupportedFileDescriptorTransportModes = std::bitset<8>().set( static_cast<size_t>(RpcSession::FileDescriptorTransportMode::NONE)); - base::unique_fd mServer; // socket we are accepting sessions on + RpcTransportFd mServer; // socket we are accepting sessions on RpcMutex mLock; // for below std::unique_ptr<RpcMaybeThread> mJoinThread; diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h index 428e27209f..9630e2fafa 100644 --- a/libs/binder/include/binder/RpcSession.h +++ b/libs/binder/include/binder/RpcSession.h @@ -269,7 +269,7 @@ private: [[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address, const std::vector<uint8_t>& sessionId, bool incoming); - [[nodiscard]] status_t initAndAddConnection(base::unique_fd fd, + [[nodiscard]] status_t initAndAddConnection(RpcTransportFd fd, const std::vector<uint8_t>& sessionId, bool incoming); [[nodiscard]] status_t addIncomingConnection(std::unique_ptr<RpcTransport> rpcTransport); diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h index 5197ef9f4b..fd52a3a1a9 100644 --- a/libs/binder/include/binder/RpcTransport.h +++ b/libs/binder/include/binder/RpcTransport.h @@ -30,12 +30,14 @@ #include <utils/Errors.h> #include <binder/RpcCertificateFormat.h> +#include <binder/RpcThreads.h> #include <sys/uio.h> namespace android { class FdTrigger; +struct RpcTransportFd; // Represents a socket connection. // No thread-safety is guaranteed for these APIs. @@ -81,6 +83,15 @@ public: const std::optional<android::base::function_ref<status_t()>> &altPoll, std::vector<std::variant<base::unique_fd, base::borrowed_fd>> *ancillaryFds) = 0; + /** + * Check whether any threads are blocked while polling the transport + * for read operations + * Return: + * True - Specifies that there is active polling on transport. + * False - No active polling on transport + */ + [[nodiscard]] virtual bool isWaiting() = 0; + protected: RpcTransport() = default; }; @@ -96,7 +107,7 @@ public: // Implementation details: for TLS, this function may incur I/O. |fdTrigger| may be used // to interrupt I/O. This function blocks until handshake is finished. [[nodiscard]] virtual std::unique_ptr<RpcTransport> newTransport( - android::base::unique_fd fd, FdTrigger *fdTrigger) const = 0; + android::RpcTransportFd fd, FdTrigger *fdTrigger) const = 0; // Return the preconfigured certificate of this context. // @@ -129,4 +140,36 @@ protected: RpcTransportCtxFactory() = default; }; +struct RpcTransportFd { +private: + mutable bool isPolling{false}; + + void setPollingState(bool state) const { isPolling = state; } + +public: + base::unique_fd fd; + + RpcTransportFd() = default; + explicit RpcTransportFd(base::unique_fd &&descriptor) + : isPolling(false), fd(std::move(descriptor)) {} + + RpcTransportFd(RpcTransportFd &&transportFd) noexcept + : isPolling(transportFd.isPolling), fd(std::move(transportFd.fd)) {} + + RpcTransportFd &operator=(RpcTransportFd &&transportFd) noexcept { + fd = std::move(transportFd.fd); + isPolling = transportFd.isPolling; + return *this; + } + + RpcTransportFd &operator=(base::unique_fd &&descriptor) noexcept { + fd = std::move(descriptor); + isPolling = false; + return *this; + } + + bool isInPollingState() const { return isPolling; } + friend class FdTrigger; +}; + } // namespace android diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp index c0d4487e09..0ec618352a 100644 --- a/libs/binder/rust/Android.bp +++ b/libs/binder/rust/Android.bp @@ -144,24 +144,6 @@ rust_bindgen { min_sdk_version: "Tiramisu", } -// TODO(b/184872979): remove once the Rust API is created. -rust_bindgen { - name: "libbinder_rpc_unstable_bindgen", - wrapper_src: ":libbinder_rpc_unstable_header", - crate_name: "binder_rpc_unstable_bindgen", - visibility: ["//packages/modules/Virtualization:__subpackages__"], - source_stem: "bindings", - shared_libs: [ - "libutils", - ], - apex_available: [ - "com.android.compos", - "com.android.uwb", - "com.android.virt", - ], - min_sdk_version: "Tiramisu", -} - rust_test { name: "libbinder_rs-internal_test", crate_name: "binder", @@ -188,13 +170,3 @@ rust_test { clippy_lints: "none", lints: "none", } - -rust_test { - name: "libbinder_rpc_unstable_bindgen_test", - srcs: [":libbinder_rpc_unstable_bindgen"], - crate_name: "binder_rpc_unstable_bindgen", - test_suites: ["general-tests"], - auto_gen_config: true, - clippy_lints: "none", - lints: "none", -} diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp new file mode 100644 index 0000000000..f16939036c --- /dev/null +++ b/libs/binder/rust/rpcbinder/Android.bp @@ -0,0 +1,59 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + +rust_library { + name: "librpcbinder_rs", + crate_name: "rpcbinder", + srcs: ["src/lib.rs"], + shared_libs: [ + "libutils", + ], + rustlibs: [ + "libbinder_ndk_sys", + "libbinder_rpc_unstable_bindgen", + "libbinder_rs", + "libdowncast_rs", + "liblibc", + ], + apex_available: [ + "com.android.compos", + "com.android.uwb", + "com.android.virt", + ], + min_sdk_version: "Tiramisu", +} + +// TODO(b/184872979): remove once the RPC Binder API is stabilised. +rust_bindgen { + name: "libbinder_rpc_unstable_bindgen", + wrapper_src: ":libbinder_rpc_unstable_header", + crate_name: "binder_rpc_unstable_bindgen", + visibility: [":__subpackages__"], + source_stem: "bindings", + shared_libs: [ + "libbinder_rpc_unstable", + "libutils", + ], + apex_available: [ + "com.android.compos", + "com.android.uwb", + "com.android.virt", + ], + min_sdk_version: "Tiramisu", +} + +rust_test { + name: "libbinder_rpc_unstable_bindgen_test", + srcs: [":libbinder_rpc_unstable_bindgen"], + crate_name: "binder_rpc_unstable_bindgen", + test_suites: ["general-tests"], + auto_gen_config: true, + clippy_lints: "none", + lints: "none", +} diff --git a/libs/binder/rust/rpcbinder/src/client.rs b/libs/binder/rust/rpcbinder/src/client.rs new file mode 100644 index 0000000000..dfc6f06b14 --- /dev/null +++ b/libs/binder/rust/rpcbinder/src/client.rs @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2022 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. + */ + +use binder::{ + unstable_api::{new_spibinder, AIBinder}, + FromIBinder, SpIBinder, StatusCode, Strong, +}; +use std::os::{ + raw::{c_int, c_void}, + unix::io::RawFd, +}; + +/// Connects to an RPC Binder server over vsock. +pub fn get_vsock_rpc_service(cid: u32, port: u32) -> Option<SpIBinder> { + // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can + // safely be taken by new_spibinder. + unsafe { new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, port) as *mut AIBinder) } +} + +/// Connects to an RPC Binder server for a particular interface over vsock. +pub fn get_vsock_rpc_interface<T: FromIBinder + ?Sized>( + cid: u32, + port: u32, +) -> Result<Strong<T>, StatusCode> { + interface_cast(get_vsock_rpc_service(cid, port)) +} + +/// Connects to an RPC Binder server, using the given callback to get (and take ownership of) +/// file descriptors already connected to it. +pub fn get_preconnected_rpc_service( + mut request_fd: impl FnMut() -> Option<RawFd>, +) -> Option<SpIBinder> { + // Double reference the factory because trait objects aren't FFI safe. + let mut request_fd_ref: RequestFd = &mut request_fd; + let param = &mut request_fd_ref as *mut RequestFd as *mut c_void; + + // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the + // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership + // of param, only passing it to request_fd_wrapper. + unsafe { + new_spibinder(binder_rpc_unstable_bindgen::RpcPreconnectedClient( + Some(request_fd_wrapper), + param, + ) as *mut AIBinder) + } +} + +type RequestFd<'a> = &'a mut dyn FnMut() -> Option<RawFd>; + +unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int { + // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the + // BinderFdFactory reference, with param being a properly aligned non-null pointer to an + // initialized instance. + let request_fd_ptr = param as *mut RequestFd; + let request_fd = request_fd_ptr.as_mut().unwrap(); + if let Some(fd) = request_fd() { + fd + } else { + -1 + } +} + +/// Connects to an RPC Binder server for a particular interface, using the given callback to get +/// (and take ownership of) file descriptors already connected to it. +pub fn get_preconnected_rpc_interface<T: FromIBinder + ?Sized>( + request_fd: impl FnMut() -> Option<RawFd>, +) -> Result<Strong<T>, StatusCode> { + interface_cast(get_preconnected_rpc_service(request_fd)) +} + +fn interface_cast<T: FromIBinder + ?Sized>( + service: Option<SpIBinder>, +) -> Result<Strong<T>, StatusCode> { + if let Some(service) = service { + FromIBinder::try_from(service) + } else { + Err(StatusCode::NAME_NOT_FOUND) + } +} diff --git a/libs/binder/rust/rpcbinder/src/lib.rs b/libs/binder/rust/rpcbinder/src/lib.rs new file mode 100644 index 0000000000..a5eea61798 --- /dev/null +++ b/libs/binder/rust/rpcbinder/src/lib.rs @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2022 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. + */ + +//! API for RPC Binder services. + +mod client; +mod server; + +pub use client::{ + get_preconnected_rpc_interface, get_preconnected_rpc_service, get_vsock_rpc_interface, + get_vsock_rpc_service, +}; +pub use server::{run_rpc_server, run_rpc_server_with_factory}; diff --git a/libs/binder/rust/rpcbinder/src/server.rs b/libs/binder/rust/rpcbinder/src/server.rs new file mode 100644 index 0000000000..d98a439da4 --- /dev/null +++ b/libs/binder/rust/rpcbinder/src/server.rs @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2022 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. + */ + +use binder::{unstable_api::AsNative, SpIBinder}; +use std::{os::raw, ptr::null_mut}; + +/// Runs a binder RPC server, serving the supplied binder service implementation on the given vsock +/// port. +/// +/// If and when the server is ready for connections (it is listening on the port), `on_ready` is +/// called to allow appropriate action to be taken - e.g. to notify clients that they may now +/// attempt to connect. +/// +/// The current thread is joined to the binder thread pool to handle incoming messages. +/// +/// Returns true if the server has shutdown normally, false if it failed in some way. +pub fn run_rpc_server<F>(service: SpIBinder, port: u32, on_ready: F) -> bool +where + F: FnOnce(), +{ + let mut ready_notifier = ReadyNotifier(Some(on_ready)); + ready_notifier.run_server(service, port) +} + +struct ReadyNotifier<F>(Option<F>) +where + F: FnOnce(); + +impl<F> ReadyNotifier<F> +where + F: FnOnce(), +{ + fn run_server(&mut self, mut service: SpIBinder, port: u32) -> bool { + let service = service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder; + let param = self.as_void_ptr(); + + // SAFETY: Service ownership is transferring to the server and won't be valid afterward. + // Plus the binder objects are threadsafe. + // RunRpcServerCallback does not retain a reference to `ready_callback` or `param`; it only + // uses them before it returns, which is during the lifetime of `self`. + unsafe { + binder_rpc_unstable_bindgen::RunRpcServerCallback( + service, + port, + Some(Self::ready_callback), + param, + ) + } + } + + fn as_void_ptr(&mut self) -> *mut raw::c_void { + self as *mut _ as *mut raw::c_void + } + + unsafe extern "C" fn ready_callback(param: *mut raw::c_void) { + // SAFETY: This is only ever called by `RunRpcServerCallback`, within the lifetime of the + // `ReadyNotifier`, with `param` taking the value returned by `as_void_ptr` (so a properly + // aligned non-null pointer to an initialized instance). + let ready_notifier = param as *mut Self; + ready_notifier.as_mut().unwrap().notify() + } + + fn notify(&mut self) { + if let Some(on_ready) = self.0.take() { + on_ready(); + } + } +} + +type RpcServerFactoryRef<'a> = &'a mut (dyn FnMut(u32) -> Option<SpIBinder> + Send + Sync); + +/// Runs a binder RPC server, using the given factory function to construct a binder service +/// implementation for each connection. +/// +/// The current thread is joined to the binder thread pool to handle incoming messages. +/// +/// Returns true if the server has shutdown normally, false if it failed in some way. +pub fn run_rpc_server_with_factory( + port: u32, + mut factory: impl FnMut(u32) -> Option<SpIBinder> + Send + Sync, +) -> bool { + // Double reference the factory because trait objects aren't FFI safe. + // NB: The type annotation is necessary to ensure that we have a `dyn` rather than an `impl`. + let mut factory_ref: RpcServerFactoryRef = &mut factory; + let context = &mut factory_ref as *mut RpcServerFactoryRef as *mut raw::c_void; + + // SAFETY: `factory_wrapper` is only ever called by `RunRpcServerWithFactory`, with context + // taking the pointer value above (so a properly aligned non-null pointer to an initialized + // `RpcServerFactoryRef`), within the lifetime of `factory_ref` (i.e. no more calls will be made + // after `RunRpcServerWithFactory` returns). + unsafe { + binder_rpc_unstable_bindgen::RunRpcServerWithFactory(Some(factory_wrapper), context, port) + } +} + +unsafe extern "C" fn factory_wrapper( + cid: u32, + context: *mut raw::c_void, +) -> *mut binder_rpc_unstable_bindgen::AIBinder { + // SAFETY: `context` was created from an `&mut RpcServerFactoryRef` by + // `run_rpc_server_with_factory`, and we are still within the lifetime of the value it is + // pointing to. + let factory_ptr = context as *mut RpcServerFactoryRef; + let factory = factory_ptr.as_mut().unwrap(); + + if let Some(mut service) = factory(cid) { + service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder + } else { + null_mut() + } +} diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index 1babfd5813..e460d2c965 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -341,6 +341,11 @@ cc_test { "binderRpcTest_shared_defaults", "libbinder_tls_shared_deps", ], + + // Add the Trusty mock library as a fake dependency so it gets built + required: [ + "libbinder_on_trusty_mock", + ], } cc_test { diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index b59308c156..21b0354b60 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -54,27 +54,6 @@ TEST(BinderRpcParcel, EntireParcelFormatted) { EXPECT_DEATH(p.markForBinder(sp<BBinder>::make()), "format must be set before data is written"); } -class BinderRpcServerOnly : public ::testing::TestWithParam<std::tuple<RpcSecurity, uint32_t>> { -public: - static std::string PrintTestParam(const ::testing::TestParamInfo<ParamType>& info) { - return std::string(newFactory(std::get<0>(info.param))->toCString()) + "_serverV" + - std::to_string(std::get<1>(info.param)); - } -}; - -TEST_P(BinderRpcServerOnly, SetExternalServerTest) { - base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR))); - int sinkFd = sink.get(); - auto server = RpcServer::make(newFactory(std::get<0>(GetParam()))); - server->setProtocolVersion(std::get<1>(GetParam())); - ASSERT_FALSE(server->hasServer()); - ASSERT_EQ(OK, server->setupExternalServer(std::move(sink))); - ASSERT_TRUE(server->hasServer()); - base::unique_fd retrieved = server->releaseServer(); - ASSERT_FALSE(server->hasServer()); - ASSERT_EQ(sinkFd, retrieved.get()); -} - TEST(BinderRpc, CannotUseNextWireVersion) { auto session = RpcSession::make(); EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT)); @@ -1619,36 +1598,6 @@ private: bool mValue = false; }; -TEST_P(BinderRpcServerOnly, Shutdown) { - if constexpr (!kEnableRpcThreads) { - GTEST_SKIP() << "Test skipped because threads were disabled at build time"; - } - - auto addr = allocateSocketAddress(); - auto server = RpcServer::make(newFactory(std::get<0>(GetParam()))); - server->setProtocolVersion(std::get<1>(GetParam())); - ASSERT_EQ(OK, server->setupUnixDomainServer(addr.c_str())); - auto joinEnds = std::make_shared<OneOffSignal>(); - - // If things are broken and the thread never stops, don't block other tests. Because the thread - // may run after the test finishes, it must not access the stack memory of the test. Hence, - // shared pointers are passed. - std::thread([server, joinEnds] { - server->join(); - joinEnds->notify(); - }).detach(); - - bool shutdown = false; - for (int i = 0; i < 10 && !shutdown; i++) { - usleep(300 * 1000); // 300ms; total 3s - if (server->shutdown()) shutdown = true; - } - ASSERT_TRUE(shutdown) << "server->shutdown() never returns true"; - - ASSERT_TRUE(joinEnds->wait(2s)) - << "After server->shutdown() returns true, join() did not stop after 2s"; -} - TEST(BinderRpc, Java) { #if !defined(__ANDROID__) GTEST_SKIP() << "This test is only run on Android. Though it can technically run on host on" @@ -1701,6 +1650,57 @@ TEST(BinderRpc, Java) { ASSERT_EQ(OK, rpcBinder->pingBinder()); } +class BinderRpcServerOnly : public ::testing::TestWithParam<std::tuple<RpcSecurity, uint32_t>> { +public: + static std::string PrintTestParam(const ::testing::TestParamInfo<ParamType>& info) { + return std::string(newFactory(std::get<0>(info.param))->toCString()) + "_serverV" + + std::to_string(std::get<1>(info.param)); + } +}; + +TEST_P(BinderRpcServerOnly, SetExternalServerTest) { + base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR))); + int sinkFd = sink.get(); + auto server = RpcServer::make(newFactory(std::get<0>(GetParam()))); + server->setProtocolVersion(std::get<1>(GetParam())); + ASSERT_FALSE(server->hasServer()); + ASSERT_EQ(OK, server->setupExternalServer(std::move(sink))); + ASSERT_TRUE(server->hasServer()); + base::unique_fd retrieved = server->releaseServer(); + ASSERT_FALSE(server->hasServer()); + ASSERT_EQ(sinkFd, retrieved.get()); +} + +TEST_P(BinderRpcServerOnly, Shutdown) { + if constexpr (!kEnableRpcThreads) { + GTEST_SKIP() << "Test skipped because threads were disabled at build time"; + } + + auto addr = allocateSocketAddress(); + auto server = RpcServer::make(newFactory(std::get<0>(GetParam()))); + server->setProtocolVersion(std::get<1>(GetParam())); + ASSERT_EQ(OK, server->setupUnixDomainServer(addr.c_str())); + auto joinEnds = std::make_shared<OneOffSignal>(); + + // If things are broken and the thread never stops, don't block other tests. Because the thread + // may run after the test finishes, it must not access the stack memory of the test. Hence, + // shared pointers are passed. + std::thread([server, joinEnds] { + server->join(); + joinEnds->notify(); + }).detach(); + + bool shutdown = false; + for (int i = 0; i < 10 && !shutdown; i++) { + usleep(300 * 1000); // 300ms; total 3s + if (server->shutdown()) shutdown = true; + } + ASSERT_TRUE(shutdown) << "server->shutdown() never returns true"; + + ASSERT_TRUE(joinEnds->wait(2s)) + << "After server->shutdown() returns true, join() did not stop after 2s"; +} + INSTANTIATE_TEST_CASE_P(BinderRpc, BinderRpcServerOnly, ::testing::Combine(::testing::ValuesIn(RpcSecurityValues()), ::testing::ValuesIn(testVersions())), @@ -1773,7 +1773,7 @@ public: } } mFd = rpcServer->releaseServer(); - if (!mFd.ok()) return AssertionFailure() << "releaseServer returns invalid fd"; + if (!mFd.fd.ok()) return AssertionFailure() << "releaseServer returns invalid fd"; mCtx = newFactory(rpcSecurity, mCertVerifier, std::move(auth))->newServerCtx(); if (mCtx == nullptr) return AssertionFailure() << "newServerCtx"; mSetup = true; @@ -1794,7 +1794,7 @@ public: std::vector<std::thread> threads; while (OK == mFdTrigger->triggerablePoll(mFd, POLLIN)) { base::unique_fd acceptedFd( - TEMP_FAILURE_RETRY(accept4(mFd.get(), nullptr, nullptr /*length*/, + TEMP_FAILURE_RETRY(accept4(mFd.fd.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC | SOCK_NONBLOCK))); threads.emplace_back(&Server::handleOne, this, std::move(acceptedFd)); } @@ -1803,7 +1803,8 @@ public: } void handleOne(android::base::unique_fd acceptedFd) { ASSERT_TRUE(acceptedFd.ok()); - auto serverTransport = mCtx->newTransport(std::move(acceptedFd), mFdTrigger.get()); + RpcTransportFd transportFd(std::move(acceptedFd)); + auto serverTransport = mCtx->newTransport(std::move(transportFd), mFdTrigger.get()); if (serverTransport == nullptr) return; // handshake failed ASSERT_TRUE(mPostConnect(serverTransport.get(), mFdTrigger.get())); } @@ -1822,7 +1823,7 @@ public: std::unique_ptr<std::thread> mThread; ConnectToServer mConnectToServer; std::unique_ptr<FdTrigger> mFdTrigger = FdTrigger::make(); - base::unique_fd mFd; + RpcTransportFd mFd; std::unique_ptr<RpcTransportCtx> mCtx; std::shared_ptr<RpcCertificateVerifierSimple> mCertVerifier = std::make_shared<RpcCertificateVerifierSimple>(); @@ -1869,7 +1870,7 @@ public: // connect() and do handshake bool setUpTransport() { mFd = mConnectToServer(); - if (!mFd.ok()) return AssertionFailure() << "Cannot connect to server"; + if (!mFd.fd.ok()) return AssertionFailure() << "Cannot connect to server"; mClientTransport = mCtx->newTransport(std::move(mFd), mFdTrigger.get()); return mClientTransport != nullptr; } @@ -1898,9 +1899,11 @@ public: ASSERT_EQ(readOk, readMessage()); } + bool isTransportWaiting() { return mClientTransport->isWaiting(); } + private: ConnectToServer mConnectToServer; - base::unique_fd mFd; + RpcTransportFd mFd; std::unique_ptr<FdTrigger> mFdTrigger = FdTrigger::make(); std::unique_ptr<RpcTransportCtx> mCtx; std::shared_ptr<RpcCertificateVerifierSimple> mCertVerifier = @@ -2147,6 +2150,56 @@ TEST_P(RpcTransportTest, Trigger) { ASSERT_FALSE(client.readMessage(msg2)); } +TEST_P(RpcTransportTest, CheckWaitingForRead) { + std::mutex readMutex; + std::condition_variable readCv; + bool shouldContinueReading = false; + // Server will write data on transport once its started + auto serverPostConnect = [&](RpcTransport* serverTransport, FdTrigger* fdTrigger) { + std::string message(RpcTransportTestUtils::kMessage); + iovec messageIov{message.data(), message.size()}; + auto status = serverTransport->interruptableWriteFully(fdTrigger, &messageIov, 1, + std::nullopt, nullptr); + if (status != OK) return AssertionFailure() << statusToString(status); + + { + std::unique_lock<std::mutex> lock(readMutex); + shouldContinueReading = true; + lock.unlock(); + readCv.notify_all(); + } + return AssertionSuccess(); + }; + + // Setup Server and client + auto server = std::make_unique<Server>(); + ASSERT_TRUE(server->setUp(GetParam())); + + Client client(server->getConnectToServerFn()); + ASSERT_TRUE(client.setUp(GetParam())); + + ASSERT_EQ(OK, trust(&client, server)); + ASSERT_EQ(OK, trust(server, &client)); + server->setPostConnect(serverPostConnect); + + server->start(); + ASSERT_TRUE(client.setUpTransport()); + { + // Wait till server writes data + std::unique_lock<std::mutex> lock(readMutex); + ASSERT_TRUE(readCv.wait_for(lock, 3s, [&] { return shouldContinueReading; })); + } + + // Since there is no read polling here, we will get polling count 0 + ASSERT_FALSE(client.isTransportWaiting()); + ASSERT_TRUE(client.readMessage(RpcTransportTestUtils::kMessage)); + // Thread should increment polling count, read and decrement polling count + // Again, polling count should be zero here + ASSERT_FALSE(client.isTransportWaiting()); + + server->shutdown(); +} + INSTANTIATE_TEST_CASE_P(BinderRpc, RpcTransportTest, ::testing::ValuesIn(RpcTransportTest::getRpcTranportTestParams()), RpcTransportTest::PrintParamInfo); diff --git a/libs/binder/tests/parcel_fuzzer/random_fd.cpp b/libs/binder/tests/parcel_fuzzer/random_fd.cpp index 3fcf104e81..e4dbb2d955 100644 --- a/libs/binder/tests/parcel_fuzzer/random_fd.cpp +++ b/libs/binder/tests/parcel_fuzzer/random_fd.cpp @@ -26,9 +26,12 @@ namespace android { using base::unique_fd; std::vector<unique_fd> getRandomFds(FuzzedDataProvider* provider) { + const char* fdType; + std::vector<unique_fd> fds = provider->PickValueInArray< std::function<std::vector<unique_fd>()>>({ [&]() { + fdType = "ashmem"; std::vector<unique_fd> ret; ret.push_back(unique_fd( ashmem_create_region("binder test region", @@ -36,18 +39,21 @@ std::vector<unique_fd> getRandomFds(FuzzedDataProvider* provider) { return ret; }, [&]() { + fdType = "/dev/null"; std::vector<unique_fd> ret; ret.push_back(unique_fd(open("/dev/null", O_RDWR))); return ret; }, [&]() { + fdType = "pipefd"; + int pipefds[2]; int flags = O_CLOEXEC; if (provider->ConsumeBool()) flags |= O_DIRECT; if (provider->ConsumeBool()) flags |= O_NONBLOCK; - CHECK_EQ(0, pipe2(pipefds, flags)); + CHECK_EQ(0, pipe2(pipefds, flags)) << flags; if (provider->ConsumeBool()) std::swap(pipefds[0], pipefds[1]); @@ -58,7 +64,7 @@ std::vector<unique_fd> getRandomFds(FuzzedDataProvider* provider) { }, })(); - for (const auto& fd : fds) CHECK(fd.ok()) << fd.get(); + for (const auto& fd : fds) CHECK(fd.ok()) << fd.get() << " " << fdType; return fds; } diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp index b21fe6acf5..46346bb3e9 100644 --- a/libs/binder/trusty/OS.cpp +++ b/libs/binder/trusty/OS.cpp @@ -20,13 +20,15 @@ #include <lib/rand/rand.h> #endif +#include <binder/RpcTransportTipcTrusty.h> + #include "../OS.h" using android::base::Result; namespace android { -Result<void> setNonBlocking(android::base::borrowed_fd fd) { +Result<void> setNonBlocking(android::base::borrowed_fd /*fd*/) { // Trusty IPC syscalls are all non-blocking by default. return {}; } @@ -41,9 +43,13 @@ status_t getRandomBytes(uint8_t* data, size_t size) { #endif // TRUSTY_USERSPACE } -status_t dupFileDescriptor(int oldFd, int* newFd) { +status_t dupFileDescriptor(int /*oldFd*/, int* /*newFd*/) { // TODO: implement separately return INVALID_OPERATION; } +std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory() { + return RpcTransportCtxFactoryTipcTrusty::make(); +} + } // namespace android diff --git a/libs/binder/trusty/README.md b/libs/binder/trusty/README.md index 1a273aab10..8a60af8b23 100644 --- a/libs/binder/trusty/README.md +++ b/libs/binder/trusty/README.md @@ -1,39 +1,45 @@ # Binder for Trusty This is the Trusty port of the libbinder library. -To build it, take the following steps: - -* Check out copies of the Trusty and AOSP repositories. -* Apply the patches from the `trusty_binder` topic on both repositories. -* Build Trusty normally using `build.py`. -* Run the sample AIDL test for Trusty: - ```shell - $ ./build-root/.../run --headless --boot-test com.android.trusty.aidl.test - ``` - -To run the Android-Trusty IPC test, do the following: - -* Build AOSP for the `qemu_trusty_arm64-userdebug` target: - ```shell - $ lunch qemu_trusty_arm64-userdebug - $ m - ``` -* In the Trusty directory, run the emulator with the newly built Android: - ```shell - $ ./build-root/.../run --android /path/to/aosp - ``` -* Using either `adb` or the shell inside the emulator itself, run the Trusty - Binder test as root: - ```shell - # /data/nativetest64/vendor/trusty_binder_test/trusty_binder_test - ``` - -## Running the AIDL compiler -For now, you will need to run the AIDL compiler manually to generate the C++ -source code for Trusty clients and services. The general syntax is: +To build it, first you will need a checkout of the Trusty tree: ```shell -$ aidl --lang=cpp -o <output directory> -h <output header directory> <AIDL files...> +$ mkdir /path/to/trusty +$ cd /path/to/trusty +$ repo init -u https://android.googlesource.com/trusty/manifest -b master +$ repo sync -j$(nproc) -c --no-tags ``` -The compiler will emit some `.cpp` files in the output directory and their -corresponding `.h` files in the header directory. +After the checkout is complete, you can use the `build.py` script for both +building and testing Trusty. For a quick build without any tests, run: +```shell +$ ./trusty/vendor/google/aosp/scripts/build.py generic-arm64-test-debug +``` +This will build the smaller `generic-arm64-test-debug` project which +does not run any tests. + +The qemu-generic-arm64-test-debug` project includes the QEMU emulator and +a full Trusty test suite, including a set of libbinder tests. +To run the latter, use the command: +```shell +$ ./trusty/vendor/google/aosp/scripts/build.py \ + --test "boot-test:com.android.trusty.binder.test" \ + qemu-generic-arm64-test-debug +``` + +## Building AIDL files on Trusty +To compile AIDL interfaces into Trusty libraries, include the `make/aidl.mk` +in your `rules.mk` file, e.g.: +``` +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_AIDLS := \ + $(LOCAL_DIR)/IFoo.aidl \ + +include make/aidl.mk +``` + +## Examples +The Trusty tree contains some sample test apps at +`trusty/user/app/sample/binder-test`. diff --git a/libs/binder/trusty/RpcServerTrusty.cpp b/libs/binder/trusty/RpcServerTrusty.cpp index e8b91e7a4c..18ce316d67 100644 --- a/libs/binder/trusty/RpcServerTrusty.cpp +++ b/libs/binder/trusty/RpcServerTrusty.cpp @@ -104,24 +104,40 @@ int RpcServerTrusty::handleConnect(const tipc_port* port, handle_t chan, const u return; } - /* Save the session for easy access */ - *ctx_p = session.get(); + /* Save the session and connection for the other callbacks */ + auto* channelContext = new (std::nothrow) ChannelContext; + if (channelContext == nullptr) { + rc = ERR_NO_MEMORY; + return; + } + + channelContext->session = std::move(session); + channelContext->connection = std::move(result.connection); + + *ctx_p = channelContext; }; base::unique_fd clientFd(chan); + android::RpcTransportFd transportFd(std::move(clientFd)); + std::array<uint8_t, RpcServer::kRpcAddressSize> addr; constexpr size_t addrLen = sizeof(*peer); memcpy(addr.data(), peer, addrLen); - RpcServer::establishConnection(sp(server->mRpcServer), std::move(clientFd), addr, addrLen, + RpcServer::establishConnection(sp(server->mRpcServer), std::move(transportFd), addr, addrLen, joinFn); return rc; } -int RpcServerTrusty::handleMessage(const tipc_port* port, handle_t chan, void* ctx) { - auto* session = reinterpret_cast<RpcSession*>(ctx); - status_t status = session->state()->drainCommands(session->mConnections.mIncoming[0], session, - RpcState::CommandType::ANY); +int RpcServerTrusty::handleMessage(const tipc_port* /*port*/, handle_t /*chan*/, void* ctx) { + auto* channelContext = reinterpret_cast<ChannelContext*>(ctx); + LOG_ALWAYS_FATAL_IF(channelContext == nullptr, + "bad state: message received on uninitialized channel"); + + auto& session = channelContext->session; + auto& connection = channelContext->connection; + status_t status = + session->state()->drainCommands(connection, session, RpcState::CommandType::ANY); if (status != OK) { LOG_RPC_DETAIL("Binder connection thread closing w/ status %s", statusToString(status).c_str()); @@ -130,13 +146,21 @@ int RpcServerTrusty::handleMessage(const tipc_port* port, handle_t chan, void* c return NO_ERROR; } -void RpcServerTrusty::handleDisconnect(const tipc_port* port, handle_t chan, void* ctx) {} +void RpcServerTrusty::handleDisconnect(const tipc_port* /*port*/, handle_t /*chan*/, + void* /*ctx*/) {} void RpcServerTrusty::handleChannelCleanup(void* ctx) { - auto* session = reinterpret_cast<RpcSession*>(ctx); - auto& connection = session->mConnections.mIncoming.at(0); + auto* channelContext = reinterpret_cast<ChannelContext*>(ctx); + if (channelContext == nullptr) { + return; + } + + auto& session = channelContext->session; + auto& connection = channelContext->connection; LOG_ALWAYS_FATAL_IF(!session->removeIncomingConnection(connection), "bad state: connection object guaranteed to be in list"); + + delete channelContext; } } // namespace android diff --git a/libs/binder/trusty/RpcTransportTipcTrusty.cpp b/libs/binder/trusty/RpcTransportTipcTrusty.cpp index dc27eb929c..0b67b9fb12 100644 --- a/libs/binder/trusty/RpcTransportTipcTrusty.cpp +++ b/libs/binder/trusty/RpcTransportTipcTrusty.cpp @@ -33,7 +33,7 @@ namespace { // RpcTransport for Trusty. class RpcTransportTipcTrusty : public RpcTransport { public: - explicit RpcTransportTipcTrusty(android::base::unique_fd socket) : mSocket(std::move(socket)) {} + explicit RpcTransportTipcTrusty(android::RpcTransportFd socket) : mSocket(std::move(socket)) {} ~RpcTransportTipcTrusty() { releaseMessage(); } status_t pollRead() override { @@ -45,9 +45,9 @@ public: } status_t interruptableWriteFully( - FdTrigger* fdTrigger, iovec* iovs, int niovs, - const std::optional<android::base::function_ref<status_t()>>& altPoll, - const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) + FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs, + const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/, + const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/) override { if (niovs < 0) { return BAD_VALUE; @@ -64,7 +64,7 @@ public: .num_handles = 0, // TODO: add ancillaryFds .handles = nullptr, }; - ssize_t rc = send_msg(mSocket.get(), &msg); + ssize_t rc = send_msg(mSocket.fd.get(), &msg); if (rc == ERR_NOT_ENOUGH_BUFFER) { // Peer is blocked, wait until it unblocks. // TODO: when tipc supports a send-unblocked handler, @@ -72,7 +72,7 @@ public: // when the handler gets called by the library uevent uevt; do { - rc = ::wait(mSocket.get(), &uevt, INFINITE_TIME); + rc = ::wait(mSocket.fd.get(), &uevt, INFINITE_TIME); if (rc < 0) { return statusFromTrusty(rc); } @@ -83,7 +83,7 @@ public: // Retry the send, it should go through this time because // sending is now unblocked - rc = send_msg(mSocket.get(), &msg); + rc = send_msg(mSocket.fd.get(), &msg); } if (rc < 0) { return statusFromTrusty(rc); @@ -95,9 +95,10 @@ public: } status_t interruptableReadFully( - FdTrigger* fdTrigger, iovec* iovs, int niovs, - const std::optional<android::base::function_ref<status_t()>>& altPoll, - std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override { + FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs, + const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/, + std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/) + override { if (niovs < 0) { return BAD_VALUE; } @@ -129,7 +130,7 @@ public: .num_handles = 0, // TODO: support ancillaryFds .handles = nullptr, }; - ssize_t rc = read_msg(mSocket.get(), mMessageInfo.id, mMessageOffset, &msg); + ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg); if (rc < 0) { return statusFromTrusty(rc); } @@ -169,6 +170,8 @@ public: } } + bool isWaiting() override { return mSocket.isInPollingState(); } + private: status_t ensureMessage(bool wait) { int rc; @@ -179,7 +182,7 @@ private: /* TODO: interruptible wait, maybe with a timeout??? */ uevent uevt; - rc = ::wait(mSocket.get(), &uevt, wait ? INFINITE_TIME : 0); + rc = ::wait(mSocket.fd.get(), &uevt, wait ? INFINITE_TIME : 0); if (rc < 0) { if (rc == ERR_TIMED_OUT && !wait) { // If we timed out with wait==false, then there's no message @@ -192,7 +195,7 @@ private: return OK; } - rc = get_msg(mSocket.get(), &mMessageInfo); + rc = get_msg(mSocket.fd.get(), &mMessageInfo); if (rc < 0) { return statusFromTrusty(rc); } @@ -204,12 +207,12 @@ private: void releaseMessage() { if (mHaveMessage) { - put_msg(mSocket.get(), mMessageInfo.id); + put_msg(mSocket.fd.get(), mMessageInfo.id); mHaveMessage = false; } } - base::unique_fd mSocket; + android::RpcTransportFd mSocket; bool mHaveMessage = false; ipc_msg_info mMessageInfo; @@ -219,9 +222,9 @@ private: // RpcTransportCtx for Trusty. class RpcTransportCtxTipcTrusty : public RpcTransportCtx { public: - std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, + std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd socket, FdTrigger*) const override { - return std::make_unique<RpcTransportTipcTrusty>(std::move(fd)); + return std::make_unique<RpcTransportTipcTrusty>(std::move(socket)); } std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; } }; diff --git a/libs/binder/trusty/include/binder/RpcServerTrusty.h b/libs/binder/trusty/include/binder/RpcServerTrusty.h index e8fc9f988d..cc31c95da1 100644 --- a/libs/binder/trusty/include/binder/RpcServerTrusty.h +++ b/libs/binder/trusty/include/binder/RpcServerTrusty.h @@ -77,6 +77,12 @@ private: explicit RpcServerTrusty(std::unique_ptr<RpcTransportCtx> ctx, std::string&& portName, std::shared_ptr<const PortAcl>&& portAcl, size_t msgMaxSize); + // The Rpc-specific context maintained for every open TIPC channel. + struct ChannelContext { + sp<RpcSession> session; + sp<RpcSession::RpcConnection> connection; + }; + static int handleConnect(const tipc_port* port, handle_t chan, const uuid* peer, void** ctx_p); static int handleMessage(const tipc_port* port, handle_t chan, void* ctx); static void handleDisconnect(const tipc_port* port, handle_t chan, void* ctx); diff --git a/libs/binder/trusty/include_mock/lib/tipc/tipc_srv.h b/libs/binder/trusty/include_mock/lib/tipc/tipc_srv.h new file mode 100644 index 0000000000..2747314508 --- /dev/null +++ b/libs/binder/trusty/include_mock/lib/tipc/tipc_srv.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <stddef.h> +#include <trusty_ipc.h> +#include <uapi/trusty_uuid.h> + +struct tipc_port_acl { + uint32_t flags; + uint32_t uuid_num; + const struct uuid** uuids; + const void* extra_data; +}; + +struct tipc_port { + const char* name; + uint32_t msg_max_size; + uint32_t msg_queue_len; + const struct tipc_port_acl* acl; + const void* priv; +}; + +struct tipc_srv_ops { + int (*on_connect)(const struct tipc_port* port, handle_t chan, const struct uuid* peer, + void** ctx_p); + + int (*on_message)(const struct tipc_port* port, handle_t chan, void* ctx); + + void (*on_disconnect)(const struct tipc_port* port, handle_t chan, void* ctx); + + void (*on_channel_cleanup)(void* ctx); +}; + +static inline int tipc_add_service(struct tipc_hset*, const struct tipc_port*, uint32_t, uint32_t, + const struct tipc_srv_ops*) { + return 0; +} diff --git a/services/surfaceflinger/CompositionEngine/tests/TestUtils.h b/libs/binder/trusty/include_mock/openssl/rand.h index c80fde6ead..07dcc1cb6d 100644 --- a/services/surfaceflinger/CompositionEngine/tests/TestUtils.h +++ b/libs/binder/trusty/include_mock/openssl/rand.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 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. @@ -15,17 +15,6 @@ */ #pragma once -#include <future> - -namespace android::compositionengine { -namespace { - -template <class T> -std::future<T> futureOf(T obj) { - std::promise<T> resultPromise; - std::future<T> resultFuture = resultPromise.get_future(); - resultPromise.set_value(std::move(obj)); - return resultFuture; +static inline int RAND_bytes(unsigned char*, int) { + return 0; } -} // namespace -} // namespace android::compositionengine diff --git a/libs/binder/trusty/include_mock/trusty_ipc.h b/libs/binder/trusty/include_mock/trusty_ipc.h new file mode 100644 index 0000000000..a2170cea64 --- /dev/null +++ b/libs/binder/trusty/include_mock/trusty_ipc.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <stddef.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <uapi/trusty_uuid.h> + +#define INFINITE_TIME 1 +#define IPC_MAX_MSG_HANDLES 8 + +#define IPC_HANDLE_POLL_HUP 0x1 +#define IPC_HANDLE_POLL_MSG 0x2 +#define IPC_HANDLE_POLL_SEND_UNBLOCKED 0x4 + +typedef int handle_t; + +typedef struct ipc_msg { + uint32_t num_iov; + iovec* iov; + uint32_t num_handles; + handle_t* handles; +} ipc_msg_t; + +typedef struct ipc_msg_info { + size_t len; + uint32_t id; + uint32_t num_handles; +} ipc_msg_info_t; + +typedef struct uevent { + uint32_t event; +} uevent_t; + +static inline handle_t port_create(const char*, uint32_t, uint32_t, uint32_t) { + return 0; +} +static inline handle_t connect(const char*, uint32_t) { + return 0; +} +static inline handle_t accept(handle_t, uuid_t*) { + return 0; +} +static inline int set_cookie(handle_t, void*) { + return 0; +} +static inline handle_t handle_set_create(void) { + return 0; +} +static inline int handle_set_ctrl(handle_t, uint32_t, struct uevent*) { + return 0; +} +static inline int wait(handle_t, uevent_t*, uint32_t) { + return 0; +} +static inline int wait_any(uevent_t*, uint32_t) { + return 0; +} +static inline int get_msg(handle_t, ipc_msg_info_t*) { + return 0; +} +static inline ssize_t read_msg(handle_t, uint32_t, uint32_t, ipc_msg_t*) { + return 0; +} +static inline int put_msg(handle_t, uint32_t) { + return 0; +} +static inline ssize_t send_msg(handle_t, ipc_msg_t*) { + return 0; +} diff --git a/libs/binder/trusty/include_mock/trusty_log.h b/libs/binder/trusty/include_mock/trusty_log.h new file mode 100644 index 0000000000..d51e75280c --- /dev/null +++ b/libs/binder/trusty/include_mock/trusty_log.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <stdio.h> + +// Mock definitions for the Trusty logging macros. These are not +// meant to be run, just compiled successfully. +#define TLOGD(fmt, ...) printf(fmt, ##__VA_ARGS__) +#define TLOGI(fmt, ...) printf(fmt, ##__VA_ARGS__) +#define TLOGW(fmt, ...) printf(fmt, ##__VA_ARGS__) +#define TLOGE(fmt, ...) printf(fmt, ##__VA_ARGS__) +#define TLOGC(fmt, ...) printf(fmt, ##__VA_ARGS__) diff --git a/libs/binder/trusty/include_mock/uapi/err.h b/libs/binder/trusty/include_mock/uapi/err.h new file mode 100644 index 0000000000..c7e117e419 --- /dev/null +++ b/libs/binder/trusty/include_mock/uapi/err.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +enum { + NO_ERROR, + ERR_ACCESS_DENIED, + ERR_ALREADY_EXISTS, + ERR_BAD_HANDLE, + ERR_BAD_LEN, + ERR_BAD_STATE, + ERR_CHANNEL_CLOSED, + ERR_CMD_UNKNOWN, + ERR_GENERIC, + ERR_INVALID_ARGS, + ERR_NO_MEMORY, + ERR_NO_MSG, + ERR_NOT_ALLOWED, + ERR_NOT_CONFIGURED, + ERR_NOT_ENOUGH_BUFFER, + ERR_NOT_FOUND, + ERR_NOT_READY, + ERR_NOT_SUPPORTED, + ERR_NOT_VALID, + ERR_TIMED_OUT, + ERR_TOO_BIG, +}; diff --git a/libs/binder/trusty/include_mock/uapi/trusty_uuid.h b/libs/binder/trusty/include_mock/uapi/trusty_uuid.h new file mode 100644 index 0000000000..f636826bec --- /dev/null +++ b/libs/binder/trusty/include_mock/uapi/trusty_uuid.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +typedef struct uuid { + int placeholder; +} uuid_t; diff --git a/libs/binder/trusty/logging.cpp b/libs/binder/trusty/logging.cpp index fd54744fdf..b4243af891 100644 --- a/libs/binder/trusty/logging.cpp +++ b/libs/binder/trusty/logging.cpp @@ -54,7 +54,7 @@ void DefaultAborter(const char* abort_message) { abort(); } -static void TrustyLogLine(const char* msg, int length, android::base::LogSeverity severity, +static void TrustyLogLine(const char* msg, int /*length*/, android::base::LogSeverity severity, const char* tag) { switch (severity) { case VERBOSE: @@ -157,7 +157,7 @@ void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severi TrustyLogger(DEFAULT, severity, tag ?: "<unknown>", file, line, message); } -bool ShouldLog(LogSeverity severity, const char* tag) { +bool ShouldLog(LogSeverity /*severity*/, const char* /*tag*/) { // This is controlled by Trusty's log level. return true; } diff --git a/libs/binder/trusty/rules.mk b/libs/binder/trusty/rules.mk index d0d0861416..4e5cd18726 100644 --- a/libs/binder/trusty/rules.mk +++ b/libs/binder/trusty/rules.mk @@ -76,7 +76,6 @@ MODULE_EXPORT_INCLUDES += \ $(LIBBINDER_DIR)/ndk/include_cpp \ MODULE_EXPORT_COMPILEFLAGS += \ - -DBINDER_NO_KERNEL_IPC \ -DBINDER_RPC_SINGLE_THREADED \ -D__ANDROID_VNDK__ \ diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp index 44e2fd19b1..2f731377f0 100644 --- a/libs/binderthreadstate/test.cpp +++ b/libs/binderthreadstate/test.cpp @@ -68,8 +68,13 @@ static void callHidl(size_t id, int32_t idx) { static void callAidl(size_t id, int32_t idx) { sp<IAidlStuff> stuff; - CHECK(OK == android::getService<IAidlStuff>(String16(id2name(id).c_str()), &stuff)); - CHECK(stuff->call(idx).isOk()); + CHECK_EQ(OK, android::getService<IAidlStuff>(String16(id2name(id).c_str()), &stuff)); + auto ret = stuff->call(idx); + CHECK(ret.isOk()) << ret; +} + +static inline std::ostream& operator<<(std::ostream& o, const BinderCallType& s) { + return o << static_cast<std::underlying_type_t<BinderCallType>>(s); } class HidlServer : public IHidlStuff { @@ -79,13 +84,13 @@ public: size_t otherId; Return<void> callLocal() { - CHECK(BinderCallType::NONE == getCurrentServingCall()); + CHECK_EQ(BinderCallType::NONE, getCurrentServingCall()); return android::hardware::Status::ok(); } Return<void> call(int32_t idx) { LOG(INFO) << "HidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx << " with tid: " << gettid(); - CHECK(BinderCallType::HWBINDER == getCurrentServingCall()); + CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall()); if (idx > 0) { if (thisId == kP1Id && idx % 4 < 2) { callHidl(otherId, idx - 1); @@ -93,7 +98,7 @@ public: callAidl(otherId, idx - 1); } } - CHECK(BinderCallType::HWBINDER == getCurrentServingCall()); + CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall()); return android::hardware::Status::ok(); } }; @@ -104,13 +109,13 @@ public: size_t otherId; Status callLocal() { - CHECK(BinderCallType::NONE == getCurrentServingCall()); + CHECK_EQ(BinderCallType::NONE, getCurrentServingCall()); return Status::ok(); } Status call(int32_t idx) { LOG(INFO) << "AidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx << " with tid: " << gettid(); - CHECK(BinderCallType::BINDER == getCurrentServingCall()); + CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall()); if (idx > 0) { if (thisId == kP2Id && idx % 4 < 2) { callHidl(otherId, idx - 1); @@ -118,7 +123,7 @@ public: callAidl(otherId, idx - 1); } } - CHECK(BinderCallType::BINDER == getCurrentServingCall()); + CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall()); return Status::ok(); } }; @@ -161,13 +166,14 @@ int server(size_t thisId, size_t otherId) { // AIDL android::ProcessState::self()->setThreadPoolMaxThreadCount(1); sp<AidlServer> aidlServer = new AidlServer(thisId, otherId); - CHECK(OK == defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer)); + CHECK_EQ(OK, + defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer)); android::ProcessState::self()->startThreadPool(); // HIDL android::hardware::configureRpcThreadpool(1, true /*callerWillJoin*/); sp<IHidlStuff> hidlServer = new HidlServer(thisId, otherId); - CHECK(OK == hidlServer->registerAsService(id2name(thisId).c_str())); + CHECK_EQ(OK, hidlServer->registerAsService(id2name(thisId).c_str())); android::hardware::joinRpcThreadpool(); return EXIT_FAILURE; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index bb660854c8..4d5978ccf7 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -40,8 +40,6 @@ layer_state_t::layer_state_t() x(0), y(0), z(0), - w(0), - h(0), alpha(0), flags(0), mask(0), @@ -84,8 +82,6 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeFloat, x); SAFE_PARCEL(output.writeFloat, y); SAFE_PARCEL(output.writeInt32, z); - SAFE_PARCEL(output.writeUint32, w); - SAFE_PARCEL(output.writeUint32, h); SAFE_PARCEL(output.writeUint32, layerStack.id); SAFE_PARCEL(output.writeFloat, alpha); SAFE_PARCEL(output.writeUint32, flags); @@ -180,8 +176,6 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readFloat, &x); SAFE_PARCEL(input.readFloat, &y); SAFE_PARCEL(input.readInt32, &z); - SAFE_PARCEL(input.readUint32, &w); - SAFE_PARCEL(input.readUint32, &h); SAFE_PARCEL(input.readUint32, &layerStack.id); SAFE_PARCEL(input.readFloat, &alpha); @@ -457,11 +451,6 @@ void layer_state_t::merge(const layer_state_t& other) { what &= ~eRelativeLayerChanged; z = other.z; } - if (other.what & eSizeChanged) { - what |= eSizeChanged; - w = other.w; - h = other.h; - } if (other.what & eAlphaChanged) { what |= eAlphaChanged; alpha = other.alpha; diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS index 31bf895371..05b55337ab 100644 --- a/libs/gui/OWNERS +++ b/libs/gui/OWNERS @@ -2,8 +2,9 @@ adyabr@google.com alecmouri@google.com chaviw@google.com chrisforbes@google.com -lpy@google.com jreck@google.com +lpy@google.com +pdwilliams@google.com racarr@google.com vishnun@google.com diff --git a/libs/gui/ScreenCaptureResults.cpp b/libs/gui/ScreenCaptureResults.cpp index fe387064bc..601a5f9b33 100644 --- a/libs/gui/ScreenCaptureResults.cpp +++ b/libs/gui/ScreenCaptureResults.cpp @@ -17,6 +17,7 @@ #include <gui/ScreenCaptureResults.h> #include <private/gui/ParcelUtils.h> +#include <ui/FenceResult.h> namespace android::gui { @@ -28,17 +29,17 @@ status_t ScreenCaptureResults::writeToParcel(android::Parcel* parcel) const { SAFE_PARCEL(parcel->writeBool, false); } - if (fence != Fence::NO_FENCE) { + if (fenceResult.ok() && fenceResult.value() != Fence::NO_FENCE) { SAFE_PARCEL(parcel->writeBool, true); - SAFE_PARCEL(parcel->write, *fence); + SAFE_PARCEL(parcel->write, *fenceResult.value()); } else { SAFE_PARCEL(parcel->writeBool, false); + SAFE_PARCEL(parcel->writeInt32, fenceStatus(fenceResult)); } SAFE_PARCEL(parcel->writeBool, capturedSecureLayers); SAFE_PARCEL(parcel->writeBool, capturedHdrLayers); SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(capturedDataspace)); - SAFE_PARCEL(parcel->writeInt32, result); return NO_ERROR; } @@ -53,8 +54,13 @@ status_t ScreenCaptureResults::readFromParcel(const android::Parcel* parcel) { bool hasFence; SAFE_PARCEL(parcel->readBool, &hasFence); if (hasFence) { - fence = new Fence(); - SAFE_PARCEL(parcel->read, *fence); + fenceResult = sp<Fence>::make(); + SAFE_PARCEL(parcel->read, *fenceResult.value()); + } else { + status_t status; + SAFE_PARCEL(parcel->readInt32, &status); + fenceResult = status == NO_ERROR ? FenceResult(Fence::NO_FENCE) + : FenceResult(base::unexpected(status)); } SAFE_PARCEL(parcel->readBool, &capturedSecureLayers); @@ -62,7 +68,6 @@ status_t ScreenCaptureResults::readFromParcel(const android::Parcel* parcel) { uint32_t dataspace = 0; SAFE_PARCEL(parcel->readUint32, &dataspace); capturedDataspace = static_cast<ui::Dataspace>(dataspace); - SAFE_PARCEL(parcel->readInt32, &result); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index e8aaf629b3..34edd65af3 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1038,9 +1038,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay flags |= ISurfaceComposer::eEarlyWakeupEnd; } - sp<IBinder> applyToken = mApplyToken - ? mApplyToken - : IInterface::asBinder(TransactionCompletedListener::getIInstance()); + sp<IBinder> applyToken = mApplyToken ? mApplyToken : sApplyToken; sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken, mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp, @@ -1055,6 +1053,15 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay return NO_ERROR; } +sp<IBinder> SurfaceComposerClient::Transaction::sApplyToken = new BBinder(); + +sp<IBinder> SurfaceComposerClient::Transaction::getDefaultApplyToken() { + return sApplyToken; +} + +void SurfaceComposerClient::Transaction::setDefaultApplyToken(sp<IBinder> applyToken) { + sApplyToken = applyToken; +} // --------------------------------------------------------------------------- sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, bool secure) { @@ -1165,21 +1172,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::hide( return setFlags(sc, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden); } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize( - const sp<SurfaceControl>& sc, uint32_t w, uint32_t h) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eSizeChanged; - s->w = w; - s->h = h; - - registerSurfaceControlForCallback(sc); - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer( const sp<SurfaceControl>& sc, int32_t z) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp index 05564e093a..48c90c5e8f 100644 --- a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp +++ b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp @@ -182,8 +182,6 @@ void SurfaceComposerClientFuzzer::invokeSurfaceComposerTransaction() { sp<SurfaceControl> surface = makeSurfaceControl(); SurfaceComposerClient::Transaction transaction; - transaction.setSize(surface, mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint32_t>()); int32_t layer = mFdp.ConsumeIntegral<int32_t>(); transaction.setLayer(surface, layer); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 759fcc6c53..3c7b16266d 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -148,7 +148,7 @@ struct layer_state_t { enum { ePositionChanged = 0x00000001, eLayerChanged = 0x00000002, - eSizeChanged = 0x00000004, + // unused = 0x00000004, eAlphaChanged = 0x00000008, eMatrixChanged = 0x00000010, eTransparentRegionChanged = 0x00000020, @@ -217,8 +217,6 @@ struct layer_state_t { float x; float y; int32_t z; - uint32_t w; - uint32_t h; ui::LayerStack layerStack = ui::DEFAULT_LAYER_STACK; float alpha; uint32_t flags; diff --git a/libs/gui/include/gui/ScreenCaptureResults.h b/libs/gui/include/gui/ScreenCaptureResults.h index 724c11c881..6e17791a29 100644 --- a/libs/gui/include/gui/ScreenCaptureResults.h +++ b/libs/gui/include/gui/ScreenCaptureResults.h @@ -19,6 +19,7 @@ #include <binder/Parcel.h> #include <binder/Parcelable.h> #include <ui/Fence.h> +#include <ui/FenceResult.h> #include <ui/GraphicBuffer.h> namespace android::gui { @@ -31,11 +32,10 @@ public: status_t readFromParcel(const android::Parcel* parcel) override; sp<GraphicBuffer> buffer; - sp<Fence> fence = Fence::NO_FENCE; + FenceResult fenceResult = Fence::NO_FENCE; bool capturedSecureLayers{false}; bool capturedHdrLayers{false}; ui::Dataspace capturedDataspace{ui::Dataspace::V0_SRGB}; - status_t result = OK; }; } // namespace android::gui diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 20c38d8012..8c47ebc3b8 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -390,6 +390,7 @@ public: class Transaction : public Parcelable { private: + static sp<IBinder> sApplyToken; void releaseBufferIfOverwriting(const layer_state_t& state); static void mergeFrameTimelineInfo(FrameTimelineInfo& t, const FrameTimelineInfo& other); static void clearFrameTimelineInfo(FrameTimelineInfo& t); @@ -468,10 +469,9 @@ public: Transaction& merge(Transaction&& other); Transaction& show(const sp<SurfaceControl>& sc); Transaction& hide(const sp<SurfaceControl>& sc); - Transaction& setPosition(const sp<SurfaceControl>& sc, - float x, float y); - Transaction& setSize(const sp<SurfaceControl>& sc, - uint32_t w, uint32_t h); + Transaction& setPosition(const sp<SurfaceControl>& sc, float x, float y); + // b/243180033 remove once functions are not called from vendor code + Transaction& setSize(const sp<SurfaceControl>&, uint32_t, uint32_t) { return *this; } Transaction& setLayer(const sp<SurfaceControl>& sc, int32_t z); @@ -669,6 +669,9 @@ public: * TODO (b/213644870): Remove all permissioned things from Transaction */ void sanitize(); + + static sp<IBinder> getDefaultApplyToken(); + static void setDefaultApplyToken(sp<IBinder> applyToken); }; status_t clearLayerFrameStats(const sp<IBinder>& token) const; diff --git a/libs/gui/include/gui/SyncScreenCaptureListener.h b/libs/gui/include/gui/SyncScreenCaptureListener.h index 0784fbc058..bcf565a494 100644 --- a/libs/gui/include/gui/SyncScreenCaptureListener.h +++ b/libs/gui/include/gui/SyncScreenCaptureListener.h @@ -34,7 +34,9 @@ public: ScreenCaptureResults waitForResults() { std::future<ScreenCaptureResults> resultsFuture = resultsPromise.get_future(); const auto screenCaptureResults = resultsFuture.get(); - screenCaptureResults.fence->waitForever(""); + if (screenCaptureResults.fenceResult.ok()) { + screenCaptureResults.fenceResult.value()->waitForever(""); + } return screenCaptureResults; } @@ -42,4 +44,4 @@ private: std::promise<ScreenCaptureResults> resultsPromise; }; -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 3e563b2aa2..c4c2fa5b85 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -311,7 +311,7 @@ protected: return err; } captureResults = captureListener->waitForResults(); - return captureResults.result; + return fenceStatus(captureResults.fenceResult); } void queueBuffer(sp<IGraphicBufferProducer> igbp, uint8_t r, uint8_t g, uint8_t b, diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 71f2ad4d3c..b9358e7717 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -218,7 +218,7 @@ protected: return err; } captureResults = captureListener->waitForResults(); - return captureResults.result; + return fenceStatus(captureResults.fenceResult); } sp<Surface> mSurface; diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 5030d60da2..29e02cf73a 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -26,6 +26,7 @@ package { filegroup { name: "inputconstants_aidl", srcs: [ + "android/hardware/input/InputDeviceCountryCode.aidl", "android/os/IInputConstants.aidl", "android/os/InputEventInjectionResult.aidl", "android/os/InputEventInjectionSync.aidl", diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index a9089690b0..3fe03c7979 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -26,6 +26,7 @@ #include <input/InputEventLabels.h> using android::base::StringPrintf; +using android::hardware::input::InputDeviceCountryCode; namespace android { @@ -177,6 +178,7 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) mAlias(other.mAlias), mIsExternal(other.mIsExternal), mHasMic(other.mHasMic), + mCountryCode(other.mCountryCode), mSources(other.mSources), mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap), @@ -192,8 +194,8 @@ InputDeviceInfo::~InputDeviceInfo() { } void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber, - const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal, - bool hasMic) { + const InputDeviceIdentifier& identifier, const std::string& alias, + bool isExternal, bool hasMic, InputDeviceCountryCode countryCode) { mId = id; mGeneration = generation; mControllerNumber = controllerNumber; @@ -201,6 +203,7 @@ void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t control mAlias = alias; mIsExternal = isExternal; mHasMic = hasMic; + mCountryCode = countryCode; mSources = 0; mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; mHasVibrator = false; diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index d6b4579a94..73710330d0 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -192,7 +192,8 @@ status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode, } // Return pair of sensor type and sensor data index, for the input device abs code -base::Result<std::pair<InputDeviceSensorType, int32_t>> KeyLayoutMap::mapSensor(int32_t absCode) { +base::Result<std::pair<InputDeviceSensorType, int32_t>> KeyLayoutMap::mapSensor( + int32_t absCode) const { auto it = mSensorsByAbsCode.find(absCode); if (it == mSensorsByAbsCode.end()) { ALOGD_IF(DEBUG_MAPPING, "mapSensor: absCode=%d, ~ Failed.", absCode); diff --git a/libs/input/android/hardware/input/InputDeviceCountryCode.aidl b/libs/input/android/hardware/input/InputDeviceCountryCode.aidl new file mode 100644 index 0000000000..6bb1a60dda --- /dev/null +++ b/libs/input/android/hardware/input/InputDeviceCountryCode.aidl @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.input; + +/** + * Constant for HID country code declared by a HID device. These constants are declared as AIDL to + * be used by java and native input code. + * + * @hide + */ +@Backing(type="int") +enum InputDeviceCountryCode { + /** + * Used as default value where country code is not set in the device HID descriptor + */ + INVALID = -1, + + /** + * Used as default value when country code is not supported by the HID device. The HID + * descriptor sets "00" as the country code in this case. + */ + NOT_SUPPORTED = 0, + + /** + * Arabic + */ + ARABIC = 1, + + /** + * Belgian + */ + BELGIAN = 2, + + /** + * Canadian (Bilingual) + */ + CANADIAN_BILINGUAL = 3, + + /** + * Canadian (French) + */ + CANADIAN_FRENCH = 4, + + /** + * Czech Republic + */ + CZECH_REPUBLIC = 5, + + /** + * Danish + */ + DANISH = 6, + + /** + * Finnish + */ + FINNISH = 7, + + /** + * French + */ + FRENCH = 8, + + /** + * German + */ + GERMAN = 9, + + /** + * Greek + */ + GREEK = 10, + + /** + * Hebrew + */ + HEBREW = 11, + + /** + * Hungary + */ + HUNGARY = 12, + + /** + * International (ISO) + */ + INTERNATIONAL = 13, + + /** + * Italian + */ + ITALIAN = 14, + + /** + * Japan (Katakana) + */ + JAPAN = 15, + + /** + * Korean + */ + KOREAN = 16, + + /** + * Latin American + */ + LATIN_AMERICAN = 17, + + /** + * Netherlands (Dutch) + */ + DUTCH = 18, + + /** + * Norwegian + */ + NORWEGIAN = 19, + + /** + * Persian + */ + PERSIAN = 20, + + /** + * Poland + */ + POLAND = 21, + + /** + * Portuguese + */ + PORTUGUESE = 22, + + /** + * Russia + */ + RUSSIA = 23, + + /** + * Slovakia + */ + SLOVAKIA = 24, + + /** + * Spanish + */ + SPANISH = 25, + + /** + * Swedish + */ + SWEDISH = 26, + + /** + * Swiss (French) + */ + SWISS_FRENCH = 27, + + /** + * Swiss (German) + */ + SWISS_GERMAN = 28, + + /** + * Switzerland + */ + SWITZERLAND = 29, + + /** + * Taiwan + */ + TAIWAN = 30, + + /** + * Turkish_Q + */ + TURKISH_Q = 31, + + /** + * UK + */ + UK = 32, + + /** + * US + */ + US = 33, + + /** + * Yugoslavia + */ + YUGOSLAVIA = 34, + + /** + * Turkish_F + */ + TURKISH_F = 35, +}
\ No newline at end of file diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index c7ad058ab9..9d9cb6b2bc 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -63,12 +63,13 @@ void RenderEngine::validateOutputBufferUsage(const sp<GraphicBuffer>& buffer) { "output buffer not gpu writeable"); } -std::future<RenderEngineResult> RenderEngine::drawLayers( - const DisplaySettings& display, const std::vector<LayerSettings>& layers, - const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence) { - const auto resultPromise = std::make_shared<std::promise<RenderEngineResult>>(); - std::future<RenderEngineResult> resultFuture = resultPromise->get_future(); +ftl::Future<FenceResult> RenderEngine::drawLayers(const DisplaySettings& display, + const std::vector<LayerSettings>& layers, + const std::shared_ptr<ExternalTexture>& buffer, + const bool useFramebufferCache, + base::unique_fd&& bufferFence) { + const auto resultPromise = std::make_shared<std::promise<FenceResult>>(); + std::future<FenceResult> resultFuture = resultPromise->get_future(); drawLayersInternal(std::move(resultPromise), display, layers, buffer, useFramebufferCache, std::move(bufferFence)); return resultFuture; diff --git a/libs/renderengine/benchmark/RenderEngineBench.cpp b/libs/renderengine/benchmark/RenderEngineBench.cpp index 7bcfff5348..739f3fa327 100644 --- a/libs/renderengine/benchmark/RenderEngineBench.cpp +++ b/libs/renderengine/benchmark/RenderEngineBench.cpp @@ -159,9 +159,10 @@ static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re, }; auto layers = std::vector<LayerSettings>{layer}; - auto [status, drawFence] = - re.drawLayers(display, layers, texture, kUseFrameBufferCache, base::unique_fd()).get(); - sp<Fence> waitFence = sp<Fence>::make(std::move(drawFence)); + sp<Fence> waitFence = + re.drawLayers(display, layers, texture, kUseFrameBufferCache, base::unique_fd()) + .get() + .value(); waitFence->waitForever(LOG_TAG); return texture; } @@ -190,10 +191,10 @@ static void benchDrawLayers(RenderEngine& re, const std::vector<LayerSettings>& // This loop starts and stops the timer. for (auto _ : benchState) { - auto [status, drawFence] = re.drawLayers(display, layers, outputBuffer, - kUseFrameBufferCache, base::unique_fd()) - .get(); - sp<Fence> waitFence = sp<Fence>::make(std::move(drawFence)); + sp<Fence> waitFence = re.drawLayers(display, layers, outputBuffer, kUseFrameBufferCache, + base::unique_fd()) + .get() + .value(); waitFence->waitForever(LOG_TAG); } diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 9a5ff54ac7..13f766c3e1 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -1081,14 +1081,14 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer } void GLESRenderEngine::drawLayersInternal( - const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise, + const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, const DisplaySettings& display, const std::vector<LayerSettings>& layers, const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); if (layers.empty()) { ALOGV("Drawing empty layer stack"); - resultPromise->set_value({NO_ERROR, base::unique_fd()}); + resultPromise->set_value(Fence::NO_FENCE); return; } @@ -1103,7 +1103,7 @@ void GLESRenderEngine::drawLayersInternal( if (buffer == nullptr) { ALOGE("No output buffer provided. Aborting GPU composition."); - resultPromise->set_value({BAD_VALUE, base::unique_fd()}); + resultPromise->set_value(base::unexpected(BAD_VALUE)); return; } @@ -1132,7 +1132,7 @@ void GLESRenderEngine::drawLayersInternal( ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", buffer->getBuffer()->handle); checkErrors(); - resultPromise->set_value({fbo->getStatus(), base::unique_fd()}); + resultPromise->set_value(base::unexpected(fbo->getStatus())); return; } setViewportAndProjection(display.physicalDisplay, display.clip); @@ -1144,7 +1144,7 @@ void GLESRenderEngine::drawLayersInternal( ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", buffer->getBuffer()->handle); checkErrors(); - resultPromise->set_value({status, base::unique_fd()}); + resultPromise->set_value(base::unexpected(status)); return; } } @@ -1178,7 +1178,7 @@ void GLESRenderEngine::drawLayersInternal( ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", buffer->getBuffer()->handle); checkErrors("Can't render first blur pass"); - resultPromise->set_value({status, base::unique_fd()}); + resultPromise->set_value(base::unexpected(status)); return; } @@ -1201,7 +1201,7 @@ void GLESRenderEngine::drawLayersInternal( ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", buffer->getBuffer()->handle); checkErrors("Can't bind native framebuffer"); - resultPromise->set_value({status, base::unique_fd()}); + resultPromise->set_value(base::unexpected(status)); return; } @@ -1210,7 +1210,7 @@ void GLESRenderEngine::drawLayersInternal( ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", buffer->getBuffer()->handle); checkErrors("Can't render blur filter"); - resultPromise->set_value({status, base::unique_fd()}); + resultPromise->set_value(base::unexpected(status)); return; } } @@ -1310,7 +1310,7 @@ void GLESRenderEngine::drawLayersInternal( checkErrors(); // Chances are, something illegal happened (either the caller passed // us bad parameters, or we messed up our shader generation). - resultPromise->set_value({INVALID_OPERATION, std::move(drawFence)}); + resultPromise->set_value(base::unexpected(INVALID_OPERATION)); return; } mLastDrawFence = nullptr; @@ -1322,8 +1322,7 @@ void GLESRenderEngine::drawLayersInternal( mPriorResourcesCleaned = false; checkErrors(); - resultPromise->set_value({NO_ERROR, std::move(drawFence)}); - return; + resultPromise->set_value(sp<Fence>::make(std::move(drawFence))); } void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) { diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index 1d7c2cafb5..1ee5cbaa3d 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -31,6 +31,7 @@ #include <renderengine/RenderEngine.h> #include <renderengine/private/Description.h> #include <sys/types.h> +#include <ui/FenceResult.h> #include "GLShadowTexture.h" #include "ImageManager.h" @@ -102,7 +103,7 @@ protected: EXCLUDES(mRenderingMutex); void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) EXCLUDES(mRenderingMutex); bool canSkipPostRenderCleanup() const override; - void drawLayersInternal(const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise, + void drawLayersInternal(const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, const DisplaySettings& display, const std::vector<LayerSettings>& layers, const std::shared_ptr<ExternalTexture>& buffer, diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 3e7f69ce02..199392c160 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -18,6 +18,7 @@ #define SF_RENDERENGINE_H_ #include <android-base/unique_fd.h> +#include <ftl/future.h> #include <math/mat4.h> #include <renderengine/DisplaySettings.h> #include <renderengine/ExternalTexture.h> @@ -26,6 +27,7 @@ #include <renderengine/LayerSettings.h> #include <stdint.h> #include <sys/types.h> +#include <ui/FenceResult.h> #include <ui/GraphicTypes.h> #include <ui/Transform.h> @@ -68,7 +70,6 @@ class Image; class Mesh; class Texture; struct RenderEngineCreationArgs; -struct RenderEngineResult; namespace threaded { class RenderEngineThreaded; @@ -158,12 +159,13 @@ public: // parameter does nothing. // @param bufferFence Fence signalling that the buffer is ready to be drawn // to. - // @return A future object of RenderEngineResult struct indicating whether - // drawing was successful in async mode. - virtual std::future<RenderEngineResult> drawLayers( - const DisplaySettings& display, const std::vector<LayerSettings>& layers, - const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence); + // @return A future object of FenceResult indicating whether drawing was + // successful in async mode. + virtual ftl::Future<FenceResult> drawLayers(const DisplaySettings& display, + const std::vector<LayerSettings>& layers, + const std::shared_ptr<ExternalTexture>& buffer, + const bool useFramebufferCache, + base::unique_fd&& bufferFence); // Clean-up method that should be called on the main thread after the // drawFence returned by drawLayers fires. This method will free up @@ -237,7 +239,7 @@ protected: const RenderEngineType mRenderEngineType; virtual void drawLayersInternal( - const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise, + const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, const DisplaySettings& display, const std::vector<LayerSettings>& layers, const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) = 0; @@ -327,13 +329,6 @@ private: RenderEngine::RenderEngineType::SKIA_GL_THREADED; }; -struct RenderEngineResult { - // status indicates if drawing is successful - status_t status; - // drawFence will fire when the buffer has been drawn to and is ready to be examined. - base::unique_fd drawFence; -}; - } // namespace renderengine } // namespace android diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index 248bd652c0..e3ce85dd07 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -48,14 +48,13 @@ public: MOCK_METHOD0(cleanupPostRender, void()); MOCK_CONST_METHOD0(canSkipPostRenderCleanup, bool()); MOCK_METHOD5(drawLayers, - std::future<RenderEngineResult>(const DisplaySettings&, - const std::vector<LayerSettings>&, - const std::shared_ptr<ExternalTexture>&, - const bool, base::unique_fd&&)); + ftl::Future<FenceResult>(const DisplaySettings&, const std::vector<LayerSettings>&, + const std::shared_ptr<ExternalTexture>&, const bool, + base::unique_fd&&)); MOCK_METHOD6(drawLayersInternal, - void(const std::shared_ptr<std::promise<RenderEngineResult>>&&, - const DisplaySettings&, const std::vector<LayerSettings>&, - const std::shared_ptr<ExternalTexture>&, const bool, base::unique_fd&&)); + void(const std::shared_ptr<std::promise<FenceResult>>&&, const DisplaySettings&, + const std::vector<LayerSettings>&, const std::shared_ptr<ExternalTexture>&, + const bool, base::unique_fd&&)); MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); MOCK_METHOD0(supportsBackgroundBlur, bool()); diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index db983a81d4..b9aa5acd30 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -632,7 +632,7 @@ private: }; void SkiaRenderEngine::drawLayersInternal( - const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise, + const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, const DisplaySettings& display, const std::vector<LayerSettings>& layers, const std::shared_ptr<ExternalTexture>& buffer, const bool /*useFramebufferCache*/, base::unique_fd&& bufferFence) { @@ -642,7 +642,7 @@ void SkiaRenderEngine::drawLayersInternal( if (buffer == nullptr) { ALOGE("No output buffer provided. Aborting GPU composition."); - resultPromise->set_value({BAD_VALUE, base::unique_fd()}); + resultPromise->set_value(base::unexpected(BAD_VALUE)); return; } @@ -675,7 +675,7 @@ void SkiaRenderEngine::drawLayersInternal( SkCanvas* dstCanvas = mCapture->tryCapture(dstSurface.get()); if (dstCanvas == nullptr) { ALOGE("Cannot acquire canvas from Skia."); - resultPromise->set_value({BAD_VALUE, base::unique_fd()}); + resultPromise->set_value(base::unexpected(BAD_VALUE)); return; } @@ -1126,8 +1126,7 @@ void SkiaRenderEngine::drawLayersInternal( } base::unique_fd drawFence = flushAndSubmit(grContext); - resultPromise->set_value({NO_ERROR, std::move(drawFence)}); - return; + resultPromise->set_value(sp<Fence>::make(std::move(drawFence))); } size_t SkiaRenderEngine::getMaxTextureSize() const { diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index a5cd278d4f..e7c5b8f0ab 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -135,7 +135,7 @@ private: void initCanvas(SkCanvas* canvas, const DisplaySettings& display); void drawShadow(SkCanvas* canvas, const SkRRect& casterRRect, const ShadowSettings& shadowSettings); - void drawLayersInternal(const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise, + void drawLayersInternal(const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, const DisplaySettings& display, const std::vector<LayerSettings>& layers, const std::shared_ptr<ExternalTexture>& buffer, diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index d23063c84d..9d8b2df98a 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -528,16 +528,15 @@ public: void invokeDraw(const renderengine::DisplaySettings& settings, const std::vector<renderengine::LayerSettings>& layers) { - std::future<renderengine::RenderEngineResult> result = + ftl::Future<FenceResult> future = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); + ASSERT_TRUE(future.valid()); - ASSERT_TRUE(result.valid()); - auto [status, fence] = result.get(); + auto result = future.get(); + ASSERT_TRUE(result.ok()); - ASSERT_EQ(NO_ERROR, status); - if (fence.ok()) { - sync_wait(fence.get(), -1); - } + auto fence = result.value(); + fence->waitForever(LOG_TAG); if (layers.size() > 0 && mGLESRE != nullptr) { ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); @@ -1681,13 +1680,13 @@ TEST_P(RenderEngineTest, drawLayers_nullOutputBuffer) { layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layers.push_back(layer); - std::future<renderengine::RenderEngineResult> result = + ftl::Future<FenceResult> future = mRE->drawLayers(settings, layers, nullptr, true, base::unique_fd()); - ASSERT_TRUE(result.valid()); - auto [status, fence] = result.get(); - ASSERT_EQ(BAD_VALUE, status); - ASSERT_FALSE(fence.ok()); + ASSERT_TRUE(future.valid()); + auto result = future.get(); + ASSERT_FALSE(result.ok()); + ASSERT_EQ(BAD_VALUE, result.error()); } TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { @@ -1712,15 +1711,14 @@ TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { layer.alpha = 1.0; layers.push_back(layer); - std::future<renderengine::RenderEngineResult> result = + ftl::Future<FenceResult> future = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd()); - ASSERT_TRUE(result.valid()); - auto [status, fence] = result.get(); + ASSERT_TRUE(future.valid()); + auto result = future.get(); - ASSERT_EQ(NO_ERROR, status); - if (fence.ok()) { - sync_wait(fence.get(), -1); - } + ASSERT_TRUE(result.ok()); + auto fence = result.value(); + fence->waitForever(LOG_TAG); ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); expectBufferColor(fullscreenRect(), 255, 0, 0, 255); @@ -2219,20 +2217,20 @@ TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) { layer.alpha = 1.0; layers.push_back(layer); - std::future<renderengine::RenderEngineResult> resultOne = + ftl::Future<FenceResult> futureOne = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); - ASSERT_TRUE(resultOne.valid()); - auto [statusOne, fenceOne] = resultOne.get(); - ASSERT_EQ(NO_ERROR, statusOne); - - std::future<renderengine::RenderEngineResult> resultTwo = - mRE->drawLayers(settings, layers, mBuffer, true, std::move(fenceOne)); - ASSERT_TRUE(resultTwo.valid()); - auto [statusTwo, fenceTwo] = resultTwo.get(); - ASSERT_EQ(NO_ERROR, statusTwo); - if (fenceTwo.ok()) { - sync_wait(fenceTwo.get(), -1); - } + ASSERT_TRUE(futureOne.valid()); + auto resultOne = futureOne.get(); + ASSERT_TRUE(resultOne.ok()); + auto fenceOne = resultOne.value(); + + ftl::Future<FenceResult> futureTwo = + mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(fenceOne->dup())); + ASSERT_TRUE(futureTwo.valid()); + auto resultTwo = futureTwo.get(); + ASSERT_TRUE(resultTwo.ok()); + auto fenceTwo = resultTwo.value(); + fenceTwo->waitForever(LOG_TAG); // Only cleanup the first time. EXPECT_FALSE(mRE->canSkipPostRenderCleanup()); diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index 909ded3a78..1a96289bc0 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -183,20 +183,17 @@ TEST_F(RenderEngineThreadedTest, drawLayers) { base::unique_fd bufferFence; EXPECT_CALL(*mRenderEngine, drawLayersInternal) - .WillOnce([&](const std::shared_ptr<std::promise<renderengine::RenderEngineResult>>&& - resultPromise, + .WillOnce([&](const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, const renderengine::DisplaySettings&, const std::vector<renderengine::LayerSettings>&, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> void { - resultPromise->set_value({NO_ERROR, base::unique_fd()}); - }); + base::unique_fd&&) { resultPromise->set_value(Fence::NO_FENCE); }); - std::future<renderengine::RenderEngineResult> result = + ftl::Future<FenceResult> future = mThreadedRE->drawLayers(settings, layers, buffer, false, std::move(bufferFence)); - ASSERT_TRUE(result.valid()); - auto [status, _] = result.get(); - ASSERT_EQ(NO_ERROR, status); + ASSERT_TRUE(future.valid()); + auto result = future.get(); + ASSERT_TRUE(result.ok()); } } // namespace android diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index 203bb54701..b41e8432a9 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -313,21 +313,21 @@ bool RenderEngineThreaded::canSkipPostRenderCleanup() const { } void RenderEngineThreaded::drawLayersInternal( - const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise, + const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, const DisplaySettings& display, const std::vector<LayerSettings>& layers, const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { - resultPromise->set_value({NO_ERROR, base::unique_fd()}); + resultPromise->set_value(Fence::NO_FENCE); return; } -std::future<RenderEngineResult> RenderEngineThreaded::drawLayers( +ftl::Future<FenceResult> RenderEngineThreaded::drawLayers( const DisplaySettings& display, const std::vector<LayerSettings>& layers, const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); - const auto resultPromise = std::make_shared<std::promise<RenderEngineResult>>(); - std::future<RenderEngineResult> resultFuture = resultPromise->get_future(); + const auto resultPromise = std::make_shared<std::promise<FenceResult>>(); + std::future<FenceResult> resultFuture = resultPromise->get_future(); int fd = bufferFence.release(); { std::lock_guard lock(mThreadMutex); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 1340902126..bf2ebea2a0 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -56,11 +56,11 @@ public: void useProtectedContext(bool useProtectedContext) override; void cleanupPostRender() override; - std::future<RenderEngineResult> drawLayers(const DisplaySettings& display, - const std::vector<LayerSettings>& layers, - const std::shared_ptr<ExternalTexture>& buffer, - const bool useFramebufferCache, - base::unique_fd&& bufferFence) override; + ftl::Future<FenceResult> drawLayers(const DisplaySettings& display, + const std::vector<LayerSettings>& layers, + const std::shared_ptr<ExternalTexture>& buffer, + const bool useFramebufferCache, + base::unique_fd&& bufferFence) override; void cleanFramebufferCache() override; int getContextPriority() override; @@ -73,7 +73,7 @@ protected: void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override; void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) override; bool canSkipPostRenderCleanup() const override; - void drawLayersInternal(const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise, + void drawLayersInternal(const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, const DisplaySettings& display, const std::vector<LayerSettings>& layers, const std::shared_ptr<ExternalTexture>& buffer, diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h b/libs/ui/include/ui/FenceResult.h index 0ce263b930..6d63fc9973 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h +++ b/libs/ui/include/ui/FenceResult.h @@ -20,30 +20,14 @@ #include <utils/Errors.h> #include <utils/StrongPointer.h> -// TODO(b/232535621): Pull this file to <ui/FenceResult.h> so that RenderEngine::drawLayers returns -// FenceResult rather than RenderEngineResult. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#include <renderengine/RenderEngine.h> -#pragma clang diagnostic pop - namespace android { class Fence; using FenceResult = base::expected<sp<Fence>, status_t>; -// TODO(b/232535621): Prevent base::unexpected(NO_ERROR) from being a valid FenceResult. inline status_t fenceStatus(const FenceResult& fenceResult) { return fenceResult.ok() ? NO_ERROR : fenceResult.error(); } -inline FenceResult toFenceResult(renderengine::RenderEngineResult&& result) { - if (auto [status, fence] = std::move(result); fence.ok()) { - return sp<Fence>::make(std::move(fence)); - } else { - return base::unexpected(status); - } -} - } // namespace android diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index bfa44acd17..336763c3c3 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -52,6 +52,7 @@ #include <filesystem> #include <regex> +#include <utility> #include "EventHub.h" @@ -60,6 +61,7 @@ #define INDENT3 " " using android::base::StringPrintf; +using android::hardware::input::InputDeviceCountryCode; namespace android { @@ -193,8 +195,7 @@ static nsecs_t processEventTimestamp(const struct input_event& event) { } /** - * Returns the sysfs root path of the input device - * + * Returns the sysfs root path of the input device. */ static std::optional<std::filesystem::path> getSysfsRootPath(const char* devicePath) { std::error_code errorCode; @@ -301,6 +302,101 @@ static std::optional<std::array<LightColor, COLOR_NUM>> getColorIndexArray( return colors; } +/** + * Read country code information exposed through the sysfs path. + */ +static InputDeviceCountryCode readCountryCodeLocked(const std::filesystem::path& sysfsRootPath) { + // Check the sysfs root path + int hidCountryCode = static_cast<int>(InputDeviceCountryCode::INVALID); + std::string str; + if (base::ReadFileToString(sysfsRootPath / "country", &str)) { + hidCountryCode = std::stoi(str, nullptr, 16); + LOG_ALWAYS_FATAL_IF(hidCountryCode > 35 || hidCountryCode < 0, + "HID country code should be in range [0, 35]. Found country code " + "to be %d", + hidCountryCode); + } + + return static_cast<InputDeviceCountryCode>(hidCountryCode); +} + +/** + * Read information about batteries exposed through the sysfs path. + */ +static std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> readBatteryConfiguration( + const std::filesystem::path& sysfsRootPath) { + std::unordered_map<int32_t, RawBatteryInfo> batteryInfos; + int32_t nextBatteryId = 0; + // Check if device has any battery. + const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::POWER_SUPPLY); + for (const auto& nodePath : paths) { + RawBatteryInfo info; + info.id = ++nextBatteryId; + info.path = nodePath; + info.name = nodePath.filename(); + + // Scan the path for all the files + // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt + const auto& files = allFilesInPath(nodePath); + for (const auto& file : files) { + const auto it = BATTERY_CLASSES.find(file.filename().string()); + if (it != BATTERY_CLASSES.end()) { + info.flags |= it->second; + } + } + batteryInfos.insert_or_assign(info.id, info); + ALOGD("configureBatteryLocked rawBatteryId %d name %s", info.id, info.name.c_str()); + } + return batteryInfos; +} + +/** + * Read information about lights exposed through the sysfs path. + */ +static std::unordered_map<int32_t /*lightId*/, RawLightInfo> readLightsConfiguration( + const std::filesystem::path& sysfsRootPath) { + std::unordered_map<int32_t, RawLightInfo> lightInfos; + int32_t nextLightId = 0; + // Check if device has any lights. + const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS); + for (const auto& nodePath : paths) { + RawLightInfo info; + info.id = ++nextLightId; + info.path = nodePath; + info.name = nodePath.filename(); + info.maxBrightness = std::nullopt; + size_t nameStart = info.name.rfind(":"); + if (nameStart != std::string::npos) { + // Trim the name to color name + info.name = info.name.substr(nameStart + 1); + // Set InputLightClass flag for colors + const auto it = LIGHT_CLASSES.find(info.name); + if (it != LIGHT_CLASSES.end()) { + info.flags |= it->second; + } + } + // Scan the path for all the files + // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt + const auto& files = allFilesInPath(nodePath); + for (const auto& file : files) { + const auto it = LIGHT_CLASSES.find(file.filename().string()); + if (it != LIGHT_CLASSES.end()) { + info.flags |= it->second; + // If the node has maximum brightness, read it + if (it->second == InputLightClass::MAX_BRIGHTNESS) { + std::string str; + if (base::ReadFileToString(file, &str)) { + info.maxBrightness = std::stoi(str); + } + } + } + } + lightInfos.insert_or_assign(info.id, info); + ALOGD("configureLightsLocked rawLightId %d name %s", info.id, info.name.c_str()); + } + return lightInfos; +} + // --- Global Functions --- ftl::Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, @@ -357,18 +453,18 @@ ftl::Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, // --- EventHub::Device --- -EventHub::Device::Device(int fd, int32_t id, const std::string& path, - const InputDeviceIdentifier& identifier) +EventHub::Device::Device(int fd, int32_t id, std::string path, InputDeviceIdentifier identifier, + std::shared_ptr<const AssociatedDevice> assocDev) : fd(fd), id(id), - path(path), - identifier(identifier), + path(std::move(path)), + identifier(std::move(identifier)), classes(0), configuration(nullptr), virtualKeyMap(nullptr), ffEffectPlaying(false), ffEffectId(-1), - associatedDevice(nullptr), + associatedDevice(std::move(assocDev)), controllerNumber(0), enabled(true), isVirtual(fd < 0) {} @@ -557,75 +653,6 @@ status_t EventHub::Device::mapLed(int32_t led, int32_t* outScanCode) const { return NAME_NOT_FOUND; } -// Check the sysfs path for any input device batteries, returns true if battery found. -bool EventHub::AssociatedDevice::configureBatteryLocked() { - nextBatteryId = 0; - // Check if device has any battery. - const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::POWER_SUPPLY); - for (const auto& nodePath : paths) { - RawBatteryInfo info; - info.id = ++nextBatteryId; - info.path = nodePath; - info.name = nodePath.filename(); - - // Scan the path for all the files - // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt - const auto& files = allFilesInPath(nodePath); - for (const auto& file : files) { - const auto it = BATTERY_CLASSES.find(file.filename().string()); - if (it != BATTERY_CLASSES.end()) { - info.flags |= it->second; - } - } - batteryInfos.insert_or_assign(info.id, info); - ALOGD("configureBatteryLocked rawBatteryId %d name %s", info.id, info.name.c_str()); - } - return !batteryInfos.empty(); -} - -// Check the sysfs path for any input device lights, returns true if lights found. -bool EventHub::AssociatedDevice::configureLightsLocked() { - nextLightId = 0; - // Check if device has any lights. - const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS); - for (const auto& nodePath : paths) { - RawLightInfo info; - info.id = ++nextLightId; - info.path = nodePath; - info.name = nodePath.filename(); - info.maxBrightness = std::nullopt; - size_t nameStart = info.name.rfind(":"); - if (nameStart != std::string::npos) { - // Trim the name to color name - info.name = info.name.substr(nameStart + 1); - // Set InputLightClass flag for colors - const auto it = LIGHT_CLASSES.find(info.name); - if (it != LIGHT_CLASSES.end()) { - info.flags |= it->second; - } - } - // Scan the path for all the files - // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt - const auto& files = allFilesInPath(nodePath); - for (const auto& file : files) { - const auto it = LIGHT_CLASSES.find(file.filename().string()); - if (it != LIGHT_CLASSES.end()) { - info.flags |= it->second; - // If the node has maximum brightness, read it - if (it->second == InputLightClass::MAX_BRIGHTNESS) { - std::string str; - if (base::ReadFileToString(file, &str)) { - info.maxBrightness = std::stoi(str); - } - } - } - } - lightInfos.insert_or_assign(info.id, info); - ALOGD("configureLightsLocked rawLightId %d name %s", info.id, info.name.c_str()); - } - return !lightInfos.empty(); -} - /** * Get the capabilities for the current process. * Crashes the system if unable to create / check / destroy the capabilities object. @@ -1034,7 +1061,7 @@ status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxis } base::Result<std::pair<InputDeviceSensorType, int32_t>> EventHub::mapSensor(int32_t deviceId, - int32_t absCode) { + int32_t absCode) const { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); @@ -1056,18 +1083,19 @@ const std::unordered_map<int32_t, RawBatteryInfo>& EventHub::getBatteryInfoLocke return device->associatedDevice->batteryInfos; } -const std::vector<int32_t> EventHub::getRawBatteryIds(int32_t deviceId) { +std::vector<int32_t> EventHub::getRawBatteryIds(int32_t deviceId) const { std::scoped_lock _l(mLock); std::vector<int32_t> batteryIds; - for (const auto [id, info] : getBatteryInfoLocked(deviceId)) { + for (const auto& [id, info] : getBatteryInfoLocked(deviceId)) { batteryIds.push_back(id); } return batteryIds; } -std::optional<RawBatteryInfo> EventHub::getRawBatteryInfo(int32_t deviceId, int32_t batteryId) { +std::optional<RawBatteryInfo> EventHub::getRawBatteryInfo(int32_t deviceId, + int32_t batteryId) const { std::scoped_lock _l(mLock); const auto infos = getBatteryInfoLocked(deviceId); @@ -1081,7 +1109,7 @@ std::optional<RawBatteryInfo> EventHub::getRawBatteryInfo(int32_t deviceId, int3 } // Gets the light info map from light ID to RawLightInfo of the miscellaneous device associated -// with the deivice ID. Returns an empty map if no miscellaneous device found. +// with the device ID. Returns an empty map if no miscellaneous device found. const std::unordered_map<int32_t, RawLightInfo>& EventHub::getLightInfoLocked( int32_t deviceId) const { static const std::unordered_map<int32_t, RawLightInfo> EMPTY_LIGHT_INFO = {}; @@ -1092,18 +1120,18 @@ const std::unordered_map<int32_t, RawLightInfo>& EventHub::getLightInfoLocked( return device->associatedDevice->lightInfos; } -const std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) { +std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) const { std::scoped_lock _l(mLock); std::vector<int32_t> lightIds; - for (const auto [id, info] : getLightInfoLocked(deviceId)) { + for (const auto& [id, info] : getLightInfoLocked(deviceId)) { lightIds.push_back(id); } return lightIds; } -std::optional<RawLightInfo> EventHub::getRawLightInfo(int32_t deviceId, int32_t lightId) { +std::optional<RawLightInfo> EventHub::getRawLightInfo(int32_t deviceId, int32_t lightId) const { std::scoped_lock _l(mLock); const auto infos = getLightInfoLocked(deviceId); @@ -1116,7 +1144,7 @@ std::optional<RawLightInfo> EventHub::getRawLightInfo(int32_t deviceId, int32_t return std::nullopt; } -std::optional<int32_t> EventHub::getLightBrightness(int32_t deviceId, int32_t lightId) { +std::optional<int32_t> EventHub::getLightBrightness(int32_t deviceId, int32_t lightId) const { std::scoped_lock _l(mLock); const auto infos = getLightInfoLocked(deviceId); @@ -1133,7 +1161,7 @@ std::optional<int32_t> EventHub::getLightBrightness(int32_t deviceId, int32_t li } std::optional<std::unordered_map<LightColor, int32_t>> EventHub::getLightIntensities( - int32_t deviceId, int32_t lightId) { + int32_t deviceId, int32_t lightId) const { std::scoped_lock _l(mLock); const auto infos = getLightInfoLocked(deviceId); @@ -1229,6 +1257,15 @@ void EventHub::setLightIntensities(int32_t deviceId, int32_t lightId, } } +InputDeviceCountryCode EventHub::getCountryCode(int32_t deviceId) const { + std::scoped_lock _l(mLock); + Device* device = getDeviceLocked(deviceId); + if (device == nullptr || !device->associatedDevice) { + return InputDeviceCountryCode::INVALID; + } + return device->associatedDevice->countryCode; +} + void EventHub::setExcludedDevices(const std::vector<std::string>& devices) { std::scoped_lock _l(mLock); @@ -1358,6 +1395,28 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) { identifier.descriptor.c_str()); } +std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDeviceLocked( + const std::filesystem::path& devicePath) const { + const std::optional<std::filesystem::path> sysfsRootPathOpt = + getSysfsRootPath(devicePath.c_str()); + if (!sysfsRootPathOpt) { + return nullptr; + } + + const auto& path = *sysfsRootPathOpt; + for (const auto& [id, dev] : mDevices) { + if (dev->associatedDevice && dev->associatedDevice->sysfsRootPath == path) { + return dev->associatedDevice; + } + } + + return std::make_shared<AssociatedDevice>( + AssociatedDevice{.sysfsRootPath = path, + .countryCode = readCountryCodeLocked(path), + .batteryInfos = readBatteryConfiguration(path), + .lightInfos = readLightsConfiguration(path)}); +} + void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); @@ -1415,7 +1474,7 @@ void EventHub::cancelVibrate(int32_t deviceId) { } } -std::vector<int32_t> EventHub::getVibratorIds(int32_t deviceId) { +std::vector<int32_t> EventHub::getVibratorIds(int32_t deviceId) const { std::scoped_lock _l(mLock); std::vector<int32_t> vibrators; Device* device = getDeviceLocked(deviceId); @@ -2024,7 +2083,9 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { // Allocate device. (The device object takes ownership of the fd at this point.) int32_t deviceId = mNextDeviceId++; - std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier); + std::unique_ptr<Device> device = + std::make_unique<Device>(fd, deviceId, devicePath, identifier, + obtainAssociatedDeviceLocked(devicePath)); ALOGV("add device %d: %s\n", deviceId, devicePath.c_str()); ALOGV(" bus: %04x\n" @@ -2042,27 +2103,6 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { // Load the configuration file for the device. device->loadConfigurationLocked(); - bool hasBattery = false; - bool hasLights = false; - // Check the sysfs root path - std::optional<std::filesystem::path> sysfsRootPath = getSysfsRootPath(devicePath.c_str()); - if (sysfsRootPath.has_value()) { - std::shared_ptr<AssociatedDevice> associatedDevice; - for (const auto& [id, dev] : mDevices) { - if (device->identifier.descriptor == dev->identifier.descriptor && - !dev->associatedDevice) { - associatedDevice = dev->associatedDevice; - } - } - if (!associatedDevice) { - associatedDevice = std::make_shared<AssociatedDevice>(sysfsRootPath.value()); - } - hasBattery = associatedDevice->configureBatteryLocked(); - hasLights = associatedDevice->configureLightsLocked(); - - device->associatedDevice = associatedDevice; - } - // Figure out the kinds of events the device reports. device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask); @@ -2212,12 +2252,12 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { } // Classify InputDeviceClass::BATTERY. - if (hasBattery) { + if (device->associatedDevice && !device->associatedDevice->batteryInfos.empty()) { device->classes |= InputDeviceClass::BATTERY; } // Classify InputDeviceClass::LIGHT. - if (hasLights) { + if (device->associatedDevice && !device->associatedDevice->lightInfos.empty()) { device->classes |= InputDeviceClass::LIGHT; } @@ -2285,7 +2325,7 @@ bool EventHub::tryAddVideoDeviceLocked(EventHub::Device& device, return true; } -bool EventHub::isDeviceEnabled(int32_t deviceId) { +bool EventHub::isDeviceEnabled(int32_t deviceId) const { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr) { @@ -2340,7 +2380,7 @@ void EventHub::createVirtualKeyboardLocked() { std::unique_ptr<Device> device = std::make_unique<Device>(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>", - identifier); + identifier, nullptr /*associatedDevice*/); device->classes = InputDeviceClass::KEYBOARD | InputDeviceClass::ALPHAKEY | InputDeviceClass::DPAD | InputDeviceClass::VIRTUAL; device->loadKeyMapLocked(); @@ -2509,7 +2549,7 @@ void EventHub::requestReopenDevices() { mNeedToReopenDevices = true; } -void EventHub::dump(std::string& dump) { +void EventHub::dump(std::string& dump) const { dump += "Event Hub State:\n"; { // acquire lock @@ -2542,14 +2582,18 @@ void EventHub::dump(std::string& dump) { device->keyMap.keyLayoutFile.c_str()); dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n", device->keyMap.keyCharacterMapFile.c_str()); + dump += StringPrintf(INDENT3 "CountryCode: %d\n", + device->associatedDevice ? device->associatedDevice->countryCode + : InputDeviceCountryCode::INVALID); dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n", device->configurationFile.c_str()); - dump += INDENT3 "VideoDevice: "; - if (device->videoDevice) { - dump += device->videoDevice->dump() + "\n"; - } else { - dump += "<none>\n"; - } + dump += StringPrintf(INDENT3 "VideoDevice: %s\n", + device->videoDevice ? device->videoDevice->dump().c_str() + : "<none>"); + dump += StringPrintf(INDENT3 "SysfsDevicePath: %s\n", + device->associatedDevice + ? device->associatedDevice->sysfsRootPath.c_str() + : "<none>"); } dump += INDENT "Unattached video devices:\n"; @@ -2562,9 +2606,9 @@ void EventHub::dump(std::string& dump) { } // release lock } -void EventHub::monitor() { +void EventHub::monitor() const { // Acquire and release the lock to ensure that the event hub has not deadlocked. std::unique_lock<std::mutex> lock(mLock); } -}; // namespace android +} // namespace android diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 5c9e63e80e..8eadcdcda8 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -35,6 +35,8 @@ #include "SwitchInputMapper.h" #include "VibratorInputMapper.h" +using android::hardware::input::InputDeviceCountryCode; + namespace android { InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation, @@ -240,6 +242,7 @@ void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config mSources = 0; mClasses = ftl::Flags<InputDeviceClass>(0); mControllerNumber = 0; + mCountryCode = InputDeviceCountryCode::INVALID; for_each_subdevice([this](InputDeviceContext& context) { mClasses |= context.getDeviceClasses(); @@ -251,6 +254,16 @@ void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config } mControllerNumber = controllerNumber; } + + InputDeviceCountryCode countryCode = context.getCountryCode(); + if (countryCode != InputDeviceCountryCode::INVALID) { + if (mCountryCode != InputDeviceCountryCode::INVALID && mCountryCode != countryCode) { + ALOGW("InputDevice::configure(): %s device contains multiple unique country " + "codes", + getName().c_str()); + } + mCountryCode = countryCode; + } }); mIsExternal = mClasses.test(InputDeviceClass::EXTERNAL); @@ -422,7 +435,7 @@ void InputDevice::updateExternalStylusState(const StylusState& state) { InputDeviceInfo InputDevice::getDeviceInfo() { InputDeviceInfo outDeviceInfo; outDeviceInfo.initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal, - mHasMic); + mHasMic, mCountryCode); for_each_mapper( [&outDeviceInfo](InputMapper& mapper) { mapper.populateDeviceInfo(&outDeviceInfo); }); diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 4733ecb323..dfb98f14c5 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -21,6 +21,7 @@ #include <climits> #include <filesystem> #include <unordered_map> +#include <utility> #include <vector> #include <batteryservice/BatteryService.h> @@ -42,6 +43,7 @@ #include "TouchVideoDevice.h" #include "VibrationElement.h" +#include "android/hardware/input/InputDeviceCountryCode.h" struct inotify_event; @@ -281,27 +283,28 @@ public: */ virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0; virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0; - virtual base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId, - int32_t absCode) = 0; + virtual base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor( + int32_t deviceId, int32_t absCode) const = 0; // Raw batteries are sysfs power_supply nodes we found from the EventHub device sysfs node, // containing the raw info of the sysfs node structure. - virtual const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) = 0; + virtual std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const = 0; virtual std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, - int32_t BatteryId) = 0; + int32_t BatteryId) const = 0; // Raw lights are sysfs led light nodes we found from the EventHub device sysfs node, // containing the raw info of the sysfs node structure. - virtual const std::vector<int32_t> getRawLightIds(int32_t deviceId) = 0; - virtual std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) = 0; - virtual std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) = 0; + virtual std::vector<int32_t> getRawLightIds(int32_t deviceId) const = 0; + virtual std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, + int32_t lightId) const = 0; + virtual std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) const = 0; virtual void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) = 0; virtual std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities( - int32_t deviceId, int32_t lightId) = 0; + int32_t deviceId, int32_t lightId) const = 0; virtual void setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map<LightColor, int32_t> intensities) = 0; - /* - * Query current input state. - */ + /* Query Country code associated with the input device. */ + virtual hardware::input::InputDeviceCountryCode getCountryCode(int32_t deviceId) const = 0; + /* Query current input state. */ virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0; virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0; virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0; @@ -332,7 +335,7 @@ public: /* Control the vibrator. */ virtual void vibrate(int32_t deviceId, const VibrationElement& effect) = 0; virtual void cancelVibrate(int32_t deviceId) = 0; - virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0; + virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) const = 0; /* Query battery level. */ virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId, @@ -348,13 +351,13 @@ public: virtual void wake() = 0; /* Dump EventHub state to a string. */ - virtual void dump(std::string& dump) = 0; + virtual void dump(std::string& dump) const = 0; /* Called by the heatbeat to ensures that the reader has not deadlocked. */ - virtual void monitor() = 0; + virtual void monitor() const = 0; /* Return true if the device is enabled. */ - virtual bool isDeviceEnabled(int32_t deviceId) = 0; + virtual bool isDeviceEnabled(int32_t deviceId) const = 0; /* Enable an input device */ virtual status_t enableDevice(int32_t deviceId) = 0; @@ -462,23 +465,27 @@ public: AxisInfo* outAxisInfo) const override final; base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor( - int32_t deviceId, int32_t absCode) override final; + int32_t deviceId, int32_t absCode) const override final; - const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) override final; + std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const override final; std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, - int32_t BatteryId) override final; + int32_t BatteryId) const override final; - const std::vector<int32_t> getRawLightIds(int32_t deviceId) override final; + std::vector<int32_t> getRawLightIds(int32_t deviceId) const override final; - std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override final; + std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, + int32_t lightId) const override final; - std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override final; + std::optional<int32_t> getLightBrightness(int32_t deviceId, + int32_t lightId) const override final; void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override final; std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities( - int32_t deviceId, int32_t lightId) override final; + int32_t deviceId, int32_t lightId) const override final; void setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map<LightColor, int32_t> intensities) override final; + hardware::input::InputDeviceCountryCode getCountryCode(int32_t deviceId) const override final; + void setExcludedDevices(const std::vector<std::string>& devices) override final; int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override final; @@ -511,15 +518,15 @@ public: void vibrate(int32_t deviceId, const VibrationElement& effect) override final; void cancelVibrate(int32_t deviceId) override final; - std::vector<int32_t> getVibratorIds(int32_t deviceId) override final; + std::vector<int32_t> getVibratorIds(int32_t deviceId) const override final; void requestReopenDevices() override final; void wake() override final; - void dump(std::string& dump) override final; + void dump(std::string& dump) const override final; - void monitor() override final; + void monitor() const override final; std::optional<int32_t> getBatteryCapacity(int32_t deviceId, int32_t batteryId) const override final; @@ -527,7 +534,7 @@ public: std::optional<int32_t> getBatteryStatus(int32_t deviceId, int32_t batteryId) const override final; - bool isDeviceEnabled(int32_t deviceId) override final; + bool isDeviceEnabled(int32_t deviceId) const override final; status_t enableDevice(int32_t deviceId) override final; @@ -536,20 +543,13 @@ public: ~EventHub() override; private: + // Holds information about the sysfs device associated with the Device. struct AssociatedDevice { - // The device descriptor from evdev device the misc device associated with. - std::string descriptor; // The sysfs root path of the misc device. std::filesystem::path sysfsRootPath; - - int32_t nextBatteryId; - int32_t nextLightId; - std::unordered_map<int32_t, RawBatteryInfo> batteryInfos; - std::unordered_map<int32_t, RawLightInfo> lightInfos; - explicit AssociatedDevice(std::filesystem::path sysfsRootPath) - : sysfsRootPath(sysfsRootPath), nextBatteryId(0), nextLightId(0) {} - bool configureBatteryLocked(); - bool configureLightsLocked(); + hardware::input::InputDeviceCountryCode countryCode; + std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> batteryInfos; + std::unordered_map<int32_t /*lightId*/, RawLightInfo> lightInfos; }; struct Device { @@ -582,13 +582,13 @@ private: int16_t ffEffectId; // initially -1 // A shared_ptr of a device associated with the input device. - // The input devices with same descriptor has the same associated device. - std::shared_ptr<AssociatedDevice> associatedDevice; + // The input devices that have the same sysfs path have the same associated device. + const std::shared_ptr<const AssociatedDevice> associatedDevice; int32_t controllerNumber; - Device(int fd, int32_t id, const std::string& path, - const InputDeviceIdentifier& identifier); + Device(int fd, int32_t id, std::string path, InputDeviceIdentifier identifier, + std::shared_ptr<const AssociatedDevice> assocDev); ~Device(); void close(); @@ -633,6 +633,8 @@ private: void createVirtualKeyboardLocked() REQUIRES(mLock); void addDeviceLocked(std::unique_ptr<Device> device) REQUIRES(mLock); void assignDescriptorLocked(InputDeviceIdentifier& identifier) REQUIRES(mLock); + std::shared_ptr<const AssociatedDevice> obtainAssociatedDeviceLocked( + const std::filesystem::path& devicePath) const REQUIRES(mLock); void closeDeviceByPathLocked(const std::string& devicePath) REQUIRES(mLock); void closeVideoDeviceByPathLocked(const std::string& devicePath) REQUIRES(mLock); diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 51872ac095..141464f6e4 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -158,6 +158,7 @@ private: int32_t mId; int32_t mGeneration; int32_t mControllerNumber; + hardware::input::InputDeviceCountryCode mCountryCode; InputDeviceIdentifier mIdentifier; std::string mAlias; ftl::Flags<InputDeviceClass> mClasses; @@ -311,6 +312,9 @@ public: } inline std::vector<TouchVideoFrame> getVideoFrames() { return mEventHub->getVideoFrames(mId); } + inline hardware::input::InputDeviceCountryCode getCountryCode() const { + return mEventHub->getCountryCode(mId); + } inline int32_t getScanCodeState(int32_t scanCode) const { return mEventHub->getScanCodeState(mId, scanCode); } diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index 6a406d21de..9bb6273d71 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -127,7 +127,6 @@ void KeyboardInputMapper::dump(std::string& dump) { dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation()); dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size()); dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState); - dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime); } std::optional<DisplayViewport> KeyboardInputMapper::findViewport( @@ -196,9 +195,7 @@ void KeyboardInputMapper::dumpParameters(std::string& dump) { } void KeyboardInputMapper::reset(nsecs_t when) { - mMetaState = AMETA_NONE; - mDownTime = 0; - mKeyDowns.clear(); + cancelAllDownKeys(when); mCurrentHidUsage = 0; resetLedState(); @@ -281,6 +278,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, policyFlags = 0; } + nsecs_t downTime = when; if (down) { // Rotate key codes according to orientation if needed. if (mParameters.orientationAware) { @@ -292,6 +290,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, if (keyDownIndex >= 0) { // key repeat, be sure to use same keycode as before in case of rotation keyCode = mKeyDowns[keyDownIndex].keyCode; + downTime = mKeyDowns[keyDownIndex].downTime; } else { // key down if ((policyFlags & POLICY_FLAG_VIRTUAL) && @@ -305,16 +304,16 @@ void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, KeyDown keyDown; keyDown.keyCode = keyCode; keyDown.scanCode = scanCode; + keyDown.downTime = when; mKeyDowns.push_back(keyDown); } - - mDownTime = when; } else { // Remove key down. ssize_t keyDownIndex = findKeyDown(scanCode); if (keyDownIndex >= 0) { // key up, be sure to use same keycode as before in case of rotation keyCode = mKeyDowns[keyDownIndex].keyCode; + downTime = mKeyDowns[keyDownIndex].downTime; mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex); } else { // key was not actually down @@ -333,8 +332,6 @@ void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, keyMetaState = mMetaState; } - nsecs_t downTime = mDownTime; - // Key down on external an keyboard should wake the device. // We don't do this for internal keyboards to prevent them from waking up in your pocket. // For internal keyboards and devices for which the default wake behavior is explicitly @@ -473,4 +470,19 @@ std::optional<int32_t> KeyboardInputMapper::getAssociatedDisplayId() { return std::nullopt; } +void KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) { + size_t n = mKeyDowns.size(); + for (size_t i = 0; i < n; i++) { + NotifyKeyArgs args(getContext()->getNextId(), when, systemTime(SYSTEM_TIME_MONOTONIC), + getDeviceId(), mSource, getDisplayId(), 0 /*policyFlags*/, + AKEY_EVENT_ACTION_UP, + AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, + mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE, + mKeyDowns[i].downTime); + getListener().notifyKey(&args); + } + mKeyDowns.clear(); + mMetaState = AMETA_NONE; +} + } // namespace android diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h index 0a55def33f..31251f4433 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h @@ -50,6 +50,7 @@ private: std::optional<DisplayViewport> mViewport; struct KeyDown { + nsecs_t downTime; int32_t keyCode; int32_t scanCode; }; @@ -59,7 +60,6 @@ private: std::vector<KeyDown> mKeyDowns; // keys that are down int32_t mMetaState; - nsecs_t mDownTime; // time of most recent key down int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none @@ -98,6 +98,7 @@ private: void updateLedStateForModifier(LedState& ledState, int32_t led, int32_t modifier, bool reset); std::optional<DisplayViewport> findViewport(nsecs_t when, const InputReaderConfiguration* config); + void cancelAllDownKeys(nsecs_t when); }; } // namespace android diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 924c4d0ba5..539e24a098 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -1524,14 +1524,13 @@ void TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) { assignPointerIds(last, next); } - if (DEBUG_RAW_EVENTS) { - ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, " - "hovering ids 0x%08x -> 0x%08x, canceled ids 0x%08x", - last.rawPointerData.pointerCount, next.rawPointerData.pointerCount, - last.rawPointerData.touchingIdBits.value, next.rawPointerData.touchingIdBits.value, - last.rawPointerData.hoveringIdBits.value, next.rawPointerData.hoveringIdBits.value, - next.rawPointerData.canceledIdBits.value); - } + ALOGD_IF(DEBUG_RAW_EVENTS, + "syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, " + "hovering ids 0x%08x -> 0x%08x, canceled ids 0x%08x", + last.rawPointerData.pointerCount, next.rawPointerData.pointerCount, + last.rawPointerData.touchingIdBits.value, next.rawPointerData.touchingIdBits.value, + last.rawPointerData.hoveringIdBits.value, next.rawPointerData.hoveringIdBits.value, + next.rawPointerData.canceledIdBits.value); if (!next.rawPointerData.touchingIdBits.isEmpty() && !next.rawPointerData.hoveringIdBits.isEmpty() && @@ -1585,9 +1584,8 @@ void TouchInputMapper::processRawTouches(bool timeout) { nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY; clearStylusDataPendingFlags(); mCurrentRawState.copyFrom(mLastRawState); - if (DEBUG_STYLUS_FUSION) { - ALOGD("Timeout expired, synthesizing event with new stylus data"); - } + ALOGD_IF(DEBUG_STYLUS_FUSION, + "Timeout expired, synthesizing event with new stylus data"); const nsecs_t readTime = when; // consider this synthetic event to be zero latency cookAndDispatch(when, readTime); } else if (mExternalStylusFusionTimeout == LLONG_MAX) { @@ -1773,24 +1771,18 @@ bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeou state.rawPointerData.pointerCount != 0; if (initialDown) { if (mExternalStylusState.pressure != 0.0f) { - if (DEBUG_STYLUS_FUSION) { - ALOGD("Have both stylus and touch data, beginning fusion"); - } + ALOGD_IF(DEBUG_STYLUS_FUSION, "Have both stylus and touch data, beginning fusion"); mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit(); } else if (timeout) { - if (DEBUG_STYLUS_FUSION) { - ALOGD("Timeout expired, assuming touch is not a stylus."); - } + ALOGD_IF(DEBUG_STYLUS_FUSION, "Timeout expired, assuming touch is not a stylus."); resetExternalStylus(); } else { if (mExternalStylusFusionTimeout == LLONG_MAX) { mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT; } - if (DEBUG_STYLUS_FUSION) { - ALOGD("No stylus data but stylus is connected, requesting timeout " - "(%" PRId64 "ms)", - mExternalStylusFusionTimeout); - } + ALOGD_IF(DEBUG_STYLUS_FUSION, + "No stylus data but stylus is connected, requesting timeout (%" PRId64 "ms)", + mExternalStylusFusionTimeout); getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout); return true; } @@ -1798,9 +1790,7 @@ bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeou // Check if the stylus pointer has gone up. if (mExternalStylusId != -1 && !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) { - if (DEBUG_STYLUS_FUSION) { - ALOGD("Stylus pointer is going up"); - } + ALOGD_IF(DEBUG_STYLUS_FUSION, "Stylus pointer is going up"); mExternalStylusId = -1; } @@ -1841,10 +1831,9 @@ bool TouchInputMapper::consumeRawTouches(nsecs_t when, nsecs_t readTime, uint32_ // Pointer went up while virtual key was down. mCurrentVirtualKey.down = false; if (!mCurrentVirtualKey.ignored) { - if (DEBUG_VIRTUAL_KEYS) { - ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d", - mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); - } + ALOGD_IF(DEBUG_VIRTUAL_KEYS, + "VirtualKeys: Generating key up: keyCode=%d, scanCode=%d", + mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); } @@ -1868,10 +1857,8 @@ bool TouchInputMapper::consumeRawTouches(nsecs_t when, nsecs_t readTime, uint32_ // into the main display surface. mCurrentVirtualKey.down = false; if (!mCurrentVirtualKey.ignored) { - if (DEBUG_VIRTUAL_KEYS) { - ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d", - mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); - } + ALOGD_IF(DEBUG_VIRTUAL_KEYS, "VirtualKeys: Canceling key: keyCode=%d, scanCode=%d", + mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY | AKEY_EVENT_FLAG_CANCELED); @@ -1901,10 +1888,9 @@ bool TouchInputMapper::consumeRawTouches(nsecs_t when, nsecs_t readTime, uint32_ virtualKey->scanCode); if (!mCurrentVirtualKey.ignored) { - if (DEBUG_VIRTUAL_KEYS) { - ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d", - mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); - } + ALOGD_IF(DEBUG_VIRTUAL_KEYS, + "VirtualKeys: Generating key down: keyCode=%d, scanCode=%d", + mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_DOWN, AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); @@ -2696,9 +2682,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi // Handle TAP timeout. if (isTimeout) { - if (DEBUG_GESTURES) { - ALOGD("Gestures: Processing timeout"); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: Processing timeout"); if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP) { if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) { @@ -2707,9 +2691,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi mConfig.pointerGestureTapDragInterval); } else { // The tap is finished. - if (DEBUG_GESTURES) { - ALOGD("Gestures: TAP finished"); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: TAP finished"); *outFinishPreviousGesture = true; mPointerGesture.activeGestureId = -1; @@ -2805,11 +2787,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi // Switch states based on button and pointer state. if (isQuietTime) { // Case 1: Quiet time. (QUIET) - if (DEBUG_GESTURES) { - ALOGD("Gestures: QUIET for next %0.3fms", - (mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval - when) * - 0.000001f); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: QUIET for next %0.3fms", + (mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval - when) * + 0.000001f); if (mPointerGesture.lastGestureMode != PointerGesture::Mode::QUIET) { *outFinishPreviousGesture = true; } @@ -2833,11 +2813,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi // active. If the user first puts one finger down to click then adds another // finger to drag then the active pointer should switch to the finger that is // being dragged. - if (DEBUG_GESTURES) { - ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, " - "currentFingerCount=%d", - activeTouchId, currentFingerCount); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, currentFingerCount=%d", + activeTouchId, currentFingerCount); // Reset state when just starting. if (mPointerGesture.lastGestureMode != PointerGesture::Mode::BUTTON_CLICK_OR_DRAG) { *outFinishPreviousGesture = true; @@ -2862,30 +2840,17 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi } if (bestId >= 0 && bestId != activeTouchId) { mPointerGesture.activeTouchId = activeTouchId = bestId; - if (DEBUG_GESTURES) { - ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, " - "bestId=%d, bestSpeed=%0.3f", - bestId, bestSpeed); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: BUTTON_CLICK_OR_DRAG switched pointers, bestId=%d, " + "bestSpeed=%0.3f", + bestId, bestSpeed); } } - float deltaX = 0, deltaY = 0; if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) { - const RawPointerData::Pointer& currentPointer = - mCurrentRawState.rawPointerData.pointerForId(activeTouchId); - const RawPointerData::Pointer& lastPointer = - mLastRawState.rawPointerData.pointerForId(activeTouchId); - deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale; - deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale; - - rotateDelta(mInputDeviceOrientation, &deltaX, &deltaY); - mPointerVelocityControl.move(when, &deltaX, &deltaY); - - // Move the pointer using a relative motion. // When using spots, the click will occur at the position of the anchor // spot and all other spots will move there. - mPointerController->move(deltaX, deltaY); + moveMousePointerFromPointerDelta(when, activeTouchId); } else { mPointerVelocityControl.reset(); } @@ -2921,9 +2886,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi mPointerController->getPosition(&x, &y); if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) { - if (DEBUG_GESTURES) { - ALOGD("Gestures: TAP"); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: TAP"); mPointerGesture.tapUpTime = when; getContext()->requestTimeoutAtTime(when + @@ -2949,10 +2912,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi tapped = true; } else { - if (DEBUG_GESTURES) { - ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f", x - mPointerGesture.tapX, - y - mPointerGesture.tapY); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: Not a TAP, deltaX=%f, deltaY=%f", + x - mPointerGesture.tapX, y - mPointerGesture.tapY); } } else { if (DEBUG_GESTURES) { @@ -2969,9 +2930,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi mPointerVelocityControl.reset(); if (!tapped) { - if (DEBUG_GESTURES) { - ALOGD("Gestures: NEUTRAL"); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: NEUTRAL"); mPointerGesture.activeGestureId = -1; mPointerGesture.currentGestureMode = PointerGesture::Mode::NEUTRAL; mPointerGesture.currentGestureIdBits.clear(); @@ -2992,50 +2951,30 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) { mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP_DRAG; } else { - if (DEBUG_GESTURES) { - ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f", - x - mPointerGesture.tapX, y - mPointerGesture.tapY); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f", + x - mPointerGesture.tapX, y - mPointerGesture.tapY); } } else { - if (DEBUG_GESTURES) { - ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up", - (when - mPointerGesture.tapUpTime) * 0.000001f); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: Not a TAP_DRAG, %0.3fms time since up", + (when - mPointerGesture.tapUpTime) * 0.000001f); } } else if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP_DRAG) { mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP_DRAG; } - float deltaX = 0, deltaY = 0; if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) { - const RawPointerData::Pointer& currentPointer = - mCurrentRawState.rawPointerData.pointerForId(activeTouchId); - const RawPointerData::Pointer& lastPointer = - mLastRawState.rawPointerData.pointerForId(activeTouchId); - deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale; - deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale; - - rotateDelta(mInputDeviceOrientation, &deltaX, &deltaY); - mPointerVelocityControl.move(when, &deltaX, &deltaY); - - // Move the pointer using a relative motion. // When using spots, the hover or drag will occur at the position of the anchor spot. - mPointerController->move(deltaX, deltaY); + moveMousePointerFromPointerDelta(when, activeTouchId); } else { mPointerVelocityControl.reset(); } bool down; if (mPointerGesture.currentGestureMode == PointerGesture::Mode::TAP_DRAG) { - if (DEBUG_GESTURES) { - ALOGD("Gestures: TAP_DRAG"); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: TAP_DRAG"); down = true; } else { - if (DEBUG_GESTURES) { - ALOGD("Gestures: HOVER"); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: HOVER"); if (mPointerGesture.lastGestureMode != PointerGesture::Mode::HOVER) { *outFinishPreviousGesture = true; } @@ -3089,13 +3028,12 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi } else if (!settled && currentFingerCount > lastFingerCount) { // Additional pointers have gone down but not yet settled. // Reset the gesture. - if (DEBUG_GESTURES) { - ALOGD("Gestures: Resetting gesture since additional pointers went down for " - "MULTITOUCH, settle time remaining %0.3fms", - (mPointerGesture.firstTouchTime + - mConfig.pointerGestureMultitouchSettleInterval - when) * - 0.000001f); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: Resetting gesture since additional pointers went down for " + "MULTITOUCH, settle time remaining %0.3fms", + (mPointerGesture.firstTouchTime + + mConfig.pointerGestureMultitouchSettleInterval - when) * + 0.000001f); *outCancelPreviousGesture = true; } else { // Continue previous gesture. @@ -3109,13 +3047,12 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi mPointerVelocityControl.reset(); // Use the centroid and pointer location as the reference points for the gesture. - if (DEBUG_GESTURES) { - ALOGD("Gestures: Using centroid as reference for MULTITOUCH, " - "settle time remaining %0.3fms", - (mPointerGesture.firstTouchTime + - mConfig.pointerGestureMultitouchSettleInterval - when) * - 0.000001f); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: Using centroid as reference for MULTITOUCH, settle time remaining " + "%0.3fms", + (mPointerGesture.firstTouchTime + + mConfig.pointerGestureMultitouchSettleInterval - when) * + 0.000001f); mCurrentRawState.rawPointerData .getCentroidOfTouchingPointers(&mPointerGesture.referenceTouchX, &mPointerGesture.referenceTouchY); @@ -3173,10 +3110,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi if (distOverThreshold >= 2) { if (currentFingerCount > 2) { // There are more than two pointers, switch to FREEFORM. - if (DEBUG_GESTURES) { - ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2", - currentFingerCount); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2", + currentFingerCount); *outCancelPreviousGesture = true; mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM; } else { @@ -3192,11 +3128,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi if (mutualDistance > mPointerGestureMaxSwipeWidth) { // There are two pointers but they are too far apart for a SWIPE, // switch to FREEFORM. - if (DEBUG_GESTURES) { - ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > " - "%0.3f", - mutualDistance, mPointerGestureMaxSwipeWidth); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f", + mutualDistance, mPointerGestureMaxSwipeWidth); *outCancelPreviousGesture = true; mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM; } else { @@ -3221,25 +3155,23 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi float cosine = dot / (dist1 * dist2); // denominator always > 0 if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) { // Pointers are moving in the same direction. Switch to SWIPE. - if (DEBUG_GESTURES) { - ALOGD("Gestures: PRESS transitioned to SWIPE, " - "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " - "cosine %0.3f >= %0.3f", - dist1, mConfig.pointerGestureMultitouchMinDistance, dist2, - mConfig.pointerGestureMultitouchMinDistance, cosine, - mConfig.pointerGestureSwipeTransitionAngleCosine); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: PRESS transitioned to SWIPE, " + "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " + "cosine %0.3f >= %0.3f", + dist1, mConfig.pointerGestureMultitouchMinDistance, dist2, + mConfig.pointerGestureMultitouchMinDistance, cosine, + mConfig.pointerGestureSwipeTransitionAngleCosine); mPointerGesture.currentGestureMode = PointerGesture::Mode::SWIPE; } else { // Pointers are moving in different directions. Switch to FREEFORM. - if (DEBUG_GESTURES) { - ALOGD("Gestures: PRESS transitioned to FREEFORM, " - "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " - "cosine %0.3f < %0.3f", - dist1, mConfig.pointerGestureMultitouchMinDistance, dist2, - mConfig.pointerGestureMultitouchMinDistance, cosine, - mConfig.pointerGestureSwipeTransitionAngleCosine); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: PRESS transitioned to FREEFORM, " + "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " + "cosine %0.3f < %0.3f", + dist1, mConfig.pointerGestureMultitouchMinDistance, dist2, + mConfig.pointerGestureMultitouchMinDistance, cosine, + mConfig.pointerGestureSwipeTransitionAngleCosine); *outCancelPreviousGesture = true; mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM; } @@ -3251,10 +3183,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi // Switch from SWIPE to FREEFORM if additional pointers go down. // Cancel previous gesture. if (currentFingerCount > 2) { - if (DEBUG_GESTURES) { - ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2", - currentFingerCount); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2", + currentFingerCount); *outCancelPreviousGesture = true; mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM; } @@ -3288,11 +3219,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi if (mPointerGesture.currentGestureMode == PointerGesture::Mode::PRESS || mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) { // PRESS or SWIPE mode. - if (DEBUG_GESTURES) { - ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d," - "activeGestureId=%d, currentTouchPointerCount=%d", - activeTouchId, mPointerGesture.activeGestureId, currentFingerCount); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: PRESS or SWIPE activeTouchId=%d, activeGestureId=%d, " + "currentTouchPointerCount=%d", + activeTouchId, mPointerGesture.activeGestureId, currentFingerCount); ALOG_ASSERT(mPointerGesture.activeGestureId >= 0); mPointerGesture.currentGestureIdBits.clear(); @@ -3309,11 +3239,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); } else if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) { // FREEFORM mode. - if (DEBUG_GESTURES) { - ALOGD("Gestures: FREEFORM activeTouchId=%d," - "activeGestureId=%d, currentTouchPointerCount=%d", - activeTouchId, mPointerGesture.activeGestureId, currentFingerCount); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: FREEFORM activeTouchId=%d, activeGestureId=%d, " + "currentTouchPointerCount=%d", + activeTouchId, mPointerGesture.activeGestureId, currentFingerCount); ALOG_ASSERT(mPointerGesture.activeGestureId >= 0); mPointerGesture.currentGestureIdBits.clear(); @@ -3352,13 +3281,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi } } - if (DEBUG_GESTURES) { - ALOGD("Gestures: FREEFORM follow up " - "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, " - "activeGestureId=%d", - mappedTouchIdBits.value, usedGestureIdBits.value, - mPointerGesture.activeGestureId); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: FREEFORM follow up mappedTouchIdBits=0x%08x, " + "usedGestureIdBits=0x%08x, activeGestureId=%d", + mappedTouchIdBits.value, usedGestureIdBits.value, + mPointerGesture.activeGestureId); BitSet32 idBits(mCurrentCookedState.fingerIdBits); for (uint32_t i = 0; i < currentFingerCount; i++) { @@ -3367,18 +3294,14 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi if (!mappedTouchIdBits.hasBit(touchId)) { gestureId = usedGestureIdBits.markFirstUnmarkedBit(); mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId; - if (DEBUG_GESTURES) { - ALOGD("Gestures: FREEFORM " - "new mapping for touch id %d -> gesture id %d", - touchId, gestureId); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: FREEFORM new mapping for touch id %d -> gesture id %d", + touchId, gestureId); } else { gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId]; - if (DEBUG_GESTURES) { - ALOGD("Gestures: FREEFORM " - "existing mapping for touch id %d -> gesture id %d", - touchId, gestureId); - } + ALOGD_IF(DEBUG_GESTURES, + "Gestures: FREEFORM existing mapping for touch id %d -> gesture id %d", + touchId, gestureId); } mPointerGesture.currentGestureIdBits.markBit(gestureId); mPointerGesture.currentGestureIdToIndex[gestureId] = i; @@ -3407,10 +3330,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi if (mPointerGesture.activeGestureId < 0) { mPointerGesture.activeGestureId = mPointerGesture.currentGestureIdBits.firstMarkedBit(); - if (DEBUG_GESTURES) { - ALOGD("Gestures: FREEFORM new activeGestureId=%d", - mPointerGesture.activeGestureId); - } + ALOGD_IF(DEBUG_GESTURES, "Gestures: FREEFORM new activeGestureId=%d", + mPointerGesture.activeGestureId); } } } @@ -3450,6 +3371,20 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi return true; } +void TouchInputMapper::moveMousePointerFromPointerDelta(nsecs_t when, uint32_t pointerId) { + const RawPointerData::Pointer& currentPointer = + mCurrentRawState.rawPointerData.pointerForId(pointerId); + const RawPointerData::Pointer& lastPointer = + mLastRawState.rawPointerData.pointerForId(pointerId); + float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale; + float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale; + + rotateDelta(mInputDeviceOrientation, &deltaX, &deltaY); + mPointerVelocityControl.move(when, &deltaX, &deltaY); + + mPointerController->move(deltaX, deltaY); +} + void TouchInputMapper::dispatchPointerStylus(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { mPointerSimple.currentCoords.clear(); mPointerSimple.currentProperties.clear(); @@ -3493,21 +3428,8 @@ void TouchInputMapper::dispatchPointerMouse(nsecs_t when, nsecs_t readTime, uint bool down, hovering; if (!mCurrentCookedState.mouseIdBits.isEmpty()) { uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit(); - uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id]; - float deltaX = 0, deltaY = 0; if (mLastCookedState.mouseIdBits.hasBit(id)) { - uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id]; - deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x - - mLastRawState.rawPointerData.pointers[lastIndex].x) * - mPointerXMovementScale; - deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y - - mLastRawState.rawPointerData.pointers[lastIndex].y) * - mPointerYMovementScale; - - rotateDelta(mInputDeviceOrientation, &deltaX, &deltaY); - mPointerVelocityControl.move(when, &deltaX, &deltaY); - - mPointerController->move(deltaX, deltaY); + moveMousePointerFromPointerDelta(when, id); } else { mPointerVelocityControl.reset(); } @@ -3517,6 +3439,7 @@ void TouchInputMapper::dispatchPointerMouse(nsecs_t when, nsecs_t readTime, uint float x, y; mPointerController->getPosition(&x, &y); + uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id]; mPointerSimple.currentCoords.copyFrom( mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]); mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); @@ -3820,12 +3743,11 @@ bool TouchInputMapper::isPointInsidePhysicalFrame(int32_t x, int32_t y) const { const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) { for (const VirtualKey& virtualKey : mVirtualKeys) { - if (DEBUG_VIRTUAL_KEYS) { - ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, " - "left=%d, top=%d, right=%d, bottom=%d", - x, y, virtualKey.keyCode, virtualKey.scanCode, virtualKey.hitLeft, - virtualKey.hitTop, virtualKey.hitRight, virtualKey.hitBottom); - } + ALOGD_IF(DEBUG_VIRTUAL_KEYS, + "VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, " + "left=%d, top=%d, right=%d, bottom=%d", + x, y, virtualKey.keyCode, virtualKey.scanCode, virtualKey.hitLeft, + virtualKey.hitTop, virtualKey.hitRight, virtualKey.hitBottom); if (virtualKey.isHit(x, y)) { return &virtualKey; @@ -3996,11 +3918,10 @@ void TouchInputMapper::assignPointerIds(const RawState& last, RawState& current) currentPointerIndex)); usedIdBits.markBit(id); - if (DEBUG_POINTER_ASSIGNMENT) { - ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32 ", id=%" PRIu32 - ", distance=%" PRIu64, - lastPointerIndex, currentPointerIndex, id, heap[0].distance); - } + ALOGD_IF(DEBUG_POINTER_ASSIGNMENT, + "assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32 ", id=%" PRIu32 + ", distance=%" PRIu64, + lastPointerIndex, currentPointerIndex, id, heap[0].distance); break; } } @@ -4015,10 +3936,9 @@ void TouchInputMapper::assignPointerIds(const RawState& last, RawState& current) current.rawPointerData.markIdBit(id, current.rawPointerData.isHovering(currentPointerIndex)); - if (DEBUG_POINTER_ASSIGNMENT) { - ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, - id); - } + ALOGD_IF(DEBUG_POINTER_ASSIGNMENT, + "assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, + id); } } diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index cdf1c7d032..fe1700612e 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -754,6 +754,10 @@ private: bool preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout); + // Moves the on-screen mouse pointer based on the movement of the pointer of the given ID + // between the last and current events. Uses a relative motion. + void moveMousePointerFromPointerDelta(nsecs_t when, uint32_t pointerId); + void dispatchPointerStylus(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); void abortPointerStylus(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 24721de75b..3e99cefec7 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -38,9 +38,12 @@ #include <gtest/gtest.h> #include <gui/constants.h> +#include "android/hardware/input/InputDeviceCountryCode.h" #include "input/DisplayViewport.h" #include "input/Input.h" +using android::hardware::input::InputDeviceCountryCode; + namespace android { using namespace ftl::flag_operators; @@ -455,6 +458,7 @@ class FakeEventHub : public EventHubInterface { BitArray<MSC_MAX> mscBitmask; std::vector<VirtualKeyDefinition> virtualKeys; bool enabled; + InputDeviceCountryCode countryCode; status_t enable() { enabled = true; @@ -509,7 +513,7 @@ public: enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0); } - bool isDeviceEnabled(int32_t deviceId) { + bool isDeviceEnabled(int32_t deviceId) const override { Device* device = getDevice(deviceId); if (device == nullptr) { ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__); @@ -518,7 +522,7 @@ public: return device->enabled; } - status_t enableDevice(int32_t deviceId) { + status_t enableDevice(int32_t deviceId) override { status_t result; Device* device = getDevice(deviceId); if (device == nullptr) { @@ -533,7 +537,7 @@ public: return result; } - status_t disableDevice(int32_t deviceId) { + status_t disableDevice(int32_t deviceId) override { Device* device = getDevice(deviceId); if (device == nullptr) { ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__); @@ -584,6 +588,11 @@ public: device->keyCodeStates.replaceValueFor(keyCode, state); } + void setCountryCode(int32_t deviceId, InputDeviceCountryCode countryCode) { + Device* device = getDevice(deviceId); + device->countryCode = countryCode; + } + void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) { Device* device = getDevice(deviceId); device->scanCodeStates.replaceValueFor(scanCode, state); @@ -795,8 +804,8 @@ private: status_t mapAxis(int32_t, int32_t, AxisInfo*) const override { return NAME_NOT_FOUND; } - base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId, - int32_t absCode) { + base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor( + int32_t deviceId, int32_t absCode) const override { Device* device = getDevice(deviceId); if (!device) { return Errorf("Sensor device not found."); @@ -845,6 +854,14 @@ private: return AKEY_STATE_UNKNOWN; } + InputDeviceCountryCode getCountryCode(int32_t deviceId) const override { + Device* device = getDevice(deviceId); + if (device) { + return device->countryCode; + } + return InputDeviceCountryCode::INVALID; + } + int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override { Device* device = getDevice(deviceId); if (device) { @@ -981,7 +998,7 @@ private: void cancelVibrate(int32_t) override {} - std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; }; + std::vector<int32_t> getVibratorIds(int32_t deviceId) const override { return mVibrators; }; std::optional<int32_t> getBatteryCapacity(int32_t, int32_t) const override { return BATTERY_CAPACITY; @@ -991,13 +1008,14 @@ private: return BATTERY_STATUS; } - const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) { return {}; } + std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const override { return {}; } - std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, int32_t batteryId) { + std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, + int32_t batteryId) const override { return std::nullopt; } - const std::vector<int32_t> getRawLightIds(int32_t deviceId) override { + std::vector<int32_t> getRawLightIds(int32_t deviceId) const override { std::vector<int32_t> ids; for (const auto& [rawId, info] : mRawLightInfos) { ids.push_back(rawId); @@ -1005,7 +1023,7 @@ private: return ids; } - std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override { + std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) const override { auto it = mRawLightInfos.find(lightId); if (it == mRawLightInfos.end()) { return std::nullopt; @@ -1022,7 +1040,7 @@ private: mLightIntensities.emplace(lightId, intensities); }; - std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override { + std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) const override { auto lightIt = mLightBrightness.find(lightId); if (lightIt == mLightBrightness.end()) { return std::nullopt; @@ -1031,7 +1049,7 @@ private: } std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities( - int32_t deviceId, int32_t lightId) override { + int32_t deviceId, int32_t lightId) const override { auto lightIt = mLightIntensities.find(lightId); if (lightIt == mLightIntensities.end()) { return std::nullopt; @@ -1039,13 +1057,9 @@ private: return lightIt->second; }; - virtual bool isExternal(int32_t) const { - return false; - } - - void dump(std::string&) override {} + void dump(std::string&) const override {} - void monitor() override {} + void monitor() const override {} void requestReopenDevices() override {} @@ -2688,6 +2702,17 @@ TEST_F(InputDeviceTest, ImmutableProperties) { ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses()); } +TEST_F(InputDeviceTest, CountryCodeCorrectlyMapped) { + mFakeEventHub->setCountryCode(EVENTHUB_ID, InputDeviceCountryCode::INTERNATIONAL); + + // Configuration + mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD); + InputReaderConfiguration config; + mDevice->configure(ARBITRARY_TIME, &config, 0); + + ASSERT_EQ(InputDeviceCountryCode::INTERNATIONAL, mDevice->getDeviceInfo().getCountryCode()); +} + TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) { ASSERT_EQ(mDevice->isEnabled(), false); } @@ -4091,6 +4116,37 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) { ASSERT_EQ(AMETA_NONE, mapper2.getMetaState()); } +TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) { + const int32_t USAGE_A = 0x070004; + mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE); + mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE); + + KeyboardInputMapper& mapper = + addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD, + AINPUT_KEYBOARD_TYPE_ALPHABETIC); + // Key down by scan code. + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1); + NotifyKeyArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(DEVICE_ID, args.deviceId); + ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); + ASSERT_EQ(ARBITRARY_TIME, args.eventTime); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action); + ASSERT_EQ(AKEYCODE_HOME, args.keyCode); + ASSERT_EQ(KEY_HOME, args.scanCode); + ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags); + + // Disable device, it should synthesize cancellation events for down events. + mFakePolicy->addDisabledDevice(DEVICE_ID); + configureDevice(InputReaderConfiguration::CHANGE_ENABLED_STATE); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); + ASSERT_EQ(AKEYCODE_HOME, args.keyCode); + ASSERT_EQ(KEY_HOME, args.scanCode); + ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags); +} + // --- KeyboardInputMapperTest_ExternalDevice --- class KeyboardInputMapperTest_ExternalDevice : public InputMapperTest { diff --git a/services/sensorservice/AidlSensorHalWrapper.cpp b/services/sensorservice/AidlSensorHalWrapper.cpp index 4d1de96caa..f67c610550 100644 --- a/services/sensorservice/AidlSensorHalWrapper.cpp +++ b/services/sensorservice/AidlSensorHalWrapper.cpp @@ -726,7 +726,7 @@ status_t AidlSensorHalWrapper::registerDirectChannel(const sensors_direct_mem_t .type = type, .format = format, .size = static_cast<int32_t>(memory->size), - .memoryHandle = makeToAidl(memory->handle), + .memoryHandle = dupToAidl(memory->handle), }; return convertToStatus(mSensors->registerDirectChannel(mem, channelHandle)); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index cce6ad7fe0..0cedfc8138 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -531,8 +531,6 @@ bool BufferStateLayer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& FrameTracer::FrameEvent::QUEUE); } - mDrawingState.width = mDrawingState.buffer->getWidth(); - mDrawingState.height = mDrawingState.buffer->getHeight(); mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint; return true; } @@ -622,14 +620,6 @@ bool BufferStateLayer::setTransactionCompletedListeners( return willPresent; } -bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { - mDrawingState.sequence++; - mDrawingState.transparentRegionHint = transparent; - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; -} - Rect BufferStateLayer::getBufferSize(const State& /*s*/) const { // for buffer state layers we use the display frame size as the buffer size. diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index a0f13e21d4..a0a52bfcd3 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -116,9 +116,6 @@ public: void releasePendingBuffer(nsecs_t dequeueReadyTime) override; - Region getActiveTransparentRegion(const Layer::State& s) const override { - return s.transparentRegionHint; - } Rect getCrop(const Layer::State& s) const; bool setTransform(uint32_t transform) override; @@ -137,10 +134,6 @@ public: bool setPosition(float /*x*/, float /*y*/) override; bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/); - // Override to ignore legacy layer state properties that are not used by BufferStateLayer - bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } - bool setTransparentRegionHint(const Region& transparent) override; - // BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame // and its parent layer is not bounded Rect getBufferSize(const State& s) const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index f93fd99f29..9753a6c83c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -20,8 +20,6 @@ #include <ostream> #include <unordered_set> -#include <compositionengine/FenceResult.h> - // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" @@ -33,6 +31,7 @@ #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include <ftl/future.h> +#include <ui/FenceResult.h> #include <utils/RefBase.h> #include <utils/Timers.h> diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index fc8dd8be94..38a391b114 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -152,6 +152,8 @@ protected: virtual const compositionengine::CompositionEngine& getCompositionEngine() const = 0; virtual void dumpState(std::string& out) const = 0; + bool mustRecompose() const; + private: void dirtyEntireOutput(); void updateCompositionStateForBorder(const compositionengine::CompositionRefreshArgs&); @@ -171,6 +173,9 @@ private: std::unique_ptr<ClientCompositionRequestCache> mClientCompositionRequestCache; std::unique_ptr<planner::Planner> mPlanner; std::unique_ptr<HwcAsyncWorker> mHwComposerAsyncWorker; + + // Whether the content must be recomposed this frame. + bool mMustRecompose = false; }; // This template factory function standardizes the implementation details of the diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index 2bfd3cfb1f..24a7744542 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -115,7 +115,7 @@ public: // Renders the cached set with the supplied output composition state. void render(renderengine::RenderEngine& re, TexturePool& texturePool, - const OutputCompositionState& outputState); + const OutputCompositionState& outputState, bool deviceHandlesColorTransform); void dump(std::string& result) const; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h index 92cc484211..f934cb20a0 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h @@ -106,7 +106,8 @@ public: // Renders the newest cached sets with the supplied output composition state void renderCachedSets(const OutputCompositionState& outputState, - std::optional<std::chrono::steady_clock::time_point> renderDeadline); + std::optional<std::chrono::steady_clock::time_point> renderDeadline, + bool deviceHandlesColorTransform); void setTexturePoolEnabled(bool enabled) { mTexturePool.setEnabled(enabled); } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h index b7ebca60fd..c968df708f 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h @@ -65,7 +65,8 @@ public: // Rendering a pending cached set is optional: if the renderDeadline is not far enough in the // future then the planner may opt to skip rendering the cached set. void renderCachedSets(const OutputCompositionState& outputState, - std::optional<std::chrono::steady_clock::time_point> renderDeadline); + std::optional<std::chrono::steady_clock::time_point> renderDeadline, + bool deviceHandlesColorTransform); void setTexturePoolEnabled(bool enabled) { mFlattener.setTexturePoolEnabled(enabled); } diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 09adaed6fc..d359424801 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -421,7 +421,7 @@ void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refre // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) - if (GpuVirtualDisplayId::tryCast(mId) && getDirtyRegion().isEmpty()) { + if (GpuVirtualDisplayId::tryCast(mId) && !mustRecompose()) { ALOGV("Skipping display composition"); return; } diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 6edc00f1e1..b5894cf0be 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1015,17 +1015,17 @@ void Output::beginFrame() { // frame, then nothing more until we get new layers. // - When a display is created with a private layer stack, we won't // emit any black frames until a layer is added to the layer stack. - const bool mustRecompose = dirty && !(empty && wasEmpty); + mMustRecompose = dirty && !(empty && wasEmpty); const char flagPrefix[] = {'-', '+'}; static_cast<void>(flagPrefix); - ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__, - mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty], - flagPrefix[empty], flagPrefix[wasEmpty]); + ALOGV("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __func__, + mMustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty], + flagPrefix[empty], flagPrefix[wasEmpty]); - mRenderSurface->beginFrame(mustRecompose); + mRenderSurface->beginFrame(mMustRecompose); - if (mustRecompose) { + if (mMustRecompose) { outputState.lastCompositionHadVisibleLayers = !empty; } } @@ -1330,11 +1330,10 @@ std::optional<base::unique_fd> Output::composeSurfaces( // over to RenderEngine, in which case this flag can be removed from the drawLayers interface. const bool useFramebufferCache = outputState.layerFilter.toInternalDisplay; - auto fenceResult = - toFenceResult(renderEngine - .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, - tex, useFramebufferCache, std::move(fd)) - .get()); + auto fenceResult = renderEngine + .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, tex, + useFramebufferCache, std::move(fd)) + .get(); if (mClientCompositionRequestCache && fenceStatus(fenceResult) != NO_ERROR) { // If rendering was not successful, remove the request from the cache. @@ -1536,7 +1535,8 @@ void Output::postFramebuffer() { void Output::renderCachedSets(const CompositionRefreshArgs& refreshArgs) { if (mPlanner) { - mPlanner->renderCachedSets(getState(), refreshArgs.scheduledFrameTime); + mPlanner->renderCachedSets(getState(), refreshArgs.scheduledFrameTime, + getState().usesDeviceComposition || getSkipColorTransform()); } } @@ -1631,5 +1631,9 @@ void Output::finishPrepareFrame() { mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition); } +bool Output::mustRecompose() const { + return mMustRecompose; +} + } // namespace impl } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index 9058f6709f..0731d4899c 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -159,7 +159,8 @@ void CachedSet::updateAge(std::chrono::steady_clock::time_point now) { } void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& texturePool, - const OutputCompositionState& outputState) { + const OutputCompositionState& outputState, + bool deviceHandlesColorTransform) { ATRACE_CALL(); const Rect& viewport = outputState.layerStackSpace.getContent(); const ui::Dataspace& outputDataspace = outputState.dataspace; @@ -170,6 +171,8 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te .physicalDisplay = outputState.framebufferSpace.getContent(), .clip = viewport, .outputDataspace = outputDataspace, + .colorTransform = outputState.colorTransformMatrix, + .deviceHandlesColorTransform = deviceHandlesColorTransform, .orientation = orientation, .targetLuminanceNits = outputState.displayBrightnessNits, }; @@ -270,11 +273,10 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te constexpr bool kUseFramebufferCache = false; - auto fenceResult = - toFenceResult(renderEngine - .drawLayers(displaySettings, layerSettings, texture->get(), - kUseFramebufferCache, std::move(bufferFence)) - .get()); + auto fenceResult = renderEngine + .drawLayers(displaySettings, layerSettings, texture->get(), + kUseFramebufferCache, std::move(bufferFence)) + .get(); if (fenceStatus(fenceResult) == NO_ERROR) { mDrawFence = std::move(fenceResult).value_or(Fence::NO_FENCE); diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index 1062b700dd..9175dd01a1 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -99,7 +99,8 @@ NonBufferHash Flattener::flattenLayers(const std::vector<const LayerState*>& lay void Flattener::renderCachedSets( const OutputCompositionState& outputState, - std::optional<std::chrono::steady_clock::time_point> renderDeadline) { + std::optional<std::chrono::steady_clock::time_point> renderDeadline, + bool deviceHandlesColorTransform) { ATRACE_CALL(); if (!mNewCachedSet) { @@ -136,7 +137,7 @@ void Flattener::renderCachedSets( } } - mNewCachedSet->render(mRenderEngine, mTexturePool, outputState); + mNewCachedSet->render(mRenderEngine, mTexturePool, outputState, deviceHandlesColorTransform); } void Flattener::dumpLayers(std::string& result) const { diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp index c8413eb8bc..54133d92b0 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp @@ -201,11 +201,11 @@ void Planner::reportFinalPlan( finalPlan); } -void Planner::renderCachedSets( - const OutputCompositionState& outputState, - std::optional<std::chrono::steady_clock::time_point> renderDeadline) { +void Planner::renderCachedSets(const OutputCompositionState& outputState, + std::optional<std::chrono::steady_clock::time_point> renderDeadline, + bool deviceHandlesColorTransform) { ATRACE_CALL(); - mFlattener.renderCachedSets(outputState, renderDeadline); + mFlattener.renderCachedSets(outputState, renderDeadline, deviceHandlesColorTransform); } void Planner::dump(const Vector<String16>& args, std::string& result) { diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index 51ca213f52..95459c0499 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -971,16 +971,40 @@ TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) { // We expect no calls to queueBuffer if composition was skipped. EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(0); + EXPECT_CALL(*renderSurface, beginFrame(false)); gpuDisplay->editState().isEnabled = true; gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region::INVALID_REGION; + gpuDisplay->editState().lastCompositionHadVisibleLayers = true; + gpuDisplay->beginFrame(); gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer)); } -TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { +TEST_F(DisplayFinishFrameTest, skipsCompositionIfEmpty) { + auto args = getDisplayCreationArgsForGpuVirtualDisplay(); + std::shared_ptr<impl::Display> gpuDisplay = impl::createDisplay(mCompositionEngine, args); + + mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); + gpuDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface)); + + // We expect no calls to queueBuffer if composition was skipped. + EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(0); + EXPECT_CALL(*renderSurface, beginFrame(false)); + + gpuDisplay->editState().isEnabled = true; + gpuDisplay->editState().usesClientComposition = false; + gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); + gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1)); + gpuDisplay->editState().lastCompositionHadVisibleLayers = false; + + gpuDisplay->beginFrame(); + gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer)); +} + +TEST_F(DisplayFinishFrameTest, performsCompositionIfDirtyAndNotEmpty) { auto args = getDisplayCreationArgsForGpuVirtualDisplay(); std::shared_ptr<impl::Display> gpuDisplay = impl::createDisplay(mCompositionEngine, args); @@ -989,11 +1013,15 @@ TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { // We expect a single call to queueBuffer when composition is not skipped. EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(1); + EXPECT_CALL(*renderSurface, beginFrame(true)); gpuDisplay->editState().isEnabled = true; gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1)); + gpuDisplay->editState().lastCompositionHadVisibleLayers = true; + + gpuDisplay->beginFrame(); gpuDisplay->finishFrame({}, std::move(mResultWithBuffer)); } diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 163a11ccd1..ace28648d7 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -39,7 +39,6 @@ #include "CallOrderStateMachineHelper.h" #include "MockHWC2.h" #include "RegionMatcher.h" -#include "TestUtils.h" namespace android::compositionengine { namespace { @@ -3527,9 +3526,8 @@ TEST_F(OutputComposeSurfacesTest, handlesZeroCompositionRequests) { .WillRepeatedly([&](const renderengine::DisplaySettings&, const std::vector<renderengine::LayerSettings>&, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) - -> std::future<renderengine::RenderEngineResult> { - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + base::unique_fd&&) -> ftl::Future<FenceResult> { + return ftl::yield<FenceResult>(Fence::NO_FENCE); }); verify().execute().expectAFenceWasReturned(); } @@ -3559,9 +3557,8 @@ TEST_F(OutputComposeSurfacesTest, buildsAndRendersRequestList) { .WillRepeatedly([&](const renderengine::DisplaySettings&, const std::vector<renderengine::LayerSettings>&, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) - -> std::future<renderengine::RenderEngineResult> { - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + base::unique_fd&&) -> ftl::Future<FenceResult> { + return ftl::yield<FenceResult>(Fence::NO_FENCE); }); verify().execute().expectAFenceWasReturned(); @@ -3594,9 +3591,8 @@ TEST_F(OutputComposeSurfacesTest, .WillRepeatedly([&](const renderengine::DisplaySettings&, const std::vector<renderengine::LayerSettings>&, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) - -> std::future<renderengine::RenderEngineResult> { - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + base::unique_fd&&) -> ftl::Future<FenceResult> { + return ftl::yield<FenceResult>(Fence::NO_FENCE); }); verify().execute().expectAFenceWasReturned(); @@ -3622,10 +3618,8 @@ TEST_F(OutputComposeSurfacesTest, renderDuplicateClientCompositionRequestsWithou EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .Times(2) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))) + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); verify().execute().expectAFenceWasReturned(); EXPECT_FALSE(mOutput.mState.reusedClientComposition); @@ -3653,8 +3647,7 @@ TEST_F(OutputComposeSurfacesTest, skipDuplicateClientCompositionRequests) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); verify().execute().expectAFenceWasReturned(); @@ -3693,9 +3686,8 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { .WillRepeatedly([&](const renderengine::DisplaySettings&, const std::vector<renderengine::LayerSettings>&, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) - -> std::future<renderengine::RenderEngineResult> { - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + base::unique_fd&&) -> ftl::Future<FenceResult> { + return ftl::yield<FenceResult>(Fence::NO_FENCE); }); verify().execute().expectAFenceWasReturned(); @@ -3726,11 +3718,9 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfRequestChanges) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r3), _, false, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); verify().execute().expectAFenceWasReturned(); EXPECT_FALSE(mOutput.mState.reusedClientComposition); @@ -3807,8 +3797,7 @@ struct OutputComposeSurfacesTest_UsesExpectedDisplaySettings : public OutputComp : public CallOrderStateMachineHelper<TestType, ExpectDisplaySettingsState> { auto thenExpectDisplaySettingsUsed(renderengine::DisplaySettings settings) { EXPECT_CALL(getInstance()->mRenderEngine, drawLayers(settings, _, _, false, _)) - .WillOnce(Return(ByMove(futureOf<renderengine::RenderEngineResult>( - {NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); return nextState<ExecuteState>(); } }; @@ -4061,14 +4050,12 @@ struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeS .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _)) - .WillRepeatedly( - [&](const renderengine::DisplaySettings&, - const std::vector<renderengine::LayerSettings>&, - const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { - return futureOf<renderengine::RenderEngineResult>( - {NO_ERROR, base::unique_fd()}); - }); + .WillRepeatedly([&](const renderengine::DisplaySettings&, + const std::vector<renderengine::LayerSettings>&, + const std::shared_ptr<renderengine::ExternalTexture>&, + const bool, base::unique_fd&&) -> ftl::Future<FenceResult> { + return ftl::yield<FenceResult>(Fence::NO_FENCE); + }); } Layer mLayer1; @@ -4133,8 +4120,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) { // Must happen after setting the protected content state. EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); base::unique_fd fd; std::shared_ptr<renderengine::ExternalTexture> tex; @@ -4226,8 +4212,7 @@ TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering, IfExepensiveOutputDatas EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); base::unique_fd fd; std::shared_ptr<renderengine::ExternalTexture> tex; @@ -4250,8 +4235,7 @@ struct OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur EXPECT_CALL(mOutput, generateClientCompositionRequests(_, kDefaultOutputDataspace, _)) .WillOnce(Return(std::vector<LayerFE::LayerSettings>{})); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _)) - .WillOnce(Return(ByMove(futureOf<renderengine::RenderEngineResult>( - {NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u)); EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)) .WillRepeatedly(Return(&mLayer.outputLayer)); diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index cb4c4e23fe..d5d688e705 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -28,8 +28,6 @@ #include <utils/Errors.h> #include <memory> -#include "tests/TestUtils.h" - namespace android::compositionengine { using namespace std::chrono_literals; @@ -353,11 +351,10 @@ TEST_F(CachedSetTest, renderUnsecureOutput) { clientComp2.emplace(); clientComp2->alpha = 0.75f; - const auto drawLayers = - [&](const renderengine::DisplaySettings& displaySettings, - const std::vector<renderengine::LayerSettings>& layers, - const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, + const std::vector<renderengine::LayerSettings>& layers, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&) -> ftl::Future<FenceResult> { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), @@ -365,7 +362,7 @@ TEST_F(CachedSetTest, renderUnsecureOutput) { EXPECT_EQ(0.5f, layers[0].alpha); EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + return ftl::yield<FenceResult>(Fence::NO_FENCE); }; EXPECT_CALL(*layerFE1, prepareClientComposition(ClientCompositionTargetSettingsSecureEq(false))) @@ -374,7 +371,7 @@ TEST_F(CachedSetTest, renderUnsecureOutput) { .WillOnce(Return(clientComp2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).WillOnce(Invoke(drawLayers)); mOutputState.isSecure = false; - cachedSet.render(mRenderEngine, mTexturePool, mOutputState); + cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true); expectReadyBuffer(cachedSet); EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace()); @@ -403,11 +400,10 @@ TEST_F(CachedSetTest, renderSecureOutput) { clientComp2.emplace(); clientComp2->alpha = 0.75f; - const auto drawLayers = - [&](const renderengine::DisplaySettings& displaySettings, - const std::vector<renderengine::LayerSettings>& layers, - const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, + const std::vector<renderengine::LayerSettings>& layers, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&) -> ftl::Future<FenceResult> { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), @@ -416,7 +412,7 @@ TEST_F(CachedSetTest, renderSecureOutput) { EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + return ftl::yield<FenceResult>(Fence::NO_FENCE); }; EXPECT_CALL(*layerFE1, prepareClientComposition(ClientCompositionTargetSettingsSecureEq(true))) @@ -425,7 +421,7 @@ TEST_F(CachedSetTest, renderSecureOutput) { .WillOnce(Return(clientComp2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).WillOnce(Invoke(drawLayers)); mOutputState.isSecure = true; - cachedSet.render(mRenderEngine, mTexturePool, mOutputState); + cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true); expectReadyBuffer(cachedSet); EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace()); @@ -454,13 +450,62 @@ TEST_F(CachedSetTest, renderWhitePoint) { mOutputState.displayBrightnessNits = 400.f; - const auto drawLayers = - [&](const renderengine::DisplaySettings& displaySettings, - const std::vector<renderengine::LayerSettings>&, - const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, + const std::vector<renderengine::LayerSettings>&, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&) -> ftl::Future<FenceResult> { + EXPECT_EQ(mOutputState.displayBrightnessNits, displaySettings.targetLuminanceNits); + return ftl::yield<FenceResult>(Fence::NO_FENCE); + }; + + EXPECT_CALL(*layerFE1, + prepareClientComposition(ClientCompositionTargetSettingsWhitePointEq( + mOutputState.displayBrightnessNits))) + .WillOnce(Return(clientComp1)); + EXPECT_CALL(*layerFE2, + prepareClientComposition(ClientCompositionTargetSettingsWhitePointEq( + mOutputState.displayBrightnessNits))) + .WillOnce(Return(clientComp2)); + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).WillOnce(Invoke(drawLayers)); + mOutputState.isSecure = true; + cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true); + expectReadyBuffer(cachedSet); + + EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace()); + EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds()); + + // Now check that appending a new cached set properly cleans up RenderEngine resources. + CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); + cachedSet.append(CachedSet(layer3)); +} + +TEST_F(CachedSetTest, renderWhitePointNoColorTransform) { + // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0) + // This is a duplicate of the "renderWhitePoint" test, but setting "deviceHandlesColorTransform" + // to false, in the render call. + + CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE; + CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE; + + CachedSet cachedSet(layer1); + cachedSet.append(CachedSet(layer2)); + + std::optional<compositionengine::LayerFE::LayerSettings> clientComp1; + clientComp1.emplace(); + + std::optional<compositionengine::LayerFE::LayerSettings> clientComp2; + clientComp2.emplace(); + + mOutputState.displayBrightnessNits = 400.f; + + const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, + const std::vector<renderengine::LayerSettings>&, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&) -> ftl::Future<FenceResult> { EXPECT_EQ(mOutputState.displayBrightnessNits, displaySettings.targetLuminanceNits); - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + return ftl::yield<FenceResult>(Fence::NO_FENCE); }; EXPECT_CALL(*layerFE1, @@ -473,7 +518,7 @@ TEST_F(CachedSetTest, renderWhitePoint) { .WillOnce(Return(clientComp2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).WillOnce(Invoke(drawLayers)); mOutputState.isSecure = true; - cachedSet.render(mRenderEngine, mTexturePool, mOutputState); + cachedSet.render(mRenderEngine, mTexturePool, mOutputState, false); expectReadyBuffer(cachedSet); EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace()); @@ -504,11 +549,10 @@ TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) { mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(2, 3, 10, 5)); - const auto drawLayers = - [&](const renderengine::DisplaySettings& displaySettings, - const std::vector<renderengine::LayerSettings>& layers, - const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, + const std::vector<renderengine::LayerSettings>& layers, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&) -> ftl::Future<FenceResult> { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), @@ -517,13 +561,13 @@ TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) { EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + return ftl::yield<FenceResult>(Fence::NO_FENCE); }; EXPECT_CALL(*layerFE1, prepareClientComposition(_)).WillOnce(Return(clientComp1)); EXPECT_CALL(*layerFE2, prepareClientComposition(_)).WillOnce(Return(clientComp2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).WillOnce(Invoke(drawLayers)); - cachedSet.render(mRenderEngine, mTexturePool, mOutputState); + cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true); expectReadyBuffer(cachedSet); EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace()); @@ -735,11 +779,10 @@ TEST_F(CachedSetTest, addHolePunch) { EXPECT_CALL(*layerFE2, prepareClientComposition(_)).WillOnce(Return(clientComp2)); EXPECT_CALL(*layerFE3, prepareClientComposition(_)).WillOnce(Return(clientComp3)); - const auto drawLayers = - [&](const renderengine::DisplaySettings&, - const std::vector<renderengine::LayerSettings>& layers, - const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + const auto drawLayers = [&](const renderengine::DisplaySettings&, + const std::vector<renderengine::LayerSettings>& layers, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&) -> ftl::Future<FenceResult> { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); @@ -759,11 +802,11 @@ TEST_F(CachedSetTest, addHolePunch) { EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); } - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + return ftl::yield<FenceResult>(Fence::NO_FENCE); }; EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).WillOnce(Invoke(drawLayers)); - cachedSet.render(mRenderEngine, mTexturePool, mOutputState); + cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true); } TEST_F(CachedSetTest, addHolePunch_noBuffer) { @@ -796,11 +839,10 @@ TEST_F(CachedSetTest, addHolePunch_noBuffer) { EXPECT_CALL(*layerFE2, prepareClientComposition(_)).WillOnce(Return(clientComp2)); EXPECT_CALL(*layerFE3, prepareClientComposition(_)).WillOnce(Return(clientComp3)); - const auto drawLayers = - [&](const renderengine::DisplaySettings&, - const std::vector<renderengine::LayerSettings>& layers, - const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + const auto drawLayers = [&](const renderengine::DisplaySettings&, + const std::vector<renderengine::LayerSettings>& layers, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&) -> ftl::Future<FenceResult> { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); @@ -821,11 +863,11 @@ TEST_F(CachedSetTest, addHolePunch_noBuffer) { EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); } - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + return ftl::yield<FenceResult>(Fence::NO_FENCE); }; EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).WillOnce(Invoke(drawLayers)); - cachedSet.render(mRenderEngine, mTexturePool, mOutputState); + cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true); } TEST_F(CachedSetTest, append_removesHolePunch) { @@ -948,11 +990,10 @@ TEST_F(CachedSetTest, addBlur) { BackgroundBlurOnly))) .WillOnce(Return(clientComp3)); - const auto drawLayers = - [&](const renderengine::DisplaySettings&, - const std::vector<renderengine::LayerSettings>& layers, - const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + const auto drawLayers = [&](const renderengine::DisplaySettings&, + const std::vector<renderengine::LayerSettings>& layers, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&) -> ftl::Future<FenceResult> { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 3u); @@ -961,11 +1002,11 @@ TEST_F(CachedSetTest, addBlur) { EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings.source.solidColor); EXPECT_EQ(0.0f, blurSettings.alpha); - return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}); + return ftl::yield<FenceResult>(Fence::NO_FENCE); }; EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).WillOnce(Invoke(drawLayers)); - cachedSet.render(mRenderEngine, mTexturePool, mOutputState); + cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true); } } // namespace diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp index b624d1a2ea..86cfee6f0a 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp @@ -27,8 +27,6 @@ #include <renderengine/mock/RenderEngine.h> #include <chrono> -#include "tests/TestUtils.h" - namespace android::compositionengine { using namespace std::chrono_literals; using impl::planner::CachedSet; @@ -159,25 +157,24 @@ void FlattenerTest::initializeFlattener(const std::vector<const LayerState*>& la initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // same geometry, update the internal layer stack initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); } void FlattenerTest::expectAllLayersFlattened(const std::vector<const LayerState*>& layers) { // layers would be flattened but the buffer would not be overridden EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); for (const auto layer : layers) { EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer); @@ -187,7 +184,7 @@ void FlattenerTest::expectAllLayersFlattened(const std::vector<const LayerState* initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); const auto buffer = layers[0]->getOutputLayer()->getState().overrideInfo.buffer; EXPECT_NE(nullptr, buffer); @@ -222,7 +219,7 @@ TEST_F(FlattenerTest, flattenLayers_ActiveLayersAreNotFlattened) { initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); } TEST_F(FlattenerTest, flattenLayers_ActiveLayersWithLowFpsAreFlattened) { @@ -284,7 +281,7 @@ TEST_F(FlattenerTest, flattenLayers_FlattenedLayersStayFlattenWhenNoUpdate) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -389,7 +386,7 @@ TEST_F(FlattenerTest, flattenLayers_addLayerToFlattenedCauseReset) { initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_EQ(nullptr, overrideBuffer1); EXPECT_EQ(nullptr, overrideBuffer2); @@ -423,12 +420,11 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateToFlatten) { layerState1->resetFramesSinceBufferUpdate(); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_EQ(nullptr, overrideBuffer1); EXPECT_EQ(nullptr, overrideBuffer2); @@ -437,7 +433,7 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateToFlatten) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_EQ(nullptr, overrideBuffer1); EXPECT_NE(nullptr, overrideBuffer2); @@ -447,12 +443,11 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateToFlatten) { mTime += 200ms; EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_EQ(nullptr, overrideBuffer1); EXPECT_NE(nullptr, overrideBuffer2); @@ -461,7 +456,7 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateToFlatten) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -500,12 +495,11 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateForMiddleLayer) { layerState3->resetFramesSinceBufferUpdate(); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_EQ(nullptr, overrideBuffer1); EXPECT_EQ(nullptr, overrideBuffer2); @@ -515,13 +509,12 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateForMiddleLayer) { // Layers 1 and 2 will be flattened a new drawFrame would be called for Layer4 and Layer5 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); mOutputState.framebufferSpace.setOrientation(ui::ROTATION_90); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -534,7 +527,7 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateForMiddleLayer) { EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); mOutputState.framebufferSpace.setOrientation(ui::ROTATION_180); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -545,12 +538,11 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateForMiddleLayer) { layerState3->incrementFramesSinceBufferUpdate(); mTime += 200ms; EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -562,7 +554,7 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateForMiddleLayer) { EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); mOutputState.framebufferSpace.setOrientation(ui::ROTATION_270); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -601,9 +593,8 @@ TEST_F(FlattenerTest, flattenLayers_pipRequiresRoundedCorners) { // This will render a CachedSet. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We've rendered a CachedSet, but we haven't merged it in. EXPECT_EQ(nullptr, overrideBuffer1); @@ -616,7 +607,7 @@ TEST_F(FlattenerTest, flattenLayers_pipRequiresRoundedCorners) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -666,9 +657,8 @@ TEST_F(FlattenerTest, flattenLayers_pip) { // This will render a CachedSet. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We've rendered a CachedSet, but we haven't merged it in. EXPECT_EQ(nullptr, overrideBuffer1); @@ -681,7 +671,7 @@ TEST_F(FlattenerTest, flattenLayers_pip) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -739,9 +729,8 @@ TEST_F(FlattenerTest, flattenLayers_holePunchSingleLayer) { // This will render a CachedSet of layer 0. Though it is just one layer, it satisfies the // exception that there would be a hole punch above it. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We've rendered a CachedSet, but we haven't merged it in. EXPECT_EQ(nullptr, overrideBuffer0); @@ -751,7 +740,7 @@ TEST_F(FlattenerTest, flattenLayers_holePunchSingleLayer) { initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer0); // got overridden EXPECT_EQ(nullptr, overrideBuffer1); // did not @@ -810,9 +799,8 @@ TEST_F(FlattenerTest, flattenLayers_holePunchSingleColorLayer) { // This will render a CachedSet of layer 0. Though it is just one layer, it satisfies the // exception that there would be a hole punch above it. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We've rendered a CachedSet, but we haven't merged it in. EXPECT_EQ(nullptr, overrideBuffer0); @@ -822,7 +810,7 @@ TEST_F(FlattenerTest, flattenLayers_holePunchSingleColorLayer) { initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer0); // got overridden EXPECT_EQ(nullptr, overrideBuffer1); // did not @@ -862,13 +850,12 @@ TEST_F(FlattenerTest, flattenLayers_flattensBlurBehindRunIfFirstRun) { // layers would be flattened but the buffer would not be overridden EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); for (const auto layer : layers) { EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer); @@ -878,7 +865,7 @@ TEST_F(FlattenerTest, flattenLayers_flattensBlurBehindRunIfFirstRun) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); EXPECT_EQ(nullptr, overrideBuffer3); @@ -908,13 +895,12 @@ TEST_F(FlattenerTest, flattenLayers_doesNotFlattenBlurBehindRun) { // layers would be flattened but the buffer would not be overridden EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillRepeatedly(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillRepeatedly(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); for (const auto layer : layers) { EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer); @@ -925,7 +911,7 @@ TEST_F(FlattenerTest, flattenLayers_doesNotFlattenBlurBehindRun) { initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); for (const auto layer : layers) { EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer); } @@ -962,13 +948,12 @@ TEST_F(FlattenerTest, flattenLayers_flattenSkipsLayerWithBlurBehind) { // layers would be flattened but the buffer would not be overridden EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); for (const auto layer : layers) { EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer); @@ -978,7 +963,7 @@ TEST_F(FlattenerTest, flattenLayers_flattenSkipsLayerWithBlurBehind) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_EQ(nullptr, overrideBuffer1); EXPECT_EQ(nullptr, blurOverrideBuffer); EXPECT_NE(nullptr, overrideBuffer3); @@ -1011,13 +996,12 @@ TEST_F(FlattenerTest, flattenLayers_whenBlurLayerIsChanging_appliesBlurToInactiv // layers would be flattened but the buffer would not be overridden EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); const auto& cachedSet = mFlattener->getNewCachedSetForTesting(); ASSERT_NE(std::nullopt, cachedSet); @@ -1031,7 +1015,7 @@ TEST_F(FlattenerTest, flattenLayers_whenBlurLayerIsChanging_appliesBlurToInactiv initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer2, overrideBuffer1); EXPECT_EQ(nullptr, blurOverrideBuffer); @@ -1054,13 +1038,12 @@ TEST_F(FlattenerTest, flattenLayers_renderCachedSets_doesNotRenderTwice) { mTime += 200ms; // layers would be flattened but the buffer would not be overridden EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); initializeOverrideBuffer(layers); EXPECT_EQ(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_EQ(nullptr, overrideBuffer1); EXPECT_EQ(nullptr, overrideBuffer2); @@ -1068,12 +1051,12 @@ TEST_F(FlattenerTest, flattenLayers_renderCachedSets_doesNotRenderTwice) { // Simulate attempting to render prior to merging the new cached set with the layer stack. // Here we should not try to re-render. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We provide the override buffer now that it's rendered EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer2, overrideBuffer1); @@ -1117,15 +1100,16 @@ TEST_F(FlattenerRenderSchedulingTest, flattenLayers_renderCachedSets_defersUpToM EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0); mFlattener->renderCachedSets(mOutputState, std::chrono::steady_clock::now() - - (kCachedSetRenderDuration + 10ms)); + (kCachedSetRenderDuration + 10ms), + true); } EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); mFlattener->renderCachedSets(mOutputState, std::chrono::steady_clock::now() - - (kCachedSetRenderDuration + 10ms)); + (kCachedSetRenderDuration + 10ms), + true); } TEST_F(FlattenerTest, flattenLayers_skipsBT601_625) { @@ -1157,9 +1141,8 @@ TEST_F(FlattenerTest, flattenLayers_skipsBT601_625) { // This will render a CachedSet. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We've rendered a CachedSet, but we haven't merged it in. EXPECT_EQ(nullptr, overrideBuffer1); @@ -1172,7 +1155,7 @@ TEST_F(FlattenerTest, flattenLayers_skipsBT601_625) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -1208,9 +1191,8 @@ TEST_F(FlattenerTest, flattenLayers_skipsHDR) { // This will render a CachedSet. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We've rendered a CachedSet, but we haven't merged it in. EXPECT_EQ(nullptr, overrideBuffer1); @@ -1223,7 +1205,7 @@ TEST_F(FlattenerTest, flattenLayers_skipsHDR) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -1259,9 +1241,8 @@ TEST_F(FlattenerTest, flattenLayers_skipsHDR2) { // This will render a CachedSet. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We've rendered a CachedSet, but we haven't merged it in. EXPECT_EQ(nullptr, overrideBuffer1); @@ -1274,7 +1255,7 @@ TEST_F(FlattenerTest, flattenLayers_skipsHDR2) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); @@ -1313,9 +1294,8 @@ TEST_F(FlattenerTest, flattenLayers_skipsColorLayers) { // This will render a CachedSet. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We've rendered a CachedSet, but we haven't merged it in. EXPECT_EQ(nullptr, overrideBuffer1); @@ -1329,7 +1309,7 @@ TEST_F(FlattenerTest, flattenLayers_skipsColorLayers) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_EQ(nullptr, overrideBuffer1); EXPECT_EQ(nullptr, overrideBuffer2); @@ -1366,9 +1346,8 @@ TEST_F(FlattenerTest, flattenLayers_includes_DISPLAY_DECORATION) { // This will render a CachedSet. EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE)))); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); // We've rendered a CachedSet, but we haven't merged it in. EXPECT_EQ(nullptr, overrideBuffer1); @@ -1381,7 +1360,7 @@ TEST_F(FlattenerTest, flattenLayers_includes_DISPLAY_DECORATION) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); + mFlattener->renderCachedSets(mOutputState, std::nullopt, true); EXPECT_NE(nullptr, overrideBuffer1); EXPECT_EQ(overrideBuffer1, overrideBuffer2); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index bff301edd1..2866a34a57 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -104,7 +104,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) mCompositionDisplay->getRenderSurface()->initialize(); - setPowerMode(args.initialPowerMode); + if (args.initialPowerMode.has_value()) setPowerMode(args.initialPowerMode.value()); // initialize the display orientation transform. setProjection(ui::ROTATION_0, Rect::INVALID_RECT, Rect::INVALID_RECT); @@ -170,19 +170,21 @@ auto DisplayDevice::getInputInfo() const -> InputInfo { void DisplayDevice::setPowerMode(hal::PowerMode mode) { mPowerMode = mode; - getCompositionDisplay()->setCompositionEnabled(mPowerMode != hal::PowerMode::OFF); + + getCompositionDisplay()->setCompositionEnabled(mPowerMode.has_value() && + *mPowerMode != hal::PowerMode::OFF); } void DisplayDevice::enableLayerCaching(bool enable) { getCompositionDisplay()->setLayerCachingEnabled(enable); } -hal::PowerMode DisplayDevice::getPowerMode() const { +std::optional<hal::PowerMode> DisplayDevice::getPowerMode() const { return mPowerMode; } bool DisplayDevice::isPoweredOn() const { - return mPowerMode != hal::PowerMode::OFF; + return mPowerMode && *mPowerMode != hal::PowerMode::OFF; } void DisplayDevice::setActiveMode(DisplayModeId id) { @@ -369,7 +371,7 @@ void DisplayDevice::dump(std::string& result) const { } result += "\n powerMode="s; - result += to_string(mPowerMode); + result += mPowerMode.has_value() ? to_string(mPowerMode.value()) : "OFF(reset)"; result += '\n'; if (mRefreshRateConfigs) { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 10fc0954ad..3eead178d3 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -181,7 +181,7 @@ public: /* ------------------------------------------------------------------------ * Display power mode management. */ - hardware::graphics::composer::hal::PowerMode getPowerMode() const; + std::optional<hardware::graphics::composer::hal::PowerMode> getPowerMode() const; void setPowerMode(hardware::graphics::composer::hal::PowerMode mode); bool isPoweredOn() const; @@ -280,8 +280,8 @@ private: static ui::Transform::RotationFlags sPrimaryDisplayRotationFlags; - hardware::graphics::composer::hal::PowerMode mPowerMode = - hardware::graphics::composer::hal::PowerMode::OFF; + // allow initial power mode as null. + std::optional<hardware::graphics::composer::hal::PowerMode> mPowerMode; DisplayModePtr mActiveMode; std::optional<float> mStagedBrightness = std::nullopt; float mBrightness = -1.f; @@ -365,8 +365,7 @@ struct DisplayDeviceCreationArgs { HdrCapabilities hdrCapabilities; int32_t supportedPerFrameMetadata{0}; std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hwcColorModes; - hardware::graphics::composer::hal::PowerMode initialPowerMode{ - hardware::graphics::composer::hal::PowerMode::ON}; + std::optional<hardware::graphics::composer::hal::PowerMode> initialPowerMode; bool isPrimary{false}; DisplayModes supportedModes; DisplayModeId activeModeId; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index dfff8fe8ee..8a401eb597 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -111,16 +111,11 @@ Layer::Layer(const LayerCreationArgs& args) sSequence = *args.sequence + 1; } mDrawingState.flags = layerFlags; - mDrawingState.active_legacy.transform.set(0, 0); mDrawingState.crop.makeInvalid(); - mDrawingState.requestedCrop = mDrawingState.crop; mDrawingState.z = 0; mDrawingState.color.a = 1.0f; mDrawingState.layerStack = ui::DEFAULT_LAYER_STACK; mDrawingState.sequence = 0; - mDrawingState.requested_legacy = mDrawingState.active_legacy; - mDrawingState.width = UINT32_MAX; - mDrawingState.height = UINT32_MAX; mDrawingState.transform.set(0, 0); mDrawingState.frameNumber = 0; mDrawingState.bufferTransform = 0; @@ -875,20 +870,6 @@ bool Layer::isTrustedOverlay() const { return (p != nullptr) && p->isTrustedOverlay(); } -bool Layer::setSize(uint32_t w, uint32_t h) { - if (mDrawingState.requested_legacy.w == w && mDrawingState.requested_legacy.h == h) - return false; - mDrawingState.requested_legacy.w = w; - mDrawingState.requested_legacy.h = h; - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); - - // record the new size, from this point on, when the client request - // a buffer, it'll get the new size. - setDefaultBufferSize(mDrawingState.requested_legacy.w, mDrawingState.requested_legacy.h); - return true; -} - bool Layer::setAlpha(float alpha) { if (mDrawingState.color.a == alpha) return false; mDrawingState.sequence++; @@ -978,7 +959,8 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { } bool Layer::setTransparentRegionHint(const Region& transparent) { - mDrawingState.requestedTransparentRegion_legacy = transparent; + mDrawingState.sequence++; + mDrawingState.transparentRegionHint = transparent; mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -1007,9 +989,8 @@ bool Layer::setFlags(uint32_t flags, uint32_t mask) { } bool Layer::setCrop(const Rect& crop) { - if (mDrawingState.requestedCrop == crop) return false; + if (mDrawingState.crop == crop) return false; mDrawingState.sequence++; - mDrawingState.requestedCrop = crop; mDrawingState.crop = crop; mDrawingState.modified = true; @@ -1433,7 +1414,6 @@ gui::LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const sp<Layer> parent = mDrawingParent.promote(); info.mParentName = parent ? parent->getName() : "none"s; info.mType = getType(); - info.mTransparentRegion = ds.activeTransparentRegion_legacy; info.mVisibleRegion = getVisibleRegion(display); info.mSurfaceDamageRegion = surfaceDamageRegion; @@ -1441,8 +1421,6 @@ gui::LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const info.mX = ds.transform.tx(); info.mY = ds.transform.ty(); info.mZ = ds.z; - info.mWidth = ds.width; - info.mHeight = ds.height; info.mCrop = ds.crop; info.mColor = ds.color; info.mFlags = ds.flags; @@ -2141,7 +2119,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet } } - LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy, + LayerProtoHelper::writeToProto(state.transparentRegionHint, [&]() { return layerInfo->mutable_transparent_region(); }); layerInfo->set_layer_stack(getLayerStack().id); @@ -2151,9 +2129,6 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet return layerInfo->mutable_requested_position(); }); - LayerProtoHelper::writeSizeToProto(state.width, state.height, - [&]() { return layerInfo->mutable_size(); }); - LayerProtoHelper::writeToProto(state.crop, [&]() { return layerInfo->mutable_crop(); }); layerInfo->set_is_opaque(isOpaque(state)); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6e83b235d4..b05a4a04e5 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -150,40 +150,23 @@ public: using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility; struct State { - Geometry active_legacy; - Geometry requested_legacy; int32_t z; - ui::LayerStack layerStack; - uint32_t flags; - uint8_t reserved[2]; int32_t sequence; // changes when visible regions can change bool modified; - // Crop is expressed in layer space coordinate. Rect crop; - Rect requestedCrop; - - // the transparentRegion hint is a bit special, it's latched only - // when we receive a buffer -- this is because it's "content" - // dependent. - Region activeTransparentRegion_legacy; - Region requestedTransparentRegion_legacy; - LayerMetadata metadata; - // If non-null, a Surface this Surface's Z-order is interpreted relative to. wp<Layer> zOrderRelativeOf; bool isRelativeOf{false}; // A list of surfaces whose Z-order is interpreted relative to ours. SortedVector<wp<Layer>> zOrderRelatives; - half4 color; float cornerRadius; int backgroundBlurRadius; - gui::WindowInfo inputInfo; wp<Layer> touchableRegionCrop; @@ -192,15 +175,10 @@ public: // The fields below this point are only used by BufferStateLayer uint64_t frameNumber; - uint32_t width; - uint32_t height; ui::Transform transform; - uint32_t bufferTransform; bool transformToDisplayInverse; - Region transparentRegionHint; - std::shared_ptr<renderengine::ExternalTexture> buffer; client_cache_t clientCacheId; sp<Fence> acquireFence; @@ -208,11 +186,9 @@ public: HdrMetadata hdrMetadata; Region surfaceDamageRegion; int32_t api; - sp<NativeHandle> sidebandStream; mat4 colorTransform; bool hasColorTransform; - // pointer to background color layer that, if set, appears below the buffer state layer // and the buffer state layer's children. Z order will be set to // INT_MIN @@ -237,7 +213,6 @@ public: // Default frame rate compatibility used to set the layer refresh rate votetype. FrameRateCompatibility defaultFrameRateCompatibility; - FrameRate frameRate; // The combined frame rate of parents / children of this layer @@ -257,7 +232,6 @@ public: // When the transaction was posted nsecs_t postTime; - sp<ITransactionCompletedListener> releaseBufferListener; // SurfaceFrame that tracks the timeline of Transactions that contain a Buffer. Only one // such SurfaceFrame exists because only one buffer can be presented on the layer per vsync. @@ -278,16 +252,11 @@ public: // Whether or not this layer is a trusted overlay for input bool isTrustedOverlay; - Rect bufferCrop; Rect destinationFrame; - sp<IBinder> releaseBufferEndpoint; - gui::DropInputMode dropInputMode; - bool autoRefresh = false; - bool dimmingEnabled = true; }; @@ -345,32 +314,6 @@ public: virtual sp<Layer> createClone() = 0; - // Geometry setting functions. - // - // The following group of functions are used to specify the layers - // bounds, and the mapping of the texture on to those bounds. According - // to various settings changes to them may apply immediately, or be delayed until - // a pending resize is completed by the producer submitting a buffer. For example - // if we were to change the buffer size, and update the matrix ahead of the - // new buffer arriving, then we would be stretching the buffer to a different - // aspect before and after the buffer arriving, which probably isn't what we wanted. - // - // The first set of geometry functions are controlled by the scaling mode, described - // in window.h. The scaling mode may be set by the client, as it submits buffers. - // - // Put simply, if our scaling mode is SCALING_MODE_FREEZE, then - // matrix updates will not be applied while a resize is pending - // and the size and transform will remain in their previous state - // until a new buffer is submitted. If the scaling mode is another value - // then the old-buffer will immediately be scaled to the pending size - // and the new matrix will be immediately applied following this scaling - // transformation. - - // Set the default buffer size for the assosciated Producer, in pixels. This is - // also the rendered size of the layer prior to any transformations. Parent - // or local matrix transformations will not affect the size of the buffer, - // but may affect it's on-screen size or clipping. - virtual bool setSize(uint32_t w, uint32_t h); // Set a 2x2 transformation matrix on the layer. This transform // will be applied after parent transforms, but before any final // producer specified transform. @@ -407,7 +350,7 @@ public: // is specified in pixels. virtual bool setBackgroundBlurRadius(int backgroundBlurRadius); virtual bool setBlurRegions(const std::vector<BlurRegion>& effectRegions); - virtual bool setTransparentRegionHint(const Region& transparent); + bool setTransparentRegionHint(const Region& transparent); virtual bool setTrustedOverlay(bool); virtual bool setFlags(uint32_t flags, uint32_t mask); virtual bool setLayerStack(ui::LayerStack); @@ -500,11 +443,9 @@ public: // to avoid grabbing the lock again to avoid deadlock virtual bool isCreatedFromMainThread() const { return false; } - uint32_t getActiveWidth(const Layer::State& s) const { return s.width; } - uint32_t getActiveHeight(const Layer::State& s) const { return s.height; } ui::Transform getActiveTransform(const Layer::State& s) const { return s.transform; } - virtual Region getActiveTransparentRegion(const Layer::State& s) const { - return s.activeTransparentRegion_legacy; + Region getActiveTransparentRegion(const Layer::State& s) const { + return s.transparentRegionHint; } virtual Rect getCrop(const Layer::State& s) const { return s.crop; } virtual bool needsFiltering(const DisplayDevice*) const { return false; } @@ -524,8 +465,6 @@ public: virtual void updateCloneBufferInfo(){}; - virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} - virtual bool isHdrY410() const { return false; } /* diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS index 2ece51c3dc..6011d0d0f7 100644 --- a/services/surfaceflinger/OWNERS +++ b/services/surfaceflinger/OWNERS @@ -2,6 +2,7 @@ adyabr@google.com alecmouri@google.com chaviw@google.com lpy@google.com +pdwilliams@google.com racarr@google.com scroggo@google.com -vishnun@google.com
\ No newline at end of file +vishnun@google.com diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 803eb4f91f..a48c921378 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -42,9 +42,9 @@ struct RefreshRateScore { DisplayModeIterator modeIt; float overallScore; struct { - float belowThreshold; - float aboveThreshold; - } fixedRateLayersScore; + float modeBelowThreshold; + float modeAboveThreshold; + } fixedRateBelowThresholdLayersScore; }; template <typename Iterator> @@ -385,7 +385,7 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire const auto weight = layer.weight; - for (auto& [modeIt, overallScore, fixedRateScore] : scores) { + for (auto& [modeIt, overallScore, fixedRateBelowThresholdLayersScore] : scores) { const auto& [id, mode] = *modeIt; const bool isSeamlessSwitch = mode->getGroup() == mActiveModeIt->second->getGroup(); @@ -431,7 +431,7 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire calculateLayerScoreLocked(layer, mode->getFps(), isSeamlessSwitch); const float weightedLayerScore = weight * layerScore; - // Layer with fixed source has a special consideration depends on the + // Layer with fixed source has a special consideration which depends on the // mConfig.frameRateMultipleThreshold. We don't want these layers to score // refresh rates above the threshold, but we also don't want to favor the lower // ones by having a greater number of layers scoring them. Instead, we calculate @@ -451,21 +451,22 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire return false; } }(layer.vote); - const bool layerAboveThreshold = mConfig.frameRateMultipleThreshold != 0 && - mode->getFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold) && + const bool layerBelowThreshold = mConfig.frameRateMultipleThreshold != 0 && layer.desiredRefreshRate < Fps::fromValue(mConfig.frameRateMultipleThreshold / 2); - if (fixedSourceLayer) { - if (layerAboveThreshold) { + if (fixedSourceLayer && layerBelowThreshold) { + const bool modeAboveThreshold = + mode->getFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold); + if (modeAboveThreshold) { ALOGV("%s gives %s fixed source (above threshold) score of %.4f", formatLayerInfo(layer, weight).c_str(), to_string(mode->getFps()).c_str(), layerScore); - fixedRateScore.aboveThreshold += weightedLayerScore; + fixedRateBelowThresholdLayersScore.modeAboveThreshold += weightedLayerScore; } else { ALOGV("%s gives %s fixed source (below threshold) score of %.4f", formatLayerInfo(layer, weight).c_str(), to_string(mode->getFps()).c_str(), layerScore); - fixedRateScore.belowThreshold += weightedLayerScore; + fixedRateBelowThresholdLayersScore.modeBelowThreshold += weightedLayerScore; } } else { ALOGV("%s gives %s score of %.4f", formatLayerInfo(layer, weight).c_str(), @@ -476,7 +477,7 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire } // We want to find the best refresh rate without the fixed source layers, - // so we could know whether we should add the aboveThreshold scores or not. + // so we could know whether we should add the modeAboveThreshold scores or not. // If the best refresh rate is already above the threshold, it means that // some non-fixed source layers already scored it, so we can just add the score // for all fixed source layers, even the ones that are above the threshold. @@ -500,10 +501,10 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire }(); // Now we can add the fixed rate layers score - for (auto& [modeIt, overallScore, fixedRateScore] : scores) { - overallScore += fixedRateScore.belowThreshold; + for (auto& [modeIt, overallScore, fixedRateBelowThresholdLayersScore] : scores) { + overallScore += fixedRateBelowThresholdLayersScore.modeBelowThreshold; if (maxScoreAboveThreshold) { - overallScore += fixedRateScore.aboveThreshold; + overallScore += fixedRateBelowThresholdLayersScore.modeAboveThreshold; } ALOGV("%s adjusted overallScore is %.4f", to_string(modeIt->second->getFps()).c_str(), overallScore); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0707b3593d..3acf203b0a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2793,7 +2793,8 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( ALOGV("Display Orientation: %s", toCString(creationArgs.physicalOrientation)); // virtual displays are always considered enabled - creationArgs.initialPowerMode = state.isVirtual() ? hal::PowerMode::ON : hal::PowerMode::OFF; + creationArgs.initialPowerMode = + state.isVirtual() ? std::make_optional(hal::PowerMode::ON) : std::nullopt; sp<DisplayDevice> display = getFactory().createDisplayDevice(creationArgs); @@ -4256,11 +4257,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime } } } - if (what & layer_state_t::eSizeChanged) { - if (layer->setSize(s.w, s.h)) { - flags |= eTraversalNeeded; - } - } if (what & layer_state_t::eAlphaChanged) { if (layer->setAlpha(s.alpha)) flags |= eTraversalNeeded; @@ -4717,8 +4713,8 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: const auto displayId = display->getPhysicalId(); ALOGD("Setting power mode %d on display %s", mode, to_string(displayId).c_str()); - const hal::PowerMode currentMode = display->getPowerMode(); - if (mode == currentMode) { + std::optional<hal::PowerMode> currentMode = display->getPowerMode(); + if (currentMode.has_value() && mode == *currentMode) { return; } @@ -4734,7 +4730,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode)); } const auto refreshRate = display->refreshRateConfigs().getActiveMode()->getFps(); - if (currentMode == hal::PowerMode::OFF) { + if (*currentMode == hal::PowerMode::OFF) { // Turn on the display if (display->isInternal() && (!activeDisplay || !activeDisplay->isPoweredOn())) { onActiveDisplayChangedLocked(display); @@ -4764,7 +4760,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: if (SurfaceFlinger::setSchedAttr(false) != NO_ERROR) { ALOGW("Couldn't set uclamp.min on display off: %s\n", strerror(errno)); } - if (isDisplayActiveLocked(display) && currentMode != hal::PowerMode::DOZE_SUSPEND) { + if (isDisplayActiveLocked(display) && *currentMode != hal::PowerMode::DOZE_SUSPEND) { mScheduler->disableHardwareVsync(true); mScheduler->onScreenReleased(mAppConnectionHandle); } @@ -4778,7 +4774,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) { // Update display while dozing getHwComposer().setPowerMode(displayId, mode); - if (isDisplayActiveLocked(display) && currentMode == hal::PowerMode::DOZE_SUSPEND) { + if (isDisplayActiveLocked(display) && *currentMode == hal::PowerMode::DOZE_SUSPEND) { ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON."); mVisibleRegionsDirty = true; scheduleRepaint(); @@ -6444,7 +6440,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( std::unique_ptr<RenderArea> renderArea = renderAreaFuture.get(); if (!renderArea) { ALOGW("Skipping screen capture because of invalid render area."); - captureResults.result = NO_MEMORY; + captureResults.fenceResult = base::unexpected(NO_MEMORY); captureListener->onScreenCaptureCompleted(captureResults); return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share(); } @@ -6461,9 +6457,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( return ftl::Future(std::move(renderFuture)) .then([captureListener, captureResults = std::move(captureResults)]( FenceResult fenceResult) mutable -> FenceResult { - // TODO(b/232535621): Change ScreenCaptureResults to store a FenceResult. - captureResults.result = fenceStatus(fenceResult); - captureResults.fence = std::move(fenceResult).value_or(Fence::NO_FENCE); + captureResults.fenceResult = std::move(fenceResult); captureListener->onScreenCaptureCompleted(captureResults); return base::unexpected(NO_ERROR); }) @@ -6620,13 +6614,11 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( getRenderEngine().useProtectedContext(useProtected); constexpr bool kUseFramebufferCache = false; - auto chain = - ftl::Future(getRenderEngine().drawLayers(clientCompositionDisplay, - clientRenderEngineLayers, buffer, - kUseFramebufferCache, std::move(bufferFence))) - .then(&toFenceResult); + const auto future = getRenderEngine() + .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, + buffer, kUseFramebufferCache, std::move(bufferFence)) + .share(); - const auto future = chain.share(); for (auto* layer : renderedLayers) { layer->onLayerDisplayed(future); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2b230b3003..310188512d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -52,11 +52,11 @@ #include <utils/Trace.h> #include <utils/threads.h> -#include <compositionengine/FenceResult.h> #include <compositionengine/OutputColorSetting.h> #include <scheduler/Fps.h> #include <scheduler/PresentLatencyTracker.h> #include <scheduler/Time.h> +#include <ui/FenceResult.h> #include "ClientCache.h" #include "DisplayDevice.h" diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 66691c2a31..6797aa697b 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -135,8 +135,6 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, layer->mDrawingState.transform.ty()); addDepthLocked(transaction, layerId, layer->mDrawingState.z); addAlphaLocked(transaction, layerId, layer->mDrawingState.color.a); - addTransparentRegionLocked(transaction, layerId, - layer->mDrawingState.activeTransparentRegion_legacy); addLayerStackLocked(transaction, layerId, layer->mDrawingState.layerStack); addCropLocked(transaction, layerId, layer->mDrawingState.crop); addCornerRadiusLocked(transaction, layerId, layer->mDrawingState.cornerRadius); @@ -420,9 +418,6 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eLayerChanged) { addDepthLocked(transaction, layerId, state.z); } - if (state.what & layer_state_t::eSizeChanged) { - addSizeLocked(transaction, layerId, state.w, state.h); - } if (state.what & layer_state_t::eAlphaChanged) { addAlphaLocked(transaction, layerId, state.alpha); } @@ -522,8 +517,6 @@ void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment, SurfaceCreation* creation(increment->mutable_surface_creation()); creation->set_id(getLayerId(layer)); creation->set_name(layer->getName()); - creation->set_w(layer->mDrawingState.active_legacy.w); - creation->set_h(layer->mDrawingState.active_legacy.h); } void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment, diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index 77dec6f7fb..dcc529ecc5 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -88,10 +88,7 @@ proto::LayerState TransactionProtoParser::toProto(const layer_state_t& layer) { if (layer.what & layer_state_t::eLayerChanged) { proto.set_z(layer.z); } - if (layer.what & layer_state_t::eSizeChanged) { - proto.set_w(layer.w); - proto.set_h(layer.h); - } + if (layer.what & layer_state_t::eLayerStackChanged) { proto.set_layer_stack(layer.layerStack.id); } @@ -376,10 +373,6 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, layer_sta if (proto.what() & layer_state_t::eLayerChanged) { layer.z = proto.z(); } - if (proto.what() & layer_state_t::eSizeChanged) { - layer.w = proto.w(); - layer.h = proto.h(); - } if (proto.what() & layer_state_t::eLayerStackChanged) { layer.layerStack.id = proto.layer_stack(); } diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 59abe3347c..23ea7a551a 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -26,10 +26,10 @@ #include <android-base/thread_annotations.h> #include <binder/IBinder.h> -#include <compositionengine/FenceResult.h> #include <ftl/future.h> #include <gui/ITransactionCompletedListener.h> #include <ui/Fence.h> +#include <ui/FenceResult.h> namespace android { diff --git a/services/surfaceflinger/layerproto/transactions.proto b/services/surfaceflinger/layerproto/transactions.proto index 49487ee550..b687abc918 100644 --- a/services/surfaceflinger/layerproto/transactions.proto +++ b/services/surfaceflinger/layerproto/transactions.proto @@ -82,7 +82,7 @@ message LayerState { eChangesLsbNone = 0; ePositionChanged = 0x00000001; eLayerChanged = 0x00000002; - eSizeChanged = 0x00000004; + // unused = 0x00000004; eAlphaChanged = 0x00000008; eMatrixChanged = 0x00000010; diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp index fbbf322732..21813700a2 100644 --- a/services/surfaceflinger/tests/LayerState_test.cpp +++ b/services/surfaceflinger/tests/LayerState_test.cpp @@ -90,13 +90,12 @@ TEST(LayerStateTest, ParcellingLayerCaptureArgs) { ASSERT_EQ(args.grayscale, args2.grayscale); } -TEST(LayerStateTest, ParcellingScreenCaptureResults) { +TEST(LayerStateTest, ParcellingScreenCaptureResultsWithFence) { ScreenCaptureResults results; results.buffer = sp<GraphicBuffer>::make(100u, 200u, PIXEL_FORMAT_RGBA_8888, 1u, 0u); - results.fence = sp<Fence>::make(dup(fileno(tmpfile()))); + results.fenceResult = sp<Fence>::make(dup(fileno(tmpfile()))); results.capturedSecureLayers = true; results.capturedDataspace = ui::Dataspace::DISPLAY_P3; - results.result = BAD_VALUE; Parcel p; results.writeToParcel(&p); @@ -110,10 +109,41 @@ TEST(LayerStateTest, ParcellingScreenCaptureResults) { ASSERT_EQ(results.buffer->getWidth(), results2.buffer->getWidth()); ASSERT_EQ(results.buffer->getHeight(), results2.buffer->getHeight()); ASSERT_EQ(results.buffer->getPixelFormat(), results2.buffer->getPixelFormat()); - ASSERT_EQ(results.fence->isValid(), results2.fence->isValid()); + ASSERT_TRUE(results.fenceResult.ok()); + ASSERT_TRUE(results2.fenceResult.ok()); + ASSERT_EQ(results.fenceResult.value()->isValid(), results2.fenceResult.value()->isValid()); ASSERT_EQ(results.capturedSecureLayers, results2.capturedSecureLayers); ASSERT_EQ(results.capturedDataspace, results2.capturedDataspace); - ASSERT_EQ(results.result, results2.result); +} + +TEST(LayerStateTest, ParcellingScreenCaptureResultsWithNoFenceOrError) { + ScreenCaptureResults results; + + Parcel p; + results.writeToParcel(&p); + p.setDataPosition(0); + + ScreenCaptureResults results2; + results2.readFromParcel(&p); + + ASSERT_TRUE(results2.fenceResult.ok()); + ASSERT_EQ(results2.fenceResult.value(), Fence::NO_FENCE); +} + +TEST(LayerStateTest, ParcellingScreenCaptureResultsWithFenceError) { + ScreenCaptureResults results; + results.fenceResult = base::unexpected(BAD_VALUE); + + Parcel p; + results.writeToParcel(&p); + p.setDataPosition(0); + + ScreenCaptureResults results2; + results2.readFromParcel(&p); + + ASSERT_FALSE(results.fenceResult.ok()); + ASSERT_FALSE(results2.fenceResult.ok()); + ASSERT_EQ(results.fenceResult.error(), results2.fenceResult.error()); } } // namespace test diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 4b9160580f..0e8f3dd1d4 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -233,7 +233,7 @@ protected: Rect(halfW, halfH, bufferWidth, bufferHeight), bottomRight); - Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); + Transaction().setBuffer(layer, buffer).apply(); } std::unique_ptr<ScreenCapture> screenshot() { diff --git a/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp b/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp index fb4458a27e..916267447b 100644 --- a/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp +++ b/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp @@ -80,14 +80,6 @@ void toggleOverlay(bool enabled) { } // namespace -TEST(RefreshRateOverlayTest, enableOverlay) { - toggleOverlay(true); -} - -TEST(RefreshRateOverlayTest, disableOverlay) { - toggleOverlay(false); -} - TEST(RefreshRateOverlayTest, enableAndDisableOverlay) { toggleOverlay(true); toggleOverlay(false); diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 8dcd013985..d79e59211b 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -140,6 +140,7 @@ protected: mComposerClient = sp<SurfaceComposerClient>::make(); ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); + GTEST_SKIP(); } void TearDown() override { @@ -342,9 +343,7 @@ void SurfaceInterceptorTest::positionUpdate(Transaction& t) { t.setPosition(mBGSurfaceControl, POSITION_UPDATE, POSITION_UPDATE); } -void SurfaceInterceptorTest::sizeUpdate(Transaction& t) { - t.setSize(mBGSurfaceControl, SIZE_UPDATE, SIZE_UPDATE); -} +void SurfaceInterceptorTest::sizeUpdate(Transaction&) {} void SurfaceInterceptorTest::alphaUpdate(Transaction& t) { t.setAlpha(mBGSurfaceControl, ALPHA_UPDATE); @@ -472,15 +471,8 @@ bool SurfaceInterceptorTest::positionUpdateFound(const SurfaceChange& change, bo return foundPosition; } -bool SurfaceInterceptorTest::sizeUpdateFound(const SurfaceChange& change, bool foundSize) { - bool hasWidth(change.size().h() == SIZE_UPDATE); - bool hasHeight(change.size().w() == SIZE_UPDATE); - if (hasWidth && hasHeight && !foundSize) { - foundSize = true; - } else if (hasWidth && hasHeight && foundSize) { - [] () { FAIL(); }(); - } - return foundSize; +bool SurfaceInterceptorTest::sizeUpdateFound(const SurfaceChange&, bool) { + return true; } bool SurfaceInterceptorTest::alphaUpdateFound(const SurfaceChange& change, bool foundAlpha) { diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 2571e3a0ff..77625b36ef 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -351,15 +351,13 @@ struct BaseDisplayVariant { .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, const std::vector<renderengine::LayerSettings>&, const std::shared_ptr<renderengine::ExternalTexture>&, - const bool, base::unique_fd&&) - -> std::future<renderengine::RenderEngineResult> { + const bool, base::unique_fd&&) -> std::future<FenceResult> { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.clip); - return futureOf<renderengine::RenderEngineResult>( - {NO_ERROR, base::unique_fd()}); + return futureOf<FenceResult>(Fence::NO_FENCE); }); } @@ -404,16 +402,14 @@ struct BaseDisplayVariant { .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, const std::vector<renderengine::LayerSettings>&, const std::shared_ptr<renderengine::ExternalTexture>&, - const bool, base::unique_fd&&) - -> std::future<renderengine::RenderEngineResult> { + const bool, base::unique_fd&&) -> std::future<FenceResult> { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.clip); EXPECT_EQ(ui::Dataspace::UNKNOWN, displaySettings.outputDataspace); - return futureOf<renderengine::RenderEngineResult>( - {NO_ERROR, base::unique_fd()}); + return futureOf<FenceResult>(Fence::NO_FENCE); }); } @@ -606,7 +602,7 @@ struct BaseLayerProperties { .WillOnce([&](const renderengine::DisplaySettings& displaySettings, const std::vector<renderengine::LayerSettings>& layerSettings, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + base::unique_fd&&) -> std::future<FenceResult> { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -614,9 +610,7 @@ struct BaseLayerProperties { displaySettings.clip); // screen capture adds an additional color layer as an alpha // prefill, so gtet the back layer. - std::future<renderengine::RenderEngineResult> resultFuture = - futureOf<renderengine::RenderEngineResult>( - {NO_ERROR, base::unique_fd()}); + std::future<FenceResult> resultFuture = futureOf<FenceResult>(Fence::NO_FENCE); if (layerSettings.empty()) { ADD_FAILURE() << "layerSettings was not expected to be empty in " "setupREBufferCompositionCommonCallExpectations " @@ -659,7 +653,7 @@ struct BaseLayerProperties { .WillOnce([&](const renderengine::DisplaySettings& displaySettings, const std::vector<renderengine::LayerSettings>& layerSettings, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + base::unique_fd&&) -> std::future<FenceResult> { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -667,9 +661,7 @@ struct BaseLayerProperties { displaySettings.clip); // screen capture adds an additional color layer as an alpha // prefill, so get the back layer. - std::future<renderengine::RenderEngineResult> resultFuture = - futureOf<renderengine::RenderEngineResult>( - {NO_ERROR, base::unique_fd()}); + std::future<FenceResult> resultFuture = futureOf<FenceResult>(Fence::NO_FENCE); if (layerSettings.empty()) { ADD_FAILURE() << "layerSettings was not expected to be empty in " @@ -740,7 +732,7 @@ struct CommonSecureLayerProperties : public BaseLayerProperties<LayerProperties> .WillOnce([&](const renderengine::DisplaySettings& displaySettings, const std::vector<renderengine::LayerSettings>& layerSettings, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, - base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> { + base::unique_fd&&) -> std::future<FenceResult> { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -748,9 +740,7 @@ struct CommonSecureLayerProperties : public BaseLayerProperties<LayerProperties> displaySettings.clip); // screen capture adds an additional color layer as an alpha // prefill, so get the back layer. - std::future<renderengine::RenderEngineResult> resultFuture = - futureOf<renderengine::RenderEngineResult>( - {NO_ERROR, base::unique_fd()}); + std::future<FenceResult> resultFuture = futureOf<FenceResult>(Fence::NO_FENCE); if (layerSettings.empty()) { ADD_FAILURE() << "layerSettings was not expected to be empty in " "setupInsecureREBufferCompositionCommonCallExpectations " @@ -828,8 +818,6 @@ struct BaseLayerVariant { static void initLayerDrawingStateAndComputeBounds(CompositionTest* test, sp<L> layer) { auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer); layerDrawingState.layerStack = LAYER_STACK; - layerDrawingState.width = 100; - layerDrawingState.height = 100; layerDrawingState.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1], LayerProperties::COLOR[2], LayerProperties::COLOR[3]); layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform(), 0.f /* shadowRadius */); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 1484bcd12b..188fd58dea 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -564,9 +564,10 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu TestableRefreshRateConfigs configs(kModes_30_60_72_90_120, kModeId60, {.frameRateMultipleThreshold = 120}); - std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 1.f}}; + std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 1.f}, {.weight = 1.f}}; auto& lr1 = layers[0]; auto& lr2 = layers[1]; + auto& lr3 = layers[2]; lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -662,6 +663,25 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu lr2.vote = LayerVoteType::ExplicitExact; lr2.name = "120Hz ExplicitExact"; EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers)); + + lr1.desiredRefreshRate = 10_Hz; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr1.name = "30Hz ExplicitExactOrMultiple"; + lr2.desiredRefreshRate = 120_Hz; + lr2.vote = LayerVoteType::Heuristic; + lr2.name = "120Hz ExplicitExact"; + EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers)); + + lr1.desiredRefreshRate = 30_Hz; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr1.name = "30Hz ExplicitExactOrMultiple"; + lr2.desiredRefreshRate = 30_Hz; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.name = "30Hz ExplicitExactOrMultiple"; + lr3.vote = LayerVoteType::Heuristic; + lr3.desiredRefreshRate = 120_Hz; + lr3.name = "120Hz Heuristic"; + EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers)); } TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) { diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 42585b579b..6c6c9aa684 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -728,6 +728,7 @@ public: mHwcDisplayId(hwcDisplayId) { mCreationArgs.connectionType = connectionType; mCreationArgs.isPrimary = isPrimary; + mCreationArgs.initialPowerMode = hal::PowerMode::ON; } sp<IBinder> token() const { return mDisplayToken; } diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h index cb7040a68b..224868c014 100644 --- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h +++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h @@ -18,6 +18,7 @@ #include <gui/AidlStatusUtil.h> #include <gui/SyncScreenCaptureListener.h> #include <private/gui/ComposerServiceAIDL.h> +#include <ui/FenceResult.h> #include <ui/Rect.h> #include <utils/String8.h> #include <functional> @@ -46,7 +47,7 @@ public: return err; } captureResults = captureListener->waitForResults(); - return captureResults.result; + return fenceStatus(captureResults.fenceResult); } static void captureScreen(std::unique_ptr<ScreenCapture>* sc) { @@ -80,7 +81,7 @@ public: return err; } captureResults = captureListener->waitForResults(); - return captureResults.result; + return fenceStatus(captureResults.fenceResult); } static void captureLayers(std::unique_ptr<ScreenCapture>* sc, LayerCaptureArgs& captureArgs) { |