Merge "Add input flag enable_per_device_input_latency_metrics" into main
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
index 28bd793..b7ad331 100644
--- a/cmds/installd/otapreopt_script.sh
+++ b/cmds/installd/otapreopt_script.sh
@@ -50,6 +50,37 @@
exit 1
fi
+# A source that infinitely emits arbitrary lines.
+# When connected to STDIN of another process, this source keeps STDIN open until
+# the consumer process closes STDIN or this script dies.
+function infinite_source {
+ while echo .; do
+ sleep 1
+ done
+}
+
+PR_DEXOPT_JOB_VERSION="$(pm art pr-dexopt-job --version)"
+if (( $? == 0 )) && (( $PR_DEXOPT_JOB_VERSION >= 3 )); then
+ # Delegate to Pre-reboot Dexopt, a feature of ART Service.
+ # ART Service decides what to do with this request:
+ # - If Pre-reboot Dexopt is disabled or unsupported, the command returns
+ # non-zero. This is always the case if the current system is Android 14 or
+ # earlier.
+ # - If Pre-reboot Dexopt is enabled in synchronous mode, the command blocks
+ # until Pre-reboot Dexopt finishes, and returns zero no matter it succeeds or
+ # not. This is the default behavior if the current system is Android 15.
+ # - If Pre-reboot Dexopt is enabled in asynchronous mode, the command schedules
+ # an asynchronous job and returns 0 immediately. The job will then run by the
+ # job scheduler when the device is idle and charging.
+ if infinite_source | pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then
+ # Handled by Pre-reboot Dexopt.
+ exit 0
+ fi
+ echo "Pre-reboot Dexopt not enabled. Fall back to otapreopt."
+else
+ echo "Pre-reboot Dexopt is too old. Fall back to otapreopt."
+fi
+
if [ "$(/system/bin/otapreopt_chroot --version)" != 2 ]; then
# We require an updated chroot wrapper that reads dexopt commands from stdin.
# Even if we kept compat with the old binary, the OTA preopt wouldn't work due
diff --git a/include/input/Input.h b/include/input/Input.h
index 1a3cb6a..a8684bd 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -251,6 +251,8 @@
TOUCH_MODE = AINPUT_EVENT_TYPE_TOUCH_MODE,
ftl_first = KEY,
ftl_last = TOUCH_MODE,
+ // Used by LatencyTracker fuzzer
+ kMaxValue = ftl_last
};
std::string inputEventSourceToString(int32_t source);
diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp
index 78896ed..d31cb3d 100644
--- a/libs/adbd_auth/adbd_auth.cpp
+++ b/libs/adbd_auth/adbd_auth.cpp
@@ -390,13 +390,16 @@
}
}
- static constexpr const char* key_paths[] = {"/adb_keys", "/data/misc/adb/adb_keys"};
+ static constexpr std::pair<const char*, bool> key_paths[] = {
+ {"/adb_keys", true /* follow symlinks */ },
+ {"/data/misc/adb/adb_keys", false /* don't follow symlinks */ },
+ };
void IteratePublicKeys(bool (*callback)(void*, const char*, size_t), void* opaque) {
- for (const auto& path : key_paths) {
+ for (const auto& [path, follow_symlinks] : key_paths) {
if (access(path, R_OK) == 0) {
LOG(INFO) << "adbd_auth: loading keys from " << path;
std::string content;
- if (!android::base::ReadFileToString(path, &content)) {
+ if (!android::base::ReadFileToString(path, &content, follow_symlinks)) {
PLOG(ERROR) << "adbd_auth: couldn't read " << path;
continue;
}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 9578713..1e463a4 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -888,6 +888,7 @@
enabled: false,
},
},
+ corpus: ["corpus/*"],
fuzz_config: {
cc: [
"smoreland@google.com",
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index f8e3fd0..b8d2b5f 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -504,13 +504,7 @@
callbackId.to_string().c_str());
return;
}
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- if (!it->second.disconnectedAfterAcquired) {
- mNumAcquired--;
- }
-#else
mNumAcquired--;
-#endif
BBQ_TRACE("frame=%" PRIu64, callbackId.framenumber);
BQA_LOGV("released %s", callbackId.to_string().c_str());
mBufferItemConsumer->releaseBuffer(it->second, releaseFence);
@@ -561,7 +555,7 @@
applyTransaction = false;
}
- BLASTBufferItem bufferItem;
+ BufferItem bufferItem;
status_t status =
mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
@@ -767,9 +761,6 @@
}
// add to shadow queue
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- mNumDequeued--;
-#endif
mNumFrameAvailable++;
if (waitForTransactionCallback && mNumFrameAvailable >= 2) {
acquireAndReleaseBuffer();
@@ -824,17 +815,8 @@
};
void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) {
- {
- std::lock_guard _lock{mTimestampMutex};
- mDequeueTimestamps.erase(bufferId);
- }
-
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- {
- std::lock_guard lock{mMutex};
- mNumDequeued--;
- }
-#endif
+ std::lock_guard _lock{mTimestampMutex};
+ mDequeueTimestamps.erase(bufferId);
}
bool BLASTBufferQueue::syncNextTransaction(
@@ -1134,116 +1116,6 @@
producerControlledByApp, output);
}
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- status_t disconnect(int api, DisconnectMode mode) override {
- sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
- if (!bbq) {
- return BufferQueueProducer::disconnect(api, mode);
- }
-
- std::lock_guard lock{bbq->mMutex};
- if (status_t status = BufferQueueProducer::disconnect(api, mode); status != OK) {
- return status;
- }
-
- // We need to reset dequeued and acquired counts because BufferQueueProducer::disconnect
- // calls BufferQueueCore::freeAllBuffersLocked which frees all dequeued and acquired
- // buffers. We don't reset mNumFrameAvailable because these buffers are still available
- // in BufferItemConsumer.
- bbq->mNumDequeued = 0;
- bbq->mNumAcquired = 0;
- // SurfaceFlinger sends release callbacks for buffers that have been acquired after a
- // disconnect. We set disconnectedAfterAcquired to true so that we can ignore any stale
- // releases that come in after the producer is disconnected. Otherwise, releaseBuffer will
- // decrement mNumAcquired for a buffer that was acquired before we reset mNumAcquired to
- // zero.
- for (auto& [releaseId, bufferItem] : bbq->mSubmitted) {
- bufferItem.disconnectedAfterAcquired = true;
- }
-
- return OK;
- }
-
- status_t setAsyncMode(bool asyncMode) override {
- if (status_t status = BufferQueueProducer::setAsyncMode(asyncMode); status != OK) {
- return status;
- }
-
- sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
- if (!bbq) {
- return OK;
- }
-
- {
- std::lock_guard lock{bbq->mMutex};
- bbq->mAsyncMode = asyncMode;
- }
-
- return OK;
- }
-
- status_t setSharedBufferMode(bool sharedBufferMode) override {
- if (status_t status = BufferQueueProducer::setSharedBufferMode(sharedBufferMode);
- status != OK) {
- return status;
- }
-
- sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
- if (!bbq) {
- return OK;
- }
-
- {
- std::lock_guard lock{bbq->mMutex};
- bbq->mSharedBufferMode = sharedBufferMode;
- }
-
- return OK;
- }
-
- status_t detachBuffer(int slot) override {
- if (status_t status = BufferQueueProducer::detachBuffer(slot); status != OK) {
- return status;
- }
-
- sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
- if (!bbq) {
- return OK;
- }
-
- {
- std::lock_guard lock{bbq->mMutex};
- bbq->mNumDequeued--;
- }
-
- return OK;
- }
-
- status_t dequeueBuffer(int* outSlot, sp<Fence>* outFence, uint32_t width, uint32_t height,
- PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
- FrameEventHistoryDelta* outTimestamps) override {
- sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
- if (!bbq) {
- return BufferQueueProducer::dequeueBuffer(outSlot, outFence, width, height, format,
- usage, outBufferAge, outTimestamps);
- }
-
- {
- std::lock_guard lock{bbq->mMutex};
- bbq->mNumDequeued++;
- }
-
- status_t status =
- BufferQueueProducer::dequeueBuffer(outSlot, outFence, width, height, format, usage,
- outBufferAge, outTimestamps);
- if (status < 0) {
- std::lock_guard lock{bbq->mMutex};
- bbq->mNumDequeued--;
- }
- return status;
- }
-#endif
-
// We want to resize the frame history when changing the size of the buffer queue
status_t setMaxDequeuedBufferCount(int maxDequeuedBufferCount) override {
int maxBufferCount;
@@ -1266,13 +1138,6 @@
bbq->resizeFrameEventHistory(newFrameHistorySize);
}
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- {
- std::lock_guard lock{bbq->mMutex};
- bbq->mMaxDequeuedBuffers = maxDequeuedBufferCount;
- }
-#endif
-
return OK;
}
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 729d46a..0e7dd20 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -187,15 +187,6 @@
// BufferQueue internally allows 1 more than
// the max to be acquired
int32_t mMaxAcquiredBuffers GUARDED_BY(mMutex) = 1;
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- int32_t mMaxDequeuedBuffers GUARDED_BY(mMutex) = 1;
- static constexpr int32_t kMaxBufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS;
-
- bool mAsyncMode GUARDED_BY(mMutex) = false;
- bool mSharedBufferMode GUARDED_BY(mMutex) = false;
-
- int32_t mNumDequeued GUARDED_BY(mMutex) = 0;
-#endif
int32_t mNumFrameAvailable GUARDED_BY(mMutex) = 0;
int32_t mNumAcquired GUARDED_BY(mMutex) = 0;
@@ -204,16 +195,9 @@
// latch stale buffers and that we don't wait on barriers from an old producer.
uint32_t mProducerId = 0;
- class BLASTBufferItem : public BufferItem {
- public:
- // True if BBQBufferQueueProducer is disconnected after the buffer is acquried but
- // before it is released.
- bool disconnectedAfterAcquired{false};
- };
-
// Keep a reference to the submitted buffers so we can release when surfaceflinger drops the
// buffer or the buffer has been presented and a new buffer is ready to be presented.
- std::unordered_map<ReleaseCallbackId, BLASTBufferItem, ReleaseBufferCallbackIdHash> mSubmitted
+ std::unordered_map<ReleaseCallbackId, BufferItem, ReleaseBufferCallbackIdHash> mSubmitted
GUARDED_BY(mMutex);
// Keep a queue of the released buffers instead of immediately releasing
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index bcef350..250e72c 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -52,6 +52,7 @@
#include "Connection.h"
#include "DebugConfig.h"
#include "InputDispatcher.h"
+#include "InputEventTimeline.h"
#include "trace/InputTracer.h"
#include "trace/InputTracingPerfettoBackend.h"
#include "trace/ThreadedBackend.h"
@@ -4642,10 +4643,9 @@
if (args.id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER &&
!mInputFilterEnabled) {
- const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN;
std::set<InputDeviceUsageSource> sources = getUsageSourcesForMotionArgs(args);
- mLatencyTracker.trackListener(args.id, isDown, args.eventTime, args.readTime,
- args.deviceId, sources);
+ mLatencyTracker.trackListener(args.id, args.eventTime, args.readTime, args.deviceId,
+ sources, args.action, InputEventType::MOTION);
}
needWake = enqueueInboundEventLocked(std::move(newEntry));
diff --git a/services/inputflinger/dispatcher/InputEventTimeline.cpp b/services/inputflinger/dispatcher/InputEventTimeline.cpp
index a365003..31ceb8d 100644
--- a/services/inputflinger/dispatcher/InputEventTimeline.cpp
+++ b/services/inputflinger/dispatcher/InputEventTimeline.cpp
@@ -68,13 +68,15 @@
InputEventTimeline::InputEventTimeline(bool isDown, nsecs_t eventTime, nsecs_t readTime,
uint16_t vendorId, uint16_t productId,
- const std::set<InputDeviceUsageSource>& sources)
+ const std::set<InputDeviceUsageSource>& sources,
+ InputEventActionType inputEventActionType)
: isDown(isDown),
eventTime(eventTime),
readTime(readTime),
vendorId(vendorId),
productId(productId),
- sources(sources) {}
+ sources(sources),
+ inputEventActionType(inputEventActionType) {}
bool InputEventTimeline::operator==(const InputEventTimeline& rhs) const {
if (connectionTimelines.size() != rhs.connectionTimelines.size()) {
@@ -90,7 +92,8 @@
}
}
return isDown == rhs.isDown && eventTime == rhs.eventTime && readTime == rhs.readTime &&
- vendorId == rhs.vendorId && productId == rhs.productId && sources == rhs.sources;
+ vendorId == rhs.vendorId && productId == rhs.productId && sources == rhs.sources &&
+ inputEventActionType == rhs.inputEventActionType;
}
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputEventTimeline.h b/services/inputflinger/dispatcher/InputEventTimeline.h
index 1756944..6668399 100644
--- a/services/inputflinger/dispatcher/InputEventTimeline.h
+++ b/services/inputflinger/dispatcher/InputEventTimeline.h
@@ -74,15 +74,39 @@
bool mHasGraphicsTimeline = false;
};
+enum class InputEventActionType : int32_t {
+ UNKNOWN_INPUT_EVENT = 0,
+ MOTION_ACTION_DOWN = 1,
+ // Motion events for ACTION_MOVE (characterizes scrolling motion)
+ MOTION_ACTION_MOVE = 2,
+ // Motion events for ACTION_UP (when the pointer first goes up)
+ MOTION_ACTION_UP = 3,
+ // Motion events for ACTION_HOVER_MOVE (pointer position on screen changes but pointer is not
+ // down)
+ MOTION_ACTION_HOVER_MOVE = 4,
+ // Motion events for ACTION_SCROLL (moving the mouse wheel)
+ MOTION_ACTION_SCROLL = 5,
+ // Key events for both ACTION_DOWN and ACTION_UP (key press and key release)
+ KEY = 6,
+
+ ftl_first = UNKNOWN_INPUT_EVENT,
+ ftl_last = KEY,
+ // Used by latency fuzzer
+ kMaxValue = ftl_last
+
+};
+
struct InputEventTimeline {
InputEventTimeline(bool isDown, nsecs_t eventTime, nsecs_t readTime, uint16_t vendorId,
- uint16_t productId, const std::set<InputDeviceUsageSource>& sources);
+ uint16_t productId, const std::set<InputDeviceUsageSource>& sources,
+ InputEventActionType inputEventActionType);
const bool isDown; // True if this is an ACTION_DOWN event
const nsecs_t eventTime;
const nsecs_t readTime;
const uint16_t vendorId;
const uint16_t productId;
const std::set<InputDeviceUsageSource> sources;
+ const InputEventActionType inputEventActionType;
struct IBinderHash {
std::size_t operator()(const sp<IBinder>& b) const {
diff --git a/services/inputflinger/dispatcher/LatencyTracker.cpp b/services/inputflinger/dispatcher/LatencyTracker.cpp
index 698bd9f..721d009 100644
--- a/services/inputflinger/dispatcher/LatencyTracker.cpp
+++ b/services/inputflinger/dispatcher/LatencyTracker.cpp
@@ -67,9 +67,10 @@
LOG_ALWAYS_FATAL_IF(processor == nullptr);
}
-void LatencyTracker::trackListener(int32_t inputEventId, bool isDown, nsecs_t eventTime,
- nsecs_t readTime, DeviceId deviceId,
- const std::set<InputDeviceUsageSource>& sources) {
+void LatencyTracker::trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime,
+ DeviceId deviceId,
+ const std::set<InputDeviceUsageSource>& sources,
+ int inputEventAction, InputEventType inputEventType) {
reportAndPruneMatureRecords(eventTime);
const auto it = mTimelines.find(inputEventId);
if (it != mTimelines.end()) {
@@ -101,9 +102,43 @@
return;
}
+ const InputEventActionType inputEventActionType = [&]() {
+ switch (inputEventType) {
+ case InputEventType::MOTION: {
+ switch (inputEventAction) {
+ case AMOTION_EVENT_ACTION_DOWN:
+ return InputEventActionType::MOTION_ACTION_DOWN;
+ case AMOTION_EVENT_ACTION_MOVE:
+ return InputEventActionType::MOTION_ACTION_MOVE;
+ case AMOTION_EVENT_ACTION_UP:
+ return InputEventActionType::MOTION_ACTION_UP;
+ case AMOTION_EVENT_ACTION_HOVER_MOVE:
+ return InputEventActionType::MOTION_ACTION_HOVER_MOVE;
+ case AMOTION_EVENT_ACTION_SCROLL:
+ return InputEventActionType::MOTION_ACTION_SCROLL;
+ default:
+ return InputEventActionType::UNKNOWN_INPUT_EVENT;
+ }
+ }
+ case InputEventType::KEY: {
+ switch (inputEventAction) {
+ case AKEY_EVENT_ACTION_DOWN:
+ case AKEY_EVENT_ACTION_UP:
+ return InputEventActionType::KEY;
+ default:
+ return InputEventActionType::UNKNOWN_INPUT_EVENT;
+ }
+ }
+ default:
+ return InputEventActionType::UNKNOWN_INPUT_EVENT;
+ }
+ }();
+
+ bool isDown = inputEventType == InputEventType::MOTION &&
+ inputEventAction == AMOTION_EVENT_ACTION_DOWN;
mTimelines.emplace(inputEventId,
InputEventTimeline(isDown, eventTime, readTime, identifier->vendor,
- identifier->product, sources));
+ identifier->product, sources, inputEventActionType));
mEventTimes.emplace(eventTime, inputEventId);
}
diff --git a/services/inputflinger/dispatcher/LatencyTracker.h b/services/inputflinger/dispatcher/LatencyTracker.h
index 890d61d..532f422 100644
--- a/services/inputflinger/dispatcher/LatencyTracker.h
+++ b/services/inputflinger/dispatcher/LatencyTracker.h
@@ -52,8 +52,9 @@
* duplicate events that happen to have the same eventTime and inputEventId. Therefore, we
* must drop all duplicate data.
*/
- void trackListener(int32_t inputEventId, bool isDown, nsecs_t eventTime, nsecs_t readTime,
- DeviceId deviceId, const std::set<InputDeviceUsageSource>& sources);
+ void trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime, DeviceId deviceId,
+ const std::set<InputDeviceUsageSource>& sources, int inputEventActionType,
+ InputEventType inputEventType);
void trackFinishedEvent(int32_t inputEventId, const sp<IBinder>& connectionToken,
nsecs_t deliveryTime, nsecs_t consumeTime, nsecs_t finishTime);
void trackGraphicsLatency(int32_t inputEventId, const sp<IBinder>& connectionToken,
diff --git a/services/inputflinger/tests/LatencyTracker_test.cpp b/services/inputflinger/tests/LatencyTracker_test.cpp
index 4fcffdd..5650286 100644
--- a/services/inputflinger/tests/LatencyTracker_test.cpp
+++ b/services/inputflinger/tests/LatencyTracker_test.cpp
@@ -61,12 +61,13 @@
InputEventTimeline getTestTimeline() {
InputEventTimeline t(
- /*isDown=*/true,
+ /*isDown=*/false,
/*eventTime=*/2,
/*readTime=*/3,
/*vendorId=*/0,
/*productId=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
ConnectionTimeline expectedCT(/*deliveryTime=*/6, /*consumeTime=*/7, /*finishTime=*/8);
std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 9;
@@ -116,9 +117,10 @@
void LatencyTrackerTest::triggerEventReporting(nsecs_t lastEventTime) {
const nsecs_t triggerEventTime =
lastEventTime + std::chrono::nanoseconds(ANR_TIMEOUT).count() + 1;
- mTracker->trackListener(/*inputEventId=*/1, /*isDown=*/true, triggerEventTime,
+ mTracker->trackListener(/*inputEventId=*/1, triggerEventTime,
/*readTime=*/3, DEVICE_ID,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
}
void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& timeline) {
@@ -167,12 +169,15 @@
* any additional ConnectionTimeline's.
*/
TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) {
- mTracker->trackListener(/*inputEventId=*/1, /*isDown=*/false, /*eventTime=*/2,
- /*readTime=*/3, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(/*inputEventId=*/1, /*eventTime=*/2,
+ /*readTime=*/3, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN},
+ AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
triggerEventReporting(/*eventTime=*/2);
- assertReceivedTimeline(InputEventTimeline{/*isDown=*/false, /*eventTime=*/2,
- /*readTime=*/3, /*vendorId=*/0, /*productID=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN}});
+ assertReceivedTimeline(
+ InputEventTimeline{/*isDown=*/false, /*eventTime=*/2,
+ /*readTime=*/3, /*vendorId=*/0, /*productID=*/0,
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT});
}
/**
@@ -203,8 +208,9 @@
const auto& [connectionToken, expectedCT] = *expected.connectionTimelines.begin();
- mTracker->trackListener(inputEventId, expected.isDown, expected.eventTime, expected.readTime,
- DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId, expected.eventTime, expected.readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
mTracker->trackFinishedEvent(inputEventId, connectionToken, expectedCT.deliveryTime,
expectedCT.consumeTime, expectedCT.finishTime);
mTracker->trackGraphicsLatency(inputEventId, connectionToken, expectedCT.graphicsTimeline);
@@ -220,14 +226,16 @@
TEST_F(LatencyTrackerTest, WhenDuplicateEventsAreReported_DoesNotCrash) {
constexpr nsecs_t inputEventId = 1;
constexpr nsecs_t readTime = 3; // does not matter for this test
- constexpr bool isDown = true; // does not matter for this test
+ constexpr bool isDown = false; // does not matter for this test
// In the following 2 calls to trackListener, the inputEventId's are the same, but event times
// are different.
- mTracker->trackListener(inputEventId, isDown, /*eventTime=*/1, readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN});
- mTracker->trackListener(inputEventId, isDown, /*eventTime=*/2, readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId, /*eventTime=*/1, readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
+ mTracker->trackListener(inputEventId, /*eventTime=*/2, readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
triggerEventReporting(/*eventTime=*/2);
// Since we sent duplicate input events, the tracker should just delete all of them, because it
@@ -238,12 +246,13 @@
TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) {
constexpr int32_t inputEventId1 = 1;
InputEventTimeline timeline1(
- /*isDown*/ true,
+ /*isDown*/ false,
/*eventTime*/ 2,
/*readTime*/ 3,
/*vendorId=*/0,
/*productId=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*inputEventType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
timeline1.connectionTimelines.emplace(connection1,
ConnectionTimeline(/*deliveryTime*/ 6, /*consumeTime*/ 7,
/*finishTime*/ 8));
@@ -260,7 +269,8 @@
/*readTime=*/30,
/*vendorId=*/0,
/*productId=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
timeline2.connectionTimelines.emplace(connection2,
ConnectionTimeline(/*deliveryTime=*/60,
/*consumeTime=*/70,
@@ -272,11 +282,13 @@
connectionTimeline2.setGraphicsTimeline(std::move(graphicsTimeline2));
// Start processing first event
- mTracker->trackListener(inputEventId1, timeline1.isDown, timeline1.eventTime,
- timeline1.readTime, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId1, timeline1.eventTime, timeline1.readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
// Start processing second event
- mTracker->trackListener(inputEventId2, timeline2.isDown, timeline2.eventTime,
- timeline2.readTime, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId2, timeline2.eventTime, timeline2.readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
mTracker->trackFinishedEvent(inputEventId1, connection1, connectionTimeline1.deliveryTime,
connectionTimeline1.consumeTime, connectionTimeline1.finishTime);
@@ -301,12 +313,14 @@
const sp<IBinder>& token = timeline.connectionTimelines.begin()->first;
for (size_t i = 1; i <= 100; i++) {
- mTracker->trackListener(/*inputEventId=*/i, timeline.isDown, timeline.eventTime,
- timeline.readTime, /*deviceId=*/DEVICE_ID,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(/*inputEventId=*/i, timeline.eventTime, timeline.readTime,
+ /*deviceId=*/DEVICE_ID,
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
expectedTimelines.push_back(InputEventTimeline{timeline.isDown, timeline.eventTime,
timeline.readTime, timeline.vendorId,
- timeline.productId, timeline.sources});
+ timeline.productId, timeline.sources,
+ timeline.inputEventActionType});
}
// Now, complete the first event that was sent.
mTracker->trackFinishedEvent(/*inputEventId=*/1, token, expectedCT.deliveryTime,
@@ -332,12 +346,14 @@
expectedCT.consumeTime, expectedCT.finishTime);
mTracker->trackGraphicsLatency(inputEventId, connection1, expectedCT.graphicsTimeline);
- mTracker->trackListener(inputEventId, expected.isDown, expected.eventTime, expected.readTime,
- DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId, expected.eventTime, expected.readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
triggerEventReporting(expected.eventTime);
assertReceivedTimeline(InputEventTimeline{expected.isDown, expected.eventTime,
expected.readTime, expected.vendorId,
- expected.productId, expected.sources});
+ expected.productId, expected.sources,
+ expected.inputEventActionType});
}
/**
@@ -348,22 +364,92 @@
TEST_F(LatencyTrackerTest, TrackListenerCheck_DeviceInfoFieldsInputEventTimeline) {
constexpr int32_t inputEventId = 1;
InputEventTimeline timeline(
- /*isDown*/ true, /*eventTime*/ 2, /*readTime*/ 3,
+ /*isDown*/ false, /*eventTime*/ 2, /*readTime*/ 3,
/*vendorId=*/50, /*productId=*/60,
/*sources=*/
- {InputDeviceUsageSource::TOUCHSCREEN, InputDeviceUsageSource::STYLUS_DIRECT});
+ {InputDeviceUsageSource::TOUCHSCREEN, InputDeviceUsageSource::STYLUS_DIRECT},
+ /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
InputDeviceInfo deviceInfo1 = generateTestDeviceInfo(
/*vendorId=*/5, /*productId=*/6, /*deviceId=*/DEVICE_ID + 1);
InputDeviceInfo deviceInfo2 = generateTestDeviceInfo(
/*vendorId=*/50, /*productId=*/60, /*deviceId=*/DEVICE_ID);
mTracker->setInputDevices({deviceInfo1, deviceInfo2});
- mTracker->trackListener(inputEventId, timeline.isDown, timeline.eventTime, timeline.readTime,
- DEVICE_ID,
+ mTracker->trackListener(inputEventId, timeline.eventTime, timeline.readTime, DEVICE_ID,
{InputDeviceUsageSource::TOUCHSCREEN,
- InputDeviceUsageSource::STYLUS_DIRECT});
+ InputDeviceUsageSource::STYLUS_DIRECT},
+ AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
triggerEventReporting(timeline.eventTime);
assertReceivedTimeline(timeline);
}
+/**
+ * Check that InputEventActionType is correctly assigned to InputEventTimeline in trackListener.
+ */
+TEST_F(LatencyTrackerTest, TrackListenerCheck_InputEventActionTypeFieldInputEventTimeline) {
+ constexpr int32_t inputEventId = 1;
+ // Create timelines for different event types (Motion, Key)
+ InputEventTimeline motionDownTimeline(
+ /*isDown*/ true, /*eventTime*/ 2, /*readTime*/ 3,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_DOWN);
+
+ InputEventTimeline motionMoveTimeline(
+ /*isDown*/ false, /*eventTime*/ 4, /*readTime*/ 5,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_MOVE);
+
+ InputEventTimeline motionUpTimeline(
+ /*isDown*/ false, /*eventTime*/ 6, /*readTime*/ 7,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_UP);
+
+ InputEventTimeline keyDownTimeline(
+ /*isDown*/ false, /*eventTime*/ 8, /*readTime*/ 9,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::KEY);
+
+ InputEventTimeline keyUpTimeline(
+ /*isDown*/ false, /*eventTime*/ 10, /*readTime*/ 11,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::KEY);
+
+ InputEventTimeline unknownTimeline(
+ /*isDown*/ false, /*eventTime*/ 12, /*readTime*/ 13,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::UNKNOWN_INPUT_EVENT);
+
+ mTracker->trackListener(inputEventId, motionDownTimeline.eventTime, motionDownTimeline.readTime,
+ DEVICE_ID, motionDownTimeline.sources, AMOTION_EVENT_ACTION_DOWN,
+ InputEventType::MOTION);
+ mTracker->trackListener(inputEventId + 1, motionMoveTimeline.eventTime,
+ motionMoveTimeline.readTime, DEVICE_ID, motionMoveTimeline.sources,
+ AMOTION_EVENT_ACTION_MOVE, InputEventType::MOTION);
+ mTracker->trackListener(inputEventId + 2, motionUpTimeline.eventTime, motionUpTimeline.readTime,
+ DEVICE_ID, motionUpTimeline.sources, AMOTION_EVENT_ACTION_UP,
+ InputEventType::MOTION);
+ mTracker->trackListener(inputEventId + 3, keyDownTimeline.eventTime, keyDownTimeline.readTime,
+ DEVICE_ID, keyDownTimeline.sources, AKEY_EVENT_ACTION_DOWN,
+ InputEventType::KEY);
+ mTracker->trackListener(inputEventId + 4, keyUpTimeline.eventTime, keyUpTimeline.readTime,
+ DEVICE_ID, keyUpTimeline.sources, AKEY_EVENT_ACTION_UP,
+ InputEventType::KEY);
+ mTracker->trackListener(inputEventId + 5, unknownTimeline.eventTime, unknownTimeline.readTime,
+ DEVICE_ID, unknownTimeline.sources, AMOTION_EVENT_ACTION_POINTER_DOWN,
+ InputEventType::MOTION);
+
+ triggerEventReporting(unknownTimeline.eventTime);
+
+ std::vector<InputEventTimeline> expectedTimelines = {motionDownTimeline, motionMoveTimeline,
+ motionUpTimeline, keyDownTimeline,
+ keyUpTimeline, unknownTimeline};
+ assertReceivedTimelines(expectedTimelines);
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp b/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp
index 6daeaaf..80c2213 100644
--- a/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp
@@ -18,6 +18,7 @@
#include <linux/input.h>
#include "../../InputDeviceMetricsSource.h"
+#include "../InputEventTimeline.h"
#include "dispatcher/LatencyTracker.h"
namespace android {
@@ -65,14 +66,15 @@
fdp.PickValueInArray<std::function<void()>>({
[&]() -> void {
int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
- int32_t isDown = fdp.ConsumeBool();
nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>();
nsecs_t readTime = fdp.ConsumeIntegral<nsecs_t>();
const DeviceId deviceId = fdp.ConsumeIntegral<int32_t>();
std::set<InputDeviceUsageSource> sources = {
fdp.ConsumeEnum<InputDeviceUsageSource>()};
- tracker.trackListener(inputEventId, isDown, eventTime, readTime, deviceId,
- sources);
+ int32_t inputEventActionType = fdp.ConsumeIntegral<int32_t>();
+ const InputEventType inputEventType = fdp.ConsumeEnum<InputEventType>();
+ tracker.trackListener(inputEventId, eventTime, readTime, deviceId, sources,
+ inputEventActionType, inputEventType);
},
[&]() -> void {
int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
index b0b1a02..eb6e677 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
@@ -33,6 +33,7 @@
#include "DisplayHardware/HWC2.h"
#include <aidl/android/hardware/graphics/composer3/Composition.h>
+#include <aidl/android/hardware/graphics/composer3/Lut.h>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
@@ -77,6 +78,7 @@
Error(const std::string&, bool, const std::vector<uint8_t>&));
MOCK_METHOD1(setBrightness, Error(float));
MOCK_METHOD1(setBlockingRegion, Error(const android::Region&));
+ MOCK_METHOD(Error, setLuts, (std::vector<aidl::android::hardware::graphics::composer3::Lut>&));
};
} // namespace mock
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 629d9f2..839fb7d 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -151,6 +151,10 @@
getOverlaySupport, (), (const, override));
MOCK_METHOD(status_t, setRefreshRateChangedCallbackDebugEnabled, (PhysicalDisplayId, bool));
MOCK_METHOD(status_t, notifyExpectedPresent, (PhysicalDisplayId, TimePoint, Fps));
+ MOCK_METHOD(status_t, getRequestedLuts,
+ (PhysicalDisplayId,
+ std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*),
+ (override));
};
} // namespace mock
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 0eced73..20ae74a 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -1540,7 +1540,7 @@
return error;
}
-Error AidlComposer::getDisplayLuts(Display display, std::vector<Lut>* outLuts) {
+Error AidlComposer::getRequestedLuts(Display display, std::vector<DisplayLuts::LayerLut>* outLuts) {
Error error = Error::NONE;
mMutex.lock_shared();
if (auto reader = getReader(display)) {
@@ -1552,6 +1552,18 @@
return error;
}
+Error AidlComposer::setLayerLuts(Display display, Layer layer, std::vector<Lut>& luts) {
+ Error error = Error::NONE;
+ mMutex.lock_shared();
+ if (auto writer = getWriter(display)) {
+ writer->get().setLayerLuts(translate<int64_t>(display), translate<int64_t>(layer), luts);
+ } else {
+ error = Error::BAD_DISPLAY;
+ }
+ mMutex.unlock_shared();
+ return error;
+}
+
Error AidlComposer::setLayerBrightness(Display display, Layer layer, float brightness) {
Error error = Error::NONE;
mMutex.lock_shared();
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index 3669d4c..246223a 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -244,9 +244,13 @@
Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) override;
Error notifyExpectedPresent(Display, nsecs_t expectedPresentTime,
int32_t frameIntervalNs) override;
- Error getDisplayLuts(
+ Error getRequestedLuts(
Display display,
- std::vector<aidl::android::hardware::graphics::composer3::Lut>* outLuts) override;
+ std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*
+ outLuts) override;
+ Error setLayerLuts(
+ Display display, Layer layer,
+ std::vector<aidl::android::hardware::graphics::composer3::Lut>& luts) override;
private:
// Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 888dc08..7db9a94 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -40,6 +40,7 @@
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
#include <aidl/android/hardware/graphics/composer3/DisplayConfiguration.h>
+#include <aidl/android/hardware/graphics/composer3/DisplayLuts.h>
#include <aidl/android/hardware/graphics/composer3/IComposerCallback.h>
#include <aidl/android/hardware/graphics/composer3/Lut.h>
#include <aidl/android/hardware/graphics/composer3/OverlayProperties.h>
@@ -304,7 +305,9 @@
virtual Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) = 0;
virtual Error notifyExpectedPresent(Display, nsecs_t expectedPresentTime,
int32_t frameIntervalNs) = 0;
- virtual Error getDisplayLuts(Display display, std::vector<V3_0::Lut>* outLuts) = 0;
+ virtual Error getRequestedLuts(Display display,
+ std::vector<V3_0::DisplayLuts::LayerLut>* outLuts) = 0;
+ virtual Error setLayerLuts(Display display, Layer layer, std::vector<V3_0::Lut>& luts) = 0;
};
} // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index d5f65c6..8e78af4 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -41,6 +41,7 @@
using aidl::android::hardware::graphics::composer3::Composition;
using AidlCapability = aidl::android::hardware::graphics::composer3::Capability;
using aidl::android::hardware::graphics::composer3::DisplayCapability;
+using aidl::android::hardware::graphics::composer3::DisplayLuts;
using aidl::android::hardware::graphics::composer3::Lut;
using aidl::android::hardware::graphics::composer3::OverlayProperties;
@@ -608,13 +609,14 @@
return static_cast<Error>(error);
}
-Error Display::getDisplayLuts(std::vector<Lut>* outLuts) {
- std::vector<Lut> tmpLuts;
- const auto error = mComposer.getDisplayLuts(mId, &tmpLuts);
- for (Lut& lut : tmpLuts) {
- if (lut.pfd.get() >= 0) {
- outLuts->push_back(
- {lut.layer, ndk::ScopedFileDescriptor(lut.pfd.release()), lut.lutProperties});
+Error Display::getRequestedLuts(std::vector<DisplayLuts::LayerLut>* outLayerLuts) {
+ std::vector<DisplayLuts::LayerLut> tmpLayerLuts;
+ const auto error = mComposer.getRequestedLuts(mId, &tmpLayerLuts);
+ for (DisplayLuts::LayerLut& layerLut : tmpLayerLuts) {
+ if (layerLut.lut.pfd.get() >= 0) {
+ outLayerLuts->push_back({layerLut.layer,
+ Lut{ndk::ScopedFileDescriptor(layerLut.lut.pfd.release()),
+ layerLut.lut.lutProperties}});
}
}
return static_cast<Error>(error);
@@ -1050,6 +1052,14 @@
return static_cast<Error>(intError);
}
+Error Layer::setLuts(std::vector<Lut>& luts) {
+ if (CC_UNLIKELY(!mDisplay)) {
+ return Error::BAD_DISPLAY;
+ }
+ const auto intError = mComposer.setLayerLuts(mDisplay->getId(), mId, luts);
+ return static_cast<Error>(intError);
+}
+
} // namespace impl
} // namespace HWC2
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index be2059a..c2dc943 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -179,8 +179,9 @@
[[nodiscard]] virtual hal::Error getClientTargetProperty(
aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness*
outClientTargetProperty) = 0;
- [[nodiscard]] virtual hal::Error getDisplayLuts(
- std::vector<aidl::android::hardware::graphics::composer3::Lut>* outLuts) = 0;
+ [[nodiscard]] virtual hal::Error getRequestedLuts(
+ std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*
+ outLuts) = 0;
[[nodiscard]] virtual hal::Error getDisplayDecorationSupport(
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) = 0;
@@ -264,8 +265,9 @@
hal::Error getClientTargetProperty(
aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness*
outClientTargetProperty) override;
- hal::Error getDisplayLuts(
- std::vector<aidl::android::hardware::graphics::composer3::Lut>* outLuts) override;
+ hal::Error getRequestedLuts(
+ std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*
+ outLuts) override;
hal::Error getDisplayDecorationSupport(
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) override;
@@ -359,6 +361,8 @@
// AIDL HAL
[[nodiscard]] virtual hal::Error setBrightness(float brightness) = 0;
[[nodiscard]] virtual hal::Error setBlockingRegion(const android::Region& region) = 0;
+ [[nodiscard]] virtual hal::Error setLuts(
+ std::vector<aidl::android::hardware::graphics::composer3::Lut>& luts) = 0;
};
namespace impl {
@@ -409,6 +413,8 @@
// AIDL HAL
hal::Error setBrightness(float brightness) override;
hal::Error setBlockingRegion(const android::Region& region) override;
+ hal::Error setLuts(
+ std::vector<aidl::android::hardware::graphics::composer3::Lut>& luts) override;
private:
// These are references to data owned by HWComposer, which will outlive
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 73fa855..c83e0da 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -533,6 +533,7 @@
DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
+ RETURN_IF_HWC_ERROR_FOR("getClientTargetProperty", error, displayId, BAD_INDEX);
outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
std::move(layerRequests),
@@ -925,6 +926,21 @@
return NO_ERROR;
}
+status_t HWComposer::getRequestedLuts(
+ PhysicalDisplayId displayId,
+ std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>* outLuts) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error = mDisplayData[displayId].hwcDisplay->getRequestedLuts(outLuts);
+ if (error == hal::Error::UNSUPPORTED) {
+ RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+ }
+ if (error == hal::Error::BAD_PARAMETER) {
+ RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+ }
+ RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 9368b7b..dec4bfe 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -52,6 +52,7 @@
#include <aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
+#include <aidl/android/hardware/graphics/composer3/DisplayLuts.h>
#include <aidl/android/hardware/graphics/composer3/OverlayProperties.h>
namespace android {
@@ -309,6 +310,11 @@
virtual status_t setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId, bool enabled) = 0;
virtual status_t notifyExpectedPresent(PhysicalDisplayId, TimePoint expectedPresentTime,
Fps frameInterval) = 0;
+
+ // Composer 4.0
+ virtual status_t getRequestedLuts(
+ PhysicalDisplayId,
+ std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*) = 0;
};
static inline bool operator==(const android::HWComposer::DeviceRequestedChanges& lhs,
@@ -472,6 +478,12 @@
status_t notifyExpectedPresent(PhysicalDisplayId, TimePoint expectedPresentTime,
Fps frameInterval) override;
+ // Composer 4.0
+ status_t getRequestedLuts(
+ PhysicalDisplayId,
+ std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*)
+ override;
+
// for debugging ----------------------------------------------------------
void dump(std::string& out) const override;
void dumpOverlayProperties(std::string& out) const override;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index ec2a3ec..ee1e07a 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -46,6 +46,7 @@
using aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness;
using aidl::android::hardware::graphics::composer3::DimmingStage;
using aidl::android::hardware::graphics::composer3::DisplayCapability;
+using aidl::android::hardware::graphics::composer3::DisplayLuts;
using aidl::android::hardware::graphics::composer3::Lut;
using aidl::android::hardware::graphics::composer3::OverlayProperties;
@@ -1409,7 +1410,11 @@
return Error::NONE;
}
-Error HidlComposer::getDisplayLuts(Display, std::vector<Lut>*) {
+Error HidlComposer::getRequestedLuts(Display, std::vector<DisplayLuts::LayerLut>*) {
+ return Error::NONE;
+}
+
+Error HidlComposer::setLayerLuts(Display, Layer, std::vector<Lut>&) {
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 8bca5ad..701a54b 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -351,8 +351,12 @@
Hdr*) override;
Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) override;
Error notifyExpectedPresent(Display, nsecs_t, int32_t) override;
- Error getDisplayLuts(Display,
- std::vector<aidl::android::hardware::graphics::composer3::Lut>*) override;
+ Error getRequestedLuts(
+ Display,
+ std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*)
+ override;
+ Error setLayerLuts(Display, Layer,
+ std::vector<aidl::android::hardware::graphics::composer3::Lut>&) override;
private:
class CommandWriter : public CommandWriterBase {
diff --git a/services/surfaceflinger/FrontEnd/Update.h b/services/surfaceflinger/FrontEnd/Update.h
index e5cca8f..4af27ab 100644
--- a/services/surfaceflinger/FrontEnd/Update.h
+++ b/services/surfaceflinger/FrontEnd/Update.h
@@ -22,28 +22,13 @@
#include "RequestedLayerState.h"
#include "TransactionState.h"
-namespace android {
-struct LayerCreatedState {
- LayerCreatedState(const wp<Layer>& layer, const wp<Layer>& parent, bool addToRoot)
- : layer(layer), initialParent(parent), addToRoot(addToRoot) {}
- wp<Layer> layer;
- // Indicates the initial parent of the created layer, only used for creating layer in
- // SurfaceFlinger. If nullptr, it may add the created layer into the current root layers.
- wp<Layer> initialParent;
- // Indicates whether the layer getting created should be added at root if there's no parent
- // and has permission ACCESS_SURFACE_FLINGER. If set to false and no parent, the layer will
- // be added offscreen.
- bool addToRoot;
-};
-} // namespace android
-
namespace android::surfaceflinger::frontend {
// Atomic set of changes affecting layer state. These changes are queued in binder threads and
// applied every vsync.
struct Update {
std::vector<TransactionState> transactions;
- std::vector<LayerCreatedState> layerCreatedStates;
+ std::vector<sp<Layer>> legacyLayers;
std::vector<std::unique_ptr<frontend::RequestedLayerState>> newLayers;
std::vector<LayerCreationArgs> layerCreationArgs;
std::vector<std::pair<uint32_t, std::string /* debugName */>> destroyedHandles;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 636f7bd..7b12a80 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -231,10 +231,6 @@
LOG_ALWAYS_FATAL_IF(std::this_thread::get_id() != mFlinger->mMainThreadId,
"Layer destructor called off the main thread.");
- // The original layer and the clone layer share the same texture and buffer. Therefore, only
- // one of the layers, in this case the original layer, needs to handle the deletion. The
- // original layer and the clone should be removed at the same time so there shouldn't be any
- // issue with the clone layer trying to use the texture.
if (mBufferInfo.mBuffer != nullptr) {
callReleaseBufferCallback(mDrawingState.releaseBufferListener,
mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber,
@@ -250,10 +246,6 @@
if (mDrawingState.sidebandStream != nullptr) {
mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
}
- if (mHadClonedChild) {
- auto& roots = mFlinger->mLayerMirrorRoots;
- roots.erase(std::remove(roots.begin(), roots.end(), this), roots.end());
- }
if (hasTrustedPresentationListener()) {
mFlinger->mNumTrustedPresentationListeners--;
updateTrustedPresentationState(nullptr, nullptr, -1 /* time_in_ms */, true /* leaveState*/);
@@ -282,48 +274,6 @@
}
}
-void Layer::removeFromCurrentState() {
- if (!mRemovedFromDrawingState) {
- mRemovedFromDrawingState = true;
- mFlinger->mScheduler->deregisterLayer(this);
- }
- updateTrustedPresentationState(nullptr, nullptr, -1 /* time_in_ms */, true /* leaveState*/);
-
- mFlinger->markLayerPendingRemovalLocked(sp<Layer>::fromExisting(this));
-}
-
-sp<Layer> Layer::getRootLayer() {
- sp<Layer> parent = getParent();
- if (parent == nullptr) {
- return sp<Layer>::fromExisting(this);
- }
- return parent->getRootLayer();
-}
-
-void Layer::onRemovedFromCurrentState() {
- // Use the root layer since we want to maintain the hierarchy for the entire subtree.
- auto layersInTree = getRootLayer()->getLayersInTree(LayerVector::StateSet::Current);
- std::sort(layersInTree.begin(), layersInTree.end());
-
- REQUIRE_MUTEX(mFlinger->mStateLock);
- traverse(LayerVector::StateSet::Current,
- [&](Layer* layer) REQUIRES(layer->mFlinger->mStateLock) {
- layer->removeFromCurrentState();
- layer->removeRelativeZ(layersInTree);
- });
-}
-
-void Layer::addToCurrentState() {
- if (mRemovedFromDrawingState) {
- mRemovedFromDrawingState = false;
- mFlinger->mScheduler->registerLayer(this, FrameRateCompatibility::Default);
- }
-
- for (const auto& child : mCurrentChildren) {
- child->addToCurrentState();
- }
-}
-
// ---------------------------------------------------------------------------
// set-up
// ---------------------------------------------------------------------------
@@ -592,7 +542,6 @@
snapshot->alpha = alpha;
snapshot->backgroundBlurRadius = getBackgroundBlurRadius();
snapshot->blurRegions = getBlurRegions();
- snapshot->stretchEffect = getStretchEffect();
}
void Layer::prepareGeometryCompositionState() {
@@ -826,33 +775,6 @@
mTransactionFlags |= mask;
}
-bool Layer::setChildLayer(const sp<Layer>& childLayer, int32_t z) {
- ssize_t idx = mCurrentChildren.indexOf(childLayer);
- if (idx < 0) {
- return false;
- }
- if (childLayer->setLayer(z)) {
- mCurrentChildren.removeAt(idx);
- mCurrentChildren.add(childLayer);
- return true;
- }
- return false;
-}
-
-bool Layer::setChildRelativeLayer(const sp<Layer>& childLayer,
- const sp<IBinder>& relativeToHandle, int32_t relativeZ) {
- ssize_t idx = mCurrentChildren.indexOf(childLayer);
- if (idx < 0) {
- return false;
- }
- if (childLayer->setRelativeLayer(relativeToHandle, relativeZ)) {
- mCurrentChildren.removeAt(idx);
- mCurrentChildren.add(childLayer);
- return true;
- }
- return false;
-}
-
bool Layer::setLayer(int32_t z) {
if (mDrawingState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false;
mDrawingState.sequence++;
@@ -959,46 +881,6 @@
return true;
}
-bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace) {
- if (!mDrawingState.bgColorLayer && alpha == 0) {
- return false;
- }
- mDrawingState.sequence++;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
-
- if (!mDrawingState.bgColorLayer && alpha != 0) {
- // create background color layer if one does not yet exist
- uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect;
- std::string name = mName + "BackgroundColorLayer";
- mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer(
- surfaceflinger::LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags,
- LayerMetadata()));
-
- // add to child list
- addChild(mDrawingState.bgColorLayer);
- mFlinger->mLayersAdded = true;
- // set up SF to handle added color layer
- if (isRemovedFromCurrentState()) {
- MUTEX_ALIAS(mFlinger->mStateLock, mDrawingState.bgColorLayer->mFlinger->mStateLock);
- mDrawingState.bgColorLayer->onRemovedFromCurrentState();
- }
- mFlinger->setTransactionFlags(eTransactionNeeded);
- } else if (mDrawingState.bgColorLayer && alpha == 0) {
- MUTEX_ALIAS(mFlinger->mStateLock, mDrawingState.bgColorLayer->mFlinger->mStateLock);
- mDrawingState.bgColorLayer->reparent(nullptr);
- mDrawingState.bgColorLayer = nullptr;
- return true;
- }
-
- mDrawingState.bgColorLayer->setColor(color);
- mDrawingState.bgColorLayer->setLayer(std::numeric_limits<int32_t>::min());
- mDrawingState.bgColorLayer->setAlpha(alpha);
- mDrawingState.bgColorLayer->setDataspace(dataspace);
-
- return true;
-}
-
bool Layer::setCornerRadius(float cornerRadius) {
if (mDrawingState.cornerRadius == cornerRadius) return false;
@@ -1149,22 +1031,6 @@
return true;
}
-StretchEffect Layer::getStretchEffect() const {
- if (mDrawingState.stretchEffect.hasEffect()) {
- return mDrawingState.stretchEffect;
- }
-
- sp<Layer> parent = getParent();
- if (parent != nullptr) {
- auto effect = parent->getStretchEffect();
- if (effect.hasEffect()) {
- // TODO(b/179047472): Map it? Or do we make the effect be in global space?
- return effect;
- }
- }
- return StretchEffect{};
-}
-
void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info,
nsecs_t postTime, gui::GameMode gameMode) {
mDrawingState.postTime = postTime;
@@ -1439,32 +1305,6 @@
mFlinger->mFrameTracer->onDestroy(layerId);
}
-size_t Layer::getDescendantCount() const {
- size_t count = 0;
- for (const sp<Layer>& child : mDrawingChildren) {
- count += 1 + child->getChildrenCount();
- }
- return count;
-}
-
-void Layer::addChild(const sp<Layer>& layer) {
- mFlinger->mSomeChildrenChanged = true;
- setTransactionFlags(eTransactionNeeded);
-
- mCurrentChildren.add(layer);
- layer->setParent(sp<Layer>::fromExisting(this));
-}
-
-ssize_t Layer::removeChild(const sp<Layer>& layer) {
- mFlinger->mSomeChildrenChanged = true;
- setTransactionFlags(eTransactionNeeded);
-
- layer->setParent(nullptr);
- const auto removeResult = mCurrentChildren.remove(layer);
-
- return removeResult;
-}
-
void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) {
for (const sp<Layer>& child : mDrawingChildren) {
child->mDrawingParent = newParent;
@@ -1475,39 +1315,6 @@
}
}
-bool Layer::reparent(const sp<IBinder>& newParentHandle) {
- sp<Layer> newParent;
- if (newParentHandle != nullptr) {
- newParent = LayerHandle::getLayer(newParentHandle);
- if (newParent == nullptr) {
- ALOGE("Unable to promote Layer handle");
- return false;
- }
- if (newParent == this) {
- ALOGE("Invalid attempt to reparent Layer (%s) to itself", getName().c_str());
- return false;
- }
- }
-
- sp<Layer> parent = getParent();
- if (parent != nullptr) {
- parent->removeChild(sp<Layer>::fromExisting(this));
- }
-
- if (newParentHandle != nullptr) {
- newParent->addChild(sp<Layer>::fromExisting(this));
- if (!newParent->isRemovedFromCurrentState()) {
- addToCurrentState();
- } else {
- onRemovedFromCurrentState();
- }
- } else {
- onRemovedFromCurrentState();
- }
-
- return true;
-}
-
bool Layer::setColorTransform(const mat4& matrix) {
static const mat4 identityMatrix = mat4();
@@ -1590,167 +1397,6 @@
return traverse;
}
-/**
- * Negatively signed relatives are before 'this' in Z-order.
- */
-void Layer::traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) {
- // In the case we have other layers who are using a relative Z to us, makeTraversalList will
- // produce a new list for traversing, including our relatives, and not including our children
- // who are relatives of another surface. In the case that there are no relative Z,
- // makeTraversalList returns our children directly to avoid significant overhead.
- // However in this case we need to take the responsibility for filtering children which
- // are relatives of another surface here.
- bool skipRelativeZUsers = false;
- const LayerVector list = makeTraversalList(stateSet, &skipRelativeZUsers);
-
- size_t i = 0;
- for (; i < list.size(); i++) {
- const auto& relative = list[i];
- if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) {
- continue;
- }
-
- if (relative->getZ(stateSet) >= 0) {
- break;
- }
- relative->traverseInZOrder(stateSet, visitor);
- }
-
- visitor(this);
- for (; i < list.size(); i++) {
- const auto& relative = list[i];
-
- if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) {
- continue;
- }
- relative->traverseInZOrder(stateSet, visitor);
- }
-}
-
-/**
- * Positively signed relatives are before 'this' in reverse Z-order.
- */
-void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet,
- const LayerVector::Visitor& visitor) {
- // See traverseInZOrder for documentation.
- bool skipRelativeZUsers = false;
- LayerVector list = makeTraversalList(stateSet, &skipRelativeZUsers);
-
- int32_t i = 0;
- for (i = int32_t(list.size()) - 1; i >= 0; i--) {
- const auto& relative = list[i];
-
- if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) {
- continue;
- }
-
- if (relative->getZ(stateSet) < 0) {
- break;
- }
- relative->traverseInReverseZOrder(stateSet, visitor);
- }
- visitor(this);
- for (; i >= 0; i--) {
- const auto& relative = list[i];
-
- if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) {
- continue;
- }
-
- relative->traverseInReverseZOrder(stateSet, visitor);
- }
-}
-
-void Layer::traverse(LayerVector::StateSet state, const LayerVector::Visitor& visitor) {
- visitor(this);
- const LayerVector& children =
- state == LayerVector::StateSet::Drawing ? mDrawingChildren : mCurrentChildren;
- for (const sp<Layer>& child : children) {
- child->traverse(state, visitor);
- }
-}
-
-void Layer::traverseChildren(const LayerVector::Visitor& visitor) {
- for (const sp<Layer>& child : mDrawingChildren) {
- visitor(child.get());
- }
-}
-
-LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet,
- const std::vector<Layer*>& layersInTree) {
- LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid,
- "makeTraversalList received invalid stateSet");
- const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
- const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
- const State& state = useDrawing ? mDrawingState : mDrawingState;
-
- LayerVector traverse(stateSet);
- for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
- sp<Layer> strongRelative = weakRelative.promote();
- // Only add relative layers that are also descendents of the top most parent of the tree.
- // If a relative layer is not a descendent, then it should be ignored.
- if (std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) {
- traverse.add(strongRelative);
- }
- }
-
- for (const sp<Layer>& child : children) {
- const State& childState = useDrawing ? child->mDrawingState : child->mDrawingState;
- // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a
- // descendent of the top most parent of the tree. If it's not a descendent, then just add
- // the child here since it won't be added later as a relative.
- if (std::binary_search(layersInTree.begin(), layersInTree.end(),
- childState.zOrderRelativeOf.promote().get())) {
- continue;
- }
- traverse.add(child);
- }
-
- return traverse;
-}
-
-void Layer::traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTree,
- LayerVector::StateSet stateSet,
- const LayerVector::Visitor& visitor) {
- const LayerVector list = makeChildrenTraversalList(stateSet, layersInTree);
-
- size_t i = 0;
- for (; i < list.size(); i++) {
- const auto& relative = list[i];
- if (relative->getZ(stateSet) >= 0) {
- break;
- }
- relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor);
- }
-
- visitor(this);
- for (; i < list.size(); i++) {
- const auto& relative = list[i];
- relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor);
- }
-}
-
-std::vector<Layer*> Layer::getLayersInTree(LayerVector::StateSet stateSet) {
- const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
- const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
-
- std::vector<Layer*> layersInTree = {this};
- for (size_t i = 0; i < children.size(); i++) {
- const auto& child = children[i];
- std::vector<Layer*> childLayers = child->getLayersInTree(stateSet);
- layersInTree.insert(layersInTree.end(), childLayers.cbegin(), childLayers.cend());
- }
-
- return layersInTree;
-}
-
-void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet,
- const LayerVector::Visitor& visitor) {
- std::vector<Layer*> layersInTree = getLayersInTree(stateSet);
- std::sort(layersInTree.begin(), layersInTree.end());
- traverseChildrenInZOrderInner(layersInTree, stateSet, visitor);
-}
-
ui::Transform Layer::getTransform() const {
return mEffectiveTransform;
}
@@ -1861,27 +1507,6 @@
return false;
}
-void Layer::commitChildList() {
- for (size_t i = 0; i < mCurrentChildren.size(); i++) {
- const auto& child = mCurrentChildren[i];
- child->commitChildList();
- }
- mDrawingChildren = mCurrentChildren;
- mDrawingParent = mCurrentParent;
- if (CC_UNLIKELY(usingRelativeZ(LayerVector::StateSet::Drawing))) {
- auto zOrderRelativeOf = mDrawingState.zOrderRelativeOf.promote();
- if (zOrderRelativeOf == nullptr) return;
- if (findInHierarchy(zOrderRelativeOf)) {
- ALOGE("Detected Z ordering loop between %s and %s", mName.c_str(),
- zOrderRelativeOf->mName.c_str());
- ALOGE("Severing rel Z loop, potentially dangerous");
- mDrawingState.isRelativeOf = false;
- zOrderRelativeOf->removeZOrderRelative(wp<Layer>::fromExisting(this));
- }
- }
-}
-
-
void Layer::setInputInfo(const WindowInfo& info) {
mDrawingState.inputInfo = info;
mDrawingState.touchableRegionCrop =
@@ -2048,10 +1673,6 @@
[&]() { return layerInfo->mutable_destination_frame(); });
}
-bool Layer::isRemovedFromCurrentState() const {
- return mRemovedFromDrawingState;
-}
-
// Applies the given transform to the region, while protecting against overflows caused by any
// offsets. If applying the offset in the transform to any of the Rects in the region would result
// in an overflow, they are not added to the output Region.
@@ -2243,16 +1864,6 @@
info.inputConfig |= WindowInfo::InputConfig::TRUSTED_OVERLAY;
}
- // If the layer is a clone, we need to crop the input region to cloned root to prevent
- // touches from going outside the cloned area.
- if (isClone()) {
- info.inputConfig |= WindowInfo::InputConfig::CLONE;
- if (const sp<Layer> clonedRoot = getClonedRoot()) {
- const Rect rect = displayTransform.transform(Rect{clonedRoot->mScreenBounds});
- info.touchableRegion = info.touchableRegion.intersect(rect);
- }
- }
-
Rect bufferSize = getBufferSize(getDrawingState());
info.contentSize = Size(bufferSize.width(), bufferSize.height());
@@ -2280,16 +1891,6 @@
return Rect{layerToDisplay.transform(croppedInputBounds)};
}
-sp<Layer> Layer::getClonedRoot() {
- if (mClonedChild != nullptr) {
- return sp<Layer>::fromExisting(this);
- }
- if (mDrawingParent == nullptr || mDrawingParent.promote() == nullptr) {
- return nullptr;
- }
- return mDrawingParent.promote()->getClonedRoot();
-}
-
bool Layer::hasInputInfo() const {
return mDrawingState.inputInfo.token != nullptr ||
mDrawingState.inputInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
@@ -2329,170 +1930,6 @@
return outputLayer ? outputLayer->getState().visibleRegion : Region();
}
-void Layer::updateCloneBufferInfo() {
- if (!isClone() || !isClonedFromAlive()) {
- return;
- }
-
- sp<Layer> clonedFrom = getClonedFrom();
- mBufferInfo = clonedFrom->mBufferInfo;
- mSidebandStream = clonedFrom->mSidebandStream;
- surfaceDamageRegion = clonedFrom->surfaceDamageRegion;
- mCurrentFrameNumber = clonedFrom->mCurrentFrameNumber.load();
- mPreviousFrameNumber = clonedFrom->mPreviousFrameNumber;
-
- // After buffer info is updated, the drawingState from the real layer needs to be copied into
- // the cloned. This is because some properties of drawingState can change when latchBuffer is
- // called. However, copying the drawingState would also overwrite the cloned layer's relatives
- // and touchableRegionCrop. Therefore, temporarily store the relatives so they can be set in
- // the cloned drawingState again.
- wp<Layer> tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf;
- SortedVector<wp<Layer>> tmpZOrderRelatives = mDrawingState.zOrderRelatives;
- wp<Layer> tmpTouchableRegionCrop = mDrawingState.touchableRegionCrop;
- WindowInfo tmpInputInfo = mDrawingState.inputInfo;
-
- cloneDrawingState(clonedFrom.get());
-
- mDrawingState.touchableRegionCrop = tmpTouchableRegionCrop;
- mDrawingState.zOrderRelativeOf = tmpZOrderRelativeOf;
- mDrawingState.zOrderRelatives = tmpZOrderRelatives;
- mDrawingState.inputInfo = tmpInputInfo;
-}
-
-bool Layer::updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates) {
- if (mClonedChild == nullptr || !mClonedChild->isClonedFromAlive()) {
- // If mClonedChild is null, there is nothing to mirror. If isClonedFromAlive returns false,
- // it means that there is a clone, but the layer it was cloned from has been destroyed. In
- // that case, we want to delete the reference to the clone since we want it to get
- // destroyed. The root, this layer, will still be around since the client can continue
- // to hold a reference, but no cloned layers will be displayed.
- mClonedChild = nullptr;
- return true;
- }
-
- std::map<sp<Layer>, sp<Layer>> clonedLayersMap;
- // If the real layer exists and is in current state, add the clone as a child of the root.
- // There's no need to remove from drawingState when the layer is offscreen since currentState is
- // copied to drawingState for the root layer. So the clonedChild is always removed from
- // drawingState and then needs to be added back each traversal.
- if (!mClonedChild->getClonedFrom()->isRemovedFromCurrentState()) {
- addChildToDrawing(mClonedChild);
- }
-
- mClonedChild->updateClonedDrawingState(clonedLayersMap);
- mClonedChild->updateClonedChildren(sp<Layer>::fromExisting(this), clonedLayersMap);
- mClonedChild->updateClonedRelatives(clonedLayersMap);
-
- for (Layer* root : cloneRootsPendingUpdates) {
- if (clonedLayersMap.find(sp<Layer>::fromExisting(root)) != clonedLayersMap.end()) {
- return false;
- }
- }
- return true;
-}
-
-void Layer::updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
- // If the layer the clone was cloned from is alive, copy the content of the drawingState
- // to the clone. If the real layer is no longer alive, continue traversing the children
- // since we may be able to pull out other children that are still alive.
- if (isClonedFromAlive()) {
- sp<Layer> clonedFrom = getClonedFrom();
- cloneDrawingState(clonedFrom.get());
- clonedLayersMap.emplace(clonedFrom, sp<Layer>::fromExisting(this));
- }
-
- // The clone layer may have children in drawingState since they may have been created and
- // added from a previous request to updateMirorInfo. This is to ensure we don't recreate clones
- // that already exist, since we can just re-use them.
- // The drawingChildren will not get overwritten by the currentChildren since the clones are
- // not updated in the regular traversal. They are skipped since the root will lose the
- // reference to them when it copies its currentChildren to drawing.
- for (sp<Layer>& child : mDrawingChildren) {
- child->updateClonedDrawingState(clonedLayersMap);
- }
-}
-
-void Layer::updateClonedChildren(const sp<Layer>& mirrorRoot,
- std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
- mDrawingChildren.clear();
-
- if (!isClonedFromAlive()) {
- return;
- }
-
- sp<Layer> clonedFrom = getClonedFrom();
- for (sp<Layer>& child : clonedFrom->mDrawingChildren) {
- if (child == mirrorRoot) {
- // This is to avoid cyclical mirroring.
- continue;
- }
- sp<Layer> clonedChild = clonedLayersMap[child];
- if (clonedChild == nullptr) {
- clonedChild = child->createClone();
- clonedLayersMap[child] = clonedChild;
- }
- addChildToDrawing(clonedChild);
- clonedChild->updateClonedChildren(mirrorRoot, clonedLayersMap);
- }
-}
-
-void Layer::updateClonedInputInfo(const std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
- auto cropLayer = mDrawingState.touchableRegionCrop.promote();
- if (cropLayer != nullptr) {
- if (clonedLayersMap.count(cropLayer) == 0) {
- // Real layer had a crop layer but it's not in the cloned hierarchy. Just set to
- // self as crop layer to avoid going outside bounds.
- mDrawingState.touchableRegionCrop = wp<Layer>::fromExisting(this);
- } else {
- const sp<Layer>& clonedCropLayer = clonedLayersMap.at(cropLayer);
- mDrawingState.touchableRegionCrop = clonedCropLayer;
- }
- }
- // Cloned layers shouldn't handle watch outside since their z order is not determined by
- // WM or the client.
- mDrawingState.inputInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, false);
-}
-
-void Layer::updateClonedRelatives(const std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
- mDrawingState.zOrderRelativeOf = wp<Layer>();
- mDrawingState.zOrderRelatives.clear();
-
- if (!isClonedFromAlive()) {
- return;
- }
-
- const sp<Layer>& clonedFrom = getClonedFrom();
- for (wp<Layer>& relativeWeak : clonedFrom->mDrawingState.zOrderRelatives) {
- const sp<Layer>& relative = relativeWeak.promote();
- if (clonedLayersMap.count(relative) > 0) {
- auto& clonedRelative = clonedLayersMap.at(relative);
- mDrawingState.zOrderRelatives.add(clonedRelative);
- }
- }
-
- // Check if the relativeLayer for the real layer is part of the cloned hierarchy.
- // It's possible that the layer it's relative to is outside the requested cloned hierarchy.
- // In that case, we treat the layer as if the relativeOf has been removed. This way, it will
- // still traverse the children, but the layer with the missing relativeOf will not be shown
- // on screen.
- const sp<Layer>& relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote();
- if (clonedLayersMap.count(relativeOf) > 0) {
- const sp<Layer>& clonedRelativeOf = clonedLayersMap.at(relativeOf);
- mDrawingState.zOrderRelativeOf = clonedRelativeOf;
- }
-
- updateClonedInputInfo(clonedLayersMap);
-
- for (sp<Layer>& child : mDrawingChildren) {
- child->updateClonedRelatives(clonedLayersMap);
- }
-}
-
-void Layer::addChildToDrawing(const sp<Layer>& layer) {
- mDrawingChildren.add(layer);
- layer->mDrawingParent = sp<Layer>::fromExisting(this);
-}
-
bool Layer::isInternalDisplayOverlay() const {
const State& s(mDrawingState);
if (s.flags & layer_state_t::eLayerSkipScreenshot) {
@@ -2503,12 +1940,6 @@
return parent && parent->isInternalDisplayOverlay();
}
-void Layer::setClonedChild(const sp<Layer>& clonedChild) {
- mClonedChild = clonedChild;
- mHadClonedChild = true;
- mFlinger->mLayerMirrorRoots.push_back(this);
-}
-
bool Layer::setDropInputMode(gui::DropInputMode mode) {
if (mDrawingState.dropInputMode == mode) {
return false;
@@ -2517,15 +1948,6 @@
return true;
}
-void Layer::cloneDrawingState(const Layer* from) {
- mDrawingState = from->mDrawingState;
- // Skip callback info since they are not applicable for cloned layers.
- mDrawingState.releaseBufferListener = nullptr;
- // TODO (b/238781169) currently broken for mirror layers because we do not
- // track release fences for mirror layers composed on other displays
- mDrawingState.callbackHandles = {};
-}
-
void Layer::callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
const sp<GraphicBuffer>& buffer, uint64_t framenumber,
const sp<Fence>& releaseFence) {
@@ -3372,13 +2794,6 @@
}
}
-sp<Layer> Layer::createClone() {
- surfaceflinger::LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0,
- LayerMetadata());
- sp<Layer> layer = mFlinger->getFactory().createBufferStateLayer(args);
- return layer;
-}
-
void Layer::decrementPendingBufferCount() {
int32_t pendingBuffers = --mPendingBufferTransactions;
tracePendingBufferCount(pendingBuffers);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f6eed63..3692fb8 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -250,8 +250,6 @@
// true if this layer is visible, false otherwise
virtual bool isVisible() const;
- virtual sp<Layer> createClone();
-
// Set a 2x2 transformation matrix on the layer. This transform
// will be applied after parent transforms, but before any final
// producer specified transform.
@@ -297,7 +295,6 @@
virtual bool setMetadata(const LayerMetadata& data);
virtual void setChildrenDrawingParent(const sp<Layer>&);
- virtual bool reparent(const sp<IBinder>& newParentHandle) REQUIRES(mFlinger->mStateLock);
virtual bool setColorTransform(const mat4& matrix);
virtual mat4 getColorTransform() const;
virtual bool hasColorTransform() const;
@@ -326,8 +323,6 @@
gui::GameMode gameMode);
bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& /*handles*/,
bool willPresent);
- virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace)
- REQUIRES(mFlinger->mStateLock);
virtual bool setColorSpaceAgnostic(const bool agnostic);
virtual bool setDimmingEnabled(const bool dimmingEnabled);
virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint);
@@ -426,7 +421,6 @@
// from graphics API
static ui::Dataspace translateDataspace(ui::Dataspace dataspace);
- void updateCloneBufferInfo();
uint64_t mPreviousFrameNumber = 0;
void onCompositionPresented(const DisplayDevice*,
@@ -638,8 +632,6 @@
return {getLayerStack(), isInternalDisplayOverlay()};
}
- bool isRemovedFromCurrentState() const;
-
perfetto::protos::LayerProto* writeToProto(perfetto::protos::LayersProto& layersProto,
uint32_t traceFlags);
void writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto,
@@ -657,8 +649,6 @@
gui::WindowInfo::Type getWindowType() const { return mWindowType; }
- bool updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates);
-
/*
* doTransaction - process the transaction. This is a good place to figure
* out which attributes of the surface have changed.
@@ -671,22 +661,6 @@
*/
void removeRelativeZ(const std::vector<Layer*>& layersInTree);
- /*
- * Remove from current state and mark for removal.
- */
- void removeFromCurrentState() REQUIRES(mFlinger->mStateLock);
-
- /*
- * called with the state lock from a binder thread when the layer is
- * removed from the current list to the pending removal list
- */
- void onRemovedFromCurrentState() REQUIRES(mFlinger->mStateLock);
-
- /*
- * Called when the layer is added back to the current state list.
- */
- void addToCurrentState();
-
inline const State& getDrawingState() const { return mDrawingState; }
inline State& getDrawingState() { return mDrawingState; }
@@ -715,57 +689,9 @@
// is ready to acquire a buffer.
ui::Transform::RotationFlags getFixedTransformHint() const;
- /**
- * Traverse this layer and it's hierarchy of children directly. Unlike traverseInZOrder
- * which will not emit children who have relativeZOrder to another layer, this method
- * just directly emits all children. It also emits them in no particular order.
- * So this method is not suitable for graphical operations, as it doesn't represent
- * the scene state, but it's also more efficient than traverseInZOrder and so useful for
- * book-keeping.
- */
- void traverse(LayerVector::StateSet, const LayerVector::Visitor&);
- void traverseInReverseZOrder(LayerVector::StateSet, const LayerVector::Visitor&);
- void traverseInZOrder(LayerVector::StateSet, const LayerVector::Visitor&);
- void traverseChildren(const LayerVector::Visitor&);
-
- /**
- * Traverse only children in z order, ignoring relative layers that are not children of the
- * parent.
- */
- void traverseChildrenInZOrder(LayerVector::StateSet, const LayerVector::Visitor&);
-
- size_t getDescendantCount() const;
- size_t getChildrenCount() const { return mDrawingChildren.size(); }
bool isHandleAlive() const { return mHandleAlive; }
bool onHandleDestroyed() { return mHandleAlive = false; }
-
- // ONLY CALL THIS FROM THE LAYER DTOR!
- // See b/141111965. We need to add current children to offscreen layers in
- // the layer dtor so as not to dangle layers. Since the layer has not
- // committed its transaction when the layer is destroyed, we must add
- // current children. This is safe in the dtor as we will no longer update
- // the current state, but should not be called anywhere else!
- LayerVector& getCurrentChildren() { return mCurrentChildren; }
-
- void addChild(const sp<Layer>&);
- // Returns index if removed, or negative value otherwise
- // for symmetry with Vector::remove
- ssize_t removeChild(const sp<Layer>& layer);
- sp<Layer> getParent() const { return mCurrentParent.promote(); }
-
- // Should be called with the surfaceflinger statelock held
- bool isAtRoot() const { return mIsAtRoot; }
- void setIsAtRoot(bool isAtRoot) { mIsAtRoot = isAtRoot; }
-
- bool hasParent() const { return getParent() != nullptr; }
Rect getScreenBounds(bool reduceTransparentRegion = true) const;
- bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
- bool setChildRelativeLayer(const sp<Layer>& childLayer,
- const sp<IBinder>& relativeToHandle, int32_t relativeZ);
-
- // Copy the current list of children to the drawing state. Called by
- // SurfaceFlinger to complete a transaction.
- void commitChildList();
int32_t getZ(LayerVector::StateSet) const;
/**
@@ -823,15 +749,6 @@
int32_t getOwnerAppId() { return mOwnerAppId; }
- // This layer is not a clone, but it's the parent to the cloned hierarchy. The
- // variable mClonedChild represents the top layer that will be cloned so this
- // layer will be the parent of mClonedChild.
- // The layers in the cloned hierarchy will match the lifetime of the real layers. That is
- // if the real layer is destroyed, then the clone layer will also be destroyed.
- sp<Layer> mClonedChild;
- bool mHadClonedChild = false;
- void setClonedChild(const sp<Layer>& mClonedChild);
-
mutable bool contentDirty{false};
Region surfaceDamageRegion;
@@ -855,7 +772,6 @@
}
bool setStretchEffect(const StretchEffect& effect);
- StretchEffect getStretchEffect() const;
bool setBufferCrop(const Rect& /* bufferCrop */);
bool setDestinationFrame(const Rect& /* destinationFrame */);
@@ -877,10 +793,6 @@
// CompositionEngine to create a single path for composing layers.
void updateSnapshot(bool updateGeometry);
void updateChildrenSnapshots(bool updateGeometry);
- sp<Layer> getClonedFrom() const {
- return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr;
- }
- bool isClone() { return mClonedFrom != nullptr; }
bool willPresentCurrentTransaction() const;
@@ -946,16 +858,6 @@
void preparePerFrameEffectsCompositionState();
void gatherBufferInfo();
- bool isClonedFromAlive() { return getClonedFrom() != nullptr; }
-
- void cloneDrawingState(const Layer* from);
- void updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap);
- void updateClonedChildren(const sp<Layer>& mirrorRoot,
- std::map<sp<Layer>, sp<Layer>>& clonedLayersMap);
- void updateClonedRelatives(const std::map<sp<Layer>, sp<Layer>>& clonedLayersMap);
- void addChildToDrawing(const sp<Layer>&);
- void updateClonedInputInfo(const std::map<sp<Layer>, sp<Layer>>& clonedLayersMap);
-
void prepareBasicGeometryCompositionState();
void prepareGeometryCompositionState();
void prepareCursorCompositionState();
@@ -1086,19 +988,6 @@
const DisplayDevice&) const;
aidl::android::hardware::graphics::composer3::Composition getCompositionType(
const compositionengine::OutputLayer*) const;
- /**
- * Returns an unsorted vector of all layers that are part of this tree.
- * That includes the current layer and all its descendants.
- */
- std::vector<Layer*> getLayersInTree(LayerVector::StateSet);
- /**
- * Traverses layers that are part of this tree in the correct z order.
- * layersInTree must be sorted before calling this method.
- */
- void traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTree,
- LayerVector::StateSet, const LayerVector::Visitor&);
- LayerVector makeChildrenTraversalList(LayerVector::StateSet,
- const std::vector<Layer*>& layersInTree);
bool propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overrideChildren,
bool* transactionNeeded);
@@ -1107,10 +996,6 @@
gui::DropInputMode getDropInputMode() const;
void handleDropInputMode(gui::WindowInfo& info) const;
- // Find the root of the cloned hierarchy, this means the first non cloned parent.
- // This will return null if first non cloned parent is not found.
- sp<Layer> getClonedRoot();
-
// Finds the top most layer in the hierarchy. This will find the root Layer where the parent is
// null.
sp<Layer> getRootLayer();
@@ -1185,12 +1070,6 @@
bool mGetHandleCalled = false;
- // The current layer is a clone of mClonedFrom. This means that this layer will update it's
- // properties based on mClonedFrom. When mClonedFrom latches a new buffer for BufferLayers,
- // this layer will update it's buffer. When mClonedFrom updates it's drawing state, children,
- // and relatives, this layer will update as well.
- wp<Layer> mClonedFrom;
-
// The inherited shadow radius after taking into account the layer hierarchy. This is the
// final shadow radius for this layer. If a shadow is specified for a layer, then effective
// shadow radius is the set shadow radius, otherwise its the parent's shadow radius.
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index f52e60d..ff0a955 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -61,35 +61,6 @@
return (l->sequence > r->sequence) ? 1 : -1;
}
-void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) const {
- for (size_t i = 0; i < size(); i++) {
- const auto& layer = (*this)[i];
- auto& state = layer->getDrawingState();
- if (state.isRelativeOf) {
- continue;
- }
- layer->traverseInZOrder(stateSet, visitor);
- }
-}
-
-void LayerVector::traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const {
- for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
- const auto& layer = (*this)[i];
- auto& state = layer->getDrawingState();
- if (state.isRelativeOf) {
- continue;
- }
- layer->traverseInReverseZOrder(stateSet, visitor);
- }
-}
-
-void LayerVector::traverse(const Visitor& visitor) const {
- for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
- const auto& layer = (*this)[i];
- layer->traverse(mStateSet, visitor);
- }
-}
-
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/LayerVector.h b/services/surfaceflinger/LayerVector.h
index a531f4f..38dc11d 100644
--- a/services/surfaceflinger/LayerVector.h
+++ b/services/surfaceflinger/LayerVector.h
@@ -46,11 +46,8 @@
// Sorts layer by layer-stack, Z order, and finally creation order (sequence).
int do_compare(const void* lhs, const void* rhs) const override;
-
using Visitor = std::function<void(Layer*)>;
- void traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const;
- void traverseInZOrder(StateSet stateSet, const Visitor& visitor) const;
- void traverse(const Visitor& visitor) const;
+
private:
const StateSet mStateSet;
};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a232228..ce83475 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2371,7 +2371,7 @@
{
// TODO(b/238781169) lockless queue this and keep order.
std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
- update.layerCreatedStates = std::move(mCreatedLayers);
+ update.legacyLayers = std::move(mCreatedLayers);
mCreatedLayers.clear();
update.newLayers = std::move(mNewLayers);
mNewLayers.clear();
@@ -2390,11 +2390,8 @@
}
mLayerLifecycleManager.applyTransactions(update.transactions);
mLayerLifecycleManager.onHandlesDestroyed(update.destroyedHandles);
- for (auto& legacyLayer : update.layerCreatedStates) {
- sp<Layer> layer = legacyLayer.layer.promote();
- if (layer) {
- mLegacyLayers[layer->sequence] = layer;
- }
+ for (auto& legacyLayer : update.legacyLayers) {
+ mLegacyLayers[legacyLayer->sequence] = legacyLayer;
}
mLayerHierarchyBuilder.update(mLayerLifecycleManager);
}
@@ -2848,9 +2845,7 @@
for (auto [layer, layerFE] : layers) {
CompositionResult compositionResult{layerFE->stealCompositionResult()};
for (auto& [releaseFence, layerStack] : compositionResult.releaseFences) {
- Layer* clonedFrom = layer->getClonedFrom().get();
- auto owningLayer = clonedFrom ? clonedFrom : layer;
- owningLayer->onLayerDisplayed(std::move(releaseFence), layerStack);
+ layer->onLayerDisplayed(std::move(releaseFence), layerStack);
}
if (compositionResult.lastClientCompositionFence) {
layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
@@ -4336,55 +4331,8 @@
void SurfaceFlinger::doCommitTransactions() {
SFTRACE_CALL();
-
- if (!mLayersPendingRemoval.isEmpty()) {
- // Notify removed layers now that they can't be drawn from
- for (const auto& l : mLayersPendingRemoval) {
- // Ensure any buffers set to display on any children are released.
- if (l->isRemovedFromCurrentState()) {
- l->latchAndReleaseBuffer();
- }
-
- // If a layer has a parent, we allow it to out-live it's handle
- // with the idea that the parent holds a reference and will eventually
- // be cleaned up. However no one cleans up the top-level so we do so
- // here.
- if (l->isAtRoot()) {
- l->setIsAtRoot(false);
- mCurrentState.layersSortedByZ.remove(l);
- }
- }
- mLayersPendingRemoval.clear();
- }
-
mDrawingState = mCurrentState;
mCurrentState.colorMatrixChanged = false;
-
- if (mVisibleRegionsDirty) {
- for (const auto& rootLayer : mDrawingState.layersSortedByZ) {
- rootLayer->commitChildList();
- }
- }
-
- if (mLayerMirrorRoots.size() > 0) {
- std::deque<Layer*> pendingUpdates;
- pendingUpdates.insert(pendingUpdates.end(), mLayerMirrorRoots.begin(),
- mLayerMirrorRoots.end());
- std::vector<Layer*> needsUpdating;
- for (Layer* cloneRoot : mLayerMirrorRoots) {
- pendingUpdates.pop_front();
- if (cloneRoot->isRemovedFromCurrentState()) {
- continue;
- }
- if (cloneRoot->updateMirrorInfo(pendingUpdates)) {
- } else {
- needsUpdating.push_back(cloneRoot);
- }
- }
- for (Layer* cloneRoot : needsUpdating) {
- cloneRoot->updateMirrorInfo({});
- }
- }
}
void SurfaceFlinger::invalidateLayerStack(const ui::LayerFilter& layerFilter, const Region& dirty) {
@@ -4427,7 +4375,7 @@
args.layerIdToMirror = LayerHandle::getLayerId(args.mirrorLayerHandle.promote());
{
std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
- mCreatedLayers.emplace_back(layer, parent, args.addToRoot);
+ mCreatedLayers.emplace_back(layer);
mNewLayers.emplace_back(std::make_unique<frontend::RequestedLayerState>(args));
args.mirrorLayerHandle.clear();
args.parentHandle.clear();
@@ -5153,8 +5101,6 @@
if (result != NO_ERROR) {
return result;
}
-
- mirrorLayer->setClonedChild(mirrorFrom->createClone());
}
outResult.layerId = mirrorLayer->sequence;
@@ -5268,33 +5214,22 @@
return NO_ERROR;
}
-void SurfaceFlinger::markLayerPendingRemovalLocked(const sp<Layer>& layer) {
- mLayersPendingRemoval.add(layer);
- mLayersRemoved = true;
- setTransactionFlags(eTransactionNeeded);
-}
-
void SurfaceFlinger::onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32_t layerId) {
{
- std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
- mDestroyedHandles.emplace_back(layerId, layer->getDebugName());
- }
-
- {
// Used to remove stalled transactions which uses an internal lock.
ftl::FakeGuard guard(kMainThreadContext);
mTransactionHandler.onLayerDestroyed(layerId);
}
-
JankTracker::flushJankData(layerId);
- Mutex::Autolock lock(mStateLock);
- markLayerPendingRemovalLocked(layer);
+ std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
+ mDestroyedHandles.emplace_back(layerId, layer->getDebugName());
+
+ Mutex::Autolock stateLock(mStateLock);
layer->onHandleDestroyed();
mBufferCountTracker.remove(handle);
layer.clear();
-
- setTransactionFlags(eTransactionFlushNeeded);
+ setTransactionFlags(eTransactionFlushNeeded | eTransactionNeeded);
}
void SurfaceFlinger::initializeDisplays() {
@@ -7199,9 +7134,7 @@
void SurfaceFlinger::attachReleaseFenceFutureToLayer(Layer* layer, LayerFE* layerFE,
ui::LayerStack layerStack) {
ftl::Future<FenceResult> futureFence = layerFE->createReleaseFenceFuture();
- Layer* clonedFrom = layer->getClonedFrom().get();
- auto owningLayer = clonedFrom ? clonedFrom : layer;
- owningLayer->prepareReleaseCallbacks(std::move(futureFence), layerStack);
+ layer->prepareReleaseCallbacks(std::move(futureFence), layerStack);
}
// Loop over all visible layers to see whether there's any protected layer. A protected layer is
@@ -7669,18 +7602,6 @@
// ---------------------------------------------------------------------------
-void SurfaceFlinger::State::traverse(const LayerVector::Visitor& visitor) const {
- layersSortedByZ.traverse(visitor);
-}
-
-void SurfaceFlinger::State::traverseInZOrder(const LayerVector::Visitor& visitor) const {
- layersSortedByZ.traverseInZOrder(stateSet, visitor);
-}
-
-void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& visitor) const {
- layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
-}
-
ftl::Optional<scheduler::FrameRateMode> SurfaceFlinger::getPreferredDisplayMode(
PhysicalDisplayId displayId, DisplayModeId defaultModeId) const {
if (const auto schedulerMode = mScheduler->getPreferredDisplayMode();
@@ -7849,16 +7770,12 @@
void SurfaceFlinger::onLayerFirstRef(Layer* layer) {
mNumLayers++;
- if (!layer->isRemovedFromCurrentState()) {
- mScheduler->registerLayer(layer, scheduler::FrameRateCompatibility::Default);
- }
+ mScheduler->registerLayer(layer, scheduler::FrameRateCompatibility::Default);
}
void SurfaceFlinger::onLayerDestroyed(Layer* layer) {
mNumLayers--;
- if (!layer->isRemovedFromCurrentState()) {
- mScheduler->deregisterLayer(layer);
- }
+ mScheduler->deregisterLayer(layer);
if (mTransactionTracing) {
mTransactionTracing->onLayerRemoved(layer->getSequence());
}
@@ -8011,37 +7928,6 @@
return calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
}
-void SurfaceFlinger::handleLayerCreatedLocked(const LayerCreatedState& state, VsyncId vsyncId) {
- sp<Layer> layer = state.layer.promote();
- if (!layer) {
- ALOGD("Layer was destroyed soon after creation %p", state.layer.unsafe_get());
- return;
- }
- MUTEX_ALIAS(mStateLock, layer->mFlinger->mStateLock);
-
- sp<Layer> parent;
- bool addToRoot = state.addToRoot;
- if (state.initialParent != nullptr) {
- parent = state.initialParent.promote();
- if (parent == nullptr) {
- ALOGD("Parent was destroyed soon after creation %p", state.initialParent.unsafe_get());
- addToRoot = false;
- }
- }
-
- if (parent == nullptr && addToRoot) {
- layer->setIsAtRoot(true);
- mCurrentState.layersSortedByZ.add(layer);
- } else if (parent == nullptr) {
- layer->onRemovedFromCurrentState();
- } else if (parent->isRemovedFromCurrentState()) {
- parent->addChild(layer);
- layer->onRemovedFromCurrentState();
- } else {
- parent->addChild(layer);
- }
-}
-
void SurfaceFlinger::sample() {
if (!mLumaSampling || !mRegionSamplingThread) {
return;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 873fac2..414088e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -297,8 +297,6 @@
// the client can no longer modify this layer directly.
void onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32_t layerId);
- std::vector<Layer*> mLayerMirrorRoots;
-
TransactionCallbackInvoker& getTransactionCallbackInvoker() {
return mTransactionCallbackInvoker;
}
@@ -389,11 +387,10 @@
class State {
public:
- explicit State(LayerVector::StateSet set) : stateSet(set), layersSortedByZ(set) {}
+ explicit State(LayerVector::StateSet set) : stateSet(set) {}
State& operator=(const State& other) {
// We explicitly don't copy stateSet so that, e.g., mDrawingState
// always uses the Drawing StateSet.
- layersSortedByZ = other.layersSortedByZ;
displays = other.displays;
colorMatrixChanged = other.colorMatrixChanged;
if (colorMatrixChanged) {
@@ -405,7 +402,6 @@
}
const LayerVector::StateSet stateSet = LayerVector::StateSet::Invalid;
- LayerVector layersSortedByZ;
// TODO(b/241285876): Replace deprecated DefaultKeyedVector with ftl::SmallMap.
DefaultKeyedVector<wp<IBinder>, DisplayDeviceState> displays;
@@ -425,10 +421,6 @@
mat4 colorMatrix;
ShadowSettings globalShadowSettings;
-
- void traverse(const LayerVector::Visitor& visitor) const;
- void traverseInZOrder(const LayerVector::Visitor& visitor) const;
- void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const;
};
// Keeps track of pending buffers per layer handle in the transaction queue or current/drawing
@@ -847,8 +839,6 @@
status_t mirrorDisplay(DisplayId displayId, const LayerCreationArgs& args,
gui::CreateSurfaceResult& outResult);
- void markLayerPendingRemovalLocked(const sp<Layer>& layer) REQUIRES(mStateLock);
-
// add a layer to SurfaceFlinger
status_t addClientLayer(LayerCreationArgs& args, const sp<IBinder>& handle,
const sp<Layer>& layer, const wp<Layer>& parentLayer,
@@ -1199,7 +1189,6 @@
State mCurrentState{LayerVector::StateSet::Current};
std::atomic<int32_t> mTransactionFlags = 0;
std::atomic<uint32_t> mUniqueTransactionId = 1;
- SortedVector<sp<Layer>> mLayersPendingRemoval;
// Buffers that have been discarded by clients and need to be evicted from per-layer caches so
// the graphics memory can be immediately freed.
@@ -1389,13 +1378,6 @@
std::unordered_map<DisplayId, sp<HdrLayerInfoReporter>> mHdrLayerInfoListeners
GUARDED_BY(mStateLock);
- mutable std::mutex mCreatedLayersLock;
-
- // A temporay pool that store the created layers and will be added to current state in main
- // thread.
- std::vector<LayerCreatedState> mCreatedLayers GUARDED_BY(mCreatedLayersLock);
- void handleLayerCreatedLocked(const LayerCreatedState&, VsyncId) REQUIRES(mStateLock);
-
std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint;
// Must only be accessed on the main thread.
@@ -1436,6 +1418,8 @@
frontend::LayerHierarchyBuilder mLayerHierarchyBuilder GUARDED_BY(kMainThreadContext);
frontend::LayerSnapshotBuilder mLayerSnapshotBuilder GUARDED_BY(kMainThreadContext);
+ mutable std::mutex mCreatedLayersLock;
+ std::vector<sp<Layer>> mCreatedLayers GUARDED_BY(mCreatedLayersLock);
std::vector<std::pair<uint32_t, std::string>> mDestroyedHandles GUARDED_BY(mCreatedLayersLock);
std::vector<std::unique_ptr<frontend::RequestedLayerState>> mNewLayers
GUARDED_BY(mCreatedLayersLock);
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 07c720f..8ec908f 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -155,6 +155,7 @@
DUMP_READ_ONLY_FLAG(force_compile_graphite_renderengine);
DUMP_READ_ONLY_FLAG(single_hop_screenshot);
DUMP_READ_ONLY_FLAG(trace_frame_rate_override);
+ DUMP_READ_ONLY_FLAG(true_hdr_screenshots);
#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
@@ -259,6 +260,7 @@
FLAG_MANAGER_READ_ONLY_FLAG(flush_buffer_slots_to_uncache, "");
FLAG_MANAGER_READ_ONLY_FLAG(force_compile_graphite_renderengine, "");
FLAG_MANAGER_READ_ONLY_FLAG(single_hop_screenshot, "");
+FLAG_MANAGER_READ_ONLY_FLAG(true_hdr_screenshots, "debug.sf.true_hdr_screenshots");
/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index a4b4a2b..473e564 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -93,6 +93,7 @@
bool force_compile_graphite_renderengine() const;
bool single_hop_screenshot() const;
bool trace_frame_rate_override() const;
+ bool true_hdr_screenshots() const;
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index 886167e..0ff846e7 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -114,6 +114,14 @@
}
} # single_hop_screenshot
+flag {
+ name: "true_hdr_screenshots"
+ namespace: "core_graphics"
+ description: "Enables screenshotting display content in HDR, sans tone mapping"
+ bug: "329470026"
+ is_fixed_read_only: true
+} # true_hdr_screenshots
+
flag {
name: "override_trusted_overlay"
namespace: "window_surfaces"
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 358f6b0..45ca7e2 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -884,7 +884,6 @@
mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
layer.clear();
- mFlinger.mutableLayersPendingRemoval().clear();
EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
}
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index a6a2758..710b5cc 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -721,7 +721,6 @@
}
auto& mutableMinAcquiredBuffers() { return SurfaceFlinger::minAcquiredBuffers; }
- auto& mutableLayersPendingRemoval() { return mFlinger->mLayersPendingRemoval; }
auto& mutableLayerSnapshotBuilder() { return mFlinger->mLayerSnapshotBuilder; };
auto fromHandle(const sp<IBinder>& handle) { return LayerHandle::getLayer(handle); }
@@ -789,7 +788,6 @@
mutableDisplays().clear();
mutableCurrentState().displays.clear();
mutableDrawingState().displays.clear();
- mFlinger->mLayersPendingRemoval.clear();
mFlinger->mScheduler.reset();
mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
mFlinger->mRenderEngine = std::unique_ptr<renderengine::RenderEngine>();
diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
index 7bf1674..f8f08c7 100644
--- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
@@ -20,6 +20,7 @@
#include <gui/SurfaceComposerClient.h>
#include <cstdint>
#include "Client.h"
+#include "Layer.h"
#include <layerproto/LayerProtoHeader.h>
#include "FrontEnd/LayerCreationArgs.h"
diff --git a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
index 9f6065b..e27af0e 100644
--- a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
@@ -128,12 +128,10 @@
NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
false);
layer->setSidebandStream(stream, FrameTimelineInfo{}, 20, gui::GameMode::Unsupported);
- mFlinger.mutableCurrentState().layersSortedByZ.add(layer);
mTunnelModeEnabledReporter->updateTunnelModeStatus();
mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener);
EXPECT_EQ(true, mTunnelModeEnabledListener->mTunnelModeEnabled);
mTunnelModeEnabledReporter->removeListener(mTunnelModeEnabledListener);
- mFlinger.mutableCurrentState().layersSortedByZ.remove(layer);
layer = nullptr;
mTunnelModeEnabledReporter->updateTunnelModeStatus();
@@ -154,12 +152,9 @@
layerWithSidebandStream->setSidebandStream(stream, FrameTimelineInfo{}, 20,
gui::GameMode::Unsupported);
- mFlinger.mutableCurrentState().layersSortedByZ.add(simpleLayer);
- mFlinger.mutableCurrentState().layersSortedByZ.add(layerWithSidebandStream);
mTunnelModeEnabledReporter->updateTunnelModeStatus();
EXPECT_EQ(true, mTunnelModeEnabledListener->mTunnelModeEnabled);
- mFlinger.mutableCurrentState().layersSortedByZ.remove(layerWithSidebandStream);
layerWithSidebandStream = nullptr;
mTunnelModeEnabledReporter->updateTunnelModeStatus();
EXPECT_EQ(false, mTunnelModeEnabledListener->mTunnelModeEnabled);
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index e380e19..f472d8f 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -180,8 +180,12 @@
MOCK_METHOD1(onHotplugDisconnect, void(Display));
MOCK_METHOD(Error, setRefreshRateChangedCallbackDebugEnabled, (Display, bool));
MOCK_METHOD(Error, notifyExpectedPresent, (Display, nsecs_t, int32_t));
- MOCK_METHOD(Error, getDisplayLuts,
- (Display, std::vector<aidl::android::hardware::graphics::composer3::Lut>*));
+ MOCK_METHOD(
+ Error, getRequestedLuts,
+ (Display,
+ std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*));
+ MOCK_METHOD(Error, setLayerLuts,
+ (Display, Layer, std::vector<aidl::android::hardware::graphics::composer3::Lut>&));
};
} // namespace Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index 1eda358..2cc1987 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -109,8 +109,9 @@
MOCK_METHOD(hal::Error, getOverlaySupport,
(aidl::android::hardware::graphics::composer3::OverlayProperties *),
(const override));
- MOCK_METHOD(hal::Error, getDisplayLuts,
- (std::vector<aidl::android::hardware::graphics::composer3::Lut>*), (override));
+ MOCK_METHOD(hal::Error, getRequestedLuts,
+ (std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*),
+ (override));
};
class Layer : public HWC2::Layer {
@@ -145,6 +146,8 @@
(const std::string &, bool, const std::vector<uint8_t> &), (override));
MOCK_METHOD(hal::Error, setBrightness, (float), (override));
MOCK_METHOD(hal::Error, setBlockingRegion, (const android::Region &), (override));
+ MOCK_METHOD(hal::Error, setLuts,
+ (std::vector<aidl::android::hardware::graphics::composer3::Lut>&), (override));
};
} // namespace android::HWC2::mock