Merge "Optimize BLAST buffer releases via Unix sockets" into main
diff --git a/Android.bp b/Android.bp
index 2520a71..4befb1b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -39,6 +39,11 @@
cc_library_headers {
name: "native_headers",
host_supported: true,
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
export_include_dirs: [
"include/",
],
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index c18d3f5..50c2cd8 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -24,7 +24,7 @@
cc_defaults {
name: "idlcli-defaults",
shared_libs: [
- "android.hardware.vibrator-V2-ndk",
+ "android.hardware.vibrator-V3-ndk",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h
index e100eac..b943495 100644
--- a/cmds/idlcli/vibrator.h
+++ b/cmds/idlcli/vibrator.h
@@ -49,7 +49,7 @@
template <typename I>
inline auto getService(std::string name) {
const auto instance = std::string() + I::descriptor + "/" + name;
- auto vibBinder = ndk::SpAIBinder(AServiceManager_getService(instance.c_str()));
+ auto vibBinder = ndk::SpAIBinder(AServiceManager_checkService(instance.c_str()));
return I::fromBinder(vibBinder);
}
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 0f251d2..d85182d 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -112,13 +112,15 @@
std::string iface;
std::string instance;
- static bool fill(const std::string& name, AidlName* aname) {
+ static bool fill(const std::string& name, AidlName* aname, bool logError) {
size_t firstSlash = name.find('/');
size_t lastDot = name.rfind('.', firstSlash);
if (firstSlash == std::string::npos || lastDot == std::string::npos) {
- ALOGE("VINTF HALs require names in the format type/instance (e.g. "
- "some.package.foo.IFoo/default) but got: %s",
- name.c_str());
+ if (logError) {
+ ALOGE("VINTF HALs require names in the format type/instance (e.g. "
+ "some.package.foo.IFoo/default) but got: %s",
+ name.c_str());
+ }
return false;
}
aname->package = name.substr(0, lastDot);
@@ -151,7 +153,7 @@
}
AidlName aname;
- if (!AidlName::fill(name, &aname)) return false;
+ if (!AidlName::fill(name, &aname, true)) return false;
bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
if (mwd.manifest->hasAidlInstance(aname.package, aname.iface, aname.instance)) {
@@ -209,7 +211,7 @@
}
AidlName aname;
- if (!AidlName::fill(name, &aname)) return std::nullopt;
+ if (!AidlName::fill(name, &aname, true)) return std::nullopt;
std::optional<std::string> updatableViaApex;
@@ -251,7 +253,7 @@
static std::optional<std::string> getVintfAccessorName(const std::string& name) {
AidlName aname;
- if (!AidlName::fill(name, &aname)) return std::nullopt;
+ if (!AidlName::fill(name, &aname, false)) return std::nullopt;
std::optional<std::string> accessor;
forEachManifest([&](const ManifestWithDescription& mwd) {
@@ -270,7 +272,7 @@
static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
AidlName aname;
- if (!AidlName::fill(name, &aname)) return std::nullopt;
+ if (!AidlName::fill(name, &aname, true)) return std::nullopt;
std::optional<std::string> ip;
std::optional<uint64_t> port;
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 21dc5c1..49def82 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -802,6 +802,10 @@
}
void RpcSession::setSessionSpecificRoot(const sp<IBinder>& sessionSpecificRoot) {
+ LOG_ALWAYS_FATAL_IF(mSessionSpecificRootObject != nullptr,
+ "Session specific root object already set");
+ LOG_ALWAYS_FATAL_IF(mForServer != nullptr,
+ "Session specific root object cannot be set for a server");
mSessionSpecificRootObject = sessionSpecificRoot;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 87fd448..685391e 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -44,8 +44,6 @@
#include <gui/AidlStatusUtil.h>
#include <gui/BufferItem.h>
-#include <gui/IProducerListener.h>
-
#include <gui/ISurfaceComposer.h>
#include <gui/LayerState.h>
#include <private/gui/ComposerService.h>
@@ -1860,30 +1858,31 @@
}
int Surface::connect(int api) {
- static sp<IProducerListener> listener = new StubProducerListener();
+ static sp<SurfaceListener> listener = new StubSurfaceListener();
return connect(api, listener);
}
-int Surface::connect(int api, const sp<IProducerListener>& listener) {
+int Surface::connect(int api, const sp<SurfaceListener>& listener) {
return connect(api, listener, false);
}
int Surface::connect(
int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) {
- if (sListener != nullptr) {
- mListenerProxy = new ProducerListenerProxy(this, sListener);
- }
- return connect(api, mListenerProxy, reportBufferRemoval);
+ return connect(api, sListener, reportBufferRemoval);
}
-int Surface::connect(
- int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) {
+int Surface::connect(int api, const sp<SurfaceListener>& listener, bool reportBufferRemoval) {
ATRACE_CALL();
ALOGV("Surface::connect");
Mutex::Autolock lock(mMutex);
IGraphicBufferProducer::QueueBufferOutput output;
mReportRemovedBuffers = reportBufferRemoval;
- int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
+ if (listener != nullptr) {
+ mListenerProxy = new ProducerListenerProxy(this, listener);
+ }
+
+ int err =
+ mGraphicBufferProducer->connect(mListenerProxy, api, mProducerControlledByApp, &output);
if (err == NO_ERROR) {
mDefaultWidth = output.width;
mDefaultHeight = output.height;
@@ -1911,7 +1910,6 @@
return err;
}
-
int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) {
ATRACE_CALL();
ALOGV("Surface::disconnect");
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index bdcaaf2..1245501 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -56,6 +56,16 @@
virtual bool needsReleaseNotify() = 0;
virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) = 0;
+ virtual void onBufferDetached(int slot) = 0;
+};
+
+class StubSurfaceListener : public SurfaceListener {
+public:
+ virtual ~StubSurfaceListener() {}
+ virtual void onBufferReleased() override {}
+ virtual bool needsReleaseNotify() { return false; }
+ virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& /*buffers*/) override {}
+ virtual void onBufferDetached(int /*slot*/) override {}
};
/*
@@ -357,15 +367,13 @@
virtual int unlockAndPost();
virtual int query(int what, int* value) const;
- virtual int connect(int api, const sp<IProducerListener>& listener);
+ virtual int connect(int api, const sp<SurfaceListener>& listener);
// When reportBufferRemoval is true, clients must call getAndFlushRemovedBuffers to fetch
// GraphicBuffers removed from this surface after a dequeueBuffer, detachNextBuffer or
// attachBuffer call. This allows clients with their own buffer caches to free up buffers no
// longer in use by this surface.
- virtual int connect(
- int api, const sp<IProducerListener>& listener,
- bool reportBufferRemoval);
+ virtual int connect(int api, const sp<SurfaceListener>& listener, bool reportBufferRemoval);
virtual int detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence);
virtual int attachBuffer(ANativeWindowBuffer*);
@@ -422,6 +430,8 @@
return mSurfaceListener->needsReleaseNotify();
}
+ virtual void onBufferDetached(int slot) { mSurfaceListener->onBufferDetached(slot); }
+
virtual void onBuffersDiscarded(const std::vector<int32_t>& slots);
private:
wp<Surface> mParent;
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 946ff05..6852589 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -1269,6 +1269,20 @@
}
};
+class TestSurfaceListener : public SurfaceListener {
+public:
+ sp<IGraphicBufferProducer> mIgbp;
+ TestSurfaceListener(const sp<IGraphicBufferProducer>& igbp) : mIgbp(igbp) {}
+ void onBufferReleased() override {
+ sp<GraphicBuffer> buffer;
+ sp<Fence> fence;
+ mIgbp->detachNextBuffer(&buffer, &fence);
+ }
+ bool needsReleaseNotify() override { return true; }
+ void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& /*buffers*/) override {}
+ void onBufferDetached(int /*slot*/) {}
+};
+
TEST_F(BLASTBufferQueueTest, CustomProducerListener) {
BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
sp<IGraphicBufferProducer> igbProducer = adapter.getIGraphicBufferProducer();
@@ -1327,7 +1341,7 @@
ASSERT_EQ(ui::Transform::ROT_0, static_cast<ui::Transform::RotationFlags>(transformHint));
ASSERT_EQ(NO_ERROR,
- surface->connect(NATIVE_WINDOW_API_CPU, new TestProducerListener(igbProducer)));
+ surface->connect(NATIVE_WINDOW_API_CPU, new TestSurfaceListener(igbProducer)));
// After connecting to the surface, we should get the correct hint.
surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ace4423..f7a8212 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -27,7 +27,6 @@
#include <configstore/Utils.h>
#include <gui/AidlStatusUtil.h>
#include <gui/BufferItemConsumer.h>
-#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
@@ -82,7 +81,7 @@
virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) {
mDiscardedBuffers.insert(mDiscardedBuffers.end(), buffers.begin(), buffers.end());
}
-
+ virtual void onBufferDetached(int /*slot*/) {}
int getReleaseNotifyCount() const {
return mBuffersReleased;
}
@@ -491,7 +490,7 @@
sp<Surface> surface = new Surface(producer);
sp<ANativeWindow> window(surface);
- sp<StubProducerListener> listener = new StubProducerListener();
+ sp<StubSurfaceListener> listener = new StubSurfaceListener();
ASSERT_EQ(OK, surface->connect(
NATIVE_WINDOW_API_CPU,
/*listener*/listener,
@@ -2154,7 +2153,7 @@
sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
sp<Surface> surface = new Surface(producer);
sp<ANativeWindow> window(surface);
- sp<StubProducerListener> listener = new StubProducerListener();
+ sp<StubSurfaceListener> listener = new StubSurfaceListener();
ASSERT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, /*listener*/listener,
/*reportBufferRemoval*/false));
@@ -2206,7 +2205,7 @@
sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
sp<Surface> surface = new Surface(producer);
sp<ANativeWindow> window(surface);
- sp<StubProducerListener> listener = new StubProducerListener();
+ sp<StubSurfaceListener> listener = new StubSurfaceListener();
ASSERT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, /*listener*/listener,
/*reportBufferRemoval*/false));
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index e11adb8..e48e94f 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -517,10 +517,10 @@
// --- RawAbsoluteAxisInfo ---
-std::ostream& operator<<(std::ostream& out, const std::optional<RawAbsoluteAxisInfo>& info) {
- if (info) {
- out << "min=" << info->minValue << ", max=" << info->maxValue << ", flat=" << info->flat
- << ", fuzz=" << info->fuzz << ", resolution=" << info->resolution;
+std::ostream& operator<<(std::ostream& out, const RawAbsoluteAxisInfo& info) {
+ if (info.valid) {
+ out << "min=" << info.minValue << ", max=" << info.maxValue << ", flat=" << info.flat
+ << ", fuzz=" << info.fuzz << ", resolution=" << info.resolution;
} else {
out << "unknown range";
}
@@ -649,6 +649,7 @@
continue;
}
auto& [axisInfo, value] = absState[axis];
+ axisInfo.valid = true;
axisInfo.minValue = info.minimum;
axisInfo.maxValue = info.maximum;
axisInfo.flat = info.flat;
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 657126a..feae6b6 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -71,14 +71,18 @@
/* Describes an absolute axis. */
struct RawAbsoluteAxisInfo {
+ bool valid{false}; // true if the information is valid, false otherwise
+
int32_t minValue{}; // minimum value
int32_t maxValue{}; // maximum value
int32_t flat{}; // center flat position, eg. flat == 8 means center is between -8 and 8
int32_t fuzz{}; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
int32_t resolution{}; // resolution in units per mm or radians per mm
+
+ inline void clear() { *this = RawAbsoluteAxisInfo(); }
};
-std::ostream& operator<<(std::ostream& out, const std::optional<RawAbsoluteAxisInfo>& info);
+std::ostream& operator<<(std::ostream& out, const RawAbsoluteAxisInfo& info);
/*
* Input device classes.
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index f2fdc37..086c26f 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -305,17 +305,22 @@
inline int32_t getDeviceControllerNumber() const {
return mEventHub->getDeviceControllerNumber(mId);
}
- inline std::optional<RawAbsoluteAxisInfo> getAbsoluteAxisInfo(int32_t code) const {
+ inline status_t getAbsoluteAxisInfo(int32_t code, RawAbsoluteAxisInfo* axisInfo) const {
std::optional<RawAbsoluteAxisInfo> info = mEventHub->getAbsoluteAxisInfo(mId, code);
+ if (!info.has_value()) {
+ axisInfo->clear();
+ return NAME_NOT_FOUND;
+ }
+ *axisInfo = *info;
// Validate axis info for InputDevice.
- if (info && info->minValue == info->maxValue) {
+ if (axisInfo->valid && axisInfo->minValue == axisInfo->maxValue) {
// Historically, we deem axes with the same min and max values as invalid to avoid
// dividing by zero when scaling by max - min.
// TODO(b/291772515): Perform axis info validation on a per-axis basis when it is used.
- return std::nullopt;
+ axisInfo->valid = false;
}
- return info;
+ return OK;
}
inline bool hasRelativeAxis(int32_t code) const {
return mEventHub->hasRelativeAxis(mId, code);
@@ -430,7 +435,8 @@
}
inline bool hasAbsoluteAxis(int32_t code) const {
- return mEventHub->getAbsoluteAxisInfo(mId, code).has_value();
+ std::optional<RawAbsoluteAxisInfo> info = mEventHub->getAbsoluteAxisInfo(mId, code);
+ return info.has_value() && info->valid;
}
inline bool isKeyPressed(int32_t scanCode) const {
return mEventHub->getScanCodeState(mId, scanCode) == AKEY_STATE_DOWN;
diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
index c8e7790..90685de 100644
--- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
+++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
@@ -16,7 +16,6 @@
#include "CapturedTouchpadEventConverter.h"
-#include <optional>
#include <sstream>
#include <android-base/stringprintf.h>
@@ -54,33 +53,32 @@
mMotionAccumulator(motionAccumulator),
mHasTouchMinor(deviceContext.hasAbsoluteAxis(ABS_MT_TOUCH_MINOR)),
mHasToolMinor(deviceContext.hasAbsoluteAxis(ABS_MT_WIDTH_MINOR)) {
- if (std::optional<RawAbsoluteAxisInfo> orientation =
- deviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION);
- orientation) {
- if (orientation->maxValue > 0) {
- mOrientationScale = M_PI_2 / orientation->maxValue;
- } else if (orientation->minValue < 0) {
- mOrientationScale = -M_PI_2 / orientation->minValue;
+ RawAbsoluteAxisInfo orientationInfo;
+ deviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &orientationInfo);
+ if (orientationInfo.valid) {
+ if (orientationInfo.maxValue > 0) {
+ mOrientationScale = M_PI_2 / orientationInfo.maxValue;
+ } else if (orientationInfo.minValue < 0) {
+ mOrientationScale = -M_PI_2 / orientationInfo.minValue;
}
}
// TODO(b/275369880): support touch.pressure.calibration and .scale properties when captured.
- if (std::optional<RawAbsoluteAxisInfo> pressure =
- deviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE);
- pressure && pressure->maxValue > 0) {
- mPressureScale = 1.0 / pressure->maxValue;
+ RawAbsoluteAxisInfo pressureInfo;
+ deviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE, &pressureInfo);
+ if (pressureInfo.valid && pressureInfo.maxValue > 0) {
+ mPressureScale = 1.0 / pressureInfo.maxValue;
}
- std::optional<RawAbsoluteAxisInfo> touchMajor =
- deviceContext.getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR);
- std::optional<RawAbsoluteAxisInfo> toolMajor =
- deviceContext.getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR);
- mHasTouchMajor = touchMajor.has_value();
- mHasToolMajor = toolMajor.has_value();
- if (mHasTouchMajor && touchMajor->maxValue != 0) {
- mSizeScale = 1.0f / touchMajor->maxValue;
- } else if (mHasToolMajor && toolMajor->maxValue != 0) {
- mSizeScale = 1.0f / toolMajor->maxValue;
+ RawAbsoluteAxisInfo touchMajorInfo, toolMajorInfo;
+ deviceContext.getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &touchMajorInfo);
+ deviceContext.getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &toolMajorInfo);
+ mHasTouchMajor = touchMajorInfo.valid;
+ mHasToolMajor = toolMajorInfo.valid;
+ if (mHasTouchMajor && touchMajorInfo.maxValue != 0) {
+ mSizeScale = 1.0f / touchMajorInfo.maxValue;
+ } else if (mHasToolMajor && toolMajorInfo.maxValue != 0) {
+ mSizeScale = 1.0f / toolMajorInfo.maxValue;
}
}
@@ -115,13 +113,15 @@
tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MAJOR, ABS_MT_WIDTH_MAJOR);
tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MINOR, ABS_MT_WIDTH_MINOR);
- if (mDeviceContext.hasAbsoluteAxis(ABS_MT_PRESSURE)) {
+ RawAbsoluteAxisInfo pressureInfo;
+ mDeviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE, &pressureInfo);
+ if (pressureInfo.valid) {
info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, SOURCE, 0, 1, 0, 0, 0);
}
- if (std::optional<RawAbsoluteAxisInfo> orientation =
- mDeviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION);
- orientation && (orientation->maxValue > 0 || orientation->minValue < 0)) {
+ RawAbsoluteAxisInfo orientationInfo;
+ mDeviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &orientationInfo);
+ if (orientationInfo.valid && (orientationInfo.maxValue > 0 || orientationInfo.minValue < 0)) {
info.addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, SOURCE, -M_PI_2, M_PI_2, 0, 0, 0);
}
@@ -133,10 +133,11 @@
void CapturedTouchpadEventConverter::tryAddRawMotionRange(InputDeviceInfo& deviceInfo,
int32_t androidAxis,
int32_t evdevAxis) const {
- std::optional<RawAbsoluteAxisInfo> info = mDeviceContext.getAbsoluteAxisInfo(evdevAxis);
- if (info) {
- deviceInfo.addMotionRange(androidAxis, SOURCE, info->minValue, info->maxValue, info->flat,
- info->fuzz, info->resolution);
+ RawAbsoluteAxisInfo info;
+ mDeviceContext.getAbsoluteAxisInfo(evdevAxis, &info);
+ if (info.valid) {
+ deviceInfo.addMotionRange(androidAxis, SOURCE, info.minValue, info.maxValue, info.flat,
+ info.fuzz, info.resolution);
}
}
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
index 7cc8940..3af1d04 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
@@ -33,7 +33,7 @@
void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
InputMapper::populateDeviceInfo(info);
- if (mRawPressureAxis) {
+ if (mRawPressureAxis.valid) {
info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f);
}
@@ -50,7 +50,7 @@
std::list<NotifyArgs> ExternalStylusInputMapper::reconfigure(nsecs_t when,
const InputReaderConfiguration& config,
ConfigurationChanges changes) {
- mRawPressureAxis = getAbsoluteAxisInfo(ABS_PRESSURE);
+ getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
mTouchButtonAccumulator.configure();
return {};
}
@@ -82,10 +82,10 @@
mStylusState.toolType = ToolType::STYLUS;
}
- if (mRawPressureAxis) {
+ if (mRawPressureAxis.valid) {
auto rawPressure = static_cast<float>(mSingleTouchMotionAccumulator.getAbsolutePressure());
- mStylusState.pressure = (rawPressure - mRawPressureAxis->minValue) /
- static_cast<float>(mRawPressureAxis->maxValue - mRawPressureAxis->minValue);
+ mStylusState.pressure = (rawPressure - mRawPressureAxis.minValue) /
+ static_cast<float>(mRawPressureAxis.maxValue - mRawPressureAxis.minValue);
} else if (mTouchButtonAccumulator.hasButtonTouch()) {
mStylusState.pressure = mTouchButtonAccumulator.isHovering() ? 0.0f : 1.0f;
}
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
index d48fd9b..c040a7b 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
@@ -16,8 +16,6 @@
#pragma once
-#include <optional>
-
#include "InputMapper.h"
#include "SingleTouchMotionAccumulator.h"
@@ -45,7 +43,7 @@
private:
SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
- std::optional<RawAbsoluteAxisInfo> mRawPressureAxis;
+ RawAbsoluteAxisInfo mRawPressureAxis;
TouchButtonAccumulator mTouchButtonAccumulator;
StylusState mStylusState;
diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp
index c44c48c..b6c5c98 100644
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ b/services/inputflinger/reader/mapper/InputMapper.cpp
@@ -18,7 +18,6 @@
#include "InputMapper.h"
-#include <optional>
#include <sstream>
#include <ftl/enum.h>
@@ -117,16 +116,15 @@
return {};
}
-std::optional<RawAbsoluteAxisInfo> InputMapper::getAbsoluteAxisInfo(int32_t axis) {
- return getDeviceContext().getAbsoluteAxisInfo(axis);
+status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
+ return getDeviceContext().getAbsoluteAxisInfo(axis, axisInfo);
}
void InputMapper::bumpGeneration() {
getDeviceContext().bumpGeneration();
}
-void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump,
- const std::optional<RawAbsoluteAxisInfo>& axis,
+void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis,
const char* name) {
std::stringstream out;
out << INDENT4 << name << ": " << axis << "\n";
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index e5afcc7..2c51448 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -16,8 +16,6 @@
#pragma once
-#include <optional>
-
#include "EventHub.h"
#include "InputDevice.h"
#include "InputListener.h"
@@ -128,11 +126,10 @@
explicit InputMapper(InputDeviceContext& deviceContext,
const InputReaderConfiguration& readerConfig);
- std::optional<RawAbsoluteAxisInfo> getAbsoluteAxisInfo(int32_t axis);
+ status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
void bumpGeneration();
- static void dumpRawAbsoluteAxisInfo(std::string& dump,
- const std::optional<RawAbsoluteAxisInfo>& axis,
+ static void dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis,
const char* name);
static void dumpStylusState(std::string& dump, const StylusState& state);
};
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index 3091714..41e018d 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -117,8 +117,9 @@
continue; // axis must be claimed by a different device
}
- if (std::optional<RawAbsoluteAxisInfo> rawAxisInfo = getAbsoluteAxisInfo(abs);
- rawAxisInfo) {
+ RawAbsoluteAxisInfo rawAxisInfo;
+ getAbsoluteAxisInfo(abs, &rawAxisInfo);
+ if (rawAxisInfo.valid) {
// Map axis.
AxisInfo axisInfo;
const bool explicitlyMapped = !getDeviceContext().mapAxis(abs, &axisInfo);
@@ -128,7 +129,7 @@
axisInfo.mode = AxisInfo::MODE_NORMAL;
axisInfo.axis = -1;
}
- mAxes.insert({abs, createAxis(axisInfo, rawAxisInfo.value(), explicitlyMapped)});
+ mAxes.insert({abs, createAxis(axisInfo, rawAxisInfo, explicitlyMapped)});
}
}
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index 3ea3c20..1986fe2 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -133,7 +133,7 @@
bool isHovering = mTouchButtonAccumulator.getToolType() != ToolType::MOUSE &&
(mTouchButtonAccumulator.isHovering() ||
- (mRawPointerAxes.pressure && inSlot.getPressure() <= 0));
+ (mRawPointerAxes.pressure.valid && inSlot.getPressure() <= 0));
outPointer.isHovering = isHovering;
// Assign pointer id using tracking id if available.
@@ -189,23 +189,21 @@
void MultiTouchInputMapper::configureRawPointerAxes() {
TouchInputMapper::configureRawPointerAxes();
- // We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub won't
- // classify a device as multitouch if they're not present.
- mRawPointerAxes.x = getAbsoluteAxisInfo(ABS_MT_POSITION_X).value();
- mRawPointerAxes.y = getAbsoluteAxisInfo(ABS_MT_POSITION_Y).value();
- mRawPointerAxes.touchMajor = getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR);
- mRawPointerAxes.touchMinor = getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR);
- mRawPointerAxes.toolMajor = getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR);
- mRawPointerAxes.toolMinor = getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR);
- mRawPointerAxes.orientation = getAbsoluteAxisInfo(ABS_MT_ORIENTATION);
- mRawPointerAxes.pressure = getAbsoluteAxisInfo(ABS_MT_PRESSURE);
- mRawPointerAxes.distance = getAbsoluteAxisInfo(ABS_MT_DISTANCE);
- mRawPointerAxes.trackingId = getAbsoluteAxisInfo(ABS_MT_TRACKING_ID);
- mRawPointerAxes.slot = getAbsoluteAxisInfo(ABS_MT_SLOT);
+ getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
+ getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
+ getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
+ getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
+ getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
+ getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
+ getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
+ getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
+ getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
+ getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
+ getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
- if (mRawPointerAxes.trackingId && mRawPointerAxes.slot && mRawPointerAxes.slot->minValue == 0 &&
- mRawPointerAxes.slot->maxValue > 0) {
- size_t slotCount = mRawPointerAxes.slot->maxValue + 1;
+ if (mRawPointerAxes.trackingId.valid && mRawPointerAxes.slot.valid &&
+ mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
+ size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
if (slotCount > MAX_SLOTS) {
ALOGW("MultiTouch Device %s reported %zu slots but the framework "
"only supports a maximum of %zu slots at this time.",
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
index 4233f78..d7f2993 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
@@ -133,8 +133,9 @@
.test(InputDeviceClass::SENSOR))) {
continue;
}
- if (std::optional<RawAbsoluteAxisInfo> rawAxisInfo = getAbsoluteAxisInfo(abs);
- rawAxisInfo) {
+ RawAbsoluteAxisInfo rawAxisInfo;
+ getAbsoluteAxisInfo(abs, &rawAxisInfo);
+ if (rawAxisInfo.valid) {
AxisInfo axisInfo;
// Axis doesn't need to be mapped, as sensor mapper doesn't generate any motion
// input events
@@ -145,7 +146,7 @@
if (ret.ok()) {
InputDeviceSensorType sensorType = (*ret).first;
int32_t sensorDataIndex = (*ret).second;
- const Axis& axis = createAxis(axisInfo, rawAxisInfo.value());
+ const Axis& axis = createAxis(axisInfo, rawAxisInfo);
parseSensorConfiguration(sensorType, abs, sensorDataIndex, axis);
mAxes.insert({abs, axis});
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
index 869feb4..140bb0c 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
@@ -44,7 +44,7 @@
bool isHovering = mTouchButtonAccumulator.getToolType() != ToolType::MOUSE &&
(mTouchButtonAccumulator.isHovering() ||
- (mRawPointerAxes.pressure &&
+ (mRawPointerAxes.pressure.valid &&
mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
outState->rawPointerData.markIdBit(0, isHovering);
@@ -72,15 +72,13 @@
void SingleTouchInputMapper::configureRawPointerAxes() {
TouchInputMapper::configureRawPointerAxes();
- // We can safely assume that ABS_X and _Y axes will be available, as EventHub won't classify a
- // device as a touch device if they're not present.
- mRawPointerAxes.x = getAbsoluteAxisInfo(ABS_X).value();
- mRawPointerAxes.y = getAbsoluteAxisInfo(ABS_Y).value();
- mRawPointerAxes.pressure = getAbsoluteAxisInfo(ABS_PRESSURE);
- mRawPointerAxes.toolMajor = getAbsoluteAxisInfo(ABS_TOOL_WIDTH);
- mRawPointerAxes.distance = getAbsoluteAxisInfo(ABS_DISTANCE);
- mRawPointerAxes.tiltX = getAbsoluteAxisInfo(ABS_TILT_X);
- mRawPointerAxes.tiltY = getAbsoluteAxisInfo(ABS_TILT_Y);
+ getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
+ getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
+ getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
+ getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
+ getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
+ getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
+ getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
}
bool SingleTouchInputMapper::hasStylus() const {
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 984e217..2d89208 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -600,10 +600,10 @@
const float diagonalSize = hypotf(mDisplayBounds.width, mDisplayBounds.height);
// Size factors.
- if (mRawPointerAxes.touchMajor && mRawPointerAxes.touchMajor->maxValue != 0) {
- mSizeScale = 1.0f / mRawPointerAxes.touchMajor->maxValue;
- } else if (mRawPointerAxes.toolMajor && mRawPointerAxes.toolMajor->maxValue != 0) {
- mSizeScale = 1.0f / mRawPointerAxes.toolMajor->maxValue;
+ if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.touchMajor.maxValue != 0) {
+ mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
+ } else if (mRawPointerAxes.toolMajor.valid && mRawPointerAxes.toolMajor.maxValue != 0) {
+ mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
} else {
mSizeScale = 0.0f;
}
@@ -618,18 +618,18 @@
.resolution = 0,
};
- if (mRawPointerAxes.touchMajor) {
- mRawPointerAxes.touchMajor->resolution =
- clampResolution("touchMajor", mRawPointerAxes.touchMajor->resolution);
- mOrientedRanges.touchMajor->resolution = mRawPointerAxes.touchMajor->resolution;
+ if (mRawPointerAxes.touchMajor.valid) {
+ mRawPointerAxes.touchMajor.resolution =
+ clampResolution("touchMajor", mRawPointerAxes.touchMajor.resolution);
+ mOrientedRanges.touchMajor->resolution = mRawPointerAxes.touchMajor.resolution;
}
mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
mOrientedRanges.touchMinor->axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
- if (mRawPointerAxes.touchMinor) {
- mRawPointerAxes.touchMinor->resolution =
- clampResolution("touchMinor", mRawPointerAxes.touchMinor->resolution);
- mOrientedRanges.touchMinor->resolution = mRawPointerAxes.touchMinor->resolution;
+ if (mRawPointerAxes.touchMinor.valid) {
+ mRawPointerAxes.touchMinor.resolution =
+ clampResolution("touchMinor", mRawPointerAxes.touchMinor.resolution);
+ mOrientedRanges.touchMinor->resolution = mRawPointerAxes.touchMinor.resolution;
}
mOrientedRanges.toolMajor = InputDeviceInfo::MotionRange{
@@ -641,18 +641,18 @@
.fuzz = 0,
.resolution = 0,
};
- if (mRawPointerAxes.toolMajor) {
- mRawPointerAxes.toolMajor->resolution =
- clampResolution("toolMajor", mRawPointerAxes.toolMajor->resolution);
- mOrientedRanges.toolMajor->resolution = mRawPointerAxes.toolMajor->resolution;
+ if (mRawPointerAxes.toolMajor.valid) {
+ mRawPointerAxes.toolMajor.resolution =
+ clampResolution("toolMajor", mRawPointerAxes.toolMajor.resolution);
+ mOrientedRanges.toolMajor->resolution = mRawPointerAxes.toolMajor.resolution;
}
mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
mOrientedRanges.toolMinor->axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
- if (mRawPointerAxes.toolMinor) {
- mRawPointerAxes.toolMinor->resolution =
- clampResolution("toolMinor", mRawPointerAxes.toolMinor->resolution);
- mOrientedRanges.toolMinor->resolution = mRawPointerAxes.toolMinor->resolution;
+ if (mRawPointerAxes.toolMinor.valid) {
+ mRawPointerAxes.toolMinor.resolution =
+ clampResolution("toolMinor", mRawPointerAxes.toolMinor.resolution);
+ mOrientedRanges.toolMinor->resolution = mRawPointerAxes.toolMinor.resolution;
}
if (mCalibration.sizeCalibration == Calibration::SizeCalibration::GEOMETRIC) {
@@ -704,10 +704,9 @@
mCalibration.pressureCalibration == Calibration::PressureCalibration::AMPLITUDE) {
if (mCalibration.pressureScale) {
mPressureScale = *mCalibration.pressureScale;
- pressureMax = mPressureScale *
- (mRawPointerAxes.pressure ? mRawPointerAxes.pressure->maxValue : 0);
- } else if (mRawPointerAxes.pressure && mRawPointerAxes.pressure->maxValue != 0) {
- mPressureScale = 1.0f / mRawPointerAxes.pressure->maxValue;
+ pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
+ } else if (mRawPointerAxes.pressure.valid && mRawPointerAxes.pressure.maxValue != 0) {
+ mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
}
}
@@ -726,18 +725,18 @@
mTiltXScale = 0;
mTiltYCenter = 0;
mTiltYScale = 0;
- mHaveTilt = mRawPointerAxes.tiltX && mRawPointerAxes.tiltY;
+ mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
if (mHaveTilt) {
- mTiltXCenter = avg(mRawPointerAxes.tiltX->minValue, mRawPointerAxes.tiltX->maxValue);
- mTiltYCenter = avg(mRawPointerAxes.tiltY->minValue, mRawPointerAxes.tiltY->maxValue);
+ mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue, mRawPointerAxes.tiltX.maxValue);
+ mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue, mRawPointerAxes.tiltY.maxValue);
mTiltXScale = M_PI / 180;
mTiltYScale = M_PI / 180;
- if (mRawPointerAxes.tiltX->resolution) {
- mTiltXScale = 1.0 / mRawPointerAxes.tiltX->resolution;
+ if (mRawPointerAxes.tiltX.resolution) {
+ mTiltXScale = 1.0 / mRawPointerAxes.tiltX.resolution;
}
- if (mRawPointerAxes.tiltY->resolution) {
- mTiltYScale = 1.0 / mRawPointerAxes.tiltY->resolution;
+ if (mRawPointerAxes.tiltY.resolution) {
+ mTiltYScale = 1.0 / mRawPointerAxes.tiltY.resolution;
}
mOrientedRanges.tilt = InputDeviceInfo::MotionRange{
@@ -767,11 +766,11 @@
} else if (mCalibration.orientationCalibration != Calibration::OrientationCalibration::NONE) {
if (mCalibration.orientationCalibration ==
Calibration::OrientationCalibration::INTERPOLATED) {
- if (mRawPointerAxes.orientation) {
- if (mRawPointerAxes.orientation->maxValue > 0) {
- mOrientationScale = M_PI_2 / mRawPointerAxes.orientation->maxValue;
- } else if (mRawPointerAxes.orientation->minValue < 0) {
- mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation->minValue;
+ if (mRawPointerAxes.orientation.valid) {
+ if (mRawPointerAxes.orientation.maxValue > 0) {
+ mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
+ } else if (mRawPointerAxes.orientation.minValue < 0) {
+ mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
} else {
mOrientationScale = 0;
}
@@ -796,14 +795,14 @@
mDistanceScale = mCalibration.distanceScale.value_or(1.0f);
}
- const bool hasDistance = mRawPointerAxes.distance.has_value();
mOrientedRanges.distance = InputDeviceInfo::MotionRange{
+
.axis = AMOTION_EVENT_AXIS_DISTANCE,
.source = mSource,
- .min = hasDistance ? mRawPointerAxes.distance->minValue * mDistanceScale : 0,
- .max = hasDistance ? mRawPointerAxes.distance->maxValue * mDistanceScale : 0,
+ .min = mRawPointerAxes.distance.minValue * mDistanceScale,
+ .max = mRawPointerAxes.distance.maxValue * mDistanceScale,
.flat = 0,
- .fuzz = hasDistance ? mRawPointerAxes.distance->fuzz * mDistanceScale : 0,
+ .fuzz = mRawPointerAxes.distance.fuzz * mDistanceScale,
.resolution = 0,
};
}
@@ -944,7 +943,12 @@
const std::optional<DisplayViewport> newViewportOpt = findViewport();
// Ensure the device is valid and can be used.
- if (!newViewportOpt) {
+ if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
+ ALOGW("Touch device '%s' did not report support for X or Y axis! "
+ "The device will be inoperable.",
+ getDeviceName().c_str());
+ mDeviceMode = DeviceMode::DISABLED;
+ } else if (!newViewportOpt) {
ALOGI("Touch device '%s' could not query the properties of its associated "
"display. The device will be inoperable until the display size "
"becomes available.",
@@ -1233,7 +1237,7 @@
void TouchInputMapper::resolveCalibration() {
// Size
- if (mRawPointerAxes.touchMajor || mRawPointerAxes.toolMajor) {
+ if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
if (mCalibration.sizeCalibration == Calibration::SizeCalibration::DEFAULT) {
mCalibration.sizeCalibration = Calibration::SizeCalibration::GEOMETRIC;
}
@@ -1242,7 +1246,7 @@
}
// Pressure
- if (mRawPointerAxes.pressure) {
+ if (mRawPointerAxes.pressure.valid) {
if (mCalibration.pressureCalibration == Calibration::PressureCalibration::DEFAULT) {
mCalibration.pressureCalibration = Calibration::PressureCalibration::PHYSICAL;
}
@@ -1251,7 +1255,7 @@
}
// Orientation
- if (mRawPointerAxes.orientation) {
+ if (mRawPointerAxes.orientation.valid) {
if (mCalibration.orientationCalibration == Calibration::OrientationCalibration::DEFAULT) {
mCalibration.orientationCalibration = Calibration::OrientationCalibration::INTERPOLATED;
}
@@ -1260,7 +1264,7 @@
}
// Distance
- if (mRawPointerAxes.distance) {
+ if (mRawPointerAxes.distance.valid) {
if (mCalibration.distanceCalibration == Calibration::DistanceCalibration::DEFAULT) {
mCalibration.distanceCalibration = Calibration::DistanceCalibration::SCALED;
}
@@ -2247,25 +2251,25 @@
case Calibration::SizeCalibration::DIAMETER:
case Calibration::SizeCalibration::BOX:
case Calibration::SizeCalibration::AREA:
- if (mRawPointerAxes.touchMajor && mRawPointerAxes.toolMajor) {
+ if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
touchMajor = in.touchMajor;
- touchMinor = mRawPointerAxes.touchMinor ? in.touchMinor : in.touchMajor;
+ touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
toolMajor = in.toolMajor;
- toolMinor = mRawPointerAxes.toolMinor ? in.toolMinor : in.toolMajor;
- size = mRawPointerAxes.touchMinor ? avg(in.touchMajor, in.touchMinor)
- : in.touchMajor;
- } else if (mRawPointerAxes.touchMajor) {
+ toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
+ size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
+ : in.touchMajor;
+ } else if (mRawPointerAxes.touchMajor.valid) {
toolMajor = touchMajor = in.touchMajor;
toolMinor = touchMinor =
- mRawPointerAxes.touchMinor ? in.touchMinor : in.touchMajor;
- size = mRawPointerAxes.touchMinor ? avg(in.touchMajor, in.touchMinor)
- : in.touchMajor;
- } else if (mRawPointerAxes.toolMajor) {
+ mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
+ size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
+ : in.touchMajor;
+ } else if (mRawPointerAxes.toolMajor.valid) {
touchMajor = toolMajor = in.toolMajor;
touchMinor = toolMinor =
- mRawPointerAxes.toolMinor ? in.toolMinor : in.toolMajor;
- size = mRawPointerAxes.toolMinor ? avg(in.toolMajor, in.toolMinor)
- : in.toolMajor;
+ mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
+ size = mRawPointerAxes.toolMinor.valid ? avg(in.toolMajor, in.toolMinor)
+ : in.toolMajor;
} else {
ALOG_ASSERT(false,
"No touch or tool axes. "
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 87b72af..a9a0190 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -61,17 +61,17 @@
struct RawPointerAxes {
RawAbsoluteAxisInfo x{};
RawAbsoluteAxisInfo y{};
- std::optional<RawAbsoluteAxisInfo> pressure{};
- std::optional<RawAbsoluteAxisInfo> touchMajor{};
- std::optional<RawAbsoluteAxisInfo> touchMinor{};
- std::optional<RawAbsoluteAxisInfo> toolMajor{};
- std::optional<RawAbsoluteAxisInfo> toolMinor{};
- std::optional<RawAbsoluteAxisInfo> orientation{};
- std::optional<RawAbsoluteAxisInfo> distance{};
- std::optional<RawAbsoluteAxisInfo> tiltX{};
- std::optional<RawAbsoluteAxisInfo> tiltY{};
- std::optional<RawAbsoluteAxisInfo> trackingId{};
- std::optional<RawAbsoluteAxisInfo> slot{};
+ RawAbsoluteAxisInfo pressure{};
+ RawAbsoluteAxisInfo touchMajor{};
+ RawAbsoluteAxisInfo touchMinor{};
+ RawAbsoluteAxisInfo toolMajor{};
+ RawAbsoluteAxisInfo toolMinor{};
+ RawAbsoluteAxisInfo orientation{};
+ RawAbsoluteAxisInfo distance{};
+ RawAbsoluteAxisInfo tiltX{};
+ RawAbsoluteAxisInfo tiltY{};
+ RawAbsoluteAxisInfo trackingId{};
+ RawAbsoluteAxisInfo slot{};
inline int32_t getRawWidth() const { return x.maxValue - x.minValue + 1; }
inline int32_t getRawHeight() const { return y.maxValue - y.minValue + 1; }
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index 5c5fd3f..128f515 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -240,15 +240,14 @@
mGestureConverter(*getContext(), deviceContext, getDeviceId()),
mCapturedEventConverter(*getContext(), deviceContext, mMotionAccumulator, getDeviceId()),
mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())) {
- if (std::optional<RawAbsoluteAxisInfo> slotAxis =
- deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT);
- slotAxis && slotAxis->maxValue >= 0) {
- mMotionAccumulator.configure(deviceContext, slotAxis->maxValue + 1, true);
- } else {
+ RawAbsoluteAxisInfo slotAxisInfo;
+ deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo);
+ if (!slotAxisInfo.valid || slotAxisInfo.maxValue < 0) {
LOG(WARNING) << "Touchpad " << deviceContext.getName()
<< " doesn't have a valid ABS_MT_SLOT axis, and probably won't work properly.";
- mMotionAccumulator.configure(deviceContext, 1, true);
+ slotAxisInfo.maxValue = 0;
}
+ mMotionAccumulator.configure(deviceContext, slotAxisInfo.maxValue + 1, true);
mGestureInterpreter->Initialize(GESTURES_DEVCLASS_TOUCHPAD);
mGestureInterpreter->SetHardwareProperties(createHardwareProperties(deviceContext));
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
index 9924d0d..e8e7376 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
@@ -66,11 +66,10 @@
const InputDeviceContext& deviceContext, int32_t deviceId)
: mDeviceId(deviceId),
mReaderContext(readerContext),
- mEnableFlingStop(input_flags::enable_touchpad_fling_stop()),
- // We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub
- // won't classify a device as a touchpad if they're not present.
- mXAxisInfo(deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X).value()),
- mYAxisInfo(deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y).value()) {}
+ mEnableFlingStop(input_flags::enable_touchpad_fling_stop()) {
+ deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mXAxisInfo);
+ deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mYAxisInfo);
+}
std::string GestureConverter::dump() const {
std::stringstream out;
diff --git a/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp b/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp
index d8a1f50..04655dc 100644
--- a/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp
+++ b/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp
@@ -16,8 +16,6 @@
#include "HardwareProperties.h"
-#include <optional>
-
namespace android {
namespace {
@@ -35,34 +33,26 @@
HardwareProperties createHardwareProperties(const InputDeviceContext& context) {
HardwareProperties props;
- // We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub won't
- // classify a device as a touchpad if they're not present.
- RawAbsoluteAxisInfo absMtPositionX = context.getAbsoluteAxisInfo(ABS_MT_POSITION_X).value();
+ RawAbsoluteAxisInfo absMtPositionX;
+ context.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &absMtPositionX);
props.left = absMtPositionX.minValue;
props.right = absMtPositionX.maxValue;
props.res_x = absMtPositionX.resolution;
- RawAbsoluteAxisInfo absMtPositionY = context.getAbsoluteAxisInfo(ABS_MT_POSITION_Y).value();
+ RawAbsoluteAxisInfo absMtPositionY;
+ context.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &absMtPositionY);
props.top = absMtPositionY.minValue;
props.bottom = absMtPositionY.maxValue;
props.res_y = absMtPositionY.resolution;
- if (std::optional<RawAbsoluteAxisInfo> absMtOrientation =
- context.getAbsoluteAxisInfo(ABS_MT_ORIENTATION);
- absMtOrientation) {
- props.orientation_minimum = absMtOrientation->minValue;
- props.orientation_maximum = absMtOrientation->maxValue;
- } else {
- props.orientation_minimum = 0;
- props.orientation_maximum = 0;
- }
+ RawAbsoluteAxisInfo absMtOrientation;
+ context.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &absMtOrientation);
+ props.orientation_minimum = absMtOrientation.minValue;
+ props.orientation_maximum = absMtOrientation.maxValue;
- if (std::optional<RawAbsoluteAxisInfo> absMtSlot = context.getAbsoluteAxisInfo(ABS_MT_SLOT);
- absMtSlot) {
- props.max_finger_cnt = absMtSlot->maxValue - absMtSlot->minValue + 1;
- } else {
- props.max_finger_cnt = 1;
- }
+ RawAbsoluteAxisInfo absMtSlot;
+ context.getAbsoluteAxisInfo(ABS_MT_SLOT, &absMtSlot);
+ props.max_finger_cnt = absMtSlot.maxValue - absMtSlot.minValue + 1;
props.max_touch_cnt = getMaxTouchCount(context);
// T5R2 ("Track 5, Report 2") is a feature of some old Synaptics touchpads that could track 5
@@ -81,7 +71,9 @@
// are haptic.
props.is_haptic_pad = false;
- props.reports_pressure = context.hasAbsoluteAxis(ABS_MT_PRESSURE);
+ RawAbsoluteAxisInfo absMtPressure;
+ context.getAbsoluteAxisInfo(ABS_MT_PRESSURE, &absMtPressure);
+ props.reports_pressure = absMtPressure.valid;
return props;
}
diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp
index 31fbf20..99db999 100644
--- a/services/inputflinger/tests/FakeEventHub.cpp
+++ b/services/inputflinger/tests/FakeEventHub.cpp
@@ -101,6 +101,7 @@
Device* device = getDevice(deviceId);
RawAbsoluteAxisInfo info;
+ info.valid = true;
info.minValue = minValue;
info.maxValue = maxValue;
info.flat = flat;
diff --git a/services/inputflinger/tests/HardwareProperties_test.cpp b/services/inputflinger/tests/HardwareProperties_test.cpp
index e87f822..643fab6 100644
--- a/services/inputflinger/tests/HardwareProperties_test.cpp
+++ b/services/inputflinger/tests/HardwareProperties_test.cpp
@@ -50,6 +50,7 @@
void setupValidAxis(int axis, int32_t min, int32_t max, int32_t resolution) {
EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis))
.WillRepeatedly(Return(std::optional<RawAbsoluteAxisInfo>{{
+ .valid = true,
.minValue = min,
.maxValue = max,
.flat = 0,
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index e773f58..7e96d5f 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -59,6 +59,7 @@
int32_t resolution) {
EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis))
.WillRepeatedly(Return(valid ? std::optional<RawAbsoluteAxisInfo>{{
+ .valid = true,
.minValue = min,
.maxValue = max,
.flat = 0,
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index fea0d9a..bf56d3a 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -129,6 +129,7 @@
}
if (mFdp->ConsumeBool()) {
return std::optional<RawAbsoluteAxisInfo>({
+ .valid = mFdp->ConsumeBool(),
.minValue = mFdp->ConsumeIntegral<int32_t>(),
.maxValue = mFdp->ConsumeIntegral<int32_t>(),
.flat = mFdp->ConsumeIntegral<int32_t>(),
diff --git a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp
index ebbb311..c620032 100644
--- a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp
@@ -34,6 +34,7 @@
if (fdp.ConsumeBool()) {
eventHub.setAbsoluteAxisInfo(id, axis,
RawAbsoluteAxisInfo{
+ .valid = fdp.ConsumeBool(),
.minValue = fdp.ConsumeIntegral<int32_t>(),
.maxValue = fdp.ConsumeIntegral<int32_t>(),
.flat = fdp.ConsumeIntegral<int32_t>(),
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 082d8aa..0682fdb 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2540,10 +2540,6 @@
compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
const DisplayDevice* display) const {
if (!display) return nullptr;
- if (!mFlinger->mLayerLifecycleManagerEnabled) {
- return display->getCompositionDisplay()->getOutputLayerForLayer(
- getCompositionEngineLayerFE());
- }
sp<LayerFE> layerFE;
frontend::LayerHierarchy::TraversalPath path{.id = static_cast<uint32_t>(sequence)};
for (auto& [p, layer] : mLayerFEs) {
@@ -2559,10 +2555,6 @@
compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
const DisplayDevice* display, const frontend::LayerHierarchy::TraversalPath& path) const {
if (!display) return nullptr;
- if (!mFlinger->mLayerLifecycleManagerEnabled) {
- return display->getCompositionDisplay()->getOutputLayerForLayer(
- getCompositionEngineLayerFE());
- }
sp<LayerFE> layerFE;
for (auto& [p, layer] : mLayerFEs) {
if (p == path) {
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 3fc3901..ee7eda1 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -487,13 +487,13 @@
return 0ns;
}
-void VSyncPredictor::onFrameBegin(TimePoint expectedPresentTime,
- TimePoint lastConfirmedPresentTime) {
+void VSyncPredictor::onFrameBegin(TimePoint expectedPresentTime, FrameTime lastSignaledFrameTime) {
SFTRACE_NAME("VSyncPredictor::onFrameBegin");
std::lock_guard lock(mMutex);
if (!mDisplayModePtr->getVrrConfig()) return;
+ const auto [lastConfirmedPresentTime, lastConfirmedExpectedPresentTime] = lastSignaledFrameTime;
if (CC_UNLIKELY(mTraceOn)) {
SFTRACE_FORMAT_INSTANT("vsync is %.2f past last signaled fence",
static_cast<float>(expectedPresentTime.ns() -
@@ -519,6 +519,11 @@
}
}
+ if (lastConfirmedExpectedPresentTime.ns() - lastConfirmedPresentTime.ns() > threshold) {
+ SFTRACE_FORMAT_INSTANT("lastFramePresentedEarly");
+ return;
+ }
+
const auto phase = ensureMinFrameDurationIsKept(expectedPresentTime, lastConfirmedPresentTime);
if (phase > 0ns) {
mMissedVsync = {expectedPresentTime, minFramePeriodLocked()};
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index 64e1029..9e1c90b 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -22,6 +22,7 @@
#include <vector>
#include <android-base/thread_annotations.h>
+#include <scheduler/FrameTime.h>
#include <scheduler/TimeKeeper.h>
#include <ui/DisplayId.h>
@@ -77,7 +78,7 @@
void setRenderRate(Fps, bool applyImmediately) final EXCLUDES(mMutex);
- void onFrameBegin(TimePoint expectedPresentTime, TimePoint lastConfirmedPresentTime) final
+ void onFrameBegin(TimePoint expectedPresentTime, FrameTime lastSignaledFrameTime) final
EXCLUDES(mMutex);
void onFrameMissed(TimePoint expectedPresentTime) final EXCLUDES(mMutex);
diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h
index 134d28e..3376fad 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -21,6 +21,7 @@
#include <scheduler/Fps.h>
#include <scheduler/FrameRateMode.h>
+#include <scheduler/FrameTime.h>
#include "VSyncDispatch.h"
@@ -112,8 +113,7 @@
*/
virtual void setRenderRate(Fps, bool applyImmediately) = 0;
- virtual void onFrameBegin(TimePoint expectedPresentTime,
- TimePoint lastConfirmedPresentTime) = 0;
+ virtual void onFrameBegin(TimePoint expectedPresentTime, FrameTime lastSignaledFrameTime) = 0;
virtual void onFrameMissed(TimePoint expectedPresentTime) = 0;
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
index d37d2dc..38cb446 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
@@ -26,6 +26,7 @@
#include <ui/FenceTime.h>
#include <scheduler/Features.h>
+#include <scheduler/FrameTime.h>
#include <scheduler/Time.h>
#include <scheduler/VsyncId.h>
#include <scheduler/interface/CompositeResult.h>
@@ -57,13 +58,6 @@
// The time of the VSYNC that preceded this frame. See `presentFenceForPastVsync` for details.
TimePoint pastVsyncTime(Period minFramePeriod) const;
- // The present fence for the frame that had targeted the most recent VSYNC before this frame.
- // If the target VSYNC for any given frame is more than `vsyncPeriod` in the future, then the
- // VSYNC of at least one previous frame has not yet passed. In other words, this is NOT the
- // `presentFenceForPreviousFrame` if running N VSYNCs ahead, but the one that should have been
- // signaled by now (unless that frame missed).
- FenceTimePtr presentFenceForPastVsync(Period minFramePeriod) const;
-
// Equivalent to `presentFenceForPastVsync` unless running N VSYNCs ahead.
const FenceTimePtr& presentFenceForPreviousFrame() const {
return mPresentFences.front().fenceTime;
@@ -72,7 +66,7 @@
bool isFramePending() const { return mFramePending; }
bool didMissFrame() const { return mFrameMissed; }
bool didMissHwcFrame() const { return mHwcFrameMissed && !mGpuFrameMissed; }
- TimePoint lastSignaledFrameTime() const { return mLastSignaledFrameTime; };
+ FrameTime lastSignaledFrameTime() const { return mLastSignaledFrameTime; }
protected:
explicit FrameTarget(const std::string& displayLabel);
@@ -106,10 +100,17 @@
FenceTimePtr fenceTime = FenceTime::NO_FENCE;
TimePoint expectedPresentTime = TimePoint();
};
+
+ // The present fence for the frame that had targeted the most recent VSYNC before this frame.
+ // If the target VSYNC for any given frame is more than `vsyncPeriod` in the future, then the
+ // VSYNC of at least one previous frame has not yet passed. In other words, this is NOT the
+ // `presentFenceForPreviousFrame` if running N VSYNCs ahead, but the one that should have been
+ // signaled by now (unless that frame missed).
+ FenceWithFenceTime presentFenceForPastVsync(Period minFramePeriod) const;
std::array<FenceWithFenceTime, 2> mPresentFences;
utils::RingBuffer<FenceWithFenceTime, 5> mFenceWithFenceTimes;
- TimePoint mLastSignaledFrameTime;
+ FrameTime mLastSignaledFrameTime;
private:
friend class FrameTargeterTestBase;
@@ -120,16 +121,17 @@
return expectedFrameDuration() > (N - 1) * minFramePeriod;
}
- const FenceTimePtr pastVsyncTimePtr() const {
- auto pastFenceTimePtr = FenceTime::NO_FENCE;
+ FenceWithFenceTime pastVsyncTimePtr() const {
+ FenceWithFenceTime pastFenceWithFenceTime;
for (size_t i = 0; i < mFenceWithFenceTimes.size(); i++) {
- const auto& [_, fenceTimePtr, expectedPresentTime] = mFenceWithFenceTimes[i];
- if (expectedPresentTime > mFrameBeginTime) {
- return pastFenceTimePtr;
+ const auto& fenceWithFenceTime = mFenceWithFenceTimes[i];
+ // TODO(b/354007767) Fix the below condition to avoid frame drop
+ if (fenceWithFenceTime.expectedPresentTime > mFrameBeginTime) {
+ return pastFenceWithFenceTime;
}
- pastFenceTimePtr = fenceTimePtr;
+ pastFenceWithFenceTime = fenceWithFenceTime;
}
- return pastFenceTimePtr;
+ return pastFenceWithFenceTime;
}
};
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameTime.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameTime.h
new file mode 100644
index 0000000..ed5c899
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameTime.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <scheduler/Time.h>
+
+namespace android::scheduler {
+struct FrameTime {
+ TimePoint signalTime;
+ TimePoint expectedPresentTime;
+};
+} // namespace android::scheduler
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp b/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
index 60694b9..1d248fb 100644
--- a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
+++ b/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
@@ -33,12 +33,12 @@
return mExpectedPresentTime - Period::fromNs(minFramePeriod.ns() << shift);
}
-FenceTimePtr FrameTarget::presentFenceForPastVsync(Period minFramePeriod) const {
+FrameTarget::FenceWithFenceTime FrameTarget::presentFenceForPastVsync(Period minFramePeriod) const {
if (FlagManager::getInstance().allow_n_vsyncs_in_targeter()) {
return pastVsyncTimePtr();
}
const size_t i = static_cast<size_t>(targetsVsyncsAhead<2>(minFramePeriod));
- return mPresentFences[i].fenceTime;
+ return mPresentFences[i];
}
bool FrameTarget::wouldPresentEarly(Period minFramePeriod) const {
@@ -51,7 +51,7 @@
return true;
}
- const auto fence = presentFenceForPastVsync(minFramePeriod);
+ const auto fence = presentFenceForPastVsync(minFramePeriod).fenceTime;
return fence->isValid() && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
}
@@ -93,7 +93,7 @@
ticks<std::milli, float>(mExpectedPresentTime - TimePoint::now()),
mExpectedPresentTime == args.expectedVsyncTime ? "" : " (adjusted)");
- const FenceTimePtr& pastPresentFence = presentFenceForPastVsync(minFramePeriod);
+ FenceWithFenceTime pastPresentFence = presentFenceForPastVsync(minFramePeriod);
// In cases where the present fence is about to fire, give it a small grace period instead of
// giving up on the frame.
@@ -105,8 +105,8 @@
// Pending frames may trigger backpressure propagation.
const auto& isFencePending = *isFencePendingFuncPtr;
- mFramePending = pastPresentFence != FenceTime::NO_FENCE &&
- isFencePending(pastPresentFence, graceTimeForPresentFenceMs);
+ mFramePending = pastPresentFence.fenceTime != FenceTime::NO_FENCE &&
+ isFencePending(pastPresentFence.fenceTime, graceTimeForPresentFenceMs);
// A frame is missed if the prior frame is still pending. If no longer pending, then we still
// count the frame as missed if the predicted present time was further in the past than when the
@@ -114,9 +114,10 @@
// than a typical frame duration, but should not be so small that it reports reasonable drift as
// a missed frame.
mFrameMissed = mFramePending || [&] {
- const nsecs_t pastPresentTime = pastPresentFence->getSignalTime();
+ const nsecs_t pastPresentTime = pastPresentFence.fenceTime->getSignalTime();
if (pastPresentTime < 0) return false;
- mLastSignaledFrameTime = TimePoint::fromNs(pastPresentTime);
+ mLastSignaledFrameTime = {.signalTime = TimePoint::fromNs(pastPresentTime),
+ .expectedPresentTime = pastPresentFence.expectedPresentTime};
const nsecs_t frameMissedSlop = vsyncPeriod.ns() / 2;
return lastScheduledPresentTime.ns() < pastPresentTime - frameMissedSlop;
}();
diff --git a/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp b/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp
index 5448eec..190d062 100644
--- a/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp
+++ b/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp
@@ -57,6 +57,10 @@
return target().wouldPresentEarly(minFramePeriod);
}
+ FrameTarget::FenceWithFenceTime presentFenceForPastVsync(Period minFramePeriod) const {
+ return target().presentFenceForPastVsync(minFramePeriod);
+ }
+
struct Frame {
Frame(FrameTargeterTestBase* testPtr, VsyncId vsyncId, TimePoint& frameBeginTime,
Duration frameDuration, Fps refreshRate, Fps peakRefreshRate,
@@ -181,7 +185,7 @@
const auto fence = frame.end();
EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - kPeriod);
- EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), fence);
+ EXPECT_EQ(presentFenceForPastVsync(kPeriod).fenceTime, fence);
}
}
@@ -200,7 +204,7 @@
const auto fence = frame.end();
EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - 2 * kPeriod);
- EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), previousFence);
+ EXPECT_EQ(presentFenceForPastVsync(kPeriod).fenceTime, previousFence);
previousFence = fence;
}
@@ -222,7 +226,7 @@
const auto pastVsyncTime = frameBeginTime + kFrameDuration - 2 * kPeriod;
EXPECT_EQ(target().pastVsyncTime(kPeriod), pastVsyncTime);
- EXPECT_EQ(target().presentFenceForPastVsync(kFrameDuration), previousFence);
+ EXPECT_EQ(presentFenceForPastVsync(kFrameDuration).fenceTime, previousFence);
frameBeginTime += kPeriod;
previousFence = fence;
@@ -248,7 +252,7 @@
const auto fence = frame.end();
EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - 2 * kPeriod);
- EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), previousFence);
+ EXPECT_EQ(presentFenceForPastVsync(kPeriod).fenceTime, previousFence);
previousFence = fence;
}
@@ -274,7 +278,7 @@
const auto pastVsyncTime = frameBeginTime + kFrameDuration - 2 * kPeriod;
EXPECT_EQ(target().pastVsyncTime(kPeriod), pastVsyncTime);
- EXPECT_EQ(target().presentFenceForPastVsync(kFrameDuration), previousFence);
+ EXPECT_EQ(presentFenceForPastVsync(kFrameDuration).fenceTime, previousFence);
frameBeginTime += kPeriod;
previousFence = fence;
@@ -283,7 +287,7 @@
TEST_F(FrameTargeterTest, doesNotDetectEarlyPresentIfNoFence) {
constexpr Period kPeriod = (60_Hz).getPeriod();
- EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), FenceTime::NO_FENCE);
+ EXPECT_EQ(presentFenceForPastVsync(kPeriod).fenceTime, FenceTime::NO_FENCE);
EXPECT_FALSE(wouldPresentEarly(kPeriod));
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index beb05b9..ea8fe6a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -534,9 +534,6 @@
mIgnoreHdrCameraLayers = ignore_hdr_camera_layers(false);
- mLayerLifecycleManagerEnabled =
- base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, true);
-
// These are set by the HWC implementation to indicate that they will use the workarounds.
mIsHotplugErrViaNegVsync =
base::GetBoolProperty("debug.sf.hwc_hotplug_error_via_neg_vsync"s, false);
@@ -2676,11 +2673,8 @@
const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded);
bool transactionsAreEmpty = false;
- if (mLayerLifecycleManagerEnabled) {
- mustComposite |=
- updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(),
- flushTransactions, transactionsAreEmpty);
- }
+ mustComposite |= updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(),
+ flushTransactions, transactionsAreEmpty);
// Tell VsyncTracker that we are going to present this frame before scheduling
// setTransactionFlags which will schedule another SF frame. This was if the tracker
@@ -2714,9 +2708,7 @@
mUpdateAttachedChoreographer = false;
Mutex::Autolock lock(mStateLock);
- mScheduler->chooseRefreshRateForContent(mLayerLifecycleManagerEnabled
- ? &mLayerHierarchyBuilder.getHierarchy()
- : nullptr,
+ mScheduler->chooseRefreshRateForContent(&mLayerHierarchyBuilder.getHierarchy(),
updateAttachedChoreographer);
if (FlagManager::getInstance().connected_display()) {
@@ -2837,7 +2829,7 @@
constexpr bool kCursorOnly = false;
const auto layers = moveSnapshotsToCompositionArgs(refreshArgs, kCursorOnly);
- if (mLayerLifecycleManagerEnabled && !mVisibleRegionsDirty) {
+ if (!mVisibleRegionsDirty) {
for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
auto compositionDisplay = display->getCompositionDisplay();
if (!compositionDisplay->getState().isEnabled) continue;
@@ -3253,28 +3245,20 @@
}
};
- if (mLayerLifecycleManagerEnabled) {
- mLayerSnapshotBuilder.forEachVisibleSnapshot(
- [&, compositionDisplay = compositionDisplay](
- std::unique_ptr<frontend::LayerSnapshot>&
- snapshot) FTL_FAKE_GUARD(kMainThreadContext) {
- auto it = mLegacyLayers.find(snapshot->sequence);
- LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(),
- "Couldnt find layer object for %s",
- snapshot->getDebugString().c_str());
- auto& legacyLayer = it->second;
- sp<LayerFE> layerFe =
- legacyLayer->getCompositionEngineLayerFE(snapshot->path);
+ mLayerSnapshotBuilder.forEachVisibleSnapshot(
+ [&, compositionDisplay = compositionDisplay](
+ std::unique_ptr<frontend::LayerSnapshot>& snapshot)
+ FTL_FAKE_GUARD(kMainThreadContext) {
+ auto it = mLegacyLayers.find(snapshot->sequence);
+ LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(),
+ "Couldnt find layer object for %s",
+ snapshot->getDebugString().c_str());
+ auto& legacyLayer = it->second;
+ sp<LayerFE> layerFe =
+ legacyLayer->getCompositionEngineLayerFE(snapshot->path);
- updateInfoFn(compositionDisplay, *snapshot, layerFe);
- });
- } else {
- mDrawingState.traverse([&, compositionDisplay = compositionDisplay](Layer* layer) {
- const auto layerFe = layer->getCompositionEngineLayerFE();
- const frontend::LayerSnapshot& snapshot = *layer->getLayerSnapshot();
- updateInfoFn(compositionDisplay, snapshot, layerFe);
- });
- }
+ updateInfoFn(compositionDisplay, *snapshot, layerFe);
+ });
listener->dispatchHdrLayerInfo(info);
}
}
@@ -3320,9 +3304,8 @@
if (!layer->hasTrustedPresentationListener()) {
return;
}
- const frontend::LayerSnapshot* snapshot = mLayerLifecycleManagerEnabled
- ? mLayerSnapshotBuilder.getSnapshot(layer->sequence)
- : layer->getLayerSnapshot();
+ const frontend::LayerSnapshot* snapshot =
+ mLayerSnapshotBuilder.getSnapshot(layer->sequence);
std::optional<const DisplayDevice*> displayOpt = std::nullopt;
if (snapshot) {
displayOpt = layerStackToDisplay.get(snapshot->outputFilter.layerStack);
@@ -4047,13 +4030,6 @@
// Commit display transactions.
const bool displayTransactionNeeded = transactionFlags & eDisplayTransactionNeeded;
mFrontEndDisplayInfosChanged = displayTransactionNeeded;
- if (displayTransactionNeeded && !mLayerLifecycleManagerEnabled) {
- processDisplayChangesLocked();
- mFrontEndDisplayInfos.clear();
- for (const auto& [_, display] : mDisplays) {
- mFrontEndDisplayInfos.try_emplace(display->getLayerStack(), display->getFrontEndInfo());
- }
- }
mForceTransactionDisplayChange = displayTransactionNeeded;
if (mSomeChildrenChanged) {
@@ -4234,23 +4210,10 @@
outWindowInfos.reserve(sNumWindowInfos);
sNumWindowInfos = 0;
- if (mLayerLifecycleManagerEnabled) {
- mLayerSnapshotBuilder.forEachInputSnapshot(
- [&outWindowInfos](const frontend::LayerSnapshot& snapshot) {
- outWindowInfos.push_back(snapshot.inputInfo);
- });
- } else {
- mDrawingState.traverseInReverseZOrder([&](Layer* layer) FTL_FAKE_GUARD(kMainThreadContext) {
- if (!layer->needsInputInfo()) return;
- const auto opt =
- mFrontEndDisplayInfos.get(layer->getLayerStack())
- .transform([](const frontend::DisplayInfo& info) {
- return Layer::InputDisplayArgs{&info.transform, info.isSecure};
- });
-
- outWindowInfos.push_back(layer->fillInputInfo(opt.value_or(Layer::InputDisplayArgs{})));
- });
- }
+ mLayerSnapshotBuilder.forEachInputSnapshot(
+ [&outWindowInfos](const frontend::LayerSnapshot& snapshot) {
+ outWindowInfos.push_back(snapshot.inputInfo);
+ });
sNumWindowInfos = outWindowInfos.size();
@@ -4324,10 +4287,8 @@
void SurfaceFlinger::onChoreographerAttached() {
SFTRACE_CALL();
- if (mLayerLifecycleManagerEnabled) {
- mUpdateAttachedChoreographer = true;
- scheduleCommit(FrameHint::kNone);
- }
+ mUpdateAttachedChoreographer = true;
+ scheduleCommit(FrameHint::kNone);
}
void SurfaceFlinger::onExpectedPresentTimePosted(TimePoint expectedPresentTime,
@@ -4871,101 +4832,6 @@
return TransactionReadiness::Ready;
}
-TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferCheckLegacy(
- const TransactionHandler::TransactionFlushState& flushState) {
- using TransactionReadiness = TransactionHandler::TransactionReadiness;
- auto ready = TransactionReadiness::Ready;
- flushState.transaction->traverseStatesWithBuffersWhileTrue([&](const ResolvedComposerState&
- resolvedState) -> bool {
- sp<Layer> layer = LayerHandle::getLayer(resolvedState.state.surface);
-
- const auto& transaction = *flushState.transaction;
- const auto& s = resolvedState.state;
- // check for barrier frames
- if (s.bufferData->hasBarrier) {
- // The current producerId is already a newer producer than the buffer that has a
- // barrier. This means the incoming buffer is older and we can release it here. We
- // don't wait on the barrier since we know that's stale information.
- if (layer->getDrawingState().barrierProducerId > s.bufferData->producerId) {
- layer->callReleaseBufferCallback(s.bufferData->releaseBufferListener,
- resolvedState.externalTexture->getBuffer(),
- s.bufferData->frameNumber,
- s.bufferData->acquireFence);
- // Delete the entire state at this point and not just release the buffer because
- // everything associated with the Layer in this Transaction is now out of date.
- SFTRACE_FORMAT("DeleteStaleBuffer %s barrierProducerId:%d > %d",
- layer->getDebugName(), layer->getDrawingState().barrierProducerId,
- s.bufferData->producerId);
- return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL;
- }
-
- if (layer->getDrawingState().barrierFrameNumber < s.bufferData->barrierFrameNumber) {
- const bool willApplyBarrierFrame =
- flushState.bufferLayersReadyToPresent.contains(s.surface.get()) &&
- ((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >=
- s.bufferData->barrierFrameNumber));
- if (!willApplyBarrierFrame) {
- SFTRACE_FORMAT("NotReadyBarrier %s barrierFrameNumber:%" PRId64 " > %" PRId64,
- layer->getDebugName(),
- layer->getDrawingState().barrierFrameNumber,
- s.bufferData->barrierFrameNumber);
- ready = TransactionReadiness::NotReadyBarrier;
- return TraverseBuffersReturnValues::STOP_TRAVERSAL;
- }
- }
- }
-
- // If backpressure is enabled and we already have a buffer to commit, keep
- // the transaction in the queue.
- const bool hasPendingBuffer =
- flushState.bufferLayersReadyToPresent.contains(s.surface.get());
- if (layer->backpressureEnabled() && hasPendingBuffer && transaction.isAutoTimestamp) {
- SFTRACE_FORMAT("hasPendingBuffer %s", layer->getDebugName());
- ready = TransactionReadiness::NotReady;
- return TraverseBuffersReturnValues::STOP_TRAVERSAL;
- }
-
- const bool acquireFenceAvailable = s.bufferData &&
- s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) &&
- s.bufferData->acquireFence;
- const bool fenceSignaled = !acquireFenceAvailable ||
- s.bufferData->acquireFence->getStatus() != Fence::Status::Unsignaled;
- if (!fenceSignaled) {
- // check fence status
- const bool allowLatchUnsignaled = shouldLatchUnsignaled(s, transaction.states.size(),
- flushState.firstTransaction) &&
- layer->isSimpleBufferUpdate(s);
-
- if (allowLatchUnsignaled) {
- SFTRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s",
- layer->getDebugName());
- ready = TransactionReadiness::NotReadyUnsignaled;
- } else {
- ready = TransactionReadiness::NotReady;
- auto& listener = s.bufferData->releaseBufferListener;
- if (listener &&
- (flushState.queueProcessTime - transaction.postTime) >
- std::chrono::nanoseconds(4s).count()) {
- // Used to add a stalled transaction which uses an internal lock.
- ftl::FakeGuard guard(kMainThreadContext);
- mTransactionHandler
- .onTransactionQueueStalled(transaction.id,
- {.pid = layer->getOwnerPid(),
- .layerId = static_cast<uint32_t>(
- layer->getSequence()),
- .layerName = layer->getDebugName(),
- .bufferId = s.bufferData->getId(),
- .frameNumber = s.bufferData->frameNumber});
- }
- SFTRACE_FORMAT("fence unsignaled %s", layer->getDebugName());
- return TraverseBuffersReturnValues::STOP_TRAVERSAL;
- }
- }
- return TraverseBuffersReturnValues::CONTINUE_TRAVERSAL;
- });
- return ready;
-}
-
TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferCheck(
const TransactionHandler::TransactionFlushState& flushState) {
using TransactionReadiness = TransactionHandler::TransactionReadiness;
@@ -5077,15 +4943,8 @@
void SurfaceFlinger::addTransactionReadyFilters() {
mTransactionHandler.addTransactionReadyFilter(
std::bind(&SurfaceFlinger::transactionReadyTimelineCheck, this, std::placeholders::_1));
- if (mLayerLifecycleManagerEnabled) {
- mTransactionHandler.addTransactionReadyFilter(
- std::bind(&SurfaceFlinger::transactionReadyBufferCheck, this,
- std::placeholders::_1));
- } else {
- mTransactionHandler.addTransactionReadyFilter(
- std::bind(&SurfaceFlinger::transactionReadyBufferCheckLegacy, this,
- std::placeholders::_1));
- }
+ mTransactionHandler.addTransactionReadyFilter(
+ std::bind(&SurfaceFlinger::transactionReadyBufferCheck, this, std::placeholders::_1));
}
// For tests only
@@ -5317,11 +5176,6 @@
const std::vector<ListenerCallbacks>& listenerCallbacks,
int originPid, int originUid, uint64_t transactionId) {
uint32_t transactionFlags = 0;
- if (!mLayerLifecycleManagerEnabled) {
- for (DisplayState& display : displays) {
- transactionFlags |= setDisplayStateLocked(display);
- }
- }
// start and end registration for listeners w/ no surface so they can get their callback. Note
// that listeners with SurfaceControls will start registration during setClientStateLocked
@@ -5329,27 +5183,11 @@
for (const auto& listener : listenerCallbacks) {
mTransactionCallbackInvoker.addEmptyTransaction(listener);
}
- nsecs_t now = systemTime();
uint32_t clientStateFlags = 0;
for (auto& resolvedState : states) {
clientStateFlags |=
updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState, desiredPresentTime,
isAutoTimestamp, postTime, transactionId);
- if (!mLayerLifecycleManagerEnabled) {
- if ((flags & eAnimation) && resolvedState.state.surface) {
- if (const auto layer = LayerHandle::getLayer(resolvedState.state.surface)) {
- const auto layerProps = scheduler::LayerProps{
- .visible = layer->isVisible(),
- .bounds = layer->getBounds(),
- .transform = layer->getTransform(),
- .setFrameRateVote = layer->getFrameRateForLayerTree(),
- .frameRateSelectionPriority = layer->getFrameRateSelectionPriority(),
- .isFrontBuffered = layer->isFrontBuffered(),
- };
- layer->recordLayerHistoryAnimationTx(layerProps, now);
- }
- }
- }
}
transactionFlags |= clientStateFlags;
@@ -6665,53 +6503,35 @@
}
void SurfaceFlinger::dumpVisibleFrontEnd(std::string& result) {
- if (!mLayerLifecycleManagerEnabled) {
- StringAppendF(&result, "Composition layers\n");
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- auto* compositionState = layer->getCompositionState();
- if (!compositionState || !compositionState->isVisible) return;
- android::base::StringAppendF(&result, "* Layer %p (%s)\n", layer,
- layer->getDebugName() ? layer->getDebugName()
- : "<unknown>");
- compositionState->dump(result);
- });
-
- StringAppendF(&result, "Offscreen Layers\n");
- for (Layer* offscreenLayer : mOffscreenLayers) {
- offscreenLayer->traverse(LayerVector::StateSet::Drawing,
- [&](Layer* layer) { layer->dumpOffscreenDebugInfo(result); });
- }
- } else {
- std::ostringstream out;
- out << "\nComposition list\n";
- ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
- mLayerSnapshotBuilder.forEachVisibleSnapshot(
- [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
- if (snapshot->hasSomethingToDraw()) {
- if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) {
- lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack;
- out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n";
- }
- out << " " << *snapshot << "\n";
+ std::ostringstream out;
+ out << "\nComposition list\n";
+ ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
+ mLayerSnapshotBuilder.forEachVisibleSnapshot(
+ [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
+ if (snapshot->hasSomethingToDraw()) {
+ if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) {
+ lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack;
+ out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n";
}
- });
+ out << " " << *snapshot << "\n";
+ }
+ });
- out << "\nInput list\n";
- lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
- mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) {
- if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) {
- lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack;
- out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n";
- }
- out << " " << snapshot << "\n";
- });
+ out << "\nInput list\n";
+ lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
+ mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) {
+ if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) {
+ lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack;
+ out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n";
+ }
+ out << " " << snapshot << "\n";
+ });
- out << "\nLayer Hierarchy\n"
- << mLayerHierarchyBuilder.getHierarchy() << "\nOffscreen Hierarchy\n"
- << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n";
- result = out.str();
- dumpHwcLayersMinidump(result);
- }
+ out << "\nLayer Hierarchy\n"
+ << mLayerHierarchyBuilder.getHierarchy() << "\nOffscreen Hierarchy\n"
+ << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n";
+ result = out.str();
+ dumpHwcLayersMinidump(result);
}
perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
@@ -6814,27 +6634,7 @@
result.append(future.get());
}
-void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) const {
- for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
- const auto displayId = HalDisplayId::tryCast(display->getId());
- if (!displayId) {
- continue;
- }
-
- StringAppendF(&result, "Display %s (%s) HWC layers:\n", to_string(*displayId).c_str(),
- displayId == mActiveDisplayId ? "active" : "inactive");
- Layer::miniDumpHeader(result);
-
- const DisplayDevice& ref = *display;
- mDrawingState.traverseInZOrder([&](Layer* layer) { layer->miniDumpLegacy(result, ref); });
- result.append("\n");
- }
-}
-
void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const {
- if (!mLayerLifecycleManagerEnabled) {
- return dumpHwcLayersMinidumpLockedLegacy(result);
- }
for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
const auto displayId = HalDisplayId::tryCast(display->getId());
if (!displayId) {
@@ -6914,8 +6714,7 @@
* Dump the visible layer list
*/
colorizer.bold(result);
- StringAppendF(&result, "SurfaceFlinger New Frontend Enabled:%s\n",
- mLayerLifecycleManagerEnabled ? "true" : "false");
+ StringAppendF(&result, "SurfaceFlinger New Frontend Enabled:%s\n", "true");
StringAppendF(&result, "Active Layers - layers with client handles (count = %zu)\n",
mNumLayers.load());
colorizer.reset(result);
@@ -8639,12 +8438,8 @@
}
void SurfaceFlinger::traverseLegacyLayers(const LayerVector::Visitor& visitor) const {
- if (mLayerLifecycleManagerEnabled) {
- for (auto& layer : mLegacyLayers) {
- visitor(layer.second.get());
- }
- } else {
- mDrawingState.traverse(visitor);
+ for (auto& layer : mLegacyLayers) {
+ visitor(layer.second.get());
}
}
@@ -8662,42 +8457,6 @@
layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
}
-void SurfaceFlinger::traverseLayersInLayerStack(ui::LayerStack layerStack, const int32_t uid,
- std::unordered_set<uint32_t> excludeLayerIds,
- const LayerVector::Visitor& visitor) {
- // We loop through the first level of layers without traversing,
- // as we need to determine which layers belong to the requested display.
- for (const auto& layer : mDrawingState.layersSortedByZ) {
- if (layer->getLayerStack() != layerStack) {
- continue;
- }
- // relative layers are traversed in Layer::traverseInZOrder
- layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
- if (layer->isInternalDisplayOverlay()) {
- return;
- }
- if (!layer->isVisible()) {
- return;
- }
- if (uid != CaptureArgs::UNSET_UID && layer->getOwnerUid() != uid) {
- return;
- }
-
- if (!excludeLayerIds.empty()) {
- auto p = sp<Layer>::fromExisting(layer);
- while (p != nullptr) {
- if (excludeLayerIds.count(p->sequence) != 0) {
- return;
- }
- p = p->getParent();
- }
- }
-
- visitor(layer);
- });
- }
-}
-
ftl::Optional<scheduler::FrameRateMode> SurfaceFlinger::getPreferredDisplayMode(
PhysicalDisplayId displayId, DisplayModeId defaultModeId) const {
if (const auto schedulerMode = mScheduler->getPreferredDisplayMode();
@@ -9361,89 +9120,49 @@
void SurfaceFlinger::moveSnapshotsFromCompositionArgs(
compositionengine::CompositionRefreshArgs& refreshArgs,
const std::vector<std::pair<Layer*, LayerFE*>>& layers) {
- if (mLayerLifecycleManagerEnabled) {
- std::vector<std::unique_ptr<frontend::LayerSnapshot>>& snapshots =
- mLayerSnapshotBuilder.getSnapshots();
- for (auto [_, layerFE] : layers) {
- auto i = layerFE->mSnapshot->globalZ;
- snapshots[i] = std::move(layerFE->mSnapshot);
- }
- }
- if (!mLayerLifecycleManagerEnabled) {
- for (auto [layer, layerFE] : layers) {
- layer->updateLayerSnapshot(std::move(layerFE->mSnapshot));
- }
+ std::vector<std::unique_ptr<frontend::LayerSnapshot>>& snapshots =
+ mLayerSnapshotBuilder.getSnapshots();
+ for (auto [_, layerFE] : layers) {
+ auto i = layerFE->mSnapshot->globalZ;
+ snapshots[i] = std::move(layerFE->mSnapshot);
}
}
std::vector<std::pair<Layer*, LayerFE*>> SurfaceFlinger::moveSnapshotsToCompositionArgs(
compositionengine::CompositionRefreshArgs& refreshArgs, bool cursorOnly) {
std::vector<std::pair<Layer*, LayerFE*>> layers;
- if (mLayerLifecycleManagerEnabled) {
- nsecs_t currentTime = systemTime();
- const bool needsMetadata = mCompositionEngine->getFeatureFlags().test(
- compositionengine::Feature::kSnapshotLayerMetadata);
- mLayerSnapshotBuilder.forEachSnapshot(
- [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) FTL_FAKE_GUARD(
- kMainThreadContext) {
- if (cursorOnly &&
- snapshot->compositionType !=
- aidl::android::hardware::graphics::composer3::Composition::CURSOR) {
- return;
- }
-
- if (!snapshot->hasSomethingToDraw()) {
- return;
- }
-
- auto it = mLegacyLayers.find(snapshot->sequence);
- LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(),
- "Couldnt find layer object for %s",
- snapshot->getDebugString().c_str());
- auto& legacyLayer = it->second;
- sp<LayerFE> layerFE = legacyLayer->getCompositionEngineLayerFE(snapshot->path);
- snapshot->fps = getLayerFramerate(currentTime, snapshot->sequence);
- layerFE->mSnapshot = std::move(snapshot);
- refreshArgs.layers.push_back(layerFE);
- layers.emplace_back(legacyLayer.get(), layerFE.get());
- },
- [needsMetadata](const frontend::LayerSnapshot& snapshot) {
- return snapshot.isVisible ||
- (needsMetadata &&
- snapshot.changes.test(
- frontend::RequestedLayerState::Changes::Metadata));
- });
- }
- if (!mLayerLifecycleManagerEnabled) {
- auto moveSnapshots = [&layers, &refreshArgs, cursorOnly](Layer* layer) {
- if (const auto& layerFE = layer->getCompositionEngineLayerFE()) {
+ nsecs_t currentTime = systemTime();
+ const bool needsMetadata = mCompositionEngine->getFeatureFlags().test(
+ compositionengine::Feature::kSnapshotLayerMetadata);
+ mLayerSnapshotBuilder.forEachSnapshot(
+ [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) FTL_FAKE_GUARD(
+ kMainThreadContext) {
if (cursorOnly &&
- layer->getLayerSnapshot()->compositionType !=
- aidl::android::hardware::graphics::composer3::Composition::CURSOR)
+ snapshot->compositionType !=
+ aidl::android::hardware::graphics::composer3::Composition::CURSOR) {
return;
- layer->updateSnapshot(refreshArgs.updatingGeometryThisFrame);
- layerFE->mSnapshot = layer->stealLayerSnapshot();
+ }
+
+ if (!snapshot->hasSomethingToDraw()) {
+ return;
+ }
+
+ auto it = mLegacyLayers.find(snapshot->sequence);
+ LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(),
+ "Couldnt find layer object for %s",
+ snapshot->getDebugString().c_str());
+ auto& legacyLayer = it->second;
+ sp<LayerFE> layerFE = legacyLayer->getCompositionEngineLayerFE(snapshot->path);
+ snapshot->fps = getLayerFramerate(currentTime, snapshot->sequence);
+ layerFE->mSnapshot = std::move(snapshot);
refreshArgs.layers.push_back(layerFE);
- layers.emplace_back(layer, layerFE.get());
- }
- };
-
- if (cursorOnly || !mVisibleRegionsDirty) {
- // for hot path avoid traversals by walking though the previous composition list
- for (sp<Layer> layer : mPreviouslyComposedLayers) {
- moveSnapshots(layer.get());
- }
- } else {
- mPreviouslyComposedLayers.clear();
- mDrawingState.traverseInZOrder(
- [&moveSnapshots](Layer* layer) { moveSnapshots(layer); });
- mPreviouslyComposedLayers.reserve(layers.size());
- for (auto [layer, _] : layers) {
- mPreviouslyComposedLayers.push_back(sp<Layer>::fromExisting(layer));
- }
- }
- }
-
+ layers.emplace_back(legacyLayer.get(), layerFE.get());
+ },
+ [needsMetadata](const frontend::LayerSnapshot& snapshot) {
+ return snapshot.isVisible ||
+ (needsMetadata &&
+ snapshot.changes.test(frontend::RequestedLayerState::Changes::Metadata));
+ });
return layers;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index af504ca..9f85a9f 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -827,9 +827,6 @@
TransactionHandler::TransactionReadiness transactionReadyTimelineCheck(
const TransactionHandler::TransactionFlushState& flushState)
REQUIRES(kMainThreadContext);
- TransactionHandler::TransactionReadiness transactionReadyBufferCheckLegacy(
- const TransactionHandler::TransactionFlushState& flushState)
- REQUIRES(kMainThreadContext);
TransactionHandler::TransactionReadiness transactionReadyBufferCheck(
const TransactionHandler::TransactionFlushState& flushState)
REQUIRES(kMainThreadContext);
@@ -935,12 +932,6 @@
std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
std::vector<sp<LayerFE>>& layerFEs);
- // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a
- // matching ownerUid
- void traverseLayersInLayerStack(ui::LayerStack, const int32_t uid,
- std::unordered_set<uint32_t> excludeLayerIds,
- const LayerVector::Visitor&);
-
void readPersistentProperties();
uint32_t getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const;
@@ -1157,7 +1148,6 @@
void dumpAll(const DumpArgs& args, const std::string& compositionLayers,
std::string& result) const EXCLUDES(mStateLock);
void dumpHwcLayersMinidump(std::string& result) const REQUIRES(mStateLock, kMainThreadContext);
- void dumpHwcLayersMinidumpLockedLegacy(std::string& result) const REQUIRES(mStateLock);
void appendSfConfigString(std::string& result) const;
void listLayers(std::string& result) const REQUIRES(kMainThreadContext);
@@ -1506,8 +1496,6 @@
}
bool mPowerHintSessionEnabled;
-
- bool mLayerLifecycleManagerEnabled = false;
// Whether a display should be turned on when initialized
bool mSkipPowerOnForQuiescent;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index cdd77fe..23d3c16 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -15,7 +15,6 @@
*/
// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#include "renderengine/ExternalTexture.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wextra"
@@ -31,6 +30,7 @@
#include <gui/IProducerListener.h>
#include <gui/LayerMetadata.h>
#include <log/log.h>
+#include <renderengine/ExternalTexture.h>
#include <renderengine/mock/FakeExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <system/window.h>
@@ -149,7 +149,6 @@
sp<compositionengine::mock::DisplaySurface> mDisplaySurface =
sp<compositionengine::mock::DisplaySurface>::make();
sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
- std::vector<sp<Layer>> mAuxiliaryLayers;
sp<GraphicBuffer> mBuffer =
sp<GraphicBuffer>::make(1u, 1u, PIXEL_FORMAT_RGBA_8888,
@@ -194,6 +193,7 @@
template <typename LayerCase>
void CompositionTest::captureScreenComposition() {
LayerCase::setupForScreenCapture(this);
+ mFlinger.commit();
const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT);
constexpr bool regionSampling = false;
@@ -204,13 +204,8 @@
RenderArea::Options::CAPTURE_SECURE_LAYERS |
RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION);
- auto traverseLayers = [this](const LayerVector::Visitor& visitor) {
- return mFlinger.traverseLayersInLayerStack(mDisplay->getLayerStack(),
- CaptureArgs::UNSET_UID, {}, visitor);
- };
-
- // TODO: Use SurfaceFlinger::getLayerSnapshotsForScreenshots instead of this legacy function
- auto getLayerSnapshotsFn = RenderArea::fromTraverseLayersLambda(traverseLayers);
+ auto getLayerSnapshotsFn = mFlinger.getLayerSnapshotsForScreenshotsFn(mDisplay->getLayerStack(),
+ CaptureArgs::UNSET_UID);
const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
@@ -462,7 +457,7 @@
static constexpr IComposerClient::BlendMode BLENDMODE =
IComposerClient::BlendMode::PREMULTIPLIED;
- static void setupLatchedBuffer(CompositionTest* test, sp<Layer> layer) {
+ static void setupLatchedBuffer(CompositionTest* test, frontend::RequestedLayerState& layer) {
Mock::VerifyAndClear(test->mRenderEngine);
const auto buffer = std::make_shared<
@@ -472,21 +467,15 @@
LayerProperties::FORMAT,
LayerProperties::USAGE |
GraphicBuffer::USAGE_HW_TEXTURE);
-
- auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
- layerDrawingState.crop = Rect(0, 0, LayerProperties::HEIGHT, LayerProperties::WIDTH);
- layerDrawingState.buffer = buffer;
- layerDrawingState.acquireFence = Fence::NO_FENCE;
- layerDrawingState.dataspace = ui::Dataspace::UNKNOWN;
- layer->setSurfaceDamageRegion(
- Region(Rect(LayerProperties::HEIGHT, LayerProperties::WIDTH)));
-
- bool ignoredRecomputeVisibleRegions;
- layer->latchBuffer(ignoredRecomputeVisibleRegions, 0);
+ layer.crop = Rect(0, 0, LayerProperties::HEIGHT, LayerProperties::WIDTH);
+ layer.externalTexture = buffer;
+ layer.bufferData->acquireFence = Fence::NO_FENCE;
+ layer.dataspace = ui::Dataspace::UNKNOWN;
+ layer.surfaceDamageRegion = Region(Rect(LayerProperties::HEIGHT, LayerProperties::WIDTH));
Mock::VerifyAndClear(test->mRenderEngine);
}
- static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
+ static void setupLayerState(CompositionTest* test, frontend::RequestedLayerState& layer) {
setupLatchedBuffer(test, layer);
}
@@ -670,14 +659,12 @@
using Base = BaseLayerProperties<SidebandLayerProperties>;
static constexpr IComposerClient::BlendMode BLENDMODE = IComposerClient::BlendMode::NONE;
- static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
+ static void setupLayerState(CompositionTest* test, frontend::RequestedLayerState& layer) {
sp<NativeHandle> stream =
NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
false);
- test->mFlinger.setLayerSidebandStream(layer, stream);
- auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
- layerDrawingState.crop =
- Rect(0, 0, SidebandLayerProperties::HEIGHT, SidebandLayerProperties::WIDTH);
+ layer.sidebandStream = stream;
+ layer.crop = Rect(0, 0, SidebandLayerProperties::HEIGHT, SidebandLayerProperties::WIDTH);
}
static void setupHwcSetSourceCropBufferCallExpectations(CompositionTest* test) {
@@ -755,17 +742,17 @@
struct CursorLayerProperties : public BaseLayerProperties<CursorLayerProperties> {
using Base = BaseLayerProperties<CursorLayerProperties>;
- static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
+ static void setupLayerState(CompositionTest* test, frontend::RequestedLayerState& layer) {
Base::setupLayerState(test, layer);
- test->mFlinger.setLayerPotentialCursor(layer, true);
+ layer.potentialCursor = true;
}
};
struct NoLayerVariant {
- using FlingerLayerType = sp<Layer>;
-
- static FlingerLayerType createLayer(CompositionTest*) { return FlingerLayerType(); }
- static void injectLayer(CompositionTest*, FlingerLayerType) {}
+ static frontend::RequestedLayerState createLayer(CompositionTest*) {
+ return {LayerCreationArgs()};
+ }
+ static void injectLayer(CompositionTest*, frontend::RequestedLayerState&) {}
static void cleanupInjectedLayers(CompositionTest*) {}
static void setupCallExpectationsForDirtyGeometry(CompositionTest*) {}
@@ -775,10 +762,10 @@
template <typename LayerProperties>
struct BaseLayerVariant {
template <typename L, typename F>
- static sp<L> createLayerWithFactory(CompositionTest* test, F factory) {
+ static frontend::RequestedLayerState createLayerWithFactory(CompositionTest* test, F factory) {
EXPECT_CALL(*test->mFlinger.scheduler(), postMessage(_)).Times(0);
- sp<L> layer = factory();
+ auto layer = factory();
// Layer should be registered with scheduler.
EXPECT_EQ(1u, test->mFlinger.scheduler()->layerHistorySize());
@@ -792,27 +779,26 @@
return layer;
}
- template <typename L>
- static void initLayerDrawingStateAndComputeBounds(CompositionTest* test, sp<L> layer) {
- auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
- layerDrawingState.layerStack = LAYER_STACK;
- layerDrawingState.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
- LayerProperties::COLOR[2], LayerProperties::COLOR[3]);
- layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform(), 0.f /* shadowRadius */);
+ static void initLayerDrawingStateAndComputeBounds(CompositionTest* test,
+ frontend::RequestedLayerState& layer) {
+ layer.layerStack = LAYER_STACK;
+ layer.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
+ LayerProperties::COLOR[2], LayerProperties::COLOR[3]);
}
- static void injectLayer(CompositionTest* test, sp<Layer> layer) {
+ static void injectLayer(CompositionTest* test, frontend::RequestedLayerState& layer) {
EXPECT_CALL(*test->mComposer, createLayer(HWC_DISPLAY, _))
.WillOnce(DoAll(SetArgPointee<1>(HWC_LAYER), Return(Error::NONE)));
-
+ auto legacyLayer = test->mFlinger.getLegacyLayer(layer.id);
auto outputLayer = test->mDisplay->getCompositionDisplay()->injectOutputLayerForTest(
- layer->getCompositionEngineLayerFE());
+ legacyLayer->getCompositionEngineLayerFE({.id = layer.id}));
outputLayer->editState().visibleRegion = Region(Rect(0, 0, 100, 100));
outputLayer->editState().outputSpaceVisibleRegion = Region(Rect(0, 0, 100, 100));
Mock::VerifyAndClear(test->mComposer);
- test->mFlinger.mutableDrawingState().layersSortedByZ.add(layer);
+ auto layerCopy = std::make_unique<frontend::RequestedLayerState>(layer);
+ test->mFlinger.addLayer(layerCopy);
test->mFlinger.mutableVisibleRegionsDirty() = true;
}
@@ -820,10 +806,9 @@
EXPECT_CALL(*test->mComposer, destroyLayer(HWC_DISPLAY, HWC_LAYER))
.WillOnce(Return(Error::NONE));
+ test->mFlinger.destroyAllLayerHandles();
test->mDisplay->getCompositionDisplay()->clearOutputLayers();
- test->mFlinger.mutableDrawingState().layersSortedByZ.clear();
test->mFlinger.mutablePreviouslyComposedLayers().clear();
-
// Layer should be unregistered with scheduler.
test->mFlinger.commit();
EXPECT_EQ(0u, test->mFlinger.scheduler()->layerHistorySize());
@@ -833,17 +818,17 @@
template <typename LayerProperties>
struct EffectLayerVariant : public BaseLayerVariant<LayerProperties> {
using Base = BaseLayerVariant<LayerProperties>;
- using FlingerLayerType = sp<Layer>;
-
- static FlingerLayerType createLayer(CompositionTest* test) {
- FlingerLayerType layer = Base::template createLayerWithFactory<Layer>(test, [test]() {
- return sp<Layer>::make(LayerCreationArgs(test->mFlinger.flinger(), sp<Client>(),
- "test-layer", LayerProperties::LAYER_FLAGS,
- LayerMetadata()));
+ static frontend::RequestedLayerState createLayer(CompositionTest* test) {
+ frontend::RequestedLayerState layer = Base::template createLayerWithFactory<
+ frontend::RequestedLayerState>(test, [test]() {
+ auto args = LayerCreationArgs(test->mFlinger.flinger(), sp<Client>(), "test-layer",
+ LayerProperties::LAYER_FLAGS, LayerMetadata());
+ auto legacyLayer = sp<Layer>::make(args);
+ test->mFlinger.injectLegacyLayer(legacyLayer);
+ return frontend::RequestedLayerState(args);
});
- auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
- layerDrawingState.crop = Rect(0, 0, LayerProperties::HEIGHT, LayerProperties::WIDTH);
+ layer.crop = Rect(0, 0, LayerProperties::HEIGHT, LayerProperties::WIDTH);
return layer;
}
@@ -869,13 +854,15 @@
template <typename LayerProperties>
struct BufferLayerVariant : public BaseLayerVariant<LayerProperties> {
using Base = BaseLayerVariant<LayerProperties>;
- using FlingerLayerType = sp<Layer>;
- static FlingerLayerType createLayer(CompositionTest* test) {
- FlingerLayerType layer = Base::template createLayerWithFactory<Layer>(test, [test]() {
+ static frontend::RequestedLayerState createLayer(CompositionTest* test) {
+ frontend::RequestedLayerState layer = Base::template createLayerWithFactory<
+ frontend::RequestedLayerState>(test, [test]() {
LayerCreationArgs args(test->mFlinger.flinger(), sp<Client>(), "test-layer",
LayerProperties::LAYER_FLAGS, LayerMetadata());
- return sp<Layer>::make(args);
+ auto legacyLayer = sp<Layer>::make(args);
+ test->mFlinger.injectLegacyLayer(legacyLayer);
+ return frontend::RequestedLayerState(args);
});
LayerProperties::setupLayerState(test, layer);
@@ -917,13 +904,14 @@
template <typename LayerProperties>
struct ContainerLayerVariant : public BaseLayerVariant<LayerProperties> {
using Base = BaseLayerVariant<LayerProperties>;
- using FlingerLayerType = sp<Layer>;
- static FlingerLayerType createLayer(CompositionTest* test) {
+ static frontend::RequestedLayerState createLayer(CompositionTest* test) {
LayerCreationArgs args(test->mFlinger.flinger(), sp<Client>(), "test-container-layer",
LayerProperties::LAYER_FLAGS, LayerMetadata());
- FlingerLayerType layer = sp<Layer>::make(args);
- Base::template initLayerDrawingStateAndComputeBounds(test, layer);
+ sp<Layer> legacyLayer = sp<Layer>::make(args);
+ test->mFlinger.injectLegacyLayer(legacyLayer);
+ frontend::RequestedLayerState layer(args);
+ Base::initLayerDrawingStateAndComputeBounds(test, layer);
return layer;
}
};
@@ -931,29 +919,19 @@
template <typename LayerVariant, typename ParentLayerVariant>
struct ChildLayerVariant : public LayerVariant {
using Base = LayerVariant;
- using FlingerLayerType = typename LayerVariant::FlingerLayerType;
using ParentBase = ParentLayerVariant;
- static FlingerLayerType createLayer(CompositionTest* test) {
+ static frontend::RequestedLayerState createLayer(CompositionTest* test) {
// Need to create child layer first. Otherwise layer history size will be 2.
- FlingerLayerType layer = Base::createLayer(test);
-
- typename ParentBase::FlingerLayerType parentLayer = ParentBase::createLayer(test);
- parentLayer->addChild(layer);
- test->mFlinger.setLayerDrawingParent(layer, parentLayer);
-
- test->mAuxiliaryLayers.push_back(parentLayer);
-
+ frontend::RequestedLayerState layer = Base::createLayer(test);
+ frontend::RequestedLayerState parentLayer = ParentBase::createLayer(test);
+ layer.parentId = parentLayer.id;
+ auto layerCopy = std::make_unique<frontend::RequestedLayerState>(parentLayer);
+ test->mFlinger.addLayer(layerCopy);
return layer;
}
- static void cleanupInjectedLayers(CompositionTest* test) {
- // Clear auxiliary layers first so that child layer can be successfully destroyed in the
- // following call.
- test->mAuxiliaryLayers.clear();
-
- Base::cleanupInjectedLayers(test);
- }
+ static void cleanupInjectedLayers(CompositionTest* test) { Base::cleanupInjectedLayers(test); }
};
/* ------------------------------------------------------------------------
@@ -1016,7 +994,7 @@
*/
struct CompositionResultBaseVariant {
- static void setupLayerState(CompositionTest*, sp<Layer>) {}
+ static void setupLayerState(CompositionTest*, frontend::RequestedLayerState&) {}
template <typename Case>
static void setupCallExpectationsForDirtyGeometry(CompositionTest* test) {
@@ -1056,9 +1034,8 @@
};
struct ForcedClientCompositionResultVariant : public CompositionResultBaseVariant {
- static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
- const auto outputLayer =
- TestableSurfaceFlinger::findOutputLayerForDisplay(layer, test->mDisplay);
+ static void setupLayerState(CompositionTest* test, frontend::RequestedLayerState& layer) {
+ const auto outputLayer = test->mFlinger.findOutputLayerForDisplay(layer.id, test->mDisplay);
LOG_FATAL_IF(!outputLayer);
outputLayer->editState().forceClientComposition = true;
}
@@ -1079,7 +1056,7 @@
};
struct ForcedClientCompositionViaDebugOptionResultVariant : public CompositionResultBaseVariant {
- static void setupLayerState(CompositionTest* test, sp<Layer>) {
+ static void setupLayerState(CompositionTest* test, frontend::RequestedLayerState&) {
test->mFlinger.mutableDebugDisableHWC() = true;
}
@@ -1099,7 +1076,7 @@
};
struct EmptyScreenshotResultVariant {
- static void setupLayerState(CompositionTest*, sp<Layer>) {}
+ static void setupLayerState(CompositionTest*, frontend::RequestedLayerState&) {}
template <typename Case>
static void setupCallExpectations(CompositionTest*) {}
@@ -1365,28 +1342,6 @@
* Layers with a parent layer with ISurfaceComposerClient::eSecure, on a non-secure display
*/
-TEST_F(CompositionTest,
- HWCComposedBufferLayerWithSecureParentLayerOnInsecureDisplayWithDirtyGeometry) {
- displayRefreshCompositionDirtyGeometry<CompositionCase<
- InsecureDisplaySetupVariant,
- ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
- ContainerLayerVariant<SecureLayerProperties>>,
- KeepCompositionTypeVariant<
- aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
- ForcedClientCompositionResultVariant>>();
-}
-
-TEST_F(CompositionTest,
- HWCComposedBufferLayerWithSecureParentLayerOnInsecureDisplayWithDirtyFrame) {
- displayRefreshCompositionDirtyFrame<CompositionCase<
- InsecureDisplaySetupVariant,
- ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
- ContainerLayerVariant<SecureLayerProperties>>,
- KeepCompositionTypeVariant<
- aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
- ForcedClientCompositionResultVariant>>();
-}
-
TEST_F(CompositionTest, captureScreenBufferLayerWithSecureParentLayerOnInsecureDisplay) {
captureScreenComposition<
CompositionCase<InsecureDisplaySetupVariant,
diff --git a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
index e74f643..c879280 100644
--- a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
@@ -706,7 +706,7 @@
testGpuScenario(config, res);
EXPECT_EQ(res.gpuDurationNanos, 0L);
EXPECT_EQ(res.cpuDurationNanos, 0L);
- EXPECT_GE(res.durationNanos, toNanos(30ms + getErrorMargin()));
+ EXPECT_GE(res.durationNanos, toNanos(29ms + getErrorMargin()));
EXPECT_LE(res.durationNanos, toNanos(31ms + getErrorMargin()));
}
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index fc54a8b..3df724a 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -34,6 +34,7 @@
#include "mock/MockSchedulerCallback.h"
#include <FrontEnd/LayerHierarchy.h>
+#include <scheduler/FrameTime.h>
#include <com_android_graphics_surfaceflinger_flags.h>
#include "FpsOps.h"
@@ -607,7 +608,8 @@
TimePoint::fromNs(2000)));
// Not crossing the min frame period
- vrrTracker->onFrameBegin(TimePoint::fromNs(2000), TimePoint::fromNs(1500));
+ vrrTracker->onFrameBegin(TimePoint::fromNs(2000),
+ {TimePoint::fromNs(1500), TimePoint::fromNs(1500)});
EXPECT_EQ(Fps::fromPeriodNsecs(1000),
scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
TimePoint::fromNs(2500)));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp
index ff7612e..d638024 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp
@@ -28,7 +28,6 @@
class ColorMatrixTest : public CommitAndCompositeTest {};
TEST_F(ColorMatrixTest, colorMatrixChanged) {
- mFlinger.enableLayerLifecycleManager();
EXPECT_COLOR_MATRIX_CHANGED(true, true);
mFlinger.mutableTransactionFlags() |= eTransactionNeeded;
@@ -46,7 +45,6 @@
}
TEST_F(ColorMatrixTest, colorMatrixChangedAfterDisplayTransaction) {
- mFlinger.enableLayerLifecycleManager();
EXPECT_COLOR_MATRIX_CHANGED(true, true);
mFlinger.mutableTransactionFlags() |= eTransactionNeeded;
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 4197cbd..e3b2af1 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -326,9 +326,13 @@
auto& mutableStateLock() { return mFlinger->mStateLock; }
- static auto findOutputLayerForDisplay(const sp<Layer>& layer,
- const sp<const DisplayDevice>& display) {
- return layer->findOutputLayerForDisplay(display.get());
+ compositionengine::OutputLayer* findOutputLayerForDisplay(
+ uint32_t layerId, const sp<const DisplayDevice>& display) {
+ ftl::FakeGuard guard(kMainThreadContext);
+ if (mFlinger->mLegacyLayers.find(layerId) == mFlinger->mLegacyLayers.end()) {
+ return nullptr;
+ }
+ return mFlinger->mLegacyLayers[layerId]->findOutputLayerForDisplay(display.get());
}
static void setLayerSidebandStream(const sp<Layer>& layer,
@@ -340,17 +344,14 @@
void setLayerCompositionType(const sp<Layer>& layer,
aidl::android::hardware::graphics::composer3::Composition type) {
- auto outputLayer = findOutputLayerForDisplay(layer, mFlinger->getDefaultDisplayDevice());
+ auto outputLayer = findOutputLayerForDisplay(static_cast<uint32_t>(layer->sequence),
+ mFlinger->getDefaultDisplayDevice());
LOG_ALWAYS_FATAL_IF(!outputLayer);
auto& state = outputLayer->editState();
LOG_ALWAYS_FATAL_IF(!outputLayer->getState().hwc);
(*state.hwc).hwcCompositionType = type;
}
- static void setLayerPotentialCursor(const sp<Layer>& layer, bool potentialCursor) {
- layer->mPotentialCursor = potentialCursor;
- }
-
static void setLayerDrawingParent(const sp<Layer>& layer, const sp<Layer>& drawingParent) {
layer->mDrawingParent = drawingParent;
}
@@ -395,7 +396,7 @@
targets.try_emplace(id, &frameTargeter.target());
targeters.try_emplace(id, &frameTargeter);
}
-
+ mFlinger->setTransactionFlags(eTransactionFlushNeeded);
mFlinger->commit(displayId, targets);
if (composite) {
@@ -505,10 +506,9 @@
captureResults, displayState, layers, layerFEs);
}
- auto traverseLayersInLayerStack(ui::LayerStack layerStack, int32_t uid,
- std::unordered_set<uint32_t> excludeLayerIds,
- const LayerVector::Visitor& visitor) {
- return mFlinger->traverseLayersInLayerStack(layerStack, uid, excludeLayerIds, visitor);
+ auto getLayerSnapshotsForScreenshotsFn(ui::LayerStack layerStack, uint32_t uid) {
+ return mFlinger->getLayerSnapshotsForScreenshots(layerStack, uid,
+ std::unordered_set<uint32_t>{});
}
auto getDisplayNativePrimaries(const sp<IBinder>& displayToken,
@@ -620,6 +620,18 @@
mFlinger->mNewLayers.emplace_back(std::move(layer));
}
+ // Used to add a layer before updateLayerSnapshots is called.
+ // Must have transactionsFlushed enabled for the new layer to be updated.
+ void addLayer(uint32_t layerId) {
+ std::scoped_lock<std::mutex> lock(mFlinger->mCreatedLayersLock);
+ LayerCreationArgs args(std::make_optional(layerId));
+ args.flinger = this->mFlinger.get();
+ auto layer = std::make_unique<frontend::RequestedLayerState>(args);
+ auto legacyLayer = sp<Layer>::make(args);
+ injectLegacyLayer(legacyLayer);
+ mFlinger->mNewLayers.emplace_back(std::move(layer));
+ }
+
/* ------------------------------------------------------------------------
* Read-only access to private data to assert post-conditions.
*/
@@ -637,12 +649,24 @@
void injectLegacyLayer(sp<Layer> layer) {
FTL_FAKE_GUARD(kMainThreadContext,
mFlinger->mLegacyLayers[static_cast<uint32_t>(layer->sequence)] = layer);
- };
+ }
void releaseLegacyLayer(uint32_t sequence) {
FTL_FAKE_GUARD(kMainThreadContext, mFlinger->mLegacyLayers.erase(sequence));
+ }
+
+ auto getLegacyLayer(uint32_t layerId) {
+ ftl::FakeGuard guard(kMainThreadContext);
+ return mFlinger->mLegacyLayers[layerId];
};
+ void destroyAllLayerHandles() {
+ ftl::FakeGuard guard(kMainThreadContext);
+ for (auto [layerId, legacyLayer] : mFlinger->mLegacyLayers) {
+ mFlinger->onHandleDestroyed(nullptr, legacyLayer, layerId);
+ }
+ }
+
auto setLayerHistoryDisplayArea(uint32_t displayArea) {
return mFlinger->mScheduler->onActiveDisplayAreaChanged(displayArea);
};
@@ -709,10 +733,6 @@
return mFlinger->initTransactionTraceWriter();
}
- // Needed since mLayerLifecycleManagerEnabled is false by default and must
- // be enabled for tests to go through the new front end path.
- void enableLayerLifecycleManager() { mFlinger->mLayerLifecycleManagerEnabled = true; }
-
void notifyExpectedPresentIfRequired(PhysicalDisplayId displayId, Period vsyncPeriod,
TimePoint expectedPresentTime, Fps frameInterval,
std::optional<Period> timeoutOpt) {
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 7fb9247..e13fe49 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -17,6 +17,7 @@
#undef LOG_TAG
#define LOG_TAG "TransactionApplicationTest"
+#include <binder/Binder.h>
#include <common/test/FlagUtils.h>
#include <compositionengine/Display.h>
#include <compositionengine/mock/DisplaySurface.h>
@@ -26,10 +27,10 @@
#include <gui/SurfaceComposerClient.h>
#include <gui/fake/BufferData.h>
#include <log/log.h>
+#include <renderengine/mock/RenderEngine.h>
#include <ui/MockFence.h>
#include <utils/String8.h>
#include <vector>
-#include <binder/Binder.h>
#include "FrontEnd/TransactionHandler.h"
#include "TestableSurfaceFlinger.h"
@@ -55,6 +56,7 @@
mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
mFlinger.setupMockScheduler();
+ mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
mFlinger.flinger()->addTransactionReadyFilters();
}
@@ -65,6 +67,7 @@
}
TestableSurfaceFlinger mFlinger;
+ renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
struct TransactionInfo {
Vector<ComposerState> states;
@@ -323,15 +326,17 @@
transaction1.states[0].state.bufferData =
std::make_shared<fake::BufferData>(/* bufferId */ 1, /* width */ 1, /* height */ 1,
/* pixelFormat */ 0, /* outUsage */ 0);
+ mFlinger.addLayer(1);
+ bool out;
+ mFlinger.updateLayerSnapshots(VsyncId{1}, 0, /* transactionsFlushed */ true, out);
transaction1.states[0].externalTexture =
std::make_shared<FakeExternalTexture>(*transaction1.states[0].state.bufferData);
- transaction1.states[0].state.surface =
- sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
- ->getHandle();
+ transaction1.states[0].state.surface = mFlinger.getLegacyLayer(1)->getHandle();
auto fence = sp<mock::MockFence>::make();
EXPECT_CALL(*fence, getStatus()).WillRepeatedly(Return(Fence::Status::Unsignaled));
transaction1.states[0].state.bufferData->acquireFence = std::move(fence);
transaction1.states[0].state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
+ transaction1.states[0].layerId = 1;
transaction1.isAutoTimestamp = true;
// Transaction 2 should be ready to be applied.
@@ -361,8 +366,7 @@
}
mFlinger.getPendingTransactionQueue().clear();
mFlinger.commitTransactionsLocked(eTransactionMask);
- mFlinger.mutableCurrentState().layersSortedByZ.clear();
- mFlinger.mutableDrawingState().layersSortedByZ.clear();
+ mFlinger.destroyAllLayerHandles();
}
static sp<Fence> fence(Fence::Status status) {
@@ -371,8 +375,7 @@
return fence;
}
- ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what,
- std::optional<sp<IBinder>> layerHandle = std::nullopt) {
+ ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what) {
ComposerState state;
state.state.bufferData =
std::make_shared<fake::BufferData>(/* bufferId */ 123L, /* width */ 1,
@@ -380,9 +383,6 @@
/* outUsage */ 0);
state.state.bufferData->acquireFence = std::move(fence);
state.state.layerId = layerId;
- state.state.surface = layerHandle.value_or(
- sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
- ->getHandle());
state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
state.state.what = what;
@@ -418,6 +418,19 @@
size_t expectedTransactionsPending) {
EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
+ std::unordered_set<uint32_t> createdLayers;
+ for (auto transaction : transactions) {
+ for (auto& state : transaction.states) {
+ auto layerId = static_cast<uint32_t>(state.state.layerId);
+ if (createdLayers.find(layerId) == createdLayers.end()) {
+ mFlinger.addLayer(layerId);
+ createdLayers.insert(layerId);
+ }
+ }
+ }
+ bool unused;
+ bool mustComposite = mFlinger.updateLayerSnapshots(VsyncId{1}, /*frameTimeNs=*/0,
+ /*transactionsFlushed=*/true, unused);
for (auto transaction : transactions) {
std::vector<ResolvedComposerState> resolvedStates;
@@ -427,6 +440,9 @@
resolvedState.state = std::move(state.state);
resolvedState.externalTexture =
std::make_shared<FakeExternalTexture>(*resolvedState.state.bufferData);
+ resolvedState.layerId = static_cast<uint32_t>(state.state.layerId);
+ resolvedState.state.surface =
+ mFlinger.getLegacyLayer(resolvedState.layerId)->getHandle();
resolvedStates.emplace_back(resolvedState);
}
@@ -458,9 +474,8 @@
TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleSignaledFromTheQueue) {
const sp<IBinder> kApplyToken =
IInterface::asBinder(TransactionCompletedListener::getIInstance());
- const auto kLayerId = 1;
+ const auto kLayerId = 10;
const auto kExpectedTransactionsPending = 0u;
-
const auto signaledTransaction =
createTransactionInfo(kApplyToken,
{createComposerState(kLayerId, fence(Fence::Status::Signaled),
@@ -773,7 +788,7 @@
TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue) {
const sp<IBinder> kApplyToken =
IInterface::asBinder(TransactionCompletedListener::getIInstance());
- const auto kLayerId = 1;
+ const auto kLayerId = 10;
const auto kExpectedTransactionsPending = 0u;
const auto signaledTransaction =
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
index 3b09554..b63f299 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
@@ -19,6 +19,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <scheduler/FrameTime.h>
#include <scheduler/Timer.h>
#include "Scheduler/VSyncDispatchTimerQueue.h"
@@ -51,7 +52,7 @@
bool isVSyncInPhase(nsecs_t, Fps) final { return false; }
void setDisplayModePtr(ftl::NonNull<DisplayModePtr>) final {}
void setRenderRate(Fps, bool) final {}
- void onFrameBegin(TimePoint, TimePoint) final {}
+ void onFrameBegin(TimePoint, scheduler::FrameTime) final {}
void onFrameMissed(TimePoint) final {}
void dump(std::string&) const final {}
bool isCurrentMode(const ftl::NonNull<DisplayModePtr>&) const final { return false; };
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index f36a8a6..8690dba 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -901,17 +901,20 @@
EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000));
- vrrTracker.onFrameBegin(TimePoint::fromNs(2000), TimePoint::fromNs(1500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(2000),
+ {TimePoint::fromNs(1500), TimePoint::fromNs(1500)});
EXPECT_EQ(3500, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 2000));
EXPECT_EQ(4500, vrrTracker.nextAnticipatedVSyncTimeFrom(3500, 3500));
// Miss when starting 4500 and expect the next vsync will be at 5000 (next one)
- vrrTracker.onFrameBegin(TimePoint::fromNs(3500), TimePoint::fromNs(2500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(3500),
+ {TimePoint::fromNs(2500), TimePoint::fromNs(2500)});
vrrTracker.onFrameMissed(TimePoint::fromNs(4500));
EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4500, 4500));
EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
- vrrTracker.onFrameBegin(TimePoint::fromNs(7000), TimePoint::fromNs(6500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(7000),
+ {TimePoint::fromNs(6500), TimePoint::fromNs(6500)});
EXPECT_EQ(10500, vrrTracker.nextAnticipatedVSyncTimeFrom(9000, 7000));
}
@@ -943,7 +946,7 @@
// SF starts to catch up
EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2700));
- vrrTracker.onFrameBegin(TimePoint::fromNs(3000), TimePoint::fromNs(0));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(3000), {TimePoint::fromNs(0), TimePoint::fromNs(0)});
// SF misses last frame (3000) and observes that when committing (4000)
EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
@@ -952,17 +955,20 @@
// SF wakes up again instead of the (4000) missed frame
EXPECT_EQ(4500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
- vrrTracker.onFrameBegin(TimePoint::fromNs(4500), TimePoint::fromNs(4500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(4500),
+ {TimePoint::fromNs(4500), TimePoint::fromNs(4500)});
// Timeline shifted. The app needs to get the next frame at (7500) as its last frame (6500) will
// be presented at (7500)
EXPECT_EQ(7500, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4500, 4500));
- vrrTracker.onFrameBegin(TimePoint::fromNs(5500), TimePoint::fromNs(4500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(5500),
+ {TimePoint::fromNs(4500), TimePoint::fromNs(4500)});
EXPECT_EQ(8500, vrrTracker.nextAnticipatedVSyncTimeFrom(7500, 7500));
EXPECT_EQ(6500, vrrTracker.nextAnticipatedVSyncTimeFrom(5500, 5500));
- vrrTracker.onFrameBegin(TimePoint::fromNs(6500), TimePoint::fromNs(5500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(6500),
+ {TimePoint::fromNs(5500), TimePoint::fromNs(5500)});
}
TEST_F(VSyncPredictorTest, renderRateIsPreservedForCommittedVsyncs) {
@@ -1020,6 +1026,35 @@
EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(13000));
}
+TEST_F(VSyncPredictorTest, timelineNotAdjustedForEarlyPresent) {
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+
+ const int32_t kGroup = 0;
+ const auto kResolution = ui::Size(1920, 1080);
+ const auto refreshRate = Fps::fromPeriodNsecs(500);
+ const auto minFrameRate = Fps::fromPeriodNsecs(1000);
+ hal::VrrConfig vrrConfig;
+ vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
+ const ftl::NonNull<DisplayModePtr> kMode =
+ ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), refreshRate, kGroup,
+ kResolution, DEFAULT_DISPLAY_ID)
+ .setVrrConfig(std::move(vrrConfig))
+ .build());
+
+ VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
+ kMinimumSamplesForPrediction, kOutlierTolerancePercent};
+
+ vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
+ vrrTracker.addVsyncTimestamp(0);
+ EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
+
+ constexpr auto kLastConfirmedExpectedPresentTime = TimePoint::fromNs(1000);
+ constexpr auto kLastActualSignalTime = TimePoint::fromNs(700); // presented early
+ vrrTracker.onFrameBegin(TimePoint::fromNs(1400),
+ {kLastActualSignalTime, kLastConfirmedExpectedPresentTime});
+ EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1400, 1000));
+ EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 1000));
+}
} // namespace android::scheduler
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h b/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
index 4f44d1b..8d6d1d3 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
@@ -18,6 +18,8 @@
#include <gmock/gmock.h>
+#include <scheduler/FrameTime.h>
+
#include "Scheduler/VSyncTracker.h"
namespace android::mock {
@@ -37,7 +39,7 @@
MOCK_METHOD(bool, isVSyncInPhase, (nsecs_t, Fps), (override));
MOCK_METHOD(void, setDisplayModePtr, (ftl::NonNull<DisplayModePtr>), (override));
MOCK_METHOD(void, setRenderRate, (Fps, bool), (override));
- MOCK_METHOD(void, onFrameBegin, (TimePoint, TimePoint), (override));
+ MOCK_METHOD(void, onFrameBegin, (TimePoint, scheduler::FrameTime), (override));
MOCK_METHOD(void, onFrameMissed, (TimePoint), (override));
MOCK_METHOD(void, dump, (std::string&), (const, override));
MOCK_METHOD(bool, isCurrentMode, (const ftl::NonNull<DisplayModePtr>&), (const, override));
diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp
index 503587f..4735ae5 100644
--- a/services/vibratorservice/Android.bp
+++ b/services/vibratorservice/Android.bp
@@ -45,7 +45,7 @@
"libhidlbase",
"liblog",
"libutils",
- "android.hardware.vibrator-V2-ndk",
+ "android.hardware.vibrator-V3-ndk",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index abe78f0..c97f401 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -32,6 +32,7 @@
using aidl::android::hardware::vibrator::Effect;
using aidl::android::hardware::vibrator::EffectStrength;
using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::VendorEffect;
using std::chrono::milliseconds;
@@ -96,6 +97,11 @@
return mInfoCache.get();
}
+HalResult<void> HalWrapper::performVendorEffect(const VendorEffect&, const std::function<void()>&) {
+ ALOGV("Skipped performVendorEffect because it's not available in Vibrator HAL");
+ return HalResult<void>::unsupported();
+}
+
HalResult<milliseconds> HalWrapper::performComposedEffect(const std::vector<CompositeEffect>&,
const std::function<void()>&) {
ALOGV("Skipped performComposedEffect because it's not available in Vibrator HAL");
@@ -271,6 +277,13 @@
return ret;
}
+HalResult<void> AidlHalWrapper::performVendorEffect(
+ const VendorEffect& effect, const std::function<void()>& completionCallback) {
+ // This method should always support callbacks, so no need to double check.
+ auto cb = ndk::SharedRefBase::make<HalCallbackWrapper>(completionCallback);
+ return HalResultFactory::fromStatus(getHal()->performVendorEffect(effect, cb));
+}
+
HalResult<milliseconds> AidlHalWrapper::performComposedEffect(
const std::vector<CompositeEffect>& primitives,
const std::function<void()>& completionCallback) {
@@ -351,7 +364,7 @@
}
if (halResult.isFailed()) {
// Fail entire request if one request has failed.
- return HalResult<std::vector<milliseconds>>::failed(status.getMessage());
+ return HalResult<std::vector<milliseconds>>::failed(halResult.errorMessage());
}
durations[primitiveIdx] = milliseconds(duration);
}
diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp
index 5bb8ceb..915d6c7 100644
--- a/services/vibratorservice/benchmarks/Android.bp
+++ b/services/vibratorservice/benchmarks/Android.bp
@@ -33,7 +33,7 @@
"liblog",
"libutils",
"libvibratorservice",
- "android.hardware.vibrator-V2-ndk",
+ "android.hardware.vibrator-V3-ndk",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index d4f7f1d..20979bd 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -349,6 +349,7 @@
public:
using Effect = aidl::android::hardware::vibrator::Effect;
using EffectStrength = aidl::android::hardware::vibrator::EffectStrength;
+ using VendorEffect = aidl::android::hardware::vibrator::VendorEffect;
using CompositePrimitive = aidl::android::hardware::vibrator::CompositePrimitive;
using CompositeEffect = aidl::android::hardware::vibrator::CompositeEffect;
using Braking = aidl::android::hardware::vibrator::Braking;
@@ -380,6 +381,9 @@
Effect effect, EffectStrength strength,
const std::function<void()>& completionCallback) = 0;
+ virtual HalResult<void> performVendorEffect(const VendorEffect& effect,
+ const std::function<void()>& completionCallback);
+
virtual HalResult<std::chrono::milliseconds> performComposedEffect(
const std::vector<CompositeEffect>& primitives,
const std::function<void()>& completionCallback);
@@ -455,6 +459,10 @@
Effect effect, EffectStrength strength,
const std::function<void()>& completionCallback) override final;
+ HalResult<void> performVendorEffect(
+ const VendorEffect& effect,
+ const std::function<void()>& completionCallback) override final;
+
HalResult<std::chrono::milliseconds> performComposedEffect(
const std::vector<CompositeEffect>& primitives,
const std::function<void()>& completionCallback) override final;
diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp
index cd05123..92527eb 100644
--- a/services/vibratorservice/test/Android.bp
+++ b/services/vibratorservice/test/Android.bp
@@ -49,7 +49,7 @@
"liblog",
"libvibratorservice",
"libutils",
- "android.hardware.vibrator-V2-ndk",
+ "android.hardware.vibrator-V3-ndk",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
index 91717f6..7bcc59a 100644
--- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "VibratorHalWrapperAidlTest"
#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <android/persistable_bundle_aidl.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -38,6 +39,8 @@
using aidl::android::hardware::vibrator::IVibrator;
using aidl::android::hardware::vibrator::IVibratorCallback;
using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::VendorEffect;
+using aidl::android::os::PersistableBundle;
using namespace android;
using namespace std::chrono_literals;
@@ -489,6 +492,42 @@
ASSERT_EQ(1, *callbackCounter.get());
}
+TEST_F(VibratorHalWrapperAidlTest, TestPerformVendorEffect) {
+ PersistableBundle vendorData;
+ vendorData.putInt("key", 1);
+ VendorEffect vendorEffect;
+ vendorEffect.vendorData = vendorData;
+ vendorEffect.strength = EffectStrength::MEDIUM;
+ vendorEffect.scale = 0.5f;
+
+ {
+ InSequence seq;
+ EXPECT_CALL(*mMockHal.get(), performVendorEffect(_, _))
+ .Times(Exactly(3))
+ .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)))
+ .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
+ .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
+ Return(ndk::ScopedAStatus::ok())));
+ }
+
+ std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
+ auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
+
+ auto result = mWrapper->performVendorEffect(vendorEffect, callback);
+ ASSERT_TRUE(result.isUnsupported());
+ // Callback not triggered on failure
+ ASSERT_EQ(0, *callbackCounter.get());
+
+ result = mWrapper->performVendorEffect(vendorEffect, callback);
+ ASSERT_TRUE(result.isFailed());
+ // Callback not triggered for unsupported
+ ASSERT_EQ(0, *callbackCounter.get());
+
+ result = mWrapper->performVendorEffect(vendorEffect, callback);
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(1, *callbackCounter.get());
+}
+
TEST_F(VibratorHalWrapperAidlTest, TestPerformComposedEffect) {
std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK,
CompositePrimitive::SPIN,
diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
index dd59093..9a7c69d 100644
--- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "VibratorHalWrapperHidlV1_0Test"
#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <android/persistable_bundle_aidl.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -39,6 +40,8 @@
using aidl::android::hardware::vibrator::EffectStrength;
using aidl::android::hardware::vibrator::IVibrator;
using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::VendorEffect;
+using aidl::android::os::PersistableBundle;
using namespace android;
using namespace std::chrono_literals;
@@ -317,6 +320,22 @@
ASSERT_EQ(0, *callbackCounter.get());
}
+TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformVendorEffectUnsupported) {
+ PersistableBundle vendorData; // empty
+ VendorEffect vendorEffect;
+ vendorEffect.vendorData = vendorData;
+ vendorEffect.strength = EffectStrength::LIGHT;
+ vendorEffect.scale = 1.0f;
+
+ std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
+ auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
+
+ ASSERT_TRUE(mWrapper->performVendorEffect(vendorEffect, callback).isUnsupported());
+
+ // No callback is triggered.
+ ASSERT_EQ(0, *callbackCounter.get());
+}
+
TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformComposedEffectUnsupported) {
std::vector<CompositeEffect> emptyEffects, singleEffect, multipleEffects;
singleEffect.push_back(
diff --git a/services/vibratorservice/test/test_mocks.h b/services/vibratorservice/test/test_mocks.h
index 7882186..2f9451e 100644
--- a/services/vibratorservice/test/test_mocks.h
+++ b/services/vibratorservice/test/test_mocks.h
@@ -41,6 +41,7 @@
using aidl::android::hardware::vibrator::IVibrator;
using aidl::android::hardware::vibrator::IVibratorCallback;
using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::VendorEffect;
// -------------------------------------------------------------------------------------------------
@@ -56,6 +57,8 @@
(Effect e, EffectStrength s, const std::shared_ptr<IVibratorCallback>& cb,
int32_t* ret),
(override));
+ MOCK_METHOD(ndk::ScopedAStatus, performVendorEffect,
+ (const VendorEffect& e, const std::shared_ptr<IVibratorCallback>& cb), (override));
MOCK_METHOD(ndk::ScopedAStatus, getSupportedEffects, (std::vector<Effect> * ret), (override));
MOCK_METHOD(ndk::ScopedAStatus, setAmplitude, (float amplitude), (override));
MOCK_METHOD(ndk::ScopedAStatus, setExternalControl, (bool enabled), (override));