Merge "Avoid copying Transaction objects unneccessarily." into main
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index ea5343a..a3499c1 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -277,15 +277,6 @@
"-fvisibility=hidden",
"-DBUILDING_LIBBINDER",
],
-
- target: {
- vendor: {
- // Trimming the exported symbols reveals a bug in vendor code, so
- // disable it for the vendor variant for now. http://b/349657329
- // TODO: Fix the issue and remove this override.
- cflags: ["-fvisibility=default"],
- },
- },
}
cc_defaults {
diff --git a/libs/binder/rust/rpcbinder/src/server/trusty.rs b/libs/binder/rust/rpcbinder/src/server/trusty.rs
index fe45dec..54d82d5 100644
--- a/libs/binder/rust/rpcbinder/src/server/trusty.rs
+++ b/libs/binder/rust/rpcbinder/src/server/trusty.rs
@@ -106,6 +106,10 @@
ctx: *mut c_void,
}
+// SAFETY: The opaque handle: `ctx` points into a dynamic allocation,
+// and not tied to anything specific to the current thread.
+unsafe impl Send for RpcServerConnection {}
+
impl Drop for RpcServerConnection {
fn drop(&mut self) {
// We do not need to close handle_fd since we do not own it.
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 6a8a698..771c65b 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -1160,6 +1160,12 @@
pub const fn enum_values() -> [Self; $size] {
[$(Self::$name),*]
}
+
+ #[inline(always)]
+ #[allow(missing_docs)]
+ pub const fn get(&self) -> $backing {
+ self.0
+ }
}
impl std::fmt::Debug for $enum {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 359a528..69ba1d7 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2545,6 +2545,7 @@
if (status.isOk()) {
// convert gui::StaticDisplayInfo to ui::StaticDisplayInfo
outInfo->connectionType = static_cast<ui::DisplayConnectionType>(ginfo.connectionType);
+ outInfo->port = ginfo.port;
outInfo->density = ginfo.density;
outInfo->secure = ginfo.secure;
outInfo->installOrientation = static_cast<ui::Rotation>(ginfo.installOrientation);
diff --git a/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl b/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl
index 0ccda56..7ff332c 100644
--- a/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl
+++ b/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl
@@ -23,6 +23,7 @@
/** @hide */
parcelable StaticDisplayInfo {
DisplayConnectionType connectionType = DisplayConnectionType.Internal;
+ int port = -1;
float density;
boolean secure;
@nullable DeviceProductInfo deviceProductInfo;
diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig
index a893b84..ce1bc95 100644
--- a/libs/gui/libgui_flags.aconfig
+++ b/libs/gui/libgui_flags.aconfig
@@ -130,9 +130,6 @@
description: "Remove BufferQueueProducer::dequeue's wait on this fence (or the fence entirely) to prevent deadlocks"
bug: "339705065"
is_fixed_read_only: true
- metadata {
- purpose: PURPOSE_BUGFIX
- }
} # bq_gl_fence_cleanup
flag {
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index cf05fd4..adf8fce 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -222,8 +222,8 @@
ASSERT_EQ(InputEventType::MOTION, ev->getType());
MotionEvent* mev = static_cast<MotionEvent*>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
- EXPECT_EQ(x, mev->getX(0));
- EXPECT_EQ(y, mev->getY(0));
+ EXPECT_NEAR(x, mev->getX(0), EPSILON);
+ EXPECT_NEAR(y, mev->getY(0), EPSILON);
EXPECT_EQ(flags, mev->getFlags() & flags);
ev = consumeEvent();
@@ -241,8 +241,8 @@
MotionEvent* mev = static_cast<MotionEvent*>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
const PointerCoords& coords = *mev->getRawPointerCoords(0 /*pointerIndex*/);
- EXPECT_EQ(displayX, coords.getX());
- EXPECT_EQ(displayY, coords.getY());
+ EXPECT_NEAR(displayX, coords.getX(), EPSILON);
+ EXPECT_NEAR(displayY, coords.getY(), EPSILON);
EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
ev = consumeEvent();
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 7f207f0..f9b84fa 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -25,6 +25,7 @@
defaults: [
"android.hardware.graphics.composer3-ndk_shared",
"renderengine_defaults",
+ "libsurfaceflinger_common_deps",
],
cflags: [
"-DGL_GLEXT_PROTOTYPES",
@@ -117,7 +118,10 @@
// possible if libskia_renderengine is just pulled into librenderengine via whole_static_libs.
cc_defaults {
name: "librenderengine_deps",
- defaults: ["skia_renderengine_deps"],
+ defaults: [
+ "skia_renderengine_deps",
+ "libsurfaceflinger_common_deps",
+ ],
static_libs: ["libskia_renderengine"],
}
diff --git a/libs/renderengine/benchmark/Android.bp b/libs/renderengine/benchmark/Android.bp
index f84db0b..2d18ddb 100644
--- a/libs/renderengine/benchmark/Android.bp
+++ b/libs/renderengine/benchmark/Android.bp
@@ -28,6 +28,7 @@
"android.hardware.graphics.composer3-ndk_shared",
"librenderengine_deps",
"surfaceflinger_defaults",
+ "libsurfaceflinger_common_deps",
],
srcs: [
"main.cpp",
@@ -38,7 +39,6 @@
static_libs: [
"librenderengine",
"libshaders",
- "libsurfaceflinger_common",
"libtonemap",
],
cflags: [
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index 25afc7b..9e1c226 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -1236,6 +1236,16 @@
LOG_ALWAYS_FATAL_IF(activeSurface != dstSurface);
auto drawFence = sp<Fence>::make(flushAndSubmit(context, dstSurface));
trace(drawFence);
+ FenceTimePtr fenceTime = FenceTime::makeValid(drawFence);
+ for (const auto& layer : layers) {
+ if (FlagManager::getInstance().monitor_buffer_fences()) {
+ if (layer.source.buffer.buffer) {
+ layer.source.buffer.buffer->getBuffer()
+ ->getDependencyMonitor()
+ .addAccessCompletion(fenceTime, "RE");
+ }
+ }
+ }
resultPromise->set_value(std::move(drawFence));
}
diff --git a/libs/renderengine/skia/filters/LutShader.cpp b/libs/renderengine/skia/filters/LutShader.cpp
index f262158..6a577ff 100644
--- a/libs/renderengine/skia/filters/LutShader.cpp
+++ b/libs/renderengine/skia/filters/LutShader.cpp
@@ -24,7 +24,6 @@
#include <ui/ColorSpace.h>
#include "include/core/SkColorSpace.h"
-#include "src/core/SkColorFilterPriv.h"
using aidl::android::hardware::graphics::composer3::LutProperties;
@@ -116,7 +115,7 @@
linear = mix(c0, c1, linear.b);
}
}
- return float4(linear, rgba.a);
+ return float4(fromLinearSrgb(linear), rgba.a);
})");
// same as shader::toColorSpace function
@@ -289,9 +288,7 @@
lutProperties[i].samplingKey, srcDataspace);
}
- auto colorXformLutToDst =
- SkColorFilterPriv::MakeColorSpaceXform(lutMathColorSpace, outColorSpace);
- input = input->makeWithColorFilter(colorXformLutToDst);
+ input = input->makeWithWorkingColorSpace(outColorSpace);
}
return input;
}
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 87e213e..10cb992 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -122,6 +122,7 @@
srcs: [
"DebugUtils.cpp",
+ "DependencyMonitor.cpp",
"DeviceProductInfo.cpp",
"DisplayIdentification.cpp",
"DynamicDisplayInfo.cpp",
diff --git a/libs/ui/DependencyMonitor.cpp b/libs/ui/DependencyMonitor.cpp
new file mode 100644
index 0000000..b7e490e
--- /dev/null
+++ b/libs/ui/DependencyMonitor.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "DependencyMonitor"
+
+#include <ui/DependencyMonitor.h>
+#include <ui/Fence.h>
+#include <utils/Timers.h>
+
+#include <inttypes.h>
+
+namespace android {
+
+void DependencyMonitor::addIngress(FenceTimePtr fence, std::string annotation) {
+ std::lock_guard lock(mMutex);
+ resolveLocked();
+ if (mDependencies.isFull() && !mDependencies.front().updateSignalTimes(true)) {
+ ALOGD("%s: Clobbering unresolved dependencies -- make me bigger!", mToken.c_str());
+ }
+
+ auto& entry = mDependencies.next();
+ entry.reset(mToken.c_str());
+ ALOGV("%" PRId64 "/%s: addIngress at CPU time %" PRId64 " (%s)", mDependencies.back().id,
+ mToken.c_str(), systemTime(), annotation.c_str());
+
+ mDependencies.back().ingress = {std::move(fence), std::move(annotation)};
+}
+
+void DependencyMonitor::addAccessCompletion(FenceTimePtr fence, std::string annotation) {
+ std::lock_guard lock(mMutex);
+ if (mDependencies.size() == 0) {
+ return;
+ }
+ ALOGV("%" PRId64 "/%s: addAccessCompletion at CPU time %" PRId64 " (%s)",
+ mDependencies.back().id, mToken.c_str(), systemTime(), annotation.c_str());
+ mDependencies.back().accessCompletions.emplace_back(std::move(fence), std::move(annotation));
+}
+
+void DependencyMonitor::addEgress(FenceTimePtr fence, std::string annotation) {
+ std::lock_guard lock(mMutex);
+ if (mDependencies.size() == 0) {
+ return;
+ }
+ ALOGV("%" PRId64 "/%s: addEgress at CPU time %" PRId64 " (%s)", mDependencies.back().id,
+ mToken.c_str(), systemTime(), annotation.c_str());
+ mDependencies.back().egress = {std::move(fence), std::move(annotation)};
+}
+
+void DependencyMonitor::resolveLocked() {
+ if (mDependencies.size() == 0) {
+ return;
+ }
+
+ for (size_t i = mDependencies.size(); i > 0; i--) {
+ auto& dependencyBlock = mDependencies[i - 1];
+
+ if (dependencyBlock.validated) {
+ continue;
+ }
+
+ if (!dependencyBlock.updateSignalTimes(false)) {
+ break;
+ }
+
+ dependencyBlock.validated = true;
+ dependencyBlock.checkUnsafeAccess();
+ }
+}
+
+bool DependencyMonitor::DependencyBlock::updateSignalTimes(bool excludeIngress) {
+ if (egress.fence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
+ return false;
+ }
+
+ if (!excludeIngress && ingress.fence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
+ return false;
+ }
+
+ for (auto& accessCompletion : accessCompletions) {
+ if (accessCompletion.fence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void DependencyMonitor::DependencyBlock::checkUnsafeAccess() const {
+ const nsecs_t egressTime = egress.fence->getCachedSignalTime();
+ const nsecs_t ingressTime = ingress.fence->getCachedSignalTime();
+
+ ALOGV_IF(egressTime != Fence::SIGNAL_TIME_INVALID,
+ "%" PRId64 "/%s: Egress time: %" PRId64 " (%s)", token, id, egressTime,
+ egress.annotation.c_str());
+ ALOGV_IF(Fence::isValidTimestamp(egressTime) && Fence::isValidTimestamp(ingressTime) &&
+ egressTime < ingressTime,
+ "%" PRId64 "/%s: Detected egress before ingress!: %" PRId64 " (%s) < %" PRId64 " (%s)",
+ id, token, egressTime, egress.annotation, ingressTime, ingress.annotation.c_str());
+
+ for (auto& accessCompletion : accessCompletions) {
+ const nsecs_t accessCompletionTime = accessCompletion.fence->getCachedSignalTime();
+ if (!Fence::isValidTimestamp(accessCompletionTime)) {
+ ALOGI("%" PRId64 "/%s: Detected invalid access completion! <%s>", id, token,
+ accessCompletion.annotation.c_str());
+ continue;
+ } else {
+ ALOGV("%" PRId64 "/%s: Access completion time: %" PRId64 " <%s>", id, token,
+ accessCompletionTime, accessCompletion.annotation.c_str());
+ }
+
+ ALOGI_IF(Fence::isValidTimestamp(egressTime) && accessCompletionTime > egressTime,
+ "%" PRId64 "/%s: Detected access completion after egress!: %" PRId64
+ " (%s) > %" PRId64 " (%s)",
+ id, token, accessCompletionTime, accessCompletion.annotation.c_str(), egressTime,
+ egress.annotation.c_str());
+
+ ALOGI_IF(Fence::isValidTimestamp(ingressTime) && accessCompletionTime < ingressTime,
+ "%" PRId64 "/%s: Detected access completion prior to ingress!: %" PRId64
+ " (%s) < %" PRId64 " (%s)",
+ id, token, accessCompletionTime, accessCompletion.annotation.c_str(), ingressTime,
+ ingress.annotation.c_str());
+ }
+
+ ALOGV_IF(ingressTime != Fence::SIGNAL_TIME_INVALID,
+ "%" PRId64 "/%s: Ingress time: %" PRId64 " (%s)", id, token, ingressTime,
+ ingress.annotation.c_str());
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp
index 4246c40..81afe9e 100644
--- a/libs/ui/FenceTime.cpp
+++ b/libs/ui/FenceTime.cpp
@@ -59,6 +59,14 @@
}
}
+FenceTimePtr FenceTime::makeValid(const sp<Fence>& fence) {
+ if (fence && fence->isValid()) {
+ return std::make_shared<FenceTime>(fence);
+ } else {
+ return std::make_shared<FenceTime>(systemTime());
+ }
+}
+
void FenceTime::applyTrustedSnapshot(const Snapshot& src) {
if (CC_UNLIKELY(src.state != Snapshot::State::SIGNAL_TIME)) {
// Applying Snapshot::State::FENCE, could change the valid state of the
@@ -289,9 +297,10 @@
// ============================================================================
void FenceTimeline::push(const std::shared_ptr<FenceTime>& fence) {
std::lock_guard<std::mutex> lock(mMutex);
- while (mQueue.size() >= MAX_ENTRIES) {
+ static constexpr size_t MAX_QUEUE_SIZE = 64;
+ while (mQueue.size() >= MAX_QUEUE_SIZE) {
// This is a sanity check to make sure the queue doesn't grow unbounded.
- // MAX_ENTRIES should be big enough not to trigger this path.
+ // MAX_QUEUE_SIZE should be big enough not to trigger this path.
// In case this path is taken though, users of FenceTime must make sure
// not to rely solely on FenceTimeline to get the final timestamp and
// should eventually call Fence::getSignalTime on their own.
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 18c9a6b..f7c9400 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -27,6 +27,8 @@
#include <ui/GraphicBufferMapper.h>
#include <utils/Trace.h>
+#include <string>
+
namespace android {
// ===========================================================================
@@ -104,6 +106,7 @@
usage = 0;
layerCount = 0;
handle = nullptr;
+ mDependencyMonitor.setToken(std::to_string(mId));
}
// deprecated
@@ -155,6 +158,8 @@
layerCount = request.layerCount;
usage = request.usage;
usage_deprecated = int(usage);
+ std::string name = request.requestorName;
+ mDependencyMonitor.setToken(name.append(":").append(std::to_string(mId)));
}
}
@@ -252,6 +257,7 @@
usage = inUsage;
usage_deprecated = int(usage);
stride = static_cast<int>(outStride);
+ mDependencyMonitor.setToken(requestorName.append(":").append(std::to_string(mId)));
}
return err;
}
@@ -609,6 +615,14 @@
mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
}
+ std::string name;
+ status_t err = mBufferMapper.getName(handle, &name);
+ if (err != NO_ERROR) {
+ name = "<Unknown>";
+ }
+
+ mDependencyMonitor.setToken(name.append(":").append(std::to_string(mId)));
+
buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
size -= sizeNeeded;
fds += numFds;
diff --git a/libs/ui/include/ui/DependencyMonitor.h b/libs/ui/include/ui/DependencyMonitor.h
new file mode 100644
index 0000000..5ad1fd9
--- /dev/null
+++ b/libs/ui/include/ui/DependencyMonitor.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <ui/FatVector.h>
+#include <ui/FenceTime.h>
+#include <ui/RingBuffer.h>
+
+namespace android {
+
+// Debugging class for that tries to add userspace logging for fence depencencies.
+// The model that a DependencyMonitor tries to follow is, for each access of some resource:
+// 1. There is a single ingress fence, that guards whether a resource is now safe to read from
+// another system.
+// 2. There are multiple access fences, that are fired when a resource is read.
+// 3. There is a single egress fence, that is fired when a resource is released and sent to another
+// system.
+//
+// Note that there can be repeated ingress and egress of a resource, but the assumption is that
+// there is exactly one egress for every ingress, unless the resource is destroyed rather than
+// released.
+//
+// The DependencyMonitor will log if there is an anomaly in the fences tracked for some resource.
+// This includes:
+// * If (2) happens before (1)
+// * If (2) happens after (3)
+//
+// Note that this class has no knowledge of the "other system". I.e., if the other system ignores
+// the fence reported in (3), but still takes a long time to write to the resource and produce (1),
+// then nothing will be logged. That other system must have its own DependencyMonitor. Conversely,
+// this class has imperfect knowledge of the system it is monitoring. For example, this class does
+// not know the precise start times of reading from a resource, the exact time that a read might
+// occur from a hardware unit is not known to userspace.
+//
+// In other words, this class logs specific classes of fence violations, but is not sensitive to
+// *all* violations. One property of this is that unless the system tracked by a DependencyMonitor
+// is feeding in literally incorrect fences, then there is no chance of a false positive.
+//
+// This class is thread safe.
+class DependencyMonitor {
+public:
+ // Sets a debug token identifying the resource this monitor is tracking.
+ void setToken(std::string token) { mToken = std::move(token); }
+
+ // Adds a fence that is fired when the resource ready to be ingested by the system using the
+ // DependencyMonitor.
+ void addIngress(FenceTimePtr fence, std::string annotation);
+ // Adds a fence that is fired when the resource is accessed.
+ void addAccessCompletion(FenceTimePtr fence, std::string annotation);
+ // Adds a fence that is fired when the resource is released to another system.
+ void addEgress(FenceTimePtr fence, std::string annotation);
+
+private:
+ struct AnnotatedFenceTime {
+ FenceTimePtr fence;
+ std::string annotation;
+ };
+
+ struct DependencyBlock {
+ int64_t id = -1;
+ AnnotatedFenceTime ingress = {FenceTime::NO_FENCE, ""};
+ FatVector<AnnotatedFenceTime> accessCompletions;
+ AnnotatedFenceTime egress = {FenceTime::NO_FENCE, ""};
+ bool validated = false;
+ const char* token = nullptr;
+
+ void reset(const char* newToken) {
+ static std::atomic<int64_t> counter = 0;
+ id = counter++;
+ ingress = {FenceTime::NO_FENCE, ""};
+ accessCompletions.clear();
+ egress = {FenceTime::NO_FENCE, ""};
+ validated = false;
+ token = newToken;
+ }
+
+ // Returns true if all fences in this block have valid signal times.
+ bool updateSignalTimes(bool excludeIngress);
+
+ void checkUnsafeAccess() const;
+ };
+
+ void resolveLocked() REQUIRES(mMutex);
+
+ std::string mToken;
+ std::mutex mMutex;
+ ui::RingBuffer<DependencyBlock, 10> mDependencies GUARDED_BY(mMutex);
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/ui/include/ui/DisplayId.h b/libs/ui/include/ui/DisplayId.h
index 937e3f1..1e1c77b 100644
--- a/libs/ui/include/ui/DisplayId.h
+++ b/libs/ui/include/ui/DisplayId.h
@@ -20,6 +20,7 @@
#include <ostream>
#include <string>
+#include <ftl/match.h>
#include <ftl/optional.h>
namespace android {
@@ -36,7 +37,6 @@
DisplayId& operator=(const DisplayId&) = default;
static constexpr DisplayId fromValue(uint64_t value) { return DisplayId(value); }
- constexpr bool isVirtual() const { return value & FLAG_VIRTUAL; }
uint64_t value;
@@ -66,13 +66,6 @@
// TODO: b/162612135 - Remove default constructor.
PhysicalDisplayId() = default;
- static constexpr ftl::Optional<PhysicalDisplayId> tryCast(DisplayId id) {
- if (id.isVirtual()) {
- return std::nullopt;
- }
- return PhysicalDisplayId(id);
- }
-
// Returns a stable ID based on EDID and port information.
static constexpr PhysicalDisplayId fromEdid(uint8_t port, uint16_t manufacturerId,
uint32_t modelHash) {
@@ -90,8 +83,6 @@
return PhysicalDisplayId(value);
}
- constexpr uint8_t getPort() const { return static_cast<uint8_t>(value); }
-
private:
// Flag indicating that the ID is stable across reboots.
static constexpr uint64_t FLAG_STABLE = 1ULL << 62;
@@ -112,13 +103,6 @@
// Flag indicating that this virtual display is backed by the GPU.
static constexpr uint64_t FLAG_GPU = 1ULL << 61;
- static constexpr std::optional<VirtualDisplayId> tryCast(DisplayId id) {
- if (id.isVirtual()) {
- return VirtualDisplayId(id);
- }
- return std::nullopt;
- }
-
static constexpr VirtualDisplayId fromValue(uint64_t value) {
return VirtualDisplayId(SkipVirtualFlag{}, value);
}
@@ -134,13 +118,6 @@
struct HalVirtualDisplayId : VirtualDisplayId {
explicit constexpr HalVirtualDisplayId(BaseId baseId) : VirtualDisplayId(baseId) {}
- static constexpr std::optional<HalVirtualDisplayId> tryCast(DisplayId id) {
- if (id.isVirtual() && !(id.value & FLAG_GPU)) {
- return HalVirtualDisplayId(id);
- }
- return std::nullopt;
- }
-
static constexpr HalVirtualDisplayId fromValue(uint64_t value) {
return HalVirtualDisplayId(SkipVirtualFlag{}, value);
}
@@ -152,13 +129,6 @@
struct GpuVirtualDisplayId : VirtualDisplayId {
explicit constexpr GpuVirtualDisplayId(BaseId baseId) : VirtualDisplayId(FLAG_GPU | baseId) {}
- static constexpr std::optional<GpuVirtualDisplayId> tryCast(DisplayId id) {
- if (id.isVirtual() && (id.value & FLAG_GPU)) {
- return GpuVirtualDisplayId(id);
- }
- return std::nullopt;
- }
-
static constexpr GpuVirtualDisplayId fromValue(uint64_t value) {
return GpuVirtualDisplayId(SkipVirtualFlag{}, value);
}
@@ -172,14 +142,6 @@
struct HalDisplayId : DisplayId {
constexpr HalDisplayId(HalVirtualDisplayId other) : DisplayId(other) {}
constexpr HalDisplayId(PhysicalDisplayId other) : DisplayId(other) {}
-
- static constexpr std::optional<HalDisplayId> tryCast(DisplayId id) {
- if (GpuVirtualDisplayId::tryCast(id)) {
- return std::nullopt;
- }
- return HalDisplayId(id);
- }
-
static constexpr HalDisplayId fromValue(uint64_t value) { return HalDisplayId(value); }
private:
@@ -187,6 +149,47 @@
explicit constexpr HalDisplayId(DisplayId other) : DisplayId(other) {}
};
+using DisplayIdVariant = std::variant<PhysicalDisplayId, GpuVirtualDisplayId, HalVirtualDisplayId>;
+using VirtualDisplayIdVariant = std::variant<GpuVirtualDisplayId, HalVirtualDisplayId>;
+
+template <typename DisplayIdType>
+inline auto asDisplayIdOfType(DisplayIdVariant variant) -> ftl::Optional<DisplayIdType> {
+ return ftl::match(
+ variant,
+ [](DisplayIdType id) -> ftl::Optional<DisplayIdType> { return ftl::Optional(id); },
+ [](auto) -> ftl::Optional<DisplayIdType> { return std::nullopt; });
+}
+
+template <typename Variant>
+inline auto asHalDisplayId(Variant variant) -> ftl::Optional<HalDisplayId> {
+ return ftl::match(
+ variant,
+ [](GpuVirtualDisplayId) -> ftl::Optional<HalDisplayId> { return std::nullopt; },
+ [](auto id) -> ftl::Optional<HalDisplayId> {
+ return ftl::Optional(static_cast<HalDisplayId>(id));
+ });
+}
+
+inline auto asPhysicalDisplayId(DisplayIdVariant variant) -> ftl::Optional<PhysicalDisplayId> {
+ return asDisplayIdOfType<PhysicalDisplayId>(variant);
+}
+
+inline auto asVirtualDisplayId(DisplayIdVariant variant) -> ftl::Optional<VirtualDisplayId> {
+ return ftl::match(
+ variant,
+ [](GpuVirtualDisplayId id) -> ftl::Optional<VirtualDisplayId> {
+ return ftl::Optional(static_cast<VirtualDisplayId>(id));
+ },
+ [](HalVirtualDisplayId id) -> ftl::Optional<VirtualDisplayId> {
+ return ftl::Optional(static_cast<VirtualDisplayId>(id));
+ },
+ [](auto) -> ftl::Optional<VirtualDisplayId> { return std::nullopt; });
+}
+
+inline auto asDisplayId(DisplayIdVariant variant) -> DisplayId {
+ return ftl::match(variant, [](auto id) -> DisplayId { return static_cast<DisplayId>(id); });
+}
+
static_assert(sizeof(DisplayId) == sizeof(uint64_t));
static_assert(sizeof(HalDisplayId) == sizeof(uint64_t));
static_assert(sizeof(VirtualDisplayId) == sizeof(uint64_t));
diff --git a/libs/ui/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h
index 334106f..3560d57 100644
--- a/libs/ui/include/ui/FenceTime.h
+++ b/libs/ui/include/ui/FenceTime.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_FENCE_TIME_H
#define ANDROID_FENCE_TIME_H
+#include <stddef.h>
#include <ui/Fence.h>
#include <utils/Flattenable.h>
#include <utils/Mutex.h>
@@ -30,6 +31,8 @@
namespace android {
class FenceToFenceTimeMap;
+class FenceTime;
+using FenceTimePtr = std::shared_ptr<FenceTime>;
// A wrapper around fence that only implements isValid and getSignalTime.
// It automatically closes the fence in a thread-safe manner once the signal
@@ -95,6 +98,10 @@
FenceTime& operator=(const FenceTime&) = delete;
FenceTime& operator=(FenceTime&&) = delete;
+ // Constructs a FenceTime, falling back to a timestamp if the fence is
+ // invalid.
+ static FenceTimePtr makeValid(const sp<Fence>& fence);
+
// This method should only be called when replacing the fence with
// a signalTime. Since this is an indirect way of setting the signal time
// of a fence, the snapshot should come from a trusted source.
@@ -142,8 +149,6 @@
std::atomic<nsecs_t> mSignalTime{Fence::SIGNAL_TIME_INVALID};
};
-using FenceTimePtr = std::shared_ptr<FenceTime>;
-
// A queue of FenceTimes that are expected to signal in FIFO order.
// Only maintains a queue of weak pointers so it doesn't keep references
// to Fences on its own.
@@ -162,8 +167,6 @@
// different threads.
class FenceTimeline {
public:
- static constexpr size_t MAX_ENTRIES = 64;
-
void push(const std::shared_ptr<FenceTime>& fence);
void updateSignalTimes();
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 936bf8f..9305180 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -23,6 +23,7 @@
#include <string>
#include <utility>
#include <vector>
+#include "ui/DependencyMonitor.h"
#include <android/hardware_buffer.h>
#include <ui/ANativeObjectBase.h>
@@ -229,6 +230,8 @@
void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context);
+ DependencyMonitor& getDependencyMonitor() { return mDependencyMonitor; }
+
private:
~GraphicBuffer();
@@ -295,6 +298,8 @@
// and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer.
std::vector<std::pair<GraphicBufferDeathCallback, void* /*mDeathCallbackContext*/>>
mDeathCallbacks;
+
+ DependencyMonitor mDependencyMonitor;
};
} // namespace android
diff --git a/libs/ui/include/ui/StaticDisplayInfo.h b/libs/ui/include/ui/StaticDisplayInfo.h
index 83da821..5316448 100644
--- a/libs/ui/include/ui/StaticDisplayInfo.h
+++ b/libs/ui/include/ui/StaticDisplayInfo.h
@@ -28,6 +28,7 @@
// Immutable information about physical display.
struct StaticDisplayInfo {
DisplayConnectionType connectionType = DisplayConnectionType::Internal;
+ uint8_t port;
float density = 0.f;
bool secure = false;
std::optional<DeviceProductInfo> deviceProductInfo;
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 2b11786..d950f2a 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -45,16 +45,6 @@
}
cc_test {
- name: "DisplayId_test",
- shared_libs: ["libui"],
- srcs: ["DisplayId_test.cpp"],
- cflags: [
- "-Wall",
- "-Werror",
- ],
-}
-
-cc_test {
name: "DisplayIdentification_test",
shared_libs: ["libui"],
static_libs: ["libgmock"],
diff --git a/libs/ui/tests/DisplayId_test.cpp b/libs/ui/tests/DisplayId_test.cpp
deleted file mode 100644
index 209acba..0000000
--- a/libs/ui/tests/DisplayId_test.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ui/DisplayId.h>
-
-#include <gtest/gtest.h>
-
-namespace android::ui {
-
-TEST(DisplayIdTest, createPhysicalIdFromEdid) {
- constexpr uint8_t port = 1;
- constexpr uint16_t manufacturerId = 13;
- constexpr uint32_t modelHash = 42;
- const PhysicalDisplayId id = PhysicalDisplayId::fromEdid(port, manufacturerId, modelHash);
- EXPECT_EQ(port, id.getPort());
- EXPECT_FALSE(VirtualDisplayId::tryCast(id));
- EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id));
- EXPECT_TRUE(PhysicalDisplayId::tryCast(id));
- EXPECT_TRUE(HalDisplayId::tryCast(id));
-
- EXPECT_EQ(id, DisplayId::fromValue(id.value));
- EXPECT_EQ(id, PhysicalDisplayId::fromValue(id.value));
-}
-
-TEST(DisplayIdTest, createPhysicalIdFromPort) {
- constexpr uint8_t port = 3;
- const PhysicalDisplayId id = PhysicalDisplayId::fromPort(port);
- EXPECT_EQ(port, id.getPort());
- EXPECT_FALSE(VirtualDisplayId::tryCast(id));
- EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id));
- EXPECT_TRUE(PhysicalDisplayId::tryCast(id));
- EXPECT_TRUE(HalDisplayId::tryCast(id));
-
- EXPECT_EQ(id, DisplayId::fromValue(id.value));
- EXPECT_EQ(id, PhysicalDisplayId::fromValue(id.value));
-}
-
-TEST(DisplayIdTest, createGpuVirtualId) {
- const GpuVirtualDisplayId id(42);
- EXPECT_TRUE(VirtualDisplayId::tryCast(id));
- EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(PhysicalDisplayId::tryCast(id));
- EXPECT_FALSE(HalDisplayId::tryCast(id));
-
- EXPECT_EQ(id, DisplayId::fromValue(id.value));
- EXPECT_EQ(id, GpuVirtualDisplayId::fromValue(id.value));
-}
-
-TEST(DisplayIdTest, createVirtualIdFromGpuVirtualId) {
- const VirtualDisplayId id(GpuVirtualDisplayId(42));
- EXPECT_TRUE(VirtualDisplayId::tryCast(id));
- EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(PhysicalDisplayId::tryCast(id));
- EXPECT_FALSE(HalDisplayId::tryCast(id));
-
- const bool isGpuVirtualId = (id.value & VirtualDisplayId::FLAG_GPU);
- EXPECT_EQ((id.isVirtual() && isGpuVirtualId), GpuVirtualDisplayId::tryCast(id).has_value());
-}
-
-TEST(DisplayIdTest, createHalVirtualId) {
- const HalVirtualDisplayId id(42);
- EXPECT_TRUE(VirtualDisplayId::tryCast(id));
- EXPECT_TRUE(HalVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(PhysicalDisplayId::tryCast(id));
- EXPECT_TRUE(HalDisplayId::tryCast(id));
-
- EXPECT_EQ(id, DisplayId::fromValue(id.value));
- EXPECT_EQ(id, HalVirtualDisplayId::fromValue(id.value));
-}
-
-TEST(DisplayIdTest, createVirtualIdFromHalVirtualId) {
- const VirtualDisplayId id(HalVirtualDisplayId(42));
- EXPECT_TRUE(VirtualDisplayId::tryCast(id));
- EXPECT_TRUE(HalVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(PhysicalDisplayId::tryCast(id));
- EXPECT_TRUE(HalDisplayId::tryCast(id));
-
- const bool isGpuVirtualId = (id.value & VirtualDisplayId::FLAG_GPU);
- EXPECT_EQ((id.isVirtual() && !isGpuVirtualId), HalVirtualDisplayId::tryCast(id).has_value());
-}
-
-} // namespace android::ui
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 888fcfb..95e1c06 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -934,6 +934,7 @@
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
+ mWindowInfosVsyncId(-1),
mMinTimeBetweenUserActivityPokes(DEFAULT_USER_ACTIVITY_POKE_INTERVAL),
mConnectionManager(mLooper),
mTouchStates(mWindowInfos, mConnectionManager),
@@ -7049,11 +7050,6 @@
setInputWindowsLocked(handles, displayId);
}
- if (update.vsyncId < mWindowInfosVsyncId) {
- ALOGE("Received out of order window infos update. Last update vsync id: %" PRId64
- ", current update vsync id: %" PRId64,
- mWindowInfosVsyncId, update.vsyncId);
- }
mWindowInfosVsyncId = update.vsyncId;
}
// Wake up poll loop since it may need to make new input dispatching choices.
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
index 252adaa..2c0a66f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
@@ -34,7 +34,7 @@
* A parameter object for creating Display instances
*/
struct DisplayCreationArgs {
- DisplayId id;
+ DisplayIdVariant idVariant;
// Size of the display in pixels
ui::Size pixels = ui::kInvalidSize;
@@ -68,8 +68,8 @@
public:
DisplayCreationArgs build() { return std::move(mArgs); }
- DisplayCreationArgsBuilder& setId(DisplayId id) {
- mArgs.id = id;
+ DisplayCreationArgsBuilder& setId(DisplayIdVariant idVariant) {
+ mArgs.idVariant = idVariant;
return *this;
}
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index 780758e..e2ea0f1 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -167,6 +167,8 @@
// Checks if the buffer's release fence has been set
virtual LayerFE::ReleaseFencePromiseStatus getReleaseFencePromiseStatus() = 0;
+ virtual void setReleasedBuffer(sp<GraphicBuffer> buffer) = 0;
+
// Indicates that the picture profile request was applied to this layer.
virtual void onPictureProfileCommitted() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index bda7856..4266da4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -170,6 +170,7 @@
// Returns the DisplayId the output represents, if it has one
virtual ftl::Optional<DisplayId> getDisplayId() const = 0;
+ virtual ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const = 0;
// Enables (or disables) composition on this output
virtual void setCompositionEnabled(bool) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 5519aaf..ec87acc 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -46,6 +46,7 @@
// compositionengine::Output overrides
ftl::Optional<DisplayId> getDisplayId() const override;
+ ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const override;
bool isValid() const override;
void dump(std::string&) const override;
using compositionengine::impl::Output::setReleasedLayers;
@@ -104,8 +105,11 @@
override;
bool hasPictureProcessing() const override;
int32_t getMaxLayerPictureProfiles() const override;
+ bool isGpuVirtualDisplay() const {
+ return std::holds_alternative<GpuVirtualDisplayId>(mIdVariant);
+ }
- DisplayId mId;
+ DisplayIdVariant mIdVariant;
bool mIsDisconnected = false;
adpf::PowerAdvisor* mPowerAdvisor = nullptr;
bool mHasPictureProcessing = false;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 0ccdd22..873764b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -45,6 +45,7 @@
// compositionengine::Output overrides
bool isValid() const override;
ftl::Optional<DisplayId> getDisplayId() const override;
+ ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const override;
void setCompositionEnabled(bool) override;
void setLayerCachingEnabled(bool) override;
void setLayerCachingTexturePoolEnabled(bool) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
index d2a5a20..f65a908 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -52,6 +52,7 @@
MOCK_METHOD0(createReleaseFenceFuture, ftl::Future<FenceResult>());
MOCK_METHOD1(setReleaseFence, void(const FenceResult&));
+ MOCK_METHOD1(setReleasedBuffer, void(sp<GraphicBuffer>));
MOCK_METHOD0(getReleaseFencePromiseStatus, LayerFE::ReleaseFencePromiseStatus());
MOCK_CONST_METHOD0(getDebugName, const char*());
MOCK_CONST_METHOD0(getSequence, int32_t());
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index f2c265a..eaa3dd3 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -35,6 +35,7 @@
MOCK_CONST_METHOD0(isValid, bool());
MOCK_CONST_METHOD0(getDisplayId, ftl::Optional<DisplayId>());
+ MOCK_CONST_METHOD0(getDisplayIdVariant, ftl::Optional<DisplayIdVariant>());
MOCK_METHOD1(setCompositionEnabled, void(bool));
MOCK_METHOD1(setLayerCachingEnabled, void(bool));
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index 34ede33..ab2a03c 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -97,7 +97,7 @@
ui::PhysicalDisplayVector<compositionengine::Output*> outputsToOffload;
for (const auto& output : outputs) {
- if (!ftl::Optional(output->getDisplayId()).and_then(HalDisplayId::tryCast)) {
+ if (!output->getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
// Not HWC-enabled, so it is always client-composited. No need to offload.
continue;
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 8364f4e..5a54677 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -52,7 +52,7 @@
Display::~Display() = default;
void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) {
- mId = args.id;
+ mIdVariant = args.idVariant;
mPowerAdvisor = args.powerAdvisor;
mHasPictureProcessing = args.hasPictureProcessing;
mMaxLayerPictureProfiles = args.maxLayerPictureProfiles;
@@ -67,7 +67,7 @@
}
DisplayId Display::getId() const {
- return mId;
+ return asDisplayId(mIdVariant);
}
bool Display::isSecure() const {
@@ -79,11 +79,15 @@
}
bool Display::isVirtual() const {
- return mId.isVirtual();
+ return !std::holds_alternative<PhysicalDisplayId>(mIdVariant);
}
ftl::Optional<DisplayId> Display::getDisplayId() const {
- return mId;
+ return getId();
+}
+
+ftl::Optional<DisplayIdVariant> Display::getDisplayIdVariant() const {
+ return mIdVariant;
}
void Display::disconnect() {
@@ -93,14 +97,14 @@
mIsDisconnected = true;
- if (const auto id = HalDisplayId::tryCast(mId)) {
+ if (const auto id = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
getCompositionEngine().getHwComposer().disconnectDisplay(*id);
}
}
void Display::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
Output::setColorTransform(args);
- const auto halDisplayId = HalDisplayId::tryCast(mId);
+ const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
if (mIsDisconnected || !halDisplayId || CC_LIKELY(!args.colorTransformMatrix)) {
return;
}
@@ -108,7 +112,7 @@
auto& hwc = getCompositionEngine().getHwComposer();
status_t result = hwc.setColorTransform(*halDisplayId, *args.colorTransformMatrix);
ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display \"%s\": %d",
- to_string(mId).c_str(), result);
+ to_string(*halDisplayId).c_str(), result);
}
void Display::setColorProfile(const ColorProfile& colorProfile) {
@@ -125,7 +129,7 @@
Output::setColorProfile(colorProfile);
- const auto physicalId = PhysicalDisplayId::tryCast(mId);
+ const auto physicalId = getDisplayIdVariant().and_then(asPhysicalDisplayId);
LOG_FATAL_IF(!physicalId);
getCompositionEngine().getHwComposer().setActiveColorMode(*physicalId, colorProfile.mode,
colorProfile.renderIntent);
@@ -133,7 +137,7 @@
void Display::dump(std::string& out) const {
const char* const type = isVirtual() ? "virtual" : "physical";
- base::StringAppendF(&out, "Display %s (%s, \"%s\")", to_string(mId).c_str(), type,
+ base::StringAppendF(&out, "Display %s (%s, \"%s\")", to_string(getId()).c_str(), type,
getName().c_str());
out.append("\n Composition Display State:\n");
@@ -157,7 +161,7 @@
const sp<compositionengine::LayerFE>& layerFE) const {
auto outputLayer = impl::createOutputLayer(*this, layerFE);
- if (const auto halDisplayId = HalDisplayId::tryCast(mId);
+ if (const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
outputLayer && !mIsDisconnected && halDisplayId) {
auto& hwc = getCompositionEngine().getHwComposer();
auto hwcLayer = hwc.createLayer(*halDisplayId);
@@ -171,8 +175,7 @@
void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& refreshArgs) {
Output::setReleasedLayers(refreshArgs);
- if (mIsDisconnected || GpuVirtualDisplayId::tryCast(mId) ||
- refreshArgs.layersWithQueuedFrames.empty()) {
+ if (mIsDisconnected || isGpuVirtualDisplay() || refreshArgs.layersWithQueuedFrames.empty()) {
return;
}
@@ -208,7 +211,7 @@
if (!getState().displayBrightness) {
return;
}
- if (auto displayId = PhysicalDisplayId::tryCast(mId)) {
+ if (auto displayId = getDisplayIdVariant().and_then(asPhysicalDisplayId)) {
auto& hwc = getCompositionEngine().getHwComposer();
status_t result = hwc.setDisplayBrightness(*displayId, *getState().displayBrightness,
getState().displayBrightnessNits,
@@ -226,7 +229,7 @@
Output::beginFrame();
// If we don't have a HWC display, then we are done.
- const auto halDisplayId = HalDisplayId::tryCast(mId);
+ const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
if (!halDisplayId) {
return;
}
@@ -244,7 +247,7 @@
}
// If we don't have a HWC display, then we are done.
- const auto halDisplayId = HalDisplayId::tryCast(mId);
+ const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
if (!halDisplayId) {
return false;
}
@@ -266,9 +269,9 @@
}
if (isPowerHintSessionEnabled()) {
- mPowerAdvisor->setHwcValidateTiming(mId, hwcValidateStartTime, TimePoint::now());
- if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
- mPowerAdvisor->setSkippedValidate(mId, hwc.getValidateSkipped(*halDisplayId));
+ mPowerAdvisor->setHwcValidateTiming(getId(), hwcValidateStartTime, TimePoint::now());
+ if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
+ mPowerAdvisor->setSkippedValidate(*halDisplayId, hwc.getValidateSkipped(*halDisplayId));
}
}
@@ -292,7 +295,7 @@
bool Display::getSkipColorTransform() const {
auto& hwc = getCompositionEngine().getHwComposer();
- if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
+ if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
return hwc.hasDisplayCapability(*halDisplayId,
DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
}
@@ -383,7 +386,7 @@
}
void Display::executeCommands() {
- const auto halDisplayIdOpt = HalDisplayId::tryCast(mId);
+ const auto halDisplayIdOpt = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
if (mIsDisconnected || !halDisplayIdOpt) {
return;
}
@@ -394,7 +397,7 @@
compositionengine::Output::FrameFences Display::presentFrame() {
auto fences = impl::Output::presentFrame();
- const auto halDisplayIdOpt = HalDisplayId::tryCast(mId);
+ const auto halDisplayIdOpt = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
if (mIsDisconnected || !halDisplayIdOpt) {
return fences;
}
@@ -404,13 +407,13 @@
const TimePoint startTime = TimePoint::now();
if (isPowerHintSessionEnabled() && getState().earliestPresentTime) {
- mPowerAdvisor->setHwcPresentDelayedTime(mId, *getState().earliestPresentTime);
+ mPowerAdvisor->setHwcPresentDelayedTime(*halDisplayIdOpt, *getState().earliestPresentTime);
}
hwc.presentAndGetReleaseFences(*halDisplayIdOpt, getState().earliestPresentTime);
if (isPowerHintSessionEnabled()) {
- mPowerAdvisor->setHwcPresentTiming(mId, startTime, TimePoint::now());
+ mPowerAdvisor->setHwcPresentTiming(*halDisplayIdOpt, startTime, TimePoint::now());
}
fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt);
@@ -433,8 +436,8 @@
void Display::setExpensiveRenderingExpected(bool enabled) {
Output::setExpensiveRenderingExpected(enabled);
- if (mPowerAdvisor && !GpuVirtualDisplayId::tryCast(mId)) {
- mPowerAdvisor->setExpensiveRenderingExpected(mId, enabled);
+ if (mPowerAdvisor && !isGpuVirtualDisplay()) {
+ mPowerAdvisor->setExpensiveRenderingExpected(getId(), enabled);
}
}
@@ -449,15 +452,15 @@
// For ADPF GPU v0 this is expected to set start time to when the GPU commands are submitted with
// fence returned, i.e. when RenderEngine flushes the commands and returns the draw fence.
void Display::setHintSessionGpuStart(TimePoint startTime) {
- mPowerAdvisor->setGpuStartTime(mId, startTime);
+ mPowerAdvisor->setGpuStartTime(getId(), startTime);
}
void Display::setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) {
- mPowerAdvisor->setGpuFenceTime(mId, std::move(gpuFence));
+ mPowerAdvisor->setGpuFenceTime(getId(), std::move(gpuFence));
}
void Display::setHintSessionRequiresRenderEngine(bool requiresRenderEngine) {
- mPowerAdvisor->setRequiresRenderEngine(mId, requiresRenderEngine);
+ mPowerAdvisor->setRequiresRenderEngine(getId(), requiresRenderEngine);
}
const aidl::android::hardware::graphics::composer3::OverlayProperties*
@@ -478,7 +481,7 @@
// 1) It is being handled by hardware composer, which may need this to
// keep its virtual display state machine in sync, or
// 2) There is work to be done (the dirty region isn't empty)
- if (GpuVirtualDisplayId::tryCast(mId) && !mustRecompose()) {
+ if (isGpuVirtualDisplay() && !mustRecompose()) {
ALOGV("Skipping display composition");
return;
}
@@ -487,7 +490,7 @@
}
bool Display::supportsOffloadPresent() const {
- if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
+ if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
auto& hwc = getCompositionEngine().getHwComposer();
return hwc.hasDisplayCapability(*halDisplayId, DisplayCapability::MULTI_THREADED_PRESENT);
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index b30cf20..00a61a5 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -118,6 +118,10 @@
return {};
}
+ftl::Optional<DisplayIdVariant> Output::getDisplayIdVariant() const {
+ return {};
+}
+
const std::string& Output::getName() const {
return mName;
}
@@ -436,8 +440,8 @@
ftl::Future<std::monostate> Output::present(
const compositionengine::CompositionRefreshArgs& refreshArgs) {
const auto stringifyExpectedPresentTime = [this, &refreshArgs]() -> std::string {
- return getDisplayId()
- .and_then(PhysicalDisplayId::tryCast)
+ return getDisplayIdVariant()
+ .and_then(asPhysicalDisplayId)
.and_then([&refreshArgs](PhysicalDisplayId id) {
return refreshArgs.frameTargets.get(id);
})
@@ -890,8 +894,8 @@
return;
}
- if (auto frameTargetPtrOpt = getDisplayId()
- .and_then(PhysicalDisplayId::tryCast)
+ if (auto frameTargetPtrOpt = getDisplayIdVariant()
+ .and_then(asPhysicalDisplayId)
.and_then([&refreshArgs](PhysicalDisplayId id) {
return refreshArgs.frameTargets.get(id);
})) {
@@ -1672,6 +1676,7 @@
Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
}
layer->getLayerFE().setReleaseFence(releaseFence);
+ layer->getLayerFE().setReleasedBuffer(layer->getLayerFE().getCompositionState()->buffer);
}
// We've got a list of layers needing fences, that are disjoint with
@@ -1841,7 +1846,7 @@
if (!getDisplayId()) {
return;
}
- if (auto displayId = PhysicalDisplayId::tryCast(*getDisplayId())) {
+ if (auto displayId = getDisplayIdVariant().and_then(asPhysicalDisplayId)) {
auto& hwc = getCompositionEngine().getHwComposer();
const status_t error =
hwc.setDisplayPictureProfileHandle(*displayId, getState().pictureProfileHandle);
diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
index b278000..34c09db 100644
--- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
@@ -62,10 +62,15 @@
void SetUp() override {
EXPECT_CALL(*mOutput1, getDisplayId)
.WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId1)));
+ EXPECT_CALL(*mOutput1, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId1));
+
EXPECT_CALL(*mOutput2, getDisplayId)
.WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId2)));
+ EXPECT_CALL(*mOutput2, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId2));
+
EXPECT_CALL(*mOutput3, getDisplayId)
.WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId3)));
+ EXPECT_CALL(*mOutput3, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId3));
// Most tests will depend on the outputs being enabled.
for (auto& state : mOutputStates) {
@@ -314,12 +319,23 @@
void SetUp() override {
EXPECT_CALL(*mDisplay1, getDisplayId)
.WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId1)));
+ EXPECT_CALL(*mDisplay1, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId1));
+
EXPECT_CALL(*mDisplay2, getDisplayId)
.WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId2)));
+ EXPECT_CALL(*mDisplay2, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId2));
+
EXPECT_CALL(*mVirtualDisplay, getDisplayId)
.WillRepeatedly(Return(std::make_optional<DisplayId>(kGpuVirtualDisplayId)));
+ const DisplayIdVariant gpuVariant =
+ GpuVirtualDisplayId::fromValue(kGpuVirtualDisplayId.value);
+ EXPECT_CALL(*mVirtualDisplay, getDisplayIdVariant).WillRepeatedly(Return(gpuVariant));
+
EXPECT_CALL(*mHalVirtualDisplay, getDisplayId)
.WillRepeatedly(Return(std::make_optional<DisplayId>(kHalVirtualDisplayId)));
+ const DisplayIdVariant halVariant =
+ HalVirtualDisplayId::fromValue(kHalVirtualDisplayId.value);
+ EXPECT_CALL(*mHalVirtualDisplay, getDisplayIdVariant).WillRepeatedly(Return(halVariant));
// Most tests will depend on the outputs being enabled.
for (auto& state : mOutputStates) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index c1e59d0..77fd446 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -278,7 +278,7 @@
impl::createDisplay(mCompositionEngine, getDisplayCreationArgsForGpuVirtualDisplay());
EXPECT_FALSE(display->isSecure());
EXPECT_TRUE(display->isVirtual());
- EXPECT_TRUE(GpuVirtualDisplayId::tryCast(display->getId()));
+ EXPECT_TRUE(display->getDisplayIdVariant().and_then(asDisplayIdOfType<GpuVirtualDisplayId>));
}
/*
@@ -318,6 +318,7 @@
EXPECT_EQ(HAL_VIRTUAL_DISPLAY_ID, mDisplay->getId());
EXPECT_FALSE(mDisplay->isSecure());
EXPECT_TRUE(mDisplay->isVirtual());
+ EXPECT_TRUE(mDisplay->getDisplayIdVariant().and_then(asDisplayIdOfType<HalVirtualDisplayId>));
EXPECT_FALSE(mDisplay->isValid());
const auto& filter = mDisplay->getState().layerFilter;
@@ -337,6 +338,7 @@
EXPECT_EQ(GPU_VIRTUAL_DISPLAY_ID, mDisplay->getId());
EXPECT_FALSE(mDisplay->isSecure());
EXPECT_TRUE(mDisplay->isVirtual());
+ EXPECT_TRUE(mDisplay->getDisplayIdVariant().and_then(asDisplayIdOfType<GpuVirtualDisplayId>));
EXPECT_FALSE(mDisplay->isValid());
const auto& filter = mDisplay->getState().layerFilter;
@@ -572,7 +574,7 @@
auto args = getDisplayCreationArgsForGpuVirtualDisplay();
std::shared_ptr<Display> gpuDisplay =
createPartialMockDisplay<Display>(mCompositionEngine, args);
- EXPECT_TRUE(GpuVirtualDisplayId::tryCast(gpuDisplay->getId()));
+ EXPECT_TRUE(gpuDisplay->getDisplayIdVariant().and_then(asDisplayIdOfType<GpuVirtualDisplayId>));
chooseCompositionStrategy(gpuDisplay.get());
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 09ad9fa..590626a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -148,20 +148,23 @@
virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
virtual ftl::Optional<DisplayId> getDisplayId() const override { return mId; }
+ virtual ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const override {
+ return DisplayIdVariant(mId);
+ }
virtual bool hasPictureProcessing() const override { return mHasPictureProcessing; }
virtual int32_t getMaxLayerPictureProfiles() const override {
return mMaxLayerPictureProfiles;
}
- void setDisplayIdForTest(DisplayId value) { mId = value; }
+ void setDisplayIdForTest(PhysicalDisplayId value) { mId = value; }
void setHasPictureProcessingForTest(bool value) { mHasPictureProcessing = value; }
void setMaxLayerPictureProfilesForTest(int32_t value) { mMaxLayerPictureProfiles = value; }
private:
- ftl::Optional<DisplayId> mId;
+ PhysicalDisplayId mId;
bool mHasPictureProcessing;
int32_t mMaxLayerPictureProfiles;
};
@@ -3311,6 +3314,17 @@
sp<Fence> layer2Fence = sp<Fence>::make();
sp<Fence> layer3Fence = sp<Fence>::make();
+ // Set up layerfe buffers
+ LayerFECompositionState layer1State;
+ layer1State.buffer = sp<GraphicBuffer>::make();
+ LayerFECompositionState layer2State;
+ layer2State.buffer = sp<GraphicBuffer>::make();
+ LayerFECompositionState layer3State;
+ layer3State.buffer = nullptr;
+ EXPECT_CALL(*mLayer1.layerFE, getCompositionState()).WillOnce(Return(&layer1State));
+ EXPECT_CALL(*mLayer2.layerFE, getCompositionState()).WillOnce(Return(&layer2State));
+ EXPECT_CALL(*mLayer3.layerFE, getCompositionState()).WillOnce(Return(&layer3State));
+
Output::FrameFences frameFences;
frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
@@ -3327,14 +3341,23 @@
.WillOnce([&layer1Fence](FenceResult releaseFence) {
EXPECT_EQ(FenceResult(layer1Fence), releaseFence);
});
+ EXPECT_CALL(*mLayer1.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) {
+ EXPECT_EQ(layer1State.buffer, buffer);
+ });
EXPECT_CALL(*mLayer2.layerFE, setReleaseFence(_))
.WillOnce([&layer2Fence](FenceResult releaseFence) {
EXPECT_EQ(FenceResult(layer2Fence), releaseFence);
});
+ EXPECT_CALL(*mLayer2.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) {
+ EXPECT_EQ(layer2State.buffer, buffer);
+ });
EXPECT_CALL(*mLayer3.layerFE, setReleaseFence(_))
.WillOnce([&layer3Fence](FenceResult releaseFence) {
EXPECT_EQ(FenceResult(layer3Fence), releaseFence);
});
+ EXPECT_CALL(*mLayer3.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) {
+ EXPECT_EQ(layer3State.buffer, buffer);
+ });
constexpr bool kFlushEvenWhenDisabled = false;
mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
@@ -3350,6 +3373,17 @@
frameFences.layerFences.emplace(&mLayer2.hwc2Layer, sp<Fence>::make());
frameFences.layerFences.emplace(&mLayer3.hwc2Layer, sp<Fence>::make());
+ // Set up layerfe buffers
+ LayerFECompositionState layer1State;
+ layer1State.buffer = sp<GraphicBuffer>::make();
+ LayerFECompositionState layer2State;
+ layer2State.buffer = sp<GraphicBuffer>::make();
+ LayerFECompositionState layer3State;
+ layer3State.buffer = nullptr;
+ EXPECT_CALL(*mLayer1.layerFE, getCompositionState()).WillOnce(Return(&layer1State));
+ EXPECT_CALL(*mLayer2.layerFE, getCompositionState()).WillOnce(Return(&layer2State));
+ EXPECT_CALL(*mLayer3.layerFE, getCompositionState()).WillOnce(Return(&layer3State));
+
EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
@@ -3359,6 +3393,15 @@
EXPECT_CALL(*mLayer1.layerFE, setReleaseFence).WillOnce(Return());
EXPECT_CALL(*mLayer2.layerFE, setReleaseFence).WillOnce(Return());
EXPECT_CALL(*mLayer3.layerFE, setReleaseFence).WillOnce(Return());
+ EXPECT_CALL(*mLayer1.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) {
+ EXPECT_EQ(layer1State.buffer, buffer);
+ });
+ EXPECT_CALL(*mLayer2.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) {
+ EXPECT_EQ(layer2State.buffer, buffer);
+ });
+ EXPECT_CALL(*mLayer3.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) {
+ EXPECT_EQ(layer3State.buffer, buffer);
+ });
constexpr bool kFlushEvenWhenDisabled = false;
mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
@@ -3401,7 +3444,6 @@
.WillOnce([&presentFence](FenceResult fenceResult) {
EXPECT_EQ(FenceResult(presentFence), fenceResult);
});
-
constexpr bool kFlushEvenWhenDisabled = false;
mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b396544..de7d455 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -26,7 +26,6 @@
#include <common/trace.h>
#include <compositionengine/CompositionEngine.h>
-#include <compositionengine/Display.h>
#include <compositionengine/DisplayColorProfile.h>
#include <compositionengine/DisplayColorProfileCreationArgs.h>
#include <compositionengine/DisplayCreationArgs.h>
@@ -51,17 +50,6 @@
namespace hal = hardware::graphics::composer::hal;
-namespace gui {
-inline std::string_view to_string(ISurfaceComposer::OptimizationPolicy optimizationPolicy) {
- switch (optimizationPolicy) {
- case ISurfaceComposer::OptimizationPolicy::optimizeForPower:
- return "optimizeForPower";
- case ISurfaceComposer::OptimizationPolicy::optimizeForPerformance:
- return "optimizeForPerformance";
- }
-}
-} // namespace gui
-
DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(
const sp<SurfaceFlinger>& flinger, HWComposer& hwComposer, const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay)
@@ -308,6 +296,10 @@
return mCompositionDisplay->getId();
}
+bool DisplayDevice::isVirtual() const {
+ return mCompositionDisplay->isVirtual();
+}
+
bool DisplayDevice::isSecure() const {
return mCompositionDisplay->isSecure();
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 02522a3..1b14145 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -23,6 +23,8 @@
#include <android-base/thread_annotations.h>
#include <android/native_window.h>
#include <binder/IBinder.h>
+#include <compositionengine/Display.h>
+#include <compositionengine/DisplaySurface.h>
#include <gui/LayerState.h>
#include <math/mat4.h>
#include <renderengine/RenderEngine.h>
@@ -61,15 +63,21 @@
struct CompositionInfo;
struct DisplayDeviceCreationArgs;
-namespace compositionengine {
-class Display;
-class DisplaySurface;
-} // namespace compositionengine
-
namespace display {
class DisplaySnapshot;
} // namespace display
+namespace gui {
+inline const char* to_string(ISurfaceComposer::OptimizationPolicy optimizationPolicy) {
+ switch (optimizationPolicy) {
+ case ISurfaceComposer::OptimizationPolicy::optimizeForPower:
+ return "optimizeForPower";
+ case ISurfaceComposer::OptimizationPolicy::optimizeForPerformance:
+ return "optimizeForPerformance";
+ }
+}
+} // namespace gui
+
class DisplayDevice : public RefBase {
public:
constexpr static float sDefaultMinLumiance = 0.0;
@@ -85,7 +93,7 @@
return mCompositionDisplay;
}
- bool isVirtual() const { return getId().isVirtual(); }
+ bool isVirtual() const;
bool isPrimary() const { return mIsPrimary; }
// isSecure indicates whether this display can be trusted to display
@@ -123,17 +131,30 @@
DisplayId getId() const;
+ DisplayIdVariant getDisplayIdVariant() const {
+ const auto idVariant = mCompositionDisplay->getDisplayIdVariant();
+ LOG_FATAL_IF(!idVariant);
+ return *idVariant;
+ }
+
+ std::optional<VirtualDisplayIdVariant> getVirtualDisplayIdVariant() const {
+ return ftl::match(
+ getDisplayIdVariant(),
+ [](PhysicalDisplayId) { return std::optional<VirtualDisplayIdVariant>(); },
+ [](auto id) { return std::optional<VirtualDisplayIdVariant>(id); });
+ }
+
// Shorthand to upcast the ID of a display whose type is known as a precondition.
PhysicalDisplayId getPhysicalId() const {
- const auto id = PhysicalDisplayId::tryCast(getId());
- LOG_FATAL_IF(!id);
- return *id;
+ const auto physicalDisplayId = asPhysicalDisplayId(getDisplayIdVariant());
+ LOG_FATAL_IF(!physicalDisplayId);
+ return *physicalDisplayId;
}
VirtualDisplayId getVirtualId() const {
- const auto id = VirtualDisplayId::tryCast(getId());
- LOG_FATAL_IF(!id);
- return *id;
+ const auto virtualDisplayId = asVirtualDisplayId(getDisplayIdVariant());
+ LOG_FATAL_IF(!virtualDisplayId);
+ return *virtualDisplayId;
}
const wp<IBinder>& getDisplayToken() const { return mDisplayToken; }
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 384f7b2..56ed11f 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -47,7 +47,8 @@
namespace android {
-VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId displayId,
+VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc,
+ VirtualDisplayIdVariant virtualIdVariant,
const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer,
@@ -58,7 +59,7 @@
: ConsumerBase(bqConsumer),
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
mHwc(hwc),
- mDisplayId(displayId),
+ mVirtualIdVariant(virtualIdVariant),
mDisplayName(name),
mSource{},
mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
@@ -119,7 +120,7 @@
}
status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
- if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
+ if (isBackedByGpu()) {
return NO_ERROR;
}
@@ -133,7 +134,7 @@
}
status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
- if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
+ if (isBackedByGpu()) {
return NO_ERROR;
}
@@ -181,7 +182,10 @@
}
status_t VirtualDisplaySurface::advanceFrame(float hdrSdrRatio) {
- if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
+ const auto halVirtualDisplayId = ftl::match(
+ mVirtualIdVariant, [](HalVirtualDisplayId id) { return ftl::Optional(id); },
+ [](auto) { return ftl::Optional<HalVirtualDisplayId>(); });
+ if (!halVirtualDisplayId) {
return NO_ERROR;
}
@@ -212,11 +216,8 @@
VDS_LOGV("%s: fb=%d(%p) out=%d(%p)", __func__, mFbProducerSlot, fbBuffer.get(),
mOutputProducerSlot, outBuffer.get());
- const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId);
- LOG_FATAL_IF(!halDisplayId);
- // At this point we know the output buffer acquire fence,
- // so update HWC state with it.
- mHwc.setOutputBuffer(*halDisplayId, mOutputFence, outBuffer);
+ // At this point we know the output buffer acquire fence, so update HWC state with it.
+ mHwc.setOutputBuffer(*halVirtualDisplayId, mOutputFence, outBuffer);
status_t result = NO_ERROR;
if (fbBuffer != nullptr) {
@@ -227,7 +228,7 @@
hwcBuffer = fbBuffer; // HWC hasn't previously seen this buffer in this slot
}
// TODO: Correctly propagate the dataspace from GL composition
- result = mHwc.setClientTarget(*halDisplayId, mFbProducerSlot, mFbFence, hwcBuffer,
+ result = mHwc.setClientTarget(*halVirtualDisplayId, mFbProducerSlot, mFbFence, hwcBuffer,
ui::Dataspace::UNKNOWN, hdrSdrRatio);
}
@@ -235,8 +236,8 @@
}
void VirtualDisplaySurface::onFrameCommitted() {
- const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId);
- if (!halDisplayId) {
+ const auto halDisplayId = asHalDisplayId(mVirtualIdVariant);
+ if (!halDisplayId.has_value()) {
return;
}
@@ -250,8 +251,7 @@
Mutex::Autolock lock(mMutex);
int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
VDS_LOGV("%s: release scratch sslot=%d", __func__, sslot);
- addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot],
- retireFence);
+ addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], retireFence);
releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot]);
}
@@ -299,7 +299,7 @@
status_t VirtualDisplaySurface::requestBuffer(int pslot,
sp<GraphicBuffer>* outBuf) {
- if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
+ if (isBackedByGpu()) {
return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf);
}
@@ -321,7 +321,7 @@
status_t VirtualDisplaySurface::dequeueBuffer(Source source,
PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
- LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
+ LOG_ALWAYS_FATAL_IF(isBackedByGpu());
status_t result =
mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
@@ -373,7 +373,7 @@
PixelFormat format, uint64_t usage,
uint64_t* outBufferAge,
FrameEventHistoryDelta* outTimestamps) {
- if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
+ if (isBackedByGpu()) {
return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge,
outTimestamps);
}
@@ -459,7 +459,7 @@
status_t VirtualDisplaySurface::queueBuffer(int pslot,
const QueueBufferInput& input, QueueBufferOutput* output) {
- if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
+ if (isBackedByGpu()) {
return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output);
}
@@ -517,7 +517,7 @@
status_t VirtualDisplaySurface::cancelBuffer(int pslot,
const sp<Fence>& fence) {
- if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
+ if (isBackedByGpu()) {
return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence);
}
@@ -621,7 +621,10 @@
}
status_t VirtualDisplaySurface::refreshOutputBuffer() {
- LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
+ const auto halVirtualDisplayId = ftl::match(
+ mVirtualIdVariant, [](HalVirtualDisplayId id) { return ftl::Optional(id); },
+ [](auto) { return ftl::Optional<HalVirtualDisplayId>(); });
+ LOG_ALWAYS_FATAL_IF(!halVirtualDisplayId);
if (mOutputProducerSlot >= 0) {
mSource[SOURCE_SINK]->cancelBuffer(
@@ -640,14 +643,16 @@
// until after GPU calls queueBuffer(). So here we just set the buffer
// (for use in HWC prepare) but not the fence; we'll call this again with
// the proper fence once we have it.
- const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId);
- LOG_FATAL_IF(!halDisplayId);
- result = mHwc.setOutputBuffer(*halDisplayId, Fence::NO_FENCE,
+ result = mHwc.setOutputBuffer(*halVirtualDisplayId, Fence::NO_FENCE,
mProducerBuffers[mOutputProducerSlot]);
return result;
}
+bool VirtualDisplaySurface::isBackedByGpu() const {
+ return std::holds_alternative<GpuVirtualDisplayId>(mVirtualIdVariant);
+}
+
// This slot mapping function is its own inverse, so two copies are unnecessary.
// Both are kept to make the intent clear where the function is called, and for
// the (unlikely) chance that we switch to a different mapping function.
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 90426f7..cb65c79 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -75,7 +75,8 @@
public BnGraphicBufferProducer,
private ConsumerBase {
public:
- VirtualDisplaySurface(HWComposer&, VirtualDisplayId, const sp<IGraphicBufferProducer>& sink,
+ VirtualDisplaySurface(HWComposer&, VirtualDisplayIdVariant,
+ const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name);
@@ -145,6 +146,7 @@
void updateQueueBufferOutput(QueueBufferOutput&&);
void resetPerFrameState();
status_t refreshOutputBuffer();
+ bool isBackedByGpu() const;
// Both the sink and scratch buffer pools have their own set of slots
// ("source slots", or "sslot"). We have to merge these into the single
@@ -159,7 +161,7 @@
// Immutable after construction
//
HWComposer& mHwc;
- const VirtualDisplayId mDisplayId;
+ const VirtualDisplayIdVariant mVirtualIdVariant;
const std::string mDisplayName;
sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_*
uint32_t mDefaultOutputFormat;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 95a7170..2e31282 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -722,6 +722,10 @@
uint32_t currentMaxAcquiredBufferCount =
mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
+ if (FlagManager::getInstance().monitor_buffer_fences()) {
+ buffer->getDependencyMonitor().addEgress(FenceTime::makeValid(fence), "Layer release");
+ }
+
if (listener) {
listener->onReleaseBuffer(callbackId, fence, currentMaxAcquiredBufferCount);
}
@@ -940,6 +944,7 @@
std::max(mDrawingState.frameNumber, mDrawingState.barrierFrameNumber);
mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
+ mDrawingState.previousBuffer = std::move(mDrawingState.buffer);
mDrawingState.buffer = std::move(buffer);
mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged)
? bufferData.acquireFence
@@ -1122,6 +1127,7 @@
handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence;
handle->frameNumber = mDrawingState.frameNumber;
handle->previousFrameNumber = mDrawingState.previousFrameNumber;
+ handle->previousBuffer = mDrawingState.previousBuffer;
if (mPreviousReleaseBufferEndpoint == handle->listener) {
// Add fence from previous screenshot now so that it can be dispatched to the
// client.
@@ -1433,8 +1439,8 @@
presentFence,
FrameTracer::FrameEvent::PRESENT_FENCE);
mDeprecatedFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
- } else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
- displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
+ } else if (const auto displayId = asPhysicalDisplayId(display->getDisplayIdVariant());
+ displayId.has_value() && mFlinger->getHwComposer().isConnected(*displayId)) {
// The HWC doesn't support present fences, so use the present timestamp instead.
const nsecs_t presentTimestamp =
mFlinger->getHwComposer().getPresentTimestamp(*displayId);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 081bb22..88754f9 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -117,6 +117,7 @@
uint32_t bufferTransform;
bool transformToDisplayInverse;
Region transparentRegionHint;
+ std::shared_ptr<renderengine::ExternalTexture> previousBuffer;
std::shared_ptr<renderengine::ExternalTexture> buffer;
sp<Fence> acquireFence;
std::shared_ptr<FenceTime> acquireFenceTime;
diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp
index b619268..5e076bd 100644
--- a/services/surfaceflinger/LayerFE.cpp
+++ b/services/surfaceflinger/LayerFE.cpp
@@ -410,6 +410,15 @@
if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::FULFILLED) {
return;
}
+
+ if (releaseFence.has_value()) {
+ if (FlagManager::getInstance().monitor_buffer_fences()) {
+ if (auto strongBuffer = mReleasedBuffer.promote()) {
+ strongBuffer->getDependencyMonitor()
+ .addAccessCompletion(FenceTime::makeValid(releaseFence.value()), "HWC");
+ }
+ }
+ }
mReleaseFence.set_value(releaseFence);
mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::FULFILLED;
}
@@ -428,6 +437,10 @@
return mReleaseFencePromiseStatus;
}
+void LayerFE::setReleasedBuffer(sp<GraphicBuffer> buffer) {
+ mReleasedBuffer = std::move(buffer);
+}
+
void LayerFE::setLastHwcState(const LayerFE::HwcLayerDebugState &state) {
mLastHwcState = state;
}
diff --git a/services/surfaceflinger/LayerFE.h b/services/surfaceflinger/LayerFE.h
index a537456..b89b6b4 100644
--- a/services/surfaceflinger/LayerFE.h
+++ b/services/surfaceflinger/LayerFE.h
@@ -18,6 +18,7 @@
#include <android/gui/CachingHint.h>
#include <gui/LayerMetadata.h>
+#include <ui/GraphicBuffer.h>
#include <ui/LayerStack.h>
#include <ui/PictureProfileHandle.h>
@@ -58,6 +59,7 @@
ftl::Future<FenceResult> createReleaseFenceFuture() override;
void setReleaseFence(const FenceResult& releaseFence) override;
LayerFE::ReleaseFencePromiseStatus getReleaseFencePromiseStatus() override;
+ void setReleasedBuffer(sp<GraphicBuffer> buffer) override;
void onPictureProfileCommitted() override;
// Used for debugging purposes, e.g. perfetto tracing, dumpsys.
@@ -95,6 +97,7 @@
std::promise<FenceResult> mReleaseFence;
ReleaseFencePromiseStatus mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::UNINITIALIZED;
HwcLayerDebugState mLastHwcState;
+ wp<GraphicBuffer> mReleasedBuffer;
};
} // namespace android
diff --git a/services/surfaceflinger/LayerVector.h b/services/surfaceflinger/LayerVector.h
index 38dc11d..81155fd 100644
--- a/services/surfaceflinger/LayerVector.h
+++ b/services/surfaceflinger/LayerVector.h
@@ -49,7 +49,8 @@
using Visitor = std::function<void(Layer*)>;
private:
- const StateSet mStateSet;
+ // FIXME: This is set but not used anywhere.
+ [[maybe_unused]] const StateSet mStateSet;
};
}
diff --git a/services/surfaceflinger/PowerAdvisor/SessionManager.h b/services/surfaceflinger/PowerAdvisor/SessionManager.h
index 93a80b5..afa52eb 100644
--- a/services/surfaceflinger/PowerAdvisor/SessionManager.h
+++ b/services/surfaceflinger/PowerAdvisor/SessionManager.h
@@ -68,7 +68,8 @@
bool isLayerRelevant(int32_t layerId);
// The UID of whoever created our ISessionManager connection
- const uid_t mUid;
+ // FIXME: This is set but is not used anywhere.
+ [[maybe_unused]] const uid_t mUid;
// State owned by the main thread
@@ -99,4 +100,4 @@
};
} // namespace adpf
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 514adac..615492a 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -348,7 +348,7 @@
SurfaceFlinger::ScreenshotArgs screenshotArgs;
screenshotArgs.captureTypeVariant = displayWeak;
- screenshotArgs.displayId = std::nullopt;
+ screenshotArgs.displayIdVariant = std::nullopt;
screenshotArgs.sourceCrop = sampledBounds.isEmpty() ? layerStackSpaceRect : sampledBounds;
screenshotArgs.reqSize = sampledBounds.getSize();
screenshotArgs.dataspace = ui::Dataspace::V0_SRGB;
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h b/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h
index 767462d..70ae940 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h
@@ -36,7 +36,7 @@
using CompositionCoverageFlags = ftl::Flags<CompositionCoverage>;
-using CompositionCoveragePerDisplay = ui::DisplayMap<DisplayId, CompositionCoverageFlags>;
+using CompositionCoveragePerDisplay = ui::DisplayMap<DisplayIdVariant, CompositionCoverageFlags>;
inline CompositionCoverageFlags multiDisplayUnion(const CompositionCoveragePerDisplay& displays) {
CompositionCoverageFlags coverage;
diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp
index af6d4d3..2906bbd 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.cpp
+++ b/services/surfaceflinger/ScreenCaptureOutput.cpp
@@ -30,11 +30,12 @@
std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs args) {
std::shared_ptr<ScreenCaptureOutput> output = compositionengine::impl::createOutputTemplated<
ScreenCaptureOutput, compositionengine::CompositionEngine,
- /* sourceCrop */ const Rect, std::optional<DisplayId>,
+ /* sourceCrop */ const Rect, ftl::Optional<DisplayIdVariant>,
const compositionengine::Output::ColorProfile&,
/* layerAlpha */ float,
- /* regionSampling */ bool>(args.compositionEngine, args.sourceCrop, args.displayId,
- args.colorProfile, args.layerAlpha, args.regionSampling,
+ /* regionSampling */ bool>(args.compositionEngine, args.sourceCrop,
+ args.displayIdVariant, args.colorProfile, args.layerAlpha,
+ args.regionSampling,
args.dimInGammaSpaceForEnhancedScreenshots,
args.enableLocalTonemapping);
output->editState().isSecure = args.isSecure;
@@ -59,8 +60,8 @@
{
std::string name = args.regionSampling ? "RegionSampling" : "ScreenCaptureOutput";
- if (args.displayId) {
- base::StringAppendF(&name, " for %" PRIu64, args.displayId.value().value);
+ if (const auto id = args.displayIdVariant.and_then(asDisplayIdOfType<DisplayId>)) {
+ base::StringAppendF(&name, " for %" PRIu64, id->value);
}
output->setName(name);
}
@@ -68,12 +69,12 @@
}
ScreenCaptureOutput::ScreenCaptureOutput(
- const Rect sourceCrop, std::optional<DisplayId> displayId,
+ const Rect sourceCrop, ftl::Optional<DisplayIdVariant> displayIdVariant,
const compositionengine::Output::ColorProfile& colorProfile, float layerAlpha,
bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots,
bool enableLocalTonemapping)
: mSourceCrop(sourceCrop),
- mDisplayId(displayId),
+ mDisplayIdVariant(displayIdVariant),
mColorProfile(colorProfile),
mLayerAlpha(layerAlpha),
mRegionSampling(regionSampling),
@@ -137,12 +138,9 @@
}
std::vector<aidl::android::hardware::graphics::composer3::Luts> luts;
- if (mDisplayId) {
- const auto id = PhysicalDisplayId::tryCast(mDisplayId.value());
- if (id) {
- auto& hwc = getCompositionEngine().getHwComposer();
- hwc.getLuts(*id, buffers, &luts);
- }
+ if (const auto physicalDisplayId = mDisplayIdVariant.and_then(asPhysicalDisplayId)) {
+ auto& hwc = getCompositionEngine().getHwComposer();
+ hwc.getLuts(*physicalDisplayId, buffers, &luts);
}
if (buffers.size() == luts.size()) {
diff --git a/services/surfaceflinger/ScreenCaptureOutput.h b/services/surfaceflinger/ScreenCaptureOutput.h
index b3e98b1..d4e20fc 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.h
+++ b/services/surfaceflinger/ScreenCaptureOutput.h
@@ -30,7 +30,7 @@
ui::LayerStack layerStack;
Rect sourceCrop;
std::shared_ptr<renderengine::ExternalTexture> buffer;
- std::optional<DisplayId> displayId;
+ ftl::Optional<DisplayIdVariant> displayIdVariant;
ui::Size reqBufferSize;
float sdrWhitePointNits;
float displayBrightnessNits;
@@ -51,7 +51,7 @@
// SurfaceFlinger::captureLayers and SurfaceFlinger::captureDisplay.
class ScreenCaptureOutput : public compositionengine::impl::Output {
public:
- ScreenCaptureOutput(const Rect sourceCrop, std::optional<DisplayId> displayId,
+ ScreenCaptureOutput(const Rect sourceCrop, ftl::Optional<DisplayIdVariant> displayIdVariant,
const compositionengine::Output::ColorProfile& colorProfile,
float layerAlpha, bool regionSampling,
bool dimInGammaSpaceForEnhancedScreenshots, bool enableLocalTonemapping);
@@ -70,7 +70,7 @@
private:
std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts> generateLuts();
const Rect mSourceCrop;
- const std::optional<DisplayId> mDisplayId;
+ const ftl::Optional<DisplayIdVariant> mDisplayIdVariant;
const compositionengine::Output::ColorProfile& mColorProfile;
const float mLayerAlpha;
const bool mRegionSampling;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0bbef95..aa933ee 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -659,12 +659,14 @@
}
}
-VirtualDisplayId SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution, ui::PixelFormat format,
- const std::string& uniqueId) {
+std::optional<VirtualDisplayIdVariant> SurfaceFlinger::acquireVirtualDisplay(
+ ui::Size resolution, ui::PixelFormat format, const std::string& uniqueId,
+ compositionengine::DisplayCreationArgsBuilder& builder) {
if (auto& generator = mVirtualDisplayIdGenerators.hal) {
if (const auto id = generator->generateId()) {
if (getHwComposer().allocateVirtualDisplay(*id, resolution, &format)) {
acquireVirtualDisplaySnapshot(*id, uniqueId);
+ builder.setId(*id);
return *id;
}
@@ -679,22 +681,23 @@
const auto id = mVirtualDisplayIdGenerators.gpu.generateId();
LOG_ALWAYS_FATAL_IF(!id, "Failed to generate ID for GPU virtual display");
acquireVirtualDisplaySnapshot(*id, uniqueId);
+ builder.setId(*id);
return *id;
}
-void SurfaceFlinger::releaseVirtualDisplay(VirtualDisplayId displayId) {
- if (const auto id = HalVirtualDisplayId::tryCast(displayId)) {
- if (auto& generator = mVirtualDisplayIdGenerators.hal) {
- generator->releaseId(*id);
- releaseVirtualDisplaySnapshot(*id);
- }
- return;
- }
-
- const auto id = GpuVirtualDisplayId::tryCast(displayId);
- LOG_ALWAYS_FATAL_IF(!id);
- mVirtualDisplayIdGenerators.gpu.releaseId(*id);
- releaseVirtualDisplaySnapshot(*id);
+void SurfaceFlinger::releaseVirtualDisplay(VirtualDisplayIdVariant displayId) {
+ ftl::match(
+ displayId,
+ [this](HalVirtualDisplayId halVirtualDisplayId) {
+ if (auto& generator = mVirtualDisplayIdGenerators.hal) {
+ generator->releaseId(halVirtualDisplayId);
+ releaseVirtualDisplaySnapshot(halVirtualDisplayId);
+ }
+ },
+ [this](GpuVirtualDisplayId gpuVirtualDisplayId) {
+ mVirtualDisplayIdGenerators.gpu.releaseId(gpuVirtualDisplayId);
+ releaseVirtualDisplaySnapshot(gpuVirtualDisplayId);
+ });
}
void SurfaceFlinger::releaseVirtualDisplaySnapshot(VirtualDisplayId displayId) {
@@ -1182,6 +1185,7 @@
const auto& snapshot = snapshotRef.get();
info->connectionType = snapshot.connectionType();
+ info->port = snapshot.port();
info->deviceProductInfo = snapshot.deviceProductInfo();
if (mEmulatedDisplayDensity) {
@@ -1265,7 +1269,17 @@
ui::FrameRateCategoryRate frameRateCategoryRate(normal.getValue(), high.getValue());
info->frameRateCategoryRate = frameRateCategoryRate;
- info->supportedRefreshRates = display->refreshRateSelector().getSupportedFrameRates();
+ if (info->hasArrSupport) {
+ info->supportedRefreshRates = display->refreshRateSelector().getSupportedFrameRates();
+ } else {
+ // On non-ARR devices, list the refresh rates same as the supported display modes.
+ std::vector<float> supportedFrameRates;
+ supportedFrameRates.reserve(info->supportedDisplayModes.size());
+ std::transform(info->supportedDisplayModes.begin(), info->supportedDisplayModes.end(),
+ std::back_inserter(supportedFrameRates),
+ [](ui::DisplayMode mode) { return mode.peakRefreshRate; });
+ info->supportedRefreshRates = supportedFrameRates;
+ }
info->activeColorMode = display->getCompositionDisplay()->getState().colorMode;
info->hdrCapabilities = filterOut4k30(display->getHdrCapabilities());
@@ -2863,9 +2877,9 @@
// output. Layer stacks are not tracked in Display when we iterate through
// frameTargeters. Cross-referencing layer stacks allows us to filter out displays
// by ID with duplicate layer stacks before adding them to CompositionEngine output.
- ui::DisplayMap<DisplayId, ui::LayerStack> physicalDisplayLayerStacks;
+ ui::DisplayMap<PhysicalDisplayId, ui::LayerStack> physicalDisplayLayerStacks;
for (auto& [_, display] : displays) {
- const auto id = PhysicalDisplayId::tryCast(display->getId());
+ const auto id = asPhysicalDisplayId(display->getDisplayIdVariant());
if (id && frameTargeters.contains(*id)) {
physicalDisplayLayerStacks.try_emplace(*id, display->getLayerStack());
}
@@ -3131,7 +3145,7 @@
for (const auto& [_, display] : displays) {
const auto& state = display->getCompositionDisplay()->getState();
CompositionCoverageFlags& flags =
- mCompositionCoverage.try_emplace(display->getId()).first->second;
+ mCompositionCoverage.try_emplace(display->getDisplayIdVariant()).first->second;
if (state.usesDeviceComposition) {
flags |= CompositionCoverage::Hwc;
@@ -3185,8 +3199,8 @@
CompositeResultsPerDisplay resultsPerDisplay;
// Filter out virtual displays.
- for (const auto& [id, coverage] : mCompositionCoverage) {
- if (const auto idOpt = PhysicalDisplayId::tryCast(id)) {
+ for (const auto& [idVar, coverage] : mCompositionCoverage) {
+ if (const auto idOpt = asPhysicalDisplayId(idVar)) {
resultsPerDisplay.try_emplace(*idOpt, CompositeResult{coverage});
}
}
@@ -3224,16 +3238,12 @@
return false;
}
-ui::Rotation SurfaceFlinger::getPhysicalDisplayOrientation(DisplayId displayId,
+ui::Rotation SurfaceFlinger::getPhysicalDisplayOrientation(PhysicalDisplayId displayId,
bool isPrimary) const {
- const auto id = PhysicalDisplayId::tryCast(displayId);
- if (!id) {
- return ui::ROTATION_0;
- }
if (!mIgnoreHwcPhysicalDisplayOrientation &&
getHwComposer().getComposer()->isSupported(
Hwc2::Composer::OptionalFeature::PhysicalDisplayOrientation)) {
- switch (getHwComposer().getPhysicalDisplayOrientation(*id)) {
+ switch (getHwComposer().getPhysicalDisplayOrientation(displayId)) {
case Hwc2::AidlTransform::ROT_90:
return ui::ROTATION_90;
case Hwc2::AidlTransform::ROT_180:
@@ -3881,13 +3891,17 @@
creationArgs.hasWideColorGamut = false;
creationArgs.supportedPerFrameMetadata = 0;
- if (const auto physicalIdOpt = PhysicalDisplayId::tryCast(compositionDisplay->getId())) {
+ if (const auto physicalIdOpt =
+ compositionDisplay->getDisplayIdVariant().and_then(asPhysicalDisplayId)) {
const auto physicalId = *physicalIdOpt;
creationArgs.isPrimary = physicalId == getPrimaryDisplayIdLocked();
creationArgs.refreshRateSelector =
FTL_FAKE_GUARD(kMainThreadContext,
mDisplayModeController.selectorPtrFor(physicalId));
+ creationArgs.physicalOrientation =
+ getPhysicalDisplayOrientation(physicalId, creationArgs.isPrimary);
+ ALOGV("Display Orientation: %s", toCString(creationArgs.physicalOrientation));
mPhysicalDisplays.get(physicalId)
.transform(&PhysicalDisplay::snapshotRef)
@@ -3900,7 +3914,8 @@
}));
}
- if (const auto id = HalDisplayId::tryCast(compositionDisplay->getId())) {
+ if (const auto id = compositionDisplay->getDisplayIdVariant().and_then(
+ asHalDisplayId<DisplayIdVariant>)) {
getHwComposer().getHdrCapabilities(*id, &creationArgs.hdrCapabilities);
creationArgs.supportedPerFrameMetadata = getHwComposer().getSupportedPerFrameMetadata(*id);
}
@@ -3916,10 +3931,6 @@
nativeWindow->setSwapInterval(nativeWindow.get(), 0);
}
- creationArgs.physicalOrientation =
- getPhysicalDisplayOrientation(compositionDisplay->getId(), creationArgs.isPrimary);
- ALOGV("Display Orientation: %s", toCString(creationArgs.physicalOrientation));
-
if (FlagManager::getInstance().correct_virtual_display_power_state()) {
creationArgs.initialPowerMode = state.initialPowerMode;
} else {
@@ -3949,7 +3960,8 @@
mode.getPeakFps());
}
- display->setLayerFilter(makeLayerFilterForDisplay(display->getId(), state.layerStack));
+ display->setLayerFilter(
+ makeLayerFilterForDisplay(display->getDisplayIdVariant(), state.layerStack));
display->setProjection(state.orientation, state.layerStackSpaceRect,
state.orientedDisplaySpaceRect);
display->setDisplayName(state.displayName);
@@ -4005,10 +4017,12 @@
}
compositionengine::DisplayCreationArgsBuilder builder;
+ std::optional<VirtualDisplayIdVariant> virtualDisplayIdVariantOpt;
if (const auto& physical = state.physical) {
builder.setId(physical->id);
} else {
- builder.setId(acquireVirtualDisplay(resolution, pixelFormat, state.uniqueId));
+ virtualDisplayIdVariantOpt =
+ acquireVirtualDisplay(resolution, pixelFormat, state.uniqueId, builder);
}
builder.setPixels(resolution);
@@ -4028,10 +4042,10 @@
getFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false);
if (state.isVirtual()) {
- const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId());
- LOG_FATAL_IF(!displayId);
- auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *displayId, state.surface,
- bqProducer, bqConsumer, state.displayName);
+ LOG_FATAL_IF(!virtualDisplayIdVariantOpt);
+ auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *virtualDisplayIdVariantOpt,
+ state.surface, bqProducer, bqConsumer,
+ state.displayName);
displaySurface = surface;
producer = std::move(surface);
} else {
@@ -4039,18 +4053,17 @@
"adding a supported display, but rendering "
"surface is provided (%p), ignoring it",
state.surface.get());
- const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId());
- LOG_FATAL_IF(!displayId);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
const auto frameBufferSurface =
- sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqProducer, bqConsumer,
+ sp<FramebufferSurface>::make(getHwComposer(), state.physical->id, bqProducer,
+ bqConsumer,
state.physical->activeMode->getResolution(),
ui::Size(maxGraphicsWidth, maxGraphicsHeight));
displaySurface = frameBufferSurface;
producer = frameBufferSurface->getSurface()->getIGraphicBufferProducer();
#else
displaySurface =
- sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,
+ sp<FramebufferSurface>::make(getHwComposer(), state.physical->id, bqConsumer,
state.physical->activeMode->getResolution(),
ui::Size(maxGraphicsWidth, maxGraphicsHeight));
producer = bqProducer;
@@ -4107,8 +4120,8 @@
if (display) {
display->disconnect();
- if (display->isVirtual()) {
- releaseVirtualDisplay(display->getVirtualId());
+ if (const auto virtualDisplayIdVariant = display->getVirtualDisplayIdVariant()) {
+ releaseVirtualDisplay(*virtualDisplayIdVariant);
} else {
mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId);
}
@@ -4151,8 +4164,8 @@
if (currentBinder != drawingBinder || currentState.sequenceId != drawingState.sequenceId) {
if (const auto display = getDisplayDeviceLocked(displayToken)) {
display->disconnect();
- if (display->isVirtual()) {
- releaseVirtualDisplay(display->getVirtualId());
+ if (const auto virtualDisplayIdVariant = display->getVirtualDisplayIdVariant()) {
+ releaseVirtualDisplay(*virtualDisplayIdVariant);
}
if (display->isRefreshable()) {
@@ -4184,8 +4197,8 @@
if (const auto display = getDisplayDeviceLocked(displayToken)) {
if (currentState.layerStack != drawingState.layerStack) {
- display->setLayerFilter(
- makeLayerFilterForDisplay(display->getId(), currentState.layerStack));
+ display->setLayerFilter(makeLayerFilterForDisplay(display->getDisplayIdVariant(),
+ currentState.layerStack));
}
if (currentState.flags != drawingState.flags) {
display->setFlags(currentState.flags);
@@ -4427,7 +4440,7 @@
void SurfaceFlinger::updateCursorAsync() {
compositionengine::CompositionRefreshArgs refreshArgs;
for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
- if (HalDisplayId::tryCast(display->getId())) {
+ if (asHalDisplayId(display->getDisplayIdVariant())) {
refreshArgs.outputs.push_back(display->getCompositionDisplay());
}
}
@@ -5085,6 +5098,12 @@
layerName.c_str(), transactionState.getId());
if (resolvedState.externalTexture) {
resolvedState.state.bufferData->buffer = resolvedState.externalTexture->getBuffer();
+ if (FlagManager::getInstance().monitor_buffer_fences()) {
+ resolvedState.state.bufferData->buffer->getDependencyMonitor()
+ .addIngress(FenceTime::makeValid(
+ resolvedState.state.bufferData->acquireFence),
+ "Incoming txn");
+ }
}
mBufferCountTracker.increment(resolvedState.layerId);
}
@@ -5700,7 +5719,13 @@
incRefreshableDisplays();
}
+ if (displayId == mActiveDisplayId &&
+ FlagManager::getInstance().correct_virtual_display_power_state()) {
+ applyOptimizationPolicy(__func__);
+ }
+
const auto activeMode = display->refreshRateSelector().getActiveMode().modePtr;
+ using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy;
if (currentMode == hal::PowerMode::OFF) {
// Turn on the display
@@ -5715,12 +5740,10 @@
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
}
- if (displayId == mActiveDisplayId) {
- if (FlagManager::getInstance().correct_virtual_display_power_state()) {
- applyOptimizationPolicy("setPhysicalDisplayPowerMode(ON)");
- } else {
- disablePowerOptimizations("setPhysicalDisplayPowerMode(ON)");
- }
+ if (displayId == mActiveDisplayId &&
+ !FlagManager::getInstance().correct_virtual_display_power_state()) {
+ optimizeThreadScheduling("setPhysicalDisplayPowerMode(ON/DOZE)",
+ OptimizationPolicy::optimizeForPerformance);
}
getHwComposer().setPowerMode(displayId, mode);
@@ -5729,7 +5752,8 @@
mScheduler->getVsyncSchedule(displayId)->getPendingHardwareVsyncState();
requestHardwareVsync(displayId, enable);
- if (displayId == mActiveDisplayId) {
+ if (displayId == mActiveDisplayId &&
+ !FlagManager::getInstance().correct_virtual_display_power_state()) {
mScheduler->enableSyntheticVsync(false);
}
@@ -5746,13 +5770,13 @@
if (const auto display = getActivatableDisplay()) {
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
} else {
- if (FlagManager::getInstance().correct_virtual_display_power_state()) {
- applyOptimizationPolicy("setPhysicalDisplayPowerMode(OFF)");
- } else {
- enablePowerOptimizations("setPhysicalDisplayPowerMode(OFF)");
+ if (!FlagManager::getInstance().correct_virtual_display_power_state()) {
+ optimizeThreadScheduling("setPhysicalDisplayPowerMode(OFF)",
+ OptimizationPolicy::optimizeForPower);
}
- if (currentModeNotDozeSuspend) {
+ if (currentModeNotDozeSuspend &&
+ !FlagManager::getInstance().correct_virtual_display_power_state()) {
mScheduler->enableSyntheticVsync();
}
}
@@ -5780,7 +5804,9 @@
ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON.");
mVisibleRegionsDirty = true;
scheduleRepaint();
- mScheduler->enableSyntheticVsync(false);
+ if (!FlagManager::getInstance().correct_virtual_display_power_state()) {
+ mScheduler->enableSyntheticVsync(false);
+ }
}
constexpr bool kAllowToEnable = true;
mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get());
@@ -5790,7 +5816,8 @@
constexpr bool kDisallow = true;
mScheduler->disableHardwareVsync(displayId, kDisallow);
- if (displayId == mActiveDisplayId) {
+ if (displayId == mActiveDisplayId &&
+ !FlagManager::getInstance().correct_virtual_display_power_state()) {
mScheduler->enableSyntheticVsync();
}
getHwComposer().setPowerMode(displayId, mode);
@@ -5829,43 +5856,44 @@
to_string(displayId).c_str());
}
-bool SurfaceFlinger::shouldOptimizeForPerformance() {
- for (const auto& [_, display] : mDisplays) {
- // Displays that are optimized for power are always powered on and should not influence
- // whether there is an active display for the purpose of power optimization, etc. If these
- // displays are being shown somewhere, a different (physical or virtual) display that is
- // optimized for performance will be powered on in addition. Displays optimized for
- // performance will change power mode, so if they are off then they are not active.
- if (display->isPoweredOn() &&
- display->getOptimizationPolicy() ==
- gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance) {
- return true;
- }
- }
- return false;
-}
+void SurfaceFlinger::optimizeThreadScheduling(
+ const char* whence, gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy) {
+ ALOGD("%s: Optimizing thread scheduling: %s", whence, to_string(optimizationPolicy));
-void SurfaceFlinger::enablePowerOptimizations(const char* whence) {
- ALOGD("%s: Enabling power optimizations", whence);
-
- setSchedAttr(false, whence);
- setSchedFifo(false, whence);
-}
-
-void SurfaceFlinger::disablePowerOptimizations(const char* whence) {
- ALOGD("%s: Disabling power optimizations", whence);
-
+ const bool optimizeForPerformance =
+ optimizationPolicy == gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance;
// TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall
// and set it before SCHED_FIFO due to b/190237315.
- setSchedAttr(true, whence);
- setSchedFifo(true, whence);
+ setSchedAttr(optimizeForPerformance, whence);
+ setSchedFifo(optimizeForPerformance, whence);
}
void SurfaceFlinger::applyOptimizationPolicy(const char* whence) {
- if (shouldOptimizeForPerformance()) {
- disablePowerOptimizations(whence);
- } else {
- enablePowerOptimizations(whence);
+ using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy;
+
+ const bool optimizeForPerformance =
+ std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) {
+ const auto& display = pair.second;
+ return display->isPoweredOn() &&
+ display->getOptimizationPolicy() ==
+ OptimizationPolicy::optimizeForPerformance;
+ });
+
+ optimizeThreadScheduling(whence,
+ optimizeForPerformance ? OptimizationPolicy::optimizeForPerformance
+ : OptimizationPolicy::optimizeForPower);
+
+ if (mScheduler) {
+ const bool disableSyntheticVsync =
+ std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) {
+ const auto& display = pair.second;
+ const hal::PowerMode powerMode = display->getPowerMode();
+ return powerMode != hal::PowerMode::OFF &&
+ powerMode != hal::PowerMode::DOZE_SUSPEND &&
+ display->getOptimizationPolicy() ==
+ OptimizationPolicy::optimizeForPerformance;
+ });
+ mScheduler->enableSyntheticVsync(!disableSyntheticVsync);
}
}
@@ -6089,17 +6117,15 @@
for (const auto& [token, display] : mDisplays) {
if (display->isVirtual()) {
- const auto displayId = display->getId();
+ const VirtualDisplayId virtualId = display->getVirtualId();
utils::Dumper::Section section(dumper,
- ftl::Concat("Virtual Display ", displayId.value).str());
+ ftl::Concat("Virtual Display ", virtualId.value).str());
display->dump(dumper);
- if (const auto virtualIdOpt = VirtualDisplayId::tryCast(displayId)) {
- std::lock_guard lock(mVirtualDisplaysMutex);
- const auto virtualSnapshotIt = mVirtualDisplays.find(virtualIdOpt.value());
- if (virtualSnapshotIt != mVirtualDisplays.end()) {
- virtualSnapshotIt->second.dump(dumper);
- }
+ std::lock_guard lock(mVirtualDisplaysMutex);
+ const auto virtualSnapshotIt = mVirtualDisplays.find(virtualId);
+ if (virtualSnapshotIt != mVirtualDisplays.end()) {
+ virtualSnapshotIt->second.dump(dumper);
}
}
}
@@ -6107,7 +6133,7 @@
void SurfaceFlinger::dumpDisplayIdentificationData(std::string& result) const {
for (const auto& [token, display] : mDisplays) {
- const auto displayId = PhysicalDisplayId::tryCast(display->getId());
+ const auto displayId = asPhysicalDisplayId(display->getDisplayIdVariant());
if (!displayId) {
continue;
}
@@ -6316,7 +6342,7 @@
void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const {
for (const auto& [token, display] : mDisplays) {
- const auto displayId = HalDisplayId::tryCast(display->getId());
+ const auto displayId = asHalDisplayId(display->getDisplayIdVariant());
if (!displayId) {
continue;
}
@@ -7383,7 +7409,7 @@
}
wp<const DisplayDevice> displayWeak;
- DisplayId displayId;
+ ftl::Optional<DisplayIdVariant> displayIdVariantOpt;
ui::LayerStack layerStack;
ui::Size reqSize(args.width, args.height);
std::unordered_set<uint32_t> excludeLayerIds;
@@ -7399,7 +7425,7 @@
return;
}
displayWeak = display;
- displayId = display->getId();
+ displayIdVariantOpt = display->getDisplayIdVariant();
layerStack = display->getLayerStack();
displayIsSecure = display->isSecure();
@@ -7427,7 +7453,7 @@
ScreenshotArgs screenshotArgs;
screenshotArgs.captureTypeVariant = displayWeak;
- screenshotArgs.displayId = displayId;
+ screenshotArgs.displayIdVariant = displayIdVariantOpt;
screenshotArgs.sourceCrop = gui::aidl_utils::fromARect(captureArgs.sourceCrop);
if (screenshotArgs.sourceCrop.isEmpty()) {
screenshotArgs.sourceCrop = layerStackSpaceRect;
@@ -7446,6 +7472,7 @@
const sp<IScreenCaptureListener>& captureListener) {
ui::LayerStack layerStack;
wp<const DisplayDevice> displayWeak;
+ ftl::Optional<DisplayIdVariant> displayIdVariantOpt;
ui::Size size;
Rect layerStackSpaceRect;
bool displayIsSecure;
@@ -7461,6 +7488,7 @@
}
displayWeak = display;
+ displayIdVariantOpt = display->getDisplayIdVariant();
layerStack = display->getLayerStack();
layerStackSpaceRect = display->getLayerStackSpaceRect();
size = display->getLayerStackSpaceRect().getSize();
@@ -7495,7 +7523,7 @@
ScreenshotArgs screenshotArgs;
screenshotArgs.captureTypeVariant = displayWeak;
- screenshotArgs.displayId = displayId;
+ screenshotArgs.displayIdVariant = displayIdVariantOpt;
screenshotArgs.sourceCrop = layerStackSpaceRect;
screenshotArgs.reqSize = size;
screenshotArgs.dataspace = static_cast<ui::Dataspace>(args.dataspace);
@@ -7987,7 +8015,7 @@
.layerStack = layerStack,
.sourceCrop = args.sourceCrop,
.buffer = std::move(buffer),
- .displayId = args.displayId,
+ .displayIdVariant = args.displayIdVariant,
.reqBufferSize = args.reqSize,
.sdrWhitePointNits = args.sdrWhitePointNits,
.displayBrightnessNits = args.displayBrightnessNits,
@@ -8387,8 +8415,8 @@
// TODO(b/255635821): Choose the pacesetter display, considering both internal and external
// displays. For now, pick the other internal display, assuming a dual-display foldable.
return findDisplay([this](const DisplayDevice& display) REQUIRES(mStateLock) {
- const auto idOpt = PhysicalDisplayId::tryCast(display.getId());
- return idOpt && *idOpt != mActiveDisplayId && display.isPoweredOn() &&
+ const auto idOpt = asPhysicalDisplayId(display.getDisplayIdVariant());
+ return idOpt.has_value() && *idOpt != mActiveDisplayId && display.isPoweredOn() &&
mPhysicalDisplays.get(*idOpt)
.transform(&PhysicalDisplay::isInternal)
.value_or(false);
@@ -8925,6 +8953,7 @@
if (status == NO_ERROR) {
// convert ui::StaticDisplayInfo to gui::StaticDisplayInfo
outInfo->connectionType = static_cast<gui::DisplayConnectionType>(info.connectionType);
+ outInfo->port = info.port;
outInfo->density = info.density;
outInfo->secure = info.secure;
outInfo->installOrientation = static_cast<gui::Rotation>(info.installOrientation);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 7568479..f61214c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -160,6 +160,7 @@
class OutputLayer;
struct CompositionRefreshArgs;
+class DisplayCreationArgsBuilder;
} // namespace compositionengine
namespace renderengine {
@@ -732,19 +733,14 @@
void setVirtualDisplayPowerMode(const sp<DisplayDevice>& display, hal::PowerMode mode)
REQUIRES(mStateLock, kMainThreadContext);
- // Returns whether to optimize globally for performance instead of power.
- bool shouldOptimizeForPerformance() REQUIRES(mStateLock);
-
- // Turns on power optimizations, for example when there are no displays to be optimized for
- // performance.
- static void enablePowerOptimizations(const char* whence);
-
- // Turns off power optimizations.
- static void disablePowerOptimizations(const char* whence);
+ // Adjusts thread scheduling according to the optimization policy
+ static void optimizeThreadScheduling(
+ const char* whence, gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy);
// Enables or disables power optimizations depending on whether there are displays that should
// be optimized for performance.
- void applyOptimizationPolicy(const char* whence) REQUIRES(mStateLock);
+ void applyOptimizationPolicy(const char* whence) REQUIRES(kMainThreadContext)
+ REQUIRES(mStateLock);
// Returns the preferred mode for PhysicalDisplayId if the Scheduler has selected one for that
// display. Falls back to the display's defaultModeId otherwise.
@@ -885,7 +881,7 @@
std::variant<int32_t, wp<const DisplayDevice>> captureTypeVariant;
// Display ID of the display the result will be on
- std::optional<DisplayId> displayId{std::nullopt};
+ ftl::Optional<DisplayIdVariant> displayIdVariant{std::nullopt};
// If true, transform is inverted from the parent layer snapshot
bool childrenOnly{false};
@@ -1039,10 +1035,10 @@
// region of all screens presenting this layer stack.
void invalidateLayerStack(const ui::LayerFilter& layerFilter, const Region& dirty);
- ui::LayerFilter makeLayerFilterForDisplay(DisplayId displayId, ui::LayerStack layerStack)
+ ui::LayerFilter makeLayerFilterForDisplay(DisplayIdVariant displayId, ui::LayerStack layerStack)
REQUIRES(mStateLock) {
return {layerStack,
- PhysicalDisplayId::tryCast(displayId)
+ asPhysicalDisplayId(displayId)
.and_then(display::getPhysicalDisplay(mPhysicalDisplays))
.transform(&display::PhysicalDisplay::isInternal)
.value_or(false)};
@@ -1135,8 +1131,10 @@
void enableHalVirtualDisplays(bool);
// Virtual display lifecycle for ID generation and HAL allocation.
- VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat, const std::string& uniqueId)
- REQUIRES(mStateLock);
+ std::optional<VirtualDisplayIdVariant> acquireVirtualDisplay(
+ ui::Size, ui::PixelFormat, const std::string& uniqueId,
+ compositionengine::DisplayCreationArgsBuilder&) REQUIRES(mStateLock);
+
template <typename ID>
void acquireVirtualDisplaySnapshot(ID displayId, const std::string& uniqueId) {
std::lock_guard lock(mVirtualDisplaysMutex);
@@ -1147,7 +1145,7 @@
}
}
- void releaseVirtualDisplay(VirtualDisplayId);
+ void releaseVirtualDisplay(VirtualDisplayIdVariant displayId);
void releaseVirtualDisplaySnapshot(VirtualDisplayId displayId);
// Returns a display other than `mActiveDisplayId` that can be activated, if any.
@@ -1232,7 +1230,7 @@
bool isHdrLayer(const frontend::LayerSnapshot& snapshot) const;
- ui::Rotation getPhysicalDisplayOrientation(DisplayId, bool isPrimary) const
+ ui::Rotation getPhysicalDisplayOrientation(PhysicalDisplayId, bool isPrimary) const
REQUIRES(mStateLock);
void traverseLegacyLayers(const LayerVector::Visitor& visitor) const
REQUIRES(kMainThreadContext);
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index b22ec66..2e8c8c1 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -18,7 +18,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
#undef LOG_TAG
#define LOG_TAG "TransactionCallbackInvoker"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -28,6 +28,7 @@
#include "Utils/FenceUtils.h"
#include <binder/IInterface.h>
+#include <common/FlagManager.h>
#include <common/trace.h>
#include <utils/RefBase.h>
@@ -142,8 +143,17 @@
handle->transformHint,
handle->currentMaxAcquiredBufferCount,
eventStats, handle->previousReleaseCallbackId);
+
if (handle->bufferReleaseChannel &&
handle->previousReleaseCallbackId != ReleaseCallbackId::INVALID_ID) {
+ if (FlagManager::getInstance().monitor_buffer_fences()) {
+ if (auto previousBuffer = handle->previousBuffer.lock()) {
+ previousBuffer->getBuffer()
+ ->getDependencyMonitor()
+ .addEgress(FenceTime::makeValid(handle->previousReleaseFence),
+ "Txn release");
+ }
+ }
mBufferReleases.emplace_back(handle->name, handle->bufferReleaseChannel,
handle->previousReleaseCallbackId,
handle->previousReleaseFence,
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 178ddbb..34f6ffc 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -25,6 +25,7 @@
#include <ftl/future.h>
#include <gui/BufferReleaseChannel.h>
#include <gui/ITransactionCompletedListener.h>
+#include <renderengine/ExternalTexture.h>
#include <ui/Fence.h>
#include <ui/FenceResult.h>
@@ -55,6 +56,7 @@
uint64_t previousFrameNumber = 0;
ReleaseCallbackId previousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> bufferReleaseChannel;
+ std::weak_ptr<renderengine::ExternalTexture> previousBuffer;
};
class TransactionCallbackInvoker {
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 5ff3d82..bf10351 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -129,6 +129,7 @@
DUMP_ACONFIG_FLAG(correct_virtual_display_power_state);
DUMP_ACONFIG_FLAG(graphite_renderengine_preview_rollout);
DUMP_ACONFIG_FLAG(increase_missed_frame_jank_threshold);
+ DUMP_ACONFIG_FLAG(monitor_buffer_fences);
DUMP_ACONFIG_FLAG(refresh_rate_overlay_on_external_display);
DUMP_ACONFIG_FLAG(vsync_predictor_recovery);
@@ -303,6 +304,7 @@
FLAG_MANAGER_ACONFIG_FLAG(adpf_native_session_manager, "");
FLAG_MANAGER_ACONFIG_FLAG(graphite_renderengine_preview_rollout, "");
FLAG_MANAGER_ACONFIG_FLAG(increase_missed_frame_jank_threshold, "");
+FLAG_MANAGER_ACONFIG_FLAG(monitor_buffer_fences, "");
FLAG_MANAGER_ACONFIG_FLAG(vsync_predictor_recovery, "");
/// Trunk stable server (R/W) flags from outside SurfaceFlinger ///
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 419e92b..8f361ac 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -63,6 +63,7 @@
bool correct_virtual_display_power_state() const;
bool graphite_renderengine_preview_rollout() const;
bool increase_missed_frame_jank_threshold() const;
+ bool monitor_buffer_fences() const;
bool refresh_rate_overlay_on_external_display() const;
bool vsync_predictor_recovery() const;
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index d8f51fe..d412a19 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -216,6 +216,13 @@
} # local_tonemap_screenshots
flag {
+ name: "monitor_buffer_fences"
+ namespace: "core_graphics"
+ description: "Monitors fences for each buffer"
+ bug: "360932099"
+} # monitor_buffer_fences
+
+flag {
name: "no_vsyncs_on_screen_off"
namespace: "core_graphics"
description: "Stop vsync / Choreographer callbacks to apps when the screen is off"
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 4322af7..75182e5 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -183,7 +183,7 @@
template <typename PhysicalDisplay>
struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
- static PhysicalDisplayId get() {
+ static DisplayIdVariant get() {
if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
return PhysicalDisplayId::fromPort(static_cast<bool>(PhysicalDisplay::PRIMARY)
? LEGACY_DISPLAY_TYPE_PRIMARY
@@ -199,12 +199,12 @@
template <VirtualDisplayId::BaseId displayId>
struct DisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
- static HalVirtualDisplayId get() { return HalVirtualDisplayId(displayId); }
+ static DisplayIdVariant get() { return HalVirtualDisplayId(displayId); }
};
template <>
struct DisplayIdGetter<GpuVirtualDisplayIdType> {
- static GpuVirtualDisplayId get() { return GpuVirtualDisplayId(0); }
+ static DisplayIdVariant get() { return GpuVirtualDisplayId(0); }
};
template <typename>
@@ -374,9 +374,8 @@
// Called by tests to inject a HWC display setup
template <hal::PowerMode kPowerMode = hal::PowerMode::ON>
static void injectHwcDisplayWithNoDefaultCapabilities(DisplayTransactionTest* test) {
- const auto displayId = DisplayVariant::DISPLAY_ID::get();
- ASSERT_FALSE(GpuVirtualDisplayId::tryCast(displayId));
- TestableSurfaceFlinger::FakeHwcDisplayInjector(displayId, HWC_DISPLAY_TYPE,
+ TestableSurfaceFlinger::FakeHwcDisplayInjector(DisplayVariant::DISPLAY_ID::get(),
+ HWC_DISPLAY_TYPE,
static_cast<bool>(DisplayVariant::PRIMARY))
.setHwcDisplayId(HWC_DISPLAY_ID)
.setResolution(DisplayVariant::RESOLUTION)
@@ -663,9 +662,8 @@
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
- const auto displayId = Base::DISPLAY_ID::get();
auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
- .setId(displayId)
+ .setId(Base::DISPLAY_ID::get())
.setPixels(Base::RESOLUTION)
.setIsSecure(static_cast<bool>(Base::SECURE))
.setPowerAdvisor(&test->mPowerAdvisor)
@@ -678,7 +676,12 @@
ceDisplayArgs);
// Insert display data so that the HWC thinks it created the virtual display.
- test->mFlinger.mutableHwcDisplayData().try_emplace(displayId);
+ const auto ceDisplayIdVar = compositionDisplay->getDisplayIdVariant();
+ LOG_ALWAYS_FATAL_IF(!ceDisplayIdVar);
+ EXPECT_EQ(*ceDisplayIdVar, Base::DISPLAY_ID::get());
+ const auto displayId = asHalDisplayId(*ceDisplayIdVar);
+ LOG_ALWAYS_FATAL_IF(!displayId);
+ test->mFlinger.mutableHwcDisplayData().try_emplace(*displayId);
return compositionDisplay;
}
@@ -816,8 +819,9 @@
inline DisplayModePtr createDisplayMode(DisplayModeId modeId, Fps refreshRate, int32_t group = 0,
ui::Size resolution = ui::Size(1920, 1080)) {
- return mock::createDisplayMode(modeId, refreshRate, group, resolution,
- PrimaryDisplayVariant::DISPLAY_ID::get());
+ const auto physicalDisplayId = asPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get());
+ LOG_ALWAYS_FATAL_IF(!physicalDisplayId);
+ return mock::createDisplayMode(modeId, refreshRate, group, resolution, *physicalDisplayId);
}
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DualDisplayTransactionTest.h b/services/surfaceflinger/tests/unittests/DualDisplayTransactionTest.h
index 90e716f..edcb639 100644
--- a/services/surfaceflinger/tests/unittests/DualDisplayTransactionTest.h
+++ b/services/surfaceflinger/tests/unittests/DualDisplayTransactionTest.h
@@ -48,8 +48,10 @@
}
}
- static inline PhysicalDisplayId kInnerDisplayId = InnerDisplayVariant::DISPLAY_ID::get();
- static inline PhysicalDisplayId kOuterDisplayId = OuterDisplayVariant::DISPLAY_ID::get();
+ static inline PhysicalDisplayId kInnerDisplayId =
+ asPhysicalDisplayId(InnerDisplayVariant::DISPLAY_ID::get()).value();
+ static inline PhysicalDisplayId kOuterDisplayId =
+ asPhysicalDisplayId(OuterDisplayVariant::DISPLAY_ID::get()).value();
sp<DisplayDevice> mInnerDisplay, mOuterDisplay;
};
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
index aa5b786..aa48c1b 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
@@ -50,9 +50,9 @@
EXPECT_EQ(display.requestedRefreshRate, Fps::fromValue(requestedRefreshRate));
EXPECT_EQ(name.c_str(), display.displayName);
- const VirtualDisplayId vid = GpuVirtualDisplayId(baseId);
sp<DisplayDevice> device =
- mFlinger.createVirtualDisplayDevice(displayToken, vid, requestedRefreshRate);
+ mFlinger.createVirtualDisplayDevice(displayToken, GpuVirtualDisplayId(baseId),
+ requestedRefreshRate);
EXPECT_TRUE(device->isVirtual());
device->adjustRefreshRate(Fps::fromValue(pacesetterDisplayRefreshRate));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
index 1335640..eac5a8e 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
@@ -68,13 +68,9 @@
template <typename Case, bool connected>
void DisplayTransactionCommitTest::expectHotplugReceived(mock::EventThread* eventThread) {
- const auto convert = [](auto physicalDisplayId) {
- return std::make_optional(DisplayId{physicalDisplayId});
- };
-
- EXPECT_CALL(*eventThread,
- onHotplugReceived(ResultOf(convert, Case::Display::DISPLAY_ID::get()), connected))
- .Times(1);
+ const auto physicalDisplayId = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
+ ASSERT_TRUE(physicalDisplayId);
+ EXPECT_CALL(*eventThread, onHotplugReceived(*physicalDisplayId, connected)).Times(1);
}
template <typename Case>
@@ -111,7 +107,7 @@
std::optional<DisplayDeviceState::Physical> expectedPhysical;
if (Case::Display::CONNECTION_TYPE::value) {
- const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get());
+ const auto displayId = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
ASSERT_TRUE(displayId);
const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
ASSERT_TRUE(hwcDisplayId);
@@ -137,10 +133,10 @@
EXPECT_TRUE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
// SF should have a display token.
- const auto displayId = Case::Display::DISPLAY_ID::get();
- ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
+ const auto displayIdOpt = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
+ ASSERT_TRUE(displayIdOpt);
- const auto displayOpt = mFlinger.mutablePhysicalDisplays().get(displayId);
+ const auto displayOpt = mFlinger.mutablePhysicalDisplays().get(*displayIdOpt);
ASSERT_TRUE(displayOpt);
const auto& display = displayOpt->get();
@@ -246,9 +242,9 @@
EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
// SF should not have a PhysicalDisplay.
- const auto displayId = Case::Display::DISPLAY_ID::get();
- ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
- ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(displayId));
+ const auto physicalDisplayIdOpt = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
+ ASSERT_TRUE(physicalDisplayIdOpt);
+ ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(*physicalDisplayIdOpt));
// The existing token should have been removed.
verifyDisplayIsNotConnected(existing.token());
@@ -356,9 +352,10 @@
EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
// SF should not have a PhysicalDisplay.
- const auto displayId = Case::Display::DISPLAY_ID::get();
- ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
- ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(displayId));
+ const auto physicalDisplayIdOpt =
+ asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
+ ASSERT_TRUE(physicalDisplayIdOpt);
+ ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(*physicalDisplayIdOpt));
}(),
testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected.");
}
@@ -400,10 +397,12 @@
// The existing token should have been removed.
verifyDisplayIsNotConnected(existing.token());
- const auto displayId = Case::Display::DISPLAY_ID::get();
- ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
+ const auto physicalDisplayIdOpt =
+ asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
+ ASSERT_TRUE(physicalDisplayIdOpt);
- const auto displayOpt = mFlinger.mutablePhysicalDisplays().get(displayId);
+ const auto displayOpt =
+ mFlinger.mutablePhysicalDisplays().get(*physicalDisplayIdOpt);
ASSERT_TRUE(displayOpt);
EXPECT_NE(existing.token(), displayOpt->get().token());
@@ -540,9 +539,9 @@
// Preconditions
// A virtual display is set up but is removed from the current state.
- const auto displayId = Case::Display::DISPLAY_ID::get();
- ASSERT_TRUE(HalVirtualDisplayId::tryCast(displayId));
- mFlinger.mutableHwcDisplayData().try_emplace(displayId);
+ const auto displayId = asHalDisplayId(Case::Display::DISPLAY_ID::get());
+ ASSERT_TRUE(displayId);
+ mFlinger.mutableHwcDisplayData().try_emplace(*displayId);
Case::Display::injectHwcDisplay(this);
auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
existing.inject();
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
index 49972b0..b8b1b95 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
@@ -90,7 +90,9 @@
mFlinger.configure();
EXPECT_TRUE(hasPhysicalHwcDisplay(PrimaryDisplay::HWC_DISPLAY_ID));
- EXPECT_TRUE(mFlinger.getHwComposer().isConnected(PrimaryDisplay::DISPLAY_ID::get()));
+ const auto primaryDisplayId = asPhysicalDisplayId(PrimaryDisplay::DISPLAY_ID::get());
+ ASSERT_TRUE(primaryDisplayId);
+ EXPECT_TRUE(mFlinger.getHwComposer().isConnected(*primaryDisplayId));
const auto primaryDisplayIdOpt =
mFlinger.getHwComposer().toPhysicalDisplayId(PrimaryDisplay::HWC_DISPLAY_ID);
ASSERT_TRUE(primaryDisplayIdOpt.has_value());
@@ -98,13 +100,15 @@
mFlinger.physicalDisplays().get(primaryDisplayIdOpt.value());
ASSERT_TRUE(primaryPhysicalDisplayOpt.has_value());
const auto primaryDisplaySnapshotRef = primaryPhysicalDisplayOpt->get().snapshotRef();
- EXPECT_EQ(PrimaryDisplay::DISPLAY_ID::get(), primaryDisplaySnapshotRef.get().displayId());
+ EXPECT_EQ(*primaryDisplayId, primaryDisplaySnapshotRef.get().displayId());
EXPECT_EQ(PrimaryDisplay::PORT::value, primaryDisplaySnapshotRef.get().port());
EXPECT_EQ(PrimaryDisplay::CONNECTION_TYPE::value,
primaryDisplaySnapshotRef.get().connectionType());
EXPECT_TRUE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
- EXPECT_TRUE(mFlinger.getHwComposer().isConnected(ExternalDisplay::DISPLAY_ID::get()));
+ const auto externalDisplayId = asPhysicalDisplayId(ExternalDisplay::DISPLAY_ID::get());
+ ASSERT_TRUE(externalDisplayId);
+ EXPECT_TRUE(mFlinger.getHwComposer().isConnected(*externalDisplayId));
const auto externalDisplayIdOpt =
mFlinger.getHwComposer().toPhysicalDisplayId(ExternalDisplay::HWC_DISPLAY_ID);
ASSERT_TRUE(externalDisplayIdOpt.has_value());
@@ -112,7 +116,7 @@
mFlinger.physicalDisplays().get(externalDisplayIdOpt.value());
ASSERT_TRUE(externalPhysicalDisplayOpt.has_value());
const auto externalDisplaySnapshotRef = externalPhysicalDisplayOpt->get().snapshotRef();
- EXPECT_EQ(ExternalDisplay::DISPLAY_ID::get(), externalDisplaySnapshotRef.get().displayId());
+ EXPECT_EQ(*externalDisplayId, externalDisplaySnapshotRef.get().displayId());
EXPECT_EQ(ExternalDisplay::PORT::value, externalDisplaySnapshotRef.get().port());
EXPECT_EQ(ExternalDisplay::CONNECTION_TYPE::value,
externalDisplaySnapshotRef.get().connectionType());
@@ -154,8 +158,8 @@
constexpr PhysicalDisplayId primaryInternalDisplayId =
PhysicalDisplayId::fromPort(primaryInternalDisplayPort);
EXPECT_TRUE(hasPhysicalHwcDisplay(PrimaryDisplay::HWC_DISPLAY_ID));
- ASSERT_EQ(primaryInternalDisplayId, PrimaryDisplay::DISPLAY_ID::get());
- EXPECT_TRUE(mFlinger.getHwComposer().isConnected(PrimaryDisplay::DISPLAY_ID::get()));
+ ASSERT_EQ(primaryInternalDisplayId, asPhysicalDisplayId(PrimaryDisplay::DISPLAY_ID::get()));
+ EXPECT_TRUE(mFlinger.getHwComposer().isConnected(primaryInternalDisplayId));
const auto primaryDisplayIdOpt =
mFlinger.getHwComposer().toPhysicalDisplayId(PrimaryDisplay::HWC_DISPLAY_ID);
ASSERT_TRUE(primaryDisplayIdOpt.has_value());
@@ -220,7 +224,9 @@
// The display should be scheduled for removal during the next commit. At this point, it should
// still exist but be marked as disconnected.
EXPECT_TRUE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
- EXPECT_FALSE(mFlinger.getHwComposer().isConnected(ExternalDisplay::DISPLAY_ID::get()));
+ const auto externalDisplayId = asPhysicalDisplayId(ExternalDisplay::DISPLAY_ID::get());
+ ASSERT_TRUE(externalDisplayId);
+ EXPECT_FALSE(mFlinger.getHwComposer().isConnected(*externalDisplayId));
}
TEST_F(HotplugTest, rejectsHotplugIfFailedToLoadDisplayModes) {
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp
index a1e37ff..2332bf6 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp
@@ -17,6 +17,7 @@
#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"
+#include <android_companion_virtualdevice_flags.h>
#include <com_android_graphics_surfaceflinger_flags.h>
#include <common/test/FlagUtils.h>
#include "DisplayTransactionTestHelpers.h"
@@ -78,11 +79,19 @@
struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant {
static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1);
+ setupDisableSyntheticVsyncCallExpectations(test);
+ }
+
+ static void setupDisableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0);
}
static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1);
+ setupEnableSyntheticVsyncCallExpectations(test);
+ }
+
+ static void setupEnableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0);
}
};
@@ -91,12 +100,20 @@
static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) {
// Expect to enable hardware VSYNC and disable synthetic VSYNC.
EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1);
+ setupDisableSyntheticVsyncCallExpectations(test);
+ }
+
+ static void setupDisableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(false)).Times(1);
}
static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) {
// Expect to disable hardware VSYNC and enable synthetic VSYNC.
EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1);
+ setupEnableSyntheticVsyncCallExpectations(test);
+ }
+
+ static void setupEnableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(true)).Times(1);
}
};
@@ -151,7 +168,7 @@
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND);
- Case::EventThread::setupVsyncNoCallExpectations(test);
+ Case::EventThread::setupEnableSyntheticVsyncCallExpectations(test);
Case::setupRepaintEverythingCallExpectations(test);
}
@@ -176,7 +193,7 @@
: public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::OFF> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
- Case::EventThread::setupVsyncNoCallExpectations(test);
+ Case::EventThread::setupEnableSyntheticVsyncCallExpectations(test);
Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF);
}
@@ -188,7 +205,7 @@
struct TransitionOnToDozeVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
- Case::EventThread::setupVsyncNoCallExpectations(test);
+ Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test);
Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE);
}
};
@@ -206,7 +223,7 @@
struct TransitionDozeToOnVariant : public TransitionVariantCommon<PowerMode::DOZE, PowerMode::ON> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
- Case::EventThread::setupVsyncNoCallExpectations(test);
+ Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test);
Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
}
};
@@ -234,7 +251,7 @@
: public TransitionVariantCommon<PowerMode::ON, static_cast<PowerMode>(POWER_MODE_LEET)> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
- Case::EventThread::setupVsyncNoCallExpectations(test);
+ Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test);
Case::setupNoComposerPowerModeCallExpectations(test);
}
};
@@ -335,11 +352,13 @@
// --------------------------------------------------------------------
// Preconditions
+ SET_FLAG_FOR_TEST(android::companion::virtualdevice::flags::correct_virtual_display_power_state,
+ true);
+
Case::Doze::setupComposerCallExpectations(this);
auto display =
Case::injectDisplayWithInitialPowerMode(this, Case::Transition::INITIAL_POWER_MODE);
- auto displayId = display->getId();
- if (auto physicalDisplayId = PhysicalDisplayId::tryCast(displayId)) {
+ if (auto physicalDisplayId = asPhysicalDisplayId(display->getDisplayIdVariant())) {
Case::setInitialHwVsyncEnabled(this, *physicalDisplayId,
PowerModeInitialVSyncEnabled<
Case::Transition::INITIAL_POWER_MODE>::value);
@@ -393,9 +412,9 @@
// Preconditions
// Insert display data so that the HWC thinks it created the virtual display.
- const auto displayId = Case::Display::DISPLAY_ID::get();
- ASSERT_TRUE(HalVirtualDisplayId::tryCast(displayId));
- mFlinger.mutableHwcDisplayData().try_emplace(displayId);
+ const auto displayId = asHalDisplayId(Case::Display::DISPLAY_ID::get());
+ ASSERT_TRUE(displayId);
+ ASSERT_TRUE(mFlinger.mutableHwcDisplayData().try_emplace(*displayId).second);
// A virtual display device is set up
Case::Display::injectHwcDisplay(this);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
index cd554ea..23e73de 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -235,7 +235,7 @@
constexpr auto kConnectionTypeOpt = Case::Display::CONNECTION_TYPE::value;
if constexpr (kConnectionTypeOpt) {
- const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get());
+ const auto displayId = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
ASSERT_TRUE(displayId);
const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
ASSERT_TRUE(hwcDisplayId);
@@ -282,7 +282,7 @@
// Postconditions
ASSERT_NE(nullptr, device);
- EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId());
+ EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getDisplayIdVariant());
EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual());
EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index f0e2361..13c32bd 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -481,7 +481,7 @@
SurfaceFlinger::ScreenshotArgs screenshotArgs;
screenshotArgs.captureTypeVariant = display;
- screenshotArgs.displayId = std::nullopt;
+ screenshotArgs.displayIdVariant = std::nullopt;
screenshotArgs.sourceCrop = sourceCrop;
screenshotArgs.reqSize = sourceCrop.getSize();
screenshotArgs.dataspace = dataspace;
@@ -573,7 +573,7 @@
}
sp<DisplayDevice> createVirtualDisplayDevice(const sp<IBinder> displayToken,
- VirtualDisplayId displayId,
+ GpuVirtualDisplayId displayId,
float requestedRefreshRate) {
constexpr ui::Size kResolution = {1080, 1920};
auto compositionDisplay = compositionengine::impl::
@@ -817,9 +817,11 @@
static constexpr int32_t DEFAULT_DPI = 320;
static constexpr hal::HWConfigId DEFAULT_ACTIVE_CONFIG = 0;
- FakeHwcDisplayInjector(HalDisplayId displayId, hal::DisplayType hwcDisplayType,
+ FakeHwcDisplayInjector(DisplayIdVariant displayIdVariant, hal::DisplayType hwcDisplayType,
bool isPrimary)
- : mDisplayId(displayId), mHwcDisplayType(hwcDisplayType), mIsPrimary(isPrimary) {}
+ : mDisplayIdVariant(displayIdVariant),
+ mHwcDisplayType(hwcDisplayType),
+ mIsPrimary(isPrimary) {}
auto& setHwcDisplayId(hal::HWDisplayId displayId) {
mHwcDisplayId = displayId;
@@ -884,7 +886,9 @@
display->setPowerMode(mPowerMode);
- flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display);
+ const auto halDisplayId = asHalDisplayId(mDisplayIdVariant);
+ ASSERT_TRUE(halDisplayId);
+ flinger->mutableHwcDisplayData()[*halDisplayId].hwcDisplay = std::move(display);
EXPECT_CALL(*composer, getDisplayConfigs(mHwcDisplayId, _))
.WillRepeatedly(
@@ -922,9 +926,10 @@
DoAll(SetArgPointee<3>(mConfigGroup), Return(hal::Error::NONE)));
if (mHwcDisplayType == hal::DisplayType::PHYSICAL) {
- const auto physicalId = PhysicalDisplayId::tryCast(mDisplayId);
- LOG_ALWAYS_FATAL_IF(!physicalId);
- flinger->mutableHwcPhysicalDisplayIdMap().emplace(mHwcDisplayId, *physicalId);
+ const auto physicalDisplayId = asPhysicalDisplayId(mDisplayIdVariant);
+ ASSERT_TRUE(physicalDisplayId);
+ flinger->mutableHwcPhysicalDisplayIdMap().emplace(mHwcDisplayId,
+ *physicalDisplayId);
if (mIsPrimary) {
flinger->mutablePrimaryHwcDisplayId() = mHwcDisplayId;
} else {
@@ -937,7 +942,7 @@
}
private:
- const HalDisplayId mDisplayId;
+ const DisplayIdVariant mDisplayIdVariant;
const hal::DisplayType mHwcDisplayType;
const bool mIsPrimary;
@@ -973,8 +978,8 @@
sp<IBinder> token() const { return mDisplayToken; }
auto physicalDisplay() const {
- return ftl::Optional(mCreationArgs.compositionDisplay->getDisplayId())
- .and_then(&PhysicalDisplayId::tryCast)
+ return mCreationArgs.compositionDisplay->getDisplayIdVariant()
+ .and_then(asPhysicalDisplayId)
.and_then(display::getPhysicalDisplay(mFlinger.physicalDisplays()));
}
@@ -1072,7 +1077,9 @@
DisplayDeviceState state;
state.isSecure = mCreationArgs.isSecure;
- if (const auto physicalId = PhysicalDisplayId::tryCast(*displayId)) {
+ if (const auto physicalId =
+ mCreationArgs.compositionDisplay->getDisplayIdVariant().and_then(
+ asPhysicalDisplayId)) {
LOG_ALWAYS_FATAL_IF(!mConnectionType);
LOG_ALWAYS_FATAL_IF(!mHwcDisplayId);