Merge "Remove ADISPLAY_ID_ definitions" into main
diff --git a/include/ftl/concat.h b/include/ftl/concat.h
index e0774d3..7680bed 100644
--- a/include/ftl/concat.h
+++ b/include/ftl/concat.h
@@ -57,7 +57,7 @@
template <std::size_t N>
struct Concat<N> {
static constexpr std::size_t max_size() { return N; }
- constexpr std::size_t size() const { return end_ - buffer_; }
+ constexpr std::size_t size() const { return static_cast<std::size_t>(end_ - buffer_); }
constexpr const char* c_str() const { return buffer_; }
@@ -68,6 +68,8 @@
protected:
constexpr Concat() : end_(buffer_) {}
+ constexpr Concat(const Concat&) = delete;
+
constexpr void append() { *end_ = '\0'; }
char buffer_[N + 1];
diff --git a/include/ftl/expected.h b/include/ftl/expected.h
index 12b6102..57448dc 100644
--- a/include/ftl/expected.h
+++ b/include/ftl/expected.h
@@ -18,9 +18,57 @@
#include <android-base/expected.h>
#include <ftl/optional.h>
+#include <ftl/unit.h>
#include <utility>
+// Given an expression `expr` that evaluates to an ftl::Expected<T, E> result (R for short), FTL_TRY
+// unwraps T out of R, or bails out of the enclosing function F if R has an error E. The return type
+// of F must be R, since FTL_TRY propagates R in the error case. As a special case, ftl::Unit may be
+// used as the error E to allow FTL_TRY expressions when F returns `void`.
+//
+// The non-standard syntax requires `-Wno-gnu-statement-expression-from-macro-expansion` to compile.
+// The UnitToVoid conversion allows the macro to be used for early exit from a function that returns
+// `void`.
+//
+// Example usage:
+//
+// using StringExp = ftl::Expected<std::string, std::errc>;
+//
+// StringExp repeat(StringExp exp) {
+// const std::string str = FTL_TRY(exp);
+// return StringExp(str + str);
+// }
+//
+// assert(StringExp("haha"s) == repeat(StringExp("ha"s)));
+// assert(repeat(ftl::Unexpected(std::errc::bad_message)).has_error([](std::errc e) {
+// return e == std::errc::bad_message;
+// }));
+//
+//
+// FTL_TRY may be used in void-returning functions by using ftl::Unit as the error type:
+//
+// void uppercase(char& c, ftl::Optional<char> opt) {
+// c = std::toupper(FTL_TRY(std::move(opt).ok_or(ftl::Unit())));
+// }
+//
+// char c = '?';
+// uppercase(c, std::nullopt);
+// assert(c == '?');
+//
+// uppercase(c, 'a');
+// assert(c == 'A');
+//
+#define FTL_TRY(expr) \
+ ({ \
+ auto exp_ = (expr); \
+ if (!exp_.has_value()) { \
+ using E = decltype(exp_)::error_type; \
+ return android::ftl::details::UnitToVoid<E>::from(std::move(exp_)); \
+ } \
+ exp_.value(); \
+ })
+
namespace android::ftl {
// Superset of base::expected<T, E> with monadic operations.
diff --git a/include/ftl/optional.h b/include/ftl/optional.h
index 94d8e3d..e245d88 100644
--- a/include/ftl/optional.h
+++ b/include/ftl/optional.h
@@ -20,13 +20,14 @@
#include <optional>
#include <utility>
+#include <android-base/expected.h>
#include <ftl/details/optional.h>
namespace android::ftl {
// Superset of std::optional<T> with monadic operations, as proposed in https://wg21.link/P0798R8.
//
-// TODO: Remove in C++23.
+// TODO: Remove standard APIs in C++23.
//
template <typename T>
struct Optional final : std::optional<T> {
@@ -109,6 +110,13 @@
return std::forward<F>(f)();
}
+ // Maps this Optional<T> to expected<T, E> where nullopt becomes E.
+ template <typename E>
+ constexpr auto ok_or(E&& e) && -> base::expected<T, E> {
+ if (has_value()) return std::move(value());
+ return base::unexpected(std::forward<E>(e));
+ }
+
// Delete new for this class. Its base doesn't have a virtual destructor, and
// if it got deleted via base class pointer, it would cause undefined
// behavior. There's not a good reason to allocate this object on the heap
diff --git a/include/ftl/unit.h b/include/ftl/unit.h
index e38230b..62549a3 100644
--- a/include/ftl/unit.h
+++ b/include/ftl/unit.h
@@ -58,4 +58,22 @@
return {std::forward<F>(f)};
}
+namespace details {
+
+// Identity function for all T except Unit, which maps to void.
+template <typename T>
+struct UnitToVoid {
+ template <typename U>
+ static auto from(U&& value) {
+ return value;
+ }
+};
+
+template <>
+struct UnitToVoid<Unit> {
+ template <typename U>
+ static void from(U&&) {}
+};
+
+} // namespace details
} // namespace android::ftl
diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp
index 4b41152..368f5e0 100644
--- a/libs/ftl/Android.bp
+++ b/libs/ftl/Android.bp
@@ -41,5 +41,6 @@
"-Wextra",
"-Wpedantic",
"-Wthread-safety",
+ "-Wno-gnu-statement-expression-from-macro-expansion",
],
}
diff --git a/libs/ftl/expected_test.cpp b/libs/ftl/expected_test.cpp
index 8cb07e4..9b7f017 100644
--- a/libs/ftl/expected_test.cpp
+++ b/libs/ftl/expected_test.cpp
@@ -15,8 +15,11 @@
*/
#include <ftl/expected.h>
+#include <ftl/optional.h>
+#include <ftl/unit.h>
#include <gtest/gtest.h>
+#include <cctype>
#include <string>
#include <system_error>
@@ -74,4 +77,42 @@
}
}
+namespace {
+
+IntExp increment(IntExp exp) {
+ const int i = FTL_TRY(exp);
+ return IntExp(i + 1);
+}
+
+StringExp repeat(StringExp exp) {
+ const std::string str = FTL_TRY(exp);
+ return StringExp(str + str);
+}
+
+void uppercase(char& c, ftl::Optional<char> opt) {
+ c = std::toupper(FTL_TRY(std::move(opt).ok_or(ftl::Unit())));
+}
+
+} // namespace
+
+// Keep in sync with example usage in header file.
+TEST(Expected, Try) {
+ EXPECT_EQ(IntExp(100), increment(IntExp(99)));
+ EXPECT_TRUE(repeat(ftl::Unexpected(std::errc::value_too_large)).has_error([](std::errc e) {
+ return e == std::errc::value_too_large;
+ }));
+
+ EXPECT_EQ(StringExp("haha"s), repeat(StringExp("ha"s)));
+ EXPECT_TRUE(repeat(ftl::Unexpected(std::errc::bad_message)).has_error([](std::errc e) {
+ return e == std::errc::bad_message;
+ }));
+
+ char c = '?';
+ uppercase(c, std::nullopt);
+ EXPECT_EQ(c, '?');
+
+ uppercase(c, 'a');
+ EXPECT_EQ(c, 'A');
+}
+
} // namespace android::test
diff --git a/libs/ftl/optional_test.cpp b/libs/ftl/optional_test.cpp
index 91bf7bc..e7f1f14 100644
--- a/libs/ftl/optional_test.cpp
+++ b/libs/ftl/optional_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <ftl/expected.h>
#include <ftl/optional.h>
#include <ftl/static_vector.h>
#include <ftl/string.h>
@@ -23,6 +24,7 @@
#include <cstdlib>
#include <functional>
#include <numeric>
+#include <system_error>
#include <utility>
using namespace std::placeholders;
@@ -204,6 +206,19 @@
.or_else([] { return Optional(-1); }));
}
+TEST(Optional, OkOr) {
+ using CharExp = ftl::Expected<char, std::errc>;
+ using StringExp = ftl::Expected<std::string, std::errc>;
+
+ EXPECT_EQ(CharExp('z'), Optional('z').ok_or(std::errc::broken_pipe));
+ EXPECT_EQ(CharExp(ftl::Unexpected(std::errc::broken_pipe)),
+ Optional<char>().ok_or(std::errc::broken_pipe));
+
+ EXPECT_EQ(StringExp("abc"s), Optional("abc"s).ok_or(std::errc::protocol_error));
+ EXPECT_EQ(StringExp(ftl::Unexpected(std::errc::protocol_error)),
+ Optional<std::string>().ok_or(std::errc::protocol_error));
+}
+
// Comparison.
namespace {
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index c62fc7d..6cf5a7e 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -394,6 +394,12 @@
/* Sysfs node change reported. Recreate device if required to incorporate the new sysfs nodes */
virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0;
+
+ /* Get the ID of the InputDevice that was used most recently.
+ *
+ * Returns ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID if no device has been used since boot.
+ */
+ virtual DeviceId getLastUsedInputDeviceId() = 0;
};
// --- TouchAffineTransformation ---
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 12f52b8..69555f8 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -38,6 +38,8 @@
namespace android {
+namespace {
+
/**
* Determines if the identifiers passed are a sub-devices. Sub-devices are physical devices
* that expose multiple input device paths such a keyboard that also has a touchpad input.
@@ -49,8 +51,8 @@
* inputs versus the same device plugged into multiple ports.
*/
-static bool isSubDevice(const InputDeviceIdentifier& identifier1,
- const InputDeviceIdentifier& identifier2) {
+bool isSubDevice(const InputDeviceIdentifier& identifier1,
+ const InputDeviceIdentifier& identifier2) {
return (identifier1.vendor == identifier2.vendor &&
identifier1.product == identifier2.product && identifier1.bus == identifier2.bus &&
identifier1.version == identifier2.version &&
@@ -58,7 +60,7 @@
identifier1.location == identifier2.location);
}
-static bool isStylusPointerGestureStart(const NotifyMotionArgs& motionArgs) {
+bool isStylusPointerGestureStart(const NotifyMotionArgs& motionArgs) {
const auto actionMasked = MotionEvent::getActionMasked(motionArgs.action);
if (actionMasked != AMOTION_EVENT_ACTION_HOVER_ENTER &&
actionMasked != AMOTION_EVENT_ACTION_DOWN &&
@@ -69,6 +71,28 @@
return isStylusToolType(motionArgs.pointerProperties[actionIndex].toolType);
}
+bool isNewGestureStart(const NotifyMotionArgs& motion) {
+ return motion.action == AMOTION_EVENT_ACTION_DOWN ||
+ motion.action == AMOTION_EVENT_ACTION_HOVER_ENTER;
+}
+
+bool isNewGestureStart(const NotifyKeyArgs& key) {
+ return key.action == AKEY_EVENT_ACTION_DOWN;
+}
+
+// Return the event's device ID if it marks the start of a new gesture.
+std::optional<DeviceId> getDeviceIdOfNewGesture(const NotifyArgs& args) {
+ if (const auto* motion = std::get_if<NotifyMotionArgs>(&args); motion != nullptr) {
+ return isNewGestureStart(*motion) ? std::make_optional(motion->deviceId) : std::nullopt;
+ }
+ if (const auto* key = std::get_if<NotifyKeyArgs>(&args); key != nullptr) {
+ return isNewGestureStart(*key) ? std::make_optional(key->deviceId) : std::nullopt;
+ }
+ return std::nullopt;
+}
+
+} // namespace
+
// --- InputReader ---
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
@@ -162,6 +186,11 @@
}
std::swap(notifyArgs, mPendingArgs);
+
+ // Keep track of the last used device
+ for (const NotifyArgs& args : notifyArgs) {
+ mLastUsedDeviceId = getDeviceIdOfNewGesture(args).value_or(mLastUsedDeviceId);
+ }
} // release lock
// Flush queued events out to the listener.
@@ -883,6 +912,11 @@
mEventHub->sysfsNodeChanged(sysfsNodePath);
}
+DeviceId InputReader::getLastUsedInputDeviceId() {
+ std::scoped_lock _l(mLock);
+ return mLastUsedDeviceId;
+}
+
void InputReader::dump(std::string& dump) {
std::scoped_lock _l(mLock);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index d9ac917..92a778a 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -118,6 +118,8 @@
void sysfsNodeChanged(const std::string& sysfsNodePath) override;
+ DeviceId getLastUsedInputDeviceId() override;
+
protected:
// These members are protected so they can be instrumented by test cases.
virtual std::shared_ptr<InputDevice> createDeviceLocked(nsecs_t when, int32_t deviceId,
@@ -200,6 +202,9 @@
// records timestamp of the last key press on the physical keyboard
nsecs_t mLastKeyDownTimestamp GUARDED_BY(mLock){0};
+ // The input device that produced a new gesture most recently.
+ DeviceId mLastUsedDeviceId GUARDED_BY(mLock){ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID};
+
// low-level input event decoding and device management
[[nodiscard]] std::list<NotifyArgs> processEventsLocked(const RawEvent* rawEvents, size_t count)
REQUIRES(mLock);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index a0abb61..8536ff0 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -27,6 +27,7 @@
#include <JoystickInputMapper.h>
#include <KeyboardInputMapper.h>
#include <MultiTouchInputMapper.h>
+#include <NotifyArgsBuilders.h>
#include <PeripheralController.h>
#include <SensorInputMapper.h>
#include <SingleTouchInputMapper.h>
@@ -1183,6 +1184,82 @@
mFakeListener->assertNotifyCaptureWasNotCalled();
}
+TEST_F(InputReaderTest, GetLastUsedInputDeviceId) {
+ constexpr int32_t FIRST_DEVICE_ID = END_RESERVED_ID + 1000;
+ constexpr int32_t SECOND_DEVICE_ID = FIRST_DEVICE_ID + 1;
+ FakeInputMapper& firstMapper =
+ addDeviceWithFakeInputMapper(FIRST_DEVICE_ID, FIRST_DEVICE_ID, "first",
+ InputDeviceClass::KEYBOARD, AINPUT_SOURCE_KEYBOARD,
+ /*configuration=*/nullptr);
+ FakeInputMapper& secondMapper =
+ addDeviceWithFakeInputMapper(SECOND_DEVICE_ID, SECOND_DEVICE_ID, "second",
+ InputDeviceClass::TOUCH_MT, AINPUT_SOURCE_STYLUS,
+ /*configuration=*/nullptr);
+
+ ASSERT_EQ(ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+ // Start a new key gesture from the first device
+ firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
+ .deviceId(FIRST_DEVICE_ID)
+ .build()});
+ mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
+ mReader->loopOnce();
+ ASSERT_EQ(firstMapper.getDeviceId(), mReader->getLastUsedInputDeviceId());
+
+ // Start a new touch gesture from the second device
+ secondMapper.setProcessResult(
+ {MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
+ .deviceId(SECOND_DEVICE_ID)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER))
+ .build()});
+ mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
+ mReader->loopOnce();
+ ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+ // Releasing the key is not a new gesture, so it does not update the last used device
+ firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
+ .deviceId(FIRST_DEVICE_ID)
+ .build()});
+ mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
+ mReader->loopOnce();
+ ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+ // But pressing a new key does start a new gesture
+ firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
+ .deviceId(FIRST_DEVICE_ID)
+ .build()});
+ mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
+ mReader->loopOnce();
+ ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+ // Moving or ending a touch gesture does not update the last used device
+ secondMapper.setProcessResult(
+ {MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
+ .deviceId(SECOND_DEVICE_ID)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
+ .build()});
+ mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
+ mReader->loopOnce();
+ ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+ secondMapper.setProcessResult({MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
+ .deviceId(SECOND_DEVICE_ID)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
+ .build()});
+ mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
+ mReader->loopOnce();
+ ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+
+ // Starting a new hover gesture updates the last used device
+ secondMapper.setProcessResult(
+ {MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+ .deviceId(SECOND_DEVICE_ID)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
+ .build()});
+ mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
+ mReader->loopOnce();
+ ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
+}
+
class FakeVibratorInputMapper : public FakeInputMapper {
public:
FakeVibratorInputMapper(InputDeviceContext& deviceContext,
diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
index 34ea54c..a19726a 100644
--- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
@@ -169,6 +169,8 @@
reader->sysfsNodeChanged(sysfsNodePath);
}
+ DeviceId getLastUsedInputDeviceId() override { return reader->getLastUsedInputDeviceId(); }
+
private:
std::unique_ptr<InputReaderInterface> reader;
};
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index c25ddb6..f323ce7 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -25,13 +25,14 @@
namespace android {
-LayerRenderArea::LayerRenderArea(sp<Layer> layer, const Rect& crop, ui::Size reqSize,
- ui::Dataspace reqDataSpace, bool allowSecureLayers,
- const ui::Transform& layerTransform, const Rect& layerBufferSize,
- bool hintForSeamlessTransition)
+LayerRenderArea::LayerRenderArea(sp<Layer> layer, frontend::LayerSnapshot layerSnapshot,
+ const Rect& crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
+ bool allowSecureLayers, const ui::Transform& layerTransform,
+ const Rect& layerBufferSize, bool hintForSeamlessTransition)
: RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, hintForSeamlessTransition,
allowSecureLayers),
mLayer(std::move(layer)),
+ mLayerSnapshot(std::move(layerSnapshot)),
mLayerBufferSize(layerBufferSize),
mCrop(crop),
mTransform(layerTransform) {}
diff --git a/services/surfaceflinger/LayerRenderArea.h b/services/surfaceflinger/LayerRenderArea.h
index b12afe8..a12bfca 100644
--- a/services/surfaceflinger/LayerRenderArea.h
+++ b/services/surfaceflinger/LayerRenderArea.h
@@ -32,19 +32,22 @@
class LayerRenderArea : public RenderArea {
public:
- LayerRenderArea(sp<Layer> layer, const Rect& crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
- bool allowSecureLayers, const ui::Transform& layerTransform,
- const Rect& layerBufferSize, bool hintForSeamlessTransition);
+ LayerRenderArea(sp<Layer> layer, frontend::LayerSnapshot layerSnapshot, const Rect& crop,
+ ui::Size reqSize, ui::Dataspace reqDataSpace, bool allowSecureLayers,
+ const ui::Transform& layerTransform, const Rect& layerBufferSize,
+ bool hintForSeamlessTransition);
const ui::Transform& getTransform() const override;
bool isSecure() const override;
sp<const DisplayDevice> getDisplayDevice() const override;
Rect getSourceCrop() const override;
- virtual sp<Layer> getParentLayer() const { return mLayer; }
+ sp<Layer> getParentLayer() const override { return mLayer; }
+ const frontend::LayerSnapshot* getLayerSnapshot() const override { return &mLayerSnapshot; }
private:
const sp<Layer> mLayer;
+ const frontend::LayerSnapshot mLayerSnapshot;
const Rect mLayerBufferSize;
const Rect mCrop;
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 18a5304..e8d20af 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -4,6 +4,8 @@
#include <ui/Transform.h>
#include <functional>
+
+#include "FrontEnd/LayerSnapshot.h"
#include "Layer.h"
namespace android {
@@ -82,6 +84,10 @@
// capture operation.
virtual sp<Layer> getParentLayer() const { return nullptr; }
+ // If this is a LayerRenderArea, return the layer snapshot
+ // of the root layer of the capture operation
+ virtual const frontend::LayerSnapshot* getLayerSnapshot() const { return nullptr; }
+
// Returns whether the render result may be used for system animations that
// must preserve the exact colors of the display.
bool getHintForSeamlessTransition() const { return mHintForSeamlessTransition; }
diff --git a/services/surfaceflinger/RenderAreaBuilder.h b/services/surfaceflinger/RenderAreaBuilder.h
index 012acd2..a25c6e0 100644
--- a/services/surfaceflinger/RenderAreaBuilder.h
+++ b/services/surfaceflinger/RenderAreaBuilder.h
@@ -83,9 +83,12 @@
layer(layer),
childrenOnly(childrenOnly) {}
- // Layer that the render area will be on
+ // Root layer of the render area
sp<Layer> layer;
+ // Layer snapshot of the root layer
+ frontend::LayerSnapshot layerSnapshot;
+
// Transform to be applied on the layers to transform them
// into the logical render area
ui::Transform layerTransform{ui::Transform()};
@@ -97,17 +100,18 @@
bool childrenOnly;
// Uses parent snapshot to determine layer transform and buffer size
- void setLayerInfo(const frontend::LayerSnapshot* parentSnapshot) {
+ void setLayerSnapshot(const frontend::LayerSnapshot& parentSnapshot) {
+ layerSnapshot = parentSnapshot;
if (!childrenOnly) {
- layerTransform = parentSnapshot->localTransform.inverse();
+ layerTransform = parentSnapshot.localTransform.inverse();
}
- layerBufferSize = parentSnapshot->bufferSize;
+ layerBufferSize = parentSnapshot.bufferSize;
}
std::unique_ptr<RenderArea> build() const override {
- return std::make_unique<LayerRenderArea>(layer, crop, reqSize, reqDataSpace,
- allowSecureLayers, layerTransform, layerBufferSize,
- hintForSeamlessTransition);
+ return std::make_unique<LayerRenderArea>(layer, std::move(layerSnapshot), crop, reqSize,
+ reqDataSpace, allowSecureLayers, layerTransform,
+ layerBufferSize, hintForSeamlessTransition);
}
};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5181fb8..b3ddb57 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -8207,7 +8207,7 @@
ALOGW("Couldn't find layer snapshot for %d",
layerRenderAreaBuilder->layer->getSequence());
} else {
- layerRenderAreaBuilder->setLayerInfo(snapshot);
+ layerRenderAreaBuilder->setLayerSnapshot(*snapshot);
}
}
@@ -8302,9 +8302,8 @@
Mutex::Autolock lock(mStateLock);
const DisplayDevice* display = nullptr;
if (parent) {
- const frontend::LayerSnapshot* snapshot = mLayerLifecycleManagerEnabled
- ? mLayerSnapshotBuilder.getSnapshot(parent->sequence)
- : parent->getLayerSnapshot();
+ const frontend::LayerSnapshot* snapshot =
+ mLayerSnapshotBuilder.getSnapshot(parent->sequence);
if (snapshot) {
display = findDisplay([layerStack = snapshot->outputFilter.layerStack](
const auto& display) {