Merge "Cleanup hide_pointer_indicators_for_secure_windows flag" into main
diff --git a/cmds/dumpstate/res/default_screenshot.png b/cmds/dumpstate/res/default_screenshot.png
index 10f36aa..1e14306 100644
--- a/cmds/dumpstate/res/default_screenshot.png
+++ b/cmds/dumpstate/res/default_screenshot.png
Binary files differ
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 36dcbca..b87ef2d 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -25,13 +25,8 @@
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 262f2e5..dc52c57 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 b943495..1a9993e 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);
+ return IVibrator::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);
-}
-
-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 9afa300..cae6909 100644
--- a/cmds/idlcli/vibrator/CommandAlwaysOnDisable.cpp
+++ b/cmds/idlcli/vibrator/CommandAlwaysOnDisable.cpp
@@ -51,21 +51,17 @@
}
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);
- return ret;
+ std::cout << "Status: " << status.getDescription() << std::endl;
+
+ return status.isOk() ? OK : ERROR;
}
int32_t mId;
diff --git a/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp b/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp
index bb7f9f2..410ca52 100644
--- a/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp
+++ b/cmds/idlcli/vibrator/CommandAlwaysOnEnable.cpp
@@ -72,21 +72,17 @@
}
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);
- return ret;
+ std::cout << "Status: " << status.getDescription() << std::endl;
+
+ return status.isOk() ? OK : ERROR;
}
int32_t mId;
diff --git a/cmds/idlcli/vibrator/CommandCompose.cpp b/cmds/idlcli/vibrator/CommandCompose.cpp
index eb9008b..41acb98 100644
--- a/cmds/idlcli/vibrator/CommandCompose.cpp
+++ b/cmds/idlcli/vibrator/CommandCompose.cpp
@@ -89,7 +89,7 @@
}
Status doMain(Args && /*args*/) override {
- auto hal = getHal<aidl::IVibrator>();
+ auto hal = getHal();
if (!hal) {
return UNAVAILABLE;
@@ -104,7 +104,7 @@
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 b8308ce..5f6bf86 100644
--- a/cmds/idlcli/vibrator/CommandComposePwle.cpp
+++ b/cmds/idlcli/vibrator/CommandComposePwle.cpp
@@ -163,7 +163,7 @@
}
Status doMain(Args && /*args*/) override {
- auto hal = getHal<aidl::IVibrator>();
+ auto hal = getHal();
if (!hal) {
return UNAVAILABLE;
@@ -178,7 +178,7 @@
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 6d3cf84..bd682ea 100644
--- a/cmds/idlcli/vibrator/CommandComposePwleV2.cpp
+++ b/cmds/idlcli/vibrator/CommandComposePwleV2.cpp
@@ -108,7 +108,7 @@
}
Status doMain(Args&& /*args*/) override {
- auto hal = getHal<aidl::IVibrator>();
+ auto hal = getHal();
if (!hal) {
return UNAVAILABLE;
@@ -123,7 +123,7 @@
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 aa01a11..44115e9 100644
--- a/cmds/idlcli/vibrator/CommandGetBandwidthAmplitudeMap.cpp
+++ b/cmds/idlcli/vibrator/CommandGetBandwidthAmplitudeMap.cpp
@@ -44,29 +44,38 @@
}
Status doMain(Args && /*args*/) override {
- std::string statusStr;
- std::vector<float> bandwidthAmplitude;
- float frequencyMinimumHz;
- float frequencyResolutionHz;
- Status ret;
+ auto hal = getHal();
- if (auto hal = getHal<aidl::IVibrator>()) {
- auto status =
- hal->call(&aidl::IVibrator::getBandwidthAmplitudeMap, &bandwidthAmplitude);
- statusStr = status.getDescription();
- ret = (status.isOk() ? OK : ERROR);
-
- status = hal->call(&aidl::IVibrator::getFrequencyMinimum, &frequencyMinimumHz);
- ret = (status.isOk() ? OK : ERROR);
-
- status =
- hal->call(&aidl::IVibrator::getFrequencyResolution, &frequencyResolutionHz);
- ret = (status.isOk() ? OK : ERROR);
- } else {
+ if (!hal) {
return UNAVAILABLE;
}
- std::cout << "Status: " << statusStr << std::endl;
+ std::vector<float> bandwidthAmplitude;
+ float frequencyMinimumHz;
+ float frequencyResolutionHz;
+
+ auto status = hal->getBandwidthAmplitudeMap(&bandwidthAmplitude);
+
+ if (!status.isOk()) {
+ std::cout << "Status: " << status.getDescription() << std::endl;
+ return ERROR;
+ }
+
+ status = hal->getFrequencyMinimum(&frequencyMinimumHz);
+
+ if (!status.isOk()) {
+ std::cout << "Status: " << status.getDescription() << std::endl;
+ return ERROR;
+ }
+
+ 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 @@
frequency += frequencyResolutionHz;
}
- return ret;
+ return OK;
}
};
diff --git a/cmds/idlcli/vibrator/CommandGetCapabilities.cpp b/cmds/idlcli/vibrator/CommandGetCapabilities.cpp
index 303a989..507d871 100644
--- a/cmds/idlcli/vibrator/CommandGetCapabilities.cpp
+++ b/cmds/idlcli/vibrator/CommandGetCapabilities.cpp
@@ -42,22 +42,19 @@
}
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 10508bd..1c1eb3c 100644
--- a/cmds/idlcli/vibrator/CommandGetCompositionDelayMax.cpp
+++ b/cmds/idlcli/vibrator/CommandGetCompositionDelayMax.cpp
@@ -44,22 +44,19 @@
}
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 900cb18..cfd4c53 100644
--- a/cmds/idlcli/vibrator/CommandGetCompositionSizeMax.cpp
+++ b/cmds/idlcli/vibrator/CommandGetCompositionSizeMax.cpp
@@ -44,22 +44,19 @@
}
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 504c648..2a61446 100644
--- a/cmds/idlcli/vibrator/CommandGetFrequencyMinimum.cpp
+++ b/cmds/idlcli/vibrator/CommandGetFrequencyMinimum.cpp
@@ -44,22 +44,19 @@
}
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 de35838..157d6bf 100644
--- a/cmds/idlcli/vibrator/CommandGetFrequencyResolution.cpp
+++ b/cmds/idlcli/vibrator/CommandGetFrequencyResolution.cpp
@@ -44,23 +44,19 @@
}
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 2edd0ca..2eb4510 100644
--- a/cmds/idlcli/vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp
+++ b/cmds/idlcli/vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp
@@ -46,26 +46,22 @@
}
Status doMain(Args&& /*args*/) override {
- std::string statusStr;
- std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
- Status ret;
+ auto hal = getHal();
- if (auto hal = getHal<aidl::IVibrator>()) {
- auto status = hal->call(&aidl::IVibrator::getFrequencyToOutputAccelerationMap,
- &frequencyToOutputAccelerationMap);
- statusStr = status.getDescription();
- ret = (status.isOk() ? OK : ERROR);
- } else {
+ 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 460d39e..c957f6b 100644
--- a/cmds/idlcli/vibrator/CommandGetPrimitiveDuration.cpp
+++ b/cmds/idlcli/vibrator/CommandGetPrimitiveDuration.cpp
@@ -57,22 +57,19 @@
}
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 b2c3551..c1b0278 100644
--- a/cmds/idlcli/vibrator/CommandGetPwleCompositionSizeMax.cpp
+++ b/cmds/idlcli/vibrator/CommandGetPwleCompositionSizeMax.cpp
@@ -44,22 +44,19 @@
}
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 9081973..ed00ba0 100644
--- a/cmds/idlcli/vibrator/CommandGetPwlePrimitiveDurationMax.cpp
+++ b/cmds/idlcli/vibrator/CommandGetPwlePrimitiveDurationMax.cpp
@@ -44,22 +44,19 @@
}
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 cca072c..f780b8b 100644
--- a/cmds/idlcli/vibrator/CommandGetPwleV2CompositionSizeMax.cpp
+++ b/cmds/idlcli/vibrator/CommandGetPwleV2CompositionSizeMax.cpp
@@ -44,22 +44,19 @@
}
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 dbbfe1a..e84e969 100644
--- a/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp
+++ b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp
@@ -44,23 +44,19 @@
}
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 09225c4..448fd2a 100644
--- a/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp
+++ b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp
@@ -44,23 +44,19 @@
}
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 a2681e9..e04bad9 100644
--- a/cmds/idlcli/vibrator/CommandGetQFactor.cpp
+++ b/cmds/idlcli/vibrator/CommandGetQFactor.cpp
@@ -42,22 +42,19 @@
}
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 81a6391..e222ea6 100644
--- a/cmds/idlcli/vibrator/CommandGetResonantFrequency.cpp
+++ b/cmds/idlcli/vibrator/CommandGetResonantFrequency.cpp
@@ -44,22 +44,19 @@
}
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 edfcd91..9b05540 100644
--- a/cmds/idlcli/vibrator/CommandGetSupportedAlwaysOnEffects.cpp
+++ b/cmds/idlcli/vibrator/CommandGetSupportedAlwaysOnEffects.cpp
@@ -44,25 +44,22 @@
}
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 b326e07..f95f682 100644
--- a/cmds/idlcli/vibrator/CommandGetSupportedBraking.cpp
+++ b/cmds/idlcli/vibrator/CommandGetSupportedBraking.cpp
@@ -44,25 +44,22 @@
}
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 7658f22..05de1b8 100644
--- a/cmds/idlcli/vibrator/CommandGetSupportedEffects.cpp
+++ b/cmds/idlcli/vibrator/CommandGetSupportedEffects.cpp
@@ -44,25 +44,22 @@
}
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 d101681..0f33f0f 100644
--- a/cmds/idlcli/vibrator/CommandGetSupportedPrimitives.cpp
+++ b/cmds/idlcli/vibrator/CommandGetSupportedPrimitives.cpp
@@ -44,25 +44,22 @@
}
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 cedb9fe..e55b44a 100644
--- a/cmds/idlcli/vibrator/CommandOff.cpp
+++ b/cmds/idlcli/vibrator/CommandOff.cpp
@@ -42,24 +42,17 @@
}
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 8212fc1..856c219 100644
--- a/cmds/idlcli/vibrator/CommandOn.cpp
+++ b/cmds/idlcli/vibrator/CommandOn.cpp
@@ -67,34 +67,27 @@
}
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();
-
- int32_t cap;
- hal->call(&aidl::IVibrator::getCapabilities, &cap);
-
- if (mBlocking && (cap & aidl::IVibrator::CAP_ON_CALLBACK)) {
- callback = ndk::SharedRefBase::make<VibratorCallback>();
- }
-
- auto status = hal->call(&aidl::IVibrator::on, mDuration, callback);
-
- 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 {
+ if (!hal) {
return UNAVAILABLE;
}
- if (ret == OK && mBlocking) {
+ std::shared_ptr<VibratorCallback> callback;
+
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+
+ int32_t cap;
+ hal->getCapabilities(&cap);
+
+ if (mBlocking && (cap & aidl::IVibrator::CAP_ON_CALLBACK)) {
+ callback = ndk::SharedRefBase::make<VibratorCallback>();
+ }
+
+ auto status = hal->on(mDuration, callback);
+
+ if (status.isOk() && mBlocking) {
if (callback) {
callback->waitForComplete();
} else {
@@ -102,9 +95,9 @@
}
}
- 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 c897686..0a354e2 100644
--- a/cmds/idlcli/vibrator/CommandPerform.cpp
+++ b/cmds/idlcli/vibrator/CommandPerform.cpp
@@ -28,34 +28,6 @@
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 @@
}
Status doMain(Args && /*args*/) override {
- std::string statusStr;
- uint32_t lengthMs;
- Status ret;
- std::shared_ptr<VibratorCallback> callback;
+ auto hal = getHal();
- if (auto hal = getHal<aidl::IVibrator>()) {
- ABinderProcess_setThreadPoolMaxThreadCount(1);
- ABinderProcess_startThreadPool();
-
- int32_t cap;
- hal->call(&aidl::IVibrator::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);
-
- 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;
- }
-
- statusStr = toString(status);
- ret = hidlRet.isOk() && status == V1_0::Status::OK ? OK : ERROR;
+ if (!hal) {
+ return UNAVAILABLE;
}
- if (ret == OK && mBlocking) {
+ uint32_t lengthMs;
+ std::shared_ptr<VibratorCallback> callback;
+
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+
+ 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->perform(mEffect, mStrength, callback, &aidlLengthMs);
+
+ lengthMs = static_cast<uint32_t>(aidlLengthMs);
+
+ if (status.isOk() && mBlocking) {
if (callback) {
callback->waitForComplete();
} else {
@@ -169,10 +111,10 @@
}
}
- 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 8b8058c..8050723 100644
--- a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
+++ b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
@@ -50,25 +50,17 @@
}
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::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 {
+ if (!hal) {
return UNAVAILABLE;
}
- std::cout << "Status: " << statusStr << std::endl;
+ auto status = hal->setAmplitude(static_cast<float>(mAmplitude) / UINT8_MAX);
- return ret;
+ std::cout << "Status: " << status.getDescription() << std::endl;
+
+ return status.isOk() ? OK : ERROR;
}
uint8_t mAmplitude;
diff --git a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
index 1795793..8f8d4b7 100644
--- a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
+++ b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
@@ -48,24 +48,17 @@
}
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::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 {
+ if (!hal) {
return UNAVAILABLE;
}
- std::cout << "Status: " << statusStr << std::endl;
+ auto status = hal->setExternalControl(mEnable);
- return ret;
+ std::cout << "Status: " << status.getDescription() << std::endl;
+
+ return status.isOk() ? OK : ERROR;
}
bool mEnable;
diff --git a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
index cdc529a..31ee954 100644
--- a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
+++ b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
@@ -42,15 +42,22 @@
}
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 ed15d76..f0c542c 100644
--- a/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
+++ b/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
@@ -42,15 +42,22 @@
}
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 0ac5266..f320504 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -119,12 +119,24 @@
}
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 {
+ 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 bdb1413..4494e32 100644
--- a/include/android/system_health.h
+++ b/include/android/system_health.h
@@ -316,8 +316,6 @@
/**
* 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 @@
/**
* 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 16023ff..1f3a45a 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -188,7 +188,9 @@
}
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 @@
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 af37bf2..c9f92da 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 @@
// 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 48c0ea6..1949cbb 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 @@
//
// 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 64b1be2..8177fb0 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -248,9 +248,18 @@
#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 09688a2..411b9de 100644
--- a/libs/binder/rust/rpcbinder/src/session.rs
+++ b/libs/binder/rust/rpcbinder/src/session.rs
@@ -195,11 +195,13 @@
/// 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 @@
self.as_ptr(),
Some(request_fd_wrapper),
param,
+ Some(param_delete_fd_wrapper),
))
};
Self::get_interface(service)
@@ -225,13 +228,18 @@
}
}
-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 cac054e..457eaa5 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -109,6 +109,9 @@
"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 02e69cc..11aa768 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 @@
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 @@
}
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 ef1b7c3..40fc218 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 @@
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 5ab31db..b5fa321 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -281,6 +281,7 @@
"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 43855da..ad95d1a 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -55,6 +55,28 @@
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 @@
transformToDisplayInverse(false),
crop({0, 0, -1, -1}),
dataspace(ui::Dataspace::UNKNOWN),
- surfaceDamageRegion(),
api(-1),
colorTransform(mat4()),
bgColor(0),
@@ -117,19 +138,21 @@
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 @@
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 @@
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 @@
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 @@
}
if (other.what & eTransparentRegionChanged) {
what |= eTransparentRegionChanged;
- transparentRegion = other.transparentRegion;
+ mNotDefCmpState.transparentRegion = other.mNotDefCmpState.transparentRegion;
}
if (other.what & eFlagsChanged) {
what |= eFlagsChanged;
@@ -615,11 +640,13 @@
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 @@
}
if (other.what & eSurfaceDamageRegionChanged) {
what |= eSurfaceDamageRegionChanged;
- surfaceDamageRegion = other.surfaceDamageRegion;
+ mNotDefCmpState.surfaceDamageRegion = other.mNotDefCmpState.surfaceDamageRegion;
}
if (other.what & eApiChanged) {
what |= eApiChanged;
@@ -684,7 +711,8 @@
}
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 bb7184f..e407a63 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1391,11 +1391,16 @@
// ---------------------------------------------------------------------------
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 0000000..9e09bc2
--- /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 da47ee2..9b2f089 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -67,6 +67,11 @@
frameRateOverride = 1 << 1,
}
+ enum OptimizationPolicy {
+ optimizeForPower = 0,
+ optimizeForPerformance = 1,
+ }
+
/**
* Signal that we're done booting.
* Requires ACCESS_SURFACE_FLINGER permission
@@ -97,6 +102,10 @@
* 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 @@
* 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 7ee291d..6381db2 100644
--- a/libs/gui/include/gui/LayerMetadata.h
+++ b/libs/gui/include/gui/LayerMetadata.h
@@ -44,6 +44,10 @@
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 c2680a4..369d3d1 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 60f16ae..4fda8de 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -345,8 +345,6 @@
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 @@
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 0000000..4358227
--- /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 420dc21..9ac49c0 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -268,6 +268,7 @@
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 @@
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 90d91ac..534f05e 100644
--- a/libs/gui/libgui_flags.aconfig
+++ b/libs/gui/libgui_flags.aconfig
@@ -77,14 +77,6 @@
} # 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 87051a7..e20345d 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -90,6 +90,7 @@
"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 eb55e3b..e7690e2 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -687,10 +687,11 @@
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 0000000..179b264
--- /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 efedf76..de5e428 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -134,13 +134,6 @@
}
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 9f64d2c..f43694e 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -803,8 +803,7 @@
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 4164c4b..f007427 100644
--- a/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp
+++ b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp
@@ -58,9 +58,6 @@
)");
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
similarity index 93%
rename from services/surfaceflinger/Utils/RingBuffer.h
rename to libs/ui/include/ui/RingBuffer.h
index 215472b..31d5a95 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 @@
~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 @@
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 2d8a1e3..2b11786 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -144,6 +144,17 @@
}
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 0000000..9839492
--- /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 04c525e..7faf361 100644
--- a/opengl/libs/EGL/MultifileBlobCache.cpp
+++ b/opengl/libs/EGL/MultifileBlobCache.cpp
@@ -356,7 +356,7 @@
// 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 3b5407b..842a0c4 100644
--- a/services/gpuservice/feature_override/Android.bp
+++ b/services/gpuservice/feature_override/Android.bp
@@ -69,6 +69,7 @@
name: "libfeatureoverride",
defaults: [
"libfeatureoverride_deps",
+ "libvkjson_deps",
],
srcs: [
":feature_config_proto_definitions",
@@ -85,6 +86,9 @@
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 a16bfa8..26ff84a 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 @@
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 @@
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 @@
// 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 @@
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 4d4bf28..f285187 100644
--- a/services/gpuservice/feature_override/proto/feature_config.proto
+++ b/services/gpuservice/feature_override/proto/feature_config.proto
@@ -21,14 +21,43 @@
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 65a1b58..66556cd 100644
--- a/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp
+++ b/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp
@@ -70,14 +70,14 @@
};
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 @@
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 @@
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 @@
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 726779e..44a6f78 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 @@
{
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 @@
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 805bf45..f8ab830 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -674,7 +674,13 @@
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::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 845cab0..58df692 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 @@
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 @@
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 0d6e102..6a25937 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 @@
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 @@
// 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 20ed74f..f38fd7b 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 @@
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 dd46bbc..d796af1 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 @@
}
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 @@
}
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 @@
/*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 @@
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 8deff6b..4d36db8 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 @@
*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 @@
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 @@
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 4ef0be8..45fc6bf 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -348,6 +348,8 @@
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 353011a..c6246d9 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 @@
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 c4257a8..dcb148f 100644
--- a/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp
@@ -198,10 +198,6 @@
ASSERT_EQ(token, *receivedToken);
}
-void FakeInputDispatcherPolicy::setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
- mInterceptKeyTimeout = timeout;
-}
-
std::chrono::nanoseconds FakeInputDispatcherPolicy::getKeyWaitingForEventsTimeout() {
return 500ms;
}
@@ -210,8 +206,9 @@
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 @@
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 @@
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 c387eac..b151686 100644
--- a/services/inputflinger/tests/FakeInputDispatcherPolicy.h
+++ b/services/inputflinger/tests/FakeInputDispatcherPolicy.h
@@ -96,10 +96,6 @@
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 @@
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 @@
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 2b9b470..835b677 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -5491,7 +5491,8 @@
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 @@
// 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 @@
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 @@
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 @@
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 06d60ce..d4e4bb0 100644
--- a/services/inputflinger/tests/InterfaceMocks.h
+++ b/services/inputflinger/tests/InterfaceMocks.h
@@ -50,6 +50,8 @@
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 40bbd34..d4b15bc 100644
--- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp
+++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
@@ -691,32 +691,163 @@
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 b691098..2b469c5 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -358,6 +358,17 @@
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 bba7389..9a59039 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -360,6 +360,7 @@
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 452b428..6308973 100644
--- a/services/sensorservice/sensorservice_flags.aconfig
+++ b/services/sensorservice/sensorservice_flags.aconfig
@@ -37,4 +37,14 @@
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 f934cb2..e42b9b1 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 @@
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 b290823..2081cd5 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -243,17 +243,9 @@
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 @@
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 @@
};
++incomingLayerIter;
}
-
- if (currentLayerIter->getLayerCount() > 1) {
- ++mInvalidatedCachedSetAges[currentLayerIter->getAge()];
- }
++currentLayerIter;
skipCount -= layerCount;
@@ -382,7 +369,6 @@
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 a086aee..87a677c 100644
--- a/services/surfaceflinger/Display/DisplayModeController.cpp
+++ b/services/surfaceflinger/Display/DisplayModeController.cpp
@@ -97,9 +97,7 @@
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 @@
// 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 e8b09b0..07770f1 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -51,6 +51,17 @@
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 @@
dumper.dump("name"sv, '"' + mDisplayName + '"');
dumper.dump("powerMode"sv, mPowerMode);
+ dumper.dump("optimizationPolicy"sv, mOptimizationPolicy);
if (mRefreshRateSelector) {
mRefreshRateSelector->dump(dumper);
@@ -305,6 +317,15 @@
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 b5a543a..be37429 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -93,6 +93,11 @@
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 @@
// 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 @@
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 01f382f..8d16a6b 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -439,11 +439,8 @@
// 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 545ed19..14088a6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -145,7 +145,7 @@
case HotplugEvent::Disconnected:
return onHotplugDisconnect(hwcDisplayId);
case HotplugEvent::LinkUnstable:
- return {};
+ return onHotplugLinkTrainingFailure(hwcDisplayId);
}
}
@@ -1245,6 +1245,16 @@
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 2c0aa3d..472411c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -544,6 +544,7 @@
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 1f0d5d0..a80bdb4 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -41,7 +41,7 @@
if (forceFullDamage) {
outSurfaceDamageRegion = Region::INVALID_REGION;
} else {
- outSurfaceDamageRegion = requested.surfaceDamageRegion;
+ outSurfaceDamageRegion = requested.getSurfaceDamageRegion();
}
}
@@ -376,7 +376,7 @@
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 @@
}
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 86ef6ca..28a6031 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -1090,7 +1090,7 @@
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 @@
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 @@
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 58c235e..d322a61 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -63,8 +63,11 @@
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 @@
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 @@
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 @@
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 @@
}
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::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 @@
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 614f33f..758b111 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 @@
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 6af0f59..081bb22 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -288,7 +288,7 @@
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 44cd319..84b1a73 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -447,7 +447,7 @@
}
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 cd7210c..788448d 100644
--- a/services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp
+++ b/services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp
@@ -515,7 +515,7 @@
}
void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
- mExpectedPresentTimes.append(expectedPresentTime);
+ mExpectedPresentTimes.next() = expectedPresentTime;
}
void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
@@ -532,7 +532,7 @@
}
void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
- mCommitStartTimes.append(commitStartTime);
+ mCommitStartTimes.next() = commitStartTime;
}
void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
@@ -579,7 +579,7 @@
}
// 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 @@
// 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 @@
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 540a9df..b97160a 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 @@
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 @@
// 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 4da76f6..e587178 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -986,7 +986,7 @@
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::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 3fdddac..81389e7 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -386,7 +386,7 @@
// 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 b9c79df..bb04d12 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -208,7 +208,8 @@
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 813d4de..ff461d2 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 @@
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 35cb63e..9d759df 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -384,6 +384,7 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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::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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
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::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 @@
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::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 3f454ba..39e237b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -211,11 +211,9 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 2676ca6..3297c16 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -139,7 +139,8 @@
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 @@
}
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 @@
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 @@
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 5cf4244..84d837c 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -102,11 +102,10 @@
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 abde524..8d1b51b 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -139,7 +139,6 @@
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 @@
/// 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 6295c5b..603139e 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -74,7 +74,6 @@
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 73dfa9f..4afcd00 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -77,7 +77,7 @@
}
}
-int main(int, char**) {
+int main() {
signal(SIGPIPE, SIG_IGN);
hardware::configureRpcThreadpool(1 /* maxThreads */,
@@ -91,9 +91,7 @@
// 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 @@
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 0ad5ac9..bfafb65 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -483,6 +483,16 @@
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 0017300..e2ac233 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -82,6 +82,11 @@
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 7910e77..82390ac 100644
--- a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
+++ b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
@@ -265,9 +265,8 @@
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 @@
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 @@
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 @@
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 9ece312..c342e1e 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -468,7 +468,7 @@
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 7aad84b..3ed038b 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -1642,8 +1642,8 @@
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 @@
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, 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, 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, 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, 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, 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, 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 1fc874d..cbcfe03 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -254,18 +254,43 @@
}
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 aadff76..aa5b786 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
@@ -141,7 +141,11 @@
// --------------------------------------------------------------------
// 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 62f1a52..525a940 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -407,8 +407,6 @@
}
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, 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, 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 b0cda0f..49972b0 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
@@ -224,8 +224,6 @@
}
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, 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 8084450..bb377ba 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -399,12 +399,16 @@
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 @@
}
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 a221d5e..ccf6a9c 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -444,40 +444,8 @@
}
}
-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 4735ae5..ed03cfc 100644
--- a/services/vibratorservice/Android.bp
+++ b/services/vibratorservice/Android.bp
@@ -42,14 +42,9 @@
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 283a5f0..302e3e1 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::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 @@
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 @@
}
}
- 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 536a6b3..5d4c17d 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::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 @@
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 @@
frequencyToOutputAccelerationMap);
}
-std::shared_ptr<Aidl::IVibrator> AidlHalWrapper::getHal() {
+std::shared_ptr<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::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 494f88f..31b6ed0 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 @@
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 @@
}
}
+ ALOGV("VibratorManager HAL service not available.");
gHalExists = false;
return std::make_shared<LegacyManagerHalWrapper>();
}
@@ -150,10 +154,10 @@
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 3db8ff8..bab3f58 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 915d6c7..6fc5cf3 100644
--- a/services/vibratorservice/benchmarks/Android.bp
+++ b/services/vibratorservice/benchmarks/Android.bp
@@ -29,15 +29,10 @@
],
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 9a39ad4..0652278 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 @@
: 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 @@
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 @@
}
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 @@
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 92527eb..038248e 100644
--- a/services/vibratorservice/test/Android.bp
+++ b/services/vibratorservice/test/Android.bp
@@ -29,10 +29,6 @@
"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 @@
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 04dbe4e..0000000
--- 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 b0a6537..0000000
--- 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 dfe3fa0..0000000
--- 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 8624332..0000000
--- 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());
-}