diff options
137 files changed, 2319 insertions, 2589 deletions
diff --git a/cmds/dumpstate/res/default_screenshot.png b/cmds/dumpstate/res/default_screenshot.png Binary files differindex 10f36aa52b..1e14306504 100644 --- a/cmds/dumpstate/res/default_screenshot.png +++ b/cmds/dumpstate/res/default_screenshot.png diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp index 36dcbca0a3..b87ef2dc36 100644 --- a/cmds/idlcli/Android.bp +++ b/cmds/idlcli/Android.bp @@ -25,13 +25,8 @@ cc_defaults { name: "idlcli-defaults", shared_libs: [ "android.hardware.vibrator-V3-ndk", - "android.hardware.vibrator@1.0", - "android.hardware.vibrator@1.1", - "android.hardware.vibrator@1.2", - "android.hardware.vibrator@1.3", "libbase", "libbinder_ndk", - "libhidlbase", "liblog", "libutils", ], diff --git a/cmds/idlcli/utils.h b/cmds/idlcli/utils.h index 262f2e50b6..dc52c57987 100644 --- a/cmds/idlcli/utils.h +++ b/cmds/idlcli/utils.h @@ -18,7 +18,6 @@ #define FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_ #include <android/binder_enums.h> -#include <hidl/HidlSupport.h> #include <iomanip> #include <iostream> diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h index b9434950f6..1a9993e5e7 100644 --- a/cmds/idlcli/vibrator.h +++ b/cmds/idlcli/vibrator.h @@ -22,102 +22,30 @@ #include <aidl/android/hardware/vibrator/IVibratorManager.h> #include <android/binder_manager.h> #include <android/binder_process.h> -#include <android/hardware/vibrator/1.3/IVibrator.h> #include "IdlCli.h" #include "utils.h" namespace android { -using hardware::Return; +using ::aidl::android::hardware::vibrator::IVibrator; using idlcli::IdlCli; -static constexpr int NUM_TRIES = 2; - -// Creates a Return<R> with STATUS::EX_NULL_POINTER. -template <class R> -inline R NullptrStatus() { - using ::android::hardware::Status; - return Status::fromExceptionCode(Status::EX_NULL_POINTER); -} - -template <> -inline ndk::ScopedAStatus NullptrStatus() { - return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_NULL_POINTER)); -} - -template <typename I> inline auto getService(std::string name) { - const auto instance = std::string() + I::descriptor + "/" + name; + const auto instance = std::string() + IVibrator::descriptor + "/" + name; auto vibBinder = ndk::SpAIBinder(AServiceManager_checkService(instance.c_str())); - return I::fromBinder(vibBinder); -} - -template <> -inline auto getService<android::hardware::vibrator::V1_0::IVibrator>(std::string name) { - return android::hardware::vibrator::V1_0::IVibrator::getService(name); -} - -template <> -inline auto getService<android::hardware::vibrator::V1_1::IVibrator>(std::string name) { - return android::hardware::vibrator::V1_1::IVibrator::getService(name); -} - -template <> -inline auto getService<android::hardware::vibrator::V1_2::IVibrator>(std::string name) { - return android::hardware::vibrator::V1_2::IVibrator::getService(name); -} - -template <> -inline auto getService<android::hardware::vibrator::V1_3::IVibrator>(std::string name) { - return android::hardware::vibrator::V1_3::IVibrator::getService(name); + return IVibrator::fromBinder(vibBinder); } -template <typename I> -using shared_ptr = std::invoke_result_t<decltype(getService<I>)&, std::string>; - -template <typename I> -class HalWrapper { -public: - static std::unique_ptr<HalWrapper> Create() { - // Assume that if getService returns a nullptr, HAL is not available on the - // device. - const auto name = IdlCli::Get().getName(); - auto hal = getService<I>(name.empty() ? "default" : name); - return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr; - } - - template <class R, class... Args0, class... Args1> - R call(R (I::*fn)(Args0...), Args1&&... args1) { - return (*mHal.*fn)(std::forward<Args1>(args1)...); - } - -private: - HalWrapper(shared_ptr<I>&& hal) : mHal(std::move(hal)) {} - -private: - shared_ptr<I> mHal; -}; - -template <typename I> static auto getHal() { - static auto sHalWrapper = HalWrapper<I>::Create(); - return sHalWrapper.get(); -} - -template <class R, class I, class... Args0, class... Args1> -R halCall(R (I::*fn)(Args0...), Args1&&... args1) { - auto hal = getHal<I>(); - return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>(); + // Assume that if getService returns a nullptr, HAL is not available on the device. + const auto name = IdlCli::Get().getName(); + return getService(name.empty() ? "default" : name); } namespace idlcli { namespace vibrator { -namespace V1_0 = ::android::hardware::vibrator::V1_0; -namespace V1_1 = ::android::hardware::vibrator::V1_1; -namespace V1_2 = ::android::hardware::vibrator::V1_2; -namespace V1_3 = ::android::hardware::vibrator::V1_3; namespace aidl = ::aidl::android::hardware::vibrator; class VibratorCallback : public aidl::BnVibratorCallback { diff --git a/cmds/idlcli/vibrator/CommandAlwaysOnDisable.cpp b/cmds/idlcli/vibrator/CommandAlwaysOnDisable.cpp index 9afa300c2b..cae690945c 100644 --- a/cmds/idlcli/vibrator/CommandAlwaysOnDisable.cpp +++ b/cmds/idlcli/vibrator/CommandAlwaysOnDisable.cpp @@ -51,21 +51,17 @@ class CommandAlwaysOnDisable : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::alwaysOnDisable, mId); - - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + auto status = hal->alwaysOnDisable(mId); + + std::cout << "Status: " << status.getDescription() << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } int32_t mId; diff --git a/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp b/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp index bb7f9f284a..410ca52068 100644 --- a/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp +++ b/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp @@ -72,21 +72,17 @@ class CommandAlwaysOnEnable : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::alwaysOnEnable, mId, mEffect, mStrength); - - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + auto status = hal->alwaysOnEnable(mId, mEffect, mStrength); + + std::cout << "Status: " << status.getDescription() << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } int32_t mId; diff --git a/cmds/idlcli/vibrator/CommandCompose.cpp b/cmds/idlcli/vibrator/CommandCompose.cpp index eb9008b68e..41acb98a95 100644 --- a/cmds/idlcli/vibrator/CommandCompose.cpp +++ b/cmds/idlcli/vibrator/CommandCompose.cpp @@ -89,7 +89,7 @@ class CommandCompose : public Command { } Status doMain(Args && /*args*/) override { - auto hal = getHal<aidl::IVibrator>(); + auto hal = getHal(); if (!hal) { return UNAVAILABLE; @@ -104,7 +104,7 @@ class CommandCompose : public Command { callback = ndk::SharedRefBase::make<VibratorCallback>(); } - auto status = hal->call(&aidl::IVibrator::compose, mComposite, callback); + auto status = hal->compose(mComposite, callback); if (status.isOk() && callback) { callback->waitForComplete(); diff --git a/cmds/idlcli/vibrator/CommandComposePwle.cpp b/cmds/idlcli/vibrator/CommandComposePwle.cpp index b8308ce16f..5f6bf8677e 100644 --- a/cmds/idlcli/vibrator/CommandComposePwle.cpp +++ b/cmds/idlcli/vibrator/CommandComposePwle.cpp @@ -163,7 +163,7 @@ class CommandComposePwle : public Command { } Status doMain(Args && /*args*/) override { - auto hal = getHal<aidl::IVibrator>(); + auto hal = getHal(); if (!hal) { return UNAVAILABLE; @@ -178,7 +178,7 @@ class CommandComposePwle : public Command { callback = ndk::SharedRefBase::make<VibratorCallback>(); } - auto status = hal->call(&aidl::IVibrator::composePwle, mCompositePwle, callback); + auto status = hal->composePwle(mCompositePwle, callback); if (status.isOk() && callback) { callback->waitForComplete(); diff --git a/cmds/idlcli/vibrator/CommandComposePwleV2.cpp b/cmds/idlcli/vibrator/CommandComposePwleV2.cpp index 6d3cf84a2e..bd682eacae 100644 --- a/cmds/idlcli/vibrator/CommandComposePwleV2.cpp +++ b/cmds/idlcli/vibrator/CommandComposePwleV2.cpp @@ -108,7 +108,7 @@ class CommandComposePwleV2 : public Command { } Status doMain(Args&& /*args*/) override { - auto hal = getHal<aidl::IVibrator>(); + auto hal = getHal(); if (!hal) { return UNAVAILABLE; @@ -123,7 +123,7 @@ class CommandComposePwleV2 : public Command { callback = ndk::SharedRefBase::make<VibratorCallback>(); } - auto status = hal->call(&aidl::IVibrator::composePwleV2, mCompositePwle, callback); + auto status = hal->composePwleV2(mCompositePwle, callback); if (status.isOk() && callback) { callback->waitForComplete(); diff --git a/cmds/idlcli/vibrator/CommandGetBandwidthAmplitudeMap.cpp b/cmds/idlcli/vibrator/CommandGetBandwidthAmplitudeMap.cpp index aa01a11237..44115e9a97 100644 --- a/cmds/idlcli/vibrator/CommandGetBandwidthAmplitudeMap.cpp +++ b/cmds/idlcli/vibrator/CommandGetBandwidthAmplitudeMap.cpp @@ -44,29 +44,38 @@ class CommandGetBandwidthAmplitudeMap : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; + auto hal = getHal(); + + if (!hal) { + return UNAVAILABLE; + } + std::vector<float> bandwidthAmplitude; float frequencyMinimumHz; float frequencyResolutionHz; - Status ret; - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = - hal->call(&aidl::IVibrator::getBandwidthAmplitudeMap, &bandwidthAmplitude); - statusStr = status.getDescription(); - ret = (status.isOk() ? OK : ERROR); + auto status = hal->getBandwidthAmplitudeMap(&bandwidthAmplitude); - status = hal->call(&aidl::IVibrator::getFrequencyMinimum, &frequencyMinimumHz); - ret = (status.isOk() ? OK : ERROR); + if (!status.isOk()) { + std::cout << "Status: " << status.getDescription() << std::endl; + return ERROR; + } - status = - hal->call(&aidl::IVibrator::getFrequencyResolution, &frequencyResolutionHz); - ret = (status.isOk() ? OK : ERROR); - } else { - return UNAVAILABLE; + status = hal->getFrequencyMinimum(&frequencyMinimumHz); + + if (!status.isOk()) { + std::cout << "Status: " << status.getDescription() << std::endl; + return ERROR; } - std::cout << "Status: " << statusStr << std::endl; + status = hal->getFrequencyResolution(&frequencyResolutionHz); + + if (!status.isOk()) { + std::cout << "Status: " << status.getDescription() << std::endl; + return ERROR; + } + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Bandwidth Amplitude Map: " << std::endl; float frequency = frequencyMinimumHz; for (auto &e : bandwidthAmplitude) { @@ -74,7 +83,7 @@ class CommandGetBandwidthAmplitudeMap : public Command { frequency += frequencyResolutionHz; } - return ret; + return OK; } }; diff --git a/cmds/idlcli/vibrator/CommandGetCapabilities.cpp b/cmds/idlcli/vibrator/CommandGetCapabilities.cpp index 303a9895e4..507d871cac 100644 --- a/cmds/idlcli/vibrator/CommandGetCapabilities.cpp +++ b/cmds/idlcli/vibrator/CommandGetCapabilities.cpp @@ -42,22 +42,19 @@ class CommandGetCapabilities : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - int32_t cap; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getCapabilities, &cap); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + int32_t cap; + auto status = hal->getCapabilities(&cap); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Capabilities: " << std::bitset<32>(cap) << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetCompositionDelayMax.cpp b/cmds/idlcli/vibrator/CommandGetCompositionDelayMax.cpp index 10508bd4dc..1c1eb3c6ff 100644 --- a/cmds/idlcli/vibrator/CommandGetCompositionDelayMax.cpp +++ b/cmds/idlcli/vibrator/CommandGetCompositionDelayMax.cpp @@ -44,22 +44,19 @@ class CommandGetCompositionDelayMax : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - int32_t maxDelayMs; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getCompositionDelayMax, &maxDelayMs); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + int32_t maxDelayMs; + auto status = hal->getCompositionDelayMax(&maxDelayMs); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Max Delay: " << maxDelayMs << " ms" << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetCompositionSizeMax.cpp b/cmds/idlcli/vibrator/CommandGetCompositionSizeMax.cpp index 900cb18809..cfd4c53ceb 100644 --- a/cmds/idlcli/vibrator/CommandGetCompositionSizeMax.cpp +++ b/cmds/idlcli/vibrator/CommandGetCompositionSizeMax.cpp @@ -44,22 +44,19 @@ class CommandGetCompositionSizeMax : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - int32_t maxSize; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getCompositionSizeMax, &maxSize); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + int32_t maxSize; + auto status = hal->getCompositionSizeMax(&maxSize); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Max Size: " << maxSize << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetFrequencyMinimum.cpp b/cmds/idlcli/vibrator/CommandGetFrequencyMinimum.cpp index 504c6482ad..2a614466ab 100644 --- a/cmds/idlcli/vibrator/CommandGetFrequencyMinimum.cpp +++ b/cmds/idlcli/vibrator/CommandGetFrequencyMinimum.cpp @@ -44,22 +44,19 @@ class CommandGetFrequencyMinimum : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - float frequencyMinimumHz; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getFrequencyMinimum, &frequencyMinimumHz); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + float frequencyMinimumHz; + auto status = hal->getFrequencyMinimum(&frequencyMinimumHz); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Minimum Frequency: " << frequencyMinimumHz << " Hz" << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetFrequencyResolution.cpp b/cmds/idlcli/vibrator/CommandGetFrequencyResolution.cpp index de358385a0..157d6bf732 100644 --- a/cmds/idlcli/vibrator/CommandGetFrequencyResolution.cpp +++ b/cmds/idlcli/vibrator/CommandGetFrequencyResolution.cpp @@ -44,23 +44,19 @@ class CommandGetFrequencyResolution : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - float frequencyResolutionHz; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = - hal->call(&aidl::IVibrator::getFrequencyResolution, &frequencyResolutionHz); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + float frequencyResolutionHz; + auto status = hal->getFrequencyResolution(&frequencyResolutionHz); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Frequency Resolution: " << frequencyResolutionHz << " Hz" << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp b/cmds/idlcli/vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp index 2edd0caf2e..2eb45100db 100644 --- a/cmds/idlcli/vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp +++ b/cmds/idlcli/vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp @@ -46,26 +46,22 @@ class CommandGetFrequencyToOutputAccelerationMap : public Command { } Status doMain(Args&& /*args*/) override { - std::string statusStr; - std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap; - Status ret; - - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getFrequencyToOutputAccelerationMap, - &frequencyToOutputAccelerationMap); - statusStr = status.getDescription(); - ret = (status.isOk() ? OK : ERROR); - } else { + auto hal = getHal(); + + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap; + auto status = hal->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Frequency to Output Amplitude Map: " << std::endl; for (auto& entry : frequencyToOutputAccelerationMap) { std::cout << entry.frequencyHz << " " << entry.maxOutputAccelerationGs << std::endl; } - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetPrimitiveDuration.cpp b/cmds/idlcli/vibrator/CommandGetPrimitiveDuration.cpp index 460d39e64f..c957f6b316 100644 --- a/cmds/idlcli/vibrator/CommandGetPrimitiveDuration.cpp +++ b/cmds/idlcli/vibrator/CommandGetPrimitiveDuration.cpp @@ -57,22 +57,19 @@ class CommandGetPrimitiveDuration : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - int32_t duration; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getPrimitiveDuration, mPrimitive, &duration); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + int32_t duration; + auto status = hal->getPrimitiveDuration(mPrimitive, &duration); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Duration: " << duration << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } CompositePrimitive mPrimitive; diff --git a/cmds/idlcli/vibrator/CommandGetPwleCompositionSizeMax.cpp b/cmds/idlcli/vibrator/CommandGetPwleCompositionSizeMax.cpp index b2c35519eb..c1b027833b 100644 --- a/cmds/idlcli/vibrator/CommandGetPwleCompositionSizeMax.cpp +++ b/cmds/idlcli/vibrator/CommandGetPwleCompositionSizeMax.cpp @@ -44,22 +44,19 @@ class CommandGetPwleCompositionSizeMax : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - int32_t maxSize; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getPwleCompositionSizeMax, &maxSize); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + int32_t maxSize; + auto status = hal->getPwleCompositionSizeMax(&maxSize); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Max Size: " << maxSize << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetPwlePrimitiveDurationMax.cpp b/cmds/idlcli/vibrator/CommandGetPwlePrimitiveDurationMax.cpp index 90819731c4..ed00ba0c13 100644 --- a/cmds/idlcli/vibrator/CommandGetPwlePrimitiveDurationMax.cpp +++ b/cmds/idlcli/vibrator/CommandGetPwlePrimitiveDurationMax.cpp @@ -44,22 +44,19 @@ class CommandGetPwlePrimitiveDurationMax : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - int32_t maxDurationMs; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getPwlePrimitiveDurationMax, &maxDurationMs); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + int32_t maxDurationMs; + auto status = hal->getPwlePrimitiveDurationMax(&maxDurationMs); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Primitive duration max: " << maxDurationMs << " ms" << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetPwleV2CompositionSizeMax.cpp b/cmds/idlcli/vibrator/CommandGetPwleV2CompositionSizeMax.cpp index cca072c46f..f780b8bfd7 100644 --- a/cmds/idlcli/vibrator/CommandGetPwleV2CompositionSizeMax.cpp +++ b/cmds/idlcli/vibrator/CommandGetPwleV2CompositionSizeMax.cpp @@ -44,22 +44,19 @@ class CommandGetPwleV2CompositionSizeMax : public Command { } Status doMain(Args&& /*args*/) override { - std::string statusStr; - int32_t maxSize; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getPwleV2CompositionSizeMax, &maxSize); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + int32_t maxSize; + auto status = hal->getPwleV2CompositionSizeMax(&maxSize); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Max Size: " << maxSize << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp index dbbfe1a6d4..e84e969e7c 100644 --- a/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp +++ b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp @@ -44,23 +44,19 @@ class CommandGetPwleV2PrimitiveDurationMaxMillis : public Command { } Status doMain(Args&& /*args*/) override { - std::string statusStr; - int32_t maxDurationMs; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getPwleV2PrimitiveDurationMaxMillis, - &maxDurationMs); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + int32_t maxDurationMs; + auto status = hal->getPwleV2PrimitiveDurationMaxMillis(&maxDurationMs); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Primitive duration max: " << maxDurationMs << " ms" << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp index 09225c49c4..448fd2adc2 100644 --- a/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp +++ b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp @@ -44,23 +44,19 @@ class CommandGetPwleV2PrimitiveDurationMinMillis : public Command { } Status doMain(Args&& /*args*/) override { - std::string statusStr; - int32_t minDurationMs; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getPwleV2PrimitiveDurationMinMillis, - &minDurationMs); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + int32_t minDurationMs; + auto status = hal->getPwleV2PrimitiveDurationMinMillis(&minDurationMs); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Primitive duration min: " << minDurationMs << " ms" << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetQFactor.cpp b/cmds/idlcli/vibrator/CommandGetQFactor.cpp index a2681e905b..e04bad9384 100644 --- a/cmds/idlcli/vibrator/CommandGetQFactor.cpp +++ b/cmds/idlcli/vibrator/CommandGetQFactor.cpp @@ -42,22 +42,19 @@ class CommandGetQFactor : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - float qFactor; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getQFactor, &qFactor); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + float qFactor; + auto status = hal->getQFactor(&qFactor); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Q Factor: " << qFactor << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetResonantFrequency.cpp b/cmds/idlcli/vibrator/CommandGetResonantFrequency.cpp index 81a6391de5..e222ea656e 100644 --- a/cmds/idlcli/vibrator/CommandGetResonantFrequency.cpp +++ b/cmds/idlcli/vibrator/CommandGetResonantFrequency.cpp @@ -44,22 +44,19 @@ class CommandGetResonantFrequency : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - float resonantFrequencyHz; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getResonantFrequency, &resonantFrequencyHz); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + float resonantFrequencyHz; + auto status = hal->getResonantFrequency(&resonantFrequencyHz); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Resonant Frequency: " << resonantFrequencyHz << " Hz" << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetSupportedAlwaysOnEffects.cpp b/cmds/idlcli/vibrator/CommandGetSupportedAlwaysOnEffects.cpp index edfcd9195a..9b05540fce 100644 --- a/cmds/idlcli/vibrator/CommandGetSupportedAlwaysOnEffects.cpp +++ b/cmds/idlcli/vibrator/CommandGetSupportedAlwaysOnEffects.cpp @@ -44,25 +44,22 @@ class CommandGetSupportedAlwaysOnEffects : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - std::vector<Effect> effects; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getSupportedAlwaysOnEffects, &effects); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + std::vector<Effect> effects; + auto status = hal->getSupportedAlwaysOnEffects(&effects); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Effects:" << std::endl; for (auto &e : effects) { std::cout << " " << toString(e) << std::endl; } - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetSupportedBraking.cpp b/cmds/idlcli/vibrator/CommandGetSupportedBraking.cpp index b326e07c22..f95f682fc0 100644 --- a/cmds/idlcli/vibrator/CommandGetSupportedBraking.cpp +++ b/cmds/idlcli/vibrator/CommandGetSupportedBraking.cpp @@ -44,25 +44,22 @@ class CommandGetSupportedBraking : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - std::vector<Braking> braking; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getSupportedBraking, &braking); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + std::vector<Braking> braking; + auto status = hal->getSupportedBraking(&braking); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Braking Mechanisms:" << std::endl; for (auto &e : braking) { std::cout << " " << toString(e) << std::endl; } - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetSupportedEffects.cpp b/cmds/idlcli/vibrator/CommandGetSupportedEffects.cpp index 7658f22def..05de1b87cf 100644 --- a/cmds/idlcli/vibrator/CommandGetSupportedEffects.cpp +++ b/cmds/idlcli/vibrator/CommandGetSupportedEffects.cpp @@ -44,25 +44,22 @@ class CommandGetSupportedEffects : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - std::vector<Effect> effects; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getSupportedEffects, &effects); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + std::vector<Effect> effects; + auto status = hal->getSupportedEffects(&effects); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Effects:" << std::endl; for (auto &e : effects) { std::cout << " " << toString(e) << std::endl; } - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandGetSupportedPrimitives.cpp b/cmds/idlcli/vibrator/CommandGetSupportedPrimitives.cpp index d101681914..0f33f0f2e9 100644 --- a/cmds/idlcli/vibrator/CommandGetSupportedPrimitives.cpp +++ b/cmds/idlcli/vibrator/CommandGetSupportedPrimitives.cpp @@ -44,25 +44,22 @@ class CommandGetSupportedPrimitives : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - std::vector<CompositePrimitive> primitives; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::getSupportedPrimitives, &primitives); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + std::vector<CompositePrimitive> primitives; + auto status = hal->getSupportedPrimitives(&primitives); + + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Primitives:" << std::endl; for (auto &e : primitives) { std::cout << " " << toString(e) << std::endl; } - return ret; + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandOff.cpp b/cmds/idlcli/vibrator/CommandOff.cpp index cedb9fec06..e55b44a9c8 100644 --- a/cmds/idlcli/vibrator/CommandOff.cpp +++ b/cmds/idlcli/vibrator/CommandOff.cpp @@ -42,24 +42,17 @@ class CommandOff : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - Status ret; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::off); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else if (auto hal = getHal<V1_0::IVibrator>()) { - auto status = hal->call(&V1_0::IVibrator::off); - statusStr = toString(status); - ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR; - } else { + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + auto status = hal->off(); - return ret; + std::cout << "Status: " << status.getDescription() << std::endl; + + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandOn.cpp b/cmds/idlcli/vibrator/CommandOn.cpp index 8212fc14a7..856c219750 100644 --- a/cmds/idlcli/vibrator/CommandOn.cpp +++ b/cmds/idlcli/vibrator/CommandOn.cpp @@ -67,34 +67,27 @@ class CommandOn : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - Status ret; - std::shared_ptr<VibratorCallback> callback; + auto hal = getHal(); - if (auto hal = getHal<aidl::IVibrator>()) { - ABinderProcess_setThreadPoolMaxThreadCount(1); - ABinderProcess_startThreadPool(); + if (!hal) { + return UNAVAILABLE; + } - int32_t cap; - hal->call(&aidl::IVibrator::getCapabilities, &cap); + std::shared_ptr<VibratorCallback> callback; - if (mBlocking && (cap & aidl::IVibrator::CAP_ON_CALLBACK)) { - callback = ndk::SharedRefBase::make<VibratorCallback>(); - } + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); - auto status = hal->call(&aidl::IVibrator::on, mDuration, callback); + int32_t cap; + hal->getCapabilities(&cap); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else if (auto hal = getHal<V1_0::IVibrator>()) { - auto status = hal->call(&V1_0::IVibrator::on, mDuration); - statusStr = toString(status); - ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR; - } else { - return UNAVAILABLE; + if (mBlocking && (cap & aidl::IVibrator::CAP_ON_CALLBACK)) { + callback = ndk::SharedRefBase::make<VibratorCallback>(); } - if (ret == OK && mBlocking) { + auto status = hal->on(mDuration, callback); + + if (status.isOk() && mBlocking) { if (callback) { callback->waitForComplete(); } else { @@ -102,9 +95,9 @@ class CommandOn : public Command { } } - std::cout << "Status: " << statusStr << std::endl; + std::cout << "Status: " << status.getDescription() << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } bool mBlocking; diff --git a/cmds/idlcli/vibrator/CommandPerform.cpp b/cmds/idlcli/vibrator/CommandPerform.cpp index c897686cbe..0a354e2c5a 100644 --- a/cmds/idlcli/vibrator/CommandPerform.cpp +++ b/cmds/idlcli/vibrator/CommandPerform.cpp @@ -28,34 +28,6 @@ class CommandVibrator; namespace vibrator { -/* - * The following static asserts are only relevant here because the argument - * parser uses a single implementation for determining the string names. - */ -static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) == - static_cast<uint8_t>(aidl::EffectStrength::LIGHT)); -static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) == - static_cast<uint8_t>(aidl::EffectStrength::MEDIUM)); -static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) == - static_cast<uint8_t>(aidl::EffectStrength::STRONG)); -static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) == - static_cast<uint8_t>(aidl::Effect::CLICK)); -static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) == - static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK)); -static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == static_cast<uint8_t>(aidl::Effect::TICK)); -static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == static_cast<uint8_t>(aidl::Effect::THUD)); -static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == static_cast<uint8_t>(aidl::Effect::POP)); -static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) == - static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK)); -static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) == - static_cast<uint8_t>(aidl::Effect::RINGTONE_1)); -static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) == - static_cast<uint8_t>(aidl::Effect::RINGTONE_2)); -static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) == - static_cast<uint8_t>(aidl::Effect::RINGTONE_15)); -static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) == - static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); - using aidl::Effect; using aidl::EffectStrength; @@ -107,61 +79,31 @@ class CommandPerform : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; + auto hal = getHal(); + + if (!hal) { + return UNAVAILABLE; + } + uint32_t lengthMs; - Status ret; std::shared_ptr<VibratorCallback> callback; - if (auto hal = getHal<aidl::IVibrator>()) { - ABinderProcess_setThreadPoolMaxThreadCount(1); - ABinderProcess_startThreadPool(); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); - int32_t cap; - hal->call(&aidl::IVibrator::getCapabilities, &cap); + int32_t cap; + hal->getCapabilities(&cap); - if (mBlocking && (cap & aidl::IVibrator::CAP_PERFORM_CALLBACK)) { - callback = ndk::SharedRefBase::make<VibratorCallback>(); - } - - int32_t aidlLengthMs; - auto status = hal->call(&aidl::IVibrator::perform, mEffect, mStrength, callback, - &aidlLengthMs); + if (mBlocking && (cap & aidl::IVibrator::CAP_PERFORM_CALLBACK)) { + callback = ndk::SharedRefBase::make<VibratorCallback>(); + } - statusStr = status.getDescription(); - lengthMs = static_cast<uint32_t>(aidlLengthMs); - ret = status.isOk() ? OK : ERROR; - } else { - Return<void> hidlRet; - V1_0::Status status; - auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) { - status = retStatus; - lengthMs = retLengthMs; - }; - - if (auto hal = getHal<V1_3::IVibrator>()) { - hidlRet = - hal->call(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(mEffect), - static_cast<V1_0::EffectStrength>(mStrength), callback); - } else if (auto hal = getHal<V1_2::IVibrator>()) { - hidlRet = - hal->call(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(mEffect), - static_cast<V1_0::EffectStrength>(mStrength), callback); - } else if (auto hal = getHal<V1_1::IVibrator>()) { - hidlRet = hal->call(&V1_1::IVibrator::perform_1_1, - static_cast<V1_1::Effect_1_1>(mEffect), - static_cast<V1_0::EffectStrength>(mStrength), callback); - } else if (auto hal = getHal<V1_0::IVibrator>()) { - hidlRet = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect), - static_cast<V1_0::EffectStrength>(mStrength), callback); - } else { - return UNAVAILABLE; - } + int32_t aidlLengthMs; + auto status = hal->perform(mEffect, mStrength, callback, &aidlLengthMs); - statusStr = toString(status); - ret = hidlRet.isOk() && status == V1_0::Status::OK ? OK : ERROR; - } + lengthMs = static_cast<uint32_t>(aidlLengthMs); - if (ret == OK && mBlocking) { + if (status.isOk() && mBlocking) { if (callback) { callback->waitForComplete(); } else { @@ -169,10 +111,10 @@ class CommandPerform : public Command { } } - std::cout << "Status: " << statusStr << std::endl; + std::cout << "Status: " << status.getDescription() << std::endl; std::cout << "Length: " << lengthMs << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } bool mBlocking; diff --git a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp index 8b8058c4fd..8050723729 100644 --- a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp +++ b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp @@ -50,25 +50,17 @@ class CommandSetAmplitude : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - Status ret; - - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::setAmplitude, - static_cast<float>(mAmplitude) / UINT8_MAX); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else if (auto hal = getHal<V1_0::IVibrator>()) { - auto status = hal->call(&V1_0::IVibrator::setAmplitude, mAmplitude); - statusStr = toString(status); - ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR; - } else { + auto hal = getHal(); + + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + auto status = hal->setAmplitude(static_cast<float>(mAmplitude) / UINT8_MAX); + + std::cout << "Status: " << status.getDescription() << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } uint8_t mAmplitude; diff --git a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp index 179579310a..8f8d4b7641 100644 --- a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp +++ b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp @@ -48,24 +48,17 @@ class CommandSetExternalControl : public Command { } Status doMain(Args && /*args*/) override { - std::string statusStr; - Status ret; - - if (auto hal = getHal<aidl::IVibrator>()) { - auto status = hal->call(&aidl::IVibrator::setExternalControl, mEnable); - statusStr = status.getDescription(); - ret = status.isOk() ? OK : ERROR; - } else if (auto hal = getHal<V1_3::IVibrator>()) { - auto status = hal->call(&V1_3::IVibrator::setExternalControl, mEnable); - statusStr = toString(status); - ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR; - } else { + auto hal = getHal(); + + if (!hal) { return UNAVAILABLE; } - std::cout << "Status: " << statusStr << std::endl; + auto status = hal->setExternalControl(mEnable); + + std::cout << "Status: " << status.getDescription() << std::endl; - return ret; + return status.isOk() ? OK : ERROR; } bool mEnable; diff --git a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp index cdc529a2f3..31ee954f63 100644 --- a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp +++ b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp @@ -42,15 +42,22 @@ class CommandSupportsAmplitudeControl : public Command { } Status doMain(Args && /*args*/) override { - auto ret = halCall(&V1_0::IVibrator::supportsAmplitudeControl); + auto hal = getHal(); - if (!ret.isOk()) { + if (!hal) { return UNAVAILABLE; } - std::cout << "Result: " << std::boolalpha << ret << std::endl; + int32_t cap; - return OK; + auto status = hal->getCapabilities(&cap); + + bool hasAmplitudeControl = cap & IVibrator::CAP_AMPLITUDE_CONTROL; + + std::cout << "Status: " << status.getDescription() << std::endl; + std::cout << "Result: " << std::boolalpha << hasAmplitudeControl << std::endl; + + return status.isOk() ? OK : ERROR; } }; diff --git a/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp b/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp index ed15d76286..f0c542cfe3 100644 --- a/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp +++ b/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp @@ -42,15 +42,22 @@ class CommandSupportsExternalControl : public Command { } Status doMain(Args && /*args*/) override { - auto ret = halCall(&V1_3::IVibrator::supportsExternalControl); + auto hal = getHal(); - if (!ret.isOk()) { + if (!hal) { return UNAVAILABLE; } - std::cout << "Result: " << std::boolalpha << ret << std::endl; + int32_t cap; - return OK; + auto status = hal->getCapabilities(&cap); + + bool hasExternalControl = cap & IVibrator::CAP_EXTERNAL_CONTROL; + + std::cout << "Status: " << status.getDescription() << std::endl; + std::cout << "Result: " << std::boolalpha << hasExternalControl << std::endl; + + return status.isOk() ? OK : ERROR; } }; diff --git a/data/etc/Android.bp b/data/etc/Android.bp index 0ac5266a0c..f320504551 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -119,12 +119,24 @@ prebuilt_etc { } prebuilt_etc { + name: "android.hardware.nfc.ese.prebuilt.xml", + src: "android.hardware.nfc.ese.xml", + defaults: ["frameworks_native_data_etc_defaults"], +} + +prebuilt_etc { name: "android.hardware.nfc.hce.prebuilt.xml", src: "android.hardware.nfc.hce.xml", defaults: ["frameworks_native_data_etc_defaults"], } prebuilt_etc { + name: "android.hardware.nfc.hcef.prebuilt.xml", + src: "android.hardware.nfc.hcef.xml", + defaults: ["frameworks_native_data_etc_defaults"], +} + +prebuilt_etc { name: "android.hardware.reboot_escrow.prebuilt.xml", src: "android.hardware.reboot_escrow.xml", defaults: ["frameworks_native_data_etc_defaults"], @@ -511,6 +523,12 @@ prebuilt_etc { } prebuilt_etc { + name: "com.nxp.mifare.prebuilt.xml", + src: "com.nxp.mifare.xml", + defaults: ["frameworks_native_data_etc_defaults"], +} + +prebuilt_etc { name: "go_handheld_core_hardware.prebuilt.xml", src: "go_handheld_core_hardware.xml", defaults: ["frameworks_native_data_etc_defaults"], diff --git a/include/android/system_health.h b/include/android/system_health.h index bdb1413555..4494e32815 100644 --- a/include/android/system_health.h +++ b/include/android/system_health.h @@ -316,8 +316,6 @@ int ASystemHealth_getMaxCpuHeadroomTidsSize(size_t* _Nonnull outSize); /** * Gets the range of the calculation window size for CPU headroom. * - * In API version 36, the range will be a superset of [50, 10000]. - * * Available since API level 36. * * @param outMinMillis Non-null output pointer to be set to the minimum window size in milliseconds. @@ -332,8 +330,6 @@ __INTRODUCED_IN(36); /** * Gets the range of the calculation window size for GPU headroom. * - * In API version 36, the range will be a superset of [50, 10000]. - * * Available since API level 36. * * @param outMinMillis Non-null output pointer to be set to the minimum window size in milliseconds. diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp index 16023ffa82..1f3a45a6df 100644 --- a/libs/binder/RpcSession.cpp +++ b/libs/binder/RpcSession.cpp @@ -188,7 +188,9 @@ status_t RpcSession::setupInetClient(const char* addr, unsigned int port) { } status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) { - return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) -> status_t { + return setupClient([&, fd = std::move(fd), + request = std::move(request)](const std::vector<uint8_t>& sessionId, + bool incoming) mutable -> status_t { if (!fd.ok()) { fd = request(); if (!fd.ok()) return BAD_VALUE; @@ -476,8 +478,10 @@ sp<RpcServer> RpcSession::server() { return server; } -status_t RpcSession::setupClient(const std::function<status_t(const std::vector<uint8_t>& sessionId, - bool incoming)>& connectAndInit) { +template <typename Fn, + typename /* = std::enable_if_t<std::is_invocable_r_v< + status_t, Fn, const std::vector<uint8_t>&, bool>> */> +status_t RpcSession::setupClient(Fn&& connectAndInit) { { RpcMutexLockGuard _l(mMutex); LOG_ALWAYS_FATAL_IF(mStartedSetup, "Must only setup session once"); diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h index af37bf29a4..c9f92da009 100644 --- a/libs/binder/include/binder/RpcSession.h +++ b/libs/binder/include/binder/RpcSession.h @@ -25,6 +25,7 @@ #include <map> #include <optional> +#include <type_traits> #include <vector> namespace android { @@ -291,9 +292,14 @@ private: // join on thread passed to preJoinThreadOwnership static void join(sp<RpcSession>&& session, PreJoinSetupResult&& result); - [[nodiscard]] status_t setupClient( - const std::function<status_t(const std::vector<uint8_t>& sessionId, bool incoming)>& - connectAndInit); + // This is a workaround to support move-only functors. + // TODO: use std::move_only_function when it becomes available. + template <typename Fn, + // Fn must be a callable type taking (const std::vector<uint8_t>&, bool) and returning + // status_t + typename = std::enable_if_t< + std::is_invocable_r_v<status_t, Fn, const std::vector<uint8_t>&, bool>>> + [[nodiscard]] status_t setupClient(Fn&& connectAndInit); [[nodiscard]] status_t setupSocketClient(const RpcSocketAddress& address); [[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address, const std::vector<uint8_t>& sessionId, diff --git a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp index 48c0ea636b..1949cbb039 100644 --- a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp +++ b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp @@ -134,9 +134,14 @@ AIBinder* ARpcSession_setupInet(ARpcSession* session, const char* address, unsig // // param will be passed to requestFd. Callers can use param to pass contexts to // the requestFd function. +// +// paramDeleteFd will be called when requestFd and param are no longer in use. +// Callers can pass a function deleting param if necessary. Callers can set +// paramDeleteFd to null if callers doesn't need to clean up param. AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* session, int (*requestFd)(void* param), - void* param); + void* param, + void (*paramDeleteFd)(void* param)); // Sets the file descriptor transport mode for this session. void ARpcSession_setFileDescriptorTransportMode(ARpcSession* session, diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp index 64b1be25d2..8177fb07db 100644 --- a/libs/binder/libbinder_rpc_unstable.cpp +++ b/libs/binder/libbinder_rpc_unstable.cpp @@ -248,9 +248,18 @@ AIBinder* ARpcSession_setupInet(ARpcSession* handle, const char* address, unsign #endif // __TRUSTY__ AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* handle, int (*requestFd)(void* param), - void* param) { + void* param, void (*paramDeleteFd)(void* param)) { auto session = handleToStrongPointer<RpcSession>(handle); - auto request = [=] { return unique_fd{requestFd(param)}; }; + auto deleter = [=](void* param) { + if (paramDeleteFd) { + paramDeleteFd(param); + } + }; + // TODO: use unique_ptr once setupPreconnectedClient uses std::move_only_function. + std::shared_ptr<void> sharedParam(param, deleter); + auto request = [=, sharedParam = std::move(sharedParam)] { + return unique_fd{requestFd(sharedParam.get())}; + }; if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) { ALOGE("Failed to set up preconnected client. error: %s", statusToString(status).c_str()); return nullptr; diff --git a/libs/binder/rust/rpcbinder/src/session.rs b/libs/binder/rust/rpcbinder/src/session.rs index 09688a21a7..411b9de849 100644 --- a/libs/binder/rust/rpcbinder/src/session.rs +++ b/libs/binder/rust/rpcbinder/src/session.rs @@ -195,11 +195,13 @@ impl RpcSessionRef { /// take ownership of) file descriptors already connected to it. pub fn setup_preconnected_client<T: FromIBinder + ?Sized>( &self, - mut request_fd: impl FnMut() -> Option<RawFd>, + request_fd: impl FnMut() -> Option<RawFd>, ) -> Result<Strong<T>, StatusCode> { - // Double reference the factory because trait objects aren't FFI safe. - let mut request_fd_ref: RequestFd = &mut request_fd; - let param = &mut request_fd_ref as *mut RequestFd as *mut c_void; + // Trait objects aren't FFI safe, so *mut c_void can't be converted back to + // *mut dyn FnMut() -> Option<RawFd>>. Double box the factory to make it possible to get + // the factory from *mut c_void (to *mut Box<dyn<...>>) in the callbacks. + let request_fd_box: Box<dyn FnMut() -> Option<RawFd>> = Box::new(request_fd); + let param = Box::into_raw(Box::new(request_fd_box)) as *mut c_void; // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership @@ -209,6 +211,7 @@ impl RpcSessionRef { self.as_ptr(), Some(request_fd_wrapper), param, + Some(param_delete_fd_wrapper), )) }; Self::get_interface(service) @@ -225,13 +228,18 @@ impl RpcSessionRef { } } -type RequestFd<'a> = &'a mut dyn FnMut() -> Option<RawFd>; - unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int { - let request_fd_ptr = param as *mut RequestFd; + let request_fd_ptr = param as *mut Box<dyn FnMut() -> Option<RawFd>>; // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the // BinderFdFactory reference, with param being a properly aligned non-null pointer to an // initialized instance. let request_fd = unsafe { request_fd_ptr.as_mut().unwrap() }; request_fd().unwrap_or(-1) } + +unsafe extern "C" fn param_delete_fd_wrapper(param: *mut c_void) { + // SAFETY: This is only ever called by RpcPreconnectedClient, with param being the + // pointer returned from Box::into_raw. + let request_fd_box = unsafe { Box::from_raw(param as *mut Box<dyn FnMut() -> Option<RawFd>>) }; + drop(request_fd_box); +} diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp index cac054eb1b..457eaa5a76 100644 --- a/libs/binder/tests/parcel_fuzzer/Android.bp +++ b/libs/binder/tests/parcel_fuzzer/Android.bp @@ -109,6 +109,9 @@ cc_library_static { "libcutils", "libutils", ], + header_libs: [ + "libaidl_transactions", + ], local_include_dirs: ["include_random_parcel"], export_include_dirs: ["include_random_parcel"], } diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp index 02e69cc371..11aa76891b 100644 --- a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp +++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include <aidl/transaction_ids.h> #include <fuzzbinder/libbinder_driver.h> #include <fuzzbinder/random_parcel.h> @@ -31,6 +33,28 @@ void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider) { fuzzService(std::vector<sp<IBinder>>{binder}, std::move(provider)); } +uint32_t getCode(FuzzedDataProvider& provider) { + if (provider.ConsumeBool()) { + return provider.ConsumeIntegral<uint32_t>(); + } + + // Most of the AIDL services will have small set of transaction codes. + if (provider.ConsumeBool()) { + return provider.ConsumeIntegralInRange<uint32_t>(0, 100); + } + + if (provider.ConsumeBool()) { + return provider.PickValueInArray<uint32_t>( + {IBinder::DUMP_TRANSACTION, IBinder::PING_TRANSACTION, + IBinder::SHELL_COMMAND_TRANSACTION, IBinder::INTERFACE_TRANSACTION, + IBinder::SYSPROPS_TRANSACTION, IBinder::EXTENSION_TRANSACTION, + IBinder::TWEET_TRANSACTION, IBinder::LIKE_TRANSACTION}); + } + + return provider.ConsumeIntegralInRange<uint32_t>(aidl::kLastMetaMethodId, + aidl::kFirstMetaMethodId); +} + void fuzzService(const std::vector<sp<IBinder>>& binders, FuzzedDataProvider&& provider) { RandomParcelOptions options{ .extraBinders = binders, @@ -61,16 +85,7 @@ void fuzzService(const std::vector<sp<IBinder>>& binders, FuzzedDataProvider&& p } while (provider.remaining_bytes() > 0) { - // Most of the AIDL services will have small set of transaction codes. - // TODO(b/295942369) : Add remaining transact codes from IBinder.h - uint32_t code = provider.ConsumeBool() ? provider.ConsumeIntegral<uint32_t>() - : provider.ConsumeBool() - ? provider.ConsumeIntegralInRange<uint32_t>(0, 100) - : provider.PickValueInArray<uint32_t>( - {IBinder::DUMP_TRANSACTION, IBinder::PING_TRANSACTION, - IBinder::SHELL_COMMAND_TRANSACTION, IBinder::INTERFACE_TRANSACTION, - IBinder::SYSPROPS_TRANSACTION, IBinder::EXTENSION_TRANSACTION, - IBinder::TWEET_TRANSACTION, IBinder::LIKE_TRANSACTION}); + uint32_t code = getCode(provider); uint32_t flags = provider.ConsumeIntegral<uint32_t>(); Parcel data; // for increased fuzz coverage diff --git a/libs/binder/trusty/rust/binder_rpc_unstable_bindgen/rules.mk b/libs/binder/trusty/rust/binder_rpc_unstable_bindgen/rules.mk index ef1b7c3cf8..40fc21867d 100644 --- a/libs/binder/trusty/rust/binder_rpc_unstable_bindgen/rules.mk +++ b/libs/binder/trusty/rust/binder_rpc_unstable_bindgen/rules.mk @@ -30,6 +30,8 @@ MODULE_LIBRARY_DEPS += \ trusty/user/base/lib/libstdc++-trusty \ trusty/user/base/lib/trusty-sys \ +MODULE_SRCDEPS := $(LIBBINDER_DIR)/include_rpc_unstable/binder_rpc_unstable.hpp + MODULE_BINDGEN_SRC_HEADER := $(LOCAL_DIR)/BinderBindings.hpp MODULE_BINDGEN_FLAGS += \ diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 5ab31dbaba..b5fa321fc2 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -281,6 +281,7 @@ filegroup { "SurfaceControl.cpp", "SurfaceComposerClient.cpp", "SyncFeatures.cpp", + "TransactionState.cpp", "VsyncEventData.cpp", "view/Surface.cpp", "WindowInfosListenerReporter.cpp", diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 43855dadcd..ad95d1a85a 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -55,6 +55,28 @@ namespace android { using gui::FocusRequest; using gui::WindowInfoHandle; +namespace { +bool isSameWindowHandle(const sp<WindowInfoHandle>& lhs, const sp<WindowInfoHandle>& rhs) { + if (lhs == rhs) { + return true; + } + + if (!lhs || !rhs) { + return false; + } + + return *lhs->getInfo() == *rhs->getInfo(); +}; + +bool isSameSurfaceControl(const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) { + if (lhs == rhs) { + return true; + } + + return SurfaceControl::isSameSurface(lhs, rhs); +}; +} // namespace + layer_state_t::layer_state_t() : surface(nullptr), layerId(-1), @@ -73,7 +95,6 @@ layer_state_t::layer_state_t() transformToDisplayInverse(false), crop({0, 0, -1, -1}), dataspace(ui::Dataspace::UNKNOWN), - surfaceDamageRegion(), api(-1), colorTransform(mat4()), bgColor(0), @@ -117,19 +138,21 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeFloat, crop.left); SAFE_PARCEL(output.writeFloat, crop.bottom); SAFE_PARCEL(output.writeFloat, crop.right); - SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, relativeLayerSurfaceControl); - SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, parentSurfaceControlForChild); + SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, + mNotDefCmpState.relativeLayerSurfaceControl); + SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, + mNotDefCmpState.parentSurfaceControlForChild); SAFE_PARCEL(output.writeFloat, color.r); SAFE_PARCEL(output.writeFloat, color.g); SAFE_PARCEL(output.writeFloat, color.b); SAFE_PARCEL(output.writeFloat, color.a); - SAFE_PARCEL(windowInfoHandle->writeToParcel, &output); - SAFE_PARCEL(output.write, transparentRegion); + SAFE_PARCEL(mNotDefCmpState.windowInfoHandle->writeToParcel, &output); + SAFE_PARCEL(output.write, mNotDefCmpState.transparentRegion); SAFE_PARCEL(output.writeUint32, bufferTransform); SAFE_PARCEL(output.writeBool, transformToDisplayInverse); SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dataspace)); SAFE_PARCEL(output.write, hdrMetadata); - SAFE_PARCEL(output.write, surfaceDamageRegion); + SAFE_PARCEL(output.write, mNotDefCmpState.surfaceDamageRegion); SAFE_PARCEL(output.writeInt32, api); if (sidebandStream) { @@ -241,8 +264,10 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readFloat, &crop.bottom); SAFE_PARCEL(input.readFloat, &crop.right); - SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &relativeLayerSurfaceControl); - SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &parentSurfaceControlForChild); + SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, + &mNotDefCmpState.relativeLayerSurfaceControl); + SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, + &mNotDefCmpState.parentSurfaceControlForChild); float tmpFloat = 0; SAFE_PARCEL(input.readFloat, &tmpFloat); @@ -254,9 +279,9 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readFloat, &tmpFloat); color.a = tmpFloat; - SAFE_PARCEL(windowInfoHandle->readFromParcel, &input); + SAFE_PARCEL(mNotDefCmpState.windowInfoHandle->readFromParcel, &input); - SAFE_PARCEL(input.read, transparentRegion); + SAFE_PARCEL(input.read, mNotDefCmpState.transparentRegion); SAFE_PARCEL(input.readUint32, &bufferTransform); SAFE_PARCEL(input.readBool, &transformToDisplayInverse); @@ -265,7 +290,7 @@ status_t layer_state_t::read(const Parcel& input) dataspace = static_cast<ui::Dataspace>(tmpUint32); SAFE_PARCEL(input.read, hdrMetadata); - SAFE_PARCEL(input.read, surfaceDamageRegion); + SAFE_PARCEL(input.read, mNotDefCmpState.surfaceDamageRegion); SAFE_PARCEL(input.readInt32, &api); bool tmpBool = false; @@ -583,7 +608,7 @@ void layer_state_t::merge(const layer_state_t& other) { } if (other.what & eTransparentRegionChanged) { what |= eTransparentRegionChanged; - transparentRegion = other.transparentRegion; + mNotDefCmpState.transparentRegion = other.mNotDefCmpState.transparentRegion; } if (other.what & eFlagsChanged) { what |= eFlagsChanged; @@ -615,11 +640,13 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eRelativeLayerChanged; what &= ~eLayerChanged; z = other.z; - relativeLayerSurfaceControl = other.relativeLayerSurfaceControl; + mNotDefCmpState.relativeLayerSurfaceControl = + other.mNotDefCmpState.relativeLayerSurfaceControl; } if (other.what & eReparent) { what |= eReparent; - parentSurfaceControlForChild = other.parentSurfaceControlForChild; + mNotDefCmpState.parentSurfaceControlForChild = + other.mNotDefCmpState.parentSurfaceControlForChild; } if (other.what & eBufferTransformChanged) { what |= eBufferTransformChanged; @@ -665,7 +692,7 @@ void layer_state_t::merge(const layer_state_t& other) { } if (other.what & eSurfaceDamageRegionChanged) { what |= eSurfaceDamageRegionChanged; - surfaceDamageRegion = other.surfaceDamageRegion; + mNotDefCmpState.surfaceDamageRegion = other.mNotDefCmpState.surfaceDamageRegion; } if (other.what & eApiChanged) { what |= eApiChanged; @@ -684,7 +711,8 @@ void layer_state_t::merge(const layer_state_t& other) { } if (other.what & eInputInfoChanged) { what |= eInputInfoChanged; - windowInfoHandle = sp<WindowInfoHandle>::make(*other.windowInfoHandle); + mNotDefCmpState.windowInfoHandle = + sp<WindowInfoHandle>::make(*other.mNotDefCmpState.windowInfoHandle); } if (other.what & eBackgroundColorChanged) { what |= eBackgroundColorChanged; @@ -807,7 +835,8 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF(diff, eAlphaChanged, other, color.a); CHECK_DIFF(diff, eMatrixChanged, other, matrix); if (other.what & eTransparentRegionChanged && - (!transparentRegion.hasSameRects(other.transparentRegion))) { + (!mNotDefCmpState.transparentRegion.hasSameRects( + other.mNotDefCmpState.transparentRegion))) { diff |= eTransparentRegionChanged; } if (other.what & eFlagsChanged) { @@ -824,8 +853,8 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { diff &= ~eLayerChanged; } if (other.what & eReparent && - !SurfaceControl::isSameSurface(parentSurfaceControlForChild, - other.parentSurfaceControlForChild)) { + !SurfaceControl::isSameSurface(mNotDefCmpState.parentSurfaceControlForChild, + other.mNotDefCmpState.parentSurfaceControlForChild)) { diff |= eReparent; } CHECK_DIFF(diff, eBufferTransformChanged, other, bufferTransform); @@ -839,7 +868,8 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF(diff, eCachingHintChanged, other, cachingHint); CHECK_DIFF(diff, eHdrMetadataChanged, other, hdrMetadata); if (other.what & eSurfaceDamageRegionChanged && - (!surfaceDamageRegion.hasSameRects(other.surfaceDamageRegion))) { + (!mNotDefCmpState.surfaceDamageRegion.hasSameRects( + other.mNotDefCmpState.surfaceDamageRegion))) { diff |= eSurfaceDamageRegionChanged; } CHECK_DIFF(diff, eApiChanged, other, api); @@ -901,6 +931,38 @@ status_t layer_state_t::matrix22_t::read(const Parcel& input) { SAFE_PARCEL(input.readFloat, &dsdy); return NO_ERROR; } +void layer_state_t::updateTransparentRegion(const Region& transparentRegion) { + what |= eTransparentRegionChanged; + mNotDefCmpState.transparentRegion = transparentRegion; +} +void layer_state_t::updateSurfaceDamageRegion(const Region& surfaceDamageRegion) { + what |= eSurfaceDamageRegionChanged; + mNotDefCmpState.surfaceDamageRegion = surfaceDamageRegion; +} +void layer_state_t::updateRelativeLayer(const sp<SurfaceControl>& relativeTo, int32_t z) { + what |= layer_state_t::eRelativeLayerChanged; + what &= ~layer_state_t::eLayerChanged; + mNotDefCmpState.relativeLayerSurfaceControl = relativeTo; + this->z = z; +} +void layer_state_t::updateParentLayer(const sp<SurfaceControl>& newParent) { + what |= layer_state_t::eReparent; + mNotDefCmpState.parentSurfaceControlForChild = + newParent ? newParent->getParentingLayer() : nullptr; +} +void layer_state_t::updateInputWindowInfo(sp<gui::WindowInfoHandle>&& info) { + what |= eInputInfoChanged; + mNotDefCmpState.windowInfoHandle = std::move(info); +} + +bool layer_state_t::NotDefaultComparableState::operator==( + const NotDefaultComparableState& rhs) const { + return transparentRegion.hasSameRects(rhs.transparentRegion) && + surfaceDamageRegion.hasSameRects(rhs.surfaceDamageRegion) && + isSameWindowHandle(windowInfoHandle, rhs.windowInfoHandle) && + isSameSurfaceControl(relativeLayerSurfaceControl, rhs.relativeLayerSurfaceControl) && + isSameSurfaceControl(parentSurfaceControlForChild, rhs.parentSurfaceControlForChild); +} // ------------------------------- InputWindowCommands ---------------------------------------- @@ -1034,8 +1096,8 @@ status_t BufferData::readFromParcel(const Parcel* input) { } status_t TrustedPresentationListener::writeToParcel(Parcel* parcel) const { - SAFE_PARCEL(parcel->writeStrongBinder, callbackInterface); - SAFE_PARCEL(parcel->writeInt32, callbackId); + SAFE_PARCEL(parcel->writeStrongBinder, mState.callbackInterface); + SAFE_PARCEL(parcel->writeInt32, mState.callbackId); return NO_ERROR; } @@ -1043,9 +1105,9 @@ status_t TrustedPresentationListener::readFromParcel(const Parcel* parcel) { sp<IBinder> tmpBinder = nullptr; SAFE_PARCEL(parcel->readNullableStrongBinder, &tmpBinder); if (tmpBinder) { - callbackInterface = checked_interface_cast<ITransactionCompletedListener>(tmpBinder); + mState.callbackInterface = checked_interface_cast<ITransactionCompletedListener>(tmpBinder); } - SAFE_PARCEL(parcel->readInt32, &callbackId); + SAFE_PARCEL(parcel->readInt32, &mState.callbackId); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index bb7184f9db..e407a63d10 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1391,11 +1391,16 @@ void SurfaceComposerClient::Transaction::enableDebugLogCallPoints() { // --------------------------------------------------------------------------- sp<IBinder> SurfaceComposerClient::createVirtualDisplay(const std::string& displayName, - bool isSecure, const std::string& uniqueId, + bool isSecure, bool optimizeForPower, + const std::string& uniqueId, float requestedRefreshRate) { + const gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy = optimizeForPower + ? gui::ISurfaceComposer::OptimizationPolicy::optimizeForPower + : gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance; sp<IBinder> display = nullptr; binder::Status status = ComposerServiceAIDL::getComposerService()->createVirtualDisplay(displayName, isSecure, + optimizationPolicy, uniqueId, requestedRefreshRate, &display); @@ -1523,11 +1528,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelat mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eRelativeLayerChanged; - s->what &= ~layer_state_t::eLayerChanged; - s->relativeLayerSurfaceControl = relativeTo; - s->z = z; - + s->updateRelativeLayer(relativeTo, z); registerSurfaceControlForCallback(sc); return *this; } @@ -1557,9 +1558,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrans mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eTransparentRegionChanged; - s->transparentRegion = transparentRegion; - + s->updateTransparentRegion(transparentRegion); registerSurfaceControlForCallback(sc); return *this; } @@ -1721,9 +1720,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent if (SurfaceControl::isSameSurface(sc, newParent)) { return *this; } - s->what |= layer_state_t::eReparent; - s->parentSurfaceControlForChild = newParent ? newParent->getParentingLayer() : nullptr; - + s->updateParentLayer(newParent); registerSurfaceControlForCallback(sc); return *this; } @@ -2009,9 +2006,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSurfa mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eSurfaceDamageRegionChanged; - s->surfaceDamageRegion = surfaceDamageRegion; - + s->updateSurfaceDamageRegion(surfaceDamageRegion); registerSurfaceControlForCallback(sc); return *this; } @@ -2130,21 +2125,20 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput mStatus = BAD_INDEX; return *this; } - s->windowInfoHandle = std::move(info); - s->what |= layer_state_t::eInputInfoChanged; + s->updateInputWindowInfo(std::move(info)); return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow( const FocusRequest& request) { - mInputWindowCommands.focusRequests.push_back(request); + mInputWindowCommands.addFocusRequest(request); return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::addWindowInfosReportedListener( sp<gui::IWindowInfosReportedListener> windowInfosReportedListener) { - mInputWindowCommands.windowInfosReportedListeners.insert(windowInfosReportedListener); + mInputWindowCommands.addWindowInfosReportedListener(windowInfosReportedListener); return *this; } @@ -2364,10 +2358,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setStret return *this; } -bool SurfaceComposerClient::flagEdgeExtensionEffectUseShader() { - return com::android::graphics::libgui::flags::edge_extension_shader(); -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setEdgeExtensionEffect( const sp<SurfaceControl>& sc, const gui::EdgeExtensionParameters& effect) { layer_state_t* s = getLayerState(sc); @@ -2572,8 +2562,9 @@ SurfaceComposerClient::Transaction::setTrustedPresentationCallback( } s->what |= layer_state_t::eTrustedPresentationInfoChanged; s->trustedPresentationThresholds = thresholds; - s->trustedPresentationListener.callbackInterface = TransactionCompletedListener::getIInstance(); - s->trustedPresentationListener.callbackId = sc->getLayerId(); + s->trustedPresentationListener.configure( + {.callbackInterface = TransactionCompletedListener::getIInstance(), + .callbackId = sc->getLayerId()}); return *this; } @@ -2589,8 +2580,7 @@ SurfaceComposerClient::Transaction::clearTrustedPresentationCallback(const sp<Su } s->what |= layer_state_t::eTrustedPresentationInfoChanged; s->trustedPresentationThresholds = TrustedPresentationThresholds(); - s->trustedPresentationListener.callbackInterface = nullptr; - s->trustedPresentationListener.callbackId = -1; + s->trustedPresentationListener.clear(); return *this; } diff --git a/libs/gui/TransactionState.cpp b/libs/gui/TransactionState.cpp new file mode 100644 index 0000000000..9e09bc2644 --- /dev/null +++ b/libs/gui/TransactionState.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "TransactionState" +#include <gui/LayerState.h> +#include <gui/SurfaceComposerClient.h> +#include <gui/TransactionState.h> +#include <private/gui/ParcelUtils.h> +#include <algorithm> + +namespace android { + +status_t TransactionState::writeToParcel(Parcel* parcel) const { + SAFE_PARCEL(parcel->writeUint64, mId); + SAFE_PARCEL(parcel->writeUint32, mFlags); + SAFE_PARCEL(parcel->writeInt64, mDesiredPresentTime); + SAFE_PARCEL(parcel->writeBool, mIsAutoTimestamp); + SAFE_PARCEL(parcel->writeParcelable, mFrameTimelineInfo); + SAFE_PARCEL(parcel->writeStrongBinder, mApplyToken); + SAFE_PARCEL(parcel->writeBool, mMayContainBuffer); + SAFE_PARCEL(parcel->writeBool, mLogCallPoints); + + SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mDisplayStates.size())); + for (auto const& displayState : mDisplayStates) { + displayState.write(*parcel); + } + SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mComposerStates.size())); + for (auto const& composerState : mComposerStates) { + composerState.write(*parcel); + } + + mInputWindowCommands.write(*parcel); + SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mUncacheBuffers.size())); + for (const client_cache_t& uncacheBuffer : mUncacheBuffers) { + SAFE_PARCEL(parcel->writeStrongBinder, uncacheBuffer.token.promote()); + SAFE_PARCEL(parcel->writeUint64, uncacheBuffer.id); + } + + SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mMergedTransactionIds.size())); + for (auto mergedTransactionId : mMergedTransactionIds) { + SAFE_PARCEL(parcel->writeUint64, mergedTransactionId); + } + + SAFE_PARCEL(parcel->writeBool, mHasListenerCallbacks); + SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mListenerCallbacks.size())); + for (const auto& [listener, callbackIds] : mListenerCallbacks) { + SAFE_PARCEL(parcel->writeStrongBinder, listener); + SAFE_PARCEL(parcel->writeParcelableVector, callbackIds); + } + + return NO_ERROR; +} + +status_t TransactionState::readFromParcel(const Parcel* parcel) { + SAFE_PARCEL(parcel->readUint64, &mId); + SAFE_PARCEL(parcel->readUint32, &mFlags); + SAFE_PARCEL(parcel->readInt64, &mDesiredPresentTime); + SAFE_PARCEL(parcel->readBool, &mIsAutoTimestamp); + SAFE_PARCEL(parcel->readParcelable, &mFrameTimelineInfo); + SAFE_PARCEL(parcel->readNullableStrongBinder, &mApplyToken); + SAFE_PARCEL(parcel->readBool, &mMayContainBuffer); + SAFE_PARCEL(parcel->readBool, &mLogCallPoints); + + uint32_t count; + SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize()) + mDisplayStates.clear(); + mDisplayStates.reserve(count); + for (size_t i = 0; i < count; i++) { + DisplayState displayState; + if (displayState.read(*parcel) == BAD_VALUE) { + return BAD_VALUE; + } + mDisplayStates.emplace_back(std::move(displayState)); + } + + SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize()) + mComposerStates.clear(); + mComposerStates.reserve(count); + for (size_t i = 0; i < count; i++) { + ComposerState composerState; + if (composerState.read(*parcel) == BAD_VALUE) { + return BAD_VALUE; + } + mComposerStates.emplace_back(std::move(composerState)); + } + + if (status_t status = mInputWindowCommands.read(*parcel) != NO_ERROR) { + return status; + } + + SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize()) + mUncacheBuffers.clear(); + mUncacheBuffers.reserve(count); + for (size_t i = 0; i < count; i++) { + client_cache_t client_cache; + sp<IBinder> tmpBinder; + SAFE_PARCEL(parcel->readStrongBinder, &tmpBinder); + client_cache.token = tmpBinder; + SAFE_PARCEL(parcel->readUint64, &client_cache.id); + mUncacheBuffers.emplace_back(std::move(client_cache)); + } + + SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize()) + mMergedTransactionIds.clear(); + mMergedTransactionIds.resize(count); + for (size_t i = 0; i < count; i++) { + SAFE_PARCEL(parcel->readUint64, &mMergedTransactionIds[i]); + } + + SAFE_PARCEL(parcel->readBool, &mHasListenerCallbacks); + SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize()); + mListenerCallbacks.clear(); + mListenerCallbacks.reserve(count); + for (uint32_t i = 0; i < count; i++) { + sp<IBinder> tmpBinder; + SAFE_PARCEL(parcel->readStrongBinder, &tmpBinder); + std::vector<CallbackId> callbackIds; + SAFE_PARCEL(parcel->readParcelableVector, &callbackIds); + mListenerCallbacks.emplace_back(tmpBinder, callbackIds); + } + + return NO_ERROR; +} + +void TransactionState::merge(TransactionState&& other, + const std::function<void(layer_state_t&)>& onBufferOverwrite) { + while (mMergedTransactionIds.size() + other.mMergedTransactionIds.size() > + MAX_MERGE_HISTORY_LENGTH - 1 && + mMergedTransactionIds.size() > 0) { + mMergedTransactionIds.pop_back(); + } + if (other.mMergedTransactionIds.size() == MAX_MERGE_HISTORY_LENGTH) { + mMergedTransactionIds.insert(mMergedTransactionIds.begin(), + other.mMergedTransactionIds.begin(), + other.mMergedTransactionIds.end() - 1); + } else if (other.mMergedTransactionIds.size() > 0u) { + mMergedTransactionIds.insert(mMergedTransactionIds.begin(), + other.mMergedTransactionIds.begin(), + other.mMergedTransactionIds.end()); + } + mMergedTransactionIds.insert(mMergedTransactionIds.begin(), other.mId); + + for (auto const& otherState : other.mComposerStates) { + if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(), + [&otherState](const auto& composerState) { + return composerState.state.surface == + otherState.state.surface; + }); + it != mComposerStates.end()) { + if (otherState.state.what & layer_state_t::eBufferChanged) { + onBufferOverwrite(it->state); + } + it->state.merge(otherState.state); + } else { + mComposerStates.push_back(otherState); + } + } + + for (auto const& state : other.mDisplayStates) { + if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(), + [&state](const auto& displayState) { + return displayState.token == state.token; + }); + it != mDisplayStates.end()) { + it->merge(state); + } else { + mDisplayStates.push_back(state); + } + } + + for (const auto& cacheId : other.mUncacheBuffers) { + mUncacheBuffers.push_back(cacheId); + } + + mInputWindowCommands.merge(other.mInputWindowCommands); + // TODO(b/385156191) Consider merging desired present time. + mFlags |= other.mFlags; + mMayContainBuffer |= other.mMayContainBuffer; + mLogCallPoints |= other.mLogCallPoints; + + // mApplyToken is explicitly not merged. Token should be set before applying the transactions to + // make synchronization decisions a bit simpler. + mergeFrameTimelineInfo(other.mFrameTimelineInfo); + other.clear(); +} + +// copied from FrameTimelineInfo::merge() +void TransactionState::mergeFrameTimelineInfo(const FrameTimelineInfo& other) { + // When merging vsync Ids we take the oldest valid one + if (mFrameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID && + other.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { + if (other.vsyncId > mFrameTimelineInfo.vsyncId) { + mFrameTimelineInfo = other; + } + } else if (mFrameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) { + mFrameTimelineInfo = other; + } +} + +void TransactionState::clear() { + mComposerStates.clear(); + mDisplayStates.clear(); + mListenerCallbacks.clear(); + mHasListenerCallbacks = false; + mInputWindowCommands.clear(); + mUncacheBuffers.clear(); + mDesiredPresentTime = 0; + mIsAutoTimestamp = true; + mApplyToken = nullptr; + mFrameTimelineInfo = {}; + mMergedTransactionIds.clear(); + mFlags = 0; + mMayContainBuffer = false; + mLogCallPoints = false; +} + +layer_state_t* TransactionState::getLayerState(const sp<SurfaceControl>& sc) { + auto handle = sc->getLayerStateHandle(); + if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(), + [&handle](const auto& composerState) { + return composerState.state.surface == handle; + }); + it != mComposerStates.end()) { + return &it->state; + } + + // we don't have it, add an initialized layer_state to our list + ComposerState s; + s.state.surface = handle; + s.state.layerId = sc->getLayerId(); + mComposerStates.push_back(s); + + return &mComposerStates.back().state; +} + +DisplayState& TransactionState::getDisplayState(const sp<IBinder>& token) { + if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(), + [token](const auto& display) { return display.token == token; }); + it != mDisplayStates.end()) { + return *it; + } + + // If display state doesn't exist, add a new one. + DisplayState s; + s.token = token; + mDisplayStates.push_back(s); + return mDisplayStates.back(); +} + +}; // namespace android diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl index da47ee27ba..9b2f089665 100644 --- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl +++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl @@ -67,6 +67,11 @@ interface ISurfaceComposer { frameRateOverride = 1 << 1, } + enum OptimizationPolicy { + optimizeForPower = 0, + optimizeForPerformance = 1, + } + /** * Signal that we're done booting. * Requires ACCESS_SURFACE_FLINGER permission @@ -97,6 +102,10 @@ interface ISurfaceComposer { * The name of the virtual display. * isSecure * Whether this virtual display is secure. + * optimizationPolicy + * Whether to optimize for power or performance. Displays that are optimizing for power may + * be dependent on a different display that optimizes for performance when they are on, + * which will guarantee performance for all of the other displays. * uniqueId * The unique ID for the display. * requestedRefreshRate @@ -108,7 +117,7 @@ interface ISurfaceComposer { * requires ACCESS_SURFACE_FLINGER permission. */ @nullable IBinder createVirtualDisplay(@utf8InCpp String displayName, boolean isSecure, - @utf8InCpp String uniqueId, float requestedRefreshRate); + OptimizationPolicy optimizationPolicy, @utf8InCpp String uniqueId, float requestedRefreshRate); /** * Destroy a virtual display. diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h index 7ee291df4c..6381db228b 100644 --- a/libs/gui/include/gui/LayerMetadata.h +++ b/libs/gui/include/gui/LayerMetadata.h @@ -44,6 +44,10 @@ struct LayerMetadata : public Parcelable { LayerMetadata& operator=(const LayerMetadata& other); LayerMetadata& operator=(LayerMetadata&& other); + // Note: `default` is not feasible because Parcelable does not provide ==. + bool operator==(const LayerMetadata& rhs) const { return mMap == rhs.mMap; } + bool operator!=(const LayerMetadata&) const = default; + // Merges other into this LayerMetadata. If eraseEmpty is true, any entries in // in this whose keys are paired with empty values in other will be erased. bool merge(const LayerMetadata& other, bool eraseEmpty = false); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index c2680a42dc..369d3d136a 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -17,9 +17,9 @@ #ifndef ANDROID_SF_LAYER_STATE_H #define ANDROID_SF_LAYER_STATE_H - #include <stdint.h> #include <sys/types.h> +#include <span> #include <android/gui/DisplayCaptureArgs.h> #include <android/gui/IWindowInfosReportedListener.h> @@ -69,21 +69,39 @@ struct client_cache_t { uint64_t id; bool operator==(const client_cache_t& other) const { return id == other.id; } + bool operator!=(const client_cache_t&) const = default; bool isValid() const { return token != nullptr; } }; class TrustedPresentationListener : public Parcelable { public: - sp<ITransactionCompletedListener> callbackInterface; - int callbackId = -1; + struct State { + sp<ITransactionCompletedListener> callbackInterface; + int callbackId = -1; + bool operator==(const State&) const = default; + bool operator!=(const State&) const = default; + }; void invoke(bool presentedWithinThresholds) { - callbackInterface->onTrustedPresentationChanged(callbackId, presentedWithinThresholds); + mState.callbackInterface->onTrustedPresentationChanged(mState.callbackId, + presentedWithinThresholds); + } + void configure(State&& state) { mState = std::move(state); } + const sp<ITransactionCompletedListener>& getCallback() { return mState.callbackInterface; } + void clear() { + mState.callbackInterface = nullptr; + mState.callbackId = -1; } status_t writeToParcel(Parcel* parcel) const; status_t readFromParcel(const Parcel* parcel); + + bool operator==(const TrustedPresentationListener& rhs) const { return mState == rhs.mState; } + bool operator!=(const TrustedPresentationListener&) const = default; + +private: + State mState; }; class BufferData : public Parcelable { @@ -309,6 +327,32 @@ struct layer_state_t { bool hasValidBuffer() const; void sanitize(int32_t permissions); + void updateTransparentRegion(const Region& transparentRegion); + const Region& getTransparentRegion() const { return mNotDefCmpState.transparentRegion; } + void updateSurfaceDamageRegion(const Region& surfaceDamageRegion); + const Region& getSurfaceDamageRegion() const { return mNotDefCmpState.surfaceDamageRegion; } + // Do not update state flags. Used to set up test state. + void setSurfaceDamageRegion(Region&& surfaceDamageRegion) { + mNotDefCmpState.surfaceDamageRegion = std::move(surfaceDamageRegion); + } + void updateRelativeLayer(const sp<SurfaceControl>& relativeTo, int32_t z); + void updateParentLayer(const sp<SurfaceControl>& newParent); + void updateInputWindowInfo(sp<gui::WindowInfoHandle>&& info); + const gui::WindowInfo& getWindowInfo() const { + return *mNotDefCmpState.windowInfoHandle->getInfo(); + } + gui::WindowInfo* editWindowInfo() { return mNotDefCmpState.windowInfoHandle->editInfo(); } + + const sp<SurfaceControl>& getParentSurfaceControlForChild() const { + return mNotDefCmpState.parentSurfaceControlForChild; + } + const sp<SurfaceControl>& getRelativeLayerSurfaceControl() const { + return mNotDefCmpState.relativeLayerSurfaceControl; + } + + bool operator==(const layer_state_t&) const = default; + bool operator!=(const layer_state_t&) const = default; + struct matrix22_t { float dsdx{0}; float dtdx{0}; @@ -337,28 +381,20 @@ struct layer_state_t { float clientDrawnCornerRadius; uint32_t backgroundBlurRadius; - sp<SurfaceControl> relativeLayerSurfaceControl; - - sp<SurfaceControl> parentSurfaceControlForChild; - half4 color; // non POD must be last. see write/read - Region transparentRegion; uint32_t bufferTransform; bool transformToDisplayInverse; FloatRect crop; std::shared_ptr<BufferData> bufferData = nullptr; ui::Dataspace dataspace; HdrMetadata hdrMetadata; - Region surfaceDamageRegion; int32_t api; sp<NativeHandle> sidebandStream; mat4 colorTransform; std::vector<BlurRegion> blurRegions; - sp<gui::WindowInfoHandle> windowInfoHandle = sp<gui::WindowInfoHandle>::make(); - LayerMetadata metadata; // The following refer to the alpha, and dataspace, respectively of @@ -444,6 +480,18 @@ struct layer_state_t { std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> bufferReleaseChannel; std::shared_ptr<gui::DisplayLuts> luts; + +protected: + struct NotDefaultComparableState { + Region transparentRegion; + Region surfaceDamageRegion; + sp<gui::WindowInfoHandle> windowInfoHandle = sp<gui::WindowInfoHandle>::make(); + sp<SurfaceControl> relativeLayerSurfaceControl; + sp<SurfaceControl> parentSurfaceControlForChild; + + bool operator==(const NotDefaultComparableState& rhs) const; + bool operator!=(const NotDefaultComparableState& rhs) const = default; + } mNotDefCmpState; }; class ComposerState { @@ -451,6 +499,9 @@ public: layer_state_t state; status_t write(Parcel& output) const; status_t read(const Parcel& input); + + bool operator==(const ComposerState&) const = default; + bool operator!=(const ComposerState&) const = default; }; struct DisplayState { @@ -516,20 +567,35 @@ struct DisplayState { status_t write(Parcel& output) const; status_t read(const Parcel& input); + + bool operator==(const DisplayState&) const = default; + bool operator!=(const DisplayState&) const = default; }; struct InputWindowCommands { - std::vector<gui::FocusRequest> focusRequests; - std::unordered_set<sp<gui::IWindowInfosReportedListener>, - SpHash<gui::IWindowInfosReportedListener>> - windowInfosReportedListeners; - + using Listener = gui::IWindowInfosReportedListener; + using ListenerSet = std::unordered_set<sp<Listener>, SpHash<Listener>>; // Merges the passed in commands and returns true if there were any changes. bool merge(const InputWindowCommands& other); bool empty() const; void clear(); + void addFocusRequest(const gui::FocusRequest& request) { focusRequests.push_back(request); } + void addWindowInfosReportedListener(const sp<Listener>& listener) { + windowInfosReportedListeners.insert(listener); + } + ListenerSet&& releaseListeners() { return std::move(windowInfosReportedListeners); } + status_t write(Parcel& output) const; status_t read(const Parcel& input); + + std::span<const gui::FocusRequest> getFocusRequests() const { return focusRequests; } + const ListenerSet& getListeners() const { return windowInfosReportedListeners; } + bool operator==(const InputWindowCommands&) const = default; + bool operator!=(const InputWindowCommands&) const = default; + +private: + std::vector<gui::FocusRequest> focusRequests; + ListenerSet windowInfosReportedListeners; }; static inline int compare_type(const ComposerState& lhs, const ComposerState& rhs) { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 60f16ae902..4fda8deb9c 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -345,8 +345,6 @@ public: static std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport> getDisplayDecorationSupport(const sp<IBinder>& displayToken); - static bool flagEdgeExtensionEffectUseShader(); - /** * Returns how many picture profiles are supported by the display. * @@ -396,6 +394,7 @@ public: static const std::string kEmpty; static sp<IBinder> createVirtualDisplay(const std::string& displayName, bool isSecure, + bool optimizeForPower = true, const std::string& uniqueId = kEmpty, float requestedRefreshRate = 0); diff --git a/libs/gui/include/gui/TransactionState.h b/libs/gui/include/gui/TransactionState.h new file mode 100644 index 0000000000..4358227dae --- /dev/null +++ b/libs/gui/include/gui/TransactionState.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2025 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/gui/FrameTimelineInfo.h> +#include <binder/Parcelable.h> +#include <gui/LayerState.h> + +namespace android { + +// Class to store all the transaction data and the parcelling logic +class TransactionState { +public: + explicit TransactionState() = default; + TransactionState(TransactionState const& other) = default; + status_t writeToParcel(Parcel* parcel) const; + status_t readFromParcel(const Parcel* parcel); + layer_state_t* getLayerState(const sp<SurfaceControl>& sc); + DisplayState& getDisplayState(const sp<IBinder>& token); + + // Returns the current id of the transaction. + // The id is updated every time the transaction is applied. + uint64_t getId() const { return mId; } + std::vector<uint64_t> getMergedTransactionIds() const { return mMergedTransactionIds; } + void enableDebugLogCallPoints() { mLogCallPoints = true; } + void merge(TransactionState&& other, + const std::function<void(layer_state_t&)>& onBufferOverwrite); + + // copied from FrameTimelineInfo::merge() + void mergeFrameTimelineInfo(const FrameTimelineInfo& other); + void clear(); + bool operator==(const TransactionState& rhs) const = default; + bool operator!=(const TransactionState& rhs) const = default; + + uint64_t mId = 0; + std::vector<uint64_t> mMergedTransactionIds; + uint32_t mFlags = 0; + // The vsync id provided by Choreographer.getVsyncId and the input event id + gui::FrameTimelineInfo mFrameTimelineInfo; + // mDesiredPresentTime is the time in nanoseconds that the client would like the transaction + // to be presented. When it is not possible to present at exactly that time, it will be + // presented after the time has passed. + // + // If the client didn't pass a desired presentation time, mDesiredPresentTime will be + // populated to the time setBuffer was called, and mIsAutoTimestamp will be set to true. + // + // Desired present times that are more than 1 second in the future may be ignored. + // When a desired present time has already passed, the transaction will be presented as soon + // as possible. + // + // Transactions from the same process are presented in the same order that they are applied. + // The desired present time does not affect this ordering. + int64_t mDesiredPresentTime = 0; + bool mIsAutoTimestamp = true; + // If not null, transactions will be queued up using this token otherwise a common token + // per process will be used. + sp<IBinder> mApplyToken; + // Indicates that the Transaction may contain buffers that should be cached. The reason this + // is only a guess is that buffers can be removed before cache is called. This is only a + // hint that at some point a buffer was added to this transaction before apply was called. + bool mMayContainBuffer = false; + // Prints debug logs when enabled. + bool mLogCallPoints = false; + + std::vector<DisplayState> mDisplayStates; + std::vector<ComposerState> mComposerStates; + InputWindowCommands mInputWindowCommands; + std::vector<client_cache_t> mUncacheBuffers; + // Note: mHasListenerCallbacks can be true even if mListenerCallbacks is + // empty. + bool mHasListenerCallbacks = false; + std::vector<ListenerCallbacks> mListenerCallbacks; + +private: + // We keep track of the last MAX_MERGE_HISTORY_LENGTH merged transaction ids. + // Ordered most recently merged to least recently merged. + static constexpr size_t MAX_MERGE_HISTORY_LENGTH = 10u; +}; + +}; // namespace android diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h index 420dc2103f..9ac49c0fb6 100644 --- a/libs/gui/include/gui/WindowInfo.h +++ b/libs/gui/include/gui/WindowInfo.h @@ -268,6 +268,7 @@ struct WindowInfo : public Parcelable { bool overlaps(const WindowInfo* other) const; bool operator==(const WindowInfo& inputChannel) const; + bool operator!=(const WindowInfo&) const = default; status_t writeToParcel(android::Parcel* parcel) const override; @@ -319,6 +320,9 @@ public: status_t readFromParcel(const android::Parcel* parcel); status_t writeToParcel(android::Parcel* parcel) const; + bool operator==(const WindowInfoHandle& rhs) const { return mInfo == rhs.mInfo; } + bool operator!=(const WindowInfoHandle&) const = default; + protected: virtual ~WindowInfoHandle(); diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig index 90d91ac06a..534f05e987 100644 --- a/libs/gui/libgui_flags.aconfig +++ b/libs/gui/libgui_flags.aconfig @@ -77,14 +77,6 @@ flag { } # wb_stream_splitter flag { - name: "edge_extension_shader" - namespace: "windowing_frontend" - description: "Enable edge extension via shader" - bug: "322036393" - is_fixed_read_only: true -} # edge_extension_shader - -flag { name: "buffer_release_channel" namespace: "window_surfaces" description: "Enable BufferReleaseChannel to optimize buffer releases" diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp index 87051a7aac..e20345dd1a 100644 --- a/libs/gui/tests/Android.bp +++ b/libs/gui/tests/Android.bp @@ -90,6 +90,7 @@ cc_test { "testserver/TestServerClient.cpp", "testserver/TestServerHost.cpp", "TextureRenderer.cpp", + "TransactionState_test.cpp", "VsyncEventData_test.cpp", "WindowInfo_test.cpp", ], diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index eb55e3baeb..e7690e2530 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -687,10 +687,11 @@ public: return binder::Status::ok(); } - binder::Status createVirtualDisplay(const std::string& /*displayName*/, bool /*isSecure*/, - const std::string& /*uniqueId*/, - float /*requestedRefreshRate*/, - sp<IBinder>* /*outDisplay*/) override { + binder::Status createVirtualDisplay( + const std::string& /*displayName*/, bool /*isSecure*/, + gui::ISurfaceComposer::OptimizationPolicy /*optimizationPolicy*/, + const std::string& /*uniqueId*/, float /*requestedRefreshRate*/, + sp<IBinder>* /*outDisplay*/) override { return binder::Status::ok(); } diff --git a/libs/gui/tests/TransactionState_test.cpp b/libs/gui/tests/TransactionState_test.cpp new file mode 100644 index 0000000000..179b264dbf --- /dev/null +++ b/libs/gui/tests/TransactionState_test.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2025 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 <gmock/gmock.h> + +#include <gtest/gtest.h> +#include <unordered_map> +#include "android/gui/FocusRequest.h" +#include "binder/Binder.h" +#include "binder/Parcel.h" +#include "gtest/gtest.h" +#include "gui/LayerState.h" +#include "gui/WindowInfo.h" + +#include "gui/TransactionState.h" + +namespace android { + +void sprintf(std::string& out, const char* format, ...) { + va_list arg_list; + va_start(arg_list, format); + + int len = vsnprintf(nullptr, 0, format, arg_list); + if (len < 0) { + va_end(arg_list); + } + std::string line(len, '\0'); + int written = vsnprintf(line.data(), len + 1, format, arg_list); + if (written != len) { + va_end(arg_list); + } + line.pop_back(); + out += line; + va_end(arg_list); +} + +constexpr std::string dump_struct(auto& x) { + std::string s; +#if __has_builtin(__builtin_dump_struct) + __builtin_dump_struct(&x, sprintf, s); +#else + (void)x; +#endif + return s; +} + +void PrintTo(const TransactionState& state, ::std::ostream* os) { + *os << dump_struct(state); + *os << state.mFrameTimelineInfo.toString(); + for (auto mergedId : state.mMergedTransactionIds) { + *os << mergedId << ","; + } +} + +void PrintTo(const ComposerState& state, ::std::ostream* os) { + *os << dump_struct(state.state); + *os << state.state.getWindowInfo(); +} + +// In case EXPECT_EQ fails, this function is useful to pinpoint exactly which +// field did not compare ==. +void Compare(const TransactionState& s1, const TransactionState& s2) { + EXPECT_EQ(s1.mId, s2.mId); + EXPECT_EQ(s1.mMergedTransactionIds, s2.mMergedTransactionIds); + EXPECT_EQ(s1.mFlags, s2.mFlags); + EXPECT_EQ(s1.mFrameTimelineInfo, s2.mFrameTimelineInfo); + EXPECT_EQ(s1.mDesiredPresentTime, s2.mDesiredPresentTime); + EXPECT_EQ(s1.mIsAutoTimestamp, s2.mIsAutoTimestamp); + EXPECT_EQ(s1.mApplyToken, s2.mApplyToken); + EXPECT_EQ(s1.mMayContainBuffer, s2.mMayContainBuffer); + EXPECT_EQ(s1.mLogCallPoints, s2.mLogCallPoints); + EXPECT_EQ(s1.mDisplayStates.size(), s2.mDisplayStates.size()); + EXPECT_THAT(s1.mDisplayStates, ::testing::ContainerEq(s2.mDisplayStates)); + EXPECT_EQ(s1.mComposerStates.size(), s2.mComposerStates.size()); + EXPECT_EQ(s1.mComposerStates, s2.mComposerStates); + EXPECT_EQ(s1.mInputWindowCommands, s2.mInputWindowCommands); + EXPECT_EQ(s1.mUncacheBuffers, s2.mUncacheBuffers); + EXPECT_EQ(s1.mHasListenerCallbacks, s2.mHasListenerCallbacks); + EXPECT_EQ(s1.mListenerCallbacks.size(), s2.mListenerCallbacks.size()); + EXPECT_EQ(s1.mListenerCallbacks, s2.mListenerCallbacks); +} + +std::unique_ptr<std::unordered_map<int, sp<BBinder>>> createTokenMap(size_t maxSize) { + auto result = std::make_unique<std::unordered_map<int, sp<BBinder>>>(); + for (size_t i = 0; i < maxSize; ++i) { + result->emplace(i, sp<BBinder>::make()); + } + return result; +} + +constexpr size_t kMaxComposerStates = 2; +ComposerState createComposerStateForTest(size_t i) { + static const auto* const sLayerHandle = createTokenMap(kMaxComposerStates).release(); + + ComposerState state; + state.state.what = layer_state_t::eFlagsChanged; + state.state.surface = sLayerHandle->at(i); + state.state.layerId = i; + state.state.flags = 20 * i; + return state; +} + +constexpr size_t kMaxDisplayStates = 5; +DisplayState createDisplayStateForTest(size_t i) { + static const auto* const sDisplayTokens = createTokenMap(kMaxDisplayStates).release(); + + DisplayState displayState; + displayState.what = DisplayState::eFlagsChanged; + displayState.token = sDisplayTokens->at(i); + displayState.flags = 20 * i; + return displayState; +} + +TransactionState createTransactionStateForTest() { + static sp<BBinder> sApplyToken = sp<BBinder>::make(); + + TransactionState state; + state.mId = 123; + state.mMergedTransactionIds.push_back(15); + state.mMergedTransactionIds.push_back(0); + state.mFrameTimelineInfo.vsyncId = 14; + state.mDesiredPresentTime = 11; + state.mIsAutoTimestamp = true; + state.mApplyToken = sApplyToken; + for (size_t i = 0; i < kMaxDisplayStates; i++) { + state.mDisplayStates.push_back(createDisplayStateForTest(i)); + } + for (size_t i = 0; i < kMaxComposerStates; i++) { + state.mComposerStates.push_back(createComposerStateForTest(i)); + } + static const auto* const sFocusRequestTokens = createTokenMap(5).release(); + for (int i = 0; i < 5; i++) { + gui::FocusRequest request; + request.token = sFocusRequestTokens->at(i); + request.timestamp = i; + state.mInputWindowCommands.addFocusRequest(request); + } + static const auto* const sCacheToken = createTokenMap(5).release(); + for (int i = 0; i < 5; i++) { + client_cache_t cache; + cache.token = sCacheToken->at(i); + cache.id = i; + state.mUncacheBuffers.emplace_back(std::move(cache)); + } + static const auto* const sListenerCallbacks = []() { + auto* callbacks = new std::vector<ListenerCallbacks>(); + for (int i = 0; i < 5; i++) { + callbacks->emplace_back(sp<BBinder>::make(), + std::unordered_set<CallbackId, CallbackIdHash>{}); + } + return callbacks; + }(); + state.mHasListenerCallbacks = true; + state.mListenerCallbacks = *sListenerCallbacks; + return state; +} + +TransactionState createEmptyTransaction(uint64_t id) { + TransactionState state; + state.mId = id; + return state; +} + +TEST(TransactionStateTest, parcel) { + TransactionState state = createTransactionStateForTest(); + Parcel p; + state.writeToParcel(&p); + p.setDataPosition(0); + TransactionState parcelledState; + parcelledState.readFromParcel(&p); + EXPECT_EQ(state, parcelledState); +}; + +TEST(TransactionStateTest, parcelDisplayState) { + DisplayState state = createDisplayStateForTest(0); + Parcel p; + state.write(p); + p.setDataPosition(0); + DisplayState parcelledState; + parcelledState.read(p); + EXPECT_EQ(state, parcelledState); +}; + +TEST(TransactionStateTest, parcelLayerState) { + ComposerState state = createComposerStateForTest(0); + Parcel p; + state.write(p); + p.setDataPosition(0); + ComposerState parcelledState; + parcelledState.read(p); + EXPECT_EQ(state, parcelledState); +}; + +TEST(TransactionStateTest, parcelEmptyState) { + TransactionState state; + Parcel p; + state.writeToParcel(&p); + p.setDataPosition(0); + TransactionState parcelledState; + state.readFromParcel(&p); + EXPECT_EQ(state, parcelledState); +}; + +TEST(TransactionStateTest, mergeLayerState) { + ComposerState composerState = createComposerStateForTest(0); + ComposerState update; + update.state.surface = composerState.state.surface; + update.state.layerId = 0; + update.state.what = layer_state_t::eAlphaChanged; + update.state.color.a = .42; + composerState.state.merge(update.state); + + ComposerState expectedMergedState = createComposerStateForTest(0); + expectedMergedState.state.what |= layer_state_t::eAlphaChanged; + expectedMergedState.state.color.a = .42; + EXPECT_EQ(composerState, expectedMergedState); +}; + +TEST(TransactionStateTest, merge) { + // Setup. + static constexpr uint64_t kUpdateTransactionId = 200; + + TransactionState state = createTransactionStateForTest(); + + TransactionState update; + update.mId = kUpdateTransactionId; + { + ComposerState composerState; + composerState.state.surface = state.mComposerStates[0].state.surface; + composerState.state.what = layer_state_t::eAlphaChanged; + composerState.state.color.a = .42; + update.mComposerStates.push_back(composerState); + } + { + ComposerState composerState; + composerState.state.surface = state.mComposerStates[1].state.surface; + composerState.state.what = layer_state_t::eBufferChanged; + update.mComposerStates.push_back(composerState); + } + int32_t overrwiteLayerId = -1; + // Mutation. + state.merge(std::move(update), + [&overrwiteLayerId](layer_state_t ls) { overrwiteLayerId = ls.layerId; }); + // Assertions. + EXPECT_EQ(1, overrwiteLayerId); + EXPECT_EQ(update, createEmptyTransaction(update.getId())); + + TransactionState expectedMergedState = createTransactionStateForTest(); + expectedMergedState.mMergedTransactionIds + .insert(expectedMergedState.mMergedTransactionIds.begin(), kUpdateTransactionId); + expectedMergedState.mComposerStates.at(0).state.what |= layer_state_t::eAlphaChanged; + expectedMergedState.mComposerStates.at(0).state.color.a = .42; + expectedMergedState.mComposerStates.at(1).state.what |= layer_state_t::eBufferChanged; + auto inputCommands = expectedMergedState.mInputWindowCommands; + + // desired present time is not merged. + expectedMergedState.mDesiredPresentTime = state.mDesiredPresentTime; + + EXPECT_EQ(state.mComposerStates[0], expectedMergedState.mComposerStates[0]); + EXPECT_EQ(state.mInputWindowCommands, expectedMergedState.mInputWindowCommands); + EXPECT_EQ(state, expectedMergedState); +}; + +TEST(TransactionStateTest, clear) { + TransactionState state = createTransactionStateForTest(); + state.clear(); + TransactionState emptyState = createEmptyTransaction(state.getId()); + EXPECT_EQ(state, emptyState); +}; + +} // namespace android diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig index efedf76e6d..de5e42875e 100644 --- a/libs/input/input_flags.aconfig +++ b/libs/input/input_flags.aconfig @@ -134,13 +134,6 @@ flag { } flag { - name: "include_relative_axis_values_for_captured_touchpads" - namespace: "input" - description: "Include AXIS_RELATIVE_X and AXIS_RELATIVE_Y values when reporting touches from captured touchpads." - bug: "330522990" -} - -flag { name: "enable_per_device_input_latency_metrics" namespace: "input" description: "Capture input latency metrics on a per device granular level using histograms." diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index 9f64d2c4db..f43694e228 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -803,8 +803,7 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine, PrimeCacheConfig co drawClippedLayers(renderengine, display, dstTexture, texture); } - if (com::android::graphics::libgui::flags::edge_extension_shader() && - config.cacheEdgeExtension) { + if (config.cacheEdgeExtension) { SFTRACE_NAME("cacheEdgeExtension"); drawEdgeExtensionLayers(renderengine, display, dstTexture, texture); drawEdgeExtensionLayers(renderengine, p3Display, dstTexture, texture); diff --git a/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp index 4164c4b4c9..f007427f1c 100644 --- a/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp +++ b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp @@ -58,9 +58,6 @@ static const SkString edgeShader = SkString(R"( )"); EdgeExtensionShaderFactory::EdgeExtensionShaderFactory() { - if (!com::android::graphics::libgui::flags::edge_extension_shader()) { - return; - } mResult = std::make_unique<SkRuntimeEffect::Result>(SkRuntimeEffect::MakeForShader(edgeShader)); LOG_ALWAYS_FATAL_IF(!mResult->errorText.isEmpty(), "EdgeExtensionShaderFactory compilation " diff --git a/services/surfaceflinger/Utils/RingBuffer.h b/libs/ui/include/ui/RingBuffer.h index 215472b388..31d5a950ef 100644 --- a/services/surfaceflinger/Utils/RingBuffer.h +++ b/libs/ui/include/ui/RingBuffer.h @@ -19,7 +19,7 @@ #include <stddef.h> #include <array> -namespace android::utils { +namespace android::ui { template <class T, size_t SIZE> class RingBuffer { @@ -31,8 +31,8 @@ public: ~RingBuffer() = default; constexpr size_t capacity() const { return SIZE; } - size_t size() const { return mCount; } + bool isFull() const { return size() == capacity(); } T& next() { mHead = static_cast<size_t>(mHead + 1) % SIZE; @@ -67,4 +67,4 @@ private: size_t mCount = 0; }; -} // namespace android::utils +} // namespace android::ui diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 2d8a1e326c..2b11786df3 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -144,6 +144,17 @@ cc_test { } cc_test { + name: "RingBuffer_test", + test_suites: ["device-tests"], + shared_libs: ["libui"], + srcs: ["RingBuffer_test.cpp"], + cflags: [ + "-Wall", + "-Werror", + ], +} + +cc_test { name: "Size_test", test_suites: ["device-tests"], shared_libs: ["libui"], diff --git a/libs/ui/tests/RingBuffer_test.cpp b/libs/ui/tests/RingBuffer_test.cpp new file mode 100644 index 0000000000..9839492b9f --- /dev/null +++ b/libs/ui/tests/RingBuffer_test.cpp @@ -0,0 +1,70 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> +#include <ui/RingBuffer.h> + +namespace android::ui { + +TEST(RingBuffer, basic) { + RingBuffer<int, 5> rb; + + rb.next() = 1; + ASSERT_EQ(1, rb.size()); + ASSERT_EQ(1, rb.back()); + ASSERT_EQ(1, rb.front()); + + rb.next() = 2; + ASSERT_EQ(2, rb.size()); + ASSERT_EQ(2, rb.back()); + ASSERT_EQ(1, rb.front()); + ASSERT_EQ(1, rb[-1]); + + rb.next() = 3; + ASSERT_EQ(3, rb.size()); + ASSERT_EQ(3, rb.back()); + ASSERT_EQ(1, rb.front()); + ASSERT_EQ(2, rb[-1]); + ASSERT_EQ(1, rb[-2]); + + rb.next() = 4; + ASSERT_EQ(4, rb.size()); + ASSERT_EQ(4, rb.back()); + ASSERT_EQ(1, rb.front()); + ASSERT_EQ(3, rb[-1]); + ASSERT_EQ(2, rb[-2]); + ASSERT_EQ(1, rb[-3]); + + rb.next() = 5; + ASSERT_EQ(5, rb.size()); + ASSERT_EQ(5, rb.back()); + ASSERT_EQ(1, rb.front()); + ASSERT_EQ(4, rb[-1]); + ASSERT_EQ(3, rb[-2]); + ASSERT_EQ(2, rb[-3]); + ASSERT_EQ(1, rb[-4]); + + rb.next() = 6; + ASSERT_EQ(5, rb.size()); + ASSERT_EQ(6, rb.back()); + ASSERT_EQ(2, rb.front()); + ASSERT_EQ(5, rb[-1]); + ASSERT_EQ(4, rb[-2]); + ASSERT_EQ(3, rb[-3]); + ASSERT_EQ(2, rb[-4]); +} + +} // namespace android::ui
\ No newline at end of file diff --git a/opengl/libs/EGL/MultifileBlobCache.cpp b/opengl/libs/EGL/MultifileBlobCache.cpp index 04c525e93d..7faf361c08 100644 --- a/opengl/libs/EGL/MultifileBlobCache.cpp +++ b/opengl/libs/EGL/MultifileBlobCache.cpp @@ -356,7 +356,7 @@ void MultifileBlobCache::set(const void* key, EGLsizeiANDROID keySize, const voi // If we're going to be over the cache limit, kick off a trim to clear space if (getTotalSize() + fileSize > mMaxTotalSize || getTotalEntries() + 1 > mMaxTotalEntries) { - ALOGV("SET: Cache is full, calling trimCache to clear space"); + ALOGW("SET: Cache is full, calling trimCache to clear space"); trimCache(); } diff --git a/services/gpuservice/feature_override/Android.bp b/services/gpuservice/feature_override/Android.bp index 3b5407bdd3..842a0c46d2 100644 --- a/services/gpuservice/feature_override/Android.bp +++ b/services/gpuservice/feature_override/Android.bp @@ -69,6 +69,7 @@ cc_library_static { name: "libfeatureoverride", defaults: [ "libfeatureoverride_deps", + "libvkjson_deps", ], srcs: [ ":feature_config_proto_definitions", @@ -85,6 +86,9 @@ cc_library_static { cppflags: [ "-Wno-sign-compare", ], + static_libs: [ + "libvkjson", + ], export_include_dirs: ["include"], proto: { type: "lite", diff --git a/services/gpuservice/feature_override/FeatureOverrideParser.cpp b/services/gpuservice/feature_override/FeatureOverrideParser.cpp index a16bfa8b35..26ff84a34c 100644 --- a/services/gpuservice/feature_override/FeatureOverrideParser.cpp +++ b/services/gpuservice/feature_override/FeatureOverrideParser.cpp @@ -23,8 +23,10 @@ #include <sys/stat.h> #include <vector> +#include <android-base/macros.h> #include <graphicsenv/FeatureOverrides.h> #include <log/log.h> +#include <vkjson.h> #include "feature_config.pb.h" @@ -35,13 +37,53 @@ void resetFeatureOverrides(android::FeatureOverrides &featureOverrides) { featureOverrides.mPackageFeatures.clear(); } +bool +gpuVendorIdMatches(const VkJsonInstance &vkJsonInstance, + const uint32_t &configVendorId) { + if (vkJsonInstance.devices.empty()) { + return false; + } + + // Always match the TEST Vendor ID + if (configVendorId == feature_override::GpuVendorID::VENDOR_ID_TEST) { + return true; + } + + // Always assume one GPU device. + uint32_t vendorID = vkJsonInstance.devices.front().properties.vendorID; + + return vendorID == configVendorId; +} + +bool +conditionsMet(const VkJsonInstance &vkJsonInstance, + const android::FeatureConfig &featureConfig) { + bool gpuVendorIdMatch = false; + + if (featureConfig.mGpuVendorIDs.empty()) { + gpuVendorIdMatch = true; + } else { + for (const auto &gpuVendorID: featureConfig.mGpuVendorIDs) { + if (gpuVendorIdMatches(vkJsonInstance, gpuVendorID)) { + gpuVendorIdMatch = true; + break; + } + } + } + + return gpuVendorIdMatch; +} + void initFeatureConfig(android::FeatureConfig &featureConfig, const feature_override::FeatureConfig &featureConfigProto) { featureConfig.mFeatureName = featureConfigProto.feature_name(); featureConfig.mEnabled = featureConfigProto.enabled(); + for (const auto &gpuVendorIdProto: featureConfigProto.gpu_vendor_ids()) { + featureConfig.mGpuVendorIDs.emplace_back(static_cast<uint32_t>(gpuVendorIdProto)); + } } -feature_override::FeatureOverrideProtos readFeatureConfigProtos(std::string configFilePath) { +feature_override::FeatureOverrideProtos readFeatureConfigProtos(const std::string &configFilePath) { feature_override::FeatureOverrideProtos overridesProtos; std::ifstream protobufBinaryFile(configFilePath.c_str()); @@ -78,9 +120,15 @@ std::string FeatureOverrideParser::getFeatureOverrideFilePath() const { bool FeatureOverrideParser::shouldReloadFeatureOverrides() const { std::string configFilePath = getFeatureOverrideFilePath(); + + std::ifstream configFile(configFilePath); + if (!configFile.good()) { + return false; + } + struct stat fileStat{}; - if (stat(getFeatureOverrideFilePath().c_str(), &fileStat) != 0) { - ALOGE("Error getting file information for '%s': %s", getFeatureOverrideFilePath().c_str(), + if (stat(configFilePath.c_str(), &fileStat) != 0) { + ALOGE("Error getting file information for '%s': %s", configFilePath.c_str(), strerror(errno)); // stat'ing the file failed, so return false since reading it will also likely fail. return false; @@ -100,12 +148,22 @@ void FeatureOverrideParser::parseFeatureOverrides() { // Clear out the stale values before adding the newly parsed data. resetFeatureOverrides(mFeatureOverrides); + if (overridesProtos.global_features().empty() && + overridesProtos.package_features().empty()) { + // No overrides to parse. + return; + } + + const VkJsonInstance vkJsonInstance = VkJsonGetInstance(); + // Global feature overrides. for (const auto &featureConfigProto: overridesProtos.global_features()) { FeatureConfig featureConfig; initFeatureConfig(featureConfig, featureConfigProto); - mFeatureOverrides.mGlobalFeatures.emplace_back(featureConfig); + if (conditionsMet(vkJsonInstance, featureConfig)) { + mFeatureOverrides.mGlobalFeatures.emplace_back(featureConfig); + } } // App-specific feature overrides. @@ -122,7 +180,9 @@ void FeatureOverrideParser::parseFeatureOverrides() { FeatureConfig featureConfig; initFeatureConfig(featureConfig, featureConfigProto); - featureConfigs.emplace_back(featureConfig); + if (conditionsMet(vkJsonInstance, featureConfig)) { + featureConfigs.emplace_back(featureConfig); + } } mFeatureOverrides.mPackageFeatures[packageName] = featureConfigs; diff --git a/services/gpuservice/feature_override/proto/feature_config.proto b/services/gpuservice/feature_override/proto/feature_config.proto index 4d4bf289f1..f28518778f 100644 --- a/services/gpuservice/feature_override/proto/feature_config.proto +++ b/services/gpuservice/feature_override/proto/feature_config.proto @@ -21,14 +21,43 @@ package feature_override; option optimize_for = LITE_RUNTIME; /** + * GPU Vendor IDs. + * Taken from: external/angle/src/libANGLE/renderer/driver_utils.h + */ +enum GpuVendorID +{ + // Test ID matches every GPU Vendor ID. + VENDOR_ID_TEST = 0; + VENDOR_ID_AMD = 0x1002; + VENDOR_ID_ARM = 0x13B5; + // Broadcom devices won't use PCI, but this is their Vulkan vendor id. + VENDOR_ID_BROADCOM = 0x14E4; + VENDOR_ID_GOOGLE = 0x1AE0; + VENDOR_ID_INTEL = 0x8086; + VENDOR_ID_MESA = 0x10005; + VENDOR_ID_MICROSOFT = 0x1414; + VENDOR_ID_NVIDIA = 0x10DE; + VENDOR_ID_POWERVR = 0x1010; + // This is Qualcomm PCI Vendor ID. + // Android doesn't have a PCI bus, but all we need is a unique id. + VENDOR_ID_QUALCOMM = 0x5143; + VENDOR_ID_SAMSUNG = 0x144D; + VENDOR_ID_VIVANTE = 0x9999; + VENDOR_ID_VMWARE = 0x15AD; + VENDOR_ID_VIRTIO = 0x1AF4; +} + +/** * Feature Configuration * feature_name: Feature name (see external/angle/include/platform/autogen/FeaturesVk_autogen.h). * enabled: Either enable or disable the feature. + * gpu_vendor_ids: The GPU architectures this FeatureConfig applies to, if any. */ message FeatureConfig { string feature_name = 1; bool enabled = 2; + repeated GpuVendorID gpu_vendor_ids = 3; } /** diff --git a/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp b/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp index 65a1b58dc3..66556cd2d0 100644 --- a/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp +++ b/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp @@ -70,14 +70,14 @@ public: }; testing::AssertionResult validateFeatureConfigTestTxtpbSizes(FeatureOverrides overrides) { - size_t expectedGlobalFeaturesSize = 1; + size_t expectedGlobalFeaturesSize = 3; if (overrides.mGlobalFeatures.size() != expectedGlobalFeaturesSize) { return testing::AssertionFailure() << "overrides.mGlobalFeatures.size(): " << overrides.mGlobalFeatures.size() << ", expected: " << expectedGlobalFeaturesSize; } - size_t expectedPackageFeaturesSize = 1; + size_t expectedPackageFeaturesSize = 3; if (overrides.mPackageFeatures.size() != expectedPackageFeaturesSize) { return testing::AssertionFailure() << "overrides.mPackageFeatures.size(): " << overrides.mPackageFeatures.size() @@ -133,6 +133,96 @@ TEST_F(FeatureOverrideParserTest, globalOverrides1) { EXPECT_TRUE(validateGlobalOverrides1(overrides)); } +testing::AssertionResult validateGlobalOverrides2(FeatureOverrides overrides) { + const int kTestFeatureIndex = 1; + const std::string expectedFeatureName = "globalOverrides2"; + const FeatureConfig &cfg = overrides.mGlobalFeatures[kTestFeatureIndex]; + + if (cfg.mFeatureName != expectedFeatureName) { + return testing::AssertionFailure() + << "cfg.mFeatureName: " << cfg.mFeatureName + << ", expected: " << expectedFeatureName; + } + + bool expectedEnabled = true; + if (cfg.mEnabled != expectedEnabled) { + return testing::AssertionFailure() + << "cfg.mEnabled: " << cfg.mEnabled + << ", expected: " << expectedEnabled; + } + + std::vector<uint32_t> expectedGpuVendorIDs = { + 0, // GpuVendorID::VENDOR_ID_TEST + 0x13B5, // GpuVendorID::VENDOR_ID_ARM + }; + if (cfg.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) { + return testing::AssertionFailure() + << "cfg.mGpuVendorIDs.size(): " << cfg.mGpuVendorIDs.size() + << ", expected: " << expectedGpuVendorIDs.size(); + } + for (int i = 0; i < expectedGpuVendorIDs.size(); i++) { + if (cfg.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) { + std::stringstream msg; + msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg.mGpuVendorIDs[i] + << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i]; + return testing::AssertionFailure() << msg.str(); + } + } + + return testing::AssertionSuccess(); +} + +TEST_F(FeatureOverrideParserTest, globalOverrides2) { + FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides(); + + EXPECT_TRUE(validateGlobalOverrides2(overrides)); +} + +testing::AssertionResult validateGlobalOverrides3(FeatureOverrides overrides) { + const int kTestFeatureIndex = 2; + const std::string expectedFeatureName = "globalOverrides3"; + const FeatureConfig &cfg = overrides.mGlobalFeatures[kTestFeatureIndex]; + + if (cfg.mFeatureName != expectedFeatureName) { + return testing::AssertionFailure() + << "cfg.mFeatureName: " << cfg.mFeatureName + << ", expected: " << expectedFeatureName; + } + + bool expectedEnabled = true; + if (cfg.mEnabled != expectedEnabled) { + return testing::AssertionFailure() + << "cfg.mEnabled: " << cfg.mEnabled + << ", expected: " << expectedEnabled; + } + + std::vector<uint32_t> expectedGpuVendorIDs = { + 0, // GpuVendorID::VENDOR_ID_TEST + 0x8086, // GpuVendorID::VENDOR_ID_INTEL + }; + if (cfg.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) { + return testing::AssertionFailure() + << "cfg.mGpuVendorIDs.size(): " << cfg.mGpuVendorIDs.size() + << ", expected: " << expectedGpuVendorIDs.size(); + } + for (int i = 0; i < expectedGpuVendorIDs.size(); i++) { + if (cfg.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) { + std::stringstream msg; + msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg.mGpuVendorIDs[i] + << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i]; + return testing::AssertionFailure() << msg.str(); + } + } + + return testing::AssertionSuccess(); +} + +TEST_F(FeatureOverrideParserTest, globalOverrides3) { +FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides(); + +EXPECT_TRUE(validateGlobalOverrides3(overrides)); +} + testing::AssertionResult validatePackageOverrides1(FeatureOverrides overrides) { const std::string expectedTestPackageName = "com.gpuservice_unittest.packageOverrides1"; @@ -155,6 +245,12 @@ testing::AssertionResult validatePackageOverrides1(FeatureOverrides overrides) { const std::string expectedFeatureName = "packageOverrides1"; const FeatureConfig &cfg = features[0]; + if (cfg.mFeatureName != expectedFeatureName) { + return testing::AssertionFailure() + << "cfg.mFeatureName: " << cfg.mFeatureName + << ", expected: " << expectedFeatureName; + } + bool expectedEnabled = true; if (cfg.mEnabled != expectedEnabled) { return testing::AssertionFailure() @@ -193,6 +289,160 @@ testing::AssertionResult validateForceFileRead(FeatureOverrides overrides) { return testing::AssertionSuccess(); } +testing::AssertionResult validatePackageOverrides2(FeatureOverrides overrides) { + const std::string expectedPackageName = "com.gpuservice_unittest.packageOverrides2"; + + if (!overrides.mPackageFeatures.count(expectedPackageName)) { + return testing::AssertionFailure() + << "overrides.mPackageFeatures missing expected package: " << expectedPackageName; + } + + const std::vector<FeatureConfig>& features = overrides.mPackageFeatures[expectedPackageName]; + + size_t expectedFeaturesSize = 1; + if (features.size() != expectedFeaturesSize) { + return testing::AssertionFailure() + << "features.size(): " << features.size() + << ", expectedFeaturesSize: " << expectedFeaturesSize; + } + + const std::string expectedFeatureName = "packageOverrides2"; + const FeatureConfig &cfg = features[0]; + + if (cfg.mFeatureName != expectedFeatureName) { + return testing::AssertionFailure() + << "cfg.mFeatureName: " << cfg.mFeatureName + << ", expected: " << expectedFeatureName; + } + + bool expectedEnabled = false; + if (cfg.mEnabled != expectedEnabled) { + return testing::AssertionFailure() + << "cfg.mEnabled: " << cfg.mEnabled + << ", expected: " << expectedEnabled; + } + + std::vector<uint32_t> expectedGpuVendorIDs = { + 0, // GpuVendorID::VENDOR_ID_TEST + 0x8086, // GpuVendorID::VENDOR_ID_INTEL + }; + if (cfg.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) { + return testing::AssertionFailure() + << "cfg.mGpuVendorIDs.size(): " << cfg.mGpuVendorIDs.size() + << ", expected: " << expectedGpuVendorIDs.size(); + } + for (int i = 0; i < expectedGpuVendorIDs.size(); i++) { + if (cfg.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) { + std::stringstream msg; + msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg.mGpuVendorIDs[i] + << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i]; + return testing::AssertionFailure() << msg.str(); + } + } + + return testing::AssertionSuccess(); +} + +TEST_F(FeatureOverrideParserTest, packageOverrides2) { + FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides(); + + EXPECT_TRUE(validatePackageOverrides2(overrides)); +} + +testing::AssertionResult validatePackageOverrides3(FeatureOverrides overrides) { + const std::string expectedPackageName = "com.gpuservice_unittest.packageOverrides3"; + + if (!overrides.mPackageFeatures.count(expectedPackageName)) { + return testing::AssertionFailure() + << "overrides.mPackageFeatures missing expected package: " << expectedPackageName; + } + + const std::vector<FeatureConfig>& features = overrides.mPackageFeatures[expectedPackageName]; + + size_t expectedFeaturesSize = 2; + if (features.size() != expectedFeaturesSize) { + return testing::AssertionFailure() + << "features.size(): " << features.size() + << ", expectedFeaturesSize: " << expectedFeaturesSize; + } + + std::string expectedFeatureName = "packageOverrides3_1"; + const FeatureConfig &cfg_1 = features[0]; + + if (cfg_1.mFeatureName != expectedFeatureName) { + return testing::AssertionFailure() + << "cfg.mFeatureName: " << cfg_1.mFeatureName + << ", expected: " << expectedFeatureName; + } + + bool expectedEnabled = false; + if (cfg_1.mEnabled != expectedEnabled) { + return testing::AssertionFailure() + << "cfg.mEnabled: " << cfg_1.mEnabled + << ", expected: " << expectedEnabled; + } + + std::vector<uint32_t> expectedGpuVendorIDs = { + 0, // GpuVendorID::VENDOR_ID_TEST + 0x13B5, // GpuVendorID::VENDOR_ID_ARM + }; + if (cfg_1.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) { + return testing::AssertionFailure() + << "cfg.mGpuVendorIDs.size(): " << cfg_1.mGpuVendorIDs.size() + << ", expected: " << expectedGpuVendorIDs.size(); + } + for (int i = 0; i < expectedGpuVendorIDs.size(); i++) { + if (cfg_1.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) { + std::stringstream msg; + msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg_1.mGpuVendorIDs[i] + << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i]; + return testing::AssertionFailure() << msg.str(); + } + } + + expectedFeatureName = "packageOverrides3_2"; + const FeatureConfig &cfg_2 = features[1]; + + if (cfg_2.mFeatureName != expectedFeatureName) { + return testing::AssertionFailure() + << "cfg.mFeatureName: " << cfg_2.mFeatureName + << ", expected: " << expectedFeatureName; + } + + expectedEnabled = true; + if (cfg_2.mEnabled != expectedEnabled) { + return testing::AssertionFailure() + << "cfg.mEnabled: " << cfg_2.mEnabled + << ", expected: " << expectedEnabled; + } + + expectedGpuVendorIDs = { + 0, // GpuVendorID::VENDOR_ID_TEST + 0x8086, // GpuVendorID::VENDOR_ID_INTEL + }; + if (cfg_2.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) { + return testing::AssertionFailure() + << "cfg.mGpuVendorIDs.size(): " << cfg_2.mGpuVendorIDs.size() + << ", expected: " << expectedGpuVendorIDs.size(); + } + for (int i = 0; i < expectedGpuVendorIDs.size(); i++) { + if (cfg_2.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) { + std::stringstream msg; + msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg_2.mGpuVendorIDs[i] + << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i]; + return testing::AssertionFailure() << msg.str(); + } + } + + return testing::AssertionSuccess(); +} + +TEST_F(FeatureOverrideParserTest, packageOverrides3) { +FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides(); + +EXPECT_TRUE(validatePackageOverrides3(overrides)); +} + TEST_F(FeatureOverrideParserTest, forceFileRead) { FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides(); diff --git a/services/gpuservice/tests/unittests/data/feature_config_test.txtpb b/services/gpuservice/tests/unittests/data/feature_config_test.txtpb index 726779e332..44a6f78e84 100644 --- a/services/gpuservice/tests/unittests/data/feature_config_test.txtpb +++ b/services/gpuservice/tests/unittests/data/feature_config_test.txtpb @@ -22,6 +22,22 @@ global_features [ { feature_name: "globalOverrides1" enabled: False + }, + { + feature_name: "globalOverrides2" + enabled: True + gpu_vendor_ids: [ + VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed. + VENDOR_ID_ARM + ] + }, + { + feature_name: "globalOverrides3" + enabled: True + gpu_vendor_ids: [ + VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed. + VENDOR_ID_INTEL + ] } ] @@ -36,5 +52,39 @@ package_features [ enabled: True } ] + }, + { + package_name: "com.gpuservice_unittest.packageOverrides2" + feature_configs: [ + { + feature_name: "packageOverrides2" + enabled: False + gpu_vendor_ids: [ + VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed. + VENDOR_ID_INTEL + ] + } + ] + }, + { + package_name: "com.gpuservice_unittest.packageOverrides3" + feature_configs: [ + { + feature_name: "packageOverrides3_1" + enabled: False + gpu_vendor_ids: [ + VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed. + VENDOR_ID_ARM + ] + }, + { + feature_name: "packageOverrides3_2" + enabled: True + gpu_vendor_ids: [ + VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed. + VENDOR_ID_INTEL + ] + } + ] } ] diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp index 805bf45603..f8ab830d2d 100644 --- a/services/inputflinger/PointerChoreographer.cpp +++ b/services/inputflinger/PointerChoreographer.cpp @@ -674,7 +674,13 @@ ui::LogicalDisplayId PointerChoreographer::getTargetMouseDisplayLocked( mTopology.graph.find(associatedDisplayId) == mTopology.graph.end()) { return associatedDisplayId; } - return mCurrentMouseDisplayId.isValid() ? mCurrentMouseDisplayId : mTopology.primaryDisplayId; + if (mCurrentMouseDisplayId.isValid()) { + return mCurrentMouseDisplayId; + } + if (mTopology.primaryDisplayId.isValid()) { + return mTopology.primaryDisplayId; + } + return ui::LogicalDisplayId::DEFAULT; } std::pair<ui::LogicalDisplayId, PointerControllerInterface&> @@ -783,7 +789,8 @@ PointerChoreographer::PointerDisplayChange PointerChoreographer::calculatePointerDisplayChangeToNotify() { ui::LogicalDisplayId displayIdToNotify = ui::LogicalDisplayId::INVALID; vec2 cursorPosition = {0, 0}; - if (const auto it = mMousePointersByDisplay.find(mCurrentMouseDisplayId); + if (const auto it = + mMousePointersByDisplay.find(getTargetMouseDisplayLocked(mCurrentMouseDisplayId)); it != mMousePointersByDisplay.end()) { const auto& pointerController = it->second; // Use the displayId from the pointerController, because it accurately reflects whether diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index 845cab05d3..58df692b3e 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -32,6 +32,7 @@ #include <unistd.h> #include <utils/Errors.h> #include <utils/Thread.h> +#include <string> #include "InputDevice.h" #include "include/gestures.h" @@ -945,7 +946,10 @@ bool InputReader::setKernelWakeEnabled(int32_t deviceId, bool enabled) { void InputReader::dump(std::string& dump) { std::scoped_lock _l(mLock); + dumpLocked(dump); +} +void InputReader::dumpLocked(std::string& dump) { mEventHub->dump(dump); dump += "\n"; @@ -1032,6 +1036,12 @@ void InputReader::monitor() { InputReader::ContextImpl::ContextImpl(InputReader* reader) : mReader(reader), mIdGenerator(IdGenerator::Source::INPUT_READER) {} +std::string InputReader::ContextImpl::dump() { + std::string dump; + mReader->dumpLocked(dump); + return dump; +} + void InputReader::ContextImpl::updateGlobalMetaState() { // lock is already held by the input loop mReader->updateGlobalMetaStateLocked(); diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index 0d6e1020c1..6a259373df 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -21,6 +21,7 @@ #include <utils/Mutex.h> #include <memory> +#include <string> #include <unordered_map> #include <vector> @@ -142,6 +143,7 @@ protected: public: explicit ContextImpl(InputReader* reader); + std::string dump() REQUIRES(mReader->mLock) override; // lock is already held by the input loop void updateGlobalMetaState() NO_THREAD_SAFETY_ANALYSIS override; int32_t getGlobalMetaState() NO_THREAD_SAFETY_ANALYSIS override; @@ -216,6 +218,8 @@ private: // The input device that produced a new gesture most recently. DeviceId mLastUsedDeviceId GUARDED_BY(mLock){ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID}; + void dumpLocked(std::string& dump) REQUIRES(mLock); + // low-level input event decoding and device management [[nodiscard]] std::list<NotifyArgs> processEventsLocked(const RawEvent* rawEvents, size_t count) REQUIRES(mLock); diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h index 20ed74fef7..f38fd7b8ac 100644 --- a/services/inputflinger/reader/include/InputReaderContext.h +++ b/services/inputflinger/reader/include/InputReaderContext.h @@ -20,6 +20,7 @@ #include <input/KeyboardClassifier.h> #include "NotifyArgs.h" +#include <string> #include <vector> namespace android { @@ -39,6 +40,8 @@ public: InputReaderContext() {} virtual ~InputReaderContext() {} + virtual std::string dump() = 0; + virtual void updateGlobalMetaState() = 0; virtual int32_t getGlobalMetaState() = 0; diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp index dd46bbc543..d796af158b 100644 --- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp +++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp @@ -25,8 +25,6 @@ #include <linux/input-event-codes.h> #include <log/log_main.h> -namespace input_flags = com::android::input::flags; - namespace android { namespace { @@ -119,15 +117,10 @@ std::string CapturedTouchpadEventConverter::dump() const { } void CapturedTouchpadEventConverter::populateMotionRanges(InputDeviceInfo& info) const { - if (input_flags::include_relative_axis_values_for_captured_touchpads()) { - tryAddRawMotionRangeWithRelative(/*byref*/ info, AMOTION_EVENT_AXIS_X, - AMOTION_EVENT_AXIS_RELATIVE_X, ABS_MT_POSITION_X); - tryAddRawMotionRangeWithRelative(/*byref*/ info, AMOTION_EVENT_AXIS_Y, - AMOTION_EVENT_AXIS_RELATIVE_Y, ABS_MT_POSITION_Y); - } else { - tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_X, ABS_MT_POSITION_X); - tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_Y, ABS_MT_POSITION_Y); - } + tryAddRawMotionRangeWithRelative(/*byref*/ info, AMOTION_EVENT_AXIS_X, + AMOTION_EVENT_AXIS_RELATIVE_X, ABS_MT_POSITION_X); + tryAddRawMotionRangeWithRelative(/*byref*/ info, AMOTION_EVENT_AXIS_Y, + AMOTION_EVENT_AXIS_RELATIVE_Y, ABS_MT_POSITION_Y); tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOUCH_MAJOR, ABS_MT_TOUCH_MAJOR); tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOUCH_MINOR, ABS_MT_TOUCH_MINOR); tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MAJOR, ABS_MT_WIDTH_MAJOR); @@ -213,13 +206,11 @@ std::list<NotifyArgs> CapturedTouchpadEventConverter::sync(nsecs_t when, nsecs_t } out.push_back( makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_MOVE, coords, properties)); - if (input_flags::include_relative_axis_values_for_captured_touchpads()) { - // For any further events we send from this sync, the pointers won't have moved relative - // to the positions we just reported in this MOVE event, so zero out the relative axes. - for (PointerCoords& pointer : coords) { - pointer.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0); - pointer.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0); - } + // For any further events we send from this sync, the pointers won't have moved relative to + // the positions we just reported in this MOVE event, so zero out the relative axes. + for (PointerCoords& pointer : coords) { + pointer.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0); + pointer.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0); } } @@ -275,9 +266,7 @@ std::list<NotifyArgs> CapturedTouchpadEventConverter::sync(nsecs_t when, nsecs_t /*flags=*/cancel ? AMOTION_EVENT_FLAG_CANCELED : 0)); freePointerIdForSlot(slotNumber); - if (input_flags::include_relative_axis_values_for_captured_touchpads()) { - mPreviousCoordsForSlotNumber.erase(slotNumber); - } + mPreviousCoordsForSlotNumber.erase(slotNumber); coords.erase(coords.begin() + indexToRemove); properties.erase(properties.begin() + indexToRemove); // Now that we've removed some coords and properties, we might have to update the slot @@ -336,15 +325,13 @@ PointerCoords CapturedTouchpadEventConverter::makePointerCoordsForSlot(size_t sl coords.clear(); coords.setAxisValue(AMOTION_EVENT_AXIS_X, slot.getX()); coords.setAxisValue(AMOTION_EVENT_AXIS_Y, slot.getY()); - if (input_flags::include_relative_axis_values_for_captured_touchpads()) { - if (auto it = mPreviousCoordsForSlotNumber.find(slotNumber); - it != mPreviousCoordsForSlotNumber.end()) { - auto [oldX, oldY] = it->second; - coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, slot.getX() - oldX); - coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, slot.getY() - oldY); - } - mPreviousCoordsForSlotNumber[slotNumber] = std::make_pair(slot.getX(), slot.getY()); + if (auto it = mPreviousCoordsForSlotNumber.find(slotNumber); + it != mPreviousCoordsForSlotNumber.end()) { + auto [oldX, oldY] = it->second; + coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, slot.getX() - oldX); + coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, slot.getY() - oldY); } + mPreviousCoordsForSlotNumber[slotNumber] = std::make_pair(slot.getX(), slot.getY()); coords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, slot.getTouchMajor()); coords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, slot.getTouchMinor()); diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 8deff6b3aa..4d36db8ff7 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -24,6 +24,8 @@ #include <cinttypes> #include <cmath> #include <cstddef> +#include <sstream> +#include <string> #include <tuple> #include <math.h> @@ -138,6 +140,40 @@ void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) con *outY = y; } +std::ostream& operator<<(std::ostream& out, const RawPointerData::Pointer& p) { + out << "id=" << p.id << ", x=" << p.x << ", y=" << p.y << ", pressure=" << p.pressure + << ", touchMajor=" << p.touchMajor << ", touchMinor=" << p.touchMinor + << ", toolMajor=" << p.toolMajor << ", toolMinor=" << p.toolMinor + << ", orientation=" << p.orientation << ", tiltX=" << p.tiltX << ", tiltY=" << p.tiltY + << ", distance=" << p.distance << ", toolType=" << ftl::enum_string(p.toolType) + << ", isHovering=" << p.isHovering; + return out; +} + +std::ostream& operator<<(std::ostream& out, const RawPointerData& data) { + out << data.pointerCount << " pointers:\n"; + for (uint32_t i = 0; i < data.pointerCount; i++) { + out << INDENT << "[" << i << "]: " << data.pointers[i] << std::endl; + } + out << "ID bits: hovering = 0x" << std::hex << std::setfill('0') << std::setw(8) + << data.hoveringIdBits.value << ", touching = 0x" << std::setfill('0') << std::setw(8) + << data.touchingIdBits.value << ", canceled = 0x" << std::setfill('0') << std::setw(8) + << data.canceledIdBits.value << std::dec; + return out; +} + +// --- TouchInputMapper::RawState --- + +std::ostream& operator<<(std::ostream& out, const TouchInputMapper::RawState& state) { + out << "When: " << state.when << std::endl; + out << "Read time: " << state.readTime << std::endl; + out << "Button state: 0x" << std::setfill('0') << std::setw(8) << std::hex << state.buttonState + << std::dec << std::endl; + out << "Raw pointer data:" << std::endl; + out << addLinePrefix(streamableToString(state.rawPointerData), INDENT); + return out; +} + // --- TouchInputMapper --- TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext, @@ -232,20 +268,8 @@ void TouchInputMapper::dump(std::string& dump) { dump += StringPrintf(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale); dump += StringPrintf(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState); - dump += StringPrintf(INDENT3 "Last Raw Touch: pointerCount=%d\n", - mLastRawState.rawPointerData.pointerCount); - for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) { - const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i]; - dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, " - "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, " - "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, " - "toolType=%s, isHovering=%s\n", - i, pointer.id, pointer.x, pointer.y, pointer.pressure, - pointer.touchMajor, pointer.touchMinor, pointer.toolMajor, - pointer.toolMinor, pointer.orientation, pointer.tiltX, pointer.tiltY, - pointer.distance, ftl::enum_string(pointer.toolType).c_str(), - toString(pointer.isHovering)); - } + dump += INDENT3 "Last Raw Touch:\n"; + dump += addLinePrefix(streamableToString(mLastRawState), INDENT4) + "\n"; dump += StringPrintf(INDENT3 "Last Cooked Button State: 0x%08x\n", mLastCookedState.buttonState); @@ -1476,6 +1500,22 @@ std::list<NotifyArgs> TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) { last.rawPointerData.touchingIdBits.value, next.rawPointerData.touchingIdBits.value, last.rawPointerData.hoveringIdBits.value, next.rawPointerData.hoveringIdBits.value, next.rawPointerData.canceledIdBits.value); + if (debugRawEvents() && last.rawPointerData.pointerCount == 0 && + next.rawPointerData.pointerCount == 1) { + // Dump a bunch of info to try to debug b/396796958. + // TODO(b/396796958): remove this debug dump. + ALOGD("pointerCount went from 0 to 1. last:\n%s", + addLinePrefix(streamableToString(last), INDENT).c_str()); + ALOGD("next:\n%s", addLinePrefix(streamableToString(next), INDENT).c_str()); + ALOGD("InputReader dump:"); + // The dump is too long to simply add as a format parameter in one log message, so we have + // to split it by line and log them individually. + std::istringstream stream(mDeviceContext.getContext()->dump()); + std::string line; + while (std::getline(stream, line, '\n')) { + ALOGD(INDENT "%s", line.c_str()); + } + } if (!next.rawPointerData.touchingIdBits.isEmpty() && !next.rawPointerData.hoveringIdBits.isEmpty() && diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index 4ef0be8f8e..45fc6bfa36 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -348,6 +348,8 @@ protected: inline void clear() { *this = RawState(); } }; + friend std::ostream& operator<<(std::ostream& out, const RawState& state); + struct CookedState { // Cooked pointer sample data. CookedPointerData cookedPointerData{}; diff --git a/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp b/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp index 353011aa5c..c6246d9eec 100644 --- a/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp +++ b/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp @@ -33,8 +33,6 @@ #include "TestEventMatchers.h" #include "TestInputListener.h" -namespace input_flags = com::android::input::flags; - namespace android { using testing::AllOf; @@ -50,8 +48,6 @@ public: mReader(mFakeEventHub, mFakePolicy, mFakeListener), mDevice(newDevice()), mDeviceContext(*mDevice, EVENTHUB_ID) { - input_flags::include_relative_axis_values_for_captured_touchpads(true); - const size_t slotCount = 8; mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, 0, slotCount - 1, 0, 0, 0); mAccumulator.configure(mDeviceContext, slotCount, /*usingSlotsProtocol=*/true); diff --git a/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp b/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp index c4257a83c3..dcb148fe41 100644 --- a/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp +++ b/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp @@ -198,10 +198,6 @@ void FakeInputDispatcherPolicy::assertNotifyInputChannelBrokenWasCalled(const sp ASSERT_EQ(token, *receivedToken); } -void FakeInputDispatcherPolicy::setInterceptKeyTimeout(std::chrono::milliseconds timeout) { - mInterceptKeyTimeout = timeout; -} - std::chrono::nanoseconds FakeInputDispatcherPolicy::getKeyWaitingForEventsTimeout() { return 500ms; } @@ -210,8 +206,9 @@ void FakeInputDispatcherPolicy::setStaleEventTimeout(std::chrono::nanoseconds ti mStaleEventTimeout = timeout; } -void FakeInputDispatcherPolicy::setConsumeKeyBeforeDispatching(bool consumeKeyBeforeDispatching) { - mConsumeKeyBeforeDispatching = consumeKeyBeforeDispatching; +void FakeInputDispatcherPolicy::setInterceptKeyBeforeDispatchingResult( + std::variant<nsecs_t, inputdispatcher::KeyEntry::InterceptKeyResult> result) { + mInterceptKeyBeforeDispatchingResult = result; } void FakeInputDispatcherPolicy::assertFocusedDisplayNotified(ui::LogicalDisplayId expectedDisplay) { @@ -404,7 +401,9 @@ bool FakeInputDispatcherPolicy::filterInputEvent(const InputEvent& inputEvent, void FakeInputDispatcherPolicy::interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) { if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) { // Clear intercept state when we handled the event. - mInterceptKeyTimeout = 0ms; + if (std::holds_alternative<nsecs_t>(mInterceptKeyBeforeDispatchingResult)) { + mInterceptKeyBeforeDispatchingResult = nsecs_t(0); + } } } @@ -414,17 +413,20 @@ void FakeInputDispatcherPolicy::interceptMotionBeforeQueueing(ui::LogicalDisplay std::variant<nsecs_t, inputdispatcher::KeyEntry::InterceptKeyResult> FakeInputDispatcherPolicy::interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) { - if (mConsumeKeyBeforeDispatching) { - return inputdispatcher::KeyEntry::InterceptKeyResult::SKIP; + if (std::holds_alternative<inputdispatcher::KeyEntry::InterceptKeyResult>( + mInterceptKeyBeforeDispatchingResult)) { + return mInterceptKeyBeforeDispatchingResult; } - nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count(); + nsecs_t delay = + std::chrono::nanoseconds(std::get<nsecs_t>(mInterceptKeyBeforeDispatchingResult)) + .count(); if (delay == 0) { return inputdispatcher::KeyEntry::InterceptKeyResult::CONTINUE; } // Clear intercept state so we could dispatch the event in next wake. - mInterceptKeyTimeout = 0ms; + mInterceptKeyBeforeDispatchingResult = nsecs_t(0); return delay; } diff --git a/services/inputflinger/tests/FakeInputDispatcherPolicy.h b/services/inputflinger/tests/FakeInputDispatcherPolicy.h index c387eacb51..b151686e9b 100644 --- a/services/inputflinger/tests/FakeInputDispatcherPolicy.h +++ b/services/inputflinger/tests/FakeInputDispatcherPolicy.h @@ -96,10 +96,6 @@ public: void assertDropTargetEquals(const InputDispatcherInterface& dispatcher, const sp<IBinder>& targetToken); void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token); - /** - * Set policy timeout. A value of zero means next key will not be intercepted. - */ - void setInterceptKeyTimeout(std::chrono::milliseconds timeout); std::chrono::nanoseconds getKeyWaitingForEventsTimeout() override; void setStaleEventTimeout(std::chrono::nanoseconds timeout); void assertUserActivityNotPoked(); @@ -116,7 +112,12 @@ public: void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler); void assertUnhandledKeyReported(int32_t keycode); void assertUnhandledKeyNotReported(); - void setConsumeKeyBeforeDispatching(bool consumeKeyBeforeDispatching); + /** + * Set policy timeout or the interception result. + * A timeout value of zero means next key will not be intercepted. + */ + void setInterceptKeyBeforeDispatchingResult( + std::variant<nsecs_t, inputdispatcher::KeyEntry::InterceptKeyResult> result); void assertFocusedDisplayNotified(ui::LogicalDisplayId expectedDisplay); private: @@ -145,11 +146,10 @@ private: std::condition_variable mNotifyUserActivity; std::queue<UserActivityPokeEvent> mUserActivityPokeEvents; - std::chrono::milliseconds mInterceptKeyTimeout = 0ms; - std::chrono::nanoseconds mStaleEventTimeout = 1000ms; - bool mConsumeKeyBeforeDispatching = false; + std::variant<nsecs_t, inputdispatcher::KeyEntry::InterceptKeyResult> + mInterceptKeyBeforeDispatchingResult; BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 2b9b470a21..835b677e1e 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -5491,7 +5491,8 @@ TEST_F(InputDispatcherTest, InterceptKeyByPolicy) { generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT); const std::chrono::milliseconds interceptKeyTimeout = 50ms; const nsecs_t injectTime = keyArgs.eventTime; - mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout); + mFakePolicy->setInterceptKeyBeforeDispatchingResult( + std::chrono::nanoseconds(interceptKeyTimeout).count()); mDispatcher->notifyKey(keyArgs); // The dispatching time should be always greater than or equal to intercept key timeout. window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT); @@ -5519,7 +5520,7 @@ TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) { // Set a value that's significantly larger than the default consumption timeout. If the // implementation is correct, the actual value doesn't matter; it won't slow down the test. - mFakePolicy->setInterceptKeyTimeout(600ms); + mFakePolicy->setInterceptKeyBeforeDispatchingResult(std::chrono::nanoseconds(600ms).count()); mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT)); // Window should receive key event immediately when same key up. window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); @@ -7438,7 +7439,8 @@ TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) { window->consumeFocusEvent(true); - mFakePolicy->setConsumeKeyBeforeDispatching(true); + mFakePolicy->setInterceptKeyBeforeDispatchingResult( + inputdispatcher::KeyEntry::InterceptKeyResult::SKIP); mDispatcher->notifyKey( KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build()); @@ -7464,7 +7466,8 @@ TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserAct window->consumeFocusEvent(true); - mFakePolicy->setConsumeKeyBeforeDispatching(true); + mFakePolicy->setInterceptKeyBeforeDispatchingResult( + inputdispatcher::KeyEntry::InterceptKeyResult::SKIP); mDispatcher->notifyKey( KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build()); @@ -9307,6 +9310,24 @@ TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) { mWindow->assertNoEvents(); } +TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterFocusedWindowChanged) { + sp<FakeWindowHandle> anotherWindow = + sp<FakeWindowHandle>::make(mApp, mDispatcher, "AnotherWindow", + ui::LogicalDisplayId::DEFAULT); + anotherWindow->setFocusable(true); + mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *anotherWindow->getInfo()}, {}, 0, 0}); + + sendAndConsumeKeyDown(/*deviceId=*/1); + expectKeyRepeatOnce(/*repeatCount=*/1); + expectKeyRepeatOnce(/*repeatCount=*/2); + setFocusedWindow(anotherWindow); + anotherWindow->consumeFocusEvent(true); + + // Window should receive key up event with cancel. + mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED); + anotherWindow->assertNoEvents(); +} + TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) { sendAndConsumeKeyDown(/*deviceId=*/1); expectKeyRepeatOnce(/*repeatCount=*/1); diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h index 06d60ce53a..d4e4bb00f7 100644 --- a/services/inputflinger/tests/InterfaceMocks.h +++ b/services/inputflinger/tests/InterfaceMocks.h @@ -50,6 +50,8 @@ namespace android { class MockInputReaderContext : public InputReaderContext { public: + std::string dump() override { return "(dump from MockInputReaderContext)"; } + MOCK_METHOD(void, updateGlobalMetaState, (), (override)); MOCK_METHOD(int32_t, getGlobalMetaState, (), (override)); diff --git a/services/inputflinger/tests/KeyboardInputMapper_test.cpp b/services/inputflinger/tests/KeyboardInputMapper_test.cpp index 40bbd3468e..d4b15bca48 100644 --- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp +++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp @@ -691,32 +691,163 @@ TEST_F(KeyboardInputMapperUnitTest, Process_GestureEventToSetFlagKeepTouchMode) expectSingleKeyArg(argsList).flags); } -TEST_F_WITH_FLAGS(KeyboardInputMapperUnitTest, WakeBehavior_AlphabeticKeyboard, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags, - enable_alphabetic_keyboard_wake))) { - // For internal alphabetic devices, keys will trigger wake on key down. +// --- KeyboardInputMapperUnitTest_WakeFlagOverride --- + +class KeyboardInputMapperUnitTest_WakeFlagOverride : public KeyboardInputMapperUnitTest { +protected: + virtual void SetUp() override { + SetUp(/*wakeFlag=*/com::android::input::flags::enable_alphabetic_keyboard_wake()); + } + + void SetUp(bool wakeFlag) { + mWakeFlagInitialValue = com::android::input::flags::enable_alphabetic_keyboard_wake(); + com::android::input::flags::enable_alphabetic_keyboard_wake(wakeFlag); + KeyboardInputMapperUnitTest::SetUp(); + } + + void TearDown() override { + com::android::input::flags::enable_alphabetic_keyboard_wake(mWakeFlagInitialValue); + KeyboardInputMapperUnitTest::TearDown(); + } + + bool mWakeFlagInitialValue; +}; + +// --- KeyboardInputMapperUnitTest_NonAlphabeticKeyboard_WakeFlagEnabled --- + +class KeyboardInputMapperUnitTest_NonAlphabeticKeyboard_WakeFlagEnabled + : public KeyboardInputMapperUnitTest_WakeFlagOverride { +protected: + void SetUp() override { + KeyboardInputMapperUnitTest_WakeFlagOverride::SetUp(/*wakeFlag=*/true); + } +}; + +TEST_F(KeyboardInputMapperUnitTest_NonAlphabeticKeyboard_WakeFlagEnabled, + NonAlphabeticDevice_WakeBehavior) { + // For internal non-alphabetic devices keys will not trigger wake. addKeyByEvdevCode(KEY_A, AKEYCODE_A); addKeyByEvdevCode(KEY_HOME, AKEYCODE_HOME); addKeyByEvdevCode(KEY_PLAYPAUSE, AKEYCODE_MEDIA_PLAY_PAUSE); std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_A, 1); - ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_A, 0); - ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); argsList = processKeyAndSync(ARBITRARY_TIME, KEY_HOME, 1); - ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_HOME, 0); - ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); argsList = processKeyAndSync(ARBITRARY_TIME, KEY_PLAYPAUSE, 1); - ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_PLAYPAUSE, 0); - ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); +} + +// --- KeyboardInputMapperUnitTest_AlphabeticKeyboard_WakeFlagEnabled --- + +class KeyboardInputMapperUnitTest_AlphabeticKeyboard_WakeFlagEnabled + : public KeyboardInputMapperUnitTest_WakeFlagOverride { +protected: + void SetUp() override { + KeyboardInputMapperUnitTest_WakeFlagOverride::SetUp(/*wakeFlag=*/true); + + ON_CALL((*mDevice), getKeyboardType).WillByDefault(Return(KeyboardType::ALPHABETIC)); + } +}; + +TEST_F(KeyboardInputMapperUnitTest_AlphabeticKeyboard_WakeFlagEnabled, WakeBehavior) { + // For internal alphabetic devices, keys will trigger wake on key down when + // flag is enabled. + addKeyByEvdevCode(KEY_A, AKEYCODE_A); + addKeyByEvdevCode(KEY_HOME, AKEYCODE_HOME); + addKeyByEvdevCode(KEY_PLAYPAUSE, AKEYCODE_MEDIA_PLAY_PAUSE); + + std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_A, 1); + EXPECT_THAT(argsList, + ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(POLICY_FLAG_WAKE)))); + + argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_A, 0); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); + + argsList = processKeyAndSync(ARBITRARY_TIME, KEY_HOME, 1); + EXPECT_THAT(argsList, + ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(POLICY_FLAG_WAKE)))); + + argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_HOME, 0); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); + + argsList = processKeyAndSync(ARBITRARY_TIME, KEY_PLAYPAUSE, 1); + EXPECT_THAT(argsList, + ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(POLICY_FLAG_WAKE)))); + + argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_PLAYPAUSE, 0); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); +} + +TEST_F(KeyboardInputMapperUnitTest_AlphabeticKeyboard_WakeFlagEnabled, WakeBehavior_UnknownKey) { + // For internal alphabetic devices, unknown keys will trigger wake on key down when + // flag is enabled. + + const int32_t USAGE_UNKNOWN = 0x07ffff; + EXPECT_CALL(mMockEventHub, mapKey(EVENTHUB_ID, KEY_UNKNOWN, USAGE_UNKNOWN, _, _, _, _)) + .WillRepeatedly(Return(NAME_NOT_FOUND)); + + // Key down with unknown scan code or usage code. + std::list<NotifyArgs> argsList = process(ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN); + argsList += process(ARBITRARY_TIME, EV_KEY, KEY_UNKNOWN, 1); + EXPECT_THAT(argsList, + ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(POLICY_FLAG_WAKE)))); + + // Key up with unknown scan code or usage code. + argsList = process(ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN); + argsList += process(ARBITRARY_TIME + 1, EV_KEY, KEY_UNKNOWN, 0); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); +} + +// --- KeyboardInputMapperUnitTest_AlphabeticDevice_AlphabeticKeyboardWakeDisabled --- + +class KeyboardInputMapperUnitTest_AlphabeticKeyboard_WakeFlagDisabled + : public KeyboardInputMapperUnitTest_WakeFlagOverride { +protected: + void SetUp() override { + KeyboardInputMapperUnitTest_WakeFlagOverride::SetUp(/*wakeFlag=*/false); + + ON_CALL((*mDevice), getKeyboardType).WillByDefault(Return(KeyboardType::ALPHABETIC)); + } +}; + +TEST_F(KeyboardInputMapperUnitTest_AlphabeticKeyboard_WakeFlagDisabled, WakeBehavior) { + // For internal alphabetic devices, keys will not trigger wake when flag is + // disabled. + + addKeyByEvdevCode(KEY_A, AKEYCODE_A); + addKeyByEvdevCode(KEY_HOME, AKEYCODE_HOME); + addKeyByEvdevCode(KEY_PLAYPAUSE, AKEYCODE_MEDIA_PLAY_PAUSE); + + std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_A, 1); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); + + argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_A, 0); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); + + argsList = processKeyAndSync(ARBITRARY_TIME, KEY_HOME, 1); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); + + argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_HOME, 0); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); + + argsList = processKeyAndSync(ARBITRARY_TIME, KEY_PLAYPAUSE, 1); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); + + argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_PLAYPAUSE, 0); + EXPECT_THAT(argsList, ElementsAre(VariantWith<NotifyKeyArgs>(WithPolicyFlags(0U)))); } // --- KeyboardInputMapperTest --- diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp index b691098ff4..2b469c5645 100644 --- a/services/inputflinger/tests/PointerChoreographer_test.cpp +++ b/services/inputflinger/tests/PointerChoreographer_test.cpp @@ -358,6 +358,17 @@ TEST_F(PointerChoreographerTest, CallsNotifyPointerDisplayIdChanged) { assertPointerDisplayIdNotified(DISPLAY_ID); } +TEST_F(PointerChoreographerTest, NoDefaultMouseSetFallbackToDefaultDisplayId) { + mChoreographer.setDisplayViewports(createViewports({ui::LogicalDisplayId::DEFAULT})); + mChoreographer.notifyInputDevicesChanged( + {/*id=*/0, + {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, + ui::LogicalDisplayId::INVALID)}}); + assertPointerControllerCreated(ControllerType::MOUSE); + + assertPointerDisplayIdNotified(ui::LogicalDisplayId::DEFAULT); +} + TEST_F(PointerChoreographerTest, WhenViewportIsSetLaterCallsNotifyPointerDisplayIdChanged) { setDefaultMouseDisplayId(DISPLAY_ID); mChoreographer.notifyInputDevicesChanged( diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index bba7389eed..9a5903981b 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -360,6 +360,7 @@ public: std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp) : mEventHub(eventHub), mPolicy(sp<FuzzInputReaderPolicy>::make(fdp)), mFdp(fdp) {} ~FuzzInputReaderContext() {} + std::string dump() { return "(dump from FuzzInputReaderContext)"; } void updateGlobalMetaState() override {} int32_t getGlobalMetaState() { return mFdp->ConsumeIntegral<int32_t>(); } void disableVirtualKeysUntil(nsecs_t time) override {} diff --git a/services/sensorservice/sensorservice_flags.aconfig b/services/sensorservice/sensorservice_flags.aconfig index 452b42826c..63089737e3 100644 --- a/services/sensorservice/sensorservice_flags.aconfig +++ b/services/sensorservice/sensorservice_flags.aconfig @@ -37,4 +37,14 @@ flag { metadata { purpose: PURPOSE_BUGFIX } +} + +flag { + name: "disable_vndk_forged_name" + namespace: "sensors" + description: "When this flag is enabled, sensor manager will not use forged name to determine if an access is from VNDK" + bug: "398253250" + metadata { + purpose: PURPOSE_BUGFIX + } }
\ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h index f934cb20a0..e42b9b12f4 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h @@ -253,7 +253,6 @@ private: std::unordered_map<size_t, size_t> mFinalLayerCounts; size_t mCachedSetCreationCount = 0; size_t mCachedSetCreationCost = 0; - std::unordered_map<size_t, size_t> mInvalidatedCachedSetAges; }; } // namespace compositionengine::impl::planner diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index b29082384d..2081cd5400 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -243,17 +243,9 @@ void Flattener::resetActivities(NonBufferHash hash, time_point now) { mCurrentGeometry = hash; mLastGeometryUpdate = now; - - for (const CachedSet& cachedSet : mLayers) { - if (cachedSet.getLayerCount() > 1) { - ++mInvalidatedCachedSetAges[cachedSet.getAge()]; - } - } - mLayers.clear(); if (mNewCachedSet) { - ++mInvalidatedCachedSetAges[mNewCachedSet->getAge()]; mNewCachedSet = std::nullopt; } } @@ -312,7 +304,6 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers mNewCachedSet->getFirstLayer().getState()->getId() == (*incomingLayerIter)->getId()) { if (mNewCachedSet->hasBufferUpdate()) { ALOGV("[%s] Dropping new cached set", __func__); - ++mInvalidatedCachedSetAges[0]; mNewCachedSet = std::nullopt; } else if (mNewCachedSet->hasReadyBuffer()) { ALOGV("[%s] Found ready buffer", __func__); @@ -339,10 +330,6 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers }; ++incomingLayerIter; } - - if (currentLayerIter->getLayerCount() > 1) { - ++mInvalidatedCachedSetAges[currentLayerIter->getAge()]; - } ++currentLayerIter; skipCount -= layerCount; @@ -382,7 +369,6 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers priorBlurLayer = currentLayerIter->getBlurLayer(); } else if (currentLayerIter->getLayerCount() > 1) { // Break the current layer into its constituent layers - ++mInvalidatedCachedSetAges[currentLayerIter->getAge()]; for (CachedSet& layer : currentLayerIter->decompose()) { bool disableBlur = priorBlurLayer && priorBlurLayer == (*incomingLayerIter)->getOutputLayer(); diff --git a/services/surfaceflinger/Display/DisplayModeController.cpp b/services/surfaceflinger/Display/DisplayModeController.cpp index a086aee847..87a677cd58 100644 --- a/services/surfaceflinger/Display/DisplayModeController.cpp +++ b/services/surfaceflinger/Display/DisplayModeController.cpp @@ -97,9 +97,7 @@ auto DisplayModeController::setDesiredMode(PhysicalDisplayId displayId, const bool force = desiredModeOpt->force; desiredModeOpt = std::move(desiredMode); desiredModeOpt->emitEvent |= emitEvent; - if (FlagManager::getInstance().connected_display()) { - desiredModeOpt->force |= force; - } + desiredModeOpt->force |= force; return DesiredModeAction::None; } @@ -191,7 +189,7 @@ auto DisplayModeController::initiateModeChange( // cleared until the next `SF::initiateDisplayModeChanges`. However, the desired mode has been // consumed at this point, so clear the `force` flag to prevent an endless loop of // `initiateModeChange`. - if (FlagManager::getInstance().connected_display()) { + { std::scoped_lock lock(displayPtr->desiredModeLock); if (displayPtr->desiredModeOpt) { displayPtr->desiredModeOpt->force = false; diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index e8b09b043e..07770f12ba 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -51,6 +51,17 @@ namespace android { namespace hal = hardware::graphics::composer::hal; +namespace gui { +inline std::string_view to_string(ISurfaceComposer::OptimizationPolicy optimizationPolicy) { + switch (optimizationPolicy) { + case ISurfaceComposer::OptimizationPolicy::optimizeForPower: + return "optimizeForPower"; + case ISurfaceComposer::OptimizationPolicy::optimizeForPerformance: + return "optimizeForPerformance"; + } +} +} // namespace gui + DisplayDeviceCreationArgs::DisplayDeviceCreationArgs( const sp<SurfaceFlinger>& flinger, HWComposer& hwComposer, const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay) @@ -283,6 +294,7 @@ void DisplayDevice::dump(utils::Dumper& dumper) const { dumper.dump("name"sv, '"' + mDisplayName + '"'); dumper.dump("powerMode"sv, mPowerMode); + dumper.dump("optimizationPolicy"sv, mOptimizationPolicy); if (mRefreshRateSelector) { mRefreshRateSelector->dump(dumper); @@ -305,6 +317,15 @@ void DisplayDevice::setSecure(bool secure) { mCompositionDisplay->setSecure(secure); } +gui::ISurfaceComposer::OptimizationPolicy DisplayDevice::getOptimizationPolicy() const { + return mOptimizationPolicy; +} + +void DisplayDevice::setOptimizationPolicy( + gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy) { + mOptimizationPolicy = optimizationPolicy; +} + const Rect DisplayDevice::getBounds() const { return mCompositionDisplay->getState().displaySpace.getBoundsAsRect(); } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index b5a543a7c1..be374299f7 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -93,6 +93,11 @@ public: bool isSecure() const; void setSecure(bool secure); + // The optimization policy influences whether this display is optimized for power or + // performance. + gui::ISurfaceComposer::OptimizationPolicy getOptimizationPolicy() const; + void setOptimizationPolicy(gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy); + int getWidth() const; int getHeight() const; ui::Size getSize() const { return {getWidth(), getHeight()}; } @@ -236,6 +241,9 @@ private: // TODO(b/182939859): Remove special cases for primary display. const bool mIsPrimary; + gui::ISurfaceComposer::OptimizationPolicy mOptimizationPolicy = + gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance; + uint32_t mFlags = 0; // Requested refresh rate in fps, supported only for virtual displays. @@ -283,6 +291,9 @@ struct DisplayDeviceState { std::string displayName; std::string uniqueId; bool isSecure = false; + + gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy = + gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance; bool isProtected = false; // Refer to DisplayDevice::mRequestedRefreshRate, for virtual display only Fps requestedRefreshRate; diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 01f382f0e8..8d16a6bbb3 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -439,11 +439,8 @@ Error Display::setActiveConfigWithConstraints(hal::HWConfigId configId, // FIXME (b/319505580): At least the first config set on an external display must be // `setActiveConfig`, so skip over the block that calls `setActiveConfigWithConstraints` // for simplicity. - const bool connected_display = FlagManager::getInstance().connected_display(); - if (isVsyncPeriodSwitchSupported() && - (!connected_display || - getConnectionType().value_opt() != ui::DisplayConnectionType::External)) { + getConnectionType().value_opt() != ui::DisplayConnectionType::External) { Hwc2::IComposerClient::VsyncPeriodChangeConstraints hwc2Constraints; hwc2Constraints.desiredTimeNanos = constraints.desiredTimeNanos; hwc2Constraints.seamlessRequired = constraints.seamlessRequired; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 545ed1949a..14088a6428 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -145,7 +145,7 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId case HotplugEvent::Disconnected: return onHotplugDisconnect(hwcDisplayId); case HotplugEvent::LinkUnstable: - return {}; + return onHotplugLinkTrainingFailure(hwcDisplayId); } } @@ -1245,6 +1245,16 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect( return DisplayIdentificationInfo{.id = *displayId}; } +std::optional<DisplayIdentificationInfo> HWComposer::onHotplugLinkTrainingFailure( + hal::HWDisplayId hwcDisplayId) { + const auto displayId = toPhysicalDisplayId(hwcDisplayId); + if (!displayId) { + LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display"); + return {}; + } + return DisplayIdentificationInfo{.id = *displayId}; +} + void HWComposer::loadCapabilities() { static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed"); auto capabilities = mComposer->getCapabilities(); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 2c0aa3d6d5..472411cf99 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -544,6 +544,7 @@ private: std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId); std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hal::HWDisplayId); + std::optional<DisplayIdentificationInfo> onHotplugLinkTrainingFailure(hal::HWDisplayId); bool shouldIgnoreHotplugConnect(hal::HWDisplayId, uint8_t port, bool hasDisplayIdentificationData) const; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index 1f0d5d05a9..a80bdb4b39 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -41,7 +41,7 @@ void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFram if (forceFullDamage) { outSurfaceDamageRegion = Region::INVALID_REGION; } else { - outSurfaceDamageRegion = requested.surfaceDamageRegion; + outSurfaceDamageRegion = requested.getSurfaceDamageRegion(); } } @@ -376,7 +376,7 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate updateSurfaceDamage(requested, requested.hasReadyFrame(), forceFullDamage, surfaceDamage); if (forceUpdate || requested.what & layer_state_t::eTransparentRegionChanged) { - transparentRegionHint = requested.transparentRegion; + transparentRegionHint = requested.getTransparentRegion(); } if (forceUpdate || requested.what & layer_state_t::eFlagsChanged) { layerOpaqueFlagSet = @@ -448,15 +448,7 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate } if (forceUpdate || requested.what & layer_state_t::eInputInfoChanged) { - if (requested.windowInfoHandle) { - inputInfo = *requested.windowInfoHandle->getInfo(); - } else { - inputInfo = {}; - // b/271132344 revisit this and see if we can always use the layers uid/pid - inputInfo.name = requested.name; - inputInfo.ownerUid = requested.ownerUid; - inputInfo.ownerPid = requested.ownerPid; - } + inputInfo = requested.getWindowInfo(); inputInfo.id = static_cast<int32_t>(uniqueSequence); touchCropId = requested.touchCropId; } diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 86ef6ca61e..28a6031c97 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -1090,7 +1090,7 @@ void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot, snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds); const Rect geomLayerBoundsWithoutTransparentRegion = RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds), - requested.transparentRegion); + requested.getTransparentRegion()); snapshot.transformedBoundsWithoutTransparentRegion = snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion); snapshot.parentTransform = parentSnapshot.geomLayerTransform; @@ -1098,7 +1098,7 @@ void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot, if (requested.potentialCursor) { // Subtract the transparent region and snap to the bounds const Rect bounds = RequestedLayerState::reduce(Rect(snapshot.croppedBufferSize), - requested.transparentRegion); + requested.getTransparentRegion()); snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds); } } @@ -1132,22 +1132,14 @@ void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot, const Args& args) { using InputConfig = gui::WindowInfo::InputConfig; - if (requested.windowInfoHandle) { - snapshot.inputInfo = *requested.windowInfoHandle->getInfo(); - } else { - snapshot.inputInfo = {}; - // b/271132344 revisit this and see if we can always use the layers uid/pid - snapshot.inputInfo.name = requested.name; - snapshot.inputInfo.ownerUid = gui::Uid{requested.ownerUid}; - snapshot.inputInfo.ownerPid = gui::Pid{requested.ownerPid}; - } + snapshot.inputInfo = requested.getWindowInfo(); snapshot.touchCropId = requested.touchCropId; snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence); snapshot.inputInfo.displayId = ui::LogicalDisplayId{static_cast<int32_t>(snapshot.outputFilter.layerStack.id)}; snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo() - ? requested.windowInfoHandle->getInfo()->touchOcclusionMode + ? requested.getWindowInfo().touchOcclusionMode : parentSnapshot.inputInfo.touchOcclusionMode; snapshot.inputInfo.canOccludePresentation = parentSnapshot.inputInfo.canOccludePresentation || (requested.flags & layer_state_t::eCanOccludePresentation); diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index 58c235ed91..d322a61eb3 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -63,8 +63,11 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) metadata.merge(args.metadata); changes |= RequestedLayerState::Changes::Metadata; handleAlive = true; - // TODO: b/305254099 remove once we don't pass invisible windows to input - windowInfoHandle = nullptr; + // b/271132344 revisit this and see if we can always use the layers uid/pid + auto* windowInfo = editWindowInfo(); + windowInfo->name = name; + windowInfo->ownerPid = ownerPid; + windowInfo->ownerUid = ownerUid; if (parentId != UNASSIGNED_LAYER_ID) { canBeRoot = false; } @@ -105,7 +108,7 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) currentHdrSdrRatio = 1.f; dataspaceRequested = false; hdrMetadata.validTypes = 0; - surfaceDamageRegion = Region::INVALID_REGION; + mNotDefCmpState.surfaceDamageRegion = Region::INVALID_REGION; cornerRadius = 0.0f; clientDrawnCornerRadius = 0.0f; backgroundBlurRadius = 0; @@ -278,7 +281,7 @@ void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerSta if (clientState.what & layer_state_t::eReparent) { changes |= RequestedLayerState::Changes::Parent; parentId = resolvedComposerState.parentId; - parentSurfaceControlForChild = nullptr; + mNotDefCmpState.parentSurfaceControlForChild = nullptr; // Once a layer has be reparented, it cannot be placed at the root. It sounds odd // but thats the existing logic and until we make this behavior more explicit, we need // to maintain this logic. @@ -288,7 +291,7 @@ void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerSta changes |= RequestedLayerState::Changes::RelativeParent; relativeParentId = resolvedComposerState.relativeParentId; isRelativeOf = true; - relativeLayerSurfaceControl = nullptr; + mNotDefCmpState.relativeLayerSurfaceControl = nullptr; } if ((clientState.what & layer_state_t::eLayerChanged || (clientState.what & layer_state_t::eReparent && parentId == UNASSIGNED_LAYER_ID)) && @@ -304,7 +307,7 @@ void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerSta } if (clientState.what & layer_state_t::eInputInfoChanged) { touchCropId = resolvedComposerState.touchCropId; - windowInfoHandle->editInfo()->touchableRegionCropHandle.clear(); + editWindowInfo()->touchableRegionCropHandle.clear(); } if (clientState.what & layer_state_t::eStretchChanged) { stretchEffect.sanitize(); @@ -554,12 +557,9 @@ bool RequestedLayerState::hasValidRelativeParent() const { } bool RequestedLayerState::hasInputInfo() const { - if (!windowInfoHandle) { - return false; - } - const auto windowInfo = windowInfoHandle->getInfo(); - return windowInfo->token != nullptr || - windowInfo->inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL); + const auto& windowInfo = getWindowInfo(); + return windowInfo.token != nullptr || + windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL); } bool RequestedLayerState::needsInputInfo() const { @@ -571,13 +571,9 @@ bool RequestedLayerState::needsInputInfo() const { return true; } - if (!windowInfoHandle) { - return false; - } - - const auto windowInfo = windowInfoHandle->getInfo(); - return windowInfo->token != nullptr || - windowInfo->inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL); + const auto& windowInfo = getWindowInfo(); + return windowInfo.token != nullptr || + windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL); } bool RequestedLayerState::hasBufferOrSidebandStream() const { diff --git a/services/surfaceflinger/HdrLayerInfoReporter.h b/services/surfaceflinger/HdrLayerInfoReporter.h index 614f33fbce..758b111e41 100644 --- a/services/surfaceflinger/HdrLayerInfoReporter.h +++ b/services/surfaceflinger/HdrLayerInfoReporter.h @@ -19,11 +19,11 @@ #include <android-base/thread_annotations.h> #include <android/gui/IHdrLayerInfoListener.h> #include <binder/IBinder.h> +#include <ui/RingBuffer.h> #include <utils/Timers.h> #include <unordered_map> -#include "Utils/RingBuffer.h" #include "WpHash.h" namespace android { @@ -102,7 +102,7 @@ private: EventHistoryEntry(const HdrLayerInfo& info) : info(info) { timestamp = systemTime(); } }; - utils::RingBuffer<EventHistoryEntry, 32> mHdrInfoHistory; + ui::RingBuffer<EventHistoryEntry, 32> mHdrInfoHistory; }; } // namespace android
\ No newline at end of file diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6af0f59d51..081bb22246 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -288,7 +288,7 @@ public: bool leaveState); inline bool hasTrustedPresentationListener() { - return mTrustedPresentationListener.callbackInterface != nullptr; + return mTrustedPresentationListener.getCallback() != nullptr; } // Sets the masked bits. diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 44cd3194bc..84b1a73e0b 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -447,7 +447,7 @@ void LayerProtoHelper::writeSnapshotToProto(perfetto::protos::LayerProto* layerI } layerInfo->set_type("Layer"); - LayerProtoHelper::writeToProto(requestedState.transparentRegion, + LayerProtoHelper::writeToProto(requestedState.getTransparentRegion(), [&]() { return layerInfo->mutable_transparent_region(); }); layerInfo->set_layer_stack(snapshot.outputFilter.layerStack.id); diff --git a/services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp b/services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp index cd7210c627..788448d079 100644 --- a/services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp +++ b/services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp @@ -515,7 +515,7 @@ void PowerAdvisor::setRequiresRenderEngine(DisplayId displayId, bool requiresRen } void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) { - mExpectedPresentTimes.append(expectedPresentTime); + mExpectedPresentTimes.next() = expectedPresentTime; } void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) { @@ -532,7 +532,7 @@ void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earli } void PowerAdvisor::setCommitStart(TimePoint commitStartTime) { - mCommitStartTimes.append(commitStartTime); + mCommitStartTimes.next() = commitStartTime; } void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) { @@ -579,7 +579,7 @@ std::optional<hal::WorkDuration> PowerAdvisor::estimateWorkDuration() { } // Tracks when we finish presenting to hwc - TimePoint estimatedHwcEndTime = mCommitStartTimes[0]; + TimePoint estimatedHwcEndTime = mCommitStartTimes.back(); // How long we spent this frame not doing anything, waiting for fences or vsync Duration idleDuration = 0ns; @@ -643,13 +643,13 @@ std::optional<hal::WorkDuration> PowerAdvisor::estimateWorkDuration() { // Also add the frame delay duration since the target did not move while we were delayed Duration totalDuration = mFrameDelayDuration + std::max(estimatedHwcEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) - - mCommitStartTimes[0]; + mCommitStartTimes.back(); Duration totalDurationWithoutGpu = - mFrameDelayDuration + estimatedHwcEndTime - mCommitStartTimes[0]; + mFrameDelayDuration + estimatedHwcEndTime - mCommitStartTimes.back(); // We finish SurfaceFlinger when post-composition finishes, so add that in here Duration flingerDuration = - estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0]; + estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes.back(); Duration estimatedGpuDuration = firstGpuTimeline.has_value() ? estimatedGpuEndTime.value_or(TimePoint{0ns}) - firstGpuTimeline->startTime : Duration::fromNs(0); @@ -661,7 +661,7 @@ std::optional<hal::WorkDuration> PowerAdvisor::estimateWorkDuration() { hal::WorkDuration duration{ .timeStampNanos = TimePoint::now().ns(), .durationNanos = combinedDuration.ns(), - .workPeriodStartTimestampNanos = mCommitStartTimes[0].ns(), + .workPeriodStartTimestampNanos = mCommitStartTimes.back().ns(), .cpuDurationNanos = supportsGpuReporting() ? cpuDuration.ns() : 0, .gpuDurationNanos = supportsGpuReporting() ? estimatedGpuDuration.ns() : 0, }; diff --git a/services/surfaceflinger/PowerAdvisor/PowerAdvisor.h b/services/surfaceflinger/PowerAdvisor/PowerAdvisor.h index 540a9df2ca..b97160a3e5 100644 --- a/services/surfaceflinger/PowerAdvisor/PowerAdvisor.h +++ b/services/surfaceflinger/PowerAdvisor/PowerAdvisor.h @@ -23,6 +23,7 @@ #include <ui/DisplayId.h> #include <ui/FenceTime.h> +#include <ui/RingBuffer.h> #include <utils/Mutex.h> // FMQ library in IPower does questionable conversions @@ -247,27 +248,6 @@ private: std::optional<GpuTimeline> estimateGpuTiming(std::optional<TimePoint> previousEndTime); }; - template <class T, size_t N> - class RingBuffer { - std::array<T, N> elements = {}; - size_t mIndex = 0; - size_t numElements = 0; - - public: - void append(T item) { - mIndex = (mIndex + 1) % N; - numElements = std::min(N, numElements + 1); - elements[mIndex] = item; - } - bool isFull() const { return numElements == N; } - // Allows access like [0] == current, [-1] = previous, etc.. - T& operator[](int offset) { - size_t positiveOffset = - static_cast<size_t>((offset % static_cast<int>(N)) + static_cast<int>(N)); - return elements[(mIndex + positiveOffset) % N]; - } - }; - // Filter and sort the display ids by a given property std::vector<DisplayId> getOrderedDisplayIds( std::optional<TimePoint> DisplayTimingData::*sortBy); @@ -287,9 +267,9 @@ private: // Last frame's post-composition duration Duration mLastPostcompDuration{0ns}; // Buffer of recent commit start times - RingBuffer<TimePoint, 2> mCommitStartTimes; + ui::RingBuffer<TimePoint, 2> mCommitStartTimes; // Buffer of recent expected present times - RingBuffer<TimePoint, 2> mExpectedPresentTimes; + ui::RingBuffer<TimePoint, 2> mExpectedPresentTimes; // Most recent present fence time, provided by SF after composition engine finishes presenting TimePoint mLastPresentFenceTime; // Most recent composition engine present end time, returned with the present fence from SF diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 4da76f6ecc..e587178ec2 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -986,7 +986,7 @@ std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked( if (const auto pacesetterOpt = pacesetterDisplayLocked()) { const Display& pacesetter = *pacesetterOpt; - if (!FlagManager::getInstance().connected_display() || params.toggleIdleTimer) { + if (params.toggleIdleTimer) { pacesetter.selectorPtr->setIdleTimerCallbacks( {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); }, .onExpired = [this] { idleTimerCallback(TimerState::Expired); }}, @@ -1018,7 +1018,7 @@ void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedu } void Scheduler::demotePacesetterDisplay(PromotionParams params) { - if (!FlagManager::getInstance().connected_display() || params.toggleIdleTimer) { + if (params.toggleIdleTimer) { // No need to lock for reads on kMainThreadContext. if (const auto pacesetterPtr = FTL_FAKE_GUARD(mDisplayLock, pacesetterSelectorPtrLocked())) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 3fdddac52a..81389e7362 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -386,7 +386,7 @@ private: // a deadlock where the main thread joins with the timer thread as the timer thread waits to // lock a mutex held by the main thread. struct PromotionParams { - // Whether to stop and start the idle timer. Ignored unless connected_display flag is set. + // Whether to stop and start the idle timer. bool toggleIdleTimer; }; diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp index b9c79df9b7..bb04d12d7c 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp @@ -208,7 +208,8 @@ bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { auto it = mRateMap.find(idealPeriod()); // Calculated slope over the period of time can become outdated as the new timestamps are // stored. Using idealPeriod instead provides a rate which is valid at all the times. - auto const currentPeriod = FlagManager::getInstance().vsync_predictor_recovery() + auto const currentPeriod = + mDisplayModePtr->getVrrConfig() && FlagManager::getInstance().vsync_predictor_recovery() ? idealPeriod() : it->second.slope; diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h index 813d4dedff..ff461d2d85 100644 --- a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h +++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h @@ -24,6 +24,7 @@ #include <ui/DisplayId.h> #include <ui/Fence.h> #include <ui/FenceTime.h> +#include <ui/RingBuffer.h> #include <scheduler/Features.h> #include <scheduler/FrameTime.h> @@ -34,7 +35,6 @@ // TODO(b/185536303): Pull to FTL. #include "../../../TracedOrdinal.h" #include "../../../Utils/Dumper.h" -#include "../../../Utils/RingBuffer.h" namespace android::scheduler { @@ -108,7 +108,7 @@ protected: std::pair<bool /* wouldBackpressure */, PresentFence> expectedSignaledPresentFence( Period vsyncPeriod, Period minFramePeriod) const; std::array<PresentFence, 2> mPresentFencesLegacy; - utils::RingBuffer<PresentFence, 5> mPresentFences; + ui::RingBuffer<PresentFence, 5> mPresentFences; FrameTime mLastSignaledFrameTime; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 35cb63ea89..9d759dfe82 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -384,6 +384,7 @@ bool SurfaceFlinger::useHwcForRgbToYuv; bool SurfaceFlinger::hasSyncFramework; int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; int64_t SurfaceFlinger::minAcquiredBuffers = 1; +std::optional<int64_t> SurfaceFlinger::maxAcquiredBuffersOpt; uint32_t SurfaceFlinger::maxGraphicsWidth; uint32_t SurfaceFlinger::maxGraphicsHeight; bool SurfaceFlinger::useContextPriority; @@ -452,6 +453,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2); minAcquiredBuffers = SurfaceFlingerProperties::min_acquired_buffers().value_or(minAcquiredBuffers); + maxAcquiredBuffersOpt = SurfaceFlingerProperties::max_acquired_buffers(); maxGraphicsWidth = std::max(max_graphics_width(0), 0); maxGraphicsHeight = std::max(max_graphics_height(0), 0); @@ -576,9 +578,10 @@ void SurfaceFlinger::run() { mScheduler->run(); } -sp<IBinder> SurfaceFlinger::createVirtualDisplay(const std::string& displayName, bool isSecure, - const std::string& uniqueId, - float requestedRefreshRate) { +sp<IBinder> SurfaceFlinger::createVirtualDisplay( + const std::string& displayName, bool isSecure, + gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy, const std::string& uniqueId, + float requestedRefreshRate) { // SurfaceComposerAIDL checks for some permissions, but adding an additional check here. // This is to ensure that only root, system, and graphics can request to create a secure // display. Secure displays can show secure content so we add an additional restriction on it. @@ -611,6 +614,7 @@ sp<IBinder> SurfaceFlinger::createVirtualDisplay(const std::string& displayName, // Set display as protected when marked as secure to ensure no behavior change // TODO (b/314820005): separate as a different arg when creating the display. state.isProtected = isSecure; + state.optimizationPolicy = optimizationPolicy; state.displayName = displayName; state.uniqueId = uniqueId; state.requestedRefreshRate = Fps::fromValue(requestedRefreshRate); @@ -1009,9 +1013,8 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { mPowerAdvisor->init(); if (base::GetBoolProperty("service.sf.prime_shader_cache"s, true)) { - if (setSchedFifo(false) != NO_ERROR) { - ALOGW("Can't set SCHED_OTHER for primeCache"); - } + constexpr const char* kWhence = "primeCache"; + setSchedFifo(false, kWhence); mRenderEnginePrimeCacheFuture.callOnce([this] { renderengine::PrimeCacheConfig config; @@ -1047,9 +1050,7 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { return getRenderEngine().primeCache(config); }); - if (setSchedFifo(true) != NO_ERROR) { - ALOGW("Can't set SCHED_FIFO after primeCache"); - } + setSchedFifo(true, kWhence); } // Avoid blocking the main thread on `init` to set properties. @@ -2286,8 +2287,7 @@ void SurfaceFlinger::scheduleSample() { void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp, std::optional<hal::VsyncPeriodNanos> vsyncPeriod) { - if (FlagManager::getInstance().connected_display() && timestamp < 0 && - vsyncPeriod.has_value()) { + if (timestamp < 0 && vsyncPeriod.has_value()) { if (mIsHdcpViaNegVsync && vsyncPeriod.value() == ~1) { const int32_t value = static_cast<int32_t>(-timestamp); // one byte is good enough to encode android.hardware.drm.HdcpLevel @@ -2339,9 +2339,19 @@ void SurfaceFlinger::onComposerHalHotplugEvent(hal::HWDisplayId hwcDisplayId, return; } - if (event == DisplayHotplugEvent::ERROR_LINK_UNSTABLE && - !FlagManager::getInstance().display_config_error_hal()) { - return; + if (event == DisplayHotplugEvent::ERROR_LINK_UNSTABLE) { + if (!FlagManager::getInstance().display_config_error_hal()) { + return; + } + { + std::lock_guard<std::mutex> lock(mHotplugMutex); + mPendingHotplugEvents.push_back( + HotplugEvent{hwcDisplayId, HWComposer::HotplugEvent::LinkUnstable}); + } + if (mScheduler) { + mScheduler->scheduleConfigure(); + } + // do not return to also report the error. } // TODO(b/311403559): use enum type instead of int @@ -3554,9 +3564,8 @@ std::pair<DisplayModes, DisplayModePtr> SurfaceFlinger::loadDisplayModes( std::vector<HWComposer::HWCDisplayMode> hwcModes; std::optional<hal::HWConfigId> activeModeHwcIdOpt; - const bool isExternalDisplay = FlagManager::getInstance().connected_display() && - getHwComposer().getDisplayConnectionType(displayId) == - ui::DisplayConnectionType::External; + const bool isExternalDisplay = getHwComposer().getDisplayConnectionType(displayId) == + ui::DisplayConnectionType::External; int attempt = 0; constexpr int kMaxAttempts = 3; @@ -3719,11 +3728,12 @@ bool SurfaceFlinger::configureLocked() { const auto displayId = info->id; const ftl::Concat displayString("display ", displayId.value, "(HAL ID ", hwcDisplayId, ')'); - - if (event == HWComposer::HotplugEvent::Connected) { + // TODO: b/393126541 - replace if with switch as all cases are handled. + if (event == HWComposer::HotplugEvent::Connected || + event == HWComposer::HotplugEvent::LinkUnstable) { const auto activeModeIdOpt = processHotplugConnect(displayId, hwcDisplayId, std::move(*info), - displayString.c_str()); + displayString.c_str(), event); if (!activeModeIdOpt) { mScheduler->dispatchHotplugError( static_cast<int32_t>(DisplayHotplugEvent::ERROR_UNKNOWN)); @@ -3749,7 +3759,7 @@ bool SurfaceFlinger::configureLocked() { LOG_ALWAYS_FATAL_IF(!snapshotOpt); mDisplayModeController.registerDisplay(*snapshotOpt, *activeModeIdOpt, config); - } else { + } else { // event == HWComposer::HotplugEvent::Disconnected // Unregister before destroying the DisplaySnapshot below. mDisplayModeController.unregisterDisplay(displayId); @@ -3764,7 +3774,8 @@ bool SurfaceFlinger::configureLocked() { std::optional<DisplayModeId> SurfaceFlinger::processHotplugConnect(PhysicalDisplayId displayId, hal::HWDisplayId hwcDisplayId, DisplayIdentificationInfo&& info, - const char* displayString) { + const char* displayString, + HWComposer::HotplugEvent event) { auto [displayModes, activeMode] = loadDisplayModes(displayId); if (!activeMode) { ALOGE("Failed to hotplug %s", displayString); @@ -3799,6 +3810,9 @@ std::optional<DisplayModeId> SurfaceFlinger::processHotplugConnect(PhysicalDispl state.physical->port = port; ALOGI("Reconnecting %s", displayString); return activeModeId; + } else if (event == HWComposer::HotplugEvent::LinkUnstable) { + ALOGE("Failed to reconnect unknown %s", displayString); + return std::nullopt; } const sp<IBinder> token = sp<BBinder>::make(); @@ -3927,6 +3941,7 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( display->setProjection(state.orientation, state.layerStackSpaceRect, state.orientedDisplaySpaceRect); display->setDisplayName(state.displayName); + display->setOptimizationPolicy(state.optimizationPolicy); display->setFlags(state.flags); return display; @@ -4051,8 +4066,7 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, // For an external display, loadDisplayModes already attempted to select the same mode // as DM, but SF still needs to be updated to match. // TODO (b/318534874): Let DM decide the initial mode. - if (const auto& physical = state.physical; - mScheduler && physical && FlagManager::getInstance().connected_display()) { + if (const auto& physical = state.physical; mScheduler && physical) { const bool isInternalDisplay = mPhysicalDisplays.get(physical->id) .transform(&PhysicalDisplay::isInternal) .value_or(false); @@ -4320,20 +4334,19 @@ void SurfaceFlinger::updateInputFlinger(VsyncId vsyncId, TimePoint frameTime) { std::move(displayInfos), ftl::to_underlying(vsyncId), frameTime.ns()}, - std::move( - inputWindowCommands.windowInfosReportedListeners), + std::move(inputWindowCommands.releaseListeners()), /* forceImmediateCall= */ visibleWindowsChanged || - !inputWindowCommands.focusRequests.empty()); + !inputWindowCommands.getFocusRequests().empty()); } else { // If there are listeners but no changes to input windows, call the listeners // immediately. - for (const auto& listener : inputWindowCommands.windowInfosReportedListeners) { + for (const auto& listener : inputWindowCommands.getListeners()) { if (IInterface::asBinder(listener)->isBinderAlive()) { listener->onWindowInfosReported(); } } } - for (const auto& focusRequest : inputWindowCommands.focusRequests) { + for (const auto& focusRequest : inputWindowCommands.getFocusRequests()) { inputFlinger->setFocusedWindow(focusRequest); } }}); @@ -5060,16 +5073,16 @@ status_t SurfaceFlinger::setTransactionState( mBufferCountTracker.increment(resolvedState.layerId); } if (resolvedState.state.what & layer_state_t::eReparent) { - resolvedState.parentId = - getLayerIdFromSurfaceControl(resolvedState.state.parentSurfaceControlForChild); + resolvedState.parentId = getLayerIdFromSurfaceControl( + resolvedState.state.getParentSurfaceControlForChild()); } if (resolvedState.state.what & layer_state_t::eRelativeLayerChanged) { - resolvedState.relativeParentId = - getLayerIdFromSurfaceControl(resolvedState.state.relativeLayerSurfaceControl); + resolvedState.relativeParentId = getLayerIdFromSurfaceControl( + resolvedState.state.getRelativeLayerSurfaceControl()); } if (resolvedState.state.what & layer_state_t::eInputInfoChanged) { wp<IBinder>& touchableRegionCropHandle = - resolvedState.state.windowInfoHandle->editInfo()->touchableRegionCropHandle; + resolvedState.state.editWindowInfo()->touchableRegionCropHandle; resolvedState.touchCropId = LayerHandle::getLayerId(touchableRegionCropHandle.promote()); } @@ -5695,16 +5708,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } if (displayId == mActiveDisplayId) { - // TODO(b/281692563): Merge the syscalls. For now, keep uclamp in a separate syscall and - // set it before SCHED_FIFO due to b/190237315. - if (setSchedAttr(true) != NO_ERROR) { - ALOGW("Failed to set uclamp.min after powering on active display: %s", - strerror(errno)); - } - if (setSchedFifo(true) != NO_ERROR) { - ALOGW("Failed to set SCHED_FIFO after powering on active display: %s", - strerror(errno)); - } + // TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall + // and set it before SCHED_FIFO due to b/190237315. + constexpr const char* kWhence = "setPowerMode(ON)"; + setSchedAttr(true, kWhence); + setSchedFifo(true, kWhence); } getHwComposer().setPowerMode(displayId, mode); @@ -5731,14 +5739,9 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: if (const auto display = getActivatableDisplay()) { onActiveDisplayChangedLocked(activeDisplay.get(), *display); } else { - if (setSchedFifo(false) != NO_ERROR) { - ALOGW("Failed to set SCHED_OTHER after powering off active display: %s", - strerror(errno)); - } - if (setSchedAttr(false) != NO_ERROR) { - ALOGW("Failed set uclamp.min after powering off active display: %s", - strerror(errno)); - } + constexpr const char* kWhence = "setPowerMode(OFF)"; + setSchedFifo(false, kWhence); + setSchedAttr(false, kWhence); if (currentModeNotDozeSuspend) { if (!FlagManager::getInstance().multithreaded_present()) { @@ -7201,7 +7204,7 @@ static status_t validateScreenshotPermissions(const CaptureArgs& captureArgs) { return PERMISSION_DENIED; } -status_t SurfaceFlinger::setSchedFifo(bool enabled) { +void SurfaceFlinger::setSchedFifo(bool enabled, const char* whence) { static constexpr int kFifoPriority = 2; static constexpr int kOtherPriority = 0; @@ -7216,19 +7219,19 @@ status_t SurfaceFlinger::setSchedFifo(bool enabled) { } if (sched_setscheduler(0, sched_policy, ¶m) != 0) { - return -errno; + const char* kPolicy[] = {"SCHED_OTHER", "SCHED_FIFO"}; + ALOGW("%s: Failed to set %s: %s", whence, kPolicy[sched_policy == SCHED_FIFO], + strerror(errno)); } - - return NO_ERROR; } -status_t SurfaceFlinger::setSchedAttr(bool enabled) { +void SurfaceFlinger::setSchedAttr(bool enabled, const char* whence) { static const unsigned int kUclampMin = base::GetUintProperty<unsigned int>("ro.surface_flinger.uclamp.min"s, 0U); if (!kUclampMin) { // uclamp.min set to 0 (default), skip setting - return NO_ERROR; + return; } sched_attr attr = {}; @@ -7239,10 +7242,9 @@ status_t SurfaceFlinger::setSchedAttr(bool enabled) { attr.sched_util_max = 1024; if (syscall(__NR_sched_setattr, 0, &attr, 0)) { - return -errno; + const char* kAction[] = {"disable", "enable"}; + ALOGW("%s: Failed to %s uclamp.min: %s", whence, kAction[enabled], strerror(errno)); } - - return NO_ERROR; } namespace { @@ -8240,11 +8242,13 @@ int SurfaceFlinger::getGpuContextPriority() { int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate, std::chrono::nanoseconds presentLatency) { - auto pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs(); + int64_t pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs(); if (presentLatency.count() % refreshRate.getPeriodNsecs()) { pipelineDepth++; } - return std::max(minAcquiredBuffers, static_cast<int64_t>(pipelineDepth - 1)); + const int64_t maxAcquiredBuffers = + std::min(pipelineDepth - 1, maxAcquiredBuffersOpt.value_or(pipelineDepth - 1)); + return std::max(minAcquiredBuffers, maxAcquiredBuffers); } status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const { @@ -8362,10 +8366,6 @@ status_t SurfaceFlinger::getStalledTransactionInfo( void SurfaceFlinger::updateHdcpLevels(hal::HWDisplayId hwcDisplayId, int32_t connectedLevel, int32_t maxLevel) { - if (!FlagManager::getInstance().connected_display()) { - return; - } - Mutex::Autolock lock(mStateLock); const auto idOpt = getHwComposer().toPhysicalDisplayId(hwcDisplayId); @@ -8749,16 +8749,16 @@ binder::Status SurfaceComposerAIDL::createConnection(sp<gui::ISurfaceComposerCli } } -binder::Status SurfaceComposerAIDL::createVirtualDisplay(const std::string& displayName, - bool isSecure, const std::string& uniqueId, - float requestedRefreshRate, - sp<IBinder>* outDisplay) { +binder::Status SurfaceComposerAIDL::createVirtualDisplay( + const std::string& displayName, bool isSecure, + gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy, const std::string& uniqueId, + float requestedRefreshRate, sp<IBinder>* outDisplay) { status_t status = checkAccessPermission(); if (status != OK) { return binderStatusFromStatusT(status); } - *outDisplay = - mFlinger->createVirtualDisplay(displayName, isSecure, uniqueId, requestedRefreshRate); + *outDisplay = mFlinger->createVirtualDisplay(displayName, isSecure, optimizationPolicy, + uniqueId, requestedRefreshRate); return binder::Status::ok(); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 3f454ba1b8..39e237b1f9 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -211,11 +211,9 @@ public: SurfaceFlinger(surfaceflinger::Factory&, SkipInitializationTag) ANDROID_API; explicit SurfaceFlinger(surfaceflinger::Factory&) ANDROID_API; - // set main thread scheduling policy - static status_t setSchedFifo(bool enabled) ANDROID_API; - - // set main thread scheduling attributes - static status_t setSchedAttr(bool enabled); + // Set scheduling policy and attributes of main thread. + static void setSchedFifo(bool enabled, const char* whence); + static void setSchedAttr(bool enabled, const char* whence); static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; } @@ -240,6 +238,11 @@ public: // ISurfaceComposer.getMaxAcquiredBufferCount(). static int64_t minAcquiredBuffers; + // Controls the maximum acquired buffers SurfaceFlinger will suggest via + // ISurfaceComposer.getMaxAcquiredBufferCount(). + // Value is set through ro.surface_flinger.max_acquired_buffers. + static std::optional<int64_t> maxAcquiredBuffersOpt; + // Controls the maximum width and height in pixels that the graphics pipeline can support for // GPU fallback composition. For example, 8k devices with 4k GPUs, or 4k devices with 2k GPUs. static uint32_t maxGraphicsWidth; @@ -531,6 +534,7 @@ private: // ISurfaceComposer implementation: sp<IBinder> createVirtualDisplay(const std::string& displayName, bool isSecure, + gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy, const std::string& uniqueId, float requestedRefreshRate = 0.0f); status_t destroyVirtualDisplay(const sp<IBinder>& displayToken); @@ -1067,7 +1071,8 @@ private: // Returns the active mode ID, or nullopt on hotplug failure. std::optional<DisplayModeId> processHotplugConnect(PhysicalDisplayId, hal::HWDisplayId, DisplayIdentificationInfo&&, - const char* displayString) + const char* displayString, + HWComposer::HotplugEvent event) REQUIRES(mStateLock, kMainThreadContext); void processHotplugDisconnect(PhysicalDisplayId, const char* displayString) REQUIRES(mStateLock, kMainThreadContext); @@ -1564,9 +1569,11 @@ public: const sp<IBinder>& layerHandle, sp<gui::IDisplayEventConnection>* outConnection) override; binder::Status createConnection(sp<gui::ISurfaceComposerClient>* outClient) override; - binder::Status createVirtualDisplay(const std::string& displayName, bool isSecure, - const std::string& uniqueId, float requestedRefreshRate, - sp<IBinder>* outDisplay) override; + binder::Status createVirtualDisplay( + const std::string& displayName, bool isSecure, + gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy, + const std::string& uniqueId, float requestedRefreshRate, + sp<IBinder>* outDisplay) override; binder::Status destroyVirtualDisplay(const sp<IBinder>& displayToken) override; binder::Status getPhysicalDisplayIds(std::vector<int64_t>* outDisplayIds) override; binder::Status getPhysicalDisplayToken(int64_t displayId, sp<IBinder>* outDisplay) override; diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index 2676ca6777..3297c16113 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -139,7 +139,8 @@ perfetto::protos::LayerState TransactionProtoParser::toProto( colorProto->set_b(layer.color.b); } if (layer.what & layer_state_t::eTransparentRegionChanged) { - LayerProtoHelper::writeToProto(layer.transparentRegion, proto.mutable_transparent_region()); + LayerProtoHelper::writeToProto(layer.getTransparentRegion(), + proto.mutable_transparent_region()); } if (layer.what & layer_state_t::eBufferTransformChanged) { proto.set_transform(layer.bufferTransform); @@ -191,33 +192,30 @@ perfetto::protos::LayerState TransactionProtoParser::toProto( } if (layer.what & layer_state_t::eInputInfoChanged) { - if (layer.windowInfoHandle) { - const gui::WindowInfo* inputInfo = layer.windowInfoHandle->getInfo(); - perfetto::protos::LayerState_WindowInfo* windowInfoProto = - proto.mutable_window_info_handle(); - windowInfoProto->set_layout_params_flags(inputInfo->layoutParamsFlags.get()); - windowInfoProto->set_layout_params_type( - static_cast<int32_t>(inputInfo->layoutParamsType)); - windowInfoProto->set_input_config(inputInfo->inputConfig.get()); - LayerProtoHelper::writeToProto(inputInfo->touchableRegion, - windowInfoProto->mutable_touchable_region()); - windowInfoProto->set_surface_inset(inputInfo->surfaceInset); - windowInfoProto->set_focusable( - !inputInfo->inputConfig.test(gui::WindowInfo::InputConfig::NOT_FOCUSABLE)); - windowInfoProto->set_has_wallpaper(inputInfo->inputConfig.test( - gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)); - windowInfoProto->set_global_scale_factor(inputInfo->globalScaleFactor); - perfetto::protos::Transform* transformProto = windowInfoProto->mutable_transform(); - transformProto->set_dsdx(inputInfo->transform.dsdx()); - transformProto->set_dtdx(inputInfo->transform.dtdx()); - transformProto->set_dtdy(inputInfo->transform.dtdy()); - transformProto->set_dsdy(inputInfo->transform.dsdy()); - transformProto->set_tx(inputInfo->transform.tx()); - transformProto->set_ty(inputInfo->transform.ty()); - windowInfoProto->set_replace_touchable_region_with_crop( - inputInfo->replaceTouchableRegionWithCrop); - windowInfoProto->set_crop_layer_id(resolvedComposerState.touchCropId); - } + const gui::WindowInfo* inputInfo = &layer.getWindowInfo(); + perfetto::protos::LayerState_WindowInfo* windowInfoProto = + proto.mutable_window_info_handle(); + windowInfoProto->set_layout_params_flags(inputInfo->layoutParamsFlags.get()); + windowInfoProto->set_layout_params_type(static_cast<int32_t>(inputInfo->layoutParamsType)); + windowInfoProto->set_input_config(inputInfo->inputConfig.get()); + LayerProtoHelper::writeToProto(inputInfo->touchableRegion, + windowInfoProto->mutable_touchable_region()); + windowInfoProto->set_surface_inset(inputInfo->surfaceInset); + windowInfoProto->set_focusable( + !inputInfo->inputConfig.test(gui::WindowInfo::InputConfig::NOT_FOCUSABLE)); + windowInfoProto->set_has_wallpaper(inputInfo->inputConfig.test( + gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)); + windowInfoProto->set_global_scale_factor(inputInfo->globalScaleFactor); + perfetto::protos::Transform* transformProto = windowInfoProto->mutable_transform(); + transformProto->set_dsdx(inputInfo->transform.dsdx()); + transformProto->set_dtdx(inputInfo->transform.dtdx()); + transformProto->set_dtdy(inputInfo->transform.dtdy()); + transformProto->set_dsdy(inputInfo->transform.dsdy()); + transformProto->set_tx(inputInfo->transform.tx()); + transformProto->set_ty(inputInfo->transform.ty()); + windowInfoProto->set_replace_touchable_region_with_crop( + inputInfo->replaceTouchableRegionWithCrop); + windowInfoProto->set_crop_layer_id(resolvedComposerState.touchCropId); } if (layer.what & layer_state_t::eBackgroundColorChanged) { proto.set_bg_color_alpha(layer.bgColor.a); @@ -410,7 +408,9 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto layer.color.b = colorProto.b(); } if (proto.what() & layer_state_t::eTransparentRegionChanged) { - LayerProtoHelper::readFromProto(proto.transparent_region(), layer.transparentRegion); + Region transparentRegion; + LayerProtoHelper::readFromProto(proto.transparent_region(), transparentRegion); + layer.updateTransparentRegion(transparentRegion); } if (proto.what() & layer_state_t::eBufferTransformChanged) { layer.bufferTransform = proto.transform(); @@ -486,7 +486,7 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto windowInfoProto.replace_touchable_region_with_crop(); resolvedComposerState.touchCropId = windowInfoProto.crop_layer_id(); - layer.windowInfoHandle = sp<gui::WindowInfoHandle>::make(inputInfo); + *layer.editWindowInfo() = inputInfo; } if (proto.what() & layer_state_t::eBackgroundColorChanged) { layer.bgColor.a = proto.bg_color_alpha(); diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp index 5cf42449c0..84d837c37a 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp @@ -102,11 +102,10 @@ bool LayerTraceGenerator::generate(const perfetto::protos::TransactionTraceFile& QueuedTransactionState transaction = parser.fromProto(entry.transactions(j)); for (auto& resolvedComposerState : transaction.states) { if (resolvedComposerState.state.what & layer_state_t::eInputInfoChanged) { - if (!resolvedComposerState.state.windowInfoHandle->getInfo()->inputConfig.test( + if (!resolvedComposerState.state.getWindowInfo().inputConfig.test( gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) { // create a fake token since the FE expects a valid token - resolvedComposerState.state.windowInfoHandle->editInfo()->token = - sp<BBinder>::make(); + resolvedComposerState.state.editWindowInfo()->token = sp<BBinder>::make(); } } } diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp index abde524214..8d1b51ba73 100644 --- a/services/surfaceflinger/common/FlagManager.cpp +++ b/services/surfaceflinger/common/FlagManager.cpp @@ -139,7 +139,6 @@ void FlagManager::dump(std::string& result) const { DUMP_ACONFIG_FLAG(begone_bright_hlg); DUMP_ACONFIG_FLAG(cache_when_source_crop_layer_only_moved); DUMP_ACONFIG_FLAG(commit_not_composited); - DUMP_ACONFIG_FLAG(connected_display); DUMP_ACONFIG_FLAG(connected_display_hdr); DUMP_ACONFIG_FLAG(correct_dpi_with_display_size); DUMP_ACONFIG_FLAG(deprecate_frame_tracker); @@ -252,7 +251,6 @@ FLAG_MANAGER_LEGACY_SERVER_FLAG(use_skia_tracing, PROPERTY_SKIA_ATRACE_ENABLED, /// Trunk stable readonly flags /// FLAG_MANAGER_ACONFIG_FLAG(adpf_fmq_sf, "") FLAG_MANAGER_ACONFIG_FLAG(arr_setframerate_gte_enum, "debug.sf.arr_setframerate_gte_enum") -FLAG_MANAGER_ACONFIG_FLAG(connected_display, "") FLAG_MANAGER_ACONFIG_FLAG(enable_small_area_detection, "") FLAG_MANAGER_ACONFIG_FLAG(stable_edid_ids, "debug.sf.stable_edid_ids") FLAG_MANAGER_ACONFIG_FLAG(frame_rate_category_mrr, "debug.sf.frame_rate_category_mrr") diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h index 6295c5b17f..603139e101 100644 --- a/services/surfaceflinger/common/include/common/FlagManager.h +++ b/services/surfaceflinger/common/include/common/FlagManager.h @@ -74,7 +74,6 @@ public: bool begone_bright_hlg() const; bool cache_when_source_crop_layer_only_moved() const; bool commit_not_composited() const; - bool connected_display() const; bool connected_display_hdr() const; bool correct_dpi_with_display_size() const; bool deprecate_frame_tracker() const; diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index 73dfa9fa2f..4afcd00ecb 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -77,7 +77,7 @@ static void startDisplayService() { } } -int main(int, char**) { +int main() { signal(SIGPIPE, SIG_IGN); hardware::configureRpcThreadpool(1 /* maxThreads */, @@ -91,9 +91,7 @@ int main(int, char**) { // Set uclamp.min setting on all threads, maybe an overkill but we want // to cover important threads like RenderEngine. - if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) { - ALOGW("Failed to set uclamp.min during boot: %s", strerror(errno)); - } + SurfaceFlinger::setSchedAttr(true, __func__); // The binder threadpool we start will inherit sched policy and priority // of (this) creating thread. We want the binder thread pool to have @@ -160,14 +158,8 @@ int main(int, char**) { startDisplayService(); // dependency on SF getting registered above - if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) { - ALOGW("Failed to set SCHED_FIFO during boot: %s", strerror(errno)); - } - - // run surface flinger in this thread + SurfaceFlinger::setSchedFifo(true, __func__); flinger->run(); - - return 0; } // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop index 0ad5ac9956..bfafb655d9 100644 --- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop +++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop @@ -483,6 +483,16 @@ prop { prop_name: "ro.surface_flinger.min_acquired_buffers" } +# Defines the maximum acquired buffers SurfaceFlinger will suggest via +# ISurfaceComposer.getMaxAcquiredBufferCount(). +prop { + api_name: "max_acquired_buffers" + type: Long + scope: Public + access: Readonly + prop_name: "ro.surface_flinger.max_acquired_buffers" +} + # When enabled, SurfaceFlinger will attempt to clear the per-layer HAL buffer cache slots for # buffers when they are evicted from the app cache by using additional setLayerBuffer commands. # Ideally, this behavior would always be enabled to reduce graphics memory consumption. However, diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt index 00173009f5..e2ac233f6b 100644 --- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt +++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt @@ -82,6 +82,11 @@ props { prop_name: "ro.surface_flinger.ignore_hdr_camera_layers" } prop { + api_name: "max_acquired_buffers" + type: Long + prop_name: "ro.surface_flinger.max_acquired_buffers" + } + prop { api_name: "max_frame_buffer_acquired_buffers" type: Long prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers" diff --git a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h index 7910e775f6..82390ac6f3 100644 --- a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h +++ b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h @@ -265,9 +265,8 @@ public: transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; transactions.back().states.front().layerId = id; - transactions.back().states.front().state.windowInfoHandle = - sp<gui::WindowInfoHandle>::make(); - auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo(); + auto inputInfo = transactions.back().states.front().state.editWindowInfo(); + *inputInfo = {}; inputInfo->touchableRegion = region; inputInfo->token = sp<BBinder>::make(); mLifecycleManager.applyTransactions(transactions); @@ -280,9 +279,8 @@ public: transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; transactions.back().states.front().layerId = id; - transactions.back().states.front().state.windowInfoHandle = - sp<gui::WindowInfoHandle>::make(); - auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo(); + auto inputInfo = transactions.back().states.front().state.editWindowInfo(); + *inputInfo = {}; if (!inputInfo->token) { inputInfo->token = sp<BBinder>::make(); } @@ -299,9 +297,8 @@ public: transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; transactions.back().states.front().layerId = id; - transactions.back().states.front().state.windowInfoHandle = - sp<gui::WindowInfoHandle>::make(); - auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo(); + auto inputInfo = transactions.back().states.front().state.editWindowInfo(); + *inputInfo = {}; inputInfo->touchableRegion = region; inputInfo->replaceTouchableRegionWithCrop = replaceTouchableRegionWithCrop; transactions.back().states.front().touchCropId = touchCropId; @@ -455,9 +452,8 @@ public: transactions.emplace_back(); transactions.back().states.push_back({}); - transactions.back().states.front().state.what = layer_state_t::eSurfaceDamageRegionChanged; transactions.back().states.front().layerId = id; - transactions.back().states.front().state.surfaceDamageRegion = damageRegion; + transactions.back().states.front().state.updateSurfaceDamageRegion(damageRegion); mLifecycleManager.applyTransactions(transactions); } diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 9ece312850..c342e1eebb 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -468,7 +468,7 @@ struct BaseLayerProperties { layer.externalTexture = buffer; layer.bufferData->acquireFence = Fence::NO_FENCE; layer.dataspace = ui::Dataspace::UNKNOWN; - layer.surfaceDamageRegion = Region(Rect(LayerProperties::HEIGHT, LayerProperties::WIDTH)); + layer.setSurfaceDamageRegion(Region(Rect(LayerProperties::HEIGHT, LayerProperties::WIDTH))); Mock::VerifyAndClear(test->mRenderEngine); } diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 7aad84b545..3ed038b3b1 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -1642,8 +1642,8 @@ TEST_F(LayerSnapshotTest, NonVisibleLayerWithInput) { transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; transactions.back().states.front().layerId = 3; - transactions.back().states.front().state.windowInfoHandle = sp<gui::WindowInfoHandle>::make(); - auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo(); + auto inputInfo = transactions.back().states.front().state.editWindowInfo(); + *inputInfo = {}; inputInfo->token = sp<BBinder>::make(); mLifecycleManager.applyTransactions(transactions); @@ -1671,8 +1671,8 @@ TEST_F(LayerSnapshotTest, NonVisibleLayerWithInputShouldNotBeIncluded) { transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; transactions.back().states.front().layerId = 3; - transactions.back().states.front().state.windowInfoHandle = sp<gui::WindowInfoHandle>::make(); - auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo(); + auto inputInfo = transactions.back().states.front().state.editWindowInfo(); + *inputInfo = {}; inputInfo->token = sp<BBinder>::make(); hideLayer(3); mLifecycleManager.applyTransactions(transactions); @@ -1879,9 +1879,6 @@ TEST_F(LayerSnapshotTest, hideLayerWithNanMatrix) { } TEST_F(LayerSnapshotTest, edgeExtensionPropagatesInHierarchy) { - if (!com::android::graphics::libgui::flags::edge_extension_shader()) { - GTEST_SKIP() << "Skipping test because edge_extension_shader is off"; - } setCrop(1, Rect(0, 0, 20, 20)); setBuffer(1221, std::make_shared<renderengine::mock::FakeExternalTexture>(20 /* width */, @@ -1920,9 +1917,6 @@ TEST_F(LayerSnapshotTest, edgeExtensionPropagatesInHierarchy) { TEST_F(LayerSnapshotTest, leftEdgeExtensionIncreaseBoundSizeWithinCrop) { // The left bound is extended when shifting to the right - if (!com::android::graphics::libgui::flags::edge_extension_shader()) { - GTEST_SKIP() << "Skipping test because edge_extension_shader is off"; - } setCrop(1, Rect(0, 0, 20, 20)); const int texSize = 10; setBuffer(1221, @@ -1942,9 +1936,6 @@ TEST_F(LayerSnapshotTest, leftEdgeExtensionIncreaseBoundSizeWithinCrop) { TEST_F(LayerSnapshotTest, rightEdgeExtensionIncreaseBoundSizeWithinCrop) { // The right bound is extended when shifting to the left - if (!com::android::graphics::libgui::flags::edge_extension_shader()) { - GTEST_SKIP() << "Skipping test because edge_extension_shader is off"; - } const int crop = 20; setCrop(1, Rect(0, 0, crop, crop)); const int texSize = 10; @@ -1965,9 +1956,6 @@ TEST_F(LayerSnapshotTest, rightEdgeExtensionIncreaseBoundSizeWithinCrop) { TEST_F(LayerSnapshotTest, topEdgeExtensionIncreaseBoundSizeWithinCrop) { // The top bound is extended when shifting to the bottom - if (!com::android::graphics::libgui::flags::edge_extension_shader()) { - GTEST_SKIP() << "Skipping test because edge_extension_shader is off"; - } setCrop(1, Rect(0, 0, 20, 20)); const int texSize = 10; setBuffer(1221, @@ -1987,9 +1975,6 @@ TEST_F(LayerSnapshotTest, topEdgeExtensionIncreaseBoundSizeWithinCrop) { TEST_F(LayerSnapshotTest, bottomEdgeExtensionIncreaseBoundSizeWithinCrop) { // The bottom bound is extended when shifting to the top - if (!com::android::graphics::libgui::flags::edge_extension_shader()) { - GTEST_SKIP() << "Skipping test because edge_extension_shader is off"; - } const int crop = 20; setCrop(1, Rect(0, 0, crop, crop)); const int texSize = 10; @@ -2010,9 +1995,6 @@ TEST_F(LayerSnapshotTest, bottomEdgeExtensionIncreaseBoundSizeWithinCrop) { TEST_F(LayerSnapshotTest, multipleEdgeExtensionIncreaseBoundSizeWithinCrop) { // The left bound is extended when shifting to the right - if (!com::android::graphics::libgui::flags::edge_extension_shader()) { - GTEST_SKIP() << "Skipping test because edge_extension_shader is off"; - } const int crop = 20; setCrop(1, Rect(0, 0, crop, crop)); const int texSize = 10; diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 1fc874dad8..cbcfe030e7 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -254,18 +254,43 @@ TEST_F(SchedulerTest, emitModeChangeEvent) { } TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) { - EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 30ms)); - EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(90_Hz, 30ms)); - EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(120_Hz, 30ms)); + struct TestCase { + Fps refreshRate; + std::chrono::nanoseconds presentLatency; + int expectedBufferCount; + }; - EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 40ms)); + const auto verifyTestCases = [&](std::vector<TestCase> tests) { + for (const auto testCase : tests) { + EXPECT_EQ(testCase.expectedBufferCount, + mFlinger.calculateMaxAcquiredBufferCount(testCase.refreshRate, + testCase.presentLatency)); + } + }; - EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); + std::vector<TestCase> testCases{{60_Hz, 30ms, 1}, + {90_Hz, 30ms, 2}, + {120_Hz, 30ms, 3}, + {60_Hz, 40ms, 2}, + {60_Hz, 10ms, 1}}; + verifyTestCases(testCases); const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers(); mFlinger.mutableMinAcquiredBuffers() = 2; - EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); + verifyTestCases({{60_Hz, 10ms, 2}}); mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers; + + const auto savedMaxAcquiredBuffers = mFlinger.mutableMaxAcquiredBuffers(); + mFlinger.mutableMaxAcquiredBuffers() = 2; + testCases = {{60_Hz, 30ms, 1}, + {90_Hz, 30ms, 2}, + {120_Hz, 30ms, 2}, // max buffers allowed is 2 + {60_Hz, 40ms, 2}, + {60_Hz, 10ms, 1}}; + verifyTestCases(testCases); + mFlinger.mutableMaxAcquiredBuffers() = 3; // max buffers allowed is 3 + verifyTestCases({{120_Hz, 30ms, 3}}); + mFlinger.mutableMaxAcquiredBuffers() = savedMaxAcquiredBuffers; } MATCHER(Is120Hz, "") { diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp index aadff760fe..aa5b7863a9 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp @@ -141,7 +141,11 @@ TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForUniqueId) { // -------------------------------------------------------------------- // Invocation - sp<IBinder> displayToken = mFlinger.createVirtualDisplay(kDisplayName, false, kUniqueId); + sp<IBinder> displayToken = + mFlinger.createVirtualDisplay(kDisplayName, false, + gui::ISurfaceComposer::OptimizationPolicy:: + optimizeForPower, + kUniqueId); // -------------------------------------------------------------------- // Postconditions diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp index 62f1a525dc..525a940960 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp @@ -407,8 +407,6 @@ TEST_F(DisplayModeSwitchingTest, changeResolutionSynced) { } TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) { - SET_FLAG_FOR_TEST(flags::connected_display, true); - const auto [innerDisplay, outerDisplay] = injectOuterDisplay(); EXPECT_TRUE(innerDisplay->isPoweredOn()); @@ -473,8 +471,6 @@ TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) { } TEST_F(DisplayModeSwitchingTest, innerAndOuterDisplay) { - SET_FLAG_FOR_TEST(flags::connected_display, true); - const auto [innerDisplay, outerDisplay] = injectOuterDisplay(); EXPECT_TRUE(innerDisplay->isPoweredOn()); @@ -543,8 +539,6 @@ TEST_F(DisplayModeSwitchingTest, powerOffDuringModeSet) { } TEST_F(DisplayModeSwitchingTest, powerOffDuringConcurrentModeSet) { - SET_FLAG_FOR_TEST(flags::connected_display, true); - const auto [innerDisplay, outerDisplay] = injectOuterDisplay(); EXPECT_TRUE(innerDisplay->isPoweredOn()); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp index b0cda0f270..49972b03f6 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp @@ -224,8 +224,6 @@ TEST_F(HotplugTest, ignoresDuplicateDisconnection) { } TEST_F(HotplugTest, rejectsHotplugIfFailedToLoadDisplayModes) { - SET_FLAG_FOR_TEST(flags::connected_display, true); - // Inject a primary display. PrimaryDisplayVariant::injectHwcDisplay(this); @@ -263,8 +261,6 @@ TEST_F(HotplugTest, rejectsHotplugIfFailedToLoadDisplayModes) { } TEST_F(HotplugTest, rejectsHotplugOnActivePortsDuplicate) { - SET_FLAG_FOR_TEST(flags::connected_display, true); - // Inject a primary display. PrimaryDisplayVariant::injectHwcDisplay(this); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 808445037a..bb377bad77 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -399,12 +399,16 @@ public: float requestedRefreshRate = 0.0f) { static const std::string kTestId = "virtual:libsurfaceflinger_unittest:TestableSurfaceFlinger"; - return mFlinger->createVirtualDisplay(displayName, isSecure, kTestId, requestedRefreshRate); + return mFlinger + ->createVirtualDisplay(displayName, isSecure, + gui::ISurfaceComposer::OptimizationPolicy::optimizeForPower, + kTestId, requestedRefreshRate); } auto createVirtualDisplay(const std::string& displayName, bool isSecure, + gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy, const std::string& uniqueId, float requestedRefreshRate = 0.0f) { - return mFlinger->createVirtualDisplay(displayName, isSecure, uniqueId, + return mFlinger->createVirtualDisplay(displayName, isSecure, optimizationPolicy, uniqueId, requestedRefreshRate); } @@ -716,6 +720,7 @@ public: } auto& mutableMinAcquiredBuffers() { return SurfaceFlinger::minAcquiredBuffers; } + auto& mutableMaxAcquiredBuffers() { return SurfaceFlinger::maxAcquiredBuffersOpt; } auto& mutableLayerSnapshotBuilder() NO_THREAD_SAFETY_ANALYSIS { return mFlinger->mLayerSnapshotBuilder; } diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp index a221d5e79b..ccf6a9c7f6 100644 --- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp @@ -444,40 +444,8 @@ TEST_F(VSyncPredictorTest, idealModelPredictionsBeforeRegressionModelIsBuilt) { } } -TEST_F(VSyncPredictorTest, doesNotPredictBeforeTimePointWithHigherIntercept_withPredictorRecovery) { - SET_FLAG_FOR_TEST(flags::vsync_predictor_recovery, true); - std::vector<nsecs_t> const simulatedVsyncs{ - 158929578733000, - 158929306806205, // oldest TS in ringbuffer - 158929650879052, - 158929661969209, - 158929684198847, - 158929695268171, - 158929706370359, - }; - auto const idealPeriod = 11111111; - auto const expectedPeriod = 11079563; - auto const expectedIntercept = 1335662; - - tracker.setDisplayModePtr(displayMode(idealPeriod)); - for (auto const& timestamp : simulatedVsyncs) { - tracker.addVsyncTimestamp(timestamp); - } - - auto [slope, intercept] = tracker.getVSyncPredictionModel(); - EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError)); - EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError)); - - // (timePoint - oldestTS) % expectedPeriod works out to be: 894272 - // (timePoint - oldestTS) / expectedPeriod works out to be: 38.08 - auto const timePoint = 158929728723871; - auto const prediction = tracker.nextAnticipatedVSyncTimeFrom(timePoint); - EXPECT_THAT(prediction, Ge(timePoint)); -} - // See b/145667109, and comment in prod code under test. TEST_F(VSyncPredictorTest, doesNotPredictBeforeTimePointWithHigherIntercept) { - SET_FLAG_FOR_TEST(flags::vsync_predictor_recovery, false); std::vector<nsecs_t> const simulatedVsyncs{ 158929578733000, 158929306806205, // oldest TS in ringbuffer diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp index 4735ae5897..ed03cfc3f5 100644 --- a/services/vibratorservice/Android.bp +++ b/services/vibratorservice/Android.bp @@ -42,14 +42,9 @@ cc_library_shared { shared_libs: [ "libbinder_ndk", - "libhidlbase", "liblog", "libutils", "android.hardware.vibrator-V3-ndk", - "android.hardware.vibrator@1.0", - "android.hardware.vibrator@1.1", - "android.hardware.vibrator@1.2", - "android.hardware.vibrator@1.3", ], cflags: [ diff --git a/services/vibratorservice/VibratorHalController.cpp b/services/vibratorservice/VibratorHalController.cpp index 283a5f0301..302e3e1299 100644 --- a/services/vibratorservice/VibratorHalController.cpp +++ b/services/vibratorservice/VibratorHalController.cpp @@ -18,8 +18,6 @@ #include <aidl/android/hardware/vibrator/IVibrator.h> #include <android/binder_manager.h> -#include <android/hardware/vibrator/1.3/IVibrator.h> -#include <hardware/vibrator.h> #include <utils/Log.h> @@ -31,15 +29,10 @@ using aidl::android::hardware::vibrator::CompositeEffect; using aidl::android::hardware::vibrator::CompositePrimitive; using aidl::android::hardware::vibrator::Effect; using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::IVibrator; using std::chrono::milliseconds; -namespace V1_0 = android::hardware::vibrator::V1_0; -namespace V1_1 = android::hardware::vibrator::V1_1; -namespace V1_2 = android::hardware::vibrator::V1_2; -namespace V1_3 = android::hardware::vibrator::V1_3; -namespace Aidl = aidl::android::hardware::vibrator; - namespace android { namespace vibrator { @@ -53,9 +46,9 @@ std::shared_ptr<HalWrapper> connectHal(std::shared_ptr<CallbackScheduler> schedu return nullptr; } - auto serviceName = std::string(Aidl::IVibrator::descriptor) + "/default"; + auto serviceName = std::string(IVibrator::descriptor) + "/default"; if (AServiceManager_isDeclared(serviceName.c_str())) { - std::shared_ptr<Aidl::IVibrator> hal = Aidl::IVibrator::fromBinder( + std::shared_ptr<IVibrator> hal = IVibrator::fromBinder( ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str()))); if (hal) { ALOGV("Successfully connected to Vibrator HAL AIDL service."); @@ -63,30 +56,9 @@ std::shared_ptr<HalWrapper> connectHal(std::shared_ptr<CallbackScheduler> schedu } } - sp<V1_0::IVibrator> halV1_0 = V1_0::IVibrator::getService(); - if (halV1_0 == nullptr) { - ALOGV("Vibrator HAL service not available."); - gHalExists = false; - return nullptr; - } - - sp<V1_3::IVibrator> halV1_3 = V1_3::IVibrator::castFrom(halV1_0); - if (halV1_3) { - ALOGV("Successfully connected to Vibrator HAL v1.3 service."); - return std::make_shared<HidlHalWrapperV1_3>(std::move(scheduler), halV1_3); - } - sp<V1_2::IVibrator> halV1_2 = V1_2::IVibrator::castFrom(halV1_0); - if (halV1_2) { - ALOGV("Successfully connected to Vibrator HAL v1.2 service."); - return std::make_shared<HidlHalWrapperV1_2>(std::move(scheduler), halV1_2); - } - sp<V1_1::IVibrator> halV1_1 = V1_1::IVibrator::castFrom(halV1_0); - if (halV1_1) { - ALOGV("Successfully connected to Vibrator HAL v1.1 service."); - return std::make_shared<HidlHalWrapperV1_1>(std::move(scheduler), halV1_1); - } - ALOGV("Successfully connected to Vibrator HAL v1.0 service."); - return std::make_shared<HidlHalWrapperV1_0>(std::move(scheduler), halV1_0); + ALOGV("Vibrator HAL service not available."); + gHalExists = false; + return nullptr; } // ------------------------------------------------------------------------------------------------- diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp index 536a6b352b..5d4c17dc76 100644 --- a/services/vibratorservice/VibratorHalWrapper.cpp +++ b/services/vibratorservice/VibratorHalWrapper.cpp @@ -17,7 +17,6 @@ #define LOG_TAG "VibratorHalWrapper" #include <aidl/android/hardware/vibrator/IVibrator.h> -#include <android/hardware/vibrator/1.3/IVibrator.h> #include <hardware/vibrator.h> #include <cmath> @@ -33,32 +32,18 @@ using aidl::android::hardware::vibrator::CompositePwleV2; using aidl::android::hardware::vibrator::Effect; using aidl::android::hardware::vibrator::EffectStrength; using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry; +using aidl::android::hardware::vibrator::IVibrator; using aidl::android::hardware::vibrator::PrimitivePwle; using aidl::android::hardware::vibrator::VendorEffect; using std::chrono::milliseconds; -namespace V1_0 = android::hardware::vibrator::V1_0; -namespace V1_1 = android::hardware::vibrator::V1_1; -namespace V1_2 = android::hardware::vibrator::V1_2; -namespace V1_3 = android::hardware::vibrator::V1_3; -namespace Aidl = aidl::android::hardware::vibrator; - namespace android { namespace vibrator { // ------------------------------------------------------------------------------------------------- -template <class T> -bool isStaticCastValid(Effect effect) { - T castEffect = static_cast<T>(effect); - auto iter = hardware::hidl_enum_range<T>(); - return castEffect >= *iter.begin() && castEffect <= *std::prev(iter.end()); -} - -// ------------------------------------------------------------------------------------------------- - Info HalWrapper::getInfo() { getCapabilities(); getPrimitiveDurations(); @@ -261,7 +246,7 @@ void AidlHalWrapper::tryReconnect() { if (!result.isOk()) { return; } - std::shared_ptr<Aidl::IVibrator> newHandle = result.value(); + std::shared_ptr<IVibrator> newHandle = result.value(); if (newHandle) { std::lock_guard<std::mutex> lock(mHandleMutex); mHandle = std::move(newHandle); @@ -514,219 +499,13 @@ AidlHalWrapper::getFrequencyToOutputAccelerationMapInternal() { frequencyToOutputAccelerationMap); } -std::shared_ptr<Aidl::IVibrator> AidlHalWrapper::getHal() { - std::lock_guard<std::mutex> lock(mHandleMutex); - return mHandle; -} - -// ------------------------------------------------------------------------------------------------- - -template <typename I> -HalResult<void> HidlHalWrapper<I>::ping() { - return HalResultFactory::fromReturn(getHal()->ping()); -} - -template <typename I> -void HidlHalWrapper<I>::tryReconnect() { - sp<I> newHandle = I::tryGetService(); - if (newHandle) { - std::lock_guard<std::mutex> lock(mHandleMutex); - mHandle = std::move(newHandle); - } -} - -template <typename I> -HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout, - const std::function<void()>& completionCallback) { - auto status = getHal()->on(timeout.count()); - auto ret = HalResultFactory::fromStatus(status.withDefault(V1_0::Status::UNKNOWN_ERROR)); - if (ret.isOk()) { - mCallbackScheduler->schedule(completionCallback, timeout); - } - return ret; -} - -template <typename I> -HalResult<void> HidlHalWrapper<I>::off() { - auto status = getHal()->off(); - return HalResultFactory::fromStatus(status.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 status = getHal()->setAmplitude(amp); - return HalResultFactory::fromStatus(status.withDefault(V1_0::Status::UNKNOWN_ERROR)); -} - -template <typename I> -HalResult<void> HidlHalWrapper<I>::setExternalControl(bool) { - ALOGV("Skipped setExternalControl because Vibrator HAL does not support it"); - return HalResult<void>::unsupported(); -} - -template <typename I> -HalResult<void> HidlHalWrapper<I>::alwaysOnEnable(int32_t, Effect, EffectStrength) { - ALOGV("Skipped alwaysOnEnable because Vibrator HAL AIDL is not available"); - return HalResult<void>::unsupported(); -} - -template <typename I> -HalResult<void> HidlHalWrapper<I>::alwaysOnDisable(int32_t) { - ALOGV("Skipped alwaysOnDisable because Vibrator HAL AIDL is not available"); - return HalResult<void>::unsupported(); -} - -template <typename I> -HalResult<Capabilities> HidlHalWrapper<I>::getCapabilitiesInternal() { - hardware::Return<bool> result = getHal()->supportsAmplitudeControl(); - Capabilities capabilities = - result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE; - return HalResultFactory::fromReturn<Capabilities>(std::move(result), capabilities); -} - -template <typename I> -template <typename T> -HalResult<milliseconds> HidlHalWrapper<I>::performInternal( - perform_fn<T> performFn, sp<I> handle, T effect, EffectStrength strength, - const std::function<void()>& completionCallback) { - V1_0::Status status; - int32_t lengthMs; - auto effectCallback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) { - status = retStatus; - lengthMs = retLengthMs; - }; - - V1_0::EffectStrength effectStrength = static_cast<V1_0::EffectStrength>(strength); - auto result = std::invoke(performFn, handle, effect, effectStrength, effectCallback); - milliseconds length = milliseconds(lengthMs); - - auto ret = HalResultFactory::fromReturn<milliseconds>(std::move(result), status, length); - if (ret.isOk()) { - mCallbackScheduler->schedule(completionCallback, length); - } - - return ret; -} - -template <typename I> -sp<I> HidlHalWrapper<I>::getHal() { +std::shared_ptr<IVibrator> AidlHalWrapper::getHal() { std::lock_guard<std::mutex> lock(mHandleMutex); return mHandle; } // ------------------------------------------------------------------------------------------------- -HalResult<milliseconds> HidlHalWrapperV1_0::performEffect( - Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) { - if (isStaticCastValid<V1_0::Effect>(effect)) { - return performInternal(&V1_0::IVibrator::perform, getHal(), - static_cast<V1_0::Effect>(effect), strength, completionCallback); - } - - ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s", - Aidl::toString(effect).c_str()); - return HalResult<milliseconds>::unsupported(); -} - -// ------------------------------------------------------------------------------------------------- - -HalResult<milliseconds> HidlHalWrapperV1_1::performEffect( - Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) { - if (isStaticCastValid<V1_0::Effect>(effect)) { - return performInternal(&V1_1::IVibrator::perform, getHal(), - static_cast<V1_0::Effect>(effect), strength, completionCallback); - } - if (isStaticCastValid<V1_1::Effect_1_1>(effect)) { - return performInternal(&V1_1::IVibrator::perform_1_1, getHal(), - static_cast<V1_1::Effect_1_1>(effect), strength, completionCallback); - } - - ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s", - Aidl::toString(effect).c_str()); - return HalResult<milliseconds>::unsupported(); -} - -// ------------------------------------------------------------------------------------------------- - -HalResult<milliseconds> HidlHalWrapperV1_2::performEffect( - Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) { - if (isStaticCastValid<V1_0::Effect>(effect)) { - return performInternal(&V1_2::IVibrator::perform, getHal(), - static_cast<V1_0::Effect>(effect), strength, completionCallback); - } - if (isStaticCastValid<V1_1::Effect_1_1>(effect)) { - return performInternal(&V1_2::IVibrator::perform_1_1, getHal(), - static_cast<V1_1::Effect_1_1>(effect), strength, completionCallback); - } - if (isStaticCastValid<V1_2::Effect>(effect)) { - return performInternal(&V1_2::IVibrator::perform_1_2, getHal(), - static_cast<V1_2::Effect>(effect), strength, completionCallback); - } - - ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s", - Aidl::toString(effect).c_str()); - return HalResult<milliseconds>::unsupported(); -} - -// ------------------------------------------------------------------------------------------------- - -HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) { - auto result = getHal()->setExternalControl(static_cast<uint32_t>(enabled)); - return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); -} - -HalResult<milliseconds> HidlHalWrapperV1_3::performEffect( - Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) { - if (isStaticCastValid<V1_0::Effect>(effect)) { - return performInternal(&V1_3::IVibrator::perform, getHal(), - static_cast<V1_0::Effect>(effect), strength, completionCallback); - } - if (isStaticCastValid<V1_1::Effect_1_1>(effect)) { - return performInternal(&V1_3::IVibrator::perform_1_1, getHal(), - static_cast<V1_1::Effect_1_1>(effect), strength, completionCallback); - } - if (isStaticCastValid<V1_2::Effect>(effect)) { - return performInternal(&V1_3::IVibrator::perform_1_2, getHal(), - static_cast<V1_2::Effect>(effect), strength, completionCallback); - } - if (isStaticCastValid<V1_3::Effect>(effect)) { - return performInternal(&V1_3::IVibrator::perform_1_3, getHal(), - static_cast<V1_3::Effect>(effect), strength, completionCallback); - } - - ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s", - Aidl::toString(effect).c_str()); - return HalResult<milliseconds>::unsupported(); -} - -HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() { - Capabilities capabilities = Capabilities::NONE; - - sp<V1_3::IVibrator> hal = getHal(); - auto amplitudeResult = hal->supportsAmplitudeControl(); - if (!amplitudeResult.isOk()) { - return HalResultFactory::fromReturn<Capabilities>(std::move(amplitudeResult), capabilities); - } - - auto externalControlResult = hal->supportsExternalControl(); - if (amplitudeResult.withDefault(false)) { - capabilities |= Capabilities::AMPLITUDE_CONTROL; - } - if (externalControlResult.withDefault(false)) { - capabilities |= Capabilities::EXTERNAL_CONTROL; - - if (amplitudeResult.withDefault(false)) { - capabilities |= Capabilities::EXTERNAL_AMPLITUDE_CONTROL; - } - } - - return HalResultFactory::fromReturn<Capabilities>(std::move(externalControlResult), - capabilities); -} - -// ------------------------------------------------------------------------------------------------- - }; // namespace vibrator }; // namespace android diff --git a/services/vibratorservice/VibratorManagerHalController.cpp b/services/vibratorservice/VibratorManagerHalController.cpp index 494f88f10e..31b6ed030f 100644 --- a/services/vibratorservice/VibratorManagerHalController.cpp +++ b/services/vibratorservice/VibratorManagerHalController.cpp @@ -20,7 +20,10 @@ #include <vibratorservice/VibratorManagerHalController.h> -namespace Aidl = aidl::android::hardware::vibrator; +using aidl::android::hardware::vibrator::IVibrationSession; +using aidl::android::hardware::vibrator::IVibrator; +using aidl::android::hardware::vibrator::IVibratorManager; +using aidl::android::hardware::vibrator::VibrationSessionConfig; namespace android { @@ -29,9 +32,9 @@ namespace vibrator { std::shared_ptr<ManagerHalWrapper> connectManagerHal(std::shared_ptr<CallbackScheduler> scheduler) { static bool gHalExists = true; if (gHalExists) { - auto serviceName = std::string(Aidl::IVibratorManager::descriptor) + "/default"; + auto serviceName = std::string(IVibratorManager::descriptor) + "/default"; if (AServiceManager_isDeclared(serviceName.c_str())) { - std::shared_ptr<Aidl::IVibratorManager> hal = Aidl::IVibratorManager::fromBinder( + std::shared_ptr<IVibratorManager> hal = IVibratorManager::fromBinder( ndk::SpAIBinder(AServiceManager_checkService(serviceName.c_str()))); if (hal) { ALOGV("Successfully connected to VibratorManager HAL AIDL service."); @@ -41,6 +44,7 @@ std::shared_ptr<ManagerHalWrapper> connectManagerHal(std::shared_ptr<CallbackSch } } + ALOGV("VibratorManager HAL service not available."); gHalExists = false; return std::make_shared<LegacyManagerHalWrapper>(); } @@ -150,10 +154,10 @@ HalResult<void> ManagerHalController::cancelSynced() { return apply(cancelSyncedFn, "cancelSynced"); } -HalResult<std::shared_ptr<Aidl::IVibrationSession>> ManagerHalController::startSession( - const std::vector<int32_t>& ids, const Aidl::VibrationSessionConfig& config, +HalResult<std::shared_ptr<IVibrationSession>> ManagerHalController::startSession( + const std::vector<int32_t>& ids, const VibrationSessionConfig& config, const std::function<void()>& completionCallback) { - hal_fn<std::shared_ptr<Aidl::IVibrationSession>> startSessionFn = + hal_fn<std::shared_ptr<IVibrationSession>> startSessionFn = [&](std::shared_ptr<ManagerHalWrapper> hal) { return hal->startSession(ids, config, completionCallback); }; diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp index 3db8ff8699..bab3f58754 100644 --- a/services/vibratorservice/VibratorManagerHalWrapper.cpp +++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp @@ -20,7 +20,10 @@ #include <vibratorservice/VibratorManagerHalWrapper.h> -namespace Aidl = aidl::android::hardware::vibrator; +using aidl::android::hardware::vibrator::IVibrationSession; +using aidl::android::hardware::vibrator::IVibrator; +using aidl::android::hardware::vibrator::IVibratorManager; +using aidl::android::hardware::vibrator::VibrationSessionConfig; namespace android { @@ -41,10 +44,9 @@ HalResult<void> ManagerHalWrapper::cancelSynced() { return HalResult<void>::unsupported(); } -HalResult<std::shared_ptr<Aidl::IVibrationSession>> ManagerHalWrapper::startSession( - const std::vector<int32_t>&, const Aidl::VibrationSessionConfig&, - const std::function<void()>&) { - return HalResult<std::shared_ptr<Aidl::IVibrationSession>>::unsupported(); +HalResult<std::shared_ptr<IVibrationSession>> ManagerHalWrapper::startSession( + const std::vector<int32_t>&, const VibrationSessionConfig&, const std::function<void()>&) { + return HalResult<std::shared_ptr<IVibrationSession>>::unsupported(); } HalResult<void> ManagerHalWrapper::clearSessions() { @@ -87,11 +89,11 @@ HalResult<std::shared_ptr<HalController>> LegacyManagerHalWrapper::getVibrator(i std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator( int32_t vibratorId, std::shared_ptr<CallbackScheduler> callbackScheduler) { - std::function<HalResult<std::shared_ptr<Aidl::IVibrator>>()> reconnectFn = [=, this]() { - std::shared_ptr<Aidl::IVibrator> vibrator; + std::function<HalResult<std::shared_ptr<IVibrator>>()> reconnectFn = [=, this]() { + std::shared_ptr<IVibrator> vibrator; auto status = this->getHal()->getVibrator(vibratorId, &vibrator); - return HalResultFactory::fromStatus<std::shared_ptr<Aidl::IVibrator>>(std::move(status), - vibrator); + return HalResultFactory::fromStatus<std::shared_ptr<IVibrator>>(std::move(status), + vibrator); }; auto result = reconnectFn(); if (!result.isOk()) { @@ -110,8 +112,8 @@ HalResult<void> AidlManagerHalWrapper::ping() { } void AidlManagerHalWrapper::tryReconnect() { - auto aidlServiceName = std::string(Aidl::IVibratorManager::descriptor) + "/default"; - std::shared_ptr<Aidl::IVibratorManager> newHandle = Aidl::IVibratorManager::fromBinder( + auto aidlServiceName = std::string(IVibratorManager::descriptor) + "/default"; + std::shared_ptr<IVibratorManager> newHandle = IVibratorManager::fromBinder( ndk::SpAIBinder(AServiceManager_checkService(aidlServiceName.c_str()))); if (newHandle) { std::lock_guard<std::mutex> lock(mHandleMutex); @@ -198,15 +200,14 @@ HalResult<void> AidlManagerHalWrapper::triggerSynced( return HalResultFactory::fromStatus(getHal()->triggerSynced(cb)); } -HalResult<std::shared_ptr<Aidl::IVibrationSession>> AidlManagerHalWrapper::startSession( - const std::vector<int32_t>& ids, const Aidl::VibrationSessionConfig& config, +HalResult<std::shared_ptr<IVibrationSession>> AidlManagerHalWrapper::startSession( + const std::vector<int32_t>& ids, const VibrationSessionConfig& config, const std::function<void()>& completionCallback) { auto cb = ndk::SharedRefBase::make<HalCallbackWrapper>(completionCallback); - std::shared_ptr<Aidl::IVibrationSession> session; + std::shared_ptr<IVibrationSession> session; auto status = getHal()->startSession(ids, config, cb, &session); - return HalResultFactory::fromStatus<std::shared_ptr<Aidl::IVibrationSession>>(std::move(status), - std::move( - session)); + return HalResultFactory::fromStatus<std::shared_ptr<IVibrationSession>>(std::move(status), + std::move(session)); } HalResult<void> AidlManagerHalWrapper::cancelSynced() { @@ -227,7 +228,7 @@ HalResult<void> AidlManagerHalWrapper::clearSessions() { return HalResultFactory::fromStatus(getHal()->clearSessions()); } -std::shared_ptr<Aidl::IVibratorManager> AidlManagerHalWrapper::getHal() { +std::shared_ptr<IVibratorManager> AidlManagerHalWrapper::getHal() { std::lock_guard<std::mutex> lock(mHandleMutex); return mHandle; } diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp index 915d6c7bc3..6fc5cf3517 100644 --- a/services/vibratorservice/benchmarks/Android.bp +++ b/services/vibratorservice/benchmarks/Android.bp @@ -29,15 +29,10 @@ cc_benchmark { ], shared_libs: [ "libbinder_ndk", - "libhidlbase", "liblog", "libutils", "libvibratorservice", "android.hardware.vibrator-V3-ndk", - "android.hardware.vibrator@1.0", - "android.hardware.vibrator@1.1", - "android.hardware.vibrator@1.2", - "android.hardware.vibrator@1.3", ], cflags: [ "-Wall", diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h index 9a39ad4f7b..065227861d 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h +++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h @@ -22,7 +22,6 @@ #include <android-base/thread_annotations.h> #include <android/binder_manager.h> -#include <android/hardware/vibrator/1.3/IVibrator.h> #include <binder/IServiceManager.h> #include <vibratorservice/VibratorCallbackScheduler.h> @@ -105,26 +104,6 @@ public: : fromFailedStatus<T>(std::move(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(std::move(data)) - : fromFailedStatus<T>(std::move(status)); - } - - template <typename T, typename R> - static HalResult<T> fromReturn(hardware::Return<R>&& ret, T data) { - return ret.isOk() ? HalResult<T>::ok(std::move(data)) - : fromFailedReturn<T, R>(std::move(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>(std::move(status), std::move(data)) - : fromFailedReturn<T, R>(std::move(ret)); - } - static HalResult<void> fromStatus(status_t status) { return (status == android::OK) ? HalResult<void>::ok() : fromFailedStatus<void>(std::move(status)); @@ -134,17 +113,6 @@ public: return status.isOk() ? HalResult<void>::ok() : fromFailedStatus<void>(std::move(status)); } - static HalResult<void> fromStatus(hardware::vibrator::V1_0::Status&& status) { - return (status == hardware::vibrator::V1_0::Status::OK) - ? HalResult<void>::ok() - : fromFailedStatus<void>(std::move(status)); - } - - template <typename R> - static HalResult<void> fromReturn(hardware::Return<R>&& ret) { - return ret.isOk() ? HalResult<void>::ok() : fromFailedReturn<void, R>(std::move(ret)); - } - private: template <typename T> static HalResult<T> fromFailedStatus(status_t status) { @@ -166,23 +134,6 @@ private: } return HalResult<T>::failed(status.getMessage()); } - - 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()); - } - } - - 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()); - } }; // ------------------------------------------------------------------------------------------------- @@ -548,108 +499,6 @@ private: std::shared_ptr<IVibrator> getHal(); }; -// Wrapper for the HDIL Vibrator HALs. -template <typename I> -class HidlHalWrapper : public HalWrapper { -public: - HidlHalWrapper(std::shared_ptr<CallbackScheduler> scheduler, sp<I> handle) - : HalWrapper(std::move(scheduler)), mHandle(std::move(handle)) {} - virtual ~HidlHalWrapper() = default; - - HalResult<void> ping() override final; - void tryReconnect() override final; - - HalResult<void> on(std::chrono::milliseconds timeout, - const std::function<void()>& completionCallback) override final; - HalResult<void> off() override final; - - HalResult<void> setAmplitude(float amplitude) override final; - virtual HalResult<void> setExternalControl(bool enabled) override; - - HalResult<void> alwaysOnEnable(int32_t id, HalWrapper::Effect effect, - HalWrapper::EffectStrength strength) override final; - HalResult<void> alwaysOnDisable(int32_t id) override final; - -protected: - std::mutex mHandleMutex; - sp<I> mHandle GUARDED_BY(mHandleMutex); - - virtual HalResult<Capabilities> getCapabilitiesInternal() override; - - template <class T> - using perform_fn = - hardware::Return<void> (I::*)(T, hardware::vibrator::V1_0::EffectStrength, - hardware::vibrator::V1_0::IVibrator::perform_cb); - - template <class T> - HalResult<std::chrono::milliseconds> performInternal( - perform_fn<T> performFn, sp<I> handle, T effect, HalWrapper::EffectStrength strength, - const std::function<void()>& completionCallback); - - sp<I> getHal(); -}; - -// Wrapper for the HDIL Vibrator HAL v1.0. -class HidlHalWrapperV1_0 : public HidlHalWrapper<hardware::vibrator::V1_0::IVibrator> { -public: - HidlHalWrapperV1_0(std::shared_ptr<CallbackScheduler> scheduler, - sp<hardware::vibrator::V1_0::IVibrator> handle) - : HidlHalWrapper<hardware::vibrator::V1_0::IVibrator>(std::move(scheduler), - std::move(handle)) {} - virtual ~HidlHalWrapperV1_0() = default; - - HalResult<std::chrono::milliseconds> performEffect( - HalWrapper::Effect effect, HalWrapper::EffectStrength strength, - const std::function<void()>& completionCallback) override final; -}; - -// Wrapper for the HDIL Vibrator HAL v1.1. -class HidlHalWrapperV1_1 : public HidlHalWrapper<hardware::vibrator::V1_1::IVibrator> { -public: - HidlHalWrapperV1_1(std::shared_ptr<CallbackScheduler> scheduler, - sp<hardware::vibrator::V1_1::IVibrator> handle) - : HidlHalWrapper<hardware::vibrator::V1_1::IVibrator>(std::move(scheduler), - std::move(handle)) {} - virtual ~HidlHalWrapperV1_1() = default; - - HalResult<std::chrono::milliseconds> performEffect( - HalWrapper::Effect effect, HalWrapper::EffectStrength strength, - const std::function<void()>& completionCallback) override final; -}; - -// Wrapper for the HDIL Vibrator HAL v1.2. -class HidlHalWrapperV1_2 : public HidlHalWrapper<hardware::vibrator::V1_2::IVibrator> { -public: - HidlHalWrapperV1_2(std::shared_ptr<CallbackScheduler> scheduler, - sp<hardware::vibrator::V1_2::IVibrator> handle) - : HidlHalWrapper<hardware::vibrator::V1_2::IVibrator>(std::move(scheduler), - std::move(handle)) {} - virtual ~HidlHalWrapperV1_2() = default; - - HalResult<std::chrono::milliseconds> performEffect( - HalWrapper::Effect effect, HalWrapper::EffectStrength strength, - const std::function<void()>& completionCallback) override final; -}; - -// Wrapper for the HDIL Vibrator HAL v1.3. -class HidlHalWrapperV1_3 : public HidlHalWrapper<hardware::vibrator::V1_3::IVibrator> { -public: - HidlHalWrapperV1_3(std::shared_ptr<CallbackScheduler> scheduler, - sp<hardware::vibrator::V1_3::IVibrator> handle) - : HidlHalWrapper<hardware::vibrator::V1_3::IVibrator>(std::move(scheduler), - std::move(handle)) {} - virtual ~HidlHalWrapperV1_3() = default; - - HalResult<void> setExternalControl(bool enabled) override final; - - HalResult<std::chrono::milliseconds> performEffect( - HalWrapper::Effect effect, HalWrapper::EffectStrength strength, - const std::function<void()>& completionCallback) override final; - -protected: - HalResult<Capabilities> getCapabilitiesInternal() override final; -}; - // ------------------------------------------------------------------------------------------------- }; // namespace vibrator diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp index 92527eb5cf..038248e636 100644 --- a/services/vibratorservice/test/Android.bp +++ b/services/vibratorservice/test/Android.bp @@ -29,10 +29,6 @@ cc_test { "VibratorCallbackSchedulerTest.cpp", "VibratorHalControllerTest.cpp", "VibratorHalWrapperAidlTest.cpp", - "VibratorHalWrapperHidlV1_0Test.cpp", - "VibratorHalWrapperHidlV1_1Test.cpp", - "VibratorHalWrapperHidlV1_2Test.cpp", - "VibratorHalWrapperHidlV1_3Test.cpp", "VibratorManagerHalControllerTest.cpp", "VibratorManagerHalWrapperAidlTest.cpp", "VibratorManagerHalWrapperLegacyTest.cpp", @@ -45,15 +41,10 @@ cc_test { shared_libs: [ "libbase", "libbinder_ndk", - "libhidlbase", "liblog", "libvibratorservice", "libutils", "android.hardware.vibrator-V3-ndk", - "android.hardware.vibrator@1.0", - "android.hardware.vibrator@1.1", - "android.hardware.vibrator@1.2", - "android.hardware.vibrator@1.3", ], static_libs: [ "libgmock", diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp deleted file mode 100644 index 04dbe4eb26..0000000000 --- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "VibratorHalWrapperHidlV1_0Test" - -#include <aidl/android/hardware/vibrator/IVibrator.h> -#include <android/persistable_bundle_aidl.h> - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <utils/Log.h> -#include <thread> - -#include <vibratorservice/VibratorCallbackScheduler.h> -#include <vibratorservice/VibratorHalWrapper.h> - -#include "test_mocks.h" -#include "test_utils.h" - -namespace V1_0 = android::hardware::vibrator::V1_0; - -using aidl::android::hardware::vibrator::Braking; -using aidl::android::hardware::vibrator::CompositeEffect; -using aidl::android::hardware::vibrator::CompositePrimitive; -using aidl::android::hardware::vibrator::CompositePwleV2; -using aidl::android::hardware::vibrator::Effect; -using aidl::android::hardware::vibrator::EffectStrength; -using aidl::android::hardware::vibrator::IVibrator; -using aidl::android::hardware::vibrator::PrimitivePwle; -using aidl::android::hardware::vibrator::PwleV2Primitive; -using aidl::android::hardware::vibrator::VendorEffect; -using aidl::android::os::PersistableBundle; - -using namespace android; -using namespace std::chrono_literals; -using namespace testing; - -// ------------------------------------------------------------------------------------------------- - -class MockIVibratorV1_0 : public V1_0::IVibrator { -public: - MOCK_METHOD(hardware::Return<void>, ping, (), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, on, (uint32_t timeoutMs), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, off, (), (override)); - MOCK_METHOD(hardware::Return<bool>, supportsAmplitudeControl, (), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, setAmplitude, (uint8_t amplitude), (override)); - MOCK_METHOD(hardware::Return<void>, perform, - (V1_0::Effect effect, V1_0::EffectStrength strength, perform_cb cb), (override)); -}; - -// ------------------------------------------------------------------------------------------------- - -class VibratorHalWrapperHidlV1_0Test : public Test { -public: - void SetUp() override { - mMockHal = new StrictMock<MockIVibratorV1_0>(); - mMockScheduler = std::make_shared<StrictMock<vibrator::MockCallbackScheduler>>(); - mWrapper = std::make_unique<vibrator::HidlHalWrapperV1_0>(mMockScheduler, mMockHal); - ASSERT_NE(mWrapper, nullptr); - } - -protected: - std::shared_ptr<StrictMock<vibrator::MockCallbackScheduler>> mMockScheduler = nullptr; - std::unique_ptr<vibrator::HalWrapper> mWrapper = nullptr; - sp<StrictMock<MockIVibratorV1_0>> mMockHal = nullptr; -}; - -// ------------------------------------------------------------------------------------------------- - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestPing) { - EXPECT_CALL(*mMockHal.get(), ping()) - .Times(Exactly(2)) - .WillOnce([]() { return hardware::Return<void>(); }) - .WillRepeatedly([]() { - return hardware::Return<void>(hardware::Status::fromExceptionCode(-1)); - }); - - ASSERT_TRUE(mWrapper->ping().isOk()); - ASSERT_TRUE(mWrapper->ping().isFailed()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestOn) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), on(Eq(static_cast<uint32_t>(1)))) - .Times(Exactly(1)) - .WillRepeatedly( - [](uint32_t) { return hardware::Return<V1_0::Status>(V1_0::Status::OK); }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(1ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - EXPECT_CALL(*mMockHal.get(), on(Eq(static_cast<uint32_t>(10)))) - .Times(Exactly(1)) - .WillRepeatedly([](uint32_t) { - return hardware::Return<V1_0::Status>(V1_0::Status::UNSUPPORTED_OPERATION); - }); - EXPECT_CALL(*mMockHal.get(), on(Eq(static_cast<uint32_t>(11)))) - .Times(Exactly(1)) - .WillRepeatedly([](uint32_t) { - return hardware::Return<V1_0::Status>(V1_0::Status::BAD_VALUE); - }); - EXPECT_CALL(*mMockHal.get(), on(Eq(static_cast<uint32_t>(12)))) - .Times(Exactly(1)) - .WillRepeatedly([](uint32_t) { - return hardware::Return<V1_0::Status>(hardware::Status::fromExceptionCode(-1)); - }); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - - ASSERT_TRUE(mWrapper->on(1ms, callback).isOk()); - ASSERT_EQ(1, *callbackCounter.get()); - - ASSERT_TRUE(mWrapper->on(10ms, callback).isUnsupported()); - ASSERT_TRUE(mWrapper->on(11ms, callback).isFailed()); - ASSERT_TRUE(mWrapper->on(12ms, callback).isFailed()); - - // Callback not triggered for unsupported and on failure - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestOff) { - EXPECT_CALL(*mMockHal.get(), off()) - .Times(Exactly(4)) - .WillOnce([]() { return hardware::Return<V1_0::Status>(V1_0::Status::OK); }) - .WillOnce([]() { - return hardware::Return<V1_0::Status>(V1_0::Status::UNSUPPORTED_OPERATION); - }) - .WillOnce([]() { return hardware::Return<V1_0::Status>(V1_0::Status::BAD_VALUE); }) - .WillRepeatedly([]() { - return hardware::Return<V1_0::Status>(hardware::Status::fromExceptionCode(-1)); - }); - - ASSERT_TRUE(mWrapper->off().isOk()); - ASSERT_TRUE(mWrapper->off().isUnsupported()); - ASSERT_TRUE(mWrapper->off().isFailed()); - ASSERT_TRUE(mWrapper->off().isFailed()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestSetAmplitude) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(static_cast<uint8_t>(1)))) - .Times(Exactly(1)) - .WillRepeatedly( - [](uint8_t) { return hardware::Return<V1_0::Status>(V1_0::Status::OK); }); - EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(static_cast<uint8_t>(2)))) - .Times(Exactly(1)) - .WillRepeatedly([](uint8_t) { - return hardware::Return<V1_0::Status>(V1_0::Status::UNSUPPORTED_OPERATION); - }); - EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(static_cast<uint8_t>(3)))) - .Times(Exactly(1)) - .WillRepeatedly([](uint8_t) { - return hardware::Return<V1_0::Status>(V1_0::Status::BAD_VALUE); - }); - EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(static_cast<uint8_t>(4)))) - .Times(Exactly(1)) - .WillRepeatedly([](uint8_t) { - return hardware::Return<V1_0::Status>(hardware::Status::fromExceptionCode(-1)); - }); - } - - auto maxAmplitude = std::numeric_limits<uint8_t>::max(); - ASSERT_TRUE(mWrapper->setAmplitude(1.0f / maxAmplitude).isOk()); - ASSERT_TRUE(mWrapper->setAmplitude(2.0f / maxAmplitude).isUnsupported()); - ASSERT_TRUE(mWrapper->setAmplitude(3.0f / maxAmplitude).isFailed()); - ASSERT_TRUE(mWrapper->setAmplitude(4.0f / maxAmplitude).isFailed()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestSetExternalControlUnsupported) { - ASSERT_TRUE(mWrapper->setExternalControl(true).isUnsupported()); - ASSERT_TRUE(mWrapper->setExternalControl(false).isUnsupported()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestAlwaysOnEnableUnsupported) { - ASSERT_TRUE(mWrapper->alwaysOnEnable(1, Effect::CLICK, EffectStrength::LIGHT).isUnsupported()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestAlwaysOnDisableUnsupported) { - ASSERT_TRUE(mWrapper->alwaysOnDisable(1).isUnsupported()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetInfoDoesNotCacheFailedResult) { - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()) - .Times(Exactly(2)) - .WillOnce([]() { - return hardware::Return<bool>(hardware::Status::fromExceptionCode(-1)); - }) - .WillRepeatedly([]() { return hardware::Return<bool>(true); }); - - ASSERT_TRUE(mWrapper->getInfo().capabilities.isFailed()); - - vibrator::Info info = mWrapper->getInfo(); - ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, info.capabilities.value()); - ASSERT_TRUE(info.supportedEffects.isUnsupported()); - ASSERT_TRUE(info.supportedBraking.isUnsupported()); - ASSERT_TRUE(info.supportedPrimitives.isUnsupported()); - ASSERT_TRUE(info.primitiveDurations.isUnsupported()); - ASSERT_TRUE(info.primitiveDelayMax.isUnsupported()); - ASSERT_TRUE(info.pwlePrimitiveDurationMax.isUnsupported()); - ASSERT_TRUE(info.compositionSizeMax.isUnsupported()); - ASSERT_TRUE(info.pwleSizeMax.isUnsupported()); - ASSERT_TRUE(info.minFrequency.isUnsupported()); - ASSERT_TRUE(info.resonantFrequency.isUnsupported()); - ASSERT_TRUE(info.frequencyResolution.isUnsupported()); - ASSERT_TRUE(info.qFactor.isUnsupported()); - ASSERT_TRUE(info.maxAmplitudes.isUnsupported()); - ASSERT_TRUE(info.maxEnvelopeEffectSize.isUnsupported()); - ASSERT_TRUE(info.minEnvelopeEffectControlPointDuration.isUnsupported()); - ASSERT_TRUE(info.maxEnvelopeEffectControlPointDuration.isUnsupported()); - ASSERT_TRUE(info.frequencyToOutputAccelerationMap.isUnsupported()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetInfoWithoutAmplitudeControl) { - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()).Times(Exactly(1)).WillRepeatedly([]() { - return hardware::Return<bool>(false); - }); - - ASSERT_EQ(vibrator::Capabilities::NONE, mWrapper->getInfo().capabilities.value()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetInfoCachesResult) { - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()).Times(Exactly(1)).WillRepeatedly([]() { - return hardware::Return<bool>(true); - }); - - std::vector<std::thread> threads; - for (int i = 0; i < 10; i++) { - threads.push_back( - std::thread([&]() { ASSERT_TRUE(mWrapper->getInfo().capabilities.isOk()); })); - } - std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); - - vibrator::Info info = mWrapper->getInfo(); - ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, info.capabilities.value()); - ASSERT_TRUE(info.supportedEffects.isUnsupported()); - ASSERT_TRUE(info.supportedBraking.isUnsupported()); - ASSERT_TRUE(info.supportedPrimitives.isUnsupported()); - ASSERT_TRUE(info.primitiveDurations.isUnsupported()); - ASSERT_TRUE(info.minFrequency.isUnsupported()); - ASSERT_TRUE(info.resonantFrequency.isUnsupported()); - ASSERT_TRUE(info.frequencyResolution.isUnsupported()); - ASSERT_TRUE(info.qFactor.isUnsupported()); - ASSERT_TRUE(info.maxAmplitudes.isUnsupported()); - ASSERT_TRUE(info.maxEnvelopeEffectSize.isUnsupported()); - ASSERT_TRUE(info.minEnvelopeEffectControlPointDuration.isUnsupported()); - ASSERT_TRUE(info.maxEnvelopeEffectControlPointDuration.isUnsupported()); - ASSERT_TRUE(info.frequencyToOutputAccelerationMap.isUnsupported()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformEffect) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform(Eq(V1_0::Effect::CLICK), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_0::Effect, V1_0::EffectStrength, MockIVibratorV1_0::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - EXPECT_CALL(*mMockHal.get(), - perform(Eq(V1_0::Effect::CLICK), Eq(V1_0::EffectStrength::MEDIUM), _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_0::Effect, V1_0::EffectStrength, MockIVibratorV1_0::perform_cb cb) { - cb(V1_0::Status::UNSUPPORTED_OPERATION, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockHal.get(), - perform(Eq(V1_0::Effect::CLICK), Eq(V1_0::EffectStrength::STRONG), _)) - .Times(Exactly(2)) - .WillOnce([](V1_0::Effect, V1_0::EffectStrength, MockIVibratorV1_0::perform_cb cb) { - cb(V1_0::Status::BAD_VALUE, 10); - return hardware::Return<void>(); - }) - .WillRepeatedly( - [](V1_0::Effect, V1_0::EffectStrength, MockIVibratorV1_0::perform_cb) { - return hardware::Return<void>(hardware::Status::fromExceptionCode(-1)); - }); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - - auto result = mWrapper->performEffect(Effect::CLICK, EffectStrength::LIGHT, callback); - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); - - result = mWrapper->performEffect(Effect::CLICK, EffectStrength::MEDIUM, callback); - ASSERT_TRUE(result.isUnsupported()); - - result = mWrapper->performEffect(Effect::CLICK, EffectStrength::STRONG, callback); - ASSERT_TRUE(result.isFailed()); - - result = mWrapper->performEffect(Effect::CLICK, EffectStrength::STRONG, callback); - ASSERT_TRUE(result.isFailed()); - - // Callback not triggered for unsupported and on failure - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformEffectUnsupported) { - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - // Using TICK that is only available in v1.1 - auto result = mWrapper->performEffect(Effect::TICK, EffectStrength::LIGHT, callback); - ASSERT_TRUE(result.isUnsupported()); - // No callback is triggered. - ASSERT_EQ(0, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformVendorEffectUnsupported) { - PersistableBundle vendorData; // empty - VendorEffect vendorEffect; - vendorEffect.vendorData = vendorData; - vendorEffect.strength = EffectStrength::LIGHT; - vendorEffect.scale = 1.0f; - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - - ASSERT_TRUE(mWrapper->performVendorEffect(vendorEffect, callback).isUnsupported()); - - // No callback is triggered. - ASSERT_EQ(0, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformComposedEffectUnsupported) { - std::vector<CompositeEffect> emptyEffects, singleEffect, multipleEffects; - singleEffect.push_back( - vibrator::TestFactory::createCompositeEffect(CompositePrimitive::CLICK, 10ms, 0.0f)); - multipleEffects.push_back( - vibrator::TestFactory::createCompositeEffect(CompositePrimitive::SPIN, 100ms, 0.5f)); - multipleEffects.push_back( - vibrator::TestFactory::createCompositeEffect(CompositePrimitive::THUD, 1000ms, 1.0f)); - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - - ASSERT_TRUE(mWrapper->performComposedEffect(singleEffect, callback).isUnsupported()); - ASSERT_TRUE(mWrapper->performComposedEffect(multipleEffects, callback).isUnsupported()); - - // No callback is triggered. - ASSERT_EQ(0, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformPwleEffectUnsupported) { - std::vector<PrimitivePwle> emptyPrimitives, multiplePrimitives; - multiplePrimitives.push_back(vibrator::TestFactory::createActivePwle(0, 1, 0, 1, 10ms)); - multiplePrimitives.push_back(vibrator::TestFactory::createBrakingPwle(Braking::NONE, 100ms)); - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - - ASSERT_TRUE(mWrapper->performPwleEffect(emptyPrimitives, callback).isUnsupported()); - ASSERT_TRUE(mWrapper->performPwleEffect(multiplePrimitives, callback).isUnsupported()); - - // No callback is triggered. - ASSERT_EQ(0, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_0Test, TestComposePwleV2Unsupported) { - CompositePwleV2 composite; - composite.pwlePrimitives = { - PwleV2Primitive(/*amplitude=*/0.2, /*frequency=*/50, /*time=*/100), - PwleV2Primitive(/*amplitude=*/0.5, /*frequency=*/150, /*time=*/100), - PwleV2Primitive(/*amplitude=*/0.8, /*frequency=*/250, /*time=*/100), - }; - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - - ASSERT_TRUE(mWrapper->composePwleV2(composite, callback).isUnsupported()); - - // No callback is triggered. - ASSERT_EQ(0, *callbackCounter.get()); -} diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_1Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_1Test.cpp deleted file mode 100644 index b0a653769e..0000000000 --- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_1Test.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "VibratorHalWrapperHidlV1_1Test" - -#include <aidl/android/hardware/vibrator/IVibrator.h> - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <utils/Log.h> - -#include <vibratorservice/VibratorCallbackScheduler.h> -#include <vibratorservice/VibratorHalWrapper.h> - -#include "test_mocks.h" -#include "test_utils.h" - -namespace V1_0 = android::hardware::vibrator::V1_0; -namespace V1_1 = android::hardware::vibrator::V1_1; - -using aidl::android::hardware::vibrator::Effect; -using aidl::android::hardware::vibrator::EffectStrength; - -using namespace android; -using namespace std::chrono_literals; -using namespace testing; - -// ------------------------------------------------------------------------------------------------- - -class MockIVibratorV1_1 : public V1_1::IVibrator { -public: - MOCK_METHOD(hardware::Return<V1_0::Status>, on, (uint32_t timeoutMs), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, off, (), (override)); - MOCK_METHOD(hardware::Return<bool>, supportsAmplitudeControl, (), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, setAmplitude, (uint8_t amplitude), (override)); - MOCK_METHOD(hardware::Return<void>, perform, - (V1_0::Effect effect, V1_0::EffectStrength strength, perform_cb cb), (override)); - MOCK_METHOD(hardware::Return<void>, perform_1_1, - (V1_1::Effect_1_1 effect, V1_0::EffectStrength strength, perform_cb cb), - (override)); -}; - -// ------------------------------------------------------------------------------------------------- - -class VibratorHalWrapperHidlV1_1Test : public Test { -public: - void SetUp() override { - mMockHal = new StrictMock<MockIVibratorV1_1>(); - mMockScheduler = std::make_shared<StrictMock<vibrator::MockCallbackScheduler>>(); - mWrapper = std::make_unique<vibrator::HidlHalWrapperV1_1>(mMockScheduler, mMockHal); - ASSERT_NE(mWrapper, nullptr); - } - -protected: - std::shared_ptr<StrictMock<vibrator::MockCallbackScheduler>> mMockScheduler = nullptr; - std::unique_ptr<vibrator::HalWrapper> mWrapper = nullptr; - sp<StrictMock<MockIVibratorV1_1>> mMockHal = nullptr; -}; - -// ------------------------------------------------------------------------------------------------- - -TEST_F(VibratorHalWrapperHidlV1_1Test, TestPerformEffectV1_0) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform(Eq(V1_0::Effect::CLICK), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_0::Effect, V1_0::EffectStrength, MockIVibratorV1_1::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - auto result = mWrapper->performEffect(Effect::CLICK, EffectStrength::LIGHT, callback); - - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_1Test, TestPerformEffectV1_1) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform_1_1(Eq(V1_1::Effect_1_1::TICK), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly([](V1_1::Effect_1_1, V1_0::EffectStrength, - MockIVibratorV1_1::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - EXPECT_CALL(*mMockHal.get(), - perform_1_1(Eq(V1_1::Effect_1_1::TICK), Eq(V1_0::EffectStrength::MEDIUM), _)) - .Times(Exactly(1)) - .WillRepeatedly([](V1_1::Effect_1_1, V1_0::EffectStrength, - MockIVibratorV1_1::perform_cb cb) { - cb(V1_0::Status::UNSUPPORTED_OPERATION, 0); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockHal.get(), - perform_1_1(Eq(V1_1::Effect_1_1::TICK), Eq(V1_0::EffectStrength::STRONG), _)) - .Times(Exactly(2)) - .WillOnce([](V1_1::Effect_1_1, V1_0::EffectStrength, - MockIVibratorV1_1::perform_cb cb) { - cb(V1_0::Status::BAD_VALUE, 0); - return hardware::Return<void>(); - }) - .WillRepeatedly( - [](V1_1::Effect_1_1, V1_0::EffectStrength, MockIVibratorV1_1::perform_cb) { - return hardware::Return<void>(hardware::Status::fromExceptionCode(-1)); - }); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - - auto result = mWrapper->performEffect(Effect::TICK, EffectStrength::LIGHT, callback); - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); - - result = mWrapper->performEffect(Effect::TICK, EffectStrength::MEDIUM, callback); - ASSERT_TRUE(result.isUnsupported()); - - result = mWrapper->performEffect(Effect::TICK, EffectStrength::STRONG, callback); - ASSERT_TRUE(result.isFailed()); - - result = mWrapper->performEffect(Effect::TICK, EffectStrength::STRONG, callback); - ASSERT_TRUE(result.isFailed()); - - // Callback not triggered for unsupported and on failure - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_1Test, TestPerformEffectUnsupported) { - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - // Using THUD that is only available in v1.2 - auto result = mWrapper->performEffect(Effect::THUD, EffectStrength::LIGHT, callback); - ASSERT_TRUE(result.isUnsupported()); - // No callback is triggered. - ASSERT_EQ(0, *callbackCounter.get()); -} diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_2Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_2Test.cpp deleted file mode 100644 index dfe3fa0e68..0000000000 --- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_2Test.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "VibratorHalWrapperHidlV1_2Test" - -#include <aidl/android/hardware/vibrator/IVibrator.h> - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <utils/Log.h> - -#include <vibratorservice/VibratorCallbackScheduler.h> -#include <vibratorservice/VibratorHalWrapper.h> - -#include "test_mocks.h" -#include "test_utils.h" - -namespace V1_0 = android::hardware::vibrator::V1_0; -namespace V1_1 = android::hardware::vibrator::V1_1; -namespace V1_2 = android::hardware::vibrator::V1_2; - -using aidl::android::hardware::vibrator::Effect; -using aidl::android::hardware::vibrator::EffectStrength; - -using namespace android; -using namespace std::chrono_literals; -using namespace testing; - -// ------------------------------------------------------------------------------------------------- - -class MockIVibratorV1_2 : public V1_2::IVibrator { -public: - MOCK_METHOD(hardware::Return<V1_0::Status>, on, (uint32_t timeoutMs), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, off, (), (override)); - MOCK_METHOD(hardware::Return<bool>, supportsAmplitudeControl, (), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, setAmplitude, (uint8_t amplitude), (override)); - MOCK_METHOD(hardware::Return<void>, perform, - (V1_0::Effect effect, V1_0::EffectStrength strength, perform_cb cb), (override)); - MOCK_METHOD(hardware::Return<void>, perform_1_1, - (V1_1::Effect_1_1 effect, V1_0::EffectStrength strength, perform_cb cb), - (override)); - MOCK_METHOD(hardware::Return<void>, perform_1_2, - (V1_2::Effect effect, V1_0::EffectStrength strength, perform_cb cb), (override)); -}; - -// ------------------------------------------------------------------------------------------------- - -class VibratorHalWrapperHidlV1_2Test : public Test { -public: - void SetUp() override { - mMockHal = new StrictMock<MockIVibratorV1_2>(); - mMockScheduler = std::make_shared<StrictMock<vibrator::MockCallbackScheduler>>(); - mWrapper = std::make_unique<vibrator::HidlHalWrapperV1_2>(mMockScheduler, mMockHal); - ASSERT_NE(mWrapper, nullptr); - } - -protected: - std::shared_ptr<StrictMock<vibrator::MockCallbackScheduler>> mMockScheduler = nullptr; - std::unique_ptr<vibrator::HalWrapper> mWrapper = nullptr; - sp<StrictMock<MockIVibratorV1_2>> mMockHal = nullptr; -}; - -// ------------------------------------------------------------------------------------------------- - -TEST_F(VibratorHalWrapperHidlV1_2Test, TestPerformEffectV1_0) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform(Eq(V1_0::Effect::CLICK), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_0::Effect, V1_0::EffectStrength, MockIVibratorV1_2::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - auto result = mWrapper->performEffect(Effect::CLICK, EffectStrength::LIGHT, callback); - - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_2Test, TestPerformEffectV1_1) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform_1_1(Eq(V1_1::Effect_1_1::TICK), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly([](V1_1::Effect_1_1, V1_0::EffectStrength, - MockIVibratorV1_2::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - auto result = mWrapper->performEffect(Effect::TICK, EffectStrength::LIGHT, callback); - - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_2Test, TestPerformEffectV1_2) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform_1_2(Eq(V1_2::Effect::THUD), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_2::Effect, V1_0::EffectStrength, MockIVibratorV1_2::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - EXPECT_CALL(*mMockHal.get(), - perform_1_2(Eq(V1_2::Effect::THUD), Eq(V1_0::EffectStrength::MEDIUM), _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_2::Effect, V1_0::EffectStrength, MockIVibratorV1_2::perform_cb cb) { - cb(V1_0::Status::UNSUPPORTED_OPERATION, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockHal.get(), - perform_1_2(Eq(V1_2::Effect::THUD), Eq(V1_0::EffectStrength::STRONG), _)) - .Times(Exactly(2)) - .WillOnce([](V1_2::Effect, V1_0::EffectStrength, MockIVibratorV1_2::perform_cb cb) { - cb(V1_0::Status::BAD_VALUE, 10); - return hardware::Return<void>(); - }) - .WillRepeatedly( - [](V1_2::Effect, V1_0::EffectStrength, MockIVibratorV1_2::perform_cb) { - return hardware::Return<void>(hardware::Status::fromExceptionCode(-1)); - }); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - - auto result = mWrapper->performEffect(Effect::THUD, EffectStrength::LIGHT, callback); - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); - - result = mWrapper->performEffect(Effect::THUD, EffectStrength::MEDIUM, callback); - ASSERT_TRUE(result.isUnsupported()); - - result = mWrapper->performEffect(Effect::THUD, EffectStrength::STRONG, callback); - ASSERT_TRUE(result.isFailed()); - - result = mWrapper->performEffect(Effect::THUD, EffectStrength::STRONG, callback); - ASSERT_TRUE(result.isFailed()); - - // Callback not triggered for unsupported and on failure - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_2Test, TestPerformEffectUnsupported) { - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - // Using TEXTURE_TICK that is only available in v1.3 - auto result = mWrapper->performEffect(Effect::TEXTURE_TICK, EffectStrength::LIGHT, callback); - ASSERT_TRUE(result.isUnsupported()); - // No callback is triggered. - ASSERT_EQ(0, *callbackCounter.get()); -} diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp deleted file mode 100644 index 86243326ac..0000000000 --- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "VibratorHalWrapperHidlV1_3Test" - -#include <aidl/android/hardware/vibrator/IVibrator.h> - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <utils/Log.h> -#include <thread> - -#include <vibratorservice/VibratorCallbackScheduler.h> -#include <vibratorservice/VibratorHalWrapper.h> - -#include "test_mocks.h" -#include "test_utils.h" - -namespace V1_0 = android::hardware::vibrator::V1_0; -namespace V1_1 = android::hardware::vibrator::V1_1; -namespace V1_2 = android::hardware::vibrator::V1_2; -namespace V1_3 = android::hardware::vibrator::V1_3; - -using aidl::android::hardware::vibrator::Effect; -using aidl::android::hardware::vibrator::EffectStrength; -using aidl::android::hardware::vibrator::IVibrator; - -using namespace android; -using namespace std::chrono_literals; -using namespace testing; - -// ------------------------------------------------------------------------------------------------- - -class MockIVibratorV1_3 : public V1_3::IVibrator { -public: - MOCK_METHOD(hardware::Return<V1_0::Status>, on, (uint32_t timeoutMs), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, off, (), (override)); - MOCK_METHOD(hardware::Return<bool>, supportsAmplitudeControl, (), (override)); - MOCK_METHOD(hardware::Return<bool>, supportsExternalControl, (), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, setAmplitude, (uint8_t amplitude), (override)); - MOCK_METHOD(hardware::Return<V1_0::Status>, setExternalControl, (bool enabled), (override)); - MOCK_METHOD(hardware::Return<void>, perform, - (V1_0::Effect effect, V1_0::EffectStrength strength, perform_cb cb), (override)); - MOCK_METHOD(hardware::Return<void>, perform_1_1, - (V1_1::Effect_1_1 effect, V1_0::EffectStrength strength, perform_cb cb), - (override)); - MOCK_METHOD(hardware::Return<void>, perform_1_2, - (V1_2::Effect effect, V1_0::EffectStrength strength, perform_cb cb), (override)); - MOCK_METHOD(hardware::Return<void>, perform_1_3, - (V1_3::Effect effect, V1_0::EffectStrength strength, perform_cb cb), (override)); -}; - -// ------------------------------------------------------------------------------------------------- - -class VibratorHalWrapperHidlV1_3Test : public Test { -public: - void SetUp() override { - mMockHal = new StrictMock<MockIVibratorV1_3>(); - mMockScheduler = std::make_shared<StrictMock<vibrator::MockCallbackScheduler>>(); - mWrapper = std::make_unique<vibrator::HidlHalWrapperV1_3>(mMockScheduler, mMockHal); - ASSERT_NE(mWrapper, nullptr); - } - -protected: - std::shared_ptr<StrictMock<vibrator::MockCallbackScheduler>> mMockScheduler = nullptr; - std::unique_ptr<vibrator::HalWrapper> mWrapper = nullptr; - sp<StrictMock<MockIVibratorV1_3>> mMockHal = nullptr; -}; - -// ------------------------------------------------------------------------------------------------- - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestSetExternalControl) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), setExternalControl(Eq(true))) - .Times(Exactly(2)) - .WillOnce([]() { return hardware::Return<V1_0::Status>(V1_0::Status::OK); }) - .WillRepeatedly([]() { - return hardware::Return<V1_0::Status>(V1_0::Status::UNSUPPORTED_OPERATION); - }); - EXPECT_CALL(*mMockHal.get(), setExternalControl(Eq(false))) - .Times(Exactly(2)) - .WillOnce([]() { return hardware::Return<V1_0::Status>(V1_0::Status::BAD_VALUE); }) - .WillRepeatedly([]() { - return hardware::Return<V1_0::Status>(hardware::Status::fromExceptionCode(-1)); - }); - } - - ASSERT_TRUE(mWrapper->setExternalControl(true).isOk()); - ASSERT_TRUE(mWrapper->setExternalControl(true).isUnsupported()); - ASSERT_TRUE(mWrapper->setExternalControl(false).isFailed()); - ASSERT_TRUE(mWrapper->setExternalControl(false).isFailed()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestGetInfoSuccessful) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { return hardware::Return<bool>(true); }); - EXPECT_CALL(*mMockHal.get(), supportsExternalControl()).Times(Exactly(1)).WillOnce([]() { - return hardware::Return<bool>(true); - }); - } - - ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL | vibrator::Capabilities::EXTERNAL_CONTROL | - vibrator::Capabilities::EXTERNAL_AMPLITUDE_CONTROL, - mWrapper->getInfo().capabilities.value()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestGetInfoOnlyAmplitudeControl) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()).Times(Exactly(1)).WillOnce([]() { - return hardware::Return<bool>(true); - }); - EXPECT_CALL(*mMockHal.get(), supportsExternalControl()).Times(Exactly(1)).WillOnce([]() { - return hardware::Return<bool>(false); - }); - } - - ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, mWrapper->getInfo().capabilities.value()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestGetInfoOnlyExternalControl) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()).Times(Exactly(1)).WillOnce([]() { - return hardware::Return<bool>(false); - }); - EXPECT_CALL(*mMockHal.get(), supportsExternalControl()).Times(Exactly(1)).WillOnce([]() { - return hardware::Return<bool>(true); - }); - } - - ASSERT_EQ(vibrator::Capabilities::EXTERNAL_CONTROL, mWrapper->getInfo().capabilities.value()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestGetInfoNoCapabilities) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { return hardware::Return<bool>(false); }); - EXPECT_CALL(*mMockHal.get(), supportsExternalControl()).Times(Exactly(1)).WillOnce([]() { - return hardware::Return<bool>(false); - }); - } - - ASSERT_EQ(vibrator::Capabilities::NONE, mWrapper->getInfo().capabilities.value()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestGetInfoFailed) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { - return hardware::Return<bool>(hardware::Status::fromExceptionCode(-1)); - }); - - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { return hardware::Return<bool>(true); }); - EXPECT_CALL(*mMockHal.get(), supportsExternalControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { - return hardware::Return<bool>(hardware::Status::fromExceptionCode(-1)); - }); - } - - ASSERT_TRUE(mWrapper->getInfo().capabilities.isFailed()); - ASSERT_TRUE(mWrapper->getInfo().capabilities.isFailed()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestGetInfoCachesResult) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { return hardware::Return<bool>(true); }); - EXPECT_CALL(*mMockHal.get(), supportsExternalControl()).Times(Exactly(1)).WillOnce([]() { - return hardware::Return<bool>(false); - }); - } - - std::vector<std::thread> threads; - for (int i = 0; i < 10; i++) { - threads.push_back( - std::thread([&]() { ASSERT_TRUE(mWrapper->getInfo().capabilities.isOk()); })); - } - std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); - - ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, mWrapper->getInfo().capabilities.value()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestGetInfoDoesNotCacheFailedResult) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { - return hardware::Return<bool>(hardware::Status::fromExceptionCode(-1)); - }); - - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { return hardware::Return<bool>(true); }); - EXPECT_CALL(*mMockHal.get(), supportsExternalControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { - return hardware::Return<bool>(hardware::Status::fromExceptionCode(-1)); - }); - - EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { return hardware::Return<bool>(true); }); - EXPECT_CALL(*mMockHal.get(), supportsExternalControl()) - .Times(Exactly(1)) - .WillRepeatedly([]() { return hardware::Return<bool>(false); }); - } - - // Call to supportsAmplitudeControl failed. - ASSERT_TRUE(mWrapper->getInfo().capabilities.isFailed()); - - // Call to supportsExternalControl failed. - ASSERT_TRUE(mWrapper->getInfo().capabilities.isFailed()); - - // Returns successful result from third call. - ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, mWrapper->getInfo().capabilities.value()); - - // Returns cached successful result. - ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, mWrapper->getInfo().capabilities.value()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestPerformEffectV1_0) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform(Eq(V1_0::Effect::CLICK), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_0::Effect, V1_0::EffectStrength, MockIVibratorV1_3::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - auto result = mWrapper->performEffect(Effect::CLICK, EffectStrength::LIGHT, callback); - - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestPerformEffectV1_1) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform_1_1(Eq(V1_1::Effect_1_1::TICK), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly([](V1_1::Effect_1_1, V1_0::EffectStrength, - MockIVibratorV1_3::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - auto result = mWrapper->performEffect(Effect::TICK, EffectStrength::LIGHT, callback); - - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestPerformEffectV1_2) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform_1_2(Eq(V1_2::Effect::THUD), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_2::Effect, V1_0::EffectStrength, MockIVibratorV1_3::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - auto result = mWrapper->performEffect(Effect::THUD, EffectStrength::LIGHT, callback); - - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); -} - -TEST_F(VibratorHalWrapperHidlV1_3Test, TestPerformEffectV1_3) { - { - InSequence seq; - EXPECT_CALL(*mMockHal.get(), - perform_1_3(Eq(V1_3::Effect::TEXTURE_TICK), Eq(V1_0::EffectStrength::LIGHT), _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_3::Effect, V1_0::EffectStrength, MockIVibratorV1_3::perform_cb cb) { - cb(V1_0::Status::OK, 10); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) - .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); - EXPECT_CALL(*mMockHal.get(), - perform_1_3(Eq(V1_3::Effect::TEXTURE_TICK), Eq(V1_0::EffectStrength::MEDIUM), - _)) - .Times(Exactly(1)) - .WillRepeatedly( - [](V1_3::Effect, V1_0::EffectStrength, MockIVibratorV1_3::perform_cb cb) { - cb(V1_0::Status::UNSUPPORTED_OPERATION, 0); - return hardware::Return<void>(); - }); - EXPECT_CALL(*mMockHal.get(), - perform_1_3(Eq(V1_3::Effect::TEXTURE_TICK), Eq(V1_0::EffectStrength::STRONG), - _)) - .Times(Exactly(2)) - .WillOnce([](V1_3::Effect, V1_0::EffectStrength, MockIVibratorV1_3::perform_cb cb) { - cb(V1_0::Status::BAD_VALUE, 0); - return hardware::Return<void>(); - }) - .WillRepeatedly( - [](V1_3::Effect, V1_0::EffectStrength, MockIVibratorV1_3::perform_cb) { - return hardware::Return<void>(hardware::Status::fromExceptionCode(-1)); - }); - } - - std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); - auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - - auto result = mWrapper->performEffect(Effect::TEXTURE_TICK, EffectStrength::LIGHT, callback); - ASSERT_TRUE(result.isOk()); - ASSERT_EQ(10ms, result.value()); - ASSERT_EQ(1, *callbackCounter.get()); - - result = mWrapper->performEffect(Effect::TEXTURE_TICK, EffectStrength::MEDIUM, callback); - ASSERT_TRUE(result.isUnsupported()); - - result = mWrapper->performEffect(Effect::TEXTURE_TICK, EffectStrength::STRONG, callback); - ASSERT_TRUE(result.isFailed()); - - result = mWrapper->performEffect(Effect::TEXTURE_TICK, EffectStrength::STRONG, callback); - ASSERT_TRUE(result.isFailed()); - - // Callback not triggered for unsupported and on failure - ASSERT_EQ(1, *callbackCounter.get()); -} |