diff options
109 files changed, 2199 insertions, 2893 deletions
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index 5719a09a16..cd4926ad50 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -313,12 +313,6 @@ static const char* k_traceClockPath = static const char* k_traceBufferSizePath = "buffer_size_kb"; -#if 0 -// TODO: Re-enable after stabilization -static const char* k_traceCmdlineSizePath = - "saved_cmdlines_size"; -#endif - static const char* k_tracingOverwriteEnablePath = "options/overwrite"; @@ -545,18 +539,6 @@ static bool setTraceBufferSizeKB(int size) return writeStr(k_traceBufferSizePath, str); } -#if 0 -// TODO: Re-enable after stabilization -// Set the default size of cmdline hashtable -static bool setCmdlineSize() -{ - if (fileExists(k_traceCmdlineSizePath)) { - return writeStr(k_traceCmdlineSizePath, "8192"); - } - return true; -} -#endif - // Set the clock to the best available option while tracing. Use 'boot' if it's // available; otherwise, use 'mono'. If neither are available use 'global'. // Any write to the trace_clock sysfs file will reset the buffer, so only @@ -870,8 +852,6 @@ static bool setUpKernelTracing() ok &= setCategoriesEnableFromFile(g_categoriesFile); ok &= setTraceOverwriteEnable(g_traceOverwrite); ok &= setTraceBufferSizeKB(g_traceBufferSizeKB); - // TODO: Re-enable after stabilization - //ok &= setCmdlineSize(); ok &= setClock(); ok &= setPrintTgidEnableIfPresent(true); ok &= setKernelTraceFuncs(g_kernelTraceFuncs); diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc index a3e29a81f1..fdac5db1d1 100644 --- a/cmds/atrace/atrace.rc +++ b/cmds/atrace/atrace.rc @@ -13,6 +13,8 @@ on late-init # Access control to these files is now entirely in selinux policy. chmod 0666 /sys/kernel/debug/tracing/trace_clock chmod 0666 /sys/kernel/tracing/trace_clock + chmod 0666 /sys/kernel/debug/tracing/buffer_percent + chmod 0666 /sys/kernel/tracing/buffer_percent chmod 0666 /sys/kernel/debug/tracing/buffer_size_kb chmod 0666 /sys/kernel/tracing/buffer_size_kb chmod 0666 /sys/kernel/debug/tracing/options/overwrite diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 5f109fb224..8d37aac0cb 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -3468,7 +3468,7 @@ void Dumpstate::MaybeSnapshotUiTraces() { "tracing", "save-for-bugreport"}); } - if (!android_tracing_perfetto_protolog()) { + if (!android_tracing_perfetto_protolog_tracing()) { dumpTracesForBugReportCommands.push_back({"dumpsys", "activity", "service", "SystemUIService", "WMShell", "protolog", "save-for-bugreport"}); diff --git a/data/etc/android.software.contextualsearch.xml b/data/etc/android.software.contextualsearch.xml new file mode 100644 index 0000000000..4564ac8804 --- /dev/null +++ b/data/etc/android.software.contextualsearch.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 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. +--> + +<!-- Feature for devices supporting contextual search helper. --> +<permissions> + <feature name="android.software.contextualsearch" /> +</permissions> diff --git a/include/android/input.h b/include/android/input.h index b5c1e5c354..fec56f02f9 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -1492,7 +1492,10 @@ const AInputEvent* AMotionEvent_fromJava(JNIEnv* env, jobject motionEvent) __INT /** * Creates a java android.view.InputEvent object that is a copy of the specified native - * {@link AInputEvent}. Returns null on error + * {@link AInputEvent}. + * + * Specified {@link AInputEvent} is require to be a valid {@link MotionEvent} or {@link KeyEvent} + * object. * * Available since API level 35. */ diff --git a/include/input/Input.h b/include/input/Input.h index a84dcfc63c..374254fc84 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -870,6 +870,10 @@ public: void copyFrom(const MotionEvent* other, bool keepHistory); + // Initialize this event by keeping only the pointers from "other" that are in splitPointerIds. + void splitFrom(const MotionEvent& other, std::bitset<MAX_POINTER_ID + 1> splitPointerIds, + int32_t newEventId); + void addSample( nsecs_t eventTime, const PointerCoords* pointerCoords); @@ -910,6 +914,11 @@ public: static std::string actionToString(int32_t action); + static std::tuple<int32_t /*action*/, std::vector<PointerProperties>, + std::vector<PointerCoords>> + split(int32_t action, int32_t flags, int32_t historySize, const std::vector<PointerProperties>&, + const std::vector<PointerCoords>&, std::bitset<MAX_POINTER_ID + 1> splitPointerIds); + // MotionEvent will transform various axes in different ways, based on the source. For // example, the x and y axes will not have any offsets/translations applied if it comes from a // relative mouse device (since SOURCE_RELATIVE_MOUSE is a non-pointer source). These methods diff --git a/include/input/InputEventBuilders.h b/include/input/InputEventBuilders.h index 2d23b97386..c0c5e2412d 100644 --- a/include/input/InputEventBuilders.h +++ b/include/input/InputEventBuilders.h @@ -118,6 +118,16 @@ public: return *this; } + MotionEventBuilder& transform(ui::Transform t) { + mTransform = t; + return *this; + } + + MotionEventBuilder& rawTransform(ui::Transform t) { + mRawTransform = t; + return *this; + } + MotionEvent build() { std::vector<PointerProperties> pointerProperties; std::vector<PointerCoords> pointerCoords; @@ -134,12 +144,11 @@ public: } MotionEvent event; - static const ui::Transform kIdentityTransform; event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC, mAction, mActionButton, mFlags, /*edgeFlags=*/0, AMETA_NONE, mButtonState, - MotionClassification::NONE, kIdentityTransform, + MotionClassification::NONE, mTransform, /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition, - mRawYCursorPosition, kIdentityTransform, mDownTime, mEventTime, + mRawYCursorPosition, mRawTransform, mDownTime, mEventTime, mPointers.size(), pointerProperties.data(), pointerCoords.data()); return event; } @@ -156,6 +165,8 @@ private: int32_t mFlags{0}; float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION}; float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION}; + ui::Transform mTransform; + ui::Transform mRawTransform; std::vector<PointerBuilder> mPointers; }; diff --git a/include/powermanager/HalResult.h b/include/powermanager/HalResult.h new file mode 100644 index 0000000000..7fe3822be0 --- /dev/null +++ b/include/powermanager/HalResult.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <android/binder_auto_utils.h> +#include <android/binder_status.h> +#include <android/hardware/power/1.0/IPower.h> +#include <binder/Status.h> +#include <hidl/HidlSupport.h> +#include <string> + +namespace android::power { + +static bool checkUnsupported(const ndk::ScopedAStatus& ndkStatus) { + return ndkStatus.getExceptionCode() == EX_UNSUPPORTED_OPERATION || + ndkStatus.getStatus() == STATUS_UNKNOWN_TRANSACTION; +} + +static bool checkUnsupported(const binder::Status& status) { + return status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == UNKNOWN_TRANSACTION; +} + +// Result of a call to the Power HAL wrapper, holding data if successful. +template <typename T> +class HalResult { +public: + static HalResult<T> ok(T&& value) { return HalResult(std::forward<T>(value)); } + static HalResult<T> ok(T& value) { return HalResult<T>::ok(T{value}); } + static HalResult<T> failed(std::string msg) { return HalResult(msg, /* unsupported= */ false); } + static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); } + + static HalResult<T> fromStatus(const binder::Status& status, T&& data) { + if (checkUnsupported(status)) { + return HalResult<T>::unsupported(); + } + if (status.isOk()) { + return HalResult<T>::ok(std::forward<T>(data)); + } + return HalResult<T>::failed(std::string(status.toString8().c_str())); + } + + static HalResult<T> fromStatus(const binder::Status& status, T& data) { + return HalResult<T>::fromStatus(status, T{data}); + } + + static HalResult<T> fromStatus(const ndk::ScopedAStatus& ndkStatus, T&& data) { + if (checkUnsupported(ndkStatus)) { + return HalResult<T>::unsupported(); + } + if (ndkStatus.isOk()) { + return HalResult<T>::ok(std::forward<T>(data)); + } + return HalResult<T>::failed(std::string(ndkStatus.getDescription())); + } + + static HalResult<T> fromStatus(const ndk::ScopedAStatus& ndkStatus, T& data) { + return HalResult<T>::fromStatus(ndkStatus, T{data}); + } + + template <typename R> + static HalResult<T> fromReturn(hardware::Return<R>& ret, T&& data) { + return ret.isOk() ? HalResult<T>::ok(std::forward<T>(data)) + : HalResult<T>::failed(ret.description()); + } + + template <typename R> + static HalResult<T> fromReturn(hardware::Return<R>& ret, T& data) { + return HalResult<T>::fromReturn(ret, T{data}); + } + + template <typename R> + static HalResult<T> fromReturn(hardware::Return<R>& ret, hardware::power::V1_0::Status status, + T&& data) { + return ret.isOk() ? HalResult<T>::fromStatus(status, std::forward<T>(data)) + : HalResult<T>::failed(ret.description()); + } + + template <typename R> + static HalResult<T> fromReturn(hardware::Return<R>& ret, hardware::power::V1_0::Status status, + T& data) { + return HalResult<T>::fromReturn(ret, status, T{data}); + } + + // This will throw std::bad_optional_access if this result is not ok. + const T& value() const { return mValue.value(); } + bool isOk() const { return !mUnsupported && mValue.has_value(); } + bool isFailed() const { return !mUnsupported && !mValue.has_value(); } + bool isUnsupported() const { return mUnsupported; } + const char* errorMessage() const { return mErrorMessage.c_str(); } + +private: + std::optional<T> mValue; + std::string mErrorMessage; + bool mUnsupported; + + explicit HalResult(T&& value) + : mValue{std::move(value)}, mErrorMessage(), mUnsupported(false) {} + explicit HalResult(std::string errorMessage, bool unsupported) + : mValue(), mErrorMessage(std::move(errorMessage)), mUnsupported(unsupported) {} +}; + +// Empty result +template <> +class HalResult<void> { +public: + static HalResult<void> ok() { return HalResult(); } + static HalResult<void> failed(std::string msg) { return HalResult(std::move(msg)); } + static HalResult<void> unsupported() { return HalResult(/* unsupported= */ true); } + + static HalResult<void> fromStatus(const binder::Status& status) { + if (checkUnsupported(status)) { + return HalResult<void>::unsupported(); + } + if (status.isOk()) { + return HalResult<void>::ok(); + } + return HalResult<void>::failed(std::string(status.toString8().c_str())); + } + + static HalResult<void> fromStatus(const ndk::ScopedAStatus& ndkStatus) { + if (ndkStatus.isOk()) { + return HalResult<void>::ok(); + } + if (checkUnsupported(ndkStatus)) { + return HalResult<void>::unsupported(); + } + return HalResult<void>::failed(ndkStatus.getDescription()); + } + + template <typename R> + static HalResult<void> fromReturn(hardware::Return<R>& ret) { + return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description()); + } + + bool isOk() const { return !mUnsupported && !mFailed; } + bool isFailed() const { return !mUnsupported && mFailed; } + bool isUnsupported() const { return mUnsupported; } + const char* errorMessage() const { return mErrorMessage.c_str(); } + +private: + std::string mErrorMessage; + bool mFailed; + bool mUnsupported; + + explicit HalResult(bool unsupported = false) + : mErrorMessage(), mFailed(false), mUnsupported(unsupported) {} + explicit HalResult(std::string errorMessage) + : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {} +}; +} // namespace android::power diff --git a/include/powermanager/PowerHalController.h b/include/powermanager/PowerHalController.h index c50bc4a188..7e0bd5bedc 100644 --- a/include/powermanager/PowerHalController.h +++ b/include/powermanager/PowerHalController.h @@ -23,6 +23,7 @@ #include <aidl/android/hardware/power/Mode.h> #include <android-base/thread_annotations.h> #include <powermanager/PowerHalWrapper.h> +#include <powermanager/PowerHintSessionWrapper.h> namespace android { @@ -38,6 +39,7 @@ public: virtual std::unique_ptr<HalWrapper> connect(); virtual void reset(); + virtual int32_t getAidlVersion(); }; // ------------------------------------------------------------------------------------------------- @@ -59,14 +61,13 @@ public: int32_t durationMs) override; virtual HalResult<void> setMode(aidl::android::hardware::power::Mode mode, bool enabled) override; - virtual HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> - createHintSession(int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, - int64_t durationNanos) override; - virtual HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> - createHintSessionWithConfig(int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, - int64_t durationNanos, - aidl::android::hardware::power::SessionTag tag, - aidl::android::hardware::power::SessionConfig* config) override; + virtual HalResult<std::shared_ptr<PowerHintSessionWrapper>> createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, + int64_t durationNanos) override; + virtual HalResult<std::shared_ptr<PowerHintSessionWrapper>> createHintSessionWithConfig( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos, + aidl::android::hardware::power::SessionTag tag, + aidl::android::hardware::power::SessionConfig* config) override; virtual HalResult<int64_t> getHintSessionPreferredRate() override; virtual HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel( int tgid, int uid) override; diff --git a/include/powermanager/PowerHalLoader.h b/include/powermanager/PowerHalLoader.h index cbbfa597ba..ab66336738 100644 --- a/include/powermanager/PowerHalLoader.h +++ b/include/powermanager/PowerHalLoader.h @@ -36,6 +36,8 @@ public: static sp<hardware::power::V1_1::IPower> loadHidlV1_1(); static sp<hardware::power::V1_2::IPower> loadHidlV1_2(); static sp<hardware::power::V1_3::IPower> loadHidlV1_3(); + // Returns aidl interface version, or 0 if AIDL is not used + static int32_t getAidlVersion(); private: static std::mutex gHalMutex; @@ -48,6 +50,8 @@ private: static sp<hardware::power::V1_0::IPower> loadHidlV1_0Locked() EXCLUSIVE_LOCKS_REQUIRED(gHalMutex); + static int32_t gAidlInterfaceVersion; + PowerHalLoader() = delete; ~PowerHalLoader() = delete; }; diff --git a/include/powermanager/PowerHalWrapper.h b/include/powermanager/PowerHalWrapper.h index e2da014606..6e347a9ce9 100644 --- a/include/powermanager/PowerHalWrapper.h +++ b/include/powermanager/PowerHalWrapper.h @@ -26,6 +26,9 @@ #include <android/hardware/power/1.1/IPower.h> #include <android/hardware/power/1.2/IPower.h> #include <android/hardware/power/1.3/IPower.h> +#include <powermanager/HalResult.h> +#include <powermanager/PowerHintSessionWrapper.h> + #include <binder/Status.h> #include <utility> @@ -41,134 +44,6 @@ enum class HalSupport { OFF = 2, }; -// Result of a call to the Power HAL wrapper, holding data if successful. -template <typename T> -class HalResult { -public: - static HalResult<T> ok(T&& value) { return HalResult(std::forward<T>(value)); } - static HalResult<T> ok(T& value) { return HalResult<T>::ok(T{value}); } - static HalResult<T> failed(std::string msg) { return HalResult(msg, /* unsupported= */ false); } - static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); } - - static HalResult<T> fromStatus(const binder::Status& status, T&& data) { - if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) { - return HalResult<T>::unsupported(); - } - if (status.isOk()) { - return HalResult<T>::ok(std::forward<T>(data)); - } - return HalResult<T>::failed(std::string(status.toString8().c_str())); - } - - static HalResult<T> fromStatus(const binder::Status& status, T& data) { - return HalResult<T>::fromStatus(status, T{data}); - } - - static HalResult<T> fromStatus(const ndk::ScopedAStatus& status, T&& data) { - if (status.getExceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) { - return HalResult<T>::unsupported(); - } - if (status.isOk()) { - return HalResult<T>::ok(std::forward<T>(data)); - } - return HalResult<T>::failed(std::string(status.getDescription())); - } - - static HalResult<T> fromStatus(const ndk::ScopedAStatus& status, T& data) { - return HalResult<T>::fromStatus(status, T{data}); - } - - template <typename R> - static HalResult<T> fromReturn(hardware::Return<R>& ret, T&& data) { - return ret.isOk() ? HalResult<T>::ok(std::forward<T>(data)) - : HalResult<T>::failed(ret.description()); - } - - template <typename R> - static HalResult<T> fromReturn(hardware::Return<R>& ret, T& data) { - return HalResult<T>::fromReturn(ret, T{data}); - } - - template <typename R> - static HalResult<T> fromReturn(hardware::Return<R>& ret, hardware::power::V1_0::Status status, - T&& data) { - return ret.isOk() ? HalResult<T>::fromStatus(status, std::forward<T>(data)) - : HalResult<T>::failed(ret.description()); - } - - template <typename R> - static HalResult<T> fromReturn(hardware::Return<R>& ret, hardware::power::V1_0::Status status, - T& data) { - return HalResult<T>::fromReturn(ret, status, T{data}); - } - - // This will throw std::bad_optional_access if this result is not ok. - const T& value() const { return mValue.value(); } - bool isOk() const { return !mUnsupported && mValue.has_value(); } - bool isFailed() const { return !mUnsupported && !mValue.has_value(); } - bool isUnsupported() const { return mUnsupported; } - const char* errorMessage() const { return mErrorMessage.c_str(); } - -private: - std::optional<T> mValue; - std::string mErrorMessage; - bool mUnsupported; - - explicit HalResult(T&& value) - : mValue{std::move(value)}, mErrorMessage(), mUnsupported(false) {} - explicit HalResult(std::string errorMessage, bool unsupported) - : mValue(), mErrorMessage(std::move(errorMessage)), mUnsupported(unsupported) {} -}; - -// Empty result of a call to the Power HAL wrapper. -template <> -class HalResult<void> { -public: - static HalResult<void> ok() { return HalResult(); } - static HalResult<void> failed(std::string msg) { return HalResult(std::move(msg)); } - static HalResult<void> unsupported() { return HalResult(/* unsupported= */ true); } - - static HalResult<void> fromStatus(const binder::Status& status) { - if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) { - return HalResult<void>::unsupported(); - } - if (status.isOk()) { - return HalResult<void>::ok(); - } - return HalResult<void>::failed(std::string(status.toString8().c_str())); - } - - static HalResult<void> fromStatus(const ndk::ScopedAStatus& status) { - if (status.getExceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) { - return HalResult<void>::unsupported(); - } - if (status.isOk()) { - return HalResult<void>::ok(); - } - return HalResult<void>::failed(std::string(status.getDescription())); - } - - template <typename R> - static HalResult<void> fromReturn(hardware::Return<R>& ret) { - return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description()); - } - - bool isOk() const { return !mUnsupported && !mFailed; } - bool isFailed() const { return !mUnsupported && mFailed; } - bool isUnsupported() const { return mUnsupported; } - const char* errorMessage() const { return mErrorMessage.c_str(); } - -private: - std::string mErrorMessage; - bool mFailed; - bool mUnsupported; - - explicit HalResult(bool unsupported = false) - : mErrorMessage(), mFailed(false), mUnsupported(unsupported) {} - explicit HalResult(std::string errorMessage) - : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {} -}; - // Wrapper for Power HAL handlers. class HalWrapper { public: @@ -177,14 +52,13 @@ public: virtual HalResult<void> setBoost(aidl::android::hardware::power::Boost boost, int32_t durationMs) = 0; virtual HalResult<void> setMode(aidl::android::hardware::power::Mode mode, bool enabled) = 0; - virtual HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> - createHintSession(int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, - int64_t durationNanos) = 0; - virtual HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> - createHintSessionWithConfig(int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, - int64_t durationNanos, - aidl::android::hardware::power::SessionTag tag, - aidl::android::hardware::power::SessionConfig* config) = 0; + virtual HalResult<std::shared_ptr<PowerHintSessionWrapper>> createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, + int64_t durationNanos) = 0; + virtual HalResult<std::shared_ptr<PowerHintSessionWrapper>> createHintSessionWithConfig( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos, + aidl::android::hardware::power::SessionTag tag, + aidl::android::hardware::power::SessionConfig* config) = 0; virtual HalResult<int64_t> getHintSessionPreferredRate() = 0; virtual HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(int tgid, int uid) = 0; @@ -200,14 +74,13 @@ public: HalResult<void> setBoost(aidl::android::hardware::power::Boost boost, int32_t durationMs) override; HalResult<void> setMode(aidl::android::hardware::power::Mode mode, bool enabled) override; - HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> createHintSession( + HalResult<std::shared_ptr<PowerHintSessionWrapper>> createHintSession( int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) override; - HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> - createHintSessionWithConfig(int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, - int64_t durationNanos, - aidl::android::hardware::power::SessionTag tag, - aidl::android::hardware::power::SessionConfig* config) override; + HalResult<std::shared_ptr<PowerHintSessionWrapper>> createHintSessionWithConfig( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos, + aidl::android::hardware::power::SessionTag tag, + aidl::android::hardware::power::SessionConfig* config) override; HalResult<int64_t> getHintSessionPreferredRate() override; HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(int tgid, int uid) override; @@ -285,14 +158,13 @@ public: HalResult<void> setBoost(aidl::android::hardware::power::Boost boost, int32_t durationMs) override; HalResult<void> setMode(aidl::android::hardware::power::Mode mode, bool enabled) override; - HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> createHintSession( + HalResult<std::shared_ptr<PowerHintSessionWrapper>> createHintSession( int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) override; - HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> - createHintSessionWithConfig(int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, - int64_t durationNanos, - aidl::android::hardware::power::SessionTag tag, - aidl::android::hardware::power::SessionConfig* config) override; + HalResult<std::shared_ptr<PowerHintSessionWrapper>> createHintSessionWithConfig( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos, + aidl::android::hardware::power::SessionTag tag, + aidl::android::hardware::power::SessionConfig* config) override; HalResult<int64_t> getHintSessionPreferredRate() override; HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(int tgid, @@ -307,14 +179,12 @@ private: std::mutex mBoostMutex; std::mutex mModeMutex; std::shared_ptr<aidl::android::hardware::power::IPower> mHandle; - // Android framework only sends boost upto DISPLAY_UPDATE_IMMINENT. - // Need to increase the array size if more boost supported. - std::array< - std::atomic<HalSupport>, - static_cast<int32_t>(aidl::android::hardware::power::Boost::DISPLAY_UPDATE_IMMINENT) + - 1> + std::array<HalSupport, + static_cast<int32_t>( + *(ndk::enum_range<aidl::android::hardware::power::Boost>().end() - 1)) + + 1> mBoostSupportedArray GUARDED_BY(mBoostMutex) = {HalSupport::UNKNOWN}; - std::array<std::atomic<HalSupport>, + std::array<HalSupport, static_cast<int32_t>( *(ndk::enum_range<aidl::android::hardware::power::Mode>().end() - 1)) + 1> diff --git a/include/powermanager/PowerHintSessionWrapper.h b/include/powermanager/PowerHintSessionWrapper.h new file mode 100644 index 0000000000..ba6fe77c80 --- /dev/null +++ b/include/powermanager/PowerHintSessionWrapper.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <aidl/android/hardware/power/Boost.h> +#include <aidl/android/hardware/power/ChannelConfig.h> +#include <aidl/android/hardware/power/IPower.h> +#include <aidl/android/hardware/power/IPowerHintSession.h> +#include <aidl/android/hardware/power/Mode.h> +#include <aidl/android/hardware/power/SessionConfig.h> +#include <android-base/thread_annotations.h> +#include "HalResult.h" + +namespace android::power { + +// Wrapper for power hint sessions, which allows for better mocking, +// support checking, and failure handling than using hint sessions directly +class PowerHintSessionWrapper { +public: + virtual ~PowerHintSessionWrapper() = default; + PowerHintSessionWrapper( + std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>&& session); + virtual HalResult<void> updateTargetWorkDuration(int64_t in_targetDurationNanos); + virtual HalResult<void> reportActualWorkDuration( + const std::vector<::aidl::android::hardware::power::WorkDuration>& in_durations); + virtual HalResult<void> pause(); + virtual HalResult<void> resume(); + virtual HalResult<void> close(); + virtual HalResult<void> sendHint(::aidl::android::hardware::power::SessionHint in_hint); + virtual HalResult<void> setThreads(const std::vector<int32_t>& in_threadIds); + virtual HalResult<void> setMode(::aidl::android::hardware::power::SessionMode in_type, + bool in_enabled); + virtual HalResult<aidl::android::hardware::power::SessionConfig> getSessionConfig(); + +private: + std::shared_ptr<aidl::android::hardware::power::IPowerHintSession> mSession; + int32_t mInterfaceVersion; +}; + +} // namespace android::power
\ No newline at end of file diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index c1770b35d1..2dd310e9ca 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -256,7 +256,7 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) { if (const auto* rpcFields = maybeRpcFields()) { if (binder) { - status_t status = writeInt32(1); // non-null + status_t status = writeInt32(RpcFields::TYPE_BINDER); // non-null if (status != OK) return status; uint64_t address; // TODO(b/167966510): need to undo this if the Parcel is not sent @@ -266,7 +266,7 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) { status = writeUint64(address); if (status != OK) return status; } else { - status_t status = writeInt32(0); // null + status_t status = writeInt32(RpcFields::TYPE_BINDER_NULL); // null if (status != OK) return status; } return finishFlattenBinder(binder); @@ -740,6 +740,12 @@ bool Parcel::hasFileDescriptors() const return kernelFields->mHasFds; } +status_t Parcel::hasBinders(bool* result) const { + status_t status = hasBindersInRange(0, dataSize(), result); + ALOGE_IF(status != NO_ERROR, "Error %d calling hasBindersInRange()", status); + return status; +} + std::vector<sp<IBinder>> Parcel::debugReadAllStrongBinders() const { std::vector<sp<IBinder>> ret; @@ -799,6 +805,46 @@ std::vector<int> Parcel::debugReadAllFileDescriptors() const { return ret; } +status_t Parcel::hasBindersInRange(size_t offset, size_t len, bool* result) const { + if (len > INT32_MAX || offset > INT32_MAX) { + // Don't accept size_t values which may have come from an inadvertent conversion from a + // negative int. + return BAD_VALUE; + } + size_t limit; + if (__builtin_add_overflow(offset, len, &limit) || limit > mDataSize) { + return BAD_VALUE; + } + *result = false; + if (const auto* kernelFields = maybeKernelFields()) { +#ifdef BINDER_WITH_KERNEL_IPC + for (size_t i = 0; i < kernelFields->mObjectsSize; i++) { + size_t pos = kernelFields->mObjects[i]; + if (pos < offset) continue; + if (pos + sizeof(flat_binder_object) > offset + len) { + if (kernelFields->mObjectsSorted) { + break; + } else { + continue; + } + } + const flat_binder_object* flat = + reinterpret_cast<const flat_binder_object*>(mData + pos); + if (flat->hdr.type == BINDER_TYPE_BINDER || flat->hdr.type == BINDER_TYPE_HANDLE) { + *result = true; + break; + } + } +#else + LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time"); + return INVALID_OPERATION; +#endif // BINDER_WITH_KERNEL_IPC + } else if (const auto* rpcFields = maybeRpcFields()) { + return INVALID_OPERATION; + } + return NO_ERROR; +} + status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool* result) const { if (len > INT32_MAX || offset > INT32_MAX) { // Don't accept size_t values which may have come from an inadvertent conversion from a diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index d7096d8a75..5e18b9197d 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -101,7 +101,9 @@ public: void restoreAllowFds(bool lastValue); bool hasFileDescriptors() const; + status_t hasBinders(bool* result) const; status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool* result) const; + status_t hasBindersInRange(size_t offset, size_t length, bool* result) const; // returns all binder objects in the Parcel std::vector<sp<IBinder>> debugReadAllStrongBinders() const; @@ -647,6 +649,8 @@ private: void freeDataNoInit(); void initState(); void scanForFds() const; + status_t scanForBinders(bool* result) const; + status_t validateReadData(size_t len) const; void updateWorkSourceRequestHeaderPosition() const; diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp index 3af9ec7481..bf7a0ba5f0 100644 --- a/libs/binder/ndk/ibinder.cpp +++ b/libs/binder/ndk/ibinder.cpp @@ -258,24 +258,11 @@ status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parce } } -void ABBinder::addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& /* recipient */, - void* /* cookie */) { - LOG_ALWAYS_FATAL("Should not reach this. Can't linkToDeath local binders."); -} - ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder) : AIBinder(nullptr /*clazz*/), mRemote(binder) { LOG_ALWAYS_FATAL_IF(binder == nullptr, "binder == nullptr"); } - -ABpBinder::~ABpBinder() { - for (auto& recip : mDeathRecipients) { - sp<AIBinder_DeathRecipient> strongRecip = recip.recipient.promote(); - if (strongRecip) { - strongRecip->pruneThisTransferEntry(getBinder(), recip.cookie); - } - } -} +ABpBinder::~ABpBinder() {} sp<AIBinder> ABpBinder::lookupOrCreateFromBinder(const ::android::sp<::android::IBinder>& binder) { if (binder == nullptr) { @@ -314,11 +301,6 @@ sp<AIBinder> ABpBinder::lookupOrCreateFromBinder(const ::android::sp<::android:: return ret; } -void ABpBinder::addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& recipient, - void* cookie) { - mDeathRecipients.emplace_back(recipient, cookie); -} - struct AIBinder_Weak { wp<AIBinder> binder; }; @@ -444,17 +426,6 @@ AIBinder_DeathRecipient::AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinde LOG_ALWAYS_FATAL_IF(onDied == nullptr, "onDied == nullptr"); } -void AIBinder_DeathRecipient::pruneThisTransferEntry(const sp<IBinder>& who, void* cookie) { - std::lock_guard<std::mutex> l(mDeathRecipientsMutex); - mDeathRecipients.erase(std::remove_if(mDeathRecipients.begin(), mDeathRecipients.end(), - [&](const sp<TransferDeathRecipient>& tdr) { - auto tdrWho = tdr->getWho(); - return tdrWho != nullptr && tdrWho.promote() == who && - cookie == tdr->getCookie(); - }), - mDeathRecipients.end()); -} - void AIBinder_DeathRecipient::pruneDeadTransferEntriesLocked() { mDeathRecipients.erase(std::remove_if(mDeathRecipients.begin(), mDeathRecipients.end(), [](const sp<TransferDeathRecipient>& tdr) { @@ -583,11 +554,8 @@ binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* return STATUS_UNEXPECTED_NULL; } - binder_status_t ret = recipient->linkToDeath(binder->getBinder(), cookie); - if (ret == STATUS_OK) { - binder->addDeathRecipient(recipient, cookie); - } - return ret; + // returns binder_status_t + return recipient->linkToDeath(binder->getBinder(), cookie); } binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h index a2682d8c0c..9d5368f674 100644 --- a/libs/binder/ndk/ibinder_internal.h +++ b/libs/binder/ndk/ibinder_internal.h @@ -51,8 +51,6 @@ struct AIBinder : public virtual ::android::RefBase { ::android::sp<::android::IBinder> binder = const_cast<AIBinder*>(this)->getBinder(); return binder->remoteBinder() != nullptr; } - virtual void addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& recipient, - void* cookie) = 0; private: // AIBinder instance is instance of this class for a local object. In order to transact on a @@ -80,8 +78,6 @@ struct ABBinder : public AIBinder, public ::android::BBinder { ::android::status_t dump(int fd, const ::android::Vector<::android::String16>& args) override; ::android::status_t onTransact(uint32_t code, const ::android::Parcel& data, ::android::Parcel* reply, binder_flags_t flags) override; - void addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& /* recipient */, - void* /* cookie */) override; private: ABBinder(const AIBinder_Class* clazz, void* userData); @@ -110,19 +106,12 @@ struct ABpBinder : public AIBinder { bool isServiceFuzzing() const { return mServiceFuzzing; } void setServiceFuzzing() { mServiceFuzzing = true; } - void addDeathRecipient(const ::android::sp<AIBinder_DeathRecipient>& recipient, - void* cookie) override; private: friend android::sp<ABpBinder>; explicit ABpBinder(const ::android::sp<::android::IBinder>& binder); ::android::sp<::android::IBinder> mRemote; bool mServiceFuzzing = false; - struct DeathRecipientInfo { - android::wp<AIBinder_DeathRecipient> recipient; - void* cookie; - }; - std::vector<DeathRecipientInfo> mDeathRecipients; }; struct AIBinder_Class { @@ -194,7 +183,6 @@ struct AIBinder_DeathRecipient : ::android::RefBase { binder_status_t linkToDeath(const ::android::sp<::android::IBinder>&, void* cookie); binder_status_t unlinkToDeath(const ::android::sp<::android::IBinder>& binder, void* cookie); void setOnUnlinked(AIBinder_DeathRecipient_onBinderUnlinked onUnlinked); - void pruneThisTransferEntry(const ::android::sp<::android::IBinder>&, void* cookie); private: // When the user of this API deletes a Bp object but not the death recipient, the diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp index ca927272f8..3ee36cd8c3 100644 --- a/libs/binder/ndk/tests/iface.cpp +++ b/libs/binder/ndk/tests/iface.cpp @@ -25,7 +25,6 @@ using ::android::wp; const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo"; const char* IFoo::kInstanceNameToDieFor = "libbinder_ndk-test-IFoo-to-die"; -const char* IFoo::kInstanceNameToDieFor2 = "libbinder_ndk-test-IFoo-to-die2"; const char* IFoo::kIFooDescriptor = "my-special-IFoo-class"; struct IFoo_Class_Data { diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h index 0cdd50b37a..0a562f085d 100644 --- a/libs/binder/ndk/tests/include/iface/iface.h +++ b/libs/binder/ndk/tests/include/iface/iface.h @@ -27,7 +27,6 @@ class IFoo : public virtual ::android::RefBase { public: static const char* kSomeInstanceName; static const char* kInstanceNameToDieFor; - static const char* kInstanceNameToDieFor2; static const char* kIFooDescriptor; static AIBinder_Class* kClass; diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index ce63b828cb..966ec959b6 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -536,7 +536,6 @@ TEST(NdkBinder, DeathRecipient) { bool deathReceived = false; std::function<void(void)> onDeath = [&] { - std::unique_lock<std::mutex> lockDeath(deathMutex); std::cerr << "Binder died (as requested)." << std::endl; deathReceived = true; deathCv.notify_one(); @@ -548,7 +547,6 @@ TEST(NdkBinder, DeathRecipient) { bool wasDeathReceivedFirst = false; std::function<void(void)> onUnlink = [&] { - std::unique_lock<std::mutex> lockUnlink(unlinkMutex); std::cerr << "Binder unlinked (as requested)." << std::endl; wasDeathReceivedFirst = deathReceived; unlinkReceived = true; @@ -562,6 +560,7 @@ TEST(NdkBinder, DeathRecipient) { EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, static_cast<void*>(cookie))); + // the binder driver should return this if the service dies during the transaction EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die()); foo = nullptr; @@ -580,123 +579,6 @@ TEST(NdkBinder, DeathRecipient) { binder = nullptr; } -TEST(NdkBinder, DeathRecipientDropBinderNoDeath) { - using namespace std::chrono_literals; - - std::mutex deathMutex; - std::condition_variable deathCv; - bool deathReceived = false; - - std::function<void(void)> onDeath = [&] { - std::unique_lock<std::mutex> lockDeath(deathMutex); - std::cerr << "Binder died (as requested)." << std::endl; - deathReceived = true; - deathCv.notify_one(); - }; - - std::mutex unlinkMutex; - std::condition_variable unlinkCv; - bool unlinkReceived = false; - bool wasDeathReceivedFirst = false; - - std::function<void(void)> onUnlink = [&] { - std::unique_lock<std::mutex> lockUnlink(unlinkMutex); - std::cerr << "Binder unlinked (as requested)." << std::endl; - wasDeathReceivedFirst = deathReceived; - unlinkReceived = true; - unlinkCv.notify_one(); - }; - - // keep the death recipient around - ndk::ScopedAIBinder_DeathRecipient recipient(AIBinder_DeathRecipient_new(LambdaOnDeath)); - AIBinder_DeathRecipient_setOnUnlinked(recipient.get(), LambdaOnUnlink); - - { - AIBinder* binder; - sp<IFoo> foo = IFoo::getService(IFoo::kInstanceNameToDieFor2, &binder); - ASSERT_NE(nullptr, foo.get()); - ASSERT_NE(nullptr, binder); - - DeathRecipientCookie* cookie = new DeathRecipientCookie{&onDeath, &onUnlink}; - - EXPECT_EQ(STATUS_OK, - AIBinder_linkToDeath(binder, recipient.get(), static_cast<void*>(cookie))); - // let the sp<IFoo> and AIBinder fall out of scope - AIBinder_decStrong(binder); - binder = nullptr; - } - - { - std::unique_lock<std::mutex> lockDeath(deathMutex); - EXPECT_FALSE(deathCv.wait_for(lockDeath, 100ms, [&] { return deathReceived; })); - EXPECT_FALSE(deathReceived); - } - - { - std::unique_lock<std::mutex> lockUnlink(unlinkMutex); - EXPECT_TRUE(deathCv.wait_for(lockUnlink, 1s, [&] { return unlinkReceived; })); - EXPECT_TRUE(unlinkReceived); - EXPECT_FALSE(wasDeathReceivedFirst); - } -} - -TEST(NdkBinder, DeathRecipientDropBinderOnDied) { - using namespace std::chrono_literals; - - std::mutex deathMutex; - std::condition_variable deathCv; - bool deathReceived = false; - - sp<IFoo> foo; - AIBinder* binder; - std::function<void(void)> onDeath = [&] { - std::unique_lock<std::mutex> lockDeath(deathMutex); - std::cerr << "Binder died (as requested)." << std::endl; - deathReceived = true; - AIBinder_decStrong(binder); - binder = nullptr; - deathCv.notify_one(); - }; - - std::mutex unlinkMutex; - std::condition_variable unlinkCv; - bool unlinkReceived = false; - bool wasDeathReceivedFirst = false; - - std::function<void(void)> onUnlink = [&] { - std::unique_lock<std::mutex> lockUnlink(unlinkMutex); - std::cerr << "Binder unlinked (as requested)." << std::endl; - wasDeathReceivedFirst = deathReceived; - unlinkReceived = true; - unlinkCv.notify_one(); - }; - - ndk::ScopedAIBinder_DeathRecipient recipient(AIBinder_DeathRecipient_new(LambdaOnDeath)); - AIBinder_DeathRecipient_setOnUnlinked(recipient.get(), LambdaOnUnlink); - - foo = IFoo::getService(IFoo::kInstanceNameToDieFor2, &binder); - ASSERT_NE(nullptr, foo.get()); - ASSERT_NE(nullptr, binder); - - DeathRecipientCookie* cookie = new DeathRecipientCookie{&onDeath, &onUnlink}; - EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient.get(), static_cast<void*>(cookie))); - - EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die()); - - { - std::unique_lock<std::mutex> lockDeath(deathMutex); - EXPECT_TRUE(deathCv.wait_for(lockDeath, 1s, [&] { return deathReceived; })); - EXPECT_TRUE(deathReceived); - } - - { - std::unique_lock<std::mutex> lockUnlink(unlinkMutex); - EXPECT_TRUE(deathCv.wait_for(lockUnlink, 100ms, [&] { return unlinkReceived; })); - EXPECT_TRUE(unlinkReceived); - EXPECT_TRUE(wasDeathReceivedFirst); - } -} - TEST(NdkBinder, RetrieveNonNdkService) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -1076,10 +958,6 @@ int main(int argc, char* argv[]) { } if (fork() == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); - return manualThreadPoolService(IFoo::kInstanceNameToDieFor2); - } - if (fork() == 0) { - prctl(PR_SET_PDEATHSIG, SIGHUP); return manualPollingService(IFoo::kSomeInstanceName); } if (fork() == 0) { diff --git a/libs/binder/tests/binderParcelUnitTest.cpp b/libs/binder/tests/binderParcelUnitTest.cpp index 34fc43f926..32a70e5b11 100644 --- a/libs/binder/tests/binderParcelUnitTest.cpp +++ b/libs/binder/tests/binderParcelUnitTest.cpp @@ -23,6 +23,7 @@ using android::BBinder; using android::IBinder; using android::IPCThreadState; +using android::NO_ERROR; using android::OK; using android::Parcel; using android::sp; @@ -164,6 +165,45 @@ TEST(Parcel, AppendPlainDataPartial) { ASSERT_EQ(2, p2.readInt32()); } +TEST(Parcel, HasBinders) { + sp<IBinder> b1 = sp<BBinder>::make(); + + Parcel p1; + p1.writeInt32(1); + p1.writeStrongBinder(b1); + + bool result = false; + ASSERT_EQ(NO_ERROR, p1.hasBinders(&result)); + ASSERT_EQ(true, result); + + p1.setDataSize(0); // clear data + result = false; + ASSERT_EQ(NO_ERROR, p1.hasBinders(&result)); + ASSERT_EQ(false, result); + p1.writeStrongBinder(b1); // reset with binder data + result = false; + ASSERT_EQ(NO_ERROR, p1.hasBinders(&result)); + ASSERT_EQ(true, result); + + Parcel p3; + p3.appendFrom(&p1, 0, p1.dataSize()); + result = false; + ASSERT_EQ(NO_ERROR, p1.hasBinders(&result)); + ASSERT_EQ(true, result); +} + +TEST(Parcel, HasBindersInRange) { + sp<IBinder> b1 = sp<BBinder>::make(); + Parcel p1; + p1.writeStrongBinder(b1); + bool result = false; + ASSERT_EQ(NO_ERROR, p1.hasBindersInRange(0, p1.dataSize(), &result)); + ASSERT_EQ(true, result); + result = false; + ASSERT_EQ(NO_ERROR, p1.hasBinders(&result)); + ASSERT_EQ(true, result); +} + TEST(Parcel, AppendWithBinder) { sp<IBinder> b1 = sp<BBinder>::make(); sp<IBinder> b2 = sp<BBinder>::make(); diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp index 08fe071bfb..5c280f4b2c 100644 --- a/libs/binder/tests/parcel_fuzzer/binder.cpp +++ b/libs/binder/tests/parcel_fuzzer/binder.cpp @@ -353,6 +353,20 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { FUZZ_LOG() << " status: " << status << " result: " << result; }, [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { + FUZZ_LOG() << "about to call hasBinders() with status"; + bool result; + status_t status = p.hasBinders(&result); + FUZZ_LOG() << " status: " << status << " result: " << result; + }, + [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { + FUZZ_LOG() << "about to call hasBindersInRange() with status"; + size_t offset = p.readUint32(); + size_t length = p.readUint32(); + bool result; + status_t status = p.hasBindersInRange(offset, length, &result); + FUZZ_LOG() << " status: " << status << " result: " << result; + }, + [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to call compareDataInRange() with status"; size_t thisOffset = p.readUint32(); size_t otherOffset = p.readUint32(); diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp index 394a0002ed..50c05f4e5b 100644 --- a/libs/graphicsenv/GraphicsEnv.cpp +++ b/libs/graphicsenv/GraphicsEnv.cpp @@ -265,7 +265,8 @@ android_namespace_t* GraphicsEnv::getDriverNamespace() { auto vndkNamespace = android_get_exported_namespace("vndk"); if (!vndkNamespace) { - return nullptr; + mDriverNamespace = nullptr; + return mDriverNamespace; } mDriverNamespace = android_create_namespace("updatable gfx driver", @@ -617,7 +618,8 @@ android_namespace_t* GraphicsEnv::getAngleNamespace() { auto vndkNamespace = android_get_exported_namespace("vndk"); if (!vndkNamespace) { - return nullptr; + mAngleNamespace = nullptr; + return mAngleNamespace; } if (!linkDriverNamespaceLocked(mAngleNamespace, vndkNamespace, "")) { diff --git a/libs/gui/FrameRateUtils.cpp b/libs/gui/FrameRateUtils.cpp index 11524e2b51..01aa7ed43c 100644 --- a/libs/gui/FrameRateUtils.cpp +++ b/libs/gui/FrameRateUtils.cpp @@ -42,6 +42,7 @@ bool ValidateFrameRate(float frameRate, int8_t compatibility, int8_t changeFrame if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT && compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE && + compatibility != ANATIVEWINDOW_FRAME_RATE_GTE && (!privileged || (compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT && compatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE))) { diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp index 9429d2cc15..86bf0ee745 100644 --- a/libs/gui/WindowInfo.cpp +++ b/libs/gui/WindowInfo.cpp @@ -262,8 +262,6 @@ void WindowInfoHandle::updateFrom(sp<WindowInfoHandle> handle) { } std::ostream& operator<<(std::ostream& out, const WindowInfo& info) { - std::string transform; - info.transform.dump(transform, "transform", " "); out << "name=" << info.name << ", id=" << info.id << ", displayId=" << info.displayId << ", inputConfig=" << info.inputConfig.string() << ", alpha=" << info.alpha << ", frame=[" << info.frame.left << "," << info.frame.top << "][" << info.frame.right << "," @@ -274,9 +272,11 @@ std::ostream& operator<<(std::ostream& out, const WindowInfo& info) { << ", ownerUid=" << info.ownerUid.toString() << ", dispatchingTimeout=" << std::chrono::duration_cast<std::chrono::milliseconds>(info.dispatchingTimeout).count() << "ms, token=" << info.token.get() - << ", touchOcclusionMode=" << ftl::enum_string(info.touchOcclusionMode) << "\n" - << transform; - if (info.canOccludePresentation) out << " canOccludePresentation"; + << ", touchOcclusionMode=" << ftl::enum_string(info.touchOcclusionMode); + if (info.canOccludePresentation) out << ", canOccludePresentation"; + std::string transform; + info.transform.dump(transform, "transform", " "); + out << "\n" << transform; return out; } diff --git a/libs/gui/fuzzer/Android.bp b/libs/gui/fuzzer/Android.bp deleted file mode 100644 index 35dd9ecd81..0000000000 --- a/libs/gui/fuzzer/Android.bp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2021 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 { - // 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"], - default_team: "trendy_team_android_core_graphics_stack", -} - -cc_defaults { - name: "libgui_fuzzer_defaults", - defaults: ["android.hardware.power-ndk_shared"], - static_libs: [ - "android.hidl.token@1.0-utils", - "libbinder_random_parcel", - "libgui_aidl_static", - "libgui_window_info_static", - "libpdx", - "libgmock", - "libgui_mocks", - "libgmock_ndk", - "libgmock_main", - "libgtest_ndk_c++", - "libgmock_main_ndk", - "librenderengine_mocks", - "perfetto_trace_protos", - "libcompositionengine_mocks", - "perfetto_trace_protos", - ], - shared_libs: [ - "android.hardware.configstore@1.0", - "android.hardware.configstore-utils", - "android.hardware.graphics.bufferqueue@1.0", - "android.hardware.graphics.bufferqueue@2.0", - "android.hidl.token@1.0", - "libSurfaceFlingerProp", - "libgui", - "libbase", - "liblog", - "libEGL", - "libGLESv2", - "libbinder", - "libcutils", - "libhidlbase", - "libinput", - "libui", - "libutils", - "libnativewindow", - "libvndksupport", - ], - header_libs: [ - "libdvr_headers", - "libui_fuzzableDataspaces_headers", - ], - fuzz_config: { - cc: [ - "android-media-fuzzing-reports@google.com", - ], - componentid: 155276, - hotlists: [ - "4593311", - ], - description: "The fuzzer targets the APIs of libgui library", - vector: "local_no_privileges_required", - service_privilege: "privileged", - users: "multi_user", - fuzzed_code_usage: "shipped", - }, -} - -cc_fuzz { - name: "libgui_surfaceComposer_fuzzer", - srcs: [ - "libgui_surfaceComposer_fuzzer.cpp", - ], - defaults: [ - "libgui_fuzzer_defaults", - "service_fuzzer_defaults", - ], -} - -cc_fuzz { - name: "libgui_surfaceComposerClient_fuzzer", - srcs: [ - "libgui_surfaceComposerClient_fuzzer.cpp", - ], - defaults: [ - "libgui_fuzzer_defaults", - "service_fuzzer_defaults", - ], -} - -cc_fuzz { - name: "libgui_parcelable_fuzzer", - srcs: [ - "libgui_parcelable_fuzzer.cpp", - ], - defaults: [ - "libgui_fuzzer_defaults", - ], -} - -cc_fuzz { - name: "libgui_bufferQueue_fuzzer", - srcs: [ - "libgui_bufferQueue_fuzzer.cpp", - ], - defaults: [ - "libgui_fuzzer_defaults", - ], -} - -cc_fuzz { - name: "libgui_consumer_fuzzer", - srcs: [ - "libgui_consumer_fuzzer.cpp", - ], - defaults: [ - "libgui_fuzzer_defaults", - ], -} - -cc_fuzz { - name: "libgui_displayEvent_fuzzer", - srcs: [ - "libgui_displayEvent_fuzzer.cpp", - ], - defaults: [ - "libgui_fuzzer_defaults", - ], -} diff --git a/libs/gui/fuzzer/README.md b/libs/gui/fuzzer/README.md deleted file mode 100644 index 96e27c989f..0000000000 --- a/libs/gui/fuzzer/README.md +++ /dev/null @@ -1,219 +0,0 @@ -# Fuzzers for Libgui - -## Table of contents -+ [libgui_surfaceComposer_fuzzer](#SurfaceComposer) -+ [libgui_surfaceComposerClient_fuzzer](#SurfaceComposerClient) -+ [libgui_parcelable_fuzzer](#Libgui_Parcelable) -+ [libgui_bufferQueue_fuzzer](#BufferQueue) -+ [libgui_consumer_fuzzer](#Libgui_Consumer) -+ [libgui_displayEvent_fuzzer](#LibGui_DisplayEvent) - -# <a name="libgui_surfaceComposer_fuzzer"></a> Fuzzer for SurfaceComposer - -SurfaceComposer supports the following parameters: -1. SurfaceWidth (parameter name:`width`) -2. SurfaceHeight (parameter name:`height`) -3. TransactionStateFlags (parameter name:`flags`) -4. TransformHint (parameter name:`outTransformHint`) -5. SurfacePixelFormat (parameter name:`format`) -6. LayerId (parameter name:`outLayerId`) -7. SurfaceComposerTags (parameter name:`surfaceTag`) -8. PowerBoostID (parameter name:`boostId`) -9. VsyncSource (parameter name:`vsyncSource`) -10. EventRegistrationFlags (parameter name:`eventRegistration`) -11. FrameRateCompatibility (parameter name:`frameRateCompatibility`) -12. ChangeFrameRateStrategy (parameter name:`changeFrameRateStrategy`) -13. HdrTypes (parameter name:`hdrTypes`) - -| Parameter| Valid Values| Configured Value| -|------------- |-------------| ----- | -|`surfaceTag` | 0.`BnSurfaceComposer::BOOT_FINISHED`, 1.`BnSurfaceComposer::CREATE_CONNECTION`, 2.`BnSurfaceComposer::GET_STATIC_DISPLAY_INFO`, 3.`BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION`, 4.`BnSurfaceComposer::CREATE_DISPLAY`, 5.`BnSurfaceComposer::DESTROY_DISPLAY`, 6.`BnSurfaceComposer::GET_PHYSICAL_DISPLAY_TOKEN`, 7.`BnSurfaceComposer::SET_TRANSACTION_STATE`, 8.`BnSurfaceComposer::AUTHENTICATE_SURFACE`, 9.`BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS`, 10.`BnSurfaceComposer::GET_DISPLAY_STATE`, 11.`BnSurfaceComposer::CAPTURE_DISPLAY`, 12.`BnSurfaceComposer::CAPTURE_LAYERS`, 13.`BnSurfaceComposer::CLEAR_ANIMATION_FRAME_STATS`, 14.`BnSurfaceComposer::GET_ANIMATION_FRAME_STATS`, 15.`BnSurfaceComposer::SET_POWER_MODE`, 16.`BnSurfaceComposer::GET_DISPLAY_STATS`, 17.`BnSurfaceComposer::SET_ACTIVE_COLOR_MODE`, 18.`BnSurfaceComposer::ENABLE_VSYNC_INJECTIONS`, 19.`BnSurfaceComposer::INJECT_VSYNC`, 20.`BnSurfaceComposer::GET_LAYER_DEBUG_INFO`, 21.`BnSurfaceComposer::GET_COMPOSITION_PREFERENCE`, 22.`BnSurfaceComposer::GET_COLOR_MANAGEMENT`, 23.`BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES`, 24.`BnSurfaceComposer::SET_DISPLAY_CONTENT_SAMPLING_ENABLED`, 25.`BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLE`, 26.`BnSurfaceComposer::GET_PROTECTED_CONTENT_SUPPORT`, 27.`BnSurfaceComposer::IS_WIDE_COLOR_DISPLAY`, 28.`BnSurfaceComposer::GET_DISPLAY_NATIVE_PRIMARIES`, 29.`BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS`, 30.`BnSurfaceComposer::ADD_REGION_SAMPLING_LISTENER`, 31.`BnSurfaceComposer::REMOVE_REGION_SAMPLING_LISTENER`, 32.`BnSurfaceComposer::SET_DESIRED_DISPLAY_MODE_SPECS`, 33.`BnSurfaceComposer::GET_DESIRED_DISPLAY_MODE_SPECS`, 34.`BnSurfaceComposer::GET_DISPLAY_BRIGHTNESS_SUPPORT`, 35.`BnSurfaceComposer::SET_DISPLAY_BRIGHTNESS`, 36.`BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID`, 37.`BnSurfaceComposer::NOTIFY_POWER_BOOST`, 38.`BnSurfaceComposer::SET_GLOBAL_SHADOW_SETTINGS`, 39.`BnSurfaceComposer::SET_AUTO_LOW_LATENCY_MODE`, 40.`BnSurfaceComposer::SET_GAME_CONTENT_TYPE`, 41.`BnSurfaceComposer::SET_FRAME_RATE`, 42.`BnSurfaceComposer::ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN`, 43.`BnSurfaceComposer::SET_FRAME_TIMELINE_INFO`, 44.`BnSurfaceComposer::ADD_TRANSACTION_TRACE_LISTENER`, 45.`BnSurfaceComposer::GET_GPU_CONTEXT_PRIORITY`, 46.`BnSurfaceComposer::GET_MAX_ACQUIRED_BUFFER_COUNT`, 47.`BnSurfaceComposer::GET_DYNAMIC_DISPLAY_INFO`, 48.`BnSurfaceComposer::ADD_FPS_LISTENER`, 49.`BnSurfaceComposer::REMOVE_FPS_LISTENER`, 50.`BnSurfaceComposer::OVERRIDE_HDR_TYPES`, 51.`BnSurfaceComposer::ADD_HDR_LAYER_INFO_LISTENER`, 52.`BnSurfaceComposer::REMOVE_HDR_LAYER_INFO_LISTENER`, 53.`BnSurfaceComposer::ON_PULL_ATOM`, 54.`BnSurfaceComposer::ADD_TUNNEL_MODE_ENABLED_LISTENER`, 55.`BnSurfaceComposer::REMOVE_TUNNEL_MODE_ENABLED_LISTENER` | Value obtained from FuzzedDataProvider| -|`boostId`| 0.`hardware::power::Boost::INTERACTION`, 1.`hardware::power::Boost::DISPLAY_UPDATE_IMMINENT`, 2.`hardware::power::Boost::ML_ACC`, 3.`hardware::power::Boost::AUDIO_LAUNCH`, 4.`hardware::power::Boost::CAMERA_LAUNCH`, 5.`hardware::power::Boost::CAMERA_SHOT` |Value obtained from FuzzedDataProvider| -|`vsyncSource`| 0.`ISurfaceComposer::eVsyncSourceApp`, 1.`ISurfaceComposer::eVsyncSourceSurfaceFlinger`, |Value obtained from FuzzedDataProvider| -|`eventRegistration`| 0.`ISurfaceComposer::EventRegistration::modeChanged`, 1.`ISurfaceComposer::EventRegistration::frameRateOverride` |Value obtained from FuzzedDataProvider| -|`frameRateCompatibility`| 0.`ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT`, 1.`ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE` |Value obtained from FuzzedDataProvider| -|`changeFrameRateStrategy`| 0.`ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS`, 1.`ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS` |Value obtained from FuzzedDataProvider| -|`hdrTypes`| 0.`ui::Hdr::DOLBY_VISION`, 1.`ui::Hdr::HDR10`, 2.`ui::Hdr::HLG`, 3.`ui::Hdr::HDR10_PLUS` |Value obtained from FuzzedDataProvider| - -#### Steps to run -1. Build the fuzzer -``` - $ mm -j$(nproc) libgui_surfaceComposer_fuzzer -``` -2. Run on device -``` - $ adb sync data - $ adb shell /data/fuzz/arm64/libgui_surfaceComposer_fuzzer/libgui_surfaceComposer_fuzzer -``` - -# <a name="libgui_surfaceComposerClient_fuzzer"></a> Fuzzer for SurfaceComposerClient - -SurfaceComposerClient supports the following data sources: -1. SurfaceWidth (parameter name:`width`) -2. SurfaceHeight (parameter name:`height`) -3. TransactionStateFlags (parameter name:`flags`) -4. TransformHint (parameter name:`outTransformHint`) -5. SurfacePixelFormat (parameter name:`format`) -6. LayerId (parameter name:`outLayerId`) -7. SurfaceComposerClientTags (parameter name:`surfaceTag`) -8. DefaultMode (parameter name:`defaultMode`) -9. PrimaryRefreshRateMin (parameter name:`primaryRefreshRateMin`) -10. PrimaryRefreshRateMax (parameter name:`primaryRefreshRateMax`) -11. AppRefreshRateMin (parameter name:`appRefreshRateMin`) -12. AppRefreshRateMax (parameter name:`appRefreshRateMax`) -13. DisplayPowerMode (parameter name:`mode`) -14. CacheId (parameter name:`cacheId`) -15. DisplayBrightness (parameter name:`brightness`) -16. PowerBoostID (parameter name:`boostId`) -17. AtomId (parameter name:`atomId`) -18. ComponentMask (parameter name:`componentMask`) -19. MaxFrames (parameter name:`maxFrames`) -20. TaskId (parameter name:`taskId`) -21. Alpha (parameter name:`aplha`) -22. CornerRadius (parameter name:`cornerRadius`) -23. BackgroundBlurRadius (parameter name:`backgroundBlurRadius`) -24. Half3Color (parameter name:`color`) -25. LayerStack (parameter name:`layerStack`) -26. Dataspace (parameter name:`dataspace`) -27. Api (parameter name:`api`) -28. Priority (parameter name:`priority`) -29. TouchableRegionPointX (parameter name:`pointX`) -30. TouchableRegionPointY (parameter name:`pointY`) -31. ColorMode (parameter name:`colorMode`) -32. WindowInfoFlags (parameter name:`flags`) -33. WindowInfoTransformOrientation (parameter name:`transform`) - -| Parameter| Valid Values| Configured Value| -|------------- |-------------| ----- | -|`surfaceTag`| 0.`Tag::CREATE_SURFACE`, 1.`Tag::CREATE_WITH_SURFACE_PARENT`, 2.`Tag::CLEAR_LAYER_FRAME_STATS`, 3.`Tag::GET_LAYER_FRAME_STATS`, 4.`Tag::MIRROR_SURFACE`, 5.`Tag::LAST` |Value obtained from FuzzedDataProvider| -|`mode`| 0.`gui::TouchOcclusionMode::BLOCK_UNTRUSTED`, 1.`gui::TouchOcclusionMode::USE_OPACITY`, 2.`gui::TouchOcclusionMode::ALLOW` |Value obtained from FuzzedDataProvider| -|`boostId`| 0.`hardware::power::Boost::INTERACTION`, 1.`hardware::power::Boost::DISPLAY_UPDATE_IMMINENT`, 2.`hardware::power::Boost::ML_ACC`, 3.`hardware::power::Boost::AUDIO_LAUNCH`, 4.`hardware::power::Boost::CAMERA_LAUNCH`, 5.`hardware::power::Boost::CAMERA_SHOT` |Value obtained from FuzzedDataProvider| -|`colorMode`|0.`ui::ColorMode::NATIVE`, 1.`ui::ColorMode::STANDARD_BT601_625`, 2.`ui::ColorMode::STANDARD_BT601_625_UNADJUSTED`, 3.`ui::ColorMode::STANDARD_BT601_525`, 4.`ui::ColorMode::STANDARD_BT601_525_UNADJUSTED`, 5.`ui::ColorMode::STANDARD_BT709`, 6.`ui::ColorMode::DCI_P3`, 7.`ui::ColorMode::SRGB`, 8.`ui::ColorMode::ADOBE_RGB`, 9.`ui::ColorMode::DISPLAY_P3`, 10.`ui::ColorMode::BT2020`, 11.`ui::ColorMode::BT2100_PQ`, 12.`ui::ColorMode::BT2100_HLG`, 13.`ui::ColorMode::DISPLAY_BT2020` |Value obtained from FuzzedDataProvider| -|`flags`|0 .`gui::WindowInfo::Flag::ALLOW_LOCK_WHILE_SCREEN_ON`, 1.`gui::WindowInfo::Flag::DIM_BEHIND`, 2.`gui::WindowInfo::Flag::BLUR_BEHIND`, 3.`gui::WindowInfo::Flag::NOT_FOCUSABLE`, 4.`gui::WindowInfo::Flag::NOT_TOUCHABLE`, 5.`gui::WindowInfo::Flag::NOT_TOUCH_MODAL`, 6.`gui::WindowInfo::Flag::TOUCHABLE_WHEN_WAKING`, 7.`gui::WindowInfo::Flag::KEEP_SCREEN_ON`, 8.`gui::WindowInfo::Flag::LAYOUT_IN_SCREEN`, 9.`gui::WindowInfo::Flag::LAYOUT_NO_LIMITS`, 10.`gui::WindowInfo::Flag::FULLSCREEN`, 11.`gui::WindowInfo::Flag::FORCE_NOT_FULLSCREEN`, 12.`gui::WindowInfo::Flag::DITHER`, 13.`gui::WindowInfo::Flag::SECURE`, 14.`gui::WindowInfo::Flag::SCALED`, 15.`gui::WindowInfo::Flag::IGNORE_CHEEK_PRESSES`, 16.`gui::WindowInfo::Flag::LAYOUT_INSET_DECOR`, 17.`gui::WindowInfo::Flag::ALT_FOCUSABLE_IM`, 18.`gui::WindowInfo::Flag::WATCH_OUTSIDE_TOUCH`, 19.`gui::WindowInfo::Flag::SHOW_WHEN_LOCKED`, 20.`gui::WindowInfo::Flag::SHOW_WALLPAPER`, 21.`gui::WindowInfo::Flag::TURN_SCREEN_ON`, 22.`gui::WindowInfo::Flag::DISMISS_KEYGUARD`, 23.`gui::WindowInfo::Flag::SPLIT_TOUCH`, 24.`gui::WindowInfo::Flag::HARDWARE_ACCELERATED`, 25.`gui::WindowInfo::Flag::LAYOUT_IN_OVERSCAN`, 26.`gui::WindowInfo::Flag::TRANSLUCENT_STATUS`, 27.`gui::WindowInfo::Flag::TRANSLUCENT_NAVIGATION`, 28.`gui::WindowInfo::Flag::LOCAL_FOCUS_MODE`, 29.`gui::WindowInfo::Flag::SLIPPERY`, 30.`gui::WindowInfo::Flag::LAYOUT_ATTACHED_IN_DECOR`, 31.`gui::WindowInfo::Flag::DRAWS_SYSTEM_BAR_BACKGROUNDS`, |Value obtained from FuzzedDataProvider| -|`dataspace`| 0.`ui::Dataspace::UNKNOWN`, 1.`ui::Dataspace::ARBITRARY`, 2.`ui::Dataspace::STANDARD_SHIFT`, 3.`ui::Dataspace::STANDARD_MASK`, 4.`ui::Dataspace::STANDARD_UNSPECIFIED`, 5.`ui::Dataspace::STANDARD_BT709`, 6.`ui::Dataspace::STANDARD_BT601_625`, 7.`ui::Dataspace::STANDARD_BT601_625_UNADJUSTED`, 8.`ui::Dataspace::STANDARD_BT601_525`, 9.`ui::Dataspace::STANDARD_BT601_525_UNADJUSTED`, 10.`ui::Dataspace::STANDARD_BT2020`, 11.`ui::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE`, 12.`ui::Dataspace::STANDARD_BT470M`, 13.`ui::Dataspace::STANDARD_FILM`, 14.`ui::Dataspace::STANDARD_DCI_P3`, 15.`ui::Dataspace::STANDARD_ADOBE_RGB`, 16.`ui::Dataspace::TRANSFER_SHIFT`, 17.`ui::Dataspace::TRANSFER_MASK`, 18.`ui::Dataspace::TRANSFER_UNSPECIFIED`, 19.`ui::Dataspace::TRANSFER_LINEAR`, 20.`ui::Dataspace::TRANSFER_SRGB`, 21.`ui::Dataspace::TRANSFER_SMPTE_170M`, 22.`ui::Dataspace::TRANSFER_GAMMA2_2`, 23.`ui::Dataspace::TRANSFER_GAMMA2_6`, 24.`ui::Dataspace::TRANSFER_GAMMA2_8`, 25.`ui::Dataspace::TRANSFER_ST2084`, 26.`ui::Dataspace::TRANSFER_HLG`, 27.`ui::Dataspace::RANGE_SHIFT`, 28.`ui::Dataspace::RANGE_MASK`, 29.`ui::Dataspace::RANGE_UNSPECIFIED`, 30.`ui::Dataspace::RANGE_FULL`, 31.`ui::Dataspace::RANGE_LIMITED`, 32.`ui::Dataspace::RANGE_EXTENDED`, 33.`ui::Dataspace::SRGB_LINEAR`, 34.`ui::Dataspace::V0_SRGB_LINEAR`, 35.`ui::Dataspace::V0_SCRGB_LINEAR`, 36.`ui::Dataspace::SRGB`, 37.`ui::Dataspace::V0_SRGB`, 38.`ui::Dataspace::V0_SCRGB`, 39.`ui::Dataspace::JFIF`, 40.`ui::Dataspace::V0_JFIF`, 41.`ui::Dataspace::BT601_625`, 42.`ui::Dataspace::V0_BT601_625`, 43.`ui::Dataspace::BT601_525`, 44.`ui::Dataspace::V0_BT601_525`, 45.`ui::Dataspace::BT709`, 46.`ui::Dataspace::V0_BT709`, 47.`ui::Dataspace::DCI_P3_LINEAR`, 48.`ui::Dataspace::DCI_P3`, 49.`ui::Dataspace::DISPLAY_P3_LINEAR`, 50.`ui::Dataspace::DISPLAY_P3`, 51.`ui::Dataspace::ADOBE_RGB`, 52.`ui::Dataspace::BT2020_LINEAR`, 53.`ui::Dataspace::BT2020`, 54.`ui::Dataspace::BT2020_PQ`, 55.`ui::Dataspace::DEPTH`, 56.`ui::Dataspace::SENSOR`, 57.`ui::Dataspace::BT2020_ITU`, 58.`ui::Dataspace::BT2020_ITU_PQ`, 59.`ui::Dataspace::BT2020_ITU_HLG`, 60.`ui::Dataspace::BT2020_HLG`, 61.`ui::Dataspace::DISPLAY_BT2020`, 62.`ui::Dataspace::DYNAMIC_DEPTH`, 63.`ui::Dataspace::JPEG_APP_SEGMENTS`, 64.`ui::Dataspace::HEIF`, |Value obtained from FuzzedDataProvider| -|`transform`| 0.`ui::Transform::ROT_0`, 1.`ui::Transform::FLIP_H`, 2.`ui::Transform::FLIP_V`, 3.`ui::Transform::ROT_90`, 4.`ui::Transform::ROT_180`, 5.`ui::Transform::ROT_270` |Value obtained from FuzzedDataProvider| - -#### Steps to run -1. Build the fuzzer -``` - $ mm -j$(nproc) libgui_surfaceComposerClient_fuzzer -``` -2. To run on device -``` - $ adb sync data - $ adb shell /data/fuzz/arm64/libgui_surfaceComposerClient_fuzzer/libgui_surfaceComposerClient_fuzzer -``` - -# <a name="libgui_parcelable_fuzzer"></a> Fuzzer for Libgui_Parcelable - -Libgui_Parcelable supports the following parameters: -1. LayerMetadataKey (parameter name:`key`) -2. Dataspace (parameter name:`mDataspace`) - -| Parameter| Valid Values| Configured Value| -|------------- |-------------| ----- | -|`key`| 0.`view::LayerMetadataKey::METADATA_OWNER_UID`, 1.`view::LayerMetadataKey::METADATA_WINDOW_TYPE`, 2.`view::LayerMetadataKey::METADATA_TASK_ID`, 3.`view::LayerMetadataKey::METADATA_MOUSE_CURSOR`, 4.`view::LayerMetadataKey::METADATA_ACCESSIBILITY_ID`, 5.`view::LayerMetadataKey::METADATA_OWNER_PID`, 6.`view::LayerMetadataKey::METADATA_DEQUEUE_TIME`, 7.`view::LayerMetadataKey::METADATA_GAME_MODE`, |Value obtained from FuzzedDataProvider| -|`mDataSpace`| 0.`ui::Dataspace::UNKNOWN`, 1.`ui::Dataspace::ARBITRARY`, 2.`ui::Dataspace::STANDARD_SHIFT`, 3.`ui::Dataspace::STANDARD_MASK`, 4.`ui::Dataspace::STANDARD_UNSPECIFIED`, 5.`ui::Dataspace::STANDARD_BT709`, 6.`ui::Dataspace::STANDARD_BT601_625`, 7.`ui::Dataspace::STANDARD_BT601_625_UNADJUSTED`, 8.`ui::Dataspace::STANDARD_BT601_525`, 9.`ui::Dataspace::STANDARD_BT601_525_UNADJUSTED`, 10.`ui::Dataspace::STANDARD_BT2020`, 11.`ui::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE`, 12.`ui::Dataspace::STANDARD_BT470M`, 13.`ui::Dataspace::STANDARD_FILM`, 14.`ui::Dataspace::STANDARD_DCI_P3`, 15.`ui::Dataspace::STANDARD_ADOBE_RGB`, 16.`ui::Dataspace::TRANSFER_SHIFT`, 17.`ui::Dataspace::TRANSFER_MASK`, 18.`ui::Dataspace::TRANSFER_UNSPECIFIED`, 19.`ui::Dataspace::TRANSFER_LINEAR`, 20.`ui::Dataspace::TRANSFER_SRGB`, 21.`ui::Dataspace::TRANSFER_SMPTE_170M`, 22.`ui::Dataspace::TRANSFER_GAMMA2_2`, 23.`ui::Dataspace::TRANSFER_GAMMA2_6`, 24.`ui::Dataspace::TRANSFER_GAMMA2_8`, 25.`ui::Dataspace::TRANSFER_ST2084`, 26.`ui::Dataspace::TRANSFER_HLG`, 27.`ui::Dataspace::RANGE_SHIFT`, 28.`ui::Dataspace::RANGE_MASK`, 29.`ui::Dataspace::RANGE_UNSPECIFIED`, 30.`ui::Dataspace::RANGE_FULL`, 31.`ui::Dataspace::RANGE_LIMITED`, 32.`ui::Dataspace::RANGE_EXTENDED`, 33.`ui::Dataspace::SRGB_LINEAR`, 34.`ui::Dataspace::V0_SRGB_LINEAR`, 35.`ui::Dataspace::V0_SCRGB_LINEAR`, 36.`ui::Dataspace::SRGB`, 37.`ui::Dataspace::V0_SRGB`, 38.`ui::Dataspace::V0_SCRGB`, 39.`ui::Dataspace::JFIF`, 40.`ui::Dataspace::V0_JFIF`, 41.`ui::Dataspace::BT601_625`, 42.`ui::Dataspace::V0_BT601_625`, 43.`ui::Dataspace::BT601_525`, 44.`ui::Dataspace::V0_BT601_525`, 45.`ui::Dataspace::BT709`, 46.`ui::Dataspace::V0_BT709`, 47.`ui::Dataspace::DCI_P3_LINEAR`, 48.`ui::Dataspace::DCI_P3`, 49.`ui::Dataspace::DISPLAY_P3_LINEAR`, 50.`ui::Dataspace::DISPLAY_P3`, 51.`ui::Dataspace::ADOBE_RGB`, 52.`ui::Dataspace::BT2020_LINEAR`, 53.`ui::Dataspace::BT2020`, 54.`ui::Dataspace::BT2020_PQ`, 55.`ui::Dataspace::DEPTH`, 56.`ui::Dataspace::SENSOR`, 57.`ui::Dataspace::BT2020_ITU`, 58.`ui::Dataspace::BT2020_ITU_PQ`, 59.`ui::Dataspace::BT2020_ITU_HLG`, 60.`ui::Dataspace::BT2020_HLG`, 61.`ui::Dataspace::DISPLAY_BT2020`, 62.`ui::Dataspace::DYNAMIC_DEPTH`, 63.`ui::Dataspace::JPEG_APP_SEGMENTS`, 64.`ui::Dataspace::HEIF`, |Value obtained from FuzzedDataProvider| - -#### Steps to run -1. Build the fuzzer -``` - $ mm -j$(nproc) libgui_fuzzer -``` -2. Run on device -``` - $ adb sync data - $ adb shell /data/fuzz/arm64/libgui_fuzzer/libgui_fuzzer -``` - -# <a name="libgui_bufferQueue_fuzzer"></a> Fuzzer for BufferQueue - -BufferQueue supports the following parameters: -1. SurfaceWidth (parameter name:`width`) -2. SurfaceHeight (parameter name:`height`) -3. TransactionStateFlags (parameter name:`flags`) -4. TransformHint (parameter name:`outTransformHint`) -5. SurfacePixelFormat (parameter name:`format`) -6. LayerId (parameter name:`layerId`) -7. BufferId (parameter name:`bufferId`) -8. FrameNumber (parameter name:`frameNumber`) -9. FrameRate (parameter name:`frameRate`) -10. Compatability (parameter name:`compatability`) -11. LatchTime (parameter name:`latchTime`) -12. AcquireTime (parameter name:`acquireTime`) -13. RefreshTime (parameter name:`refreshTime`) -14. DequeueTime (parameter name:`dequeueTime`) -15. Slot (parameter name:`slot`) -16. MaxBuffers (parameter name:`maxBuffers`) -17. GenerationNumber (parameter name:`generationNumber`) -18. Api (parameter name:`api`) -19. Usage (parameter name:`usage`) -20. MaxFrameNumber (parameter name:`maxFrameNumber`) -21. BufferCount (parameter name:`bufferCount`) -22. MaxAcquredBufferCount (parameter name:`maxAcquredBufferCount`) -23. Status (parameter name:`status`) -24. ApiConnection (parameter name:`apiConnection`) -25. Dataspace (parameter name:`dataspace`) - -| Parameter| Valid Values| Configured Value| -|------------- |-------------| ----- | -|`status`| 0.`OK`, 1.`NO_MEMORY`, 2.`NO_INIT`, 3.`BAD_VALUE`, 4.`DEAD_OBJECT`, 5.`INVALID_OPERATION`, 6.`TIMED_OUT`, 7.`WOULD_BLOCK`, 8.`UNKNOWN_ERROR`, 9.`ALREADY_EXISTS`, |Value obtained from FuzzedDataProvider| -|`apiConnection`| 0.`BufferQueueCore::CURRENTLY_CONNECTED_API`, 1.`BufferQueueCore::NO_CONNECTED_API`, 2.`NATIVE_WINDOW_API_EGL`, 3.`NATIVE_WINDOW_API_CPU`, 4.`NATIVE_WINDOW_API_MEDIA`, 5.`NATIVE_WINDOW_API_CAMERA`, |Value obtained from FuzzedDataProvider| -|`dataspace`| 0.`ui::Dataspace::UNKNOWN`, 1.`ui::Dataspace::ARBITRARY`, 2.`ui::Dataspace::STANDARD_SHIFT`, 3.`ui::Dataspace::STANDARD_MASK`, 4.`ui::Dataspace::STANDARD_UNSPECIFIED`, 5.`ui::Dataspace::STANDARD_BT709`, 6.`ui::Dataspace::STANDARD_BT601_625`, 7.`ui::Dataspace::STANDARD_BT601_625_UNADJUSTED`, 8.`ui::Dataspace::STANDARD_BT601_525`, 9.`ui::Dataspace::STANDARD_BT601_525_UNADJUSTED`, 10.`ui::Dataspace::STANDARD_BT2020`, 11.`ui::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE`, 12.`ui::Dataspace::STANDARD_BT470M`, 13.`ui::Dataspace::STANDARD_FILM`, 14.`ui::Dataspace::STANDARD_DCI_P3`, 15.`ui::Dataspace::STANDARD_ADOBE_RGB`, 16.`ui::Dataspace::TRANSFER_SHIFT`, 17.`ui::Dataspace::TRANSFER_MASK`, 18.`ui::Dataspace::TRANSFER_UNSPECIFIED`, 19.`ui::Dataspace::TRANSFER_LINEAR`, 20.`ui::Dataspace::TRANSFER_SRGB`, 21.`ui::Dataspace::TRANSFER_SMPTE_170M`, 22.`ui::Dataspace::TRANSFER_GAMMA2_2`, 23.`ui::Dataspace::TRANSFER_GAMMA2_6`, 24.`ui::Dataspace::TRANSFER_GAMMA2_8`, 25.`ui::Dataspace::TRANSFER_ST2084`, 26.`ui::Dataspace::TRANSFER_HLG`, 27.`ui::Dataspace::RANGE_SHIFT`, 28.`ui::Dataspace::RANGE_MASK`, 29.`ui::Dataspace::RANGE_UNSPECIFIED`, 30.`ui::Dataspace::RANGE_FULL`, 31.`ui::Dataspace::RANGE_LIMITED`, 32.`ui::Dataspace::RANGE_EXTENDED`, 33.`ui::Dataspace::SRGB_LINEAR`, 34.`ui::Dataspace::V0_SRGB_LINEAR`, 35.`ui::Dataspace::V0_SCRGB_LINEAR`, 36.`ui::Dataspace::SRGB`, 37.`ui::Dataspace::V0_SRGB`, 38.`ui::Dataspace::V0_SCRGB`, 39.`ui::Dataspace::JFIF`, 40.`ui::Dataspace::V0_JFIF`, 41.`ui::Dataspace::BT601_625`, 42.`ui::Dataspace::V0_BT601_625`, 43.`ui::Dataspace::BT601_525`, 44.`ui::Dataspace::V0_BT601_525`, 45.`ui::Dataspace::BT709`, 46.`ui::Dataspace::V0_BT709`, 47.`ui::Dataspace::DCI_P3_LINEAR`, 48.`ui::Dataspace::DCI_P3`, 49.`ui::Dataspace::DISPLAY_P3_LINEAR`, 50.`ui::Dataspace::DISPLAY_P3`, 51.`ui::Dataspace::ADOBE_RGB`, 52.`ui::Dataspace::BT2020_LINEAR`, 53.`ui::Dataspace::BT2020`, 54.`ui::Dataspace::BT2020_PQ`, 55.`ui::Dataspace::DEPTH`, 56.`ui::Dataspace::SENSOR`, 57.`ui::Dataspace::BT2020_ITU`, 58.`ui::Dataspace::BT2020_ITU_PQ`, 59.`ui::Dataspace::BT2020_ITU_HLG`, 60.`ui::Dataspace::BT2020_HLG`, 61.`ui::Dataspace::DISPLAY_BT2020`, 62.`ui::Dataspace::DYNAMIC_DEPTH`, 63.`ui::Dataspace::JPEG_APP_SEGMENTS`, 64.`ui::Dataspace::HEIF`, |Value obtained from FuzzedDataProvider| - -#### Steps to run -1. Build the fuzzer -``` - $ mm -j$(nproc) libgui_bufferQueue_fuzzer -``` -2. To run on device -``` - $ adb sync data - $ adb shell /data/fuzz/arm64/libgui_bufferQueue_fuzzer/libgui_bufferQueue_fuzzer -``` - -# <a name="libgui_consumer_fuzzer"></a> Fuzzer for Libgui_Consumer - -Libgui_Consumer supports the following parameters: -1. GraphicWidth (parameter name:`graphicWidth`) -2. GraphicHeight (parameter name:`graphicHeight`) -4. TransformHint (parameter name:`outTransformHint`) -5. GraphicPixelFormat (parameter name:`format`) -6. Usage (parameter name:`usage`) - -#### Steps to run -1. Build the fuzzer -``` - $ mm -j$(nproc) libgui_consumer_fuzzer -``` -2. Run on device -``` - $ adb sync data - $ adb shell /data/fuzz/arm64/libgui_consumer_fuzzer/libgui_consumer_fuzzer -``` - -# <a name="libgui_displayEvent_fuzzer"></a> Fuzzer for LibGui_DisplayEvent - -LibGui_DisplayEvent supports the following parameters: -1. DisplayEventType (parameter name:`type`) -2. Events (parameter name:`events`) -3. VsyncSource (parameter name:`vsyncSource`) -4. EventRegistrationFlags (parameter name:`flags`) - -| Parameter| Valid Values| Configured Value| -|------------- |-------------| ----- | -|`vsyncSource`| 0.`ISurfaceComposer::eVsyncSourceApp`, 1.`ISurfaceComposer::eVsyncSourceSurfaceFlinger`, |Value obtained from FuzzedDataProvider| -|`flags`| 0.`ISurfaceComposer::EventRegistration::modeChanged`, 1.`ISurfaceComposer::EventRegistration::frameRateOverride`, |Value obtained from FuzzedDataProvider| -|`type`| 0.`DisplayEventReceiver::DISPLAY_EVENT_NULL`, 1.`DisplayEventReceiver::DISPLAY_EVENT_VSYNC`, 2.`DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG`, 3.`DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE`, 4.`DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE`, 5.`DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH`, |Value obtained from FuzzedDataProvider| -|`events`| 0.`Looper::EVENT_INPUT`, 1.`Looper::EVENT_OUTPUT`, 2.`Looper::EVENT_ERROR`, 3.`Looper::EVENT_HANGUP`, 4.`Looper::EVENT_INVALID`, |Value obtained from FuzzedDataProvider| - -#### Steps to run -1. Build the fuzzer -``` - $ mm -j$(nproc) libgui_displayEvent_fuzzer -``` -2. Run on device -``` - $ adb sync data - $ adb shell /data/fuzz/arm64/libgui_displayEvent_fuzzer/libgui_displayEvent_fuzzer -``` diff --git a/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp b/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp deleted file mode 100644 index 2e270b721f..0000000000 --- a/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright 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. - */ -#include <android-base/stringprintf.h> -#include <gui/BufferQueueConsumer.h> -#include <gui/BufferQueueCore.h> -#include <gui/BufferQueueProducer.h> -#include <gui/bufferqueue/2.0/types.h> -#include <system/window.h> - -#include <libgui_fuzzer_utils.h> - -using namespace android; -using namespace hardware::graphics::bufferqueue; -using namespace V1_0::utils; -using namespace V2_0::utils; - -constexpr int32_t kMaxBytes = 256; - -constexpr int32_t kError[] = { - OK, NO_MEMORY, NO_INIT, BAD_VALUE, DEAD_OBJECT, INVALID_OPERATION, - TIMED_OUT, WOULD_BLOCK, UNKNOWN_ERROR, ALREADY_EXISTS, -}; - -constexpr int32_t kAPIConnection[] = { - BufferQueueCore::CURRENTLY_CONNECTED_API, - BufferQueueCore::NO_CONNECTED_API, - NATIVE_WINDOW_API_EGL, - NATIVE_WINDOW_API_CPU, - NATIVE_WINDOW_API_MEDIA, - NATIVE_WINDOW_API_CAMERA, -}; - -class BufferQueueFuzzer { -public: - BufferQueueFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){}; - void process(); - -private: - void invokeTypes(); - void invokeH2BGraphicBufferV1(); - void invokeH2BGraphicBufferV2(); - void invokeBufferQueueConsumer(); - void invokeBufferQueueProducer(); - void invokeBlastBufferQueue(); - void invokeQuery(sp<BufferQueueProducer>); - void invokeQuery(sp<V1_0::utils::H2BGraphicBufferProducer>); - void invokeQuery(sp<V2_0::utils::H2BGraphicBufferProducer>); - void invokeAcquireBuffer(sp<BufferQueueConsumer>); - void invokeOccupancyTracker(sp<BufferQueueConsumer>); - sp<SurfaceControl> makeSurfaceControl(); - sp<BLASTBufferQueue> makeBLASTBufferQueue(sp<SurfaceControl>); - - FuzzedDataProvider mFdp; -}; - -class ManageResourceHandle { -public: - ManageResourceHandle(FuzzedDataProvider* fdp) { - mNativeHandle = native_handle_create(0 /*numFds*/, 1 /*numInts*/); - mShouldOwn = fdp->ConsumeBool(); - mStream = NativeHandle::create(mNativeHandle, mShouldOwn); - } - ~ManageResourceHandle() { - if (!mShouldOwn) { - native_handle_close(mNativeHandle); - native_handle_delete(mNativeHandle); - } - } - sp<NativeHandle> getStream() { return mStream; } - -private: - bool mShouldOwn; - sp<NativeHandle> mStream; - native_handle_t* mNativeHandle; -}; - -sp<SurfaceControl> BufferQueueFuzzer::makeSurfaceControl() { - sp<IBinder> handle; - const sp<FakeBnSurfaceComposerClient> testClient(new FakeBnSurfaceComposerClient()); - sp<SurfaceComposerClient> client = new SurfaceComposerClient(testClient); - sp<BnGraphicBufferProducer> producer; - uint32_t layerId = mFdp.ConsumeIntegral<uint32_t>(); - std::string layerName = base::StringPrintf("#%d", layerId); - return sp<SurfaceControl>::make(client, handle, layerId, layerName, - mFdp.ConsumeIntegral<int32_t>(), - mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<int32_t>(), - mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint32_t>()); -} - -sp<BLASTBufferQueue> BufferQueueFuzzer::makeBLASTBufferQueue(sp<SurfaceControl> surface) { - return sp<BLASTBufferQueue>::make(mFdp.ConsumeRandomLengthString(kMaxBytes), surface, - mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<int32_t>()); -} - -void BufferQueueFuzzer::invokeBlastBufferQueue() { - sp<SurfaceControl> surface = makeSurfaceControl(); - sp<BLASTBufferQueue> queue = makeBLASTBufferQueue(surface); - - BufferItem item; - queue->onFrameAvailable(item); - queue->onFrameReplaced(item); - uint64_t bufferId = mFdp.ConsumeIntegral<uint64_t>(); - queue->onFrameDequeued(bufferId); - queue->onFrameCancelled(bufferId); - - SurfaceComposerClient::Transaction next; - uint64_t frameNumber = mFdp.ConsumeIntegral<uint64_t>(); - queue->mergeWithNextTransaction(&next, frameNumber); - queue->applyPendingTransactions(frameNumber); - - queue->update(surface, mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<int32_t>()); - queue->setFrameRate(mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeIntegral<int8_t>(), - mFdp.ConsumeBool() /*shouldBeSeamless*/); - FrameTimelineInfo info; - queue->setFrameTimelineInfo(mFdp.ConsumeIntegral<uint64_t>(), info); - - ManageResourceHandle handle(&mFdp); - queue->setSidebandStream(handle.getStream()); - - queue->getLastTransformHint(); - queue->getLastAcquiredFrameNum(); - - CompositorTiming compTiming; - sp<Fence> previousFence = new Fence(memfd_create("pfd", MFD_ALLOW_SEALING)); - sp<Fence> gpuFence = new Fence(memfd_create("gfd", MFD_ALLOW_SEALING)); - FrameEventHistoryStats frameStats(frameNumber, mFdp.ConsumeIntegral<uint64_t>(), gpuFence, - compTiming, mFdp.ConsumeIntegral<int64_t>(), - mFdp.ConsumeIntegral<int64_t>()); - std::vector<SurfaceControlStats> stats; - sp<Fence> presentFence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING)); - SurfaceControlStats controlStats(surface, mFdp.ConsumeIntegral<int64_t>(), - mFdp.ConsumeIntegral<int64_t>(), presentFence, previousFence, - mFdp.ConsumeIntegral<uint32_t>(), frameStats, - mFdp.ConsumeIntegral<uint32_t>()); - stats.push_back(controlStats); -} - -void BufferQueueFuzzer::invokeQuery(sp<BufferQueueProducer> producer) { - int32_t value; - producer->query(mFdp.ConsumeIntegral<int32_t>(), &value); -} - -void BufferQueueFuzzer::invokeQuery(sp<V1_0::utils::H2BGraphicBufferProducer> producer) { - int32_t value; - producer->query(mFdp.ConsumeIntegral<int32_t>(), &value); -} - -void BufferQueueFuzzer::invokeQuery(sp<V2_0::utils::H2BGraphicBufferProducer> producer) { - int32_t value; - producer->query(mFdp.ConsumeIntegral<int32_t>(), &value); -} - -void BufferQueueFuzzer::invokeBufferQueueProducer() { - sp<BufferQueueCore> core(new BufferQueueCore()); - sp<BufferQueueProducer> producer(new BufferQueueProducer(core)); - const sp<android::IProducerListener> listener; - android::IGraphicBufferProducer::QueueBufferOutput output; - uint32_t api = mFdp.ConsumeIntegral<uint32_t>(); - producer->connect(listener, api, mFdp.ConsumeBool() /*producerControlledByApp*/, &output); - - sp<GraphicBuffer> buffer; - int32_t slot = mFdp.ConsumeIntegral<int32_t>(); - uint32_t maxBuffers = mFdp.ConsumeIntegral<uint32_t>(); - producer->requestBuffer(slot, &buffer); - producer->setMaxDequeuedBufferCount(maxBuffers); - producer->setAsyncMode(mFdp.ConsumeBool() /*async*/); - - android::IGraphicBufferProducer::QueueBufferInput input; - producer->attachBuffer(&slot, buffer); - producer->queueBuffer(slot, input, &output); - - int32_t format = mFdp.ConsumeIntegral<int32_t>(); - uint32_t width = mFdp.ConsumeIntegral<uint32_t>(); - uint32_t height = mFdp.ConsumeIntegral<uint32_t>(); - uint64_t usage = mFdp.ConsumeIntegral<uint64_t>(); - uint64_t outBufferAge; - FrameEventHistoryDelta outTimestamps; - sp<android::Fence> fence; - producer->dequeueBuffer(&slot, &fence, width, height, format, usage, &outBufferAge, - &outTimestamps); - producer->detachBuffer(slot); - producer->detachNextBuffer(&buffer, &fence); - producer->cancelBuffer(slot, fence); - - invokeQuery(producer); - - ManageResourceHandle handle(&mFdp); - producer->setSidebandStream(handle.getStream()); - - producer->allocateBuffers(width, height, format, usage); - producer->allowAllocation(mFdp.ConsumeBool() /*allow*/); - producer->setSharedBufferMode(mFdp.ConsumeBool() /*sharedBufferMode*/); - producer->setAutoRefresh(mFdp.ConsumeBool() /*autoRefresh*/); - producer->setLegacyBufferDrop(mFdp.ConsumeBool() /*drop*/); - producer->setAutoPrerotation(mFdp.ConsumeBool() /*autoPrerotation*/); - - producer->setGenerationNumber(mFdp.ConsumeIntegral<uint32_t>()); - producer->setDequeueTimeout(mFdp.ConsumeIntegral<uint32_t>()); - producer->disconnect(api); -} - -void BufferQueueFuzzer::invokeAcquireBuffer(sp<BufferQueueConsumer> consumer) { - BufferItem item; - consumer->acquireBuffer(&item, mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint64_t>()); -} - -void BufferQueueFuzzer::invokeOccupancyTracker(sp<BufferQueueConsumer> consumer) { - String8 outResult; - String8 prefix((mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str()); - consumer->dumpState(prefix, &outResult); - - std::vector<OccupancyTracker::Segment> outHistory; - consumer->getOccupancyHistory(mFdp.ConsumeBool() /*forceFlush*/, &outHistory); -} - -void BufferQueueFuzzer::invokeBufferQueueConsumer() { - sp<BufferQueueCore> core(new BufferQueueCore()); - sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core)); - sp<android::IConsumerListener> listener; - consumer->consumerConnect(listener, mFdp.ConsumeBool() /*controlledByApp*/); - invokeAcquireBuffer(consumer); - - int32_t slot = mFdp.ConsumeIntegral<int32_t>(); - sp<GraphicBuffer> buffer = - new GraphicBuffer(mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint64_t>()); - consumer->attachBuffer(&slot, buffer); - consumer->detachBuffer(slot); - - consumer->setDefaultBufferSize(mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint32_t>()); - consumer->setMaxBufferCount(mFdp.ConsumeIntegral<int32_t>()); - consumer->setMaxAcquiredBufferCount(mFdp.ConsumeIntegral<int32_t>()); - - String8 name((mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str()); - consumer->setConsumerName(name); - consumer->setDefaultBufferFormat(mFdp.ConsumeIntegral<int32_t>()); - android_dataspace dataspace = - static_cast<android_dataspace>(mFdp.PickValueInArray(kDataspaces)); - consumer->setDefaultBufferDataSpace(dataspace); - - consumer->setTransformHint(mFdp.ConsumeIntegral<uint32_t>()); - consumer->setConsumerUsageBits(mFdp.ConsumeIntegral<uint64_t>()); - consumer->setConsumerIsProtected(mFdp.ConsumeBool() /*isProtected*/); - invokeOccupancyTracker(consumer); - - sp<Fence> releaseFence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING)); - consumer->releaseBuffer(mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<uint64_t>(), - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence); - consumer->consumerDisconnect(); -} - -void BufferQueueFuzzer::invokeTypes() { - HStatus hStatus; - int32_t status = mFdp.PickValueInArray(kError); - bool bufferNeedsReallocation = mFdp.ConsumeBool(); - bool releaseAllBuffers = mFdp.ConsumeBool(); - b2h(status, &hStatus, &bufferNeedsReallocation, &releaseAllBuffers); - h2b(hStatus, &status); - - HConnectionType type; - int32_t apiConnection = mFdp.PickValueInArray(kAPIConnection); - b2h(apiConnection, &type); - h2b(type, &apiConnection); -} - -void BufferQueueFuzzer::invokeH2BGraphicBufferV1() { - sp<V1_0::utils::H2BGraphicBufferProducer> producer( - new V1_0::utils::H2BGraphicBufferProducer(new FakeGraphicBufferProducerV1())); - const sp<android::IProducerListener> listener; - android::IGraphicBufferProducer::QueueBufferOutput output; - uint32_t api = mFdp.ConsumeIntegral<uint32_t>(); - producer->connect(listener, api, mFdp.ConsumeBool() /*producerControlledByApp*/, &output); - - sp<GraphicBuffer> buffer; - int32_t slot = mFdp.ConsumeIntegral<int32_t>(); - producer->requestBuffer(slot, &buffer); - producer->setMaxDequeuedBufferCount(mFdp.ConsumeIntegral<int32_t>()); - producer->setAsyncMode(mFdp.ConsumeBool()); - - android::IGraphicBufferProducer::QueueBufferInput input; - input.fence = new Fence(memfd_create("ffd", MFD_ALLOW_SEALING)); - producer->attachBuffer(&slot, buffer); - producer->queueBuffer(slot, input, &output); - - int32_t format = mFdp.ConsumeIntegral<int32_t>(); - uint32_t width = mFdp.ConsumeIntegral<uint32_t>(); - uint32_t height = mFdp.ConsumeIntegral<uint32_t>(); - uint64_t usage = mFdp.ConsumeIntegral<uint64_t>(); - uint64_t outBufferAge; - FrameEventHistoryDelta outTimestamps; - sp<android::Fence> fence; - producer->dequeueBuffer(&slot, &fence, width, height, format, usage, &outBufferAge, - &outTimestamps); - producer->detachBuffer(slot); - producer->cancelBuffer(slot, fence); - - invokeQuery(producer); - - ManageResourceHandle handle(&mFdp); - producer->setSidebandStream(handle.getStream()); - - producer->allocateBuffers(width, height, format, usage); - producer->allowAllocation(mFdp.ConsumeBool() /*allow*/); - producer->setSharedBufferMode(mFdp.ConsumeBool() /*sharedBufferMode*/); - producer->setAutoRefresh(mFdp.ConsumeBool() /*autoRefresh*/); - - producer->setGenerationNumber(mFdp.ConsumeIntegral<uint32_t>()); - producer->setDequeueTimeout(mFdp.ConsumeIntegral<uint32_t>()); - producer->disconnect(api); -} - -void BufferQueueFuzzer::invokeH2BGraphicBufferV2() { - sp<V2_0::utils::H2BGraphicBufferProducer> producer( - new V2_0::utils::H2BGraphicBufferProducer(new FakeGraphicBufferProducerV2())); - const sp<android::IProducerListener> listener; - android::IGraphicBufferProducer::QueueBufferOutput output; - uint32_t api = mFdp.ConsumeIntegral<uint32_t>(); - producer->connect(listener, api, mFdp.ConsumeBool() /*producerControlledByApp*/, &output); - - sp<GraphicBuffer> buffer; - int32_t slot = mFdp.ConsumeIntegral<int32_t>(); - producer->requestBuffer(slot, &buffer); - producer->setMaxDequeuedBufferCount(mFdp.ConsumeIntegral<uint32_t>()); - producer->setAsyncMode(mFdp.ConsumeBool()); - - android::IGraphicBufferProducer::QueueBufferInput input; - input.fence = new Fence(memfd_create("ffd", MFD_ALLOW_SEALING)); - producer->attachBuffer(&slot, buffer); - producer->queueBuffer(slot, input, &output); - - int32_t format = mFdp.ConsumeIntegral<int32_t>(); - uint32_t width = mFdp.ConsumeIntegral<uint32_t>(); - uint32_t height = mFdp.ConsumeIntegral<uint32_t>(); - uint64_t usage = mFdp.ConsumeIntegral<uint64_t>(); - uint64_t outBufferAge; - FrameEventHistoryDelta outTimestamps; - sp<android::Fence> fence; - producer->dequeueBuffer(&slot, &fence, width, height, format, usage, &outBufferAge, - &outTimestamps); - producer->detachBuffer(slot); - producer->cancelBuffer(slot, fence); - - invokeQuery(producer); - - ManageResourceHandle handle(&mFdp); - producer->setSidebandStream(handle.getStream()); - - producer->allocateBuffers(width, height, format, usage); - producer->allowAllocation(mFdp.ConsumeBool() /*allow*/); - producer->setSharedBufferMode(mFdp.ConsumeBool() /*sharedBufferMode*/); - producer->setAutoRefresh(mFdp.ConsumeBool() /*autoRefresh*/); - - producer->setGenerationNumber(mFdp.ConsumeIntegral<uint32_t>()); - producer->setDequeueTimeout(mFdp.ConsumeIntegral<uint32_t>()); - producer->disconnect(api); -} - -void BufferQueueFuzzer::process() { - invokeBlastBufferQueue(); - invokeH2BGraphicBufferV1(); - invokeH2BGraphicBufferV2(); - invokeTypes(); - invokeBufferQueueConsumer(); - invokeBufferQueueProducer(); -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - BufferQueueFuzzer bufferQueueFuzzer(data, size); - bufferQueueFuzzer.process(); - return 0; -} diff --git a/libs/gui/fuzzer/libgui_consumer_fuzzer.cpp b/libs/gui/fuzzer/libgui_consumer_fuzzer.cpp deleted file mode 100644 index 24a046d3a9..0000000000 --- a/libs/gui/fuzzer/libgui_consumer_fuzzer.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 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. - */ -#include <gui/BufferQueueConsumer.h> -#include <gui/BufferQueueCore.h> -#include <gui/BufferQueueProducer.h> -#include <gui/GLConsumer.h> -#include <libgui_fuzzer_utils.h> - -using namespace android; - -constexpr int32_t kMinBuffer = 0; -constexpr int32_t kMaxBuffer = 100000; - -class ConsumerFuzzer { -public: - ConsumerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){}; - void process(); - -private: - FuzzedDataProvider mFdp; -}; - -void ConsumerFuzzer::process() { - sp<BufferQueueCore> core(new BufferQueueCore()); - sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); - - uint64_t maxBuffers = mFdp.ConsumeIntegralInRange<uint64_t>(kMinBuffer, kMaxBuffer); - sp<CpuConsumer> cpu( - new CpuConsumer(consumer, maxBuffers, mFdp.ConsumeBool() /*controlledByApp*/)); - CpuConsumer::LockedBuffer lockBuffer; - cpu->lockNextBuffer(&lockBuffer); - cpu->unlockBuffer(lockBuffer); - cpu->abandon(); - - uint32_t tex = mFdp.ConsumeIntegral<uint32_t>(); - sp<GLConsumer> glComsumer(new GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, - mFdp.ConsumeBool() /*useFenceSync*/, - mFdp.ConsumeBool() /*isControlledByApp*/)); - sp<Fence> releaseFence = new Fence(memfd_create("rfd", MFD_ALLOW_SEALING)); - glComsumer->setReleaseFence(releaseFence); - glComsumer->updateTexImage(); - glComsumer->releaseTexImage(); - - sp<GraphicBuffer> buffer = - new GraphicBuffer(mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint64_t>()); - float mtx[16]; - glComsumer->getTransformMatrix(mtx); - glComsumer->computeTransformMatrix(mtx, buffer, getRect(&mFdp), - mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeBool() /*filtering*/); - glComsumer->scaleDownCrop(getRect(&mFdp), mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint32_t>()); - - glComsumer->setDefaultBufferSize(mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint32_t>()); - glComsumer->setFilteringEnabled(mFdp.ConsumeBool() /*enabled*/); - - glComsumer->setConsumerUsageBits(mFdp.ConsumeIntegral<uint64_t>()); - glComsumer->attachToContext(tex); - glComsumer->abandon(); -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - ConsumerFuzzer consumerFuzzer(data, size); - consumerFuzzer.process(); - return 0; -} diff --git a/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp b/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp deleted file mode 100644 index 0d2a52b576..0000000000 --- a/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 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. - */ - -#include <android/gui/ISurfaceComposer.h> - -#include <libgui_fuzzer_utils.h> - -using namespace android; - -constexpr gui::ISurfaceComposer::VsyncSource kVsyncSource[] = { - gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp, - gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger, -}; - -constexpr gui::ISurfaceComposer::EventRegistration kEventRegistration[] = { - gui::ISurfaceComposer::EventRegistration::modeChanged, - gui::ISurfaceComposer::EventRegistration::frameRateOverride, -}; - -constexpr uint32_t kDisplayEvent[] = { - DisplayEventReceiver::DISPLAY_EVENT_NULL, - DisplayEventReceiver::DISPLAY_EVENT_VSYNC, - DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, - DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, - DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE, - DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH, -}; - -constexpr int32_t kEvents[] = { - Looper::EVENT_INPUT, Looper::EVENT_OUTPUT, Looper::EVENT_ERROR, - Looper::EVENT_HANGUP, Looper::EVENT_INVALID, -}; - -DisplayEventReceiver::Event buildDisplayEvent(FuzzedDataProvider* fdp, uint32_t type, - DisplayEventReceiver::Event event) { - switch (type) { - case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: { - event.vsync.count = fdp->ConsumeIntegral<uint32_t>(); - event.vsync.vsyncData.frameInterval = fdp->ConsumeIntegral<uint64_t>(); - event.vsync.vsyncData.preferredFrameTimelineIndex = fdp->ConsumeIntegral<uint32_t>(); - for (size_t idx = 0; idx < gui::VsyncEventData::kFrameTimelinesCapacity; ++idx) { - event.vsync.vsyncData.frameTimelines[idx].vsyncId = fdp->ConsumeIntegral<int64_t>(); - event.vsync.vsyncData.frameTimelines[idx].deadlineTimestamp = - fdp->ConsumeIntegral<uint64_t>(); - event.vsync.vsyncData.frameTimelines[idx].expectedPresentationTime = - fdp->ConsumeIntegral<uint64_t>(); - } - break; - - } - case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: { - event.hotplug = - DisplayEventReceiver::Event::Hotplug{fdp->ConsumeBool() /*connected*/, - fdp->ConsumeIntegral< - int32_t>() /*connectionError*/}; - break; - } - case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: { - event.modeChange = - DisplayEventReceiver::Event::ModeChange{fdp->ConsumeIntegral<int32_t>(), - fdp->ConsumeIntegral<int64_t>()}; - break; - } - case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE: - case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH: { - event.frameRateOverride = - DisplayEventReceiver::Event::FrameRateOverride{fdp->ConsumeIntegral<uint32_t>(), - fdp->ConsumeFloatingPoint< - float>()}; - break; - } - } - return event; -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp(data, size); - sp<Looper> looper; - sp<FakeDisplayEventDispatcher> dispatcher( - new FakeDisplayEventDispatcher(looper, fdp.PickValueInArray(kVsyncSource), - fdp.PickValueInArray(kEventRegistration))); - - dispatcher->initialize(); - DisplayEventReceiver::Event event; - uint32_t type = fdp.PickValueInArray(kDisplayEvent); - PhysicalDisplayId displayId; - event.header = - DisplayEventReceiver::Event::Header{type, displayId, fdp.ConsumeIntegral<int64_t>()}; - event = buildDisplayEvent(&fdp, type, event); - - dispatcher->injectEvent(event); - dispatcher->handleEvent(0, fdp.PickValueInArray(kEvents), nullptr); - return 0; -} diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h deleted file mode 100644 index 2bdbd43233..0000000000 --- a/libs/gui/fuzzer/libgui_fuzzer_utils.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <android/gui/BnRegionSamplingListener.h> -#include <android/gui/BnSurfaceComposer.h> -#include <android/gui/BnSurfaceComposerClient.h> -#include <android/gui/IDisplayEventConnection.h> -#include <android/gui/ISurfaceComposerClient.h> -#include <fuzzer/FuzzedDataProvider.h> -#include <gmock/gmock.h> -#include <gui/BLASTBufferQueue.h> -#include <gui/DisplayEventDispatcher.h> -#include <gui/IGraphicBufferProducer.h> -#include <gui/LayerDebugInfo.h> -#include <gui/LayerState.h> -#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h> -#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h> -#include <ui/fuzzer/FuzzableDataspaces.h> - -namespace android { - -constexpr uint32_t kOrientation[] = { - ui::Transform::ROT_0, ui::Transform::FLIP_H, ui::Transform::FLIP_V, - ui::Transform::ROT_90, ui::Transform::ROT_180, ui::Transform::ROT_270, -}; - -Rect getRect(FuzzedDataProvider* fdp) { - const int32_t left = fdp->ConsumeIntegral<int32_t>(); - const int32_t top = fdp->ConsumeIntegral<int32_t>(); - const int32_t right = fdp->ConsumeIntegral<int32_t>(); - const int32_t bottom = fdp->ConsumeIntegral<int32_t>(); - return Rect(left, top, right, bottom); -} - -gui::DisplayBrightness getBrightness(FuzzedDataProvider* fdp) { - static constexpr float kMinBrightness = 0; - static constexpr float kMaxBrightness = 1; - gui::DisplayBrightness brightness; - brightness.sdrWhitePoint = - fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness); - brightness.sdrWhitePointNits = - fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness); - brightness.displayBrightness = - fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness); - brightness.displayBrightnessNits = - fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness); - return brightness; -} - -class FakeBnSurfaceComposer : public gui::BnSurfaceComposer { -public: - MOCK_METHOD(binder::Status, bootFinished, (), (override)); - MOCK_METHOD(binder::Status, createDisplayEventConnection, - (gui::ISurfaceComposer::VsyncSource, gui::ISurfaceComposer::EventRegistration, - const sp<IBinder>& /*layerHandle*/, sp<gui::IDisplayEventConnection>*), - (override)); - MOCK_METHOD(binder::Status, createConnection, (sp<gui::ISurfaceComposerClient>*), (override)); - MOCK_METHOD(binder::Status, createDisplay, (const std::string&, bool, float, sp<IBinder>*), - (override)); - MOCK_METHOD(binder::Status, destroyDisplay, (const sp<IBinder>&), (override)); - MOCK_METHOD(binder::Status, getPhysicalDisplayIds, (std::vector<int64_t>*), (override)); - MOCK_METHOD(binder::Status, getPhysicalDisplayToken, (int64_t, sp<IBinder>*), (override)); - MOCK_METHOD(binder::Status, setPowerMode, (const sp<IBinder>&, int), (override)); - MOCK_METHOD(binder::Status, getSupportedFrameTimestamps, (std::vector<FrameEvent>*), - (override)); - MOCK_METHOD(binder::Status, getDisplayStats, (const sp<IBinder>&, gui::DisplayStatInfo*), - (override)); - MOCK_METHOD(binder::Status, getDisplayState, (const sp<IBinder>&, gui::DisplayState*), - (override)); - MOCK_METHOD(binder::Status, getStaticDisplayInfo, (int64_t, gui::StaticDisplayInfo*), - (override)); - MOCK_METHOD(binder::Status, getDynamicDisplayInfoFromId, (int64_t, gui::DynamicDisplayInfo*), - (override)); - MOCK_METHOD(binder::Status, getDynamicDisplayInfoFromToken, - (const sp<IBinder>&, gui::DynamicDisplayInfo*), (override)); - MOCK_METHOD(binder::Status, getDisplayNativePrimaries, - (const sp<IBinder>&, gui::DisplayPrimaries*), (override)); - MOCK_METHOD(binder::Status, setActiveColorMode, (const sp<IBinder>&, int), (override)); - MOCK_METHOD(binder::Status, setBootDisplayMode, (const sp<IBinder>&, int), (override)); - MOCK_METHOD(binder::Status, clearBootDisplayMode, (const sp<IBinder>&), (override)); - MOCK_METHOD(binder::Status, getBootDisplayModeSupport, (bool*), (override)); - MOCK_METHOD(binder::Status, getHdrConversionCapabilities, - (std::vector<gui::HdrConversionCapability>*), (override)); - MOCK_METHOD(binder::Status, setHdrConversionStrategy, - (const gui::HdrConversionStrategy&, int32_t*), (override)); - MOCK_METHOD(binder::Status, getHdrOutputConversionSupport, (bool*), (override)); - MOCK_METHOD(binder::Status, setAutoLowLatencyMode, (const sp<IBinder>&, bool), (override)); - MOCK_METHOD(binder::Status, setGameContentType, (const sp<IBinder>&, bool), (override)); - MOCK_METHOD(binder::Status, captureDisplay, - (const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&), (override)); - MOCK_METHOD(binder::Status, captureDisplayById, - (int64_t, const gui::CaptureArgs&, const sp<IScreenCaptureListener>&), (override)); - MOCK_METHOD(binder::Status, captureLayers, - (const LayerCaptureArgs&, const sp<IScreenCaptureListener>&), (override)); - MOCK_METHOD(binder::Status, captureLayersSync, - (const LayerCaptureArgs&, gui::ScreenCaptureResults*), (override)); - MOCK_METHOD(binder::Status, clearAnimationFrameStats, (), (override)); - MOCK_METHOD(binder::Status, getAnimationFrameStats, (gui::FrameStats*), (override)); - MOCK_METHOD(binder::Status, overrideHdrTypes, (const sp<IBinder>&, const std::vector<int32_t>&), - (override)); - MOCK_METHOD(binder::Status, onPullAtom, (int32_t, gui::PullAtomData*), (override)); - MOCK_METHOD(binder::Status, getLayerDebugInfo, (std::vector<gui::LayerDebugInfo>*), (override)); - MOCK_METHOD(binder::Status, getCompositionPreference, (gui::CompositionPreference*), - (override)); - MOCK_METHOD(binder::Status, getDisplayedContentSamplingAttributes, - (const sp<IBinder>&, gui::ContentSamplingAttributes*), (override)); - MOCK_METHOD(binder::Status, setDisplayContentSamplingEnabled, - (const sp<IBinder>&, bool, int8_t, int64_t), (override)); - MOCK_METHOD(binder::Status, getDisplayedContentSample, - (const sp<IBinder>&, int64_t, int64_t, gui::DisplayedFrameStats*), (override)); - MOCK_METHOD(binder::Status, getProtectedContentSupport, (bool*), (override)); - MOCK_METHOD(binder::Status, isWideColorDisplay, (const sp<IBinder>&, bool*), (override)); - MOCK_METHOD(binder::Status, addRegionSamplingListener, - (const gui::ARect&, const sp<IBinder>&, const sp<gui::IRegionSamplingListener>&), - (override)); - MOCK_METHOD(binder::Status, removeRegionSamplingListener, - (const sp<gui::IRegionSamplingListener>&), (override)); - MOCK_METHOD(binder::Status, addFpsListener, (int32_t, const sp<gui::IFpsListener>&), - (override)); - MOCK_METHOD(binder::Status, removeFpsListener, (const sp<gui::IFpsListener>&), (override)); - MOCK_METHOD(binder::Status, addTunnelModeEnabledListener, - (const sp<gui::ITunnelModeEnabledListener>&), (override)); - MOCK_METHOD(binder::Status, removeTunnelModeEnabledListener, - (const sp<gui::ITunnelModeEnabledListener>&), (override)); - MOCK_METHOD(binder::Status, setDesiredDisplayModeSpecs, - (const sp<IBinder>&, const gui::DisplayModeSpecs&), (override)); - MOCK_METHOD(binder::Status, getDesiredDisplayModeSpecs, - (const sp<IBinder>&, gui::DisplayModeSpecs*), (override)); - MOCK_METHOD(binder::Status, getDisplayBrightnessSupport, (const sp<IBinder>&, bool*), - (override)); - MOCK_METHOD(binder::Status, setDisplayBrightness, - (const sp<IBinder>&, const gui::DisplayBrightness&), (override)); - MOCK_METHOD(binder::Status, addHdrLayerInfoListener, - (const sp<IBinder>&, const sp<gui::IHdrLayerInfoListener>&), (override)); - MOCK_METHOD(binder::Status, removeHdrLayerInfoListener, - (const sp<IBinder>&, const sp<gui::IHdrLayerInfoListener>&), (override)); - MOCK_METHOD(binder::Status, notifyPowerBoost, (int), (override)); - MOCK_METHOD(binder::Status, setGlobalShadowSettings, - (const gui::Color&, const gui::Color&, float, float, float), (override)); - MOCK_METHOD(binder::Status, getDisplayDecorationSupport, - (const sp<IBinder>&, std::optional<gui::DisplayDecorationSupport>*), (override)); - MOCK_METHOD(binder::Status, setGameModeFrameRateOverride, (int32_t, float), (override)); - MOCK_METHOD(binder::Status, setGameDefaultFrameRateOverride, (int32_t, float), (override)); - MOCK_METHOD(binder::Status, enableRefreshRateOverlay, (bool), (override)); - MOCK_METHOD(binder::Status, setDebugFlash, (int), (override)); - MOCK_METHOD(binder::Status, scheduleComposite, (), (override)); - MOCK_METHOD(binder::Status, scheduleCommit, (), (override)); - MOCK_METHOD(binder::Status, forceClientComposition, (bool), (override)); - MOCK_METHOD(binder::Status, updateSmallAreaDetection, - (const std::vector<int32_t>&, const std::vector<float>&), (override)); - MOCK_METHOD(binder::Status, setSmallAreaDetectionThreshold, (int32_t, float), (override)); - MOCK_METHOD(binder::Status, getGpuContextPriority, (int32_t*), (override)); - MOCK_METHOD(binder::Status, getMaxAcquiredBufferCount, (int32_t*), (override)); - MOCK_METHOD(binder::Status, addWindowInfosListener, - (const sp<gui::IWindowInfosListener>&, gui::WindowInfosListenerInfo*), (override)); - MOCK_METHOD(binder::Status, removeWindowInfosListener, (const sp<gui::IWindowInfosListener>&), - (override)); - MOCK_METHOD(binder::Status, getOverlaySupport, (gui::OverlayProperties*), (override)); - MOCK_METHOD(binder::Status, getStalledTransactionInfo, - (int32_t, std::optional<gui::StalledTransactionInfo>*), (override)); - MOCK_METHOD(binder::Status, getSchedulingPolicy, (gui::SchedulingPolicy*), (override)); -}; - -class FakeBnSurfaceComposerClient : public gui::BnSurfaceComposerClient { -public: - MOCK_METHOD(binder::Status, createSurface, - (const std::string& name, int32_t flags, const sp<IBinder>& parent, - const gui::LayerMetadata& metadata, gui::CreateSurfaceResult* outResult), - (override)); - - MOCK_METHOD(binder::Status, clearLayerFrameStats, (const sp<IBinder>& handle), (override)); - - MOCK_METHOD(binder::Status, getLayerFrameStats, - (const sp<IBinder>& handle, gui::FrameStats* outStats), (override)); - - MOCK_METHOD(binder::Status, mirrorSurface, - (const sp<IBinder>& mirrorFromHandle, gui::CreateSurfaceResult* outResult), - (override)); - - MOCK_METHOD(binder::Status, mirrorDisplay, - (int64_t displayId, gui::CreateSurfaceResult* outResult), (override)); - - MOCK_METHOD(binder::Status, getSchedulingPolicy, (gui::SchedulingPolicy*), (override)); -}; - -class FakeDisplayEventDispatcher : public DisplayEventDispatcher { -public: - FakeDisplayEventDispatcher(const sp<Looper>& looper, - gui::ISurfaceComposer::VsyncSource vsyncSource, - gui::ISurfaceComposer::EventRegistration eventRegistration) - : DisplayEventDispatcher(looper, vsyncSource, eventRegistration){}; - - MOCK_METHOD4(dispatchVsync, void(nsecs_t, PhysicalDisplayId, uint32_t, VsyncEventData)); - MOCK_METHOD3(dispatchHotplug, void(nsecs_t, PhysicalDisplayId, bool)); - MOCK_METHOD2(dispatchHotplugConnectionError, void(nsecs_t, int32_t)); - MOCK_METHOD4(dispatchModeChanged, void(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t)); - MOCK_METHOD2(dispatchNullEvent, void(nsecs_t, PhysicalDisplayId)); - MOCK_METHOD3(dispatchFrameRateOverrides, - void(nsecs_t, PhysicalDisplayId, std::vector<FrameRateOverride>)); - MOCK_METHOD3(dispatchHdcpLevelsChanged, void(PhysicalDisplayId, int32_t, int32_t)); -}; - -} // namespace android - -namespace android::hardware { - -namespace graphics::bufferqueue::V1_0::utils { - -class FakeGraphicBufferProducerV1 : public HGraphicBufferProducer { -public: - FakeGraphicBufferProducerV1() { - ON_CALL(*this, setMaxDequeuedBufferCount).WillByDefault([]() { return 0; }); - ON_CALL(*this, setAsyncMode).WillByDefault([]() { return 0; }); - ON_CALL(*this, detachBuffer).WillByDefault([]() { return 0; }); - ON_CALL(*this, cancelBuffer).WillByDefault([]() { return 0; }); - ON_CALL(*this, disconnect).WillByDefault([]() { return 0; }); - ON_CALL(*this, setSidebandStream).WillByDefault([]() { return 0; }); - ON_CALL(*this, allowAllocation).WillByDefault([]() { return 0; }); - ON_CALL(*this, setGenerationNumber).WillByDefault([]() { return 0; }); - ON_CALL(*this, setSharedBufferMode).WillByDefault([]() { return 0; }); - ON_CALL(*this, setAutoRefresh).WillByDefault([]() { return 0; }); - ON_CALL(*this, setDequeueTimeout).WillByDefault([]() { return 0; }); - ON_CALL(*this, setLegacyBufferDrop).WillByDefault([]() { return 0; }); - }; - MOCK_METHOD2(requestBuffer, Return<void>(int, requestBuffer_cb)); - MOCK_METHOD1(setMaxDequeuedBufferCount, Return<int32_t>(int32_t)); - MOCK_METHOD1(setAsyncMode, Return<int32_t>(bool)); - MOCK_METHOD6(dequeueBuffer, - Return<void>(uint32_t, uint32_t, graphics::common::V1_0::PixelFormat, uint32_t, - bool, dequeueBuffer_cb)); - MOCK_METHOD1(detachBuffer, Return<int32_t>(int)); - MOCK_METHOD1(detachNextBuffer, Return<void>(detachNextBuffer_cb)); - MOCK_METHOD2(attachBuffer, Return<void>(const media::V1_0::AnwBuffer&, attachBuffer_cb)); - MOCK_METHOD3( - queueBuffer, - Return<void>( - int, - const graphics::bufferqueue::V1_0::IGraphicBufferProducer::QueueBufferInput&, - queueBuffer_cb)); - MOCK_METHOD2(cancelBuffer, Return<int32_t>(int, const hidl_handle&)); - MOCK_METHOD2(query, Return<void>(int32_t, query_cb)); - MOCK_METHOD4(connect, - Return<void>(const sp<graphics::bufferqueue::V1_0::IProducerListener>&, int32_t, - bool, connect_cb)); - MOCK_METHOD2(disconnect, - Return<int32_t>( - int, graphics::bufferqueue::V1_0::IGraphicBufferProducer::DisconnectMode)); - MOCK_METHOD1(setSidebandStream, Return<int32_t>(const hidl_handle&)); - MOCK_METHOD4(allocateBuffers, - Return<void>(uint32_t, uint32_t, graphics::common::V1_0::PixelFormat, uint32_t)); - MOCK_METHOD1(allowAllocation, Return<int32_t>(bool)); - MOCK_METHOD1(setGenerationNumber, Return<int32_t>(uint32_t)); - MOCK_METHOD1(getConsumerName, Return<void>(getConsumerName_cb)); - MOCK_METHOD1(setSharedBufferMode, Return<int32_t>(bool)); - MOCK_METHOD1(setAutoRefresh, Return<int32_t>(bool)); - MOCK_METHOD1(setDequeueTimeout, Return<int32_t>(nsecs_t)); - MOCK_METHOD1(setLegacyBufferDrop, Return<int32_t>(bool)); - MOCK_METHOD1(getLastQueuedBuffer, Return<void>(getLastQueuedBuffer_cb)); - MOCK_METHOD1(getFrameTimestamps, Return<void>(getFrameTimestamps_cb)); - MOCK_METHOD1(getUniqueId, Return<void>(getUniqueId_cb)); -}; - -}; // namespace graphics::bufferqueue::V1_0::utils - -namespace graphics::bufferqueue::V2_0::utils { - -class FakeGraphicBufferProducerV2 : public HGraphicBufferProducer { -public: - FakeGraphicBufferProducerV2() { - ON_CALL(*this, setMaxDequeuedBufferCount).WillByDefault([]() { return Status::OK; }); - ON_CALL(*this, setAsyncMode).WillByDefault([]() { return Status::OK; }); - ON_CALL(*this, detachBuffer).WillByDefault([]() { return Status::OK; }); - ON_CALL(*this, cancelBuffer).WillByDefault([]() { return Status::OK; }); - ON_CALL(*this, disconnect).WillByDefault([]() { return Status::OK; }); - ON_CALL(*this, allocateBuffers).WillByDefault([]() { return Status::OK; }); - ON_CALL(*this, allowAllocation).WillByDefault([]() { return Status::OK; }); - ON_CALL(*this, setGenerationNumber).WillByDefault([]() { return Status::OK; }); - ON_CALL(*this, setDequeueTimeout).WillByDefault([]() { return Status::OK; }); - ON_CALL(*this, getUniqueId).WillByDefault([]() { return 0; }); - }; - MOCK_METHOD2(requestBuffer, Return<void>(int, requestBuffer_cb)); - MOCK_METHOD1(setMaxDequeuedBufferCount, Return<graphics::bufferqueue::V2_0::Status>(int)); - MOCK_METHOD1(setAsyncMode, Return<graphics::bufferqueue::V2_0::Status>(bool)); - MOCK_METHOD2( - dequeueBuffer, - Return<void>( - const graphics::bufferqueue::V2_0::IGraphicBufferProducer::DequeueBufferInput&, - dequeueBuffer_cb)); - MOCK_METHOD1(detachBuffer, Return<graphics::bufferqueue::V2_0::Status>(int)); - MOCK_METHOD1(detachNextBuffer, Return<void>(detachNextBuffer_cb)); - MOCK_METHOD3(attachBuffer, - Return<void>(const graphics::common::V1_2::HardwareBuffer&, uint32_t, - attachBuffer_cb)); - MOCK_METHOD3( - queueBuffer, - Return<void>( - int, - const graphics::bufferqueue::V2_0::IGraphicBufferProducer::QueueBufferInput&, - queueBuffer_cb)); - MOCK_METHOD2(cancelBuffer, - Return<graphics::bufferqueue::V2_0::Status>(int, const hidl_handle&)); - MOCK_METHOD2(query, Return<void>(int32_t, query_cb)); - MOCK_METHOD4(connect, - Return<void>(const sp<graphics::bufferqueue::V2_0::IProducerListener>&, - graphics::bufferqueue::V2_0::ConnectionType, bool, connect_cb)); - MOCK_METHOD1(disconnect, - Return<graphics::bufferqueue::V2_0::Status>( - graphics::bufferqueue::V2_0::ConnectionType)); - MOCK_METHOD4(allocateBuffers, - Return<graphics::bufferqueue::V2_0::Status>(uint32_t, uint32_t, uint32_t, - uint64_t)); - MOCK_METHOD1(allowAllocation, Return<graphics::bufferqueue::V2_0::Status>(bool)); - MOCK_METHOD1(setGenerationNumber, Return<graphics::bufferqueue::V2_0::Status>(uint32_t)); - MOCK_METHOD1(getConsumerName, Return<void>(getConsumerName_cb)); - MOCK_METHOD1(setDequeueTimeout, Return<graphics::bufferqueue::V2_0::Status>(int64_t)); - MOCK_METHOD0(getUniqueId, Return<uint64_t>()); -}; - -}; // namespace graphics::bufferqueue::V2_0::utils -}; // namespace android::hardware diff --git a/libs/gui/fuzzer/libgui_parcelable_fuzzer.cpp b/libs/gui/fuzzer/libgui_parcelable_fuzzer.cpp deleted file mode 100644 index 9f0f6cac19..0000000000 --- a/libs/gui/fuzzer/libgui_parcelable_fuzzer.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 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. - */ -#include <gui/BufferQueueConsumer.h> -#include <gui/BufferQueueCore.h> -#include <gui/BufferQueueProducer.h> -#include <gui/LayerMetadata.h> -#include <gui/OccupancyTracker.h> -#include <gui/StreamSplitter.h> -#include <gui/Surface.h> -#include <gui/SurfaceControl.h> -#include <gui/view/Surface.h> -#include <libgui_fuzzer_utils.h> -#include "android/view/LayerMetadataKey.h" - -using namespace android; - -constexpr int32_t kMaxBytes = 256; -constexpr int32_t kMatrixSize = 4; -constexpr int32_t kLayerMetadataKeyCount = 8; - -constexpr uint32_t kMetadataKey[] = { - (uint32_t)view::LayerMetadataKey::METADATA_OWNER_UID, - (uint32_t)view::LayerMetadataKey::METADATA_WINDOW_TYPE, - (uint32_t)view::LayerMetadataKey::METADATA_TASK_ID, - (uint32_t)view::LayerMetadataKey::METADATA_MOUSE_CURSOR, - (uint32_t)view::LayerMetadataKey::METADATA_ACCESSIBILITY_ID, - (uint32_t)view::LayerMetadataKey::METADATA_OWNER_PID, - (uint32_t)view::LayerMetadataKey::METADATA_DEQUEUE_TIME, - (uint32_t)view::LayerMetadataKey::METADATA_GAME_MODE, -}; - -class ParcelableFuzzer { -public: - ParcelableFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){}; - void process(); - -private: - void invokeStreamSplitter(); - void invokeOccupancyTracker(); - void invokeLayerDebugInfo(); - void invokeLayerMetadata(); - void invokeViewSurface(); - - FuzzedDataProvider mFdp; -}; - -void ParcelableFuzzer::invokeViewSurface() { - view::Surface surface; - surface.name = String16((mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str()); - Parcel parcel; - surface.writeToParcel(&parcel); - parcel.setDataPosition(0); - surface.readFromParcel(&parcel); - bool nameAlreadyWritten = mFdp.ConsumeBool(); - surface.writeToParcel(&parcel, nameAlreadyWritten); - parcel.setDataPosition(0); - surface.readFromParcel(&parcel, mFdp.ConsumeBool()); -} - -void ParcelableFuzzer::invokeLayerMetadata() { - std::unordered_map<uint32_t, std::vector<uint8_t>> map; - for (size_t idx = 0; idx < kLayerMetadataKeyCount; ++idx) { - std::vector<uint8_t> data; - for (size_t idx1 = 0; idx1 < mFdp.ConsumeIntegral<uint32_t>(); ++idx1) { - data.push_back(mFdp.ConsumeIntegral<uint8_t>()); - } - map[kMetadataKey[idx]] = data; - } - LayerMetadata metadata(map); - uint32_t key = mFdp.PickValueInArray(kMetadataKey); - metadata.setInt32(key, mFdp.ConsumeIntegral<int32_t>()); - metadata.itemToString(key, (mFdp.ConsumeRandomLengthString(kMaxBytes)).c_str()); - - Parcel parcel; - metadata.writeToParcel(&parcel); - parcel.setDataPosition(0); - metadata.readFromParcel(&parcel); -} - -void ParcelableFuzzer::invokeLayerDebugInfo() { - gui::LayerDebugInfo info; - info.mName = mFdp.ConsumeRandomLengthString(kMaxBytes); - info.mParentName = mFdp.ConsumeRandomLengthString(kMaxBytes); - info.mType = mFdp.ConsumeRandomLengthString(kMaxBytes); - info.mLayerStack = mFdp.ConsumeIntegral<uint32_t>(); - info.mX = mFdp.ConsumeFloatingPoint<float>(); - info.mY = mFdp.ConsumeFloatingPoint<float>(); - info.mZ = mFdp.ConsumeIntegral<uint32_t>(); - info.mWidth = mFdp.ConsumeIntegral<int32_t>(); - info.mHeight = mFdp.ConsumeIntegral<int32_t>(); - info.mActiveBufferWidth = mFdp.ConsumeIntegral<int32_t>(); - info.mActiveBufferHeight = mFdp.ConsumeIntegral<int32_t>(); - info.mActiveBufferStride = mFdp.ConsumeIntegral<int32_t>(); - info.mActiveBufferFormat = mFdp.ConsumeIntegral<int32_t>(); - info.mNumQueuedFrames = mFdp.ConsumeIntegral<int32_t>(); - - info.mFlags = mFdp.ConsumeIntegral<uint32_t>(); - info.mPixelFormat = mFdp.ConsumeIntegral<int32_t>(); - info.mTransparentRegion = Region(getRect(&mFdp)); - info.mVisibleRegion = Region(getRect(&mFdp)); - info.mSurfaceDamageRegion = Region(getRect(&mFdp)); - info.mCrop = getRect(&mFdp); - info.mDataSpace = static_cast<android_dataspace>(mFdp.PickValueInArray(kDataspaces)); - info.mColor = half4(mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(), - mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>()); - for (size_t idx = 0; idx < kMatrixSize; ++idx) { - info.mMatrix[idx / 2][idx % 2] = mFdp.ConsumeFloatingPoint<float>(); - } - info.mIsOpaque = mFdp.ConsumeBool(); - info.mContentDirty = mFdp.ConsumeBool(); - info.mStretchEffect.width = mFdp.ConsumeFloatingPoint<float>(); - info.mStretchEffect.height = mFdp.ConsumeFloatingPoint<float>(); - info.mStretchEffect.vectorX = mFdp.ConsumeFloatingPoint<float>(); - info.mStretchEffect.vectorY = mFdp.ConsumeFloatingPoint<float>(); - info.mStretchEffect.maxAmountX = mFdp.ConsumeFloatingPoint<float>(); - info.mStretchEffect.maxAmountY = mFdp.ConsumeFloatingPoint<float>(); - info.mStretchEffect.mappedChildBounds = - FloatRect(mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(), - mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>()); - - Parcel parcel; - info.writeToParcel(&parcel); - parcel.setDataPosition(0); - info.readFromParcel(&parcel); -} - -void ParcelableFuzzer::invokeOccupancyTracker() { - nsecs_t totalTime = mFdp.ConsumeIntegral<uint32_t>(); - size_t numFrames = mFdp.ConsumeIntegral<size_t>(); - float occupancyAverage = mFdp.ConsumeFloatingPoint<float>(); - OccupancyTracker::Segment segment(totalTime, numFrames, occupancyAverage, - mFdp.ConsumeBool() /*usedThirdBuffer*/); - Parcel parcel; - segment.writeToParcel(&parcel); - parcel.setDataPosition(0); - segment.readFromParcel(&parcel); -} - -void ParcelableFuzzer::invokeStreamSplitter() { - sp<IGraphicBufferProducer> producer; - sp<IGraphicBufferConsumer> consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp<StreamSplitter> splitter; - StreamSplitter::createSplitter(consumer, &splitter); - splitter->addOutput(producer); - std::string name = mFdp.ConsumeRandomLengthString(kMaxBytes); - splitter->setName(String8(name.c_str())); -} - -void ParcelableFuzzer::process() { - invokeStreamSplitter(); - invokeOccupancyTracker(); - invokeLayerDebugInfo(); - invokeLayerMetadata(); - invokeViewSurface(); -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - ParcelableFuzzer libGuiFuzzer(data, size); - libGuiFuzzer.process(); - return 0; -} diff --git a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp deleted file mode 100644 index 4daa3be36f..0000000000 --- a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright 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. - */ -#include <aidl/android/hardware/power/Boost.h> -#include <fuzzbinder/libbinder_driver.h> -#include <gui/Surface.h> -#include <gui/SurfaceComposerClient.h> -#include <libgui_fuzzer_utils.h> -#include "android-base/stringprintf.h" - -using namespace android; - -constexpr int32_t kRandomStringMaxBytes = 256; - -constexpr ui::ColorMode kColormodes[] = {ui::ColorMode::NATIVE, - ui::ColorMode::STANDARD_BT601_625, - ui::ColorMode::STANDARD_BT601_625_UNADJUSTED, - ui::ColorMode::STANDARD_BT601_525, - ui::ColorMode::STANDARD_BT601_525_UNADJUSTED, - ui::ColorMode::STANDARD_BT709, - ui::ColorMode::DCI_P3, - ui::ColorMode::SRGB, - ui::ColorMode::ADOBE_RGB, - ui::ColorMode::DISPLAY_P3, - ui::ColorMode::BT2020, - ui::ColorMode::BT2100_PQ, - ui::ColorMode::BT2100_HLG, - ui::ColorMode::DISPLAY_BT2020}; - -constexpr aidl::android::hardware::power::Boost kBoost[] = { - aidl::android::hardware::power::Boost::INTERACTION, - aidl::android::hardware::power::Boost::DISPLAY_UPDATE_IMMINENT, - aidl::android::hardware::power::Boost::ML_ACC, - aidl::android::hardware::power::Boost::AUDIO_LAUNCH, - aidl::android::hardware::power::Boost::CAMERA_LAUNCH, - aidl::android::hardware::power::Boost::CAMERA_SHOT, -}; - -constexpr gui::TouchOcclusionMode kMode[] = { - gui::TouchOcclusionMode::BLOCK_UNTRUSTED, - gui::TouchOcclusionMode::USE_OPACITY, - gui::TouchOcclusionMode::ALLOW, -}; - -constexpr gui::WindowInfo::Flag kFlags[] = { - gui::WindowInfo::Flag::ALLOW_LOCK_WHILE_SCREEN_ON, - gui::WindowInfo::Flag::DIM_BEHIND, - gui::WindowInfo::Flag::BLUR_BEHIND, - gui::WindowInfo::Flag::NOT_FOCUSABLE, - gui::WindowInfo::Flag::NOT_TOUCHABLE, - gui::WindowInfo::Flag::NOT_TOUCH_MODAL, - gui::WindowInfo::Flag::TOUCHABLE_WHEN_WAKING, - gui::WindowInfo::Flag::KEEP_SCREEN_ON, - gui::WindowInfo::Flag::LAYOUT_IN_SCREEN, - gui::WindowInfo::Flag::LAYOUT_NO_LIMITS, - gui::WindowInfo::Flag::FULLSCREEN, - gui::WindowInfo::Flag::FORCE_NOT_FULLSCREEN, - gui::WindowInfo::Flag::DITHER, - gui::WindowInfo::Flag::SECURE, - gui::WindowInfo::Flag::SCALED, - gui::WindowInfo::Flag::IGNORE_CHEEK_PRESSES, - gui::WindowInfo::Flag::LAYOUT_INSET_DECOR, - gui::WindowInfo::Flag::ALT_FOCUSABLE_IM, - gui::WindowInfo::Flag::WATCH_OUTSIDE_TOUCH, - gui::WindowInfo::Flag::SHOW_WHEN_LOCKED, - gui::WindowInfo::Flag::SHOW_WALLPAPER, - gui::WindowInfo::Flag::TURN_SCREEN_ON, - gui::WindowInfo::Flag::DISMISS_KEYGUARD, - gui::WindowInfo::Flag::SPLIT_TOUCH, - gui::WindowInfo::Flag::HARDWARE_ACCELERATED, - gui::WindowInfo::Flag::LAYOUT_IN_OVERSCAN, - gui::WindowInfo::Flag::TRANSLUCENT_STATUS, - gui::WindowInfo::Flag::TRANSLUCENT_NAVIGATION, - gui::WindowInfo::Flag::LOCAL_FOCUS_MODE, - gui::WindowInfo::Flag::SLIPPERY, - gui::WindowInfo::Flag::LAYOUT_ATTACHED_IN_DECOR, - gui::WindowInfo::Flag::DRAWS_SYSTEM_BAR_BACKGROUNDS, -}; - -constexpr gui::WindowInfo::Type kType[] = { - gui::WindowInfo::Type::UNKNOWN, - gui::WindowInfo::Type::FIRST_APPLICATION_WINDOW, - gui::WindowInfo::Type::BASE_APPLICATION, - gui::WindowInfo::Type::APPLICATION, - gui::WindowInfo::Type::APPLICATION_STARTING, - gui::WindowInfo::Type::LAST_APPLICATION_WINDOW, - gui::WindowInfo::Type::FIRST_SUB_WINDOW, - gui::WindowInfo::Type::APPLICATION_PANEL, - gui::WindowInfo::Type::APPLICATION_MEDIA, - gui::WindowInfo::Type::APPLICATION_SUB_PANEL, - gui::WindowInfo::Type::APPLICATION_ATTACHED_DIALOG, - gui::WindowInfo::Type::APPLICATION_MEDIA_OVERLAY, -}; - -constexpr gui::WindowInfo::InputConfig kFeatures[] = { - gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL, - gui::WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, - gui::WindowInfo::InputConfig::DROP_INPUT, - gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, - gui::WindowInfo::InputConfig::SPY, - gui::WindowInfo::InputConfig::INTERCEPTS_STYLUS, -}; - -class SurfaceComposerClientFuzzer { -public: - SurfaceComposerClientFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){}; - void process(); - -private: - void invokeSurfaceComposerClient(); - void invokeSurfaceComposerClientBinder(); - void invokeSurfaceComposerTransaction(); - void getWindowInfo(gui::WindowInfo*); - sp<SurfaceControl> makeSurfaceControl(); - BlurRegion getBlurRegion(); - void fuzzOnPullAtom(); - gui::DisplayModeSpecs getDisplayModeSpecs(); - - FuzzedDataProvider mFdp; -}; - -gui::DisplayModeSpecs SurfaceComposerClientFuzzer::getDisplayModeSpecs() { - const auto getRefreshRateRange = [&] { - gui::DisplayModeSpecs::RefreshRateRanges::RefreshRateRange range; - range.min = mFdp.ConsumeFloatingPoint<float>(); - range.max = mFdp.ConsumeFloatingPoint<float>(); - return range; - }; - - const auto getRefreshRateRanges = [&] { - gui::DisplayModeSpecs::RefreshRateRanges ranges; - ranges.physical = getRefreshRateRange(); - ranges.render = getRefreshRateRange(); - return ranges; - }; - - String8 displayName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str()); - sp<IBinder> displayToken = - SurfaceComposerClient::createDisplay(displayName, mFdp.ConsumeBool() /*secure*/); - gui::DisplayModeSpecs specs; - specs.defaultMode = mFdp.ConsumeIntegral<int32_t>(); - specs.allowGroupSwitching = mFdp.ConsumeBool(); - specs.primaryRanges = getRefreshRateRanges(); - specs.appRequestRanges = getRefreshRateRanges(); - return specs; -} - -BlurRegion SurfaceComposerClientFuzzer::getBlurRegion() { - int32_t left = mFdp.ConsumeIntegral<int32_t>(); - int32_t right = mFdp.ConsumeIntegral<int32_t>(); - int32_t top = mFdp.ConsumeIntegral<int32_t>(); - int32_t bottom = mFdp.ConsumeIntegral<int32_t>(); - uint32_t blurRadius = mFdp.ConsumeIntegral<uint32_t>(); - float alpha = mFdp.ConsumeFloatingPoint<float>(); - float cornerRadiusTL = mFdp.ConsumeFloatingPoint<float>(); - float cornerRadiusTR = mFdp.ConsumeFloatingPoint<float>(); - float cornerRadiusBL = mFdp.ConsumeFloatingPoint<float>(); - float cornerRadiusBR = mFdp.ConsumeFloatingPoint<float>(); - return BlurRegion{blurRadius, cornerRadiusTL, cornerRadiusTR, cornerRadiusBL, - cornerRadiusBR, alpha, left, top, - right, bottom}; -} - -void SurfaceComposerClientFuzzer::getWindowInfo(gui::WindowInfo* windowInfo) { - windowInfo->id = mFdp.ConsumeIntegral<int32_t>(); - windowInfo->name = mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes); - windowInfo->layoutParamsFlags = mFdp.PickValueInArray(kFlags); - windowInfo->layoutParamsType = mFdp.PickValueInArray(kType); - windowInfo->frame = Rect(mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<int32_t>(), - mFdp.ConsumeIntegral<int32_t>(), mFdp.ConsumeIntegral<int32_t>()); - windowInfo->surfaceInset = mFdp.ConsumeIntegral<int32_t>(); - windowInfo->alpha = mFdp.ConsumeFloatingPointInRange<float>(0, 1); - ui::Transform transform(mFdp.PickValueInArray(kOrientation)); - windowInfo->transform = transform; - windowInfo->touchableRegion = Region(getRect(&mFdp)); - windowInfo->replaceTouchableRegionWithCrop = mFdp.ConsumeBool(); - windowInfo->touchOcclusionMode = mFdp.PickValueInArray(kMode); - windowInfo->ownerPid = gui::Pid{mFdp.ConsumeIntegral<pid_t>()}; - windowInfo->ownerUid = gui::Uid{mFdp.ConsumeIntegral<uid_t>()}; - windowInfo->packageName = mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes); - windowInfo->inputConfig = mFdp.PickValueInArray(kFeatures); -} - -sp<SurfaceControl> SurfaceComposerClientFuzzer::makeSurfaceControl() { - sp<IBinder> handle; - const sp<FakeBnSurfaceComposerClient> testClient(new FakeBnSurfaceComposerClient()); - sp<SurfaceComposerClient> client = new SurfaceComposerClient(testClient); - sp<BnGraphicBufferProducer> producer; - uint32_t width = mFdp.ConsumeIntegral<uint32_t>(); - uint32_t height = mFdp.ConsumeIntegral<uint32_t>(); - uint32_t transformHint = mFdp.ConsumeIntegral<uint32_t>(); - uint32_t flags = mFdp.ConsumeIntegral<uint32_t>(); - int32_t format = mFdp.ConsumeIntegral<int32_t>(); - int32_t layerId = mFdp.ConsumeIntegral<int32_t>(); - std::string layerName = base::StringPrintf("#%d", layerId); - return new SurfaceControl(client, handle, layerId, layerName, width, height, format, - transformHint, flags); -} - -void SurfaceComposerClientFuzzer::invokeSurfaceComposerTransaction() { - sp<SurfaceControl> surface = makeSurfaceControl(); - - SurfaceComposerClient::Transaction transaction; - int32_t layer = mFdp.ConsumeIntegral<int32_t>(); - transaction.setLayer(surface, layer); - - sp<SurfaceControl> relativeSurface = makeSurfaceControl(); - transaction.setRelativeLayer(surface, relativeSurface, layer); - - Region transparentRegion(getRect(&mFdp)); - transaction.setTransparentRegionHint(surface, transparentRegion); - transaction.setAlpha(surface, mFdp.ConsumeFloatingPoint<float>()); - - transaction.setCornerRadius(surface, mFdp.ConsumeFloatingPoint<float>()); - transaction.setBackgroundBlurRadius(surface, mFdp.ConsumeFloatingPoint<float>()); - std::vector<BlurRegion> regions; - uint32_t vectorSize = mFdp.ConsumeIntegralInRange<uint32_t>(0, 100); - regions.resize(vectorSize); - for (size_t idx = 0; idx < vectorSize; ++idx) { - regions.push_back(getBlurRegion()); - } - transaction.setBlurRegions(surface, regions); - - transaction.setLayerStack(surface, {mFdp.ConsumeIntegral<uint32_t>()}); - half3 color = {mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<uint32_t>(), - mFdp.ConsumeIntegral<uint32_t>()}; - transaction.setColor(surface, color); - transaction.setBackgroundColor(surface, color, mFdp.ConsumeFloatingPoint<float>(), - mFdp.PickValueInArray(kDataspaces)); - - transaction.setApi(surface, mFdp.ConsumeIntegral<int32_t>()); - transaction.setFrameRateSelectionPriority(surface, mFdp.ConsumeIntegral<int32_t>()); - transaction.setColorSpaceAgnostic(surface, mFdp.ConsumeBool() /*agnostic*/); - - gui::WindowInfo windowInfo; - getWindowInfo(&windowInfo); - transaction.setInputWindowInfo(surface, windowInfo); - Parcel windowParcel; - windowInfo.writeToParcel(&windowParcel); - windowParcel.setDataPosition(0); - windowInfo.readFromParcel(&windowParcel); - - windowInfo.addTouchableRegion(getRect(&mFdp)); - int32_t pointX = mFdp.ConsumeIntegral<int32_t>(); - int32_t pointY = mFdp.ConsumeIntegral<int32_t>(); - windowInfo.touchableRegionContainsPoint(pointX, pointY); - windowInfo.frameContainsPoint(pointX, pointY); - - Parcel transactionParcel; - transaction.writeToParcel(&transactionParcel); - transactionParcel.setDataPosition(0); - transaction.readFromParcel(&transactionParcel); - SurfaceComposerClient::Transaction::createFromParcel(&transactionParcel); -} - -void SurfaceComposerClientFuzzer::fuzzOnPullAtom() { - std::string outData; - bool success; - SurfaceComposerClient::onPullAtom(mFdp.ConsumeIntegral<int32_t>(), &outData, &success); -} - -void SurfaceComposerClientFuzzer::invokeSurfaceComposerClient() { - String8 displayName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str()); - sp<IBinder> displayToken = - SurfaceComposerClient::createDisplay(displayName, mFdp.ConsumeBool() /*secure*/); - SurfaceComposerClient::setDesiredDisplayModeSpecs(displayToken, getDisplayModeSpecs()); - - ui::ColorMode colorMode = mFdp.PickValueInArray(kColormodes); - SurfaceComposerClient::setActiveColorMode(displayToken, colorMode); - SurfaceComposerClient::setAutoLowLatencyMode(displayToken, mFdp.ConsumeBool() /*on*/); - SurfaceComposerClient::setGameContentType(displayToken, mFdp.ConsumeBool() /*on*/); - SurfaceComposerClient::setDisplayPowerMode(displayToken, mFdp.ConsumeIntegral<int32_t>()); - SurfaceComposerClient::doUncacheBufferTransaction(mFdp.ConsumeIntegral<uint64_t>()); - - SurfaceComposerClient::setDisplayBrightness(displayToken, getBrightness(&mFdp)); - aidl::android::hardware::power::Boost boostId = mFdp.PickValueInArray(kBoost); - SurfaceComposerClient::notifyPowerBoost((int32_t)boostId); - - String8 surfaceName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str()); - sp<BBinder> handle(new BBinder()); - sp<BnGraphicBufferProducer> producer; - sp<Surface> surfaceParent( - new Surface(producer, mFdp.ConsumeBool() /*controlledByApp*/, handle)); - - fuzzOnPullAtom(); - SurfaceComposerClient::setDisplayContentSamplingEnabled(displayToken, - mFdp.ConsumeBool() /*enable*/, - mFdp.ConsumeIntegral<uint8_t>(), - mFdp.ConsumeIntegral<uint64_t>()); - - sp<IBinder> stopLayerHandle; - sp<gui::IRegionSamplingListener> listener = sp<gui::IRegionSamplingListenerDefault>::make(); - sp<gui::IRegionSamplingListenerDelegator> sampleListener = - new gui::IRegionSamplingListenerDelegator(listener); - SurfaceComposerClient::addRegionSamplingListener(getRect(&mFdp), stopLayerHandle, - sampleListener); - sp<gui::IFpsListenerDefault> fpsListener; - SurfaceComposerClient::addFpsListener(mFdp.ConsumeIntegral<int32_t>(), fpsListener); -} - -void SurfaceComposerClientFuzzer::invokeSurfaceComposerClientBinder() { - sp<FakeBnSurfaceComposerClient> client(new FakeBnSurfaceComposerClient()); - fuzzService(client.get(), std::move(mFdp)); -} - -void SurfaceComposerClientFuzzer::process() { - invokeSurfaceComposerClient(); - invokeSurfaceComposerTransaction(); - invokeSurfaceComposerClientBinder(); -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - SurfaceComposerClientFuzzer surfaceComposerClientFuzzer(data, size); - surfaceComposerClientFuzzer.process(); - return 0; -} diff --git a/libs/gui/fuzzer/libgui_surfaceComposer_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposer_fuzzer.cpp deleted file mode 100644 index 6d5427bc9e..0000000000 --- a/libs/gui/fuzzer/libgui_surfaceComposer_fuzzer.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <fuzzbinder/libbinder_driver.h> -#include <fuzzer/FuzzedDataProvider.h> -#include <libgui_fuzzer_utils.h> - -using namespace android; - -class SurfaceComposerFuzzer { -public: - SurfaceComposerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){}; - void process(); - -private: - FuzzedDataProvider mFdp; -}; - -void SurfaceComposerFuzzer::process() { - sp<FakeBnSurfaceComposer> composer(new FakeBnSurfaceComposer()); - fuzzService(composer.get(), std::move(mFdp)); -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - SurfaceComposerFuzzer surfaceComposerFuzzer(data, size); - surfaceComposerFuzzer.process(); - return 0; -} diff --git a/libs/gui/tests/FrameRateUtilsTest.cpp b/libs/gui/tests/FrameRateUtilsTest.cpp index 5fe22b05f9..04bfb28f65 100644 --- a/libs/gui/tests/FrameRateUtilsTest.cpp +++ b/libs/gui/tests/FrameRateUtilsTest.cpp @@ -34,6 +34,8 @@ TEST(FrameRateUtilsTest, ValidateFrameRate) { ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS, "")); EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); + EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_GTE, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); // Privileged APIs. EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 9e0ce1db33..d58fb42f05 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -60,6 +60,45 @@ bool shouldDisregardOffset(uint32_t source) { return !isFromSource(source, AINPUT_SOURCE_CLASS_POINTER); } +int32_t resolveActionForSplitMotionEvent( + int32_t action, int32_t flags, const std::vector<PointerProperties>& pointerProperties, + const std::vector<PointerProperties>& splitPointerProperties) { + LOG_ALWAYS_FATAL_IF(splitPointerProperties.empty()); + const auto maskedAction = MotionEvent::getActionMasked(action); + if (maskedAction != AMOTION_EVENT_ACTION_POINTER_DOWN && + maskedAction != AMOTION_EVENT_ACTION_POINTER_UP) { + // The action is unaffected by splitting this motion event. + return action; + } + const auto actionIndex = MotionEvent::getActionIndex(action); + if (CC_UNLIKELY(actionIndex >= pointerProperties.size())) { + LOG(FATAL) << "Action index is out of bounds, index: " << actionIndex; + } + + const auto affectedPointerId = pointerProperties[actionIndex].id; + std::optional<uint32_t> splitActionIndex; + for (uint32_t i = 0; i < splitPointerProperties.size(); i++) { + if (affectedPointerId == splitPointerProperties[i].id) { + splitActionIndex = i; + break; + } + } + if (!splitActionIndex.has_value()) { + // The affected pointer is not part of the split motion event. + return AMOTION_EVENT_ACTION_MOVE; + } + + if (splitPointerProperties.size() > 1) { + return maskedAction | (*splitActionIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); + } + + if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { + return ((flags & AMOTION_EVENT_FLAG_CANCELED) != 0) ? AMOTION_EVENT_ACTION_CANCEL + : AMOTION_EVENT_ACTION_UP; + } + return AMOTION_EVENT_ACTION_DOWN; +} + } // namespace const char* motionClassificationToString(MotionClassification classification) { @@ -584,6 +623,28 @@ void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { } } +void MotionEvent::splitFrom(const android::MotionEvent& other, + std::bitset<MAX_POINTER_ID + 1> splitPointerIds, int32_t newEventId) { + // TODO(b/327503168): The down time should be a parameter to the split function, because only + // the caller can know when the first event went down on the target. + const nsecs_t splitDownTime = other.mDownTime; + + auto [action, pointerProperties, pointerCoords] = + split(other.getAction(), other.getFlags(), other.getHistorySize(), + other.mPointerProperties, other.mSamplePointerCoords, splitPointerIds); + + // Initialize the event with zero pointers, and manually set the split pointers. + initialize(newEventId, other.mDeviceId, other.mSource, other.mDisplayId, /*hmac=*/{}, action, + other.mActionButton, other.mFlags, other.mEdgeFlags, other.mMetaState, + other.mButtonState, other.mClassification, other.mTransform, other.mXPrecision, + other.mYPrecision, other.mRawXCursorPosition, other.mRawYCursorPosition, + other.mRawTransform, splitDownTime, other.getEventTime(), /*pointerCount=*/0, + pointerProperties.data(), pointerCoords.data()); + mPointerProperties = std::move(pointerProperties); + mSamplePointerCoords = std::move(pointerCoords); + mSampleEventTimes = other.mSampleEventTimes; +} + void MotionEvent::addSample( int64_t eventTime, const PointerCoords* pointerCoords) { @@ -934,6 +995,45 @@ std::string MotionEvent::actionToString(int32_t action) { return android::base::StringPrintf("%" PRId32, action); } +std::tuple<int32_t, std::vector<PointerProperties>, std::vector<PointerCoords>> MotionEvent::split( + int32_t action, int32_t flags, int32_t historySize, + const std::vector<PointerProperties>& pointerProperties, + const std::vector<PointerCoords>& pointerCoords, + std::bitset<MAX_POINTER_ID + 1> splitPointerIds) { + LOG_ALWAYS_FATAL_IF(!splitPointerIds.any()); + const auto pointerCount = pointerProperties.size(); + LOG_ALWAYS_FATAL_IF(pointerCoords.size() != (pointerCount * (historySize + 1))); + const auto splitCount = splitPointerIds.count(); + + std::vector<PointerProperties> splitPointerProperties; + std::vector<PointerCoords> splitPointerCoords; + + for (uint32_t i = 0; i < pointerCount; i++) { + if (splitPointerIds.test(pointerProperties[i].id)) { + splitPointerProperties.emplace_back(pointerProperties[i]); + } + } + for (uint32_t i = 0; i < pointerCoords.size(); i++) { + if (splitPointerIds.test(pointerProperties[i % pointerCount].id)) { + splitPointerCoords.emplace_back(pointerCoords[i]); + } + } + LOG_ALWAYS_FATAL_IF(splitPointerCoords.size() != + (splitPointerProperties.size() * (historySize + 1))); + + if (CC_UNLIKELY(splitPointerProperties.size() != splitCount)) { + LOG(FATAL) << "Cannot split MotionEvent: Requested splitting " << splitCount + << " pointers from the original event, but the original event only contained " + << splitPointerProperties.size() << " of those pointers."; + } + + // TODO(b/327503168): Verify the splitDownTime here once it is used correctly. + + const auto splitAction = resolveActionForSplitMotionEvent(action, flags, pointerProperties, + splitPointerProperties); + return {splitAction, splitPointerProperties, splitPointerCoords}; +} + // Apply the given transformation to the point without checking whether the entire transform // should be disregarded altogether for the provided source. static inline vec2 calculateTransformedXYUnchecked(uint32_t source, const ui::Transform& transform, diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index d4dbc45090..c348833747 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -20,12 +20,14 @@ #include <unistd.h> #include <ctype.h> +#include <android-base/properties.h> #include <android-base/stringprintf.h> #include <ftl/enum.h> #include <gui/constants.h> #include <input/InputDevice.h> #include <input/InputEventLabels.h> +using android::base::GetProperty; using android::base::StringPrintf; namespace android { @@ -96,21 +98,22 @@ std::string getInputDeviceConfigurationFilePathByName( // Treblized input device config files will be located /product/usr, /system_ext/usr, // /odm/usr or /vendor/usr. - // These files may also be in the com.android.input.config APEX. - const char* rootsForPartition[]{ - "/product", - "/system_ext", - "/odm", - "/vendor", - "/apex/com.android.input.config/etc", - getenv("ANDROID_ROOT"), + std::vector<std::string> pathPrefixes{ + "/product/usr/", + "/system_ext/usr/", + "/odm/usr/", + "/vendor/usr/", }; - for (size_t i = 0; i < size(rootsForPartition); i++) { - if (rootsForPartition[i] == nullptr) { - continue; - } - path = rootsForPartition[i]; - path += "/usr/"; + // These files may also be in the APEX pointed by input_device.config_file.apex sysprop. + if (auto apex = GetProperty("input_device.config_file.apex", ""); !apex.empty()) { + pathPrefixes.push_back("/apex/" + apex + "/etc/usr/"); + } + // ANDROID_ROOT may not be set on host + if (auto android_root = getenv("ANDROID_ROOT"); android_root != nullptr) { + pathPrefixes.push_back(std::string(android_root) + "/usr/"); + } + for (const auto& prefix : pathPrefixes) { + path = prefix; appendInputDeviceConfigurationFileRelativePath(path, name, type); #if DEBUG_PROBE ALOGD("Probing for system provided input device configuration file: path='%s'", diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index a9655730fc..540766d66c 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -23,6 +23,7 @@ #include <gtest/gtest.h> #include <gui/constants.h> #include <input/Input.h> +#include <input/InputEventBuilders.h> namespace android { @@ -31,6 +32,18 @@ static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT; static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION; +static constexpr auto POINTER_0_DOWN = + AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); + +static constexpr auto POINTER_1_DOWN = + AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); + +static constexpr auto POINTER_0_UP = + AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); + +static constexpr auto POINTER_1_UP = + AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); + class BaseTest : public testing::Test { protected: static constexpr std::array<uint8_t, 32> HMAC = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, @@ -554,6 +567,145 @@ TEST_F(MotionEventTest, CopyFrom_DoNotKeepHistory) { ASSERT_EQ(event.getX(0), copy.getX(0)); } +TEST_F(MotionEventTest, SplitPointerDown) { + MotionEvent event = MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .downTime(ARBITRARY_DOWN_TIME) + .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4)) + .pointer(PointerBuilder(/*id=*/6, ToolType::FINGER).x(6).y(6)) + .pointer(PointerBuilder(/*id=*/8, ToolType::FINGER).x(8).y(8)) + .build(); + + MotionEvent splitDown; + std::bitset<MAX_POINTER_ID + 1> splitDownIds{}; + splitDownIds.set(6, true); + splitDown.splitFrom(event, splitDownIds, /*eventId=*/42); + ASSERT_EQ(splitDown.getAction(), AMOTION_EVENT_ACTION_DOWN); + ASSERT_EQ(splitDown.getPointerCount(), 1u); + ASSERT_EQ(splitDown.getPointerId(0), 6); + ASSERT_EQ(splitDown.getX(0), 6); + ASSERT_EQ(splitDown.getY(0), 6); + + MotionEvent splitPointerDown; + std::bitset<MAX_POINTER_ID + 1> splitPointerDownIds{}; + splitPointerDownIds.set(6, true); + splitPointerDownIds.set(8, true); + splitPointerDown.splitFrom(event, splitPointerDownIds, /*eventId=*/42); + ASSERT_EQ(splitPointerDown.getAction(), POINTER_0_DOWN); + ASSERT_EQ(splitPointerDown.getPointerCount(), 2u); + ASSERT_EQ(splitPointerDown.getPointerId(0), 6); + ASSERT_EQ(splitPointerDown.getX(0), 6); + ASSERT_EQ(splitPointerDown.getY(0), 6); + ASSERT_EQ(splitPointerDown.getPointerId(1), 8); + ASSERT_EQ(splitPointerDown.getX(1), 8); + ASSERT_EQ(splitPointerDown.getY(1), 8); + + MotionEvent splitMove; + std::bitset<MAX_POINTER_ID + 1> splitMoveIds{}; + splitMoveIds.set(4, true); + splitMove.splitFrom(event, splitMoveIds, /*eventId=*/43); + ASSERT_EQ(splitMove.getAction(), AMOTION_EVENT_ACTION_MOVE); + ASSERT_EQ(splitMove.getPointerCount(), 1u); + ASSERT_EQ(splitMove.getPointerId(0), 4); + ASSERT_EQ(splitMove.getX(0), 4); + ASSERT_EQ(splitMove.getY(0), 4); +} + +TEST_F(MotionEventTest, SplitPointerUp) { + MotionEvent event = MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN) + .downTime(ARBITRARY_DOWN_TIME) + .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4)) + .pointer(PointerBuilder(/*id=*/6, ToolType::FINGER).x(6).y(6)) + .pointer(PointerBuilder(/*id=*/8, ToolType::FINGER).x(8).y(8)) + .build(); + + MotionEvent splitUp; + std::bitset<MAX_POINTER_ID + 1> splitUpIds{}; + splitUpIds.set(4, true); + splitUp.splitFrom(event, splitUpIds, /*eventId=*/42); + ASSERT_EQ(splitUp.getAction(), AMOTION_EVENT_ACTION_UP); + ASSERT_EQ(splitUp.getPointerCount(), 1u); + ASSERT_EQ(splitUp.getPointerId(0), 4); + ASSERT_EQ(splitUp.getX(0), 4); + ASSERT_EQ(splitUp.getY(0), 4); + + MotionEvent splitPointerUp; + std::bitset<MAX_POINTER_ID + 1> splitPointerUpIds{}; + splitPointerUpIds.set(4, true); + splitPointerUpIds.set(8, true); + splitPointerUp.splitFrom(event, splitPointerUpIds, /*eventId=*/42); + ASSERT_EQ(splitPointerUp.getAction(), POINTER_0_UP); + ASSERT_EQ(splitPointerUp.getPointerCount(), 2u); + ASSERT_EQ(splitPointerUp.getPointerId(0), 4); + ASSERT_EQ(splitPointerUp.getX(0), 4); + ASSERT_EQ(splitPointerUp.getY(0), 4); + ASSERT_EQ(splitPointerUp.getPointerId(1), 8); + ASSERT_EQ(splitPointerUp.getX(1), 8); + ASSERT_EQ(splitPointerUp.getY(1), 8); + + MotionEvent splitMove; + std::bitset<MAX_POINTER_ID + 1> splitMoveIds{}; + splitMoveIds.set(6, true); + splitMoveIds.set(8, true); + splitMove.splitFrom(event, splitMoveIds, /*eventId=*/43); + ASSERT_EQ(splitMove.getAction(), AMOTION_EVENT_ACTION_MOVE); + ASSERT_EQ(splitMove.getPointerCount(), 2u); + ASSERT_EQ(splitMove.getPointerId(0), 6); + ASSERT_EQ(splitMove.getX(0), 6); + ASSERT_EQ(splitMove.getY(0), 6); + ASSERT_EQ(splitMove.getPointerId(1), 8); + ASSERT_EQ(splitMove.getX(1), 8); + ASSERT_EQ(splitMove.getY(1), 8); +} + +TEST_F(MotionEventTest, SplitPointerUpCancel) { + MotionEvent event = MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN) + .downTime(ARBITRARY_DOWN_TIME) + .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4)) + .pointer(PointerBuilder(/*id=*/6, ToolType::FINGER).x(6).y(6)) + .pointer(PointerBuilder(/*id=*/8, ToolType::FINGER).x(8).y(8)) + .addFlag(AMOTION_EVENT_FLAG_CANCELED) + .build(); + + MotionEvent splitUp; + std::bitset<MAX_POINTER_ID + 1> splitUpIds{}; + splitUpIds.set(6, true); + splitUp.splitFrom(event, splitUpIds, /*eventId=*/42); + ASSERT_EQ(splitUp.getAction(), AMOTION_EVENT_ACTION_CANCEL); + ASSERT_EQ(splitUp.getPointerCount(), 1u); + ASSERT_EQ(splitUp.getPointerId(0), 6); + ASSERT_EQ(splitUp.getX(0), 6); + ASSERT_EQ(splitUp.getY(0), 6); +} + +TEST_F(MotionEventTest, SplitPointerMove) { + MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) + .downTime(ARBITRARY_DOWN_TIME) + .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4)) + .pointer(PointerBuilder(/*id=*/6, ToolType::FINGER).x(6).y(6)) + .pointer(PointerBuilder(/*id=*/8, ToolType::FINGER).x(8).y(8)) + .transform(ui::Transform(ui::Transform::ROT_90, 100, 100)) + .rawTransform(ui::Transform(ui::Transform::FLIP_H, 50, 50)) + .build(); + + MotionEvent splitMove; + std::bitset<MAX_POINTER_ID + 1> splitMoveIds{}; + splitMoveIds.set(4, true); + splitMoveIds.set(8, true); + splitMove.splitFrom(event, splitMoveIds, /*eventId=*/42); + ASSERT_EQ(splitMove.getAction(), AMOTION_EVENT_ACTION_MOVE); + ASSERT_EQ(splitMove.getPointerCount(), 2u); + ASSERT_EQ(splitMove.getPointerId(0), 4); + ASSERT_EQ(splitMove.getX(0), event.getX(0)); + ASSERT_EQ(splitMove.getY(0), event.getY(0)); + ASSERT_EQ(splitMove.getRawX(0), event.getRawX(0)); + ASSERT_EQ(splitMove.getRawY(0), event.getRawY(0)); + ASSERT_EQ(splitMove.getPointerId(1), 8); + ASSERT_EQ(splitMove.getX(1), event.getX(2)); + ASSERT_EQ(splitMove.getY(1), event.getY(2)); + ASSERT_EQ(splitMove.getRawX(1), event.getRawX(2)); + ASSERT_EQ(splitMove.getRawY(1), event.getRawY(2)); +} + TEST_F(MotionEventTest, OffsetLocation) { MotionEvent event; initializeEventWithHistory(&event); diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp index f7f20b452c..03f4f399d0 100644 --- a/libs/nativedisplay/Android.bp +++ b/libs/nativedisplay/Android.bp @@ -34,7 +34,13 @@ license { cc_library_headers { name: "libnativedisplay_headers", + host_supported: true, export_include_dirs: ["include"], + target: { + windows: { + enabled: true, + }, + }, } cc_library_shared { diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp index 0e90327a17..855807472e 100644 --- a/libs/nativewindow/Android.bp +++ b/libs/nativewindow/Android.bp @@ -54,6 +54,11 @@ cc_library_headers { "test_com.android.media.swcodec", ], host_supported: true, + target: { + windows: { + enabled: true, + }, + }, } ndk_library { diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h index e0e30c3283..6fcb3a4842 100644 --- a/libs/nativewindow/include/android/hardware_buffer.h +++ b/libs/nativewindow/include/android/hardware_buffer.h @@ -52,6 +52,10 @@ #include <inttypes.h> #include <sys/cdefs.h> +#if !defined(__INTRODUCED_IN) +#define __INTRODUCED_IN(__api_level) /* nothing */ +#endif + __BEGIN_DECLS // clang-format off diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp index b43ab6c9df..eb7a9d5bfa 100644 --- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp @@ -378,6 +378,11 @@ VulkanInterface initVulkanInterface(bool protectedContent = false) { BAIL("Could not find a Vulkan 1.1+ physical device"); } + if (physDevProps.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) { + // TODO: b/326633110 - SkiaVK is not working correctly on swiftshader path. + BAIL("CPU implementations of Vulkan is not supported"); + } + // Check for syncfd support. Bail if we cannot both import and export them. VkPhysicalDeviceExternalSemaphoreInfo semInfo = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp index 1e7e70775a..00514c4417 100644 --- a/libs/sensorprivacy/Android.bp +++ b/libs/sensorprivacy/Android.bp @@ -57,7 +57,6 @@ cc_library_shared { filegroup { name: "libsensorprivacy_aidl", srcs: [ - "aidl/android/hardware/CameraPrivacyAllowlistEntry.aidl", "aidl/android/hardware/ISensorPrivacyListener.aidl", "aidl/android/hardware/ISensorPrivacyManager.aidl", ], diff --git a/libs/sensorprivacy/SensorPrivacyManager.cpp b/libs/sensorprivacy/SensorPrivacyManager.cpp index fe9378616d..3f3ad9343c 100644 --- a/libs/sensorprivacy/SensorPrivacyManager.cpp +++ b/libs/sensorprivacy/SensorPrivacyManager.cpp @@ -155,10 +155,9 @@ int SensorPrivacyManager::getToggleSensorPrivacyState(int toggleType, int sensor return DISABLED; } -std::vector<hardware::CameraPrivacyAllowlistEntry> - SensorPrivacyManager::getCameraPrivacyAllowlist(){ +std::vector<String16> SensorPrivacyManager::getCameraPrivacyAllowlist(){ sp<hardware::ISensorPrivacyManager> service = getService(); - std::vector<hardware::CameraPrivacyAllowlistEntry> result; + std::vector<String16> result; if (service != nullptr) { service->getCameraPrivacyAllowlist(&result); return result; diff --git a/libs/sensorprivacy/aidl/android/hardware/CameraPrivacyAllowlistEntry.aidl b/libs/sensorprivacy/aidl/android/hardware/CameraPrivacyAllowlistEntry.aidl deleted file mode 100644 index 03e153704b..0000000000 --- a/libs/sensorprivacy/aidl/android/hardware/CameraPrivacyAllowlistEntry.aidl +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) 2024, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware; - -parcelable CameraPrivacyAllowlistEntry { - String packageName; - boolean isMandatory; -} diff --git a/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl index b6bd39e557..f7071872bf 100644 --- a/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl +++ b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl @@ -16,7 +16,6 @@ package android.hardware; -import android.hardware.CameraPrivacyAllowlistEntry; import android.hardware.ISensorPrivacyListener; /** @hide */ @@ -43,7 +42,7 @@ interface ISensorPrivacyManager { void setToggleSensorPrivacyForProfileGroup(int userId, int source, int sensor, boolean enable); - List<CameraPrivacyAllowlistEntry> getCameraPrivacyAllowlist(); + List<String> getCameraPrivacyAllowlist(); int getToggleSensorPrivacyState(int toggleType, int sensor); diff --git a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h index 9e97e166be..8935b76adc 100644 --- a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h +++ b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h @@ -45,9 +45,7 @@ public: enum { ENABLED = 1, DISABLED = 2, - AUTOMOTIVE_DRIVER_ASSISTANCE_HELPFUL_APPS = 3, - AUTOMOTIVE_DRIVER_ASSISTANCE_REQUIRED_APPS = 4, - AUTOMOTIVE_DRIVER_ASSISTANCE_APPS = 5 + ENABLED_EXCEPT_ALLOWLISTED_APPS = 3 }; SensorPrivacyManager(); @@ -62,7 +60,7 @@ public: bool isToggleSensorPrivacyEnabled(int toggleType, int sensor); status_t isToggleSensorPrivacyEnabled(int toggleType, int sensor, bool &result); int getToggleSensorPrivacyState(int toggleType, int sensor); - std::vector<hardware::CameraPrivacyAllowlistEntry> getCameraPrivacyAllowlist(); + std::vector<String16> getCameraPrivacyAllowlist(); bool isCameraPrivacyEnabled(String16 packageName); status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient); diff --git a/services/batteryservice/include/batteryservice/BatteryService.h b/services/batteryservice/include/batteryservice/BatteryService.h index 654c903db2..f697f94a7e 100644 --- a/services/batteryservice/include/batteryservice/BatteryService.h +++ b/services/batteryservice/include/batteryservice/BatteryService.h @@ -34,9 +34,9 @@ enum { BATTERY_PROP_CAPACITY = 4, // equals BATTERY_PROPERTY_CAPACITY BATTERY_PROP_ENERGY_COUNTER = 5, // equals BATTERY_PROPERTY_ENERGY_COUNTER BATTERY_PROP_BATTERY_STATUS = 6, // equals BATTERY_PROPERTY_BATTERY_STATUS - BATTERY_PROP_CHARGING_POLICY = 7, // equals BATTERY_PROPERTY_CHARGING_POLICY - BATTERY_PROP_MANUFACTURING_DATE = 8, // equals BATTERY_PROPERTY_MANUFACTURING_DATE - BATTERY_PROP_FIRST_USAGE_DATE = 9, // equals BATTERY_PROPERTY_FIRST_USAGE_DATE + BATTERY_PROP_MANUFACTURING_DATE = 7, // equals BATTERY_PROPERTY_MANUFACTURING_DATE + BATTERY_PROP_FIRST_USAGE_DATE = 8, // equals BATTERY_PROPERTY_FIRST_USAGE_DATE + BATTERY_PROP_CHARGING_POLICY = 9, // equals BATTERY_PROPERTY_CHARGING_POLICY BATTERY_PROP_STATE_OF_HEALTH = 10, // equals BATTERY_PROPERTY_STATE_OF_HEALTH BATTERY_PROP_PART_STATUS = 12, // equals BATTERY_PROPERTY_PART_STATUS }; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index ef7b7805a0..057b996a23 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2576,9 +2576,9 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( return {}; } - // Drop touch events if requested by input feature + // Do not slide events to the window which can not receive motion event if (newTouchedWindowHandle != nullptr && - shouldDropInput(entry, newTouchedWindowHandle)) { + !canWindowReceiveMotionLocked(newTouchedWindowHandle, entry)) { newTouchedWindowHandle = nullptr; } @@ -4286,72 +4286,13 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent( const MotionEntry& originalMotionEntry, std::bitset<MAX_POINTER_ID + 1> pointerIds, nsecs_t splitDownTime) { - ALOG_ASSERT(pointerIds.any()); - - uint32_t splitPointerIndexMap[MAX_POINTERS]; - std::vector<PointerProperties> splitPointerProperties; - std::vector<PointerCoords> splitPointerCoords; - - uint32_t originalPointerCount = originalMotionEntry.getPointerCount(); - uint32_t splitPointerCount = 0; - - for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount; - originalPointerIndex++) { - const PointerProperties& pointerProperties = - originalMotionEntry.pointerProperties[originalPointerIndex]; - uint32_t pointerId = uint32_t(pointerProperties.id); - if (pointerIds.test(pointerId)) { - splitPointerIndexMap[splitPointerCount] = originalPointerIndex; - splitPointerProperties.push_back(pointerProperties); - splitPointerCoords.push_back(originalMotionEntry.pointerCoords[originalPointerIndex]); - splitPointerCount += 1; - } - } - - if (splitPointerCount != pointerIds.count()) { - // This is bad. We are missing some of the pointers that we expected to deliver. - // Most likely this indicates that we received an ACTION_MOVE events that has - // different pointer ids than we expected based on the previous ACTION_DOWN - // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers - // in this way. - ALOGW("Dropping split motion event because the pointer count is %d but " - "we expected there to be %zu pointers. This probably means we received " - "a broken sequence of pointer ids from the input device: %s", - splitPointerCount, pointerIds.count(), originalMotionEntry.getDescription().c_str()); - return nullptr; - } - - int32_t action = originalMotionEntry.action; - int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK; - if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN || - maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { - int32_t originalPointerIndex = MotionEvent::getActionIndex(action); - const PointerProperties& pointerProperties = - originalMotionEntry.pointerProperties[originalPointerIndex]; - uint32_t pointerId = uint32_t(pointerProperties.id); - if (pointerIds.test(pointerId)) { - if (pointerIds.count() == 1) { - // The first/last pointer went down/up. - action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN - ? AMOTION_EVENT_ACTION_DOWN - : (originalMotionEntry.flags & AMOTION_EVENT_FLAG_CANCELED) != 0 - ? AMOTION_EVENT_ACTION_CANCEL - : AMOTION_EVENT_ACTION_UP; - } else { - // A secondary pointer went down/up. - uint32_t splitPointerIndex = 0; - while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) { - splitPointerIndex += 1; - } - action = maskedAction | - (splitPointerIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - } - } else { - // An unrelated pointer changed. - action = AMOTION_EVENT_ACTION_MOVE; - } - } + const auto& [action, pointerProperties, pointerCoords] = + MotionEvent::split(originalMotionEntry.action, originalMotionEntry.flags, + /*historySize=*/0, originalMotionEntry.pointerProperties, + originalMotionEntry.pointerCoords, pointerIds); + // TODO(b/327503168): Move this check inside MotionEvent::split once all callers handle it + // correctly. if (action == AMOTION_EVENT_ACTION_DOWN && splitDownTime != originalMotionEntry.eventTime) { logDispatchStateLocked(); LOG_ALWAYS_FATAL("Split motion event has mismatching downTime and eventTime for " @@ -4379,7 +4320,7 @@ std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent( originalMotionEntry.yPrecision, originalMotionEntry.xCursorPosition, originalMotionEntry.yCursorPosition, splitDownTime, - splitPointerProperties, splitPointerCoords); + pointerProperties, pointerCoords); return splitMotionEntry; } diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp index 45f09ae32a..06f10e5445 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp @@ -40,6 +40,8 @@ namespace android { // The default velocity control parameters that has no effect. static const VelocityControlParameters FLAT_VELOCITY_CONTROL_PARAMS{}; +static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer(); + // --- CursorMotionAccumulator --- CursorMotionAccumulator::CursorMotionAccumulator() { @@ -76,9 +78,14 @@ void CursorMotionAccumulator::finishSync() { CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig) + : CursorInputMapper(deviceContext, readerConfig, ENABLE_POINTER_CHOREOGRAPHER) {} + +CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig, + bool enablePointerChoreographer) : InputMapper(deviceContext, readerConfig), mLastEventTime(std::numeric_limits<nsecs_t>::min()), - mEnablePointerChoreographer(input_flags::enable_pointer_choreographer()), + mEnablePointerChoreographer(enablePointerChoreographer), mEnableNewMousePointerBallistics(input_flags::enable_new_mouse_pointer_ballistics()) {} CursorInputMapper::~CursorInputMapper() { diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h index 1ddf6f2b5b..ca541d9924 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.h +++ b/services/inputflinger/reader/mapper/CursorInputMapper.h @@ -133,6 +133,10 @@ private: explicit CursorInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig); + // Constructor for testing. + explicit CursorInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig, + bool enablePointerChoreographer); void dumpParameters(std::string& dump); void configureBasicParams(); void configureOnPointerCapture(const InputReaderConfiguration& config); diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp index b990dd5e79..eacc66eeab 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp @@ -47,6 +47,8 @@ namespace android { namespace { +static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer(); + /** * Log details of each gesture output by the gestures library. * Enable this via "adb shell setprop log.tag.TouchpadInputMapperGestures DEBUG" (requires @@ -232,6 +234,11 @@ private: TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig) + : TouchpadInputMapper(deviceContext, readerConfig, ENABLE_POINTER_CHOREOGRAPHER) {} + +TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig, + bool enablePointerChoreographer) : InputMapper(deviceContext, readerConfig), mGestureInterpreter(NewGestureInterpreter(), DeleteGestureInterpreter), mPointerController(getContext()->getPointerController(getDeviceId())), @@ -240,7 +247,7 @@ TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext, mGestureConverter(*getContext(), deviceContext, getDeviceId()), mCapturedEventConverter(*getContext(), deviceContext, mMotionAccumulator, getDeviceId()), mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())), - mEnablePointerChoreographer(input_flags::enable_pointer_choreographer()) { + mEnablePointerChoreographer(enablePointerChoreographer) { RawAbsoluteAxisInfo slotAxisInfo; deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo); if (!slotAxisInfo.valid || slotAxisInfo.maxValue <= 0) { diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h index 897edca4e1..9f272cf846 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h @@ -72,6 +72,10 @@ private: void resetGestureInterpreter(nsecs_t when); explicit TouchpadInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig); + // Constructor for testing. + explicit TouchpadInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig, + bool enablePointerChoreographer); void updatePalmDetectionMetrics(); [[nodiscard]] std::list<NotifyArgs> sendHardwareState(nsecs_t when, nsecs_t readTime, SelfContainedHardwareState schs); diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp index 797ebcc8be..764bb56141 100644 --- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp +++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp @@ -67,7 +67,6 @@ GestureConverter::GestureConverter(InputReaderContext& readerContext, : mDeviceId(deviceId), mReaderContext(readerContext), mPointerController(readerContext.getPointerController(deviceId)), - mEnablePointerChoreographer(input_flags::enable_pointer_choreographer()), mEnableFlingStop(input_flags::enable_touchpad_fling_stop()) { deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mXAxisInfo); deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mYAxisInfo); @@ -175,8 +174,7 @@ std::list<NotifyArgs> GestureConverter::handleMove(nsecs_t when, nsecs_t readTim const Gesture& gesture) { float deltaX = gesture.details.move.dx; float deltaY = gesture.details.move.dy; - const auto [oldXCursorPosition, oldYCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [oldXCursorPosition, oldYCursorPosition] = mPointerController->getPosition(); if (ENABLE_TOUCHPAD_PALM_REJECTION_V2) { bool wasHoverCancelled = mIsHoverCancelled; // Gesture will be cancelled if it started before the user started typing and @@ -214,8 +212,7 @@ std::list<NotifyArgs> GestureConverter::handleMove(nsecs_t when, nsecs_t readTim if (!down) { out += enterHover(when, readTime, oldXCursorPosition, oldYCursorPosition); } - const auto [newXCursorPosition, newYCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [newXCursorPosition, newYCursorPosition] = mPointerController->getPosition(); PointerCoords coords; coords.clear(); @@ -239,8 +236,7 @@ std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_ mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER); mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE); - const auto [xCursorPosition, yCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition(); PointerCoords coords; coords.clear(); @@ -320,8 +316,7 @@ std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_ std::list<NotifyArgs> GestureConverter::releaseAllButtons(nsecs_t when, nsecs_t readTime) { std::list<NotifyArgs> out; - const auto [xCursorPosition, yCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition(); PointerCoords coords; coords.clear(); @@ -356,8 +351,7 @@ std::list<NotifyArgs> GestureConverter::handleScroll(nsecs_t when, nsecs_t readT const Gesture& gesture) { std::list<NotifyArgs> out; PointerCoords& coords = mFakeFingerCoords[0]; - const auto [xCursorPosition, yCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition(); if (mCurrentClassification != MotionClassification::TWO_FINGER_SWIPE) { out += exitHover(when, readTime, xCursorPosition, yCursorPosition); @@ -415,9 +409,8 @@ std::list<NotifyArgs> GestureConverter::handleFling(nsecs_t when, nsecs_t readTi // avoid side effects (e.g. activation of UI elements). // TODO(b/326056750): add an API for fling stops. mFlingMayBeInProgress = false; - const auto [xCursorPosition, yCursorPosition] = mEnablePointerChoreographer - ? FloatPoint{0, 0} - : mPointerController->getPosition(); + const auto [xCursorPosition, yCursorPosition] = + mPointerController->getPosition(); PointerCoords coords; coords.clear(); coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition); @@ -461,8 +454,7 @@ std::list<NotifyArgs> GestureConverter::handleFling(nsecs_t when, nsecs_t readTi std::list<NotifyArgs> GestureConverter::endScroll(nsecs_t when, nsecs_t readTime) { std::list<NotifyArgs> out; - const auto [xCursorPosition, yCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition(); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_X_DISTANCE, 0); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_Y_DISTANCE, 0); NotifyMotionArgs args = @@ -482,8 +474,7 @@ std::list<NotifyArgs> GestureConverter::endScroll(nsecs_t when, nsecs_t readTime float dx, float dy) { std::list<NotifyArgs> out = {}; - const auto [xCursorPosition, yCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition(); if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) { // If the user changes the number of fingers mid-way through a swipe (e.g. they start with // three and then put a fourth finger down), the gesture library will treat it as two @@ -547,8 +538,7 @@ std::list<NotifyArgs> GestureConverter::endScroll(nsecs_t when, nsecs_t readTime if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) { return out; } - const auto [xCursorPosition, yCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition(); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, 0); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, 0); @@ -571,8 +561,7 @@ std::list<NotifyArgs> GestureConverter::endScroll(nsecs_t when, nsecs_t readTime [[nodiscard]] std::list<NotifyArgs> GestureConverter::handlePinch(nsecs_t when, nsecs_t readTime, const Gesture& gesture) { - const auto [xCursorPosition, yCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition(); // Pinch gesture phases are reported a little differently from others, in that the same details // struct is used for all phases of the gesture, just with different zoom_state values. When @@ -630,8 +619,7 @@ std::list<NotifyArgs> GestureConverter::endScroll(nsecs_t when, nsecs_t readTime std::list<NotifyArgs> GestureConverter::endPinch(nsecs_t when, nsecs_t readTime) { std::list<NotifyArgs> out; - const auto [xCursorPosition, yCursorPosition] = - mEnablePointerChoreographer ? FloatPoint{0, 0} : mPointerController->getPosition(); + const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition(); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR, 1.0); out.push_back(makeMotionArgs(when, readTime, diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.h b/services/inputflinger/reader/mapper/gestures/GestureConverter.h index ffab03967d..c8f437e0b8 100644 --- a/services/inputflinger/reader/mapper/gestures/GestureConverter.h +++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.h @@ -105,7 +105,6 @@ private: const int32_t mDeviceId; InputReaderContext& mReaderContext; std::shared_ptr<PointerControllerInterface> mPointerController; - const bool mEnablePointerChoreographer; const bool mEnableFlingStop; std::optional<int32_t> mDisplayId; diff --git a/services/inputflinger/rust/slow_keys_filter.rs b/services/inputflinger/rust/slow_keys_filter.rs index 01165b57fa..09fbf40842 100644 --- a/services/inputflinger/rust/slow_keys_filter.rs +++ b/services/inputflinger/rust/slow_keys_filter.rs @@ -28,6 +28,9 @@ use log::debug; use std::collections::HashSet; use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; +// Policy flags from Input.h +const POLICY_FLAG_DISABLE_KEY_REPEAT: i32 = 0x08000000; + #[derive(Debug)] struct OngoingKeyDown { scancode: i32, @@ -129,6 +132,12 @@ impl Filter for SlowKeysFilter { let mut pending_event = *event; pending_event.downTime += slow_filter.slow_key_threshold_ns; pending_event.eventTime = pending_event.downTime; + // Currently a slow keys user ends up repeating the presses key quite often + // since default repeat thresholds are very low, so blocking repeat for events + // when slow keys is enabled. + // TODO(b/322327461): Allow key repeat with slow keys, once repeat key rate and + // thresholds can be modified in the settings. + pending_event.policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT; slow_filter.pending_down_events.push(pending_event); } KeyEventAction::UP => { @@ -200,7 +209,7 @@ impl ThreadCallback for SlowKeysFilter { mod tests { use crate::input_filter::{test_callbacks::TestCallbacks, test_filter::TestFilter, Filter}; use crate::input_filter_thread::test_thread::TestThread; - use crate::slow_keys_filter::SlowKeysFilter; + use crate::slow_keys_filter::{SlowKeysFilter, POLICY_FLAG_DISABLE_KEY_REPEAT}; use android_hardware_input_common::aidl::android::hardware::input::common::Source::Source; use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{ DeviceInfo::DeviceInfo, KeyEvent::KeyEvent, KeyEventAction::KeyEventAction, @@ -285,6 +294,7 @@ mod tests { action: KeyEventAction::DOWN, downTime: 100, eventTime: 100, + policyFlags: POLICY_FLAG_DISABLE_KEY_REPEAT, ..BASE_KEY_EVENT } ); diff --git a/services/inputflinger/tests/CursorInputMapper_test.cpp b/services/inputflinger/tests/CursorInputMapper_test.cpp index 8c17221ead..de740672fc 100644 --- a/services/inputflinger/tests/CursorInputMapper_test.cpp +++ b/services/inputflinger/tests/CursorInputMapper_test.cpp @@ -157,9 +157,12 @@ protected: mFakePolicy->addDisplayViewport(createPrimaryViewport(ui::Rotation::Rotation0)); } + virtual bool isPointerChoreographerEnabled() { return false; } + void createMapper() { createDevice(); - mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration); + mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration, + isPointerChoreographerEnabled()); } void setPointerCapture(bool enabled) { @@ -194,10 +197,11 @@ protected: class CursorInputMapperUnitTest : public CursorInputMapperUnitTestBase { protected: void SetUp() override { - input_flags::enable_pointer_choreographer(false); input_flags::enable_new_mouse_pointer_ballistics(false); CursorInputMapperUnitTestBase::SetUp(); } + + bool isPointerChoreographerEnabled() override { return false; } }; TEST_F(CursorInputMapperUnitTest, GetSourcesReturnsMouseInPointerMode) { @@ -321,10 +325,10 @@ TEST_F(CursorInputMapperUnitTest, ProcessPointerCapture) { // Disable pointer capture. Afterwards, events should be generated the usual way. setPointerCapture(false); - const auto expectedCoords = input_flags::enable_pointer_choreographer() + const auto expectedCoords = CursorInputMapperUnitTest::isPointerChoreographerEnabled() ? WithCoords(0, 0) : WithCoords(INITIAL_CURSOR_X + 10.0f, INITIAL_CURSOR_Y + 20.0f); - const auto expectedCursorPosition = input_flags::enable_pointer_choreographer() + const auto expectedCursorPosition = CursorInputMapperUnitTest::isPointerChoreographerEnabled() ? WithCursorPosition(INVALID_CURSOR_POSITION, INVALID_CURSOR_POSITION) : WithCursorPosition(INITIAL_CURSOR_X + 10.0f, INITIAL_CURSOR_Y + 20.0f); args.clear(); @@ -708,7 +712,9 @@ TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdWithAssociatedViewport) { createDevice(); // Associate the InputDevice with the secondary display. ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport); - mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); + mMapper = createInputMapper< + CursorInputMapper>(deviceContext, mReaderConfiguration, + CursorInputMapperUnitTest::isPointerChoreographerEnabled()); // Ensure input events are generated for the secondary display. std::list<NotifyArgs> args; @@ -731,7 +737,9 @@ TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdIgnoresEventsForMismatchedPo createDevice(); // Associate the InputDevice with the secondary display. ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport); - mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); + mMapper = createInputMapper< + CursorInputMapper>(deviceContext, mReaderConfiguration, + CursorInputMapperUnitTest::isPointerChoreographerEnabled()); // The mapper should not generate any events because it is associated with a display that is // different from the pointer display. @@ -837,7 +845,9 @@ class CursorInputMapperButtonKeyTest : public CursorInputMapperUnitTest, public testing::WithParamInterface< std::tuple<int32_t /*evdevCode*/, int32_t /*expectedButtonState*/, - int32_t /*expectedKeyCode*/>> {}; + int32_t /*expectedKeyCode*/>> { + virtual bool isPointerChoreographerEnabled() override { return false; } +}; TEST_P(CursorInputMapperButtonKeyTest, ProcessShouldHandleButtonKey) { auto [evdevCode, expectedButtonState, expectedKeyCode] = GetParam(); @@ -956,10 +966,11 @@ TEST_F(CursorInputMapperUnitTest, PointerCaptureDisablesVelocityProcessing) { class CursorInputMapperUnitTestWithChoreographer : public CursorInputMapperUnitTestBase { protected: void SetUp() override { - input_flags::enable_pointer_choreographer(true); input_flags::enable_new_mouse_pointer_ballistics(false); CursorInputMapperUnitTestBase::SetUp(); } + + bool isPointerChoreographerEnabled() override { return true; } }; TEST_F(CursorInputMapperUnitTestWithChoreographer, PopulateDeviceInfoReturnsRangeFromPolicy) { @@ -1288,10 +1299,11 @@ TEST_F(CursorInputMapperUnitTestWithChoreographer, ConfigureDisplayIdNoAssociate class CursorInputMapperUnitTestWithNewBallistics : public CursorInputMapperUnitTestBase { protected: void SetUp() override { - input_flags::enable_pointer_choreographer(true); input_flags::enable_new_mouse_pointer_ballistics(true); CursorInputMapperUnitTestBase::SetUp(); } + + bool isPointerChoreographerEnabled() override { return true; } }; TEST_F(CursorInputMapperUnitTestWithNewBallistics, PointerCaptureDisablesVelocityProcessing) { @@ -1413,7 +1425,6 @@ constexpr nsecs_t MAX_BLUETOOTH_SMOOTHING_DELTA = ms2ns(32); class BluetoothCursorInputMapperUnitTest : public CursorInputMapperUnitTestBase { protected: void SetUp() override { - input_flags::enable_pointer_choreographer(false); SetUpWithBus(BUS_BLUETOOTH); mFakePointerController = std::make_shared<FakePointerController>(); @@ -1531,12 +1542,13 @@ TEST_F(BluetoothCursorInputMapperUnitTest, TimestampSmootheningNotUsed) { class BluetoothCursorInputMapperUnitTestWithChoreographer : public CursorInputMapperUnitTestBase { protected: void SetUp() override { - input_flags::enable_pointer_choreographer(true); SetUpWithBus(BUS_BLUETOOTH); mFakePointerController = std::make_shared<FakePointerController>(); mFakePolicy->setPointerController(mFakePointerController); } + + bool isPointerChoreographerEnabled() override { return true; } }; TEST_F(BluetoothCursorInputMapperUnitTestWithChoreographer, TimestampSmoothening) { diff --git a/services/inputflinger/tests/FakePointerController.cpp b/services/inputflinger/tests/FakePointerController.cpp index 31e117352b..dc199e2729 100644 --- a/services/inputflinger/tests/FakePointerController.cpp +++ b/services/inputflinger/tests/FakePointerController.cpp @@ -37,16 +37,22 @@ const std::map<int32_t, std::vector<int32_t>>& FakePointerController::getSpots() } void FakePointerController::setPosition(float x, float y) { + if (!mEnabled) return; + mX = x; mY = y; } FloatPoint FakePointerController::getPosition() const { + if (!mEnabled) { + return {0, 0}; + } + return {mX, mY}; } int32_t FakePointerController::getDisplayId() const { - if (!mDisplayId) { + if (!mEnabled || !mDisplayId) { return ADISPLAY_ID_NONE; } return *mDisplayId; @@ -64,6 +70,8 @@ void FakePointerController::updatePointerIcon(PointerIconStyle iconId) { } void FakePointerController::setCustomPointerIcon(const SpriteIcon& icon) { + if (!mEnabled) return; + ASSERT_FALSE(mCustomIconStyle.has_value()) << "Custom pointer icon was set more than once"; mCustomIconStyle = icon.style; } @@ -114,10 +122,14 @@ bool FakePointerController::isPointerShown() { } std::optional<FloatRect> FakePointerController::getBounds() const { + if (!mEnabled) return std::nullopt; + return mHaveBounds ? std::make_optional<FloatRect>(mMinX, mMinY, mMaxX, mMaxY) : std::nullopt; } void FakePointerController::move(float deltaX, float deltaY) { + if (!mEnabled) return; + mX += deltaX; if (mX < mMinX) mX = mMinX; if (mX > mMaxX) mX = mMaxX; @@ -127,14 +139,20 @@ void FakePointerController::move(float deltaX, float deltaY) { } void FakePointerController::fade(Transition) { + if (!mEnabled) return; + mIsPointerShown = false; } void FakePointerController::unfade(Transition) { + if (!mEnabled) return; + mIsPointerShown = true; } void FakePointerController::setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits, int32_t displayId) { + if (!mEnabled) return; + std::vector<int32_t> newSpots; // Add spots for fingers that are down. for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) { @@ -146,6 +164,8 @@ void FakePointerController::setSpots(const PointerCoords*, const uint32_t*, BitS } void FakePointerController::clearSpots() { + if (!mEnabled) return; + mSpotsByDisplay.clear(); } diff --git a/services/inputflinger/tests/FakePointerController.h b/services/inputflinger/tests/FakePointerController.h index 061ae62b57..536b447215 100644 --- a/services/inputflinger/tests/FakePointerController.h +++ b/services/inputflinger/tests/FakePointerController.h @@ -30,6 +30,9 @@ struct SpriteIcon { class FakePointerController : public PointerControllerInterface { public: + FakePointerController() : FakePointerController(/*enabled=*/true) {} + FakePointerController(bool enabled) : mEnabled(enabled) {} + virtual ~FakePointerController() {} void setBounds(float minX, float minY, float maxX, float maxY); @@ -64,6 +67,7 @@ private: int32_t displayId) override; void clearSpots() override; + const bool mEnabled; bool mHaveBounds{false}; float mMinX{0}, mMinY{0}, mMaxX{0}, mMaxY{0}; float mX{0}, mY{0}; diff --git a/services/inputflinger/tests/GestureConverter_test.cpp b/services/inputflinger/tests/GestureConverter_test.cpp index ca9ef8e0ef..337b52b677 100644 --- a/services/inputflinger/tests/GestureConverter_test.cpp +++ b/services/inputflinger/tests/GestureConverter_test.cpp @@ -69,7 +69,8 @@ protected: mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, -500, 500, 0, 0, 20); mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, -500, 500, 0, 0, 20); - mFakePointerController = std::make_shared<FakePointerController>(); + mFakePointerController = std::make_shared<FakePointerController>( + /*enabled=*/!input_flags::enable_pointer_choreographer()); mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1); mFakePointerController->setPosition(POINTER_X, POINTER_Y); mFakePolicy->setPointerController(mFakePointerController); diff --git a/services/inputflinger/tests/TouchpadInputMapper_test.cpp b/services/inputflinger/tests/TouchpadInputMapper_test.cpp index fbafbadb44..a92dce5dd0 100644 --- a/services/inputflinger/tests/TouchpadInputMapper_test.cpp +++ b/services/inputflinger/tests/TouchpadInputMapper_test.cpp @@ -117,8 +117,11 @@ protected: return base::ResultError("Axis not supported", NAME_NOT_FOUND); }); createDevice(); - mMapper = createInputMapper<TouchpadInputMapper>(*mDeviceContext, mReaderConfiguration); + mMapper = createInputMapper<TouchpadInputMapper>(*mDeviceContext, mReaderConfiguration, + isPointerChoreographerEnabled()); } + + virtual bool isPointerChoreographerEnabled() { return false; } }; class TouchpadInputMapperTest : public TouchpadInputMapperTestBase { @@ -182,10 +185,9 @@ TEST_F(TouchpadInputMapperTest, HoverAndLeftButtonPress) { class TouchpadInputMapperTestWithChoreographer : public TouchpadInputMapperTestBase { protected: - void SetUp() override { - input_flags::enable_pointer_choreographer(true); - TouchpadInputMapperTestBase::SetUp(); - } + void SetUp() override { TouchpadInputMapperTestBase::SetUp(); } + + bool isPointerChoreographerEnabled() override { return true; } }; // TODO(b/311416205): De-duplicate the test cases after the refactoring is complete and the flagging diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp index 1f72e8ba2c..3ea08febfd 100644 --- a/services/powermanager/Android.bp +++ b/services/powermanager/Android.bp @@ -17,6 +17,7 @@ cc_library_shared { "PowerHalController.cpp", "PowerHalLoader.cpp", "PowerHalWrapper.cpp", + "PowerHintSessionWrapper.cpp", "PowerSaveState.cpp", "Temperature.cpp", "WorkDuration.cpp", diff --git a/services/powermanager/PowerHalController.cpp b/services/powermanager/PowerHalController.cpp index bc178bce8f..40fd097491 100644 --- a/services/powermanager/PowerHalController.cpp +++ b/services/powermanager/PowerHalController.cpp @@ -57,6 +57,10 @@ void HalConnector::reset() { PowerHalLoader::unloadAll(); } +int32_t HalConnector::getAidlVersion() { + return PowerHalLoader::getAidlVersion(); +} + // ------------------------------------------------------------------------------------------------- void PowerHalController::init() { @@ -77,6 +81,22 @@ std::shared_ptr<HalWrapper> PowerHalController::initHal() { return mConnectedHal; } +// Using statement expression macro instead of a method lets the static be +// scoped to the outer method while dodging the need for a support lookup table +// This only works for AIDL methods that do not vary supported/unsupported depending +// on their arguments (not setBoost, setMode) which do their own support checks +#define CACHE_SUPPORT(version, method) \ + ({ \ + static bool support = mHalConnector->getAidlVersion() >= version; \ + !support ? decltype(method)::unsupported() : ({ \ + auto result = method; \ + if (result.isUnsupported()) { \ + support = false; \ + } \ + std::move(result); \ + }); \ + }) + // Check if a call to Power HAL function failed; if so, log the failure and // invalidate the current Power HAL handle. template <typename T> @@ -103,40 +123,49 @@ HalResult<void> PowerHalController::setMode(aidl::android::hardware::power::Mode return processHalResult(handle->setMode(mode, enabled), "setMode"); } -HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> -PowerHalController::createHintSession(int32_t tgid, int32_t uid, - const std::vector<int32_t>& threadIds, - int64_t durationNanos) { +// Aidl-only methods + +HalResult<std::shared_ptr<PowerHintSessionWrapper>> PowerHalController::createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) { std::shared_ptr<HalWrapper> handle = initHal(); - return processHalResult(handle->createHintSession(tgid, uid, threadIds, durationNanos), - "createHintSession"); + return CACHE_SUPPORT(2, + processHalResult(handle->createHintSession(tgid, uid, threadIds, + durationNanos), + "createHintSession")); } -HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>> -PowerHalController::createHintSessionWithConfig( +HalResult<std::shared_ptr<PowerHintSessionWrapper>> PowerHalController::createHintSessionWithConfig( int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos, aidl::android::hardware::power::SessionTag tag, aidl::android::hardware::power::SessionConfig* config) { std::shared_ptr<HalWrapper> handle = initHal(); - return processHalResult(handle->createHintSessionWithConfig(tgid, uid, threadIds, durationNanos, - tag, config), - "createHintSessionWithConfig"); + return CACHE_SUPPORT(5, + processHalResult(handle->createHintSessionWithConfig(tgid, uid, threadIds, + durationNanos, tag, + config), + "createHintSessionWithConfig")); } HalResult<int64_t> PowerHalController::getHintSessionPreferredRate() { std::shared_ptr<HalWrapper> handle = initHal(); - return processHalResult(handle->getHintSessionPreferredRate(), "getHintSessionPreferredRate"); + return CACHE_SUPPORT(2, + processHalResult(handle->getHintSessionPreferredRate(), + "getHintSessionPreferredRate")); } HalResult<aidl::android::hardware::power::ChannelConfig> PowerHalController::getSessionChannel( int tgid, int uid) { std::shared_ptr<HalWrapper> handle = initHal(); - return processHalResult(handle->getSessionChannel(tgid, uid), "getSessionChannel"); + return CACHE_SUPPORT(5, + processHalResult(handle->getSessionChannel(tgid, uid), + "getSessionChannel")); } HalResult<void> PowerHalController::closeSessionChannel(int tgid, int uid) { std::shared_ptr<HalWrapper> handle = initHal(); - return processHalResult(handle->closeSessionChannel(tgid, uid), "closeSessionChannel"); + return CACHE_SUPPORT(5, + processHalResult(handle->closeSessionChannel(tgid, uid), + "closeSessionChannel")); } } // namespace power diff --git a/services/powermanager/PowerHalLoader.cpp b/services/powermanager/PowerHalLoader.cpp index 22144615da..ea284c36d8 100644 --- a/services/powermanager/PowerHalLoader.cpp +++ b/services/powermanager/PowerHalLoader.cpp @@ -60,6 +60,7 @@ sp<V1_0::IPower> PowerHalLoader::gHalHidlV1_0 = nullptr; sp<V1_1::IPower> PowerHalLoader::gHalHidlV1_1 = nullptr; sp<V1_2::IPower> PowerHalLoader::gHalHidlV1_2 = nullptr; sp<V1_3::IPower> PowerHalLoader::gHalHidlV1_3 = nullptr; +int32_t PowerHalLoader::gAidlInterfaceVersion = 0; void PowerHalLoader::unloadAll() { std::lock_guard<std::mutex> lock(gHalMutex); @@ -89,6 +90,8 @@ std::shared_ptr<aidl::android::hardware::power::IPower> PowerHalLoader::loadAidl ndk::SpAIBinder(AServiceManager_waitForService(aidlServiceName.c_str()))); if (gHalAidl) { ALOGI("Successfully connected to Power HAL AIDL service."); + gHalAidl->getInterfaceVersion(&gAidlInterfaceVersion); + } else { ALOGI("Power HAL AIDL service not available."); gHalExists = false; @@ -128,6 +131,10 @@ sp<V1_0::IPower> PowerHalLoader::loadHidlV1_0Locked() { return loadHal<V1_0::IPower>(gHalExists, gHalHidlV1_0, loadFn, "HIDL v1.0"); } +int32_t PowerHalLoader::getAidlVersion() { + return gAidlInterfaceVersion; +} + // ------------------------------------------------------------------------------------------------- } // namespace power diff --git a/services/powermanager/PowerHalWrapper.cpp b/services/powermanager/PowerHalWrapper.cpp index 1009100cc2..bd6685cbad 100644 --- a/services/powermanager/PowerHalWrapper.cpp +++ b/services/powermanager/PowerHalWrapper.cpp @@ -18,11 +18,10 @@ #include <aidl/android/hardware/power/Boost.h> #include <aidl/android/hardware/power/IPowerHintSession.h> #include <aidl/android/hardware/power/Mode.h> +#include <powermanager/HalResult.h> #include <powermanager/PowerHalWrapper.h> #include <utils/Log.h> -#include <cinttypes> - using namespace android::hardware::power; namespace Aidl = aidl::android::hardware::power; @@ -31,15 +30,6 @@ namespace android { namespace power { // ------------------------------------------------------------------------------------------------- -inline HalResult<void> toHalResult(const ndk::ScopedAStatus& result) { - if (result.isOk()) { - return HalResult<void>::ok(); - } - ALOGE("Power HAL request failed: %s", result.getDescription().c_str()); - return HalResult<void>::failed(result.getDescription()); -} - -// ------------------------------------------------------------------------------------------------- HalResult<void> EmptyHalWrapper::setBoost(Aidl::Boost boost, int32_t durationMs) { ALOGV("Skipped setBoost %s with duration %dms because %s", toString(boost).c_str(), durationMs, @@ -53,19 +43,19 @@ HalResult<void> EmptyHalWrapper::setMode(Aidl::Mode mode, bool enabled) { return HalResult<void>::unsupported(); } -HalResult<std::shared_ptr<Aidl::IPowerHintSession>> EmptyHalWrapper::createHintSession( +HalResult<std::shared_ptr<PowerHintSessionWrapper>> EmptyHalWrapper::createHintSession( int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t) { ALOGV("Skipped createHintSession(task num=%zu) because %s", threadIds.size(), getUnsupportedMessage()); - return HalResult<std::shared_ptr<Aidl::IPowerHintSession>>::unsupported(); + return HalResult<std::shared_ptr<PowerHintSessionWrapper>>::unsupported(); } -HalResult<std::shared_ptr<Aidl::IPowerHintSession>> EmptyHalWrapper::createHintSessionWithConfig( +HalResult<std::shared_ptr<PowerHintSessionWrapper>> EmptyHalWrapper::createHintSessionWithConfig( int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t, Aidl::SessionTag, Aidl::SessionConfig*) { ALOGV("Skipped createHintSessionWithConfig(task num=%zu) because %s", threadIds.size(), getUnsupportedMessage()); - return HalResult<std::shared_ptr<Aidl::IPowerHintSession>>::unsupported(); + return HalResult<std::shared_ptr<PowerHintSessionWrapper>>::unsupported(); } HalResult<int64_t> EmptyHalWrapper::getHintSessionPreferredRate() { @@ -225,7 +215,7 @@ HalResult<void> AidlHalWrapper::setBoost(Aidl::Boost boost, int32_t durationMs) } lock.unlock(); - return toHalResult(mHandle->setBoost(boost, durationMs)); + return HalResult<void>::fromStatus(mHandle->setBoost(boost, durationMs)); } HalResult<void> AidlHalWrapper::setMode(Aidl::Mode mode, bool enabled) { @@ -253,25 +243,25 @@ HalResult<void> AidlHalWrapper::setMode(Aidl::Mode mode, bool enabled) { } lock.unlock(); - return toHalResult(mHandle->setMode(mode, enabled)); + return HalResult<void>::fromStatus(mHandle->setMode(mode, enabled)); } -HalResult<std::shared_ptr<Aidl::IPowerHintSession>> AidlHalWrapper::createHintSession( +HalResult<std::shared_ptr<PowerHintSessionWrapper>> AidlHalWrapper::createHintSession( int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) { std::shared_ptr<Aidl::IPowerHintSession> appSession; - return HalResult<std::shared_ptr<Aidl::IPowerHintSession>>:: + return HalResult<std::shared_ptr<PowerHintSessionWrapper>>:: fromStatus(mHandle->createHintSession(tgid, uid, threadIds, durationNanos, &appSession), - std::move(appSession)); + std::make_shared<PowerHintSessionWrapper>(std::move(appSession))); } -HalResult<std::shared_ptr<Aidl::IPowerHintSession>> AidlHalWrapper::createHintSessionWithConfig( +HalResult<std::shared_ptr<PowerHintSessionWrapper>> AidlHalWrapper::createHintSessionWithConfig( int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos, Aidl::SessionTag tag, Aidl::SessionConfig* config) { std::shared_ptr<Aidl::IPowerHintSession> appSession; - return HalResult<std::shared_ptr<Aidl::IPowerHintSession>>:: + return HalResult<std::shared_ptr<PowerHintSessionWrapper>>:: fromStatus(mHandle->createHintSessionWithConfig(tgid, uid, threadIds, durationNanos, tag, config, &appSession), - std::move(appSession)); + std::make_shared<PowerHintSessionWrapper>(std::move(appSession))); } HalResult<int64_t> AidlHalWrapper::getHintSessionPreferredRate() { @@ -287,7 +277,7 @@ HalResult<Aidl::ChannelConfig> AidlHalWrapper::getSessionChannel(int tgid, int u } HalResult<void> AidlHalWrapper::closeSessionChannel(int tgid, int uid) { - return toHalResult(mHandle->closeSessionChannel(tgid, uid)); + return HalResult<void>::fromStatus(mHandle->closeSessionChannel(tgid, uid)); } const char* AidlHalWrapper::getUnsupportedMessage() { diff --git a/services/powermanager/PowerHintSessionWrapper.cpp b/services/powermanager/PowerHintSessionWrapper.cpp new file mode 100644 index 0000000000..930c7fa2b8 --- /dev/null +++ b/services/powermanager/PowerHintSessionWrapper.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <powermanager/PowerHintSessionWrapper.h> + +using namespace aidl::android::hardware::power; + +namespace android::power { + +// Caches support for a given call in a static variable, checking both +// the return value and interface version. +#define CACHE_SUPPORT(version, method) \ + ({ \ + static bool support = mInterfaceVersion >= version; \ + !support ? decltype(method)::unsupported() : ({ \ + auto result = method; \ + if (result.isUnsupported()) { \ + support = false; \ + } \ + std::move(result); \ + }); \ + }) + +#define CHECK_SESSION(resultType) \ + if (mSession == nullptr) { \ + return HalResult<resultType>::failed("Session not running"); \ + } + +// FWD_CALL just forwards calls from the wrapper to the session object. +// It only works if the call has no return object, as is the case with all calls +// except getSessionConfig. +#define FWD_CALL(version, name, args, untypedArgs) \ + HalResult<void> PowerHintSessionWrapper::name args { \ + CHECK_SESSION(void) \ + return CACHE_SUPPORT(version, HalResult<void>::fromStatus(mSession->name untypedArgs)); \ + } + +PowerHintSessionWrapper::PowerHintSessionWrapper(std::shared_ptr<IPowerHintSession>&& session) + : mSession(session) { + if (mSession != nullptr) { + mSession->getInterfaceVersion(&mInterfaceVersion); + } +} + +// Support for individual hints/modes is not really handled here since there +// is no way to check for it, so in the future if a way to check that is added, +// this will need to be updated. + +FWD_CALL(2, updateTargetWorkDuration, (int64_t in_targetDurationNanos), (in_targetDurationNanos)); +FWD_CALL(2, reportActualWorkDuration, (const std::vector<WorkDuration>& in_durations), + (in_durations)); +FWD_CALL(2, pause, (), ()); +FWD_CALL(2, resume, (), ()); +FWD_CALL(2, close, (), ()); +FWD_CALL(4, sendHint, (SessionHint in_hint), (in_hint)); +FWD_CALL(4, setThreads, (const std::vector<int32_t>& in_threadIds), (in_threadIds)); +FWD_CALL(5, setMode, (SessionMode in_type, bool in_enabled), (in_type, in_enabled)); + +HalResult<SessionConfig> PowerHintSessionWrapper::getSessionConfig() { + CHECK_SESSION(SessionConfig); + SessionConfig config; + return CACHE_SUPPORT(5, + HalResult<SessionConfig>::fromStatus(mSession->getSessionConfig(&config), + std::move(config))); +} + +} // namespace android::power diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp index 6fc96c0959..a05ce2b39c 100644 --- a/services/powermanager/tests/Android.bp +++ b/services/powermanager/tests/Android.bp @@ -37,6 +37,7 @@ cc_test { "PowerHalWrapperHidlV1_1Test.cpp", "PowerHalWrapperHidlV1_2Test.cpp", "PowerHalWrapperHidlV1_3Test.cpp", + "PowerHintSessionWrapperTest.cpp", "WorkSourceTest.cpp", ], cflags: [ diff --git a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp index a7202969ad..1589c9937d 100644 --- a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp +++ b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp @@ -86,6 +86,10 @@ protected: void PowerHalWrapperAidlTest::SetUp() { mMockHal = ndk::SharedRefBase::make<StrictMock<MockIPower>>(); + EXPECT_CALL(*mMockHal, getInterfaceVersion(_)).WillRepeatedly(([](int32_t* ret) { + *ret = 5; + return ndk::ScopedAStatus::ok(); + })); mWrapper = std::make_unique<AidlHalWrapper>(mMockHal); ASSERT_NE(nullptr, mWrapper); } @@ -130,10 +134,12 @@ TEST_F(PowerHalWrapperAidlTest, TestSetBoostFailed) { } TEST_F(PowerHalWrapperAidlTest, TestSetBoostUnsupported) { - EXPECT_CALL(*mMockHal.get(), isBoostSupported(Eq(Boost::INTERACTION), _)) - .Times(Exactly(1)) - .WillOnce(DoAll(SetArgPointee<1>(false), - Return(testing::ByMove(ndk::ScopedAStatus::ok())))); + EXPECT_CALL(*mMockHal.get(), isBoostSupported(_, _)) + .Times(Exactly(2)) + .WillRepeatedly([](Boost, bool* ret) { + *ret = false; + return ndk::ScopedAStatus::ok(); + }); auto result = mWrapper->setBoost(Boost::INTERACTION, 1000); ASSERT_TRUE(result.isUnsupported()); @@ -311,3 +317,29 @@ TEST_F(PowerHalWrapperAidlTest, TestSessionChannel) { auto closeResult = mWrapper->closeSessionChannel(tgid, uid); ASSERT_TRUE(closeResult.isOk()); } + +TEST_F(PowerHalWrapperAidlTest, TestCreateHintSessionWithConfigUnsupported) { + std::vector<int> threadIds{gettid()}; + int32_t tgid = 999; + int32_t uid = 1001; + int64_t durationNanos = 16666666L; + SessionTag tag = SessionTag::OTHER; + SessionConfig out; + EXPECT_CALL(*mMockHal.get(), + createHintSessionWithConfig(Eq(tgid), Eq(uid), Eq(threadIds), Eq(durationNanos), + Eq(tag), _, _)) + .Times(1) + .WillOnce(Return(testing::ByMove( + ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)))); + auto result = + mWrapper->createHintSessionWithConfig(tgid, uid, threadIds, durationNanos, tag, &out); + ASSERT_TRUE(result.isUnsupported()); + Mock::VerifyAndClearExpectations(mMockHal.get()); + EXPECT_CALL(*mMockHal.get(), + createHintSessionWithConfig(Eq(tgid), Eq(uid), Eq(threadIds), Eq(durationNanos), + Eq(tag), _, _)) + .WillOnce(Return( + testing::ByMove(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)))); + result = mWrapper->createHintSessionWithConfig(tgid, uid, threadIds, durationNanos, tag, &out); + ASSERT_TRUE(result.isUnsupported()); +} diff --git a/services/powermanager/tests/PowerHintSessionWrapperTest.cpp b/services/powermanager/tests/PowerHintSessionWrapperTest.cpp new file mode 100644 index 0000000000..7743fa4363 --- /dev/null +++ b/services/powermanager/tests/PowerHintSessionWrapperTest.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <aidl/android/hardware/power/IPowerHintSession.h> +#include <powermanager/PowerHintSessionWrapper.h> + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +using aidl::android::hardware::power::IPowerHintSession; +using android::power::PowerHintSessionWrapper; + +using namespace android; +using namespace std::chrono_literals; +using namespace testing; + +class MockIPowerHintSession : public IPowerHintSession { +public: + MockIPowerHintSession() = default; + MOCK_METHOD(::ndk::ScopedAStatus, updateTargetWorkDuration, (int64_t in_targetDurationNanos), + (override)); + MOCK_METHOD(::ndk::ScopedAStatus, reportActualWorkDuration, + (const std::vector<::aidl::android::hardware::power::WorkDuration>& in_durations), + (override)); + MOCK_METHOD(::ndk::ScopedAStatus, pause, (), (override)); + MOCK_METHOD(::ndk::ScopedAStatus, resume, (), (override)); + MOCK_METHOD(::ndk::ScopedAStatus, close, (), (override)); + MOCK_METHOD(::ndk::ScopedAStatus, sendHint, + (::aidl::android::hardware::power::SessionHint in_hint), (override)); + MOCK_METHOD(::ndk::ScopedAStatus, setThreads, (const std::vector<int32_t>& in_threadIds), + (override)); + MOCK_METHOD(::ndk::ScopedAStatus, setMode, + (::aidl::android::hardware::power::SessionMode in_type, bool in_enabled), + (override)); + MOCK_METHOD(::ndk::ScopedAStatus, getSessionConfig, + (::aidl::android::hardware::power::SessionConfig * _aidl_return), (override)); + MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceVersion, (int32_t * _aidl_return), (override)); + MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceHash, (std::string * _aidl_return), (override)); + MOCK_METHOD(::ndk::SpAIBinder, asBinder, (), (override)); + MOCK_METHOD(bool, isRemote, (), (override)); +}; + +class PowerHintSessionWrapperTest : public Test { +public: + void SetUp() override; + +protected: + std::shared_ptr<NiceMock<MockIPowerHintSession>> mMockSession = nullptr; + std::unique_ptr<PowerHintSessionWrapper> mSession = nullptr; +}; + +void PowerHintSessionWrapperTest::SetUp() { + mMockSession = ndk::SharedRefBase::make<NiceMock<MockIPowerHintSession>>(); + EXPECT_CALL(*mMockSession, getInterfaceVersion(_)).WillRepeatedly(([](int32_t* ret) { + *ret = 5; + return ndk::ScopedAStatus::ok(); + })); + mSession = std::make_unique<PowerHintSessionWrapper>(mMockSession); + ASSERT_NE(nullptr, mSession); +} + +TEST_F(PowerHintSessionWrapperTest, updateTargetWorkDuration) { + EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(1000000000)) + .WillOnce(Return(ndk::ScopedAStatus::ok())); + auto status = mSession->updateTargetWorkDuration(1000000000); + ASSERT_TRUE(status.isOk()); +} + +TEST_F(PowerHintSessionWrapperTest, reportActualWorkDuration) { + EXPECT_CALL(*mMockSession.get(), + reportActualWorkDuration( + std::vector<::aidl::android::hardware::power::WorkDuration>())) + .WillOnce(Return(ndk::ScopedAStatus::ok())); + auto status = mSession->reportActualWorkDuration( + std::vector<::aidl::android::hardware::power::WorkDuration>()); + ASSERT_TRUE(status.isOk()); +} + +TEST_F(PowerHintSessionWrapperTest, pause) { + EXPECT_CALL(*mMockSession.get(), pause()).WillOnce(Return(ndk::ScopedAStatus::ok())); + auto status = mSession->pause(); + ASSERT_TRUE(status.isOk()); +} + +TEST_F(PowerHintSessionWrapperTest, resume) { + EXPECT_CALL(*mMockSession.get(), resume()).WillOnce(Return(ndk::ScopedAStatus::ok())); + auto status = mSession->resume(); + ASSERT_TRUE(status.isOk()); +} + +TEST_F(PowerHintSessionWrapperTest, close) { + EXPECT_CALL(*mMockSession.get(), close()).WillOnce(Return(ndk::ScopedAStatus::ok())); + auto status = mSession->close(); + ASSERT_TRUE(status.isOk()); +} + +TEST_F(PowerHintSessionWrapperTest, sendHint) { + EXPECT_CALL(*mMockSession.get(), + sendHint(::aidl::android::hardware::power::SessionHint::CPU_LOAD_UP)) + .WillOnce(Return(ndk::ScopedAStatus::ok())); + auto status = mSession->sendHint(::aidl::android::hardware::power::SessionHint::CPU_LOAD_UP); + ASSERT_TRUE(status.isOk()); +} + +TEST_F(PowerHintSessionWrapperTest, setThreads) { + EXPECT_CALL(*mMockSession.get(), setThreads(_)).WillOnce(Return(ndk::ScopedAStatus::ok())); + auto status = mSession->setThreads(std::vector<int32_t>{gettid()}); + ASSERT_TRUE(status.isOk()); +} + +TEST_F(PowerHintSessionWrapperTest, setMode) { + EXPECT_CALL(*mMockSession.get(), + setMode(::aidl::android::hardware::power::SessionMode::POWER_EFFICIENCY, true)) + .WillOnce(Return(ndk::ScopedAStatus::ok())); + auto status = mSession->setMode(::aidl::android::hardware::power::SessionMode::POWER_EFFICIENCY, + true); + ASSERT_TRUE(status.isOk()); +} + +TEST_F(PowerHintSessionWrapperTest, getSessionConfig) { + EXPECT_CALL(*mMockSession.get(), getSessionConfig(_)) + .WillOnce(DoAll(SetArgPointee<0>( + aidl::android::hardware::power::SessionConfig{.id = 12L}), + Return(ndk::ScopedAStatus::ok()))); + auto status = mSession->getSessionConfig(); + ASSERT_TRUE(status.isOk()); +} diff --git a/services/sensorservice/AidlSensorHalWrapper.cpp b/services/sensorservice/AidlSensorHalWrapper.cpp index e60db93431..91c2d1f3be 100644 --- a/services/sensorservice/AidlSensorHalWrapper.cpp +++ b/services/sensorservice/AidlSensorHalWrapper.cpp @@ -178,6 +178,11 @@ ssize_t AidlSensorHalWrapper::pollFmq(sensors_event_t *buffer, size_t maxNumEven if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) { ALOGD("Event FMQ internal wake, returning from poll with no events"); return DEAD_OBJECT; + } else if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mInHalBypassMode && + availableEvents == 0) { + ALOGD("Event FMQ internal wake due to HAL Bypass Mode, returning from poll with no " + "events"); + return OK; } } @@ -221,6 +226,17 @@ std::vector<sensor_t> AidlSensorHalWrapper::getSensorsList() { status_t AidlSensorHalWrapper::setOperationMode(SensorService::Mode mode) { if (mSensors == nullptr) return NO_INIT; + if (mode == SensorService::Mode::HAL_BYPASS_REPLAY_DATA_INJECTION) { + if (!mInHalBypassMode) { + mInHalBypassMode = true; + mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE)); + } + return OK; + } else { + if (mInHalBypassMode) { + mInHalBypassMode = false; + } + } return convertToStatus(mSensors->setOperationMode(static_cast<ISensors::OperationMode>(mode))); } diff --git a/services/sensorservice/HidlSensorHalWrapper.cpp b/services/sensorservice/HidlSensorHalWrapper.cpp index c55c9b4748..8c867bdd32 100644 --- a/services/sensorservice/HidlSensorHalWrapper.cpp +++ b/services/sensorservice/HidlSensorHalWrapper.cpp @@ -203,6 +203,11 @@ ssize_t HidlSensorHalWrapper::pollFmq(sensors_event_t* buffer, size_t maxNumEven if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) { ALOGD("Event FMQ internal wake, returning from poll with no events"); return DEAD_OBJECT; + } else if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mInHalBypassMode && + availableEvents == 0) { + ALOGD("Event FMQ internal wake due to HAL Bypass Mode, returning from poll with no " + "events"); + return OK; } } @@ -251,6 +256,17 @@ std::vector<sensor_t> HidlSensorHalWrapper::getSensorsList() { status_t HidlSensorHalWrapper::setOperationMode(SensorService::Mode mode) { if (mSensors == nullptr) return NO_INIT; + if (mode == SensorService::Mode::HAL_BYPASS_REPLAY_DATA_INJECTION) { + if (!mInHalBypassMode) { + mInHalBypassMode = true; + mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE)); + } + return OK; + } else { + if (mInHalBypassMode) { + mInHalBypassMode = false; + } + } return checkReturnAndGetStatus( mSensors->setOperationMode(static_cast<hardware::sensors::V1_0::OperationMode>(mode))); } diff --git a/services/sensorservice/ISensorHalWrapper.h b/services/sensorservice/ISensorHalWrapper.h index 3d33540c18..891dfe5a77 100644 --- a/services/sensorservice/ISensorHalWrapper.h +++ b/services/sensorservice/ISensorHalWrapper.h @@ -97,6 +97,8 @@ public: virtual void writeWakeLockHandled(uint32_t count) = 0; std::atomic_bool mReconnecting = false; + + std::atomic_bool mInHalBypassMode = false; }; } // namespace android diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index 8e9dfea65e..f62562ce9d 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -812,7 +812,6 @@ status_t SensorDevice::setMode(uint32_t mode) { } mInHalBypassMode = true; } - return OK; } else { if (mInHalBypassMode) { // We are transitioning out of HAL Bypass mode. We need to notify the reader thread diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 118d9281fc..bd54d24a9f 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -340,8 +340,8 @@ private: binder::Status onSensorPrivacyChanged(int toggleType, int sensor, bool enabled); - // This callback is used for additional automotive-specific states for sensor privacy - // such as AUTO_DRIVER_ASSISTANCE_APPS. The newly defined states will only be valid + // This callback is used for additional automotive-specific state for sensor privacy + // such as ENABLED_EXCEPT_ALLOWLISTED_APPS. The newly defined states will only be valid // for camera privacy on automotive devices. onSensorPrivacyChanged() will still be // invoked whenever the enabled status of a toggle changes. binder::Status onSensorPrivacyStateChanged(int, int, int) {return binder::Status::ok();} diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 6a0ea221cc..d77180362b 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -12,7 +12,10 @@ aconfig_declarations { name: "surfaceflinger_flags", package: "com.android.graphics.surfaceflinger.flags", container: "system", - srcs: ["surfaceflinger_flags.aconfig"], + srcs: [ + "surfaceflinger_flags.aconfig", + "surfaceflinger_flags_new.aconfig", + ], } cc_aconfig_library { @@ -42,6 +45,7 @@ cc_defaults { "android.hardware.power-ndk_shared", "librenderengine_deps", "libtimestats_deps", + "libsurfaceflinger_common_deps", "surfaceflinger_defaults", ], cflags: [ @@ -82,7 +86,6 @@ cc_defaults { "libinput", "libutils", "libSurfaceFlingerProp", - "server_configurable_flags", ], static_libs: [ "libaidlcommonsupport", @@ -95,10 +98,8 @@ cc_defaults { "libscheduler", "libserviceutils", "libshaders", - "libsurfaceflinger_common", "libtimestats", "libtonemap", - "libsurfaceflingerflags", ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 0b01c666a4..a52cc87e7b 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -38,7 +38,6 @@ cc_defaults { "libSurfaceFlingerProp", "libui", "libutils", - "server_configurable_flags", ], static_libs: [ "liblayers_proto", @@ -90,24 +89,23 @@ filegroup { cc_library { name: "libcompositionengine", - defaults: ["libcompositionengine_defaults"], - static_libs: [ - "libsurfaceflinger_common", - "libsurfaceflingerflags", + defaults: [ + "libcompositionengine_defaults", + "libsurfaceflinger_common_deps", ], srcs: [ ":libcompositionengine_sources", ], local_include_dirs: ["include"], export_include_dirs: ["include"], - shared_libs: [ - "server_configurable_flags", - ], } cc_library { name: "libcompositionengine_mocks", - defaults: ["libcompositionengine_defaults"], + defaults: [ + "libcompositionengine_defaults", + "libsurfaceflinger_common_test_deps", + ], srcs: [ "mock/CompositionEngine.cpp", "mock/Display.cpp", @@ -123,11 +121,6 @@ cc_library { "libgtest", "libgmock", "libcompositionengine", - "libsurfaceflinger_common_test", - "libsurfaceflingerflags_test", - ], - shared_libs: [ - "server_configurable_flags", ], local_include_dirs: ["include"], export_include_dirs: ["include"], @@ -140,7 +133,10 @@ cc_test { "frameworks/native/services/surfaceflinger/common/include", "frameworks/native/services/surfaceflinger/tests/unittests", ], - defaults: ["libcompositionengine_defaults"], + defaults: [ + "libcompositionengine_defaults", + "libsurfaceflinger_common_test_deps", + ], srcs: [ ":libcompositionengine_sources", "tests/planner/CachedSetTest.cpp", @@ -166,14 +162,11 @@ cc_test { "librenderengine_mocks", "libgmock", "libgtest", - "libsurfaceflinger_common_test", - "libsurfaceflingerflags_test", ], shared_libs: [ // For some reason, libvulkan isn't picked up from librenderengine // Probably ASAN related? "libvulkan", - "server_configurable_flags", ], sanitize: { hwaddress: true, diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 1c2f6cb686..921e05dfb2 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1276,7 +1276,9 @@ void Output::updateProtectedContentState() { if (isProtected && supportsProtectedContent) { auto layers = getOutputLayersOrderedByZ(); bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) { - return layer->getLayerFE().getCompositionState()->hasProtectedContent; + return layer->getLayerFE().getCompositionState()->hasProtectedContent && + (!FlagManager::getInstance().protected_if_client() || + layer->requiresClientComposition()); }); if (needsProtected != mRenderSurface->isProtected()) { mRenderSurface->setProtected(needsProtected); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 62cfaf412c..799c7edebd 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -4051,6 +4051,7 @@ struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeS Layer() { EXPECT_CALL(*mLayerFE, getCompositionState()).WillRepeatedly(Return(&mLayerFEState)); EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(*mLayerFE)); + EXPECT_CALL(mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); } StrictMock<mock::OutputLayer> mOutputLayer; @@ -4091,6 +4092,7 @@ struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeS }; TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) { + SET_FLAG_FOR_TEST(flags::protected_if_client, true); if (FlagManager::getInstance().display_protected()) { mOutput.mState.isProtected = true; } else { @@ -4109,6 +4111,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLa } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) { + SET_FLAG_FOR_TEST(flags::protected_if_client, true); if (FlagManager::getInstance().display_protected()) { mOutput.mState.isProtected = true; } else { @@ -4135,6 +4138,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) { } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) { + SET_FLAG_FOR_TEST(flags::protected_if_client, true); if (FlagManager::getInstance().display_protected()) { mOutput.mState.isProtected = true; } else { @@ -4152,6 +4156,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEveryw } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) { + SET_FLAG_FOR_TEST(flags::protected_if_client, true); if (FlagManager::getInstance().display_protected()) { mOutput.mState.isProtected = true; } else { @@ -5096,5 +5101,79 @@ TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, calledForOneFrame) { mOutput->present(mRefreshArgs); } +/* + * Output::updateProtectedContentState() + */ + +struct OutputUpdateProtectedContentStateTest : public testing::Test { + struct OutputPartialMock : public OutputPartialMockBase { + // Sets up the helper functions called by the function under test to use + // mock implementations. + MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&()); + }; + + OutputUpdateProtectedContentStateTest() { + mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface)); + EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine)); + EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); + EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u)); + EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0)) + .WillRepeatedly(Return(&mLayer1.mOutputLayer)); + EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1)) + .WillRepeatedly(Return(&mLayer2.mOutputLayer)); + } + + struct Layer { + Layer() { + EXPECT_CALL(*mLayerFE, getCompositionState()).WillRepeatedly(Return(&mLayerFEState)); + EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(*mLayerFE)); + } + + StrictMock<mock::OutputLayer> mOutputLayer; + sp<StrictMock<mock::LayerFE>> mLayerFE = sp<StrictMock<mock::LayerFE>>::make(); + LayerFECompositionState mLayerFEState; + }; + + mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>(); + StrictMock<OutputPartialMock> mOutput; + StrictMock<mock::CompositionEngine> mCompositionEngine; + StrictMock<renderengine::mock::RenderEngine> mRenderEngine; + Layer mLayer1; + Layer mLayer2; +}; + +TEST_F(OutputUpdateProtectedContentStateTest, ifProtectedContentLayerComposeByHWC) { + SET_FLAG_FOR_TEST(flags::protected_if_client, true); + if (FlagManager::getInstance().display_protected()) { + mOutput.mState.isProtected = true; + } else { + mOutput.mState.isSecure = true; + } + mLayer1.mLayerFEState.hasProtectedContent = false; + mLayer2.mLayerFEState.hasProtectedContent = true; + EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true)); + EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false)); + EXPECT_CALL(mLayer1.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); + EXPECT_CALL(mLayer2.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); + mOutput.updateProtectedContentState(); +} + +TEST_F(OutputUpdateProtectedContentStateTest, ifProtectedContentLayerComposeByClient) { + SET_FLAG_FOR_TEST(flags::protected_if_client, true); + if (FlagManager::getInstance().display_protected()) { + mOutput.mState.isProtected = true; + } else { + mOutput.mState.isSecure = true; + } + mLayer1.mLayerFEState.hasProtectedContent = false; + mLayer2.mLayerFEState.hasProtectedContent = true; + EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true)); + EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false)); + EXPECT_CALL(*mRenderSurface, setProtected(true)); + EXPECT_CALL(mLayer1.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); + EXPECT_CALL(mLayer2.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); + mOutput.updateProtectedContentState(); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp index a0c943ba72..8dfbeb80cd 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp @@ -233,7 +233,7 @@ void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) { auto ret = mHintSession->updateTargetWorkDuration(targetDuration.ns()); if (!ret.isOk()) { ALOGW("Failed to set power hint target work duration with error: %s", - ret.getDescription().c_str()); + ret.errorMessage()); mHintSession = nullptr; } } @@ -293,8 +293,7 @@ void PowerAdvisor::reportActualWorkDuration() { auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue); if (!ret.isOk()) { - ALOGW("Failed to report actual work durations with error: %s", - ret.getDescription().c_str()); + ALOGW("Failed to report actual work durations with error: %s", ret.errorMessage()); mHintSession = nullptr; return; } diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h index bbe51cc09d..1040048b13 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h @@ -259,8 +259,8 @@ private: std::optional<bool> mSupportsHintSession; std::mutex mHintSessionMutex; - std::shared_ptr<aidl::android::hardware::power::IPowerHintSession> mHintSession - GUARDED_BY(mHintSessionMutex) = nullptr; + std::shared_ptr<power::PowerHintSessionWrapper> mHintSession GUARDED_BY(mHintSessionMutex) = + nullptr; // Initialize to true so we try to call, to check if it's supported bool mHasExpensiveRendering = true; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index c888ccc8ae..77e045d6f9 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -377,8 +377,8 @@ void RegionSamplingThread::captureSample() { constexpr bool kIsProtected = false; if (const auto fenceResult = - mFlinger.captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, buffer, - kRegionSampling, kGrayscale, kIsProtected, nullptr) + mFlinger.captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, buffer, + kRegionSampling, kGrayscale, kIsProtected, nullptr) .get(); fenceResult.ok()) { fenceResult.value()->waitForever(LOG_TAG); diff --git a/services/surfaceflinger/Scheduler/Android.bp b/services/surfaceflinger/Scheduler/Android.bp index 16776cf18a..5455fdc155 100644 --- a/services/surfaceflinger/Scheduler/Android.bp +++ b/services/surfaceflinger/Scheduler/Android.bp @@ -53,7 +53,10 @@ cc_library_static { cc_test { name: "libscheduler_test", test_suites: ["device-tests"], - defaults: ["libscheduler_defaults"], + defaults: [ + "libscheduler_defaults", + "libsurfaceflinger_common_test_deps", + ], srcs: [ "tests/FrameTargeterTest.cpp", "tests/PresentLatencyTrackerTest.cpp", @@ -63,9 +66,5 @@ cc_test { "libgmock", "libgtest", "libscheduler", - "libsurfaceflingerflags_test", - ], - shared_libs: [ - "server_configurable_flags", ], } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index dcb62546a6..b8d5e76358 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -300,12 +300,26 @@ void LayerHistory::partitionLayers(nsecs_t now) { if (gameModeFrameRateOverride.isValid()) { info->setLayerVote({gameFrameRateOverrideVoteType, gameModeFrameRateOverride}); + ATRACE_FORMAT_INSTANT("GameModeFrameRateOverride"); + if (CC_UNLIKELY(mTraceEnabled)) { + trace(*info, gameFrameRateOverrideVoteType, + gameModeFrameRateOverride.getIntValue()); + } } else if (frameRate.isValid()) { info->setLayerVote({setFrameRateVoteType, frameRate.vote.rate, frameRate.vote.seamlessness, frameRate.category}); + if (CC_UNLIKELY(mTraceEnabled)) { + trace(*info, gameFrameRateOverrideVoteType, + frameRate.vote.rate.getIntValue()); + } } else if (gameDefaultFrameRateOverride.isValid()) { info->setLayerVote( {gameFrameRateOverrideVoteType, gameDefaultFrameRateOverride}); + ATRACE_FORMAT_INSTANT("GameDefaultFrameRateOverride"); + if (CC_UNLIKELY(mTraceEnabled)) { + trace(*info, gameFrameRateOverrideVoteType, + gameDefaultFrameRateOverride.getIntValue()); + } } else { info->resetLayerVote(); } @@ -341,9 +355,18 @@ void LayerHistory::clear() { std::string LayerHistory::dump() const { std::lock_guard lock(mLock); - return base::StringPrintf("{size=%zu, active=%zu}", + return base::StringPrintf("{size=%zu, active=%zu}\n\tGameFrameRateOverrides=\n\t\t%s", mActiveLayerInfos.size() + mInactiveLayerInfos.size(), - mActiveLayerInfos.size()); + mActiveLayerInfos.size(), dumpGameFrameRateOverridesLocked().c_str()); +} + +std::string LayerHistory::dumpGameFrameRateOverridesLocked() const { + std::string overridesString = "(uid, gameModeOverride, gameDefaultOverride)="; + for (auto it = mGameFrameRateOverride.begin(); it != mGameFrameRateOverride.end(); ++it) { + base::StringAppendF(&overridesString, "{%u, %d %d} ", it->first, + it->second.first.getIntValue(), it->second.second.getIntValue()); + } + return overridesString; } float LayerHistory::getLayerFramerate(nsecs_t now, int32_t id) const { diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 930d06c8f0..a6f1b56bf2 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -108,6 +108,8 @@ private: // keyed by id as returned from Layer::getSequence() using LayerInfos = std::unordered_map<int32_t, LayerPair>; + std::string dumpGameFrameRateOverridesLocked() const REQUIRES(mLock); + // Iterates over layers maps moving all active layers to mActiveLayerInfos and all inactive // layers to mInactiveLayerInfos. // worst case time complexity is O(2 * inactive + active) diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index e696e8c358..ffd3463296 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -948,17 +948,43 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme const auto layersByUid = groupLayersByUid(layers); UidToFrameRateOverride frameRateOverrides; for (const auto& [uid, layersWithSameUid] : layersByUid) { - // Layers with ExplicitExactOrMultiple expect touch boost - const bool hasExplicitExactOrMultiple = - std::any_of(layersWithSameUid.cbegin(), layersWithSameUid.cend(), - [](const auto& layer) { - return layer->vote == LayerVoteType::ExplicitExactOrMultiple; - }); + // Look for cases that should not have frame rate overrides. + bool hasExplicitExactOrMultiple = false; + bool hasExplicitDefault = false; + bool hasHighHint = false; + for (const auto& layer : layersWithSameUid) { + switch (layer->vote) { + case LayerVoteType::ExplicitExactOrMultiple: + hasExplicitExactOrMultiple = true; + break; + case LayerVoteType::ExplicitDefault: + hasExplicitDefault = true; + break; + case LayerVoteType::ExplicitCategory: + if (layer->frameRateCategory == FrameRateCategory::HighHint) { + hasHighHint = true; + } + break; + default: + // No action + break; + } + if (hasExplicitExactOrMultiple && hasExplicitDefault && hasHighHint) { + break; + } + } + // Layers with ExplicitExactOrMultiple expect touch boost if (globalSignals.touch && hasExplicitExactOrMultiple) { continue; } + // Mirrors getRankedFrameRates. If there is no ExplicitDefault, expect touch boost and + // skip frame rate override. + if (hasHighHint && !hasExplicitDefault) { + continue; + } + for (auto& [_, score] : scoredFrameRates) { score = 0; } @@ -972,6 +998,7 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault && layer->vote != LayerVoteType::ExplicitExactOrMultiple && layer->vote != LayerVoteType::ExplicitExact && + layer->vote != LayerVoteType::ExplicitGte && layer->vote != LayerVoteType::ExplicitCategory, "Invalid layer vote type for frame rate overrides"); for (auto& [fps, score] : scoredFrameRates) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index e6c58a304e..3f9168252b 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -154,9 +154,13 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, if (isNew) { onHardwareVsyncRequest(displayId, false); } + + dispatchHotplug(displayId, Hotplug::Connected); } void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { + dispatchHotplug(displayId, Hotplug::Disconnected); + demotePacesetterDisplay(); std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule; @@ -375,15 +379,18 @@ sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( return connection; } -void Scheduler::onHotplugReceived(Cycle cycle, PhysicalDisplayId displayId, bool connected) { +void Scheduler::dispatchHotplug(PhysicalDisplayId displayId, Hotplug hotplug) { if (hasEventThreads()) { - eventThreadFor(cycle).onHotplugReceived(displayId, connected); + const bool connected = hotplug == Hotplug::Connected; + eventThreadFor(Cycle::Render).onHotplugReceived(displayId, connected); + eventThreadFor(Cycle::LastComposite).onHotplugReceived(displayId, connected); } } -void Scheduler::onHotplugConnectionError(Cycle cycle, int32_t errorCode) { +void Scheduler::dispatchHotplugError(int32_t errorCode) { if (hasEventThreads()) { - eventThreadFor(cycle).onHotplugConnectionError(errorCode); + eventThreadFor(Cycle::Render).onHotplugConnectionError(errorCode); + eventThreadFor(Cycle::LastComposite).onHotplugConnectionError(errorCode); } } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index dc322254c0..09f75fdaca 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -142,8 +142,10 @@ public: return cycle == Cycle::Render ? mRenderEventConnection : mLastCompositeEventConnection; } - void onHotplugReceived(Cycle, PhysicalDisplayId, bool connected); - void onHotplugConnectionError(Cycle, int32_t errorCode); + enum class Hotplug { Connected, Disconnected }; + void dispatchHotplug(PhysicalDisplayId, Hotplug); + + void dispatchHotplugError(int32_t errorCode); void onPrimaryDisplayModeChanged(Cycle, const FrameRateMode&) EXCLUDES(mPolicyLock); void onNonPrimaryDisplayModeChanged(Cycle, const FrameRateMode&); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 08a78cc54a..2501f4b7f7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -854,6 +854,9 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { mCompositionEngine->getHwComposer().setCallback(*this); ClientCache::getInstance().setRenderEngine(&getRenderEngine()); + mHasReliablePresentFences = + !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE); + enableLatchUnsignaledConfig = getLatchUnsignaledConfig(); if (base::GetBoolProperty("debug.sf.enable_hwc_vds"s, false)) { @@ -886,7 +889,6 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { // the DisplayDevice, hence the above commit of the primary display. Remove that special case by // initializing the Scheduler after configureLocked, once decoupled from DisplayDevice. initScheduler(display); - dispatchDisplayHotplugEvent(display->getPhysicalId(), true); mLayerTracing.setTakeLayersSnapshotProtoFunction([&](uint32_t traceFlags) { auto snapshot = perfetto::protos::LayersSnapshotProto{}; @@ -928,9 +930,7 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { // Inform native graphics APIs whether the present timestamp is supported: - const bool presentFenceReliable = - !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE); - mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable); + mStartPropertySetThread = getFactory().createStartPropertySetThread(mHasReliablePresentFences); if (mStartPropertySetThread->Start() != NO_ERROR) { ALOGE("Run StartPropertySetThread failed!"); @@ -1004,9 +1004,7 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps( FrameEvent::RELEASE, }; - ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); - - if (!getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) { + if (mHasReliablePresentFences) { outSupported->push_back(FrameEvent::DISPLAY_PRESENT); } return NO_ERROR; @@ -1756,7 +1754,7 @@ status_t SurfaceFlinger::overrideHdrTypes(const sp<IBinder>& displayToken, } display->overrideHdrTypes(hdrTypes); - dispatchDisplayHotplugEvent(display->getPhysicalId(), true /* connected */); + mScheduler->dispatchHotplug(display->getPhysicalId(), scheduler::Scheduler::Hotplug::Connected); return NO_ERROR; } @@ -2128,10 +2126,9 @@ void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t t vsyncPeriod.has_value()) { // use ~0 instead of -1 as AidlComposerHal.cpp passes the param as unsigned int32 if (mIsHotplugErrViaNegVsync && vsyncPeriod.value() == ~0) { - const int32_t hotplugErrorCode = static_cast<int32_t>(-timestamp); - ALOGD("SurfaceFlinger got hotplugErrorCode=%d for display %" PRIu64, hotplugErrorCode, - hwcDisplayId); - mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, hotplugErrorCode); + const auto errorCode = static_cast<int32_t>(-timestamp); + ALOGD("%s: Hotplug error %d for display %" PRIu64, __func__, errorCode, hwcDisplayId); + mScheduler->dispatchHotplugError(errorCode); return; } @@ -2140,8 +2137,7 @@ void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t t // one byte is good enough to encode android.hardware.drm.HdcpLevel const int32_t maxLevel = (value >> 8) & 0xFF; const int32_t connectedLevel = value & 0xFF; - ALOGD("SurfaceFlinger got HDCP level changed: connected=%d, max=%d for " - "display=%" PRIu64, + ALOGD("%s: HDCP levels changed (connected=%d, max=%d) for display %" PRIu64, __func__, connectedLevel, maxLevel, hwcDisplayId); updateHdcpLevels(hwcDisplayId, connectedLevel, maxLevel); return; @@ -2180,9 +2176,10 @@ void SurfaceFlinger::onComposerHalHotplugEvent(hal::HWDisplayId hwcDisplayId, } if (FlagManager::getInstance().hotplug2()) { - ALOGD("SurfaceFlinger got hotplug event=%d", static_cast<int32_t>(event)); // TODO(b/311403559): use enum type instead of int - mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, static_cast<int32_t>(event)); + const auto errorCode = static_cast<int32_t>(event); + ALOGD("%s: Hotplug error %d for display %" PRIu64, __func__, errorCode, hwcDisplayId); + mScheduler->dispatchHotplugError(errorCode); } } @@ -3033,10 +3030,9 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, // but that should be okay since CompositorTiming has snapping logic. const TimePoint compositeTime = TimePoint::fromNs(mCompositionEngine->getLastFrameRefreshTimestamp()); - const Duration presentLatency = - getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE) - ? Duration::zero() - : mPresentLatencyTracker.trackPendingFrame(compositeTime, pacesetterPresentFenceTime); + const Duration presentLatency = mHasReliablePresentFences + ? mPresentLatencyTracker.trackPendingFrame(compositeTime, pacesetterPresentFenceTime) + : Duration::zero(); const auto schedule = mScheduler->getVsyncSchedule(); const TimePoint vsyncDeadline = schedule->vsyncDeadlineAfter(presentTime); @@ -3476,9 +3472,8 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, if (!activeMode) { ALOGE("Failed to hotplug display %s", to_string(displayId).c_str()); if (FlagManager::getInstance().hotplug2()) { - mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, - static_cast<int32_t>( - DisplayHotplugEvent::ERROR_UNKNOWN)); + mScheduler->dispatchHotplugError( + static_cast<int32_t>(DisplayHotplugEvent::ERROR_UNKNOWN)); } getHwComposer().disconnectDisplay(displayId); return nullptr; @@ -3528,11 +3523,6 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, return "Connecting"; } -void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected) { - mScheduler->onHotplugReceived(scheduler::Cycle::Render, displayId, connected); - mScheduler->onHotplugReceived(scheduler::Cycle::LastComposite, displayId, connected); -} - void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId, const scheduler::FrameRateMode& mode) { // TODO(b/255635821): Merge code paths and move to Scheduler. @@ -3721,16 +3711,11 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, displaySurface, producer); if (mScheduler && !display->isVirtual()) { - const auto displayId = display->getPhysicalId(); - { - // TODO(b/241285876): Annotate `processDisplayAdded` instead. - ftl::FakeGuard guard(kMainThreadContext); + // TODO(b/241285876): Annotate `processDisplayAdded` instead. + ftl::FakeGuard guard(kMainThreadContext); - // For hotplug reconnect, renew the registration since display modes have been reloaded. - mScheduler->registerDisplay(displayId, display->holdRefreshRateSelector()); - } - - dispatchDisplayHotplugEvent(displayId, true); + // For hotplug reconnect, renew the registration since display modes have been reloaded. + mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); } if (display->isVirtual()) { @@ -3769,7 +3754,6 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); } else { - dispatchDisplayHotplugEvent(display->getPhysicalId(), false); mScheduler->unregisterDisplay(display->getPhysicalId()); } } @@ -4371,7 +4355,7 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { features |= Feature::kTracePredictedVsync; } if (!base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false) && - !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) { + mHasReliablePresentFences) { features |= Feature::kPresentFences; } if (display->refreshRateSelector().kernelIdleTimerController()) { @@ -4405,6 +4389,9 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { /* workDuration */ activeRefreshRate.getPeriod(), /* readyDuration */ configs.late.sfWorkDuration); + // Dispatch after EventThread creation, since registerDisplay above skipped dispatch. + mScheduler->dispatchHotplug(display->getPhysicalId(), scheduler::Scheduler::Hotplug::Connected); + mScheduler->initVsync(*mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration); mRegionSamplingThread = @@ -8074,6 +8061,19 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, args.allowProtected, args.grayscale, captureListener); } +bool SurfaceFlinger::layersHasProtectedLayer( + const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const { + bool protectedLayerFound = false; + for (auto& [_, layerFe] : layers) { + protectedLayerFound |= + (layerFe->mSnapshot->isVisible && layerFe->mSnapshot->hasProtectedContent); + if (protectedLayerFound) { + break; + } + } + return protectedLayerFound; +} + void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, @@ -8096,18 +8096,9 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, const bool supportsProtected = getRenderEngine().supportsProtectedContent(); bool hasProtectedLayer = false; if (allowProtected && supportsProtected) { - hasProtectedLayer = mScheduler - ->schedule([=]() { - bool protectedLayerFound = false; - auto layers = getLayerSnapshots(); - for (auto& [_, layerFe] : layers) { - protectedLayerFound |= - (layerFe->mSnapshot->isVisible && - layerFe->mSnapshot->hasProtectedContent); - } - return protectedLayerFound; - }) - .get(); + // Snapshots must be taken from the main thread. + auto layers = mScheduler->schedule([=]() { return getLayerSnapshots(); }).get(); + hasProtectedLayer = layersHasProtectedLayer(layers); } const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected; const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER | @@ -8132,52 +8123,53 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, renderengine::impl::ExternalTexture>(buffer, getRenderEngine(), renderengine::impl::ExternalTexture::Usage:: WRITEABLE); - auto fence = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture, - false /* regionSampling */, grayscale, isProtected, - captureListener); - fence.get(); + auto futureFence = + captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, texture, + false /* regionSampling */, grayscale, isProtected, captureListener); + futureFence.get(); } -ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( +ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot( RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); - auto future = mScheduler->schedule( - [=, this, renderAreaFuture = std::move(renderAreaFuture)]() FTL_FAKE_GUARD( - kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { - ScreenCaptureResults captureResults; - std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get(); - if (!renderArea) { - ALOGW("Skipping screen capture because of invalid render area."); - if (captureListener) { - captureResults.fenceResult = base::unexpected(NO_MEMORY); - captureListener->onScreenCaptureCompleted(captureResults); - } - return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share(); - } + auto takeScreenshotFn = [=, this, renderAreaFuture = std::move(renderAreaFuture)]() REQUIRES( + kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { + ScreenCaptureResults captureResults; + std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get(); + if (!renderArea) { + ALOGW("Skipping screen capture because of invalid render area."); + if (captureListener) { + captureResults.fenceResult = base::unexpected(NO_MEMORY); + captureListener->onScreenCaptureCompleted(captureResults); + } + return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share(); + } - ftl::SharedFuture<FenceResult> renderFuture; - renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { - renderFuture = - renderScreenImpl(renderArea, getLayerSnapshots, buffer, regionSampling, - grayscale, isProtected, captureResults); - }); + ftl::SharedFuture<FenceResult> renderFuture; + renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { + renderFuture = renderScreenImpl(renderArea, getLayerSnapshots, buffer, regionSampling, + grayscale, isProtected, captureResults); + }); - if (captureListener) { - // Defer blocking on renderFuture back to the Binder thread. - return ftl::Future(std::move(renderFuture)) - .then([captureListener, captureResults = std::move(captureResults)]( - FenceResult fenceResult) mutable -> FenceResult { - captureResults.fenceResult = std::move(fenceResult); - captureListener->onScreenCaptureCompleted(captureResults); - return base::unexpected(NO_ERROR); - }) - .share(); - } - return renderFuture; - }); + if (captureListener) { + // Defer blocking on renderFuture back to the Binder thread. + return ftl::Future(std::move(renderFuture)) + .then([captureListener, captureResults = std::move(captureResults)]( + FenceResult fenceResult) mutable -> FenceResult { + captureResults.fenceResult = std::move(fenceResult); + captureListener->onScreenCaptureCompleted(captureResults); + return base::unexpected(NO_ERROR); + }) + .share(); + } + return renderFuture; + }; + + auto future = + mScheduler->schedule(FTL_FAKE_GUARD(kMainThreadContext, std::move(takeScreenshotFn))); // Flatten nested futures. auto chain = ftl::Future(std::move(future)).then([](ftl::SharedFuture<FenceResult> future) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bada8292fd..005f2e6344 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -874,13 +874,17 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); + bool layersHasProtectedLayer(const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const; + void captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction, ui::Size bufferSize, ui::PixelFormat, bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>&); - ftl::SharedFuture<FenceResult> captureScreenCommon( + + ftl::SharedFuture<FenceResult> captureScreenshot( RenderAreaFuture, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, bool grayscale, bool isProtected, const sp<IScreenCaptureListener>&); + ftl::SharedFuture<FenceResult> renderScreenImpl( std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, @@ -1050,7 +1054,6 @@ private: const DisplayDeviceState& drawingState) REQUIRES(mStateLock, kMainThreadContext); - void dispatchDisplayHotplugEvent(PhysicalDisplayId, bool connected); void dispatchDisplayModeChangeEvent(PhysicalDisplayId, const scheduler::FrameRateMode&) REQUIRES(mStateLock); @@ -1221,6 +1224,7 @@ private: // constant members (no synchronization needed for access) const nsecs_t mBootTime = systemTime(); bool mIsUserBuild = true; + bool mHasReliablePresentFences = false; // Can only accessed from the main thread, these members // don't need synchronization diff --git a/services/surfaceflinger/common/Android.bp b/services/surfaceflinger/common/Android.bp index f2ff00b842..4a89dd06ce 100644 --- a/services/surfaceflinger/common/Android.bp +++ b/services/surfaceflinger/common/Android.bp @@ -35,6 +35,7 @@ cc_library_static { ], static_libs: [ "libsurfaceflingerflags", + "android.os.flags-aconfig-cc", ], } @@ -45,5 +46,30 @@ cc_library_static { ], static_libs: [ "libsurfaceflingerflags_test", + "android.os.flags-aconfig-cc-test", + ], +} + +cc_defaults { + name: "libsurfaceflinger_common_deps", + shared_libs: [ + "server_configurable_flags", + ], + static_libs: [ + "libsurfaceflinger_common", + "libsurfaceflingerflags", + "android.os.flags-aconfig-cc", + ], +} + +cc_defaults { + name: "libsurfaceflinger_common_test_deps", + shared_libs: [ + "server_configurable_flags", + ], + static_libs: [ + "libsurfaceflinger_common_test", + "libsurfaceflingerflags_test", + "android.os.flags-aconfig-cc-test", ], } diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp index f7adc0e5d6..3b669c6b54 100644 --- a/services/surfaceflinger/common/FlagManager.cpp +++ b/services/surfaceflinger/common/FlagManager.cpp @@ -26,6 +26,7 @@ #include <server_configurable_flags/get_flags.h> #include <cinttypes> +#include <android_os.h> #include <com_android_graphics_surfaceflinger_flags.h> namespace android { @@ -109,6 +110,7 @@ void FlagManager::dump(std::string& result) const { /// Trunk stable server flags /// DUMP_SERVER_FLAG(refresh_rate_overlay_on_external_display); + DUMP_SERVER_FLAG(adpf_use_fmq_channel); /// Trunk stable readonly flags /// DUMP_READ_ONLY_FLAG(connected_display); @@ -131,6 +133,7 @@ void FlagManager::dump(std::string& result) const { DUMP_READ_ONLY_FLAG(renderable_buffer_usage); DUMP_READ_ONLY_FLAG(restore_blur_step); DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro); + DUMP_READ_ONLY_FLAG(protected_if_client); #undef DUMP_READ_ONLY_FLAG #undef DUMP_SERVER_FLAG #undef DUMP_FLAG_INTERVAL @@ -157,7 +160,7 @@ bool FlagManager::getServerConfigurableFlag(const char* experimentFlagName) cons return getServerConfigurableFlag(serverFlagName); \ } -#define FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, checkForBootCompleted) \ +#define FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, checkForBootCompleted, owner) \ bool FlagManager::name() const { \ if (checkForBootCompleted) { \ LOG_ALWAYS_FATAL_IF(!mBootCompleted, \ @@ -165,21 +168,24 @@ bool FlagManager::getServerConfigurableFlag(const char* experimentFlagName) cons __func__); \ } \ static const std::optional<bool> debugOverride = getBoolProperty(syspropOverride); \ - static const bool value = getFlagValue([] { return flags::name(); }, debugOverride); \ + static const bool value = getFlagValue([] { return owner ::name(); }, debugOverride); \ if (mUnitTestMode) { \ /* \ * When testing, we don't want to rely on the cached `value` or the debugOverride. \ */ \ - return flags::name(); \ + return owner ::name(); \ } \ return value; \ } #define FLAG_MANAGER_SERVER_FLAG(name, syspropOverride) \ - FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true) + FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true, flags) #define FLAG_MANAGER_READ_ONLY_FLAG(name, syspropOverride) \ - FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false) + FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false, flags) + +#define FLAG_MANAGER_SERVER_FLAG_IMPORTED(name, syspropOverride, owner) \ + FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true, owner) /// Legacy server flags /// FLAG_MANAGER_LEGACY_SERVER_FLAG(test_flag, "", "") @@ -210,8 +216,12 @@ FLAG_MANAGER_READ_ONLY_FLAG(vulkan_renderengine, "debug.renderengine.vulkan") FLAG_MANAGER_READ_ONLY_FLAG(renderable_buffer_usage, "") FLAG_MANAGER_READ_ONLY_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step") FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "") +FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "") /// Trunk stable server flags /// FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "") +/// Trunk stable server flags from outside SurfaceFlinger /// +FLAG_MANAGER_SERVER_FLAG_IMPORTED(adpf_use_fmq_channel, "", android::os) + } // namespace android diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h index 18f623faff..763963e24f 100644 --- a/services/surfaceflinger/common/include/common/FlagManager.h +++ b/services/surfaceflinger/common/include/common/FlagManager.h @@ -49,6 +49,7 @@ public: /// Trunk stable server flags /// bool refresh_rate_overlay_on_external_display() const; + bool adpf_use_fmq_channel() const; /// Trunk stable readonly flags /// bool connected_display() const; @@ -71,6 +72,7 @@ public: bool renderable_buffer_usage() const; bool restore_blur_step() const; bool dont_skip_on_early_ro() const; + bool protected_if_client() const; protected: // overridden for unit tests diff --git a/services/surfaceflinger/surfaceflinger_flags.aconfig b/services/surfaceflinger/surfaceflinger_flags.aconfig index f5ec1eeaf2..5174fa7fb1 100644 --- a/services/surfaceflinger/surfaceflinger_flags.aconfig +++ b/services/surfaceflinger/surfaceflinger_flags.aconfig @@ -1,3 +1,5 @@ +# This file is locked and should not be changed. Use surfaceflinger_flags_new.aconfig + package: "com.android.graphics.surfaceflinger.flags" container: "system" @@ -25,6 +27,8 @@ flag { is_fixed_read_only: true } +# This file is locked and should not be changed. Use surfaceflinger_flags_new.aconfig + flag { name: "enable_layer_command_batching" namespace: "core_graphics" @@ -49,6 +53,8 @@ flag { is_fixed_read_only: true } +# This file is locked and should not be changed. Use surfaceflinger_flags_new.aconfig + flag { name: "hotplug2" namespace: "core_graphics" @@ -73,6 +79,8 @@ flag { is_fixed_read_only: true } +# This file is locked and should not be changed. Use surfaceflinger_flags_new.aconfig + flag { name: "refresh_rate_overlay_on_external_display" namespace: "core_graphics" @@ -98,6 +106,8 @@ flag { # is_fixed_read_only: true # } +# This file is locked and should not be changed. Use surfaceflinger_flags_new.aconfig + flag { name: "cache_when_source_crop_layer_only_moved" namespace: "core_graphics" @@ -130,6 +140,8 @@ flag { is_fixed_read_only: true } +# This file is locked and should not be changed. Use surfaceflinger_flags_new.aconfig + flag { name: "game_default_frame_rate" namespace: "game" @@ -162,6 +174,8 @@ flag { is_fixed_read_only: true } +# This file is locked and should not be changed. Use surfaceflinger_flags_new.aconfig + flag { name: "renderable_buffer_usage" namespace: "core_graphics" @@ -184,6 +198,8 @@ flag { } } +# This file is locked and should not be changed. Use surfaceflinger_flags_new.aconfig + flag { name: "dont_skip_on_early_ro" namespace: "core_graphics" @@ -194,3 +210,16 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "protected_if_client" + namespace: "core_graphics" + description: "Only set the RenderSurface to protected if protected layers are in client composition." + bug: "307674749" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} + +# This file is locked and should not be changed. Use surfaceflinger_flags_new.aconfig diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig new file mode 100644 index 0000000000..5451752d91 --- /dev/null +++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig @@ -0,0 +1,13 @@ +# IMPORTANT - please keep alphabetize to reduce merge conflicts + +package: "com.android.graphics.surfaceflinger.flags" +container: "system" + +flag { + name: "dont_skip_on_early_ro2" + namespace: "core_graphics" + description: "This flag is guarding the behaviour where SurfaceFlinger is trying to opportunistically present a frame when the configuration change from late to early" + bug: "273702768" +} # dont_skip_on_early_ro2 + +# IMPORTANT - please keep alphabetize to reduce merge conflicts diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index dab0a3f13c..925fe0b794 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -27,6 +27,7 @@ cc_test { defaults: [ "android.hardware.graphics.common-ndk_shared", "surfaceflinger_defaults", + "libsurfaceflinger_common_test_deps", ], test_suites: ["device-tests"], srcs: [ @@ -66,7 +67,6 @@ cc_test { static_libs: [ "liblayers_proto", "android.hardware.graphics.composer@2.1", - "libsurfaceflingerflags", ], shared_libs: [ "android.hardware.graphics.common@1.2", diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index f529f7cb05..0c13db3d94 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -29,7 +29,7 @@ filegroup { "mock/DisplayHardware/MockComposer.cpp", "mock/DisplayHardware/MockHWC2.cpp", "mock/DisplayHardware/MockIPower.cpp", - "mock/DisplayHardware/MockIPowerHintSession.cpp", + "mock/DisplayHardware/MockPowerHintSessionWrapper.cpp", "mock/DisplayHardware/MockPowerAdvisor.cpp", "mock/MockEventThread.cpp", "mock/MockFrameTimeline.cpp", @@ -149,6 +149,7 @@ cc_defaults { "android.hardware.graphics.composer3-ndk_static", "android.hardware.power-ndk_static", "librenderengine_deps", + "libsurfaceflinger_common_test_deps", ], static_libs: [ "android.hardware.common-V2-ndk", @@ -173,13 +174,11 @@ cc_defaults { "librenderengine_mocks", "libscheduler", "libserviceutils", - "libsurfaceflinger_common_test", "libtimestats", "libtimestats_atoms_proto", "libtimestats_proto", "libtonemap", "perfetto_trace_protos", - "libsurfaceflingerflags_test", ], shared_libs: [ "android.hardware.configstore-utils", @@ -208,7 +207,6 @@ cc_defaults { "libsync", "libui", "libutils", - "server_configurable_flags", ], header_libs: [ "android.hardware.graphics.composer3-command-buffer", diff --git a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp index 9c66a97573..1d44a3ef77 100644 --- a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp +++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp @@ -26,8 +26,8 @@ #include <chrono> #include <future> #include "TestableSurfaceFlinger.h" -#include "mock/DisplayHardware/MockIPowerHintSession.h" #include "mock/DisplayHardware/MockPowerHalController.h" +#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h" using namespace android; using namespace android::Hwc2::mock; @@ -54,7 +54,7 @@ protected: TestableSurfaceFlinger mFlinger; std::unique_ptr<PowerAdvisor> mPowerAdvisor; MockPowerHalController* mMockPowerHalController; - std::shared_ptr<MockIPowerHintSession> mMockPowerHintSession; + std::shared_ptr<MockPowerHintSessionWrapper> mMockPowerHintSession; }; bool PowerAdvisorTest::sessionExists() { @@ -68,25 +68,29 @@ void PowerAdvisorTest::SetUp() { mMockPowerHalController = reinterpret_cast<MockPowerHalController*>(mPowerAdvisor->mPowerHal.get()); ON_CALL(*mMockPowerHalController, getHintSessionPreferredRate) - .WillByDefault(Return(HalResult<int64_t>::fromStatus(binder::Status::ok(), 16000))); + .WillByDefault(Return( + ByMove(HalResult<int64_t>::fromStatus(ndk::ScopedAStatus::ok(), 16000)))); } void PowerAdvisorTest::startPowerHintSession(bool returnValidSession) { - mMockPowerHintSession = ndk::SharedRefBase::make<NiceMock<MockIPowerHintSession>>(); + mMockPowerHintSession = std::make_shared<NiceMock<MockPowerHintSessionWrapper>>(); if (returnValidSession) { ON_CALL(*mMockPowerHalController, createHintSession) - .WillByDefault( - Return(HalResult<std::shared_ptr<IPowerHintSession>>:: - fromStatus(binder::Status::ok(), mMockPowerHintSession))); + .WillByDefault([&](int32_t, int32_t, const std::vector<int32_t>&, int64_t) { + return HalResult<std::shared_ptr<PowerHintSessionWrapper>>:: + fromStatus(ndk::ScopedAStatus::ok(), mMockPowerHintSession); + }); } else { - ON_CALL(*mMockPowerHalController, createHintSession) - .WillByDefault(Return(HalResult<std::shared_ptr<IPowerHintSession>>:: - fromStatus(binder::Status::ok(), nullptr))); + ON_CALL(*mMockPowerHalController, createHintSession).WillByDefault([] { + return HalResult< + std::shared_ptr<PowerHintSessionWrapper>>::fromStatus(ndk::ScopedAStatus::ok(), + nullptr); + }); } mPowerAdvisor->enablePowerHintSession(true); mPowerAdvisor->startPowerHintSession({1, 2, 3}); ON_CALL(*mMockPowerHintSession, updateTargetWorkDuration) - .WillByDefault(Return(testing::ByMove(ndk::ScopedAStatus::ok()))); + .WillByDefault(Return(testing::ByMove(HalResult<void>::ok()))); } void PowerAdvisorTest::setExpectedTiming(Duration totalFrameTargetDuration, @@ -148,7 +152,7 @@ TEST_F(PowerAdvisorTest, hintSessionUseHwcDisplay) { reportActualWorkDuration(ElementsAre( Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns()))))) .Times(1) - .WillOnce(Return(testing::ByMove(ndk::ScopedAStatus::ok()))); + .WillOnce(Return(testing::ByMove(HalResult<void>::ok()))); fakeBasicFrameTiming(startTime, vsyncPeriod); setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod); mPowerAdvisor->setDisplays(displayIds); @@ -188,7 +192,7 @@ TEST_F(PowerAdvisorTest, hintSessionSubtractsHwcFenceTime) { reportActualWorkDuration(ElementsAre( Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns()))))) .Times(1) - .WillOnce(Return(testing::ByMove(ndk::ScopedAStatus::ok()))); + .WillOnce(Return(testing::ByMove(HalResult<void>::ok()))); fakeBasicFrameTiming(startTime, vsyncPeriod); setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod); @@ -231,7 +235,7 @@ TEST_F(PowerAdvisorTest, hintSessionUsingSecondaryVirtualDisplays) { reportActualWorkDuration(ElementsAre( Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns()))))) .Times(1) - .WillOnce(Return(testing::ByMove(ndk::ScopedAStatus::ok()))); + .WillOnce(Return(testing::ByMove(HalResult<void>::ok()))); fakeBasicFrameTiming(startTime, vsyncPeriod); setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod); @@ -328,17 +332,17 @@ TEST_F(PowerAdvisorTest, hintSessionTestNotifyReportRace) { ON_CALL(*mMockPowerHintSession, sendHint).WillByDefault([&letSendHintFinish] { letSendHintFinish.get_future().wait(); - return ndk::ScopedAStatus::fromExceptionCode(-127); + return HalResult<void>::fromStatus(ndk::ScopedAStatus::fromExceptionCode(-127)); }); ON_CALL(*mMockPowerHintSession, reportActualWorkDuration).WillByDefault([] { - return ndk::ScopedAStatus::fromExceptionCode(-127); + return HalResult<void>::fromStatus(ndk::ScopedAStatus::fromExceptionCode(-127)); }); - ON_CALL(*mMockPowerHalController, createHintSession) - .WillByDefault(Return( - HalResult<std::shared_ptr<IPowerHintSession>>:: - fromStatus(ndk::ScopedAStatus::fromExceptionCode(-127), nullptr))); + ON_CALL(*mMockPowerHalController, createHintSession).WillByDefault([] { + return HalResult<std::shared_ptr<PowerHintSessionWrapper>>:: + fromStatus(ndk::ScopedAStatus::fromExceptionCode(-127), nullptr); + }); // First background call, to notice the session is down auto firstHint = std::async(std::launch::async, [this] { diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp index 39a8aacaf8..0a6e3054dd 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp @@ -3159,6 +3159,210 @@ TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_twoUids) { EXPECT_TRUE(frameRateOverrides.empty()); } +TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_withFrameRateCategory) { + if (GetParam() == Config::FrameRateOverride::Disabled) { + return; + } + + ASSERT_TRUE(GetParam() == Config::FrameRateOverride::AppOverrideNativeRefreshRates || + GetParam() == Config::FrameRateOverride::AppOverride || + GetParam() == Config::FrameRateOverride::Enabled); + + auto selector = createSelector(kModes_30_60_72_90_120, kModeId120); + + std::vector<LayerRequirement> layers = {{.ownerUid = 1234, .weight = 1.f}, + {.ownerUid = 1234, .weight = 1.f}}; + + // HighHint case with touch boost and thus should skip frame rate override. + layers[0].name = "ExplicitCategory HighHint"; + layers[0].vote = LayerVoteType::ExplicitCategory; + layers[0].desiredRefreshRate = 0_Hz; + layers[0].frameRateCategory = FrameRateCategory::HighHint; + layers[1].name = "ExplicitCategory High"; + layers[1].vote = LayerVoteType::ExplicitCategory; + layers[1].desiredRefreshRate = 0_Hz; + layers[1].frameRateCategory = FrameRateCategory::High; + auto frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_TRUE(frameRateOverrides.empty()); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_TRUE(frameRateOverrides.empty()); + + // HighHint case with touch boost and thus should skip frame rate override. + layers[0].name = "ExplicitCategory HighHint"; + layers[0].vote = LayerVoteType::ExplicitCategory; + layers[0].desiredRefreshRate = 0_Hz; + layers[0].frameRateCategory = FrameRateCategory::HighHint; + layers[1].name = "ExplicitCategory Normal"; + layers[1].vote = LayerVoteType::ExplicitCategory; + layers[1].desiredRefreshRate = 0_Hz; + layers[1].frameRateCategory = FrameRateCategory::Normal; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_TRUE(frameRateOverrides.empty()); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_TRUE(frameRateOverrides.empty()); + + // HighHint case with touch boost and thus should skip frame rate override. + layers[0].name = "ExplicitCategory HighHint"; + layers[0].vote = LayerVoteType::ExplicitCategory; + layers[0].desiredRefreshRate = 0_Hz; + layers[0].frameRateCategory = FrameRateCategory::HighHint; + layers[1].name = "ExplicitCategory Low"; + layers[1].vote = LayerVoteType::ExplicitCategory; + layers[1].desiredRefreshRate = 0_Hz; + layers[1].frameRateCategory = FrameRateCategory::Low; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_TRUE(frameRateOverrides.empty()); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_TRUE(frameRateOverrides.empty()); + + // HighHint case with touch boost and thus should skip frame rate override. + layers[0].name = "ExplicitCategory HighHint"; + layers[0].vote = LayerVoteType::ExplicitCategory; + layers[0].desiredRefreshRate = 0_Hz; + layers[0].frameRateCategory = FrameRateCategory::HighHint; + layers[1].name = "ExplicitCategory NoPreference"; + layers[1].vote = LayerVoteType::ExplicitCategory; + layers[1].desiredRefreshRate = 0_Hz; + layers[1].frameRateCategory = FrameRateCategory::NoPreference; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_TRUE(frameRateOverrides.empty()); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_TRUE(frameRateOverrides.empty()); + + // HighHint case *without* touch boost has frame rate override. + // For example, game and touch interaction. + layers[0].name = "ExplicitCategory HighHint"; + layers[0].vote = LayerVoteType::ExplicitCategory; + layers[0].desiredRefreshRate = 0_Hz; + layers[0].frameRateCategory = FrameRateCategory::HighHint; + layers[1].name = "ExplicitDefault 60"; + layers[1].vote = LayerVoteType::ExplicitDefault; + layers[1].desiredRefreshRate = 60_Hz; + layers[1].frameRateCategory = FrameRateCategory::Default; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + + // HighHint case with touch boost and thus should skip frame rate override. + layers[0].name = "ExplicitCategory HighHint"; + layers[0].vote = LayerVoteType::ExplicitCategory; + layers[0].desiredRefreshRate = 0_Hz; + layers[0].frameRateCategory = FrameRateCategory::HighHint; + layers[1].name = "ExplicitExactOrMultiple 30"; + layers[1].vote = LayerVoteType::ExplicitExactOrMultiple; + layers[1].desiredRefreshRate = 30_Hz; + layers[1].frameRateCategory = FrameRateCategory::Default; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_TRUE(frameRateOverrides.empty()); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_TRUE(frameRateOverrides.empty()); + + // HighHint case with touch boost and thus should skip frame rate override. + layers[0].name = "ExplicitCategory HighHint"; + layers[0].vote = LayerVoteType::ExplicitCategory; + layers[0].desiredRefreshRate = 0_Hz; + layers[0].frameRateCategory = FrameRateCategory::HighHint; + layers[1].name = "ExplicitExact 60"; + layers[1].vote = LayerVoteType::ExplicitExact; + layers[1].desiredRefreshRate = 60_Hz; + layers[1].frameRateCategory = FrameRateCategory::Default; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_TRUE(frameRateOverrides.empty()); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_TRUE(frameRateOverrides.empty()); + + // HighHint case with touch boost and thus should skip frame rate override. + layers[0].name = "ExplicitCategory HighHint"; + layers[0].vote = LayerVoteType::ExplicitCategory; + layers[0].desiredRefreshRate = 0_Hz; + layers[0].frameRateCategory = FrameRateCategory::HighHint; + layers[1].name = "ExplicitGte 60"; + layers[1].vote = LayerVoteType::ExplicitGte; + layers[1].desiredRefreshRate = 60_Hz; + layers[1].frameRateCategory = FrameRateCategory::Default; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_TRUE(frameRateOverrides.empty()); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_TRUE(frameRateOverrides.empty()); + + // ExplicitCategory case that expects no global touch boost and thus has frame rate override. + layers[0].name = "ExplicitDefault 60"; + layers[0].vote = LayerVoteType::ExplicitDefault; + layers[0].desiredRefreshRate = 60_Hz; + layers[0].frameRateCategory = FrameRateCategory::Default; + layers[1].name = "ExplicitCategory High"; + layers[1].vote = LayerVoteType::ExplicitCategory; + layers[1].desiredRefreshRate = 0_Hz; + layers[1].frameRateCategory = FrameRateCategory::High; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(120_Hz, frameRateOverrides.at(1234)); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(120_Hz, frameRateOverrides.at(1234)); + + // ExplicitCategory case that expects no global touch boost and thus has frame rate override. + layers[0].name = "ExplicitDefault 60"; + layers[0].vote = LayerVoteType::ExplicitDefault; + layers[0].desiredRefreshRate = 60_Hz; + layers[0].frameRateCategory = FrameRateCategory::Default; + layers[1].name = "ExplicitCategory Normal"; + layers[1].vote = LayerVoteType::ExplicitCategory; + layers[1].desiredRefreshRate = 0_Hz; + layers[1].frameRateCategory = FrameRateCategory::Normal; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + + // ExplicitCategory case that expects no global touch boost and thus has frame rate override. + layers[0].name = "ExplicitDefault 60"; + layers[0].vote = LayerVoteType::ExplicitDefault; + layers[0].desiredRefreshRate = 60_Hz; + layers[0].frameRateCategory = FrameRateCategory::Default; + layers[1].name = "ExplicitCategory Low"; + layers[1].vote = LayerVoteType::ExplicitCategory; + layers[1].desiredRefreshRate = 0_Hz; + layers[1].frameRateCategory = FrameRateCategory::Low; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + + // ExplicitCategory case that expects no global touch boost and thus has frame rate override. + layers[0].name = "ExplicitDefault 60"; + layers[0].vote = LayerVoteType::ExplicitDefault; + layers[0].desiredRefreshRate = 60_Hz; + layers[0].frameRateCategory = FrameRateCategory::Default; + layers[1].name = "ExplicitCategory NoPreference"; + layers[1].vote = LayerVoteType::ExplicitCategory; + layers[1].desiredRefreshRate = 0_Hz; + layers[1].frameRateCategory = FrameRateCategory::NoPreference; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); +} + TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_touch) { if (GetParam() == Config::FrameRateOverride::Disabled) { return; @@ -3204,6 +3408,17 @@ TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_touch) { frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); EXPECT_TRUE(frameRateOverrides.empty()); + + layers[0].vote = LayerVoteType::ExplicitGte; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); } TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_DivisorIsNotDisplayRefreshRate) { diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h deleted file mode 100644 index 27564b26de..0000000000 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 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 "binder/Status.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#include <aidl/android/hardware/power/IPower.h> -#pragma clang diagnostic pop - -#include <gmock/gmock.h> - -using aidl::android::hardware::power::IPowerHintSession; -using aidl::android::hardware::power::SessionConfig; -using aidl::android::hardware::power::SessionHint; -using aidl::android::hardware::power::SessionMode; -using android::binder::Status; - -using namespace aidl::android::hardware::power; - -namespace android::Hwc2::mock { - -class MockIPowerHintSession : public IPowerHintSession { -public: - MockIPowerHintSession(); - - MOCK_METHOD(ndk::SpAIBinder, asBinder, (), (override)); - MOCK_METHOD(ndk::ScopedAStatus, pause, (), (override)); - MOCK_METHOD(ndk::ScopedAStatus, resume, (), (override)); - MOCK_METHOD(ndk::ScopedAStatus, close, (), (override)); - MOCK_METHOD(ndk::ScopedAStatus, getInterfaceVersion, (int32_t * version), (override)); - MOCK_METHOD(ndk::ScopedAStatus, getInterfaceHash, (std::string * hash), (override)); - MOCK_METHOD(bool, isRemote, (), (override)); - MOCK_METHOD(ndk::ScopedAStatus, updateTargetWorkDuration, (int64_t), (override)); - MOCK_METHOD(ndk::ScopedAStatus, reportActualWorkDuration, (const ::std::vector<WorkDuration>&), - (override)); - MOCK_METHOD(ndk::ScopedAStatus, sendHint, (SessionHint), (override)); - MOCK_METHOD(ndk::ScopedAStatus, setThreads, (const ::std::vector<int32_t>&), (override)); - MOCK_METHOD(ndk::ScopedAStatus, setMode, (SessionMode, bool), (override)); - MOCK_METHOD(ndk::ScopedAStatus, getSessionConfig, (SessionConfig * _aidl_return), (override)); -}; - -} // namespace android::Hwc2::mock diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.h index ae41e7ea75..af1862d1cf 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.h @@ -44,10 +44,10 @@ public: MOCK_METHOD(HalResult<void>, setBoost, (aidl::android::hardware::power::Boost, int32_t), (override)); MOCK_METHOD(HalResult<void>, setMode, (aidl::android::hardware::power::Mode, bool), (override)); - MOCK_METHOD(HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>>, + MOCK_METHOD(HalResult<std::shared_ptr<android::power::PowerHintSessionWrapper>>, createHintSession, (int32_t, int32_t, const std::vector<int32_t>&, int64_t), (override)); - MOCK_METHOD(HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>>, + MOCK_METHOD(HalResult<std::shared_ptr<android::power::PowerHintSessionWrapper>>, createHintSessionWithConfig, (int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos, aidl::android::hardware::power::SessionTag tag, diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp index 770bc15869..d383283d8e 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.cpp +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,12 @@ * limitations under the License. */ -#include "mock/DisplayHardware/MockIPowerHintSession.h" +#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h" namespace android::Hwc2::mock { // Explicit default instantiation is recommended. -MockIPowerHintSession::MockIPowerHintSession() = default; +MockPowerHintSessionWrapper::MockPowerHintSessionWrapper() + : power::PowerHintSessionWrapper(nullptr) {} } // namespace android::Hwc2::mock diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.h new file mode 100644 index 0000000000..bc6950cccb --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.h @@ -0,0 +1,55 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "binder/Status.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" +#include <aidl/android/hardware/power/IPower.h> +#include <powermanager/PowerHintSessionWrapper.h> +#pragma clang diagnostic pop + +#include <gmock/gmock.h> + +using aidl::android::hardware::power::IPowerHintSession; +using aidl::android::hardware::power::SessionConfig; +using aidl::android::hardware::power::SessionHint; +using aidl::android::hardware::power::SessionMode; +using android::binder::Status; + +using namespace aidl::android::hardware::power; + +namespace android::Hwc2::mock { + +class MockPowerHintSessionWrapper : public power::PowerHintSessionWrapper { +public: + MockPowerHintSessionWrapper(); + + MOCK_METHOD(power::HalResult<void>, updateTargetWorkDuration, (int64_t), (override)); + MOCK_METHOD(power::HalResult<void>, reportActualWorkDuration, + (const ::std::vector<WorkDuration>&), (override)); + MOCK_METHOD(power::HalResult<void>, pause, (), (override)); + MOCK_METHOD(power::HalResult<void>, resume, (), (override)); + MOCK_METHOD(power::HalResult<void>, close, (), (override)); + MOCK_METHOD(power::HalResult<void>, sendHint, (SessionHint), (override)); + MOCK_METHOD(power::HalResult<void>, setThreads, (const ::std::vector<int32_t>&), (override)); + MOCK_METHOD(power::HalResult<void>, setMode, (SessionMode, bool), (override)); + MOCK_METHOD(power::HalResult<SessionConfig>, getSessionConfig, (), (override)); +}; + +} // namespace android::Hwc2::mock diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp index 63ecaec06f..f10ba44d74 100644 --- a/services/vibratorservice/VibratorHalWrapper.cpp +++ b/services/vibratorservice/VibratorHalWrapper.cpp @@ -56,75 +56,6 @@ bool isStaticCastValid(Effect effect) { // ------------------------------------------------------------------------------------------------- -const constexpr char* STATUS_T_ERROR_MESSAGE_PREFIX = "status_t = "; -const constexpr char* STATUS_V_1_0_ERROR_MESSAGE_PREFIX = - "android::hardware::vibrator::V1_0::Status = "; - -template <typename T> -HalResult<T> HalResult<T>::fromStatus(V1_0::Status status, T data) { - switch (status) { - case V1_0::Status::OK: - return HalResult<T>::ok(data); - case V1_0::Status::UNSUPPORTED_OPERATION: - return HalResult<T>::unsupported(); - default: - return HalResult<T>::failed(STATUS_V_1_0_ERROR_MESSAGE_PREFIX + toString(status)); - } -} - -template <typename T> -template <typename R> -HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, T data) { - return ret.isOk() ? HalResult<T>::ok(data) : HalResult<T>::failed(ret.description()); -} - -template <typename T> -template <typename R> -HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, V1_0::Status status, T data) { - return ret.isOk() ? HalResult<T>::fromStatus(status, data) - : HalResult<T>::failed(ret.description()); -} - -// ------------------------------------------------------------------------------------------------- - -HalResult<void> HalResult<void>::fromStatus(status_t status) { - if (status == android::OK) { - return HalResult<void>::ok(); - } - return HalResult<void>::failed(STATUS_T_ERROR_MESSAGE_PREFIX + statusToString(status)); -} - -HalResult<void> HalResult<void>::fromStatus(binder::Status status) { - if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION || - status.transactionError() == android::UNKNOWN_TRANSACTION) { - // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is - // the same as the operation being unsupported by this HAL. Should not retry. - return HalResult<void>::unsupported(); - } - if (status.isOk()) { - return HalResult<void>::ok(); - } - return HalResult<void>::failed(std::string(status.toString8().c_str())); -} - -HalResult<void> HalResult<void>::fromStatus(V1_0::Status status) { - switch (status) { - case V1_0::Status::OK: - return HalResult<void>::ok(); - case V1_0::Status::UNSUPPORTED_OPERATION: - return HalResult<void>::unsupported(); - default: - return HalResult<void>::failed(STATUS_V_1_0_ERROR_MESSAGE_PREFIX + toString(status)); - } -} - -template <typename R> -HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) { - return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description()); -} - -// ------------------------------------------------------------------------------------------------- - Info HalWrapper::getInfo() { getCapabilities(); getPrimitiveDurations(); @@ -269,7 +200,7 @@ HalResult<std::vector<float>> HalWrapper::getMaxAmplitudesInternal() { // ------------------------------------------------------------------------------------------------- HalResult<void> AidlHalWrapper::ping() { - return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder()); + return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder()); } void AidlHalWrapper::tryReconnect() { @@ -291,7 +222,7 @@ HalResult<void> AidlHalWrapper::on(milliseconds timeout, static_cast<int32_t>(capabilities.value() & Capabilities::ON_CALLBACK); auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; - auto ret = HalResult<void>::fromStatus(getHal()->on(timeout.count(), cb)); + auto ret = HalResultFactory::fromStatus(getHal()->on(timeout.count(), cb)); if (!supportsCallback && ret.isOk()) { mCallbackScheduler->schedule(completionCallback, timeout); } @@ -300,23 +231,23 @@ HalResult<void> AidlHalWrapper::on(milliseconds timeout, } HalResult<void> AidlHalWrapper::off() { - return HalResult<void>::fromStatus(getHal()->off()); + return HalResultFactory::fromStatus(getHal()->off()); } HalResult<void> AidlHalWrapper::setAmplitude(float amplitude) { - return HalResult<void>::fromStatus(getHal()->setAmplitude(amplitude)); + return HalResultFactory::fromStatus(getHal()->setAmplitude(amplitude)); } HalResult<void> AidlHalWrapper::setExternalControl(bool enabled) { - return HalResult<void>::fromStatus(getHal()->setExternalControl(enabled)); + return HalResultFactory::fromStatus(getHal()->setExternalControl(enabled)); } HalResult<void> AidlHalWrapper::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) { - return HalResult<void>::fromStatus(getHal()->alwaysOnEnable(id, effect, strength)); + return HalResultFactory::fromStatus(getHal()->alwaysOnEnable(id, effect, strength)); } HalResult<void> AidlHalWrapper::alwaysOnDisable(int32_t id) { - return HalResult<void>::fromStatus(getHal()->alwaysOnDisable(id)); + return HalResultFactory::fromStatus(getHal()->alwaysOnDisable(id)); } HalResult<milliseconds> AidlHalWrapper::performEffect( @@ -330,7 +261,7 @@ HalResult<milliseconds> AidlHalWrapper::performEffect( auto result = getHal()->perform(effect, strength, cb, &lengthMs); milliseconds length = milliseconds(lengthMs); - auto ret = HalResult<milliseconds>::fromStatus(result, length); + auto ret = HalResultFactory::fromStatus<milliseconds>(result, length); if (!supportsCallback && ret.isOk()) { mCallbackScheduler->schedule(completionCallback, length); } @@ -357,38 +288,40 @@ HalResult<milliseconds> AidlHalWrapper::performComposedEffect( duration += milliseconds(effect.delayMs); } - return HalResult<milliseconds>::fromStatus(getHal()->compose(primitives, cb), duration); + return HalResultFactory::fromStatus<milliseconds>(getHal()->compose(primitives, cb), duration); } HalResult<void> AidlHalWrapper::performPwleEffect(const std::vector<PrimitivePwle>& primitives, const std::function<void()>& completionCallback) { // This method should always support callbacks, so no need to double check. auto cb = new HalCallbackWrapper(completionCallback); - return HalResult<void>::fromStatus(getHal()->composePwle(primitives, cb)); + return HalResultFactory::fromStatus(getHal()->composePwle(primitives, cb)); } HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() { int32_t capabilities = 0; auto result = getHal()->getCapabilities(&capabilities); - return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities)); + return HalResultFactory::fromStatus<Capabilities>(result, + static_cast<Capabilities>(capabilities)); } HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffectsInternal() { std::vector<Effect> supportedEffects; auto result = getHal()->getSupportedEffects(&supportedEffects); - return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects); + return HalResultFactory::fromStatus<std::vector<Effect>>(result, supportedEffects); } HalResult<std::vector<Braking>> AidlHalWrapper::getSupportedBrakingInternal() { std::vector<Braking> supportedBraking; auto result = getHal()->getSupportedBraking(&supportedBraking); - return HalResult<std::vector<Braking>>::fromStatus(result, supportedBraking); + return HalResultFactory::fromStatus<std::vector<Braking>>(result, supportedBraking); } HalResult<std::vector<CompositePrimitive>> AidlHalWrapper::getSupportedPrimitivesInternal() { std::vector<CompositePrimitive> supportedPrimitives; auto result = getHal()->getSupportedPrimitives(&supportedPrimitives); - return HalResult<std::vector<CompositePrimitive>>::fromStatus(result, supportedPrimitives); + return HalResultFactory::fromStatus<std::vector<CompositePrimitive>>(result, + supportedPrimitives); } HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsInternal( @@ -408,7 +341,7 @@ HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsIntern } int32_t duration = 0; auto result = getHal()->getPrimitiveDuration(primitive, &duration); - auto halResult = HalResult<int32_t>::fromStatus(result, duration); + auto halResult = HalResultFactory::fromStatus<int32_t>(result, duration); if (halResult.isUnsupported()) { // Should not happen, supported primitives should always support requesting duration. ALOGE("Supported primitive %zu returned unsupported for getPrimitiveDuration", @@ -427,55 +360,55 @@ HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsIntern HalResult<milliseconds> AidlHalWrapper::getPrimitiveDelayMaxInternal() { int32_t delay = 0; auto result = getHal()->getCompositionDelayMax(&delay); - return HalResult<milliseconds>::fromStatus(result, milliseconds(delay)); + return HalResultFactory::fromStatus<milliseconds>(result, milliseconds(delay)); } HalResult<milliseconds> AidlHalWrapper::getPrimitiveDurationMaxInternal() { int32_t delay = 0; auto result = getHal()->getPwlePrimitiveDurationMax(&delay); - return HalResult<milliseconds>::fromStatus(result, milliseconds(delay)); + return HalResultFactory::fromStatus<milliseconds>(result, milliseconds(delay)); } HalResult<int32_t> AidlHalWrapper::getCompositionSizeMaxInternal() { int32_t size = 0; auto result = getHal()->getCompositionSizeMax(&size); - return HalResult<int32_t>::fromStatus(result, size); + return HalResultFactory::fromStatus<int32_t>(result, size); } HalResult<int32_t> AidlHalWrapper::getPwleSizeMaxInternal() { int32_t size = 0; auto result = getHal()->getPwleCompositionSizeMax(&size); - return HalResult<int32_t>::fromStatus(result, size); + return HalResultFactory::fromStatus<int32_t>(result, size); } HalResult<float> AidlHalWrapper::getMinFrequencyInternal() { float minFrequency = 0; auto result = getHal()->getFrequencyMinimum(&minFrequency); - return HalResult<float>::fromStatus(result, minFrequency); + return HalResultFactory::fromStatus<float>(result, minFrequency); } HalResult<float> AidlHalWrapper::getResonantFrequencyInternal() { float f0 = 0; auto result = getHal()->getResonantFrequency(&f0); - return HalResult<float>::fromStatus(result, f0); + return HalResultFactory::fromStatus<float>(result, f0); } HalResult<float> AidlHalWrapper::getFrequencyResolutionInternal() { float frequencyResolution = 0; auto result = getHal()->getFrequencyResolution(&frequencyResolution); - return HalResult<float>::fromStatus(result, frequencyResolution); + return HalResultFactory::fromStatus<float>(result, frequencyResolution); } HalResult<float> AidlHalWrapper::getQFactorInternal() { float qFactor = 0; auto result = getHal()->getQFactor(&qFactor); - return HalResult<float>::fromStatus(result, qFactor); + return HalResultFactory::fromStatus<float>(result, qFactor); } HalResult<std::vector<float>> AidlHalWrapper::getMaxAmplitudesInternal() { std::vector<float> amplitudes; auto result = getHal()->getBandwidthAmplitudeMap(&litudes); - return HalResult<std::vector<float>>::fromStatus(result, amplitudes); + return HalResultFactory::fromStatus<std::vector<float>>(result, amplitudes); } sp<Aidl::IVibrator> AidlHalWrapper::getHal() { @@ -488,7 +421,7 @@ sp<Aidl::IVibrator> AidlHalWrapper::getHal() { template <typename I> HalResult<void> HidlHalWrapper<I>::ping() { auto result = getHal()->ping(); - return HalResult<void>::fromReturn(result); + return HalResultFactory::fromReturn(result); } template <typename I> @@ -504,7 +437,7 @@ template <typename I> HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout, const std::function<void()>& completionCallback) { auto result = getHal()->on(timeout.count()); - auto ret = HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); + auto ret = HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); if (ret.isOk()) { mCallbackScheduler->schedule(completionCallback, timeout); } @@ -514,14 +447,14 @@ HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout, template <typename I> HalResult<void> HidlHalWrapper<I>::off() { auto result = getHal()->off(); - return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); + return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); } template <typename I> HalResult<void> HidlHalWrapper<I>::setAmplitude(float amplitude) { uint8_t amp = static_cast<uint8_t>(amplitude * std::numeric_limits<uint8_t>::max()); auto result = getHal()->setAmplitude(amp); - return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); + return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); } template <typename I> @@ -547,7 +480,7 @@ HalResult<Capabilities> HidlHalWrapper<I>::getCapabilitiesInternal() { hardware::Return<bool> result = getHal()->supportsAmplitudeControl(); Capabilities capabilities = result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE; - return HalResult<Capabilities>::fromReturn(result, capabilities); + return HalResultFactory::fromReturn<Capabilities>(result, capabilities); } template <typename I> @@ -566,7 +499,7 @@ HalResult<milliseconds> HidlHalWrapper<I>::performInternal( auto result = std::invoke(performFn, handle, effect, effectStrength, effectCallback); milliseconds length = milliseconds(lengthMs); - auto ret = HalResult<milliseconds>::fromReturn(result, status, length); + auto ret = HalResultFactory::fromReturn<milliseconds>(result, status, length); if (ret.isOk()) { mCallbackScheduler->schedule(completionCallback, length); } @@ -638,7 +571,7 @@ HalResult<milliseconds> HidlHalWrapperV1_2::performEffect( HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) { auto result = getHal()->setExternalControl(static_cast<uint32_t>(enabled)); - return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); + return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); } HalResult<milliseconds> HidlHalWrapperV1_3::performEffect( @@ -671,7 +604,7 @@ HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() { sp<V1_3::IVibrator> hal = getHal(); auto amplitudeResult = hal->supportsAmplitudeControl(); if (!amplitudeResult.isOk()) { - return HalResult<Capabilities>::fromReturn(amplitudeResult, capabilities); + return HalResultFactory::fromReturn<Capabilities>(amplitudeResult, capabilities); } auto externalControlResult = hal->supportsExternalControl(); @@ -686,7 +619,7 @@ HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() { } } - return HalResult<Capabilities>::fromReturn(externalControlResult, capabilities); + return HalResultFactory::fromReturn<Capabilities>(externalControlResult, capabilities); } // ------------------------------------------------------------------------------------------------- diff --git a/services/vibratorservice/VibratorManagerHalController.cpp b/services/vibratorservice/VibratorManagerHalController.cpp index 0df0bfa19a..aa5b7fc86f 100644 --- a/services/vibratorservice/VibratorManagerHalController.cpp +++ b/services/vibratorservice/VibratorManagerHalController.cpp @@ -46,8 +46,6 @@ template <typename T> HalResult<T> ManagerHalController::processHalResult(HalResult<T> result, const char* functionName) { if (result.isFailed()) { ALOGE("VibratorManager HAL %s failed: %s", functionName, result.errorMessage()); - std::lock_guard<std::mutex> lock(mConnectedHalMutex); - mConnectedHal->tryReconnect(); } return result; } @@ -70,12 +68,16 @@ HalResult<T> ManagerHalController::apply(ManagerHalController::hal_fn<T>& halFn, hal = mConnectedHal; } - HalResult<T> ret = processHalResult(halFn(hal), functionName); - for (int i = 0; i < MAX_RETRIES && ret.isFailed(); i++) { - ret = processHalResult(halFn(hal), functionName); + HalResult<T> result = processHalResult(halFn(hal), functionName); + for (int i = 0; i < MAX_RETRIES && result.shouldRetry(); i++) { + { + std::lock_guard<std::mutex> lock(mConnectedHalMutex); + mConnectedHal->tryReconnect(); + } + result = processHalResult(halFn(hal), functionName); } - return ret; + return result; } // ------------------------------------------------------------------------------------------------- diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp index 6e660e7e41..13412667e0 100644 --- a/services/vibratorservice/VibratorManagerHalWrapper.cpp +++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp @@ -55,8 +55,8 @@ HalResult<std::shared_ptr<HalController>> LegacyManagerHalWrapper::getVibrator(i return HalResult<std::shared_ptr<HalController>>::ok(mController); } // Controller.init did not connect to any vibrator HAL service, so the device has no vibrator. - return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + - std::to_string(id)); + return HalResult<std::shared_ptr<HalController>>::failed( + (MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)).c_str()); } HalResult<void> LegacyManagerHalWrapper::prepareSynced(const std::vector<int32_t>&) { @@ -75,10 +75,10 @@ HalResult<void> LegacyManagerHalWrapper::cancelSynced() { std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator( int32_t vibratorId, std::shared_ptr<CallbackScheduler> callbackScheduler) { - std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [=]() { + std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [=, this]() { sp<Aidl::IVibrator> vibrator; auto result = this->getHal()->getVibrator(vibratorId, &vibrator); - return HalResult<sp<Aidl::IVibrator>>::fromStatus(result, vibrator); + return HalResultFactory::fromStatus<sp<Aidl::IVibrator>>(result, vibrator); }; auto result = reconnectFn(); if (!result.isOk()) { @@ -88,12 +88,12 @@ std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator( if (!vibrator) { return nullptr; } - return std::move(std::make_unique<AidlHalWrapper>(std::move(callbackScheduler), - std::move(vibrator), reconnectFn)); + return std::make_unique<AidlHalWrapper>(std::move(callbackScheduler), std::move(vibrator), + reconnectFn); } HalResult<void> AidlManagerHalWrapper::ping() { - return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder()); + return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder()); } void AidlManagerHalWrapper::tryReconnect() { @@ -112,8 +112,8 @@ HalResult<ManagerCapabilities> AidlManagerHalWrapper::getCapabilities() { } int32_t cap = 0; auto result = getHal()->getCapabilities(&cap); - auto ret = HalResult<ManagerCapabilities>::fromStatus(result, - static_cast<ManagerCapabilities>(cap)); + auto capabilities = static_cast<ManagerCapabilities>(cap); + auto ret = HalResultFactory::fromStatus<ManagerCapabilities>(result, capabilities); if (ret.isOk()) { // Cache copy of returned value. mCapabilities.emplace(ret.value()); @@ -129,7 +129,7 @@ HalResult<std::vector<int32_t>> AidlManagerHalWrapper::getVibratorIds() { } std::vector<int32_t> ids; auto result = getHal()->getVibratorIds(&ids); - auto ret = HalResult<std::vector<int32_t>>::fromStatus(result, ids); + auto ret = HalResultFactory::fromStatus<std::vector<int32_t>>(result, ids); if (ret.isOk()) { // Cache copy of returned value and the individual controllers. mVibratorIds.emplace(ret.value()); @@ -152,12 +152,12 @@ HalResult<std::shared_ptr<HalController>> AidlManagerHalWrapper::getVibrator(int if (it != mVibrators.end()) { return HalResult<std::shared_ptr<HalController>>::ok(it->second); } - return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + - std::to_string(id)); + return HalResult<std::shared_ptr<HalController>>::failed( + (MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)).c_str()); } HalResult<void> AidlManagerHalWrapper::prepareSynced(const std::vector<int32_t>& ids) { - auto ret = HalResult<void>::fromStatus(getHal()->prepareSynced(ids)); + auto ret = HalResultFactory::fromStatus(getHal()->prepareSynced(ids)); if (ret.isOk()) { // Force reload of all vibrator controllers that were prepared for a sync operation here. // This will trigger calls to getVibrator(id) on each controller, so they can use the @@ -179,11 +179,11 @@ HalResult<void> AidlManagerHalWrapper::triggerSynced( bool supportsCallback = capabilities.isOk() && static_cast<int32_t>(capabilities.value() & ManagerCapabilities::TRIGGER_CALLBACK); auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; - return HalResult<void>::fromStatus(getHal()->triggerSynced(cb)); + return HalResultFactory::fromStatus(getHal()->triggerSynced(cb)); } HalResult<void> AidlManagerHalWrapper::cancelSynced() { - auto ret = HalResult<void>::fromStatus(getHal()->cancelSynced()); + auto ret = HalResultFactory::fromStatus(getHal()->cancelSynced()); if (ret.isOk()) { // Force reload of all vibrator controllers that were prepared for a sync operation before. // This will trigger calls to getVibrator(id) on each controller, so they can use the diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h index 6b73d17b0a..f97442ddee 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorHalController.h +++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h @@ -64,7 +64,29 @@ public: */ Info getInfo() { static Info sDefaultInfo = InfoCache().get(); - return apply<Info>([](HalWrapper* hal) { return hal->getInfo(); }, sDefaultInfo, "getInfo"); + if (!init()) { + ALOGV("Skipped getInfo because Vibrator HAL is not available"); + return sDefaultInfo; + } + std::shared_ptr<HalWrapper> hal; + { + std::lock_guard<std::mutex> lock(mConnectedHalMutex); + hal = mConnectedHal; + } + + for (int i = 0; i < MAX_RETRIES; i++) { + Info result = hal.get()->getInfo(); + result.logFailures(); + if (result.shouldRetry()) { + tryReconnect(); + } else { + return result; + } + } + + Info result = hal.get()->getInfo(); + result.logFailures(); + return result; } /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the @@ -72,7 +94,7 @@ public: */ template <typename T> HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, const char* functionName) { - return apply(halFn, HalResult<T>::unsupported(), functionName); + return doWithRetry<T>(halFn, HalResult<T>::unsupported(), functionName); } private: @@ -90,7 +112,8 @@ private: * function name is for logging purposes. */ template <typename T> - T apply(const HalFunction<T>& halFn, T defaultValue, const char* functionName) { + HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, HalResult<T> defaultValue, + const char* functionName) { if (!init()) { ALOGV("Skipped %s because Vibrator HAL is not available", functionName); return defaultValue; @@ -101,16 +124,22 @@ private: hal = mConnectedHal; } - for (int i = 0; i < MAX_RETRIES; i++) { - T result = halFn(hal.get()); - if (result.isFailedLogged(functionName)) { - tryReconnect(); - } else { - return result; - } + HalResult<T> result = doOnce(hal.get(), halFn, functionName); + for (int i = 0; i < MAX_RETRIES && result.shouldRetry(); i++) { + tryReconnect(); + result = doOnce(hal.get(), halFn, functionName); } + return result; + } - return halFn(hal.get()); + template <typename T> + HalResult<T> doOnce(HalWrapper* hal, const HalFunction<HalResult<T>>& halFn, + const char* functionName) { + HalResult<T> result = halFn(hal); + if (result.isFailed()) { + ALOGE("Vibrator HAL %s failed: %s", functionName, result.errorMessage()); + } + return result; } }; diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h index d2cc9ad7df..39c4eb441e 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h +++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h @@ -31,101 +31,154 @@ namespace vibrator { // ------------------------------------------------------------------------------------------------- +// Base class to represent a generic result of a call to the Vibrator HAL wrapper. +class BaseHalResult { +public: + bool isOk() const { return mStatus == SUCCESS; } + bool isFailed() const { return mStatus == FAILED; } + bool isUnsupported() const { return mStatus == UNSUPPORTED; } + bool shouldRetry() const { return isFailed() && mDeadObject; } + const char* errorMessage() const { return mErrorMessage.c_str(); } + +protected: + enum Status { SUCCESS, UNSUPPORTED, FAILED }; + Status mStatus; + std::string mErrorMessage; + bool mDeadObject; + + explicit BaseHalResult(Status status, const char* errorMessage = "", bool deadObject = false) + : mStatus(status), mErrorMessage(errorMessage), mDeadObject(deadObject) {} + virtual ~BaseHalResult() = default; +}; + // Result of a call to the Vibrator HAL wrapper, holding data if successful. template <typename T> -class HalResult { +class HalResult : public BaseHalResult { public: static HalResult<T> ok(T value) { return HalResult(value); } - static HalResult<T> failed(std::string msg) { - return HalResult(std::move(msg), /* unsupported= */ false); - } - static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); } - - static HalResult<T> fromStatus(binder::Status status, T data) { - if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION || - status.transactionError() == android::UNKNOWN_TRANSACTION) { - // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is - // the same as the operation being unsupported by this HAL. Should not retry. - return HalResult<T>::unsupported(); - } - if (status.isOk()) { - return HalResult<T>::ok(data); - } - return HalResult<T>::failed(status.toString8().c_str()); + static HalResult<T> unsupported() { return HalResult(Status::UNSUPPORTED); } + static HalResult<T> failed(const char* msg) { return HalResult(Status::FAILED, msg); } + static HalResult<T> transactionFailed(const char* msg) { + return HalResult(Status::FAILED, msg, /* deadObject= */ true); } - static HalResult<T> fromStatus(hardware::vibrator::V1_0::Status status, T data); - - template <typename R> - static HalResult<T> fromReturn(hardware::Return<R>& ret, T data); - - template <typename R> - static HalResult<T> fromReturn(hardware::Return<R>& ret, - hardware::vibrator::V1_0::Status status, T data); // This will throw std::bad_optional_access if this result is not ok. const T& value() const { return mValue.value(); } const T valueOr(T&& defaultValue) const { return mValue.value_or(defaultValue); } - bool isOk() const { return !mUnsupported && mValue.has_value(); } - bool isFailed() const { return !mUnsupported && !mValue.has_value(); } - bool isUnsupported() const { return mUnsupported; } - const char* errorMessage() const { return mErrorMessage.c_str(); } - bool isFailedLogged(const char* functionNameForLogging) const { - if (isFailed()) { - ALOGE("Vibrator HAL %s failed: %s", functionNameForLogging, errorMessage()); - return true; - } - return false; - } private: std::optional<T> mValue; - std::string mErrorMessage; - bool mUnsupported; explicit HalResult(T value) - : mValue(std::make_optional(value)), mErrorMessage(), mUnsupported(false) {} - explicit HalResult(std::string errorMessage, bool unsupported) - : mValue(), mErrorMessage(std::move(errorMessage)), mUnsupported(unsupported) {} + : BaseHalResult(Status::SUCCESS), mValue(std::make_optional(value)) {} + explicit HalResult(Status status, const char* errorMessage = "", bool deadObject = false) + : BaseHalResult(status, errorMessage, deadObject), mValue() {} }; // Empty result of a call to the Vibrator HAL wrapper. template <> -class HalResult<void> { +class HalResult<void> : public BaseHalResult { public: - static HalResult<void> ok() { return HalResult(); } - static HalResult<void> failed(std::string msg) { return HalResult(std::move(msg)); } - static HalResult<void> unsupported() { return HalResult(/* unsupported= */ true); } + static HalResult<void> ok() { return HalResult(Status::SUCCESS); } + static HalResult<void> unsupported() { return HalResult(Status::UNSUPPORTED); } + static HalResult<void> failed(const char* msg) { return HalResult(Status::FAILED, msg); } + static HalResult<void> transactionFailed(const char* msg) { + return HalResult(Status::FAILED, msg, /* deadObject= */ true); + } - static HalResult<void> fromStatus(status_t status); - static HalResult<void> fromStatus(binder::Status status); - static HalResult<void> fromStatus(hardware::vibrator::V1_0::Status status); +private: + explicit HalResult(Status status, const char* errorMessage = "", bool deadObject = false) + : BaseHalResult(status, errorMessage, deadObject) {} +}; + +// ------------------------------------------------------------------------------------------------- + +// Factory functions that convert failed HIDL/AIDL results into HalResult instances. +// Implementation of static template functions needs to be in this header file for the linker. +class HalResultFactory { +public: + template <typename T> + static HalResult<T> fromStatus(binder::Status status, T data) { + return status.isOk() ? HalResult<T>::ok(data) : fromFailedStatus<T>(status); + } + + template <typename T> + static HalResult<T> fromStatus(hardware::vibrator::V1_0::Status status, T data) { + return (status == hardware::vibrator::V1_0::Status::OK) ? HalResult<T>::ok(data) + : fromFailedStatus<T>(status); + } + + template <typename T, typename R> + static HalResult<T> fromReturn(hardware::Return<R>& ret, T data) { + return ret.isOk() ? HalResult<T>::ok(data) : fromFailedReturn<T, R>(ret); + } + + template <typename T, typename R> + static HalResult<T> fromReturn(hardware::Return<R>& ret, + hardware::vibrator::V1_0::Status status, T data) { + return ret.isOk() ? fromStatus<T>(status, data) : fromFailedReturn<T, R>(ret); + } + + static HalResult<void> fromStatus(status_t status) { + return (status == android::OK) ? HalResult<void>::ok() : fromFailedStatus<void>(status); + } + + static HalResult<void> fromStatus(binder::Status status) { + return status.isOk() ? HalResult<void>::ok() : fromFailedStatus<void>(status); + } + + static HalResult<void> fromStatus(hardware::vibrator::V1_0::Status status) { + return (status == hardware::vibrator::V1_0::Status::OK) ? HalResult<void>::ok() + : fromFailedStatus<void>(status); + } template <typename R> - static HalResult<void> fromReturn(hardware::Return<R>& ret); + static HalResult<void> fromReturn(hardware::Return<R>& ret) { + return ret.isOk() ? HalResult<void>::ok() : fromFailedReturn<void, R>(ret); + } - bool isOk() const { return !mUnsupported && !mFailed; } - bool isFailed() const { return !mUnsupported && mFailed; } - bool isUnsupported() const { return mUnsupported; } - const char* errorMessage() const { return mErrorMessage.c_str(); } - bool isFailedLogged(const char* functionNameForLogging) const { - if (isFailed()) { - ALOGE("Vibrator HAL %s failed: %s", functionNameForLogging, errorMessage()); - return true; +private: + template <typename T> + static HalResult<T> fromFailedStatus(status_t status) { + auto msg = "status_t = " + statusToString(status); + return (status == android::DEAD_OBJECT) ? HalResult<T>::transactionFailed(msg.c_str()) + : HalResult<T>::failed(msg.c_str()); + } + + template <typename T> + static HalResult<T> fromFailedStatus(binder::Status status) { + if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION) { + // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is + // the same as the operation being unsupported by this HAL. Should not retry. + return HalResult<T>::unsupported(); } - return false; + if (status.exceptionCode() == binder::Status::EX_TRANSACTION_FAILED) { + return HalResult<T>::transactionFailed(status.toString8().c_str()); + } + return HalResult<T>::failed(status.toString8().c_str()); } -private: - std::string mErrorMessage; - bool mFailed; - bool mUnsupported; + template <typename T> + static HalResult<T> fromFailedStatus(hardware::vibrator::V1_0::Status status) { + switch (status) { + case hardware::vibrator::V1_0::Status::UNSUPPORTED_OPERATION: + return HalResult<T>::unsupported(); + default: + auto msg = "android::hardware::vibrator::V1_0::Status = " + toString(status); + return HalResult<T>::failed(msg.c_str()); + } + } - explicit HalResult(bool unsupported = false) - : mErrorMessage(), mFailed(false), mUnsupported(unsupported) {} - explicit HalResult(std::string errorMessage) - : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {} + template <typename T, typename R> + static HalResult<T> fromFailedReturn(hardware::Return<R>& ret) { + return ret.isDeadObject() ? HalResult<T>::transactionFailed(ret.description().c_str()) + : HalResult<T>::failed(ret.description().c_str()); + } }; +// ------------------------------------------------------------------------------------------------- + class HalCallbackWrapper : public hardware::vibrator::BnVibratorCallback { public: HalCallbackWrapper(std::function<void()> completionCallback) @@ -192,21 +245,44 @@ public: const HalResult<float> qFactor; const HalResult<std::vector<float>> maxAmplitudes; - bool isFailedLogged(const char*) const { - return capabilities.isFailedLogged("getCapabilities") || - supportedEffects.isFailedLogged("getSupportedEffects") || - supportedBraking.isFailedLogged("getSupportedBraking") || - supportedPrimitives.isFailedLogged("getSupportedPrimitives") || - primitiveDurations.isFailedLogged("getPrimitiveDuration") || - primitiveDelayMax.isFailedLogged("getPrimitiveDelayMax") || - pwlePrimitiveDurationMax.isFailedLogged("getPwlePrimitiveDurationMax") || - compositionSizeMax.isFailedLogged("getCompositionSizeMax") || - pwleSizeMax.isFailedLogged("getPwleSizeMax") || - minFrequency.isFailedLogged("getMinFrequency") || - resonantFrequency.isFailedLogged("getResonantFrequency") || - frequencyResolution.isFailedLogged("getFrequencyResolution") || - qFactor.isFailedLogged("getQFactor") || - maxAmplitudes.isFailedLogged("getMaxAmplitudes"); + void logFailures() const { + logFailure<Capabilities>(capabilities, "getCapabilities"); + logFailure<std::vector<hardware::vibrator::Effect>>(supportedEffects, + "getSupportedEffects"); + logFailure<std::vector<hardware::vibrator::Braking>>(supportedBraking, + "getSupportedBraking"); + logFailure<std::vector<hardware::vibrator::CompositePrimitive>>(supportedPrimitives, + "getSupportedPrimitives"); + logFailure<std::vector<std::chrono::milliseconds>>(primitiveDurations, + "getPrimitiveDuration"); + logFailure<std::chrono::milliseconds>(primitiveDelayMax, "getPrimitiveDelayMax"); + logFailure<std::chrono::milliseconds>(pwlePrimitiveDurationMax, + "getPwlePrimitiveDurationMax"); + logFailure<int32_t>(compositionSizeMax, "getCompositionSizeMax"); + logFailure<int32_t>(pwleSizeMax, "getPwleSizeMax"); + logFailure<float>(minFrequency, "getMinFrequency"); + logFailure<float>(resonantFrequency, "getResonantFrequency"); + logFailure<float>(frequencyResolution, "getFrequencyResolution"); + logFailure<float>(qFactor, "getQFactor"); + logFailure<std::vector<float>>(maxAmplitudes, "getMaxAmplitudes"); + } + + bool shouldRetry() const { + return capabilities.shouldRetry() || supportedEffects.shouldRetry() || + supportedBraking.shouldRetry() || supportedPrimitives.shouldRetry() || + primitiveDurations.shouldRetry() || primitiveDelayMax.shouldRetry() || + pwlePrimitiveDurationMax.shouldRetry() || compositionSizeMax.shouldRetry() || + pwleSizeMax.shouldRetry() || minFrequency.shouldRetry() || + resonantFrequency.shouldRetry() || frequencyResolution.shouldRetry() || + qFactor.shouldRetry() || maxAmplitudes.shouldRetry(); + } + +private: + template <typename T> + void logFailure(HalResult<T> result, const char* functionName) const { + if (result.isFailed()) { + ALOGE("Vibrator HAL %s failed: %s", functionName, result.errorMessage()); + } } }; @@ -230,27 +306,29 @@ public: } private: + // Create a transaction failed results as default so we can retry on the first time we get them. static const constexpr char* MSG = "never loaded"; - HalResult<Capabilities> mCapabilities = HalResult<Capabilities>::failed(MSG); + HalResult<Capabilities> mCapabilities = HalResult<Capabilities>::transactionFailed(MSG); HalResult<std::vector<hardware::vibrator::Effect>> mSupportedEffects = - HalResult<std::vector<hardware::vibrator::Effect>>::failed(MSG); + HalResult<std::vector<hardware::vibrator::Effect>>::transactionFailed(MSG); HalResult<std::vector<hardware::vibrator::Braking>> mSupportedBraking = - HalResult<std::vector<hardware::vibrator::Braking>>::failed(MSG); + HalResult<std::vector<hardware::vibrator::Braking>>::transactionFailed(MSG); HalResult<std::vector<hardware::vibrator::CompositePrimitive>> mSupportedPrimitives = - HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::failed(MSG); + HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::transactionFailed(MSG); HalResult<std::vector<std::chrono::milliseconds>> mPrimitiveDurations = - HalResult<std::vector<std::chrono::milliseconds>>::failed(MSG); + HalResult<std::vector<std::chrono::milliseconds>>::transactionFailed(MSG); HalResult<std::chrono::milliseconds> mPrimitiveDelayMax = - HalResult<std::chrono::milliseconds>::failed(MSG); + HalResult<std::chrono::milliseconds>::transactionFailed(MSG); HalResult<std::chrono::milliseconds> mPwlePrimitiveDurationMax = - HalResult<std::chrono::milliseconds>::failed(MSG); - HalResult<int32_t> mCompositionSizeMax = HalResult<int>::failed(MSG); - HalResult<int32_t> mPwleSizeMax = HalResult<int>::failed(MSG); - HalResult<float> mMinFrequency = HalResult<float>::failed(MSG); - HalResult<float> mResonantFrequency = HalResult<float>::failed(MSG); - HalResult<float> mFrequencyResolution = HalResult<float>::failed(MSG); - HalResult<float> mQFactor = HalResult<float>::failed(MSG); - HalResult<std::vector<float>> mMaxAmplitudes = HalResult<std::vector<float>>::failed(MSG); + HalResult<std::chrono::milliseconds>::transactionFailed(MSG); + HalResult<int32_t> mCompositionSizeMax = HalResult<int>::transactionFailed(MSG); + HalResult<int32_t> mPwleSizeMax = HalResult<int>::transactionFailed(MSG); + HalResult<float> mMinFrequency = HalResult<float>::transactionFailed(MSG); + HalResult<float> mResonantFrequency = HalResult<float>::transactionFailed(MSG); + HalResult<float> mFrequencyResolution = HalResult<float>::transactionFailed(MSG); + HalResult<float> mQFactor = HalResult<float>::transactionFailed(MSG); + HalResult<std::vector<float>> mMaxAmplitudes = + HalResult<std::vector<float>>::transactionFailed(MSG); friend class HalWrapper; }; diff --git a/services/vibratorservice/test/VibratorHalControllerTest.cpp b/services/vibratorservice/test/VibratorHalControllerTest.cpp index 8e77bc57f3..9b95d74899 100644 --- a/services/vibratorservice/test/VibratorHalControllerTest.cpp +++ b/services/vibratorservice/test/VibratorHalControllerTest.cpp @@ -107,17 +107,38 @@ TEST_F(VibratorHalControllerTest, TestInit) { ASSERT_EQ(1, mConnectCounter); } -TEST_F(VibratorHalControllerTest, TestGetInfoRetriesOnAnyFailure) { +TEST_F(VibratorHalControllerTest, TestGetInfoRetriesOnTransactionFailure) { EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1)); EXPECT_CALL(*mMockHal.get(), getCapabilitiesInternal()) .Times(Exactly(2)) - .WillOnce(Return(vibrator::HalResult<vibrator::Capabilities>::failed("message"))) + .WillOnce(Return(vibrator::HalResult<vibrator::Capabilities>::transactionFailed("msg"))) .WillRepeatedly(Return(vibrator::HalResult<vibrator::Capabilities>::ok( vibrator::Capabilities::ON_CALLBACK))); auto result = mController->getInfo(); - ASSERT_FALSE(result.capabilities.isFailed()); + ASSERT_TRUE(result.capabilities.isOk()); + ASSERT_EQ(1, mConnectCounter); +} + +TEST_F(VibratorHalControllerTest, TestGetInfoDoesNotRetryOnOperationFailure) { + EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0)); + EXPECT_CALL(*mMockHal.get(), getCapabilitiesInternal()) + .Times(Exactly(1)) + .WillRepeatedly(Return(vibrator::HalResult<vibrator::Capabilities>::failed("msg"))); + auto result = mController->getInfo(); + ASSERT_TRUE(result.capabilities.isFailed()); + ASSERT_EQ(1, mConnectCounter); +} + +TEST_F(VibratorHalControllerTest, TestGetInfoDoesNotRetryOnUnsupported) { + EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0)); + EXPECT_CALL(*mMockHal.get(), getCapabilitiesInternal()) + .Times(Exactly(1)) + .WillRepeatedly(Return(vibrator::HalResult<vibrator::Capabilities>::unsupported())); + + auto result = mController->getInfo(); + ASSERT_TRUE(result.capabilities.isUnsupported()); ASSERT_EQ(1, mConnectCounter); } @@ -128,48 +149,54 @@ TEST_F(VibratorHalControllerTest, TestApiCallsAreForwardedToHal) { auto result = mController->doWithRetry<void>(ON_FN, "on"); ASSERT_TRUE(result.isOk()); - ASSERT_EQ(1, mConnectCounter); } -TEST_F(VibratorHalControllerTest, TestUnsupportedApiResultDoNotResetHalConnection) { +TEST_F(VibratorHalControllerTest, TestUnsupportedApiResultDoesNotResetHalConnection) { + EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0)); EXPECT_CALL(*mMockHal.get(), off()) .Times(Exactly(1)) .WillRepeatedly(Return(vibrator::HalResult<void>::unsupported())); - ASSERT_EQ(0, mConnectCounter); auto result = mController->doWithRetry<void>(OFF_FN, "off"); ASSERT_TRUE(result.isUnsupported()); ASSERT_EQ(1, mConnectCounter); } -TEST_F(VibratorHalControllerTest, TestFailedApiResultResetsHalConnection) { +TEST_F(VibratorHalControllerTest, TestOperationFailedApiResultDoesNotResetHalConnection) { + EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0)); EXPECT_CALL(*mMockHal.get(), on(_, _)) - .Times(Exactly(2)) + .Times(Exactly(1)) .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message"))); - EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1)); - ASSERT_EQ(0, mConnectCounter); + auto result = mController->doWithRetry<void>(ON_FN, "on"); + ASSERT_TRUE(result.isFailed()); + ASSERT_EQ(1, mConnectCounter); +} + +TEST_F(VibratorHalControllerTest, TestTransactionFailedApiResultResetsHalConnection) { + EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1)); + EXPECT_CALL(*mMockHal.get(), on(_, _)) + .Times(Exactly(2)) + .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message"))); auto result = mController->doWithRetry<void>(ON_FN, "on"); ASSERT_TRUE(result.isFailed()); ASSERT_EQ(1, mConnectCounter); } -TEST_F(VibratorHalControllerTest, TestFailedApiResultReturnsSuccessAfterRetries) { +TEST_F(VibratorHalControllerTest, TestTransactionFailedApiResultReturnsSuccessAfterRetries) { { InSequence seq; EXPECT_CALL(*mMockHal.get(), ping()) .Times(Exactly(1)) - .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message"))); + .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message"))); EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1)); EXPECT_CALL(*mMockHal.get(), ping()) .Times(Exactly(1)) .WillRepeatedly(Return(vibrator::HalResult<void>::ok())); } - ASSERT_EQ(0, mConnectCounter); - auto result = mController->doWithRetry<void>(PING_FN, "ping"); ASSERT_TRUE(result.isOk()); ASSERT_EQ(1, mConnectCounter); @@ -221,11 +248,11 @@ TEST_F(VibratorHalControllerTest, TestScheduledCallbackSurvivesReconnection) { }); EXPECT_CALL(*mMockHal.get(), ping()) .Times(Exactly(1)) - .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message"))); + .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message"))); EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1)); EXPECT_CALL(*mMockHal.get(), ping()) .Times(Exactly(1)) - .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message"))); + .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message"))); } std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); diff --git a/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp b/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp index e5fbbaeac9..11a8b66968 100644 --- a/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp +++ b/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp @@ -98,8 +98,10 @@ protected: .WillRepeatedly(Return(voidResult)); if (cardinality > 1) { - // One reconnection call after each failure. - EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(7 * cardinality)); + // One reconnection for each retry. + EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(7 * (cardinality - 1))); + } else { + EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0)); } } }; @@ -141,14 +143,12 @@ TEST_F(VibratorManagerHalControllerTest, TestApiCallsAreForwardedToHal) { ASSERT_EQ(1, mConnectCounter); } -TEST_F(VibratorManagerHalControllerTest, TestUnsupportedApiResultDoNotResetHalConnection) { +TEST_F(VibratorManagerHalControllerTest, TestUnsupportedApiResultDoesNotResetHalConnection) { setHalExpectations(/* cardinality= */ 1, vibrator::HalResult<void>::unsupported(), vibrator::HalResult<vibrator::ManagerCapabilities>::unsupported(), vibrator::HalResult<std::vector<int32_t>>::unsupported(), vibrator::HalResult<std::shared_ptr<HalController>>::unsupported()); - ASSERT_EQ(0, mConnectCounter); - ASSERT_TRUE(mController->ping().isUnsupported()); ASSERT_TRUE(mController->getCapabilities().isUnsupported()); ASSERT_TRUE(mController->getVibratorIds().isUnsupported()); @@ -160,13 +160,28 @@ TEST_F(VibratorManagerHalControllerTest, TestUnsupportedApiResultDoNotResetHalCo ASSERT_EQ(1, mConnectCounter); } -TEST_F(VibratorManagerHalControllerTest, TestFailedApiResultResetsHalConnection) { - setHalExpectations(MAX_ATTEMPTS, vibrator::HalResult<void>::failed("message"), - vibrator::HalResult<vibrator::ManagerCapabilities>::failed("message"), - vibrator::HalResult<std::vector<int32_t>>::failed("message"), - vibrator::HalResult<std::shared_ptr<HalController>>::failed("message")); +TEST_F(VibratorManagerHalControllerTest, TestOperationFailedApiResultDoesNotResetHalConnection) { + setHalExpectations(/* cardinality= */ 1, vibrator::HalResult<void>::failed("msg"), + vibrator::HalResult<vibrator::ManagerCapabilities>::failed("msg"), + vibrator::HalResult<std::vector<int32_t>>::failed("msg"), + vibrator::HalResult<std::shared_ptr<HalController>>::failed("msg")); - ASSERT_EQ(0, mConnectCounter); + ASSERT_TRUE(mController->ping().isFailed()); + ASSERT_TRUE(mController->getCapabilities().isFailed()); + ASSERT_TRUE(mController->getVibratorIds().isFailed()); + ASSERT_TRUE(mController->getVibrator(VIBRATOR_ID).isFailed()); + ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isFailed()); + ASSERT_TRUE(mController->triggerSynced([]() {}).isFailed()); + ASSERT_TRUE(mController->cancelSynced().isFailed()); + + ASSERT_EQ(1, mConnectCounter); +} + +TEST_F(VibratorManagerHalControllerTest, TestTransactionFailedApiResultResetsHalConnection) { + setHalExpectations(MAX_ATTEMPTS, vibrator::HalResult<void>::transactionFailed("m"), + vibrator::HalResult<vibrator::ManagerCapabilities>::transactionFailed("m"), + vibrator::HalResult<std::vector<int32_t>>::transactionFailed("m"), + vibrator::HalResult<std::shared_ptr<HalController>>::transactionFailed("m")); ASSERT_TRUE(mController->ping().isFailed()); ASSERT_TRUE(mController->getCapabilities().isFailed()); @@ -184,14 +199,13 @@ TEST_F(VibratorManagerHalControllerTest, TestFailedApiResultReturnsSuccessAfterR InSequence seq; EXPECT_CALL(*mMockHal.get(), ping()) .Times(Exactly(1)) - .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message"))); + .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message"))); EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1)); EXPECT_CALL(*mMockHal.get(), ping()) .Times(Exactly(1)) .WillRepeatedly(Return(vibrator::HalResult<void>::ok())); } - ASSERT_EQ(0, mConnectCounter); ASSERT_TRUE(mController->ping().isOk()); ASSERT_EQ(1, mConnectCounter); } diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp index 1593cb18ec..dffc281fa1 100644 --- a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp +++ b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp @@ -254,13 +254,14 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorRecoversVibratorPointer EXPECT_CALL(*mMockHal.get(), getVibrator(Eq(kVibratorId), _)) .Times(Exactly(3)) .WillOnce(DoAll(SetArgPointee<1>(nullptr), - Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))) + Return(Status::fromExceptionCode( + Status::Exception::EX_TRANSACTION_FAILED)))) .WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status()))); EXPECT_CALL(*mMockVibrator.get(), off()) .Times(Exactly(3)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) + .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_TRANSACTION_FAILED))) + .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_TRANSACTION_FAILED))) .WillRepeatedly(Return(Status())); // Get vibrator controller is successful even if first getVibrator. |