Merge "Use a strongly typed LogicalDisplayId for displayId(2/n)" into main
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index b1ab7b0..2929bce 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -718,9 +718,17 @@
* When registering the interface, add:
* std::shared_ptr<MyFoo> foo = new MyFoo; // class in AOSP codebase
* std::shared_ptr<MyBar> bar = new MyBar; // custom extension class
- * ... = AIBinder_setExtension(foo->asBinder().get(), bar->asBinder().get());
+ * SpAIBinder binder = foo->asBinder(); // target binder to extend
+ * ... = AIBinder_setExtension(binder.get(), bar->asBinder().get());
+ * ... = AServiceManager_addService(binder.get(), instanceName);
* // handle error
*
+ * Do not use foo->asBinder().get() as the target binder argument to
+ * AIBinder_setExtensions because asBinder it creates a new binder
+ * object that will be destroyed after the function is called. The same
+ * binder object must be used for AIBinder_setExtension and
+ * AServiceManager_addService to register the service with an extension.
+ *
* Then, clients of IFoo can get this extension:
* SpAIBinder binder = ...;
* std::shared_ptr<IFoo> foo = IFoo::fromBinder(binder); // handle if null
diff --git a/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs b/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs
index 73a15be..82f528e 100644
--- a/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs
+++ b/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//!
-
use crate::{
buffers::BufferPool, subscriptions::SharedBufferSubscription, BufferPublisher,
BufferSubscriber, Frame, StreamConfig,
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 5c4b889..560166c 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -16,13 +16,6 @@
}
flag {
- name: "enable_pointer_choreographer"
- namespace: "input"
- description: "Set to true to enable PointerChoreographer: the new pipeline for showing pointer icons"
- bug: "293587049"
-}
-
-flag {
name: "enable_gestures_library_timer_provider"
namespace: "input"
description: "Set to true to enable timer support for the touchpad Gestures library"
diff --git a/services/sensorservice/senserservice_flags.aconfig b/services/sensorservice/senserservice_flags.aconfig
index 8d43f79..f20b213 100644
--- a/services/sensorservice/senserservice_flags.aconfig
+++ b/services/sensorservice/senserservice_flags.aconfig
@@ -13,4 +13,11 @@
namespace: "sensors"
description: "This flag controls if the callback onDynamicSensorsDisconnected is implemented or not."
bug: "316958439"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "sensor_event_connection_send_event_require_nonnull_scratch"
+ namespace: "sensors"
+ description: "This flag controls we allow to pass in nullptr as scratch in SensorEventConnection::sendEvents()"
+ bug: "339306599"
+}
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 96d5ca6..6c1a813 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -46,10 +46,21 @@
namespace impl {
using aidl::android::hardware::power::Boost;
+using aidl::android::hardware::power::ChannelConfig;
using aidl::android::hardware::power::Mode;
using aidl::android::hardware::power::SessionHint;
using aidl::android::hardware::power::SessionTag;
using aidl::android::hardware::power::WorkDuration;
+using aidl::android::hardware::power::WorkDurationFixedV1;
+
+using aidl::android::hardware::common::fmq::MQDescriptor;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using aidl::android::hardware::power::ChannelMessage;
+using android::hardware::EventFlag;
+
+using ChannelMessageContents = ChannelMessage::ChannelMessageContents;
+using MsgQueue = android::AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>;
+using FlagQueue = android::AidlMessageQueue<int8_t, SynchronizedReadWrite>;
PowerAdvisor::~PowerAdvisor() = default;
@@ -140,15 +151,7 @@
if (!mBootFinished.load()) {
return;
}
- if (usePowerHintSession()) {
- std::lock_guard lock(mHintSessionMutex);
- if (ensurePowerHintSessionRunning()) {
- auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_UP);
- if (!ret.isOk()) {
- mHintSession = nullptr;
- }
- }
- }
+ sendHintSessionHint(SessionHint::CPU_LOAD_UP);
}
void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
@@ -160,15 +163,7 @@
if (mSendUpdateImminent.exchange(false)) {
ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
- if (usePowerHintSession()) {
- std::lock_guard lock(mHintSessionMutex);
- if (ensurePowerHintSessionRunning()) {
- auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_RESET);
- if (!ret.isOk()) {
- mHintSession = nullptr;
- }
- }
- }
+ sendHintSessionHint(SessionHint::CPU_LOAD_RESET);
if (!mHasDisplayUpdateImminent) {
ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
@@ -210,6 +205,30 @@
FlagManager::getInstance().adpf_use_fmq_channel();
}
+void PowerAdvisor::sendHintSessionHint(SessionHint hint) {
+ if (!mBootFinished || !usePowerHintSession()) {
+ ALOGV("Power hint session is not enabled, skip sending session hint");
+ return;
+ }
+ ATRACE_CALL();
+ if (sTraceHintSessionData) ATRACE_INT("Session hint", static_cast<int>(hint));
+ {
+ std::scoped_lock lock(mHintSessionMutex);
+ if (!ensurePowerHintSessionRunning()) {
+ ALOGV("Hint session not running and could not be started, skip sending session hint");
+ return;
+ }
+ ALOGV("Sending session hint: %d", static_cast<int>(hint));
+ if (!writeHintSessionMessage<ChannelMessageContents::Tag::hint>(&hint, 1)) {
+ auto ret = mHintSession->sendHint(hint);
+ if (!ret.isOk()) {
+ ALOGW("Failed to send session hint with error: %s", ret.errorMessage());
+ mHintSession = nullptr;
+ }
+ }
+ }
+}
+
bool PowerAdvisor::ensurePowerHintSessionRunning() {
if (mHintSession == nullptr && !mHintSessionThreadIds.empty() && usePowerHintSession()) {
if (shouldCreateSessionWithConfig()) {
@@ -221,6 +240,9 @@
&mSessionConfig);
if (ret.isOk()) {
mHintSession = ret.value();
+ if (FlagManager::getInstance().adpf_use_fmq_channel_fixed()) {
+ setUpFmq();
+ }
}
// If it fails the first time we try, or ever returns unsupported, assume unsupported
else if (mFirstConfigSupportCheck || ret.isUnsupported()) {
@@ -241,9 +263,36 @@
return mHintSession != nullptr;
}
+void PowerAdvisor::setUpFmq() {
+ auto&& channelRet = getPowerHal().getSessionChannel(getpid(), static_cast<int32_t>(getuid()));
+ if (!channelRet.isOk()) {
+ ALOGE("Failed to get session channel with error: %s", channelRet.errorMessage());
+ return;
+ }
+ auto& channelConfig = channelRet.value();
+ mMsgQueue = std::make_unique<MsgQueue>(std::move(channelConfig.channelDescriptor), true);
+ LOG_ALWAYS_FATAL_IF(!mMsgQueue->isValid(), "Failed to set up hint session msg queue");
+ LOG_ALWAYS_FATAL_IF(channelConfig.writeFlagBitmask <= 0,
+ "Invalid flag bit masks found in channel config: writeBitMask(%d)",
+ channelConfig.writeFlagBitmask);
+ mFmqWriteMask = static_cast<uint32_t>(channelConfig.writeFlagBitmask);
+ if (!channelConfig.eventFlagDescriptor.has_value()) {
+ // For FMQ v1 in Android 15 we will force using shared event flag since the default
+ // no-op FMQ impl in Power HAL v5 will always return a valid channel config with
+ // non-zero masks but no shared flag.
+ mMsgQueue = nullptr;
+ ALOGE("No event flag descriptor found in channel config");
+ return;
+ }
+ mFlagQueue = std::make_unique<FlagQueue>(std::move(*channelConfig.eventFlagDescriptor), true);
+ LOG_ALWAYS_FATAL_IF(!mFlagQueue->isValid(), "Failed to set up hint session flag queue");
+ auto status = EventFlag::createEventFlag(mFlagQueue->getEventFlagWord(), &mEventFlag);
+ LOG_ALWAYS_FATAL_IF(status != OK, "Failed to set up hint session event flag");
+}
+
void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) {
if (!mBootFinished || !usePowerHintSession()) {
- ALOGV("Power hint session target duration cannot be set, skipping");
+ ALOGV("Power hint session is not enabled, skipping target update");
return;
}
ATRACE_CALL();
@@ -251,10 +300,15 @@
mTargetDuration = targetDuration;
if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
if (targetDuration == mLastTargetDurationSent) return;
- std::lock_guard lock(mHintSessionMutex);
- if (ensurePowerHintSessionRunning()) {
- ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
- mLastTargetDurationSent = targetDuration;
+ std::scoped_lock lock(mHintSessionMutex);
+ if (!ensurePowerHintSessionRunning()) {
+ ALOGV("Hint session not running and could not be started, skip updating target");
+ return;
+ }
+ ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
+ mLastTargetDurationSent = targetDuration;
+ auto target = targetDuration.ns();
+ if (!writeHintSessionMessage<ChannelMessageContents::Tag::targetDuration>(&target, 1)) {
auto ret = mHintSession->updateTargetWorkDuration(targetDuration.ns());
if (!ret.isOk()) {
ALOGW("Failed to set power hint target work duration with error: %s",
@@ -302,23 +356,73 @@
}
{
- std::lock_guard lock(mHintSessionMutex);
+ std::scoped_lock lock(mHintSessionMutex);
if (!ensurePowerHintSessionRunning()) {
- ALOGV("Hint session not running and could not be started, skipping");
+ ALOGV("Hint session not running and could not be started, skip reporting durations");
return;
}
mHintSessionQueue.push_back(*actualDuration);
-
- auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue);
- if (!ret.isOk()) {
- ALOGW("Failed to report actual work durations with error: %s", ret.errorMessage());
- mHintSession = nullptr;
- return;
+ if (!writeHintSessionMessage<
+ ChannelMessageContents::Tag::workDuration>(mHintSessionQueue.data(),
+ mHintSessionQueue.size())) {
+ auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue);
+ if (!ret.isOk()) {
+ ALOGW("Failed to report actual work durations with error: %s", ret.errorMessage());
+ mHintSession = nullptr;
+ return;
+ }
}
}
mHintSessionQueue.clear();
}
+template <ChannelMessage::ChannelMessageContents::Tag T, class In>
+bool PowerAdvisor::writeHintSessionMessage(In* contents, size_t count) {
+ if (!mMsgQueue) {
+ ALOGV("Skip using FMQ with message tag %hhd as it's not supported", T);
+ return false;
+ }
+ auto availableSize = mMsgQueue->availableToWrite();
+ if (availableSize < count) {
+ ALOGW("Skip using FMQ with message tag %hhd as there isn't enough space", T);
+ return false;
+ }
+ MsgQueue::MemTransaction tx;
+ if (!mMsgQueue->beginWrite(count, &tx)) {
+ ALOGW("Failed to begin writing message with tag %hhd", T);
+ return false;
+ }
+ for (size_t i = 0; i < count; ++i) {
+ if constexpr (T == ChannelMessageContents::Tag::workDuration) {
+ const WorkDuration& duration = contents[i];
+ new (tx.getSlot(i)) ChannelMessage{
+ .sessionID = static_cast<int32_t>(mSessionConfig.id),
+ .timeStampNanos =
+ (i == count - 1) ? ::android::uptimeNanos() : duration.timeStampNanos,
+ .data = ChannelMessageContents::make<ChannelMessageContents::Tag::workDuration,
+ WorkDurationFixedV1>({
+ .durationNanos = duration.durationNanos,
+ .workPeriodStartTimestampNanos = duration.workPeriodStartTimestampNanos,
+ .cpuDurationNanos = duration.cpuDurationNanos,
+ .gpuDurationNanos = duration.gpuDurationNanos,
+ }),
+ };
+ } else {
+ new (tx.getSlot(i)) ChannelMessage{
+ .sessionID = static_cast<int32_t>(mSessionConfig.id),
+ .timeStampNanos = ::android::uptimeNanos(),
+ .data = ChannelMessageContents::make<T, In>(std::move(contents[i])),
+ };
+ }
+ }
+ if (!mMsgQueue->commitWrite(count)) {
+ ALOGW("Failed to send message with tag %hhd, fall back to binder call", T);
+ return false;
+ }
+ mEventFlag->wake(mFmqWriteMask);
+ return true;
+}
+
void PowerAdvisor::enablePowerHintSession(bool enabled) {
mHintSessionEnabled = enabled;
}
@@ -334,12 +438,14 @@
}
LOG_ALWAYS_FATAL_IF(mHintSessionThreadIds.empty(),
"No thread IDs provided to power hint session!");
- std::lock_guard lock(mHintSessionMutex);
- if (mHintSession != nullptr) {
- ALOGE("Cannot start power hint session: already running");
- return false;
+ {
+ std::scoped_lock lock(mHintSessionMutex);
+ if (mHintSession != nullptr) {
+ ALOGE("Cannot start power hint session: already running");
+ return false;
+ }
+ return ensurePowerHintSessionRunning();
}
- return ensurePowerHintSessionRunning();
}
bool PowerAdvisor::supportsGpuReporting() {
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 161ca63..bc4a41b 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -29,6 +29,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#include <aidl/android/hardware/power/IPower.h>
+#include <fmq/AidlMessageQueue.h>
#include <powermanager/PowerHalController.h>
#pragma clang diagnostic pop
@@ -237,6 +238,7 @@
bool shouldCreateSessionWithConfig() REQUIRES(mHintSessionMutex);
bool ensurePowerHintSessionRunning() REQUIRES(mHintSessionMutex);
+ void setUpFmq() REQUIRES(mHintSessionMutex);
std::unordered_map<DisplayId, DisplayTimingData> mDisplayTimingData;
// Current frame's delay
Duration mFrameDelayDuration{0ns};
@@ -272,6 +274,15 @@
bool mHasDisplayUpdateImminent = true;
// Queue of actual durations saved to report
std::vector<aidl::android::hardware::power::WorkDuration> mHintSessionQueue;
+ std::unique_ptr<::android::AidlMessageQueue<
+ aidl::android::hardware::power::ChannelMessage,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>>
+ mMsgQueue GUARDED_BY(mHintSessionMutex);
+ std::unique_ptr<::android::AidlMessageQueue<
+ int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>>
+ mFlagQueue GUARDED_BY(mHintSessionMutex);
+ android::hardware::EventFlag* mEventFlag;
+ uint32_t mFmqWriteMask;
// The latest values we have received for target and actual
Duration mTargetDuration = kDefaultTargetDuration;
// The list of thread ids, stored so we can restart the session from this class if needed
@@ -306,6 +317,12 @@
// How long we expect hwc to run after the present call until it waits for the fence
static constexpr const Duration kFenceWaitStartDelayValidated{150us};
static constexpr const Duration kFenceWaitStartDelaySkippedValidate{250us};
+
+ void sendHintSessionHint(aidl::android::hardware::power::SessionHint hint);
+
+ template <aidl::android::hardware::power::ChannelMessage::ChannelMessageContents::Tag T,
+ class In>
+ bool writeHintSessionMessage(In* elements, size_t count) REQUIRES(mHintSessionMutex);
};
} // namespace impl
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 2ec20ad..2b4e234 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -279,14 +279,6 @@
const Rect sampledBounds = sampleRegion.bounds();
constexpr bool kHintForSeamlessTransition = false;
- SurfaceFlinger::RenderAreaFuture renderAreaFuture = ftl::defer([=] {
- DisplayRenderAreaBuilder displayRenderArea(sampledBounds, sampledBounds.getSize(),
- ui::Dataspace::V0_SRGB,
- kHintForSeamlessTransition,
- true /* captureSecureLayers */, displayWeak);
- return displayRenderArea.build();
- });
-
std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
auto layerFilterFn = [&](const char* layerName, uint32_t layerId, const Rect& bounds,
@@ -381,8 +373,14 @@
constexpr bool kIsProtected = false;
if (const auto fenceResult =
- mFlinger.captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, buffer,
- kRegionSampling, kGrayscale, kIsProtected, nullptr)
+ mFlinger.captureScreenshot(SurfaceFlinger::RenderAreaBuilderVariant(
+ std::in_place_type<DisplayRenderAreaBuilder>,
+ sampledBounds, sampledBounds.getSize(),
+ ui::Dataspace::V0_SRGB,
+ kHintForSeamlessTransition,
+ true /* captureSecureLayers */, displayWeak),
+ getLayerSnapshots, buffer, kRegionSampling, kGrayscale,
+ kIsProtected, nullptr)
.get();
fenceResult.ok()) {
fenceResult.value()->waitForever(LOG_TAG);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 496185e..0d2e514 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -7899,13 +7899,6 @@
}
}
- RenderAreaFuture renderAreaFuture = ftl::defer([=] {
- DisplayRenderAreaBuilder displayRenderArea(args.sourceCrop, reqSize, args.dataspace,
- args.hintForSeamlessTransition,
- args.captureSecureLayers, displayWeak);
- return displayRenderArea.build();
- });
-
GetLayerSnapshotsFunction getLayerSnapshots;
if (mLayerLifecycleManagerEnabled) {
getLayerSnapshots =
@@ -7918,8 +7911,12 @@
getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
}
- captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat,
- args.allowProtected, args.grayscale, captureListener);
+ captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
+ args.sourceCrop, reqSize, args.dataspace,
+ args.hintForSeamlessTransition,
+ args.captureSecureLayers, displayWeak),
+ getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected,
+ args.grayscale, captureListener);
}
void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args,
@@ -7955,13 +7952,6 @@
return;
}
- RenderAreaFuture renderAreaFuture = ftl::defer([=] {
- DisplayRenderAreaBuilder displayRenderArea(Rect(), size, args.dataspace,
- args.hintForSeamlessTransition,
- false /* captureSecureLayers */, displayWeak);
- return displayRenderArea.build();
- });
-
GetLayerSnapshotsFunction getLayerSnapshots;
if (mLayerLifecycleManagerEnabled) {
getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID,
@@ -7982,8 +7972,12 @@
constexpr bool kAllowProtected = false;
constexpr bool kGrayscale = false;
- captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size, args.pixelFormat,
- kAllowProtected, kGrayscale, captureListener);
+ captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
+ Rect(), size, args.dataspace,
+ args.hintForSeamlessTransition,
+ false /* captureSecureLayers */, displayWeak),
+ getLayerSnapshots, size, args.pixelFormat, kAllowProtected, kGrayscale,
+ captureListener);
}
ScreenCaptureResults SurfaceFlinger::captureLayersSync(const LayerCaptureArgs& args) {
@@ -8064,22 +8058,6 @@
return;
}
- RenderAreaFuture renderAreaFuture = ftl::defer(
- [=, this]() FTL_FAKE_GUARD(kMainThreadContext) -> std::unique_ptr<RenderArea> {
- LayerRenderAreaBuilder layerRenderArea(crop, reqSize, dataspace,
- args.captureSecureLayers,
- args.hintForSeamlessTransition, parent,
- args.childrenOnly);
-
- frontend::LayerSnapshot* snapshot =
- mLayerSnapshotBuilder.getSnapshot(parent->getSequence());
- if (!snapshot) {
- ALOGW("Couldn't find layer snapshot for %d", parent->getSequence());
- } else {
- layerRenderArea.setLayerInfo(snapshot);
- }
- return layerRenderArea.build();
- });
GetLayerSnapshotsFunction getLayerSnapshots;
if (mLayerLifecycleManagerEnabled) {
std::optional<FloatRect> parentCrop = std::nullopt;
@@ -8122,8 +8100,12 @@
return;
}
- captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat,
- args.allowProtected, args.grayscale, captureListener);
+ captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<LayerRenderAreaBuilder>, crop,
+ reqSize, dataspace, args.captureSecureLayers,
+ args.hintForSeamlessTransition, parent,
+ args.childrenOnly),
+ getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected,
+ args.grayscale, captureListener);
}
// Creates a Future release fence for a layer and keeps track of it in a list to
@@ -8150,7 +8132,7 @@
return protectedLayerFound;
}
-void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
+void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuilder,
GetLayerSnapshotsFunction getLayerSnapshots,
ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
bool allowProtected, bool grayscale,
@@ -8199,21 +8181,35 @@
renderengine::impl::ExternalTexture::Usage::
WRITEABLE);
auto futureFence =
- captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, texture,
+ captureScreenshot(renderAreaBuilder, getLayerSnapshots, texture,
false /* regionSampling */, grayscale, isProtected, captureListener);
futureFence.get();
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
- RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots,
+ RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshots,
const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
- auto takeScreenshotFn = [=, this, renderAreaFuture = std::move(renderAreaFuture)]() REQUIRES(
+ auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES(
kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
// LayerSnapshots must be obtained from the main thread.
auto layers = getLayerSnapshots();
+
+ if (auto* layerRenderAreaBuilder =
+ std::get_if<LayerRenderAreaBuilder>(&renderAreaBuilder)) {
+ // LayerSnapshotBuilder should only be accessed from the main thread.
+ frontend::LayerSnapshot* snapshot =
+ mLayerSnapshotBuilder.getSnapshot(layerRenderAreaBuilder->layer->getSequence());
+ if (!snapshot) {
+ ALOGW("Couldn't find layer snapshot for %d",
+ layerRenderAreaBuilder->layer->getSequence());
+ } else {
+ layerRenderAreaBuilder->setLayerInfo(snapshot);
+ }
+ }
+
if (FlagManager::getInstance().ce_fence_promise()) {
for (auto& [layer, layerFE] : layers) {
attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
@@ -8221,7 +8217,10 @@
}
ScreenCaptureResults captureResults;
- std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get();
+ std::unique_ptr<const RenderArea> renderArea =
+ std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); },
+ renderAreaBuilder);
+
if (!renderArea) {
ALOGW("Skipping screen capture because of invalid render area.");
if (captureListener) {
@@ -8232,8 +8231,8 @@
}
ftl::SharedFuture<FenceResult> renderFuture =
- renderScreenImpl(renderArea, buffer, regionSampling, grayscale, isProtected,
- captureResults, layers);
+ renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale,
+ isProtected, captureResults, layers);
if (captureListener) {
// Defer blocking on renderFuture back to the Binder thread.
@@ -8250,9 +8249,7 @@
};
// TODO(b/294936197): Run takeScreenshotsFn() in a binder thread to reduce the number
- // of calls on the main thread. renderAreaFuture runs on the main thread and should
- // no longer be a future, so that it does not need to make an additional jump on the
- // main thread whenever get() is called.
+ // of calls on the main thread.
auto future =
mScheduler->schedule(FTL_FAKE_GUARD(kMainThreadContext, std::move(takeScreenshotFn)));
@@ -8265,16 +8262,16 @@
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
- std::shared_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots,
+ std::unique_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots,
const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
bool grayscale, bool isProtected, ScreenCaptureResults& captureResults) {
auto layers = getLayerSnapshots();
- return renderScreenImpl(renderArea, buffer, regionSampling, grayscale, isProtected,
+ return renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale, isProtected,
captureResults, layers);
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
- std::shared_ptr<const RenderArea> renderArea,
+ std::unique_ptr<const RenderArea> renderArea,
const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
bool grayscale, bool isProtected, ScreenCaptureResults& captureResults,
std::vector<std::pair<Layer*, sp<android::LayerFE>>>& layers) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 2444424..4cb5aa3 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -192,6 +192,9 @@
Always,
};
+struct DisplayRenderAreaBuilder;
+struct LayerRenderAreaBuilder;
+
using DisplayColorSetting = compositionengine::OutputColorSetting;
class SurfaceFlinger : public BnSurfaceComposer,
@@ -383,7 +386,7 @@
using TransactionSchedule = scheduler::TransactionSchedule;
using GetLayerSnapshotsFunction = std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()>;
- using RenderAreaFuture = ftl::Future<std::unique_ptr<RenderArea>>;
+ using RenderAreaBuilderVariant = std::variant<DisplayRenderAreaBuilder, LayerRenderAreaBuilder>;
using DumpArgs = Vector<String16>;
using Dumper = std::function<void(const DumpArgs&, bool asProto, std::string&)>;
@@ -891,12 +894,12 @@
// Checks if a protected layer exists in a list of layers.
bool layersHasProtectedLayer(const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const;
- void captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction, ui::Size bufferSize,
- ui::PixelFormat, bool allowProtected, bool grayscale,
- const sp<IScreenCaptureListener>&);
+ void captureScreenCommon(RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
+ ui::Size bufferSize, ui::PixelFormat, bool allowProtected,
+ bool grayscale, const sp<IScreenCaptureListener>&);
ftl::SharedFuture<FenceResult> captureScreenshot(
- RenderAreaFuture, GetLayerSnapshotsFunction,
+ RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
bool grayscale, bool isProtected, const sp<IScreenCaptureListener>&);
@@ -904,13 +907,13 @@
// not yet been captured, and thus cannot yet be passed in as a parameter.
// Needed for TestableSurfaceFlinger.
ftl::SharedFuture<FenceResult> renderScreenImpl(
- std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction,
+ std::unique_ptr<const RenderArea>, GetLayerSnapshotsFunction,
const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
bool grayscale, bool isProtected, ScreenCaptureResults&) EXCLUDES(mStateLock)
REQUIRES(kMainThreadContext);
ftl::SharedFuture<FenceResult> renderScreenImpl(
- std::shared_ptr<const RenderArea>,
+ std::unique_ptr<const RenderArea>,
const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
bool grayscale, bool isProtected, ScreenCaptureResults&,
std::vector<std::pair<Layer*, sp<android::LayerFE>>>& layers) EXCLUDES(mStateLock)
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index f074b7d..45b3290 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -249,5 +249,6 @@
/// Trunk stable readonly flags from outside SurfaceFlinger ///
FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(idle_screen_refresh_rate_timeout, "",
com::android::server::display::feature::flags)
+FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(adpf_use_fmq_channel_fixed, "", android::os)
} // namespace android
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 0acf754..592e774 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -51,6 +51,7 @@
bool refresh_rate_overlay_on_external_display() const;
bool adpf_gpu_sf() const;
bool adpf_use_fmq_channel() const;
+ bool adpf_use_fmq_channel_fixed() const;
/// Trunk stable readonly flags ///
bool connected_display() const;
diff --git a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
index 86ad86e..e74f643 100644
--- a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
@@ -45,6 +45,7 @@
class PowerAdvisorTest : public testing::Test {
public:
void SetUp() override;
+ void SetUpFmq(bool usesSharedEventFlag, bool isQueueFull);
void startPowerHintSession(bool returnValidSession = true);
void fakeBasicFrameTiming(TimePoint startTime, Duration vsyncPeriod);
void setExpectedTiming(Duration totalFrameTargetDuration, TimePoint expectedPresentTime);
@@ -64,16 +65,26 @@
Duration postCompDuration = 0ms;
bool frame1RequiresRenderEngine;
bool frame2RequiresRenderEngine;
+ bool usesFmq = false;
+ bool usesSharedFmqFlag = true;
+ bool fmqFull = false;
};
- WorkDuration testGpuScenario(GpuTestConfig& config);
+ void testGpuScenario(GpuTestConfig& config, WorkDuration& ret);
protected:
TestableSurfaceFlinger mFlinger;
std::unique_ptr<PowerAdvisor> mPowerAdvisor;
MockPowerHalController* mMockPowerHalController;
std::shared_ptr<MockPowerHintSessionWrapper> mMockPowerHintSession;
+ std::shared_ptr<AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>> mBackendFmq;
+ std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> mBackendFlagQueue;
+ android::hardware::EventFlag* mEventFlag;
+ uint32_t mWriteFlagBitmask = 2;
+ uint32_t mReadFlagBitmask = 1;
+ int64_t mSessionId = 123;
SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel, true);
+ SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, false);
};
bool PowerAdvisorTest::sessionExists() {
@@ -95,12 +106,44 @@
ByMove(HalResult<int64_t>::fromStatus(ndk::ScopedAStatus::ok(), 16000))));
}
+void PowerAdvisorTest::SetUpFmq(bool usesSharedEventFlag, bool isQueueFull) {
+ mBackendFmq = std::make_shared<
+ AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>>(2, !usesSharedEventFlag);
+ ChannelConfig config;
+ config.channelDescriptor = mBackendFmq->dupeDesc();
+ if (usesSharedEventFlag) {
+ mBackendFlagQueue =
+ std::make_shared<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(1, true);
+ config.eventFlagDescriptor = mBackendFlagQueue->dupeDesc();
+ ASSERT_EQ(android::hardware::EventFlag::createEventFlag(mBackendFlagQueue
+ ->getEventFlagWord(),
+ &mEventFlag),
+ android::NO_ERROR);
+ } else {
+ ASSERT_EQ(android::hardware::EventFlag::createEventFlag(mBackendFmq->getEventFlagWord(),
+ &mEventFlag),
+ android::NO_ERROR);
+ }
+ config.writeFlagBitmask = static_cast<int32_t>(mWriteFlagBitmask);
+ config.readFlagBitmask = static_cast<int32_t>(mReadFlagBitmask);
+ ON_CALL(*mMockPowerHalController, getSessionChannel)
+ .WillByDefault(Return(
+ ByMove(HalResult<ChannelConfig>::fromStatus(Status::ok(), std::move(config)))));
+ startPowerHintSession();
+ if (isQueueFull) {
+ std::vector<ChannelMessage> msgs;
+ msgs.resize(2);
+ mBackendFmq->writeBlocking(msgs.data(), 2, mReadFlagBitmask, mWriteFlagBitmask,
+ std::chrono::nanoseconds(1ms).count(), mEventFlag);
+ }
+}
+
void PowerAdvisorTest::startPowerHintSession(bool returnValidSession) {
mMockPowerHintSession = std::make_shared<NiceMock<MockPowerHintSessionWrapper>>();
if (returnValidSession) {
ON_CALL(*mMockPowerHalController, createHintSessionWithConfig)
.WillByDefault(DoAll(SetArgPointee<5>(aidl::android::hardware::power::SessionConfig{
- .id = 12}),
+ .id = mSessionId}),
Return(HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
fromStatus(binder::Status::ok(),
mMockPowerHintSession))));
@@ -137,11 +180,17 @@
mPowerAdvisor->mDelayReportActualMutexAcquisitonPromise.set_value(true);
}
-WorkDuration PowerAdvisorTest::testGpuScenario(GpuTestConfig& config) {
+void PowerAdvisorTest::testGpuScenario(GpuTestConfig& config, WorkDuration& ret) {
SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_gpu_sf,
config.adpfGpuFlagOn);
+ SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, config.usesFmq);
mPowerAdvisor->onBootFinished();
- startPowerHintSession();
+ bool expectsFmqSuccess = config.usesSharedFmqFlag && !config.fmqFull;
+ if (config.usesFmq) {
+ SetUpFmq(config.usesSharedFmqFlag, config.fmqFull);
+ } else {
+ startPowerHintSession();
+ }
std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u), GpuVirtualDisplayId(0),
GpuVirtualDisplayId(1)};
@@ -150,8 +199,41 @@
// 60hz
TimePoint startTime = TimePoint::now();
+ int64_t target;
+ SessionHint hint;
+ if (!config.usesFmq || !expectsFmqSuccess) {
+ EXPECT_CALL(*mMockPowerHintSession, updateTargetWorkDuration(_))
+ .Times(1)
+ .WillOnce(DoAll(testing::SaveArg<0>(&target),
+ testing::Return(testing::ByMove(HalResult<void>::ok()))));
+ EXPECT_CALL(*mMockPowerHintSession, sendHint(_))
+ .Times(1)
+ .WillOnce(DoAll(testing::SaveArg<0>(&hint),
+ testing::Return(testing::ByMove(HalResult<void>::ok()))));
+ }
// advisor only starts on frame 2 so do an initial frame
fakeBasicFrameTiming(startTime, config.vsyncPeriod);
+ // send a load hint
+ mPowerAdvisor->notifyCpuLoadUp();
+ if (config.usesFmq && expectsFmqSuccess) {
+ std::vector<ChannelMessage> msgs;
+ ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
+ msgs.resize(2);
+ ASSERT_TRUE(mBackendFmq->readBlocking(msgs.data(), 2, mReadFlagBitmask, mWriteFlagBitmask,
+ std::chrono::nanoseconds(1ms).count(), mEventFlag));
+ ASSERT_EQ(msgs[0].sessionID, mSessionId);
+ ASSERT_GE(msgs[0].timeStampNanos, startTime.ns());
+ ASSERT_EQ(msgs[0].data.getTag(),
+ ChannelMessage::ChannelMessageContents::Tag::targetDuration);
+ target = msgs[0].data.get<ChannelMessage::ChannelMessageContents::Tag::targetDuration>();
+ ASSERT_EQ(msgs[1].sessionID, mSessionId);
+ ASSERT_GE(msgs[1].timeStampNanos, startTime.ns());
+ ASSERT_EQ(msgs[1].data.getTag(), ChannelMessage::ChannelMessageContents::Tag::hint);
+ hint = msgs[1].data.get<ChannelMessage::ChannelMessageContents::Tag::hint>();
+ }
+ ASSERT_EQ(target, config.vsyncPeriod.ns());
+ ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
+
setExpectedTiming(config.vsyncPeriod, startTime + config.vsyncPeriod);
// report GPU
@@ -171,6 +253,10 @@
std::this_thread::sleep_for(config.vsyncPeriod);
startTime = TimePoint::now();
fakeBasicFrameTiming(startTime, config.vsyncPeriod);
+ if (config.usesFmq && expectsFmqSuccess) {
+ // same target update will not trigger FMQ write
+ ASSERT_EQ(mBackendFmq->availableToRead(), 0uL);
+ }
setExpectedTiming(config.vsyncPeriod, startTime + config.vsyncPeriod);
// report GPU
@@ -192,14 +278,31 @@
mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime, startTime);
mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime, startTime);
- std::vector<aidl::android::hardware::power::WorkDuration> durationReq;
- EXPECT_CALL(*mMockPowerHintSession, reportActualWorkDuration(_))
- .Times(1)
- .WillOnce(DoAll(testing::SaveArg<0>(&durationReq),
- testing::Return(testing::ByMove(HalResult<void>::ok()))));
- mPowerAdvisor->reportActualWorkDuration();
- EXPECT_EQ(durationReq.size(), 1u);
- return durationReq[0];
+ if (config.usesFmq && expectsFmqSuccess) {
+ mPowerAdvisor->reportActualWorkDuration();
+ ASSERT_EQ(mBackendFmq->availableToRead(), 1uL);
+ std::vector<ChannelMessage> msgs;
+ msgs.resize(1);
+ ASSERT_TRUE(mBackendFmq->readBlocking(msgs.data(), 1, mReadFlagBitmask, mWriteFlagBitmask,
+ std::chrono::nanoseconds(1ms).count(), mEventFlag));
+ ASSERT_EQ(msgs[0].sessionID, mSessionId);
+ ASSERT_GE(msgs[0].timeStampNanos, startTime.ns());
+ ASSERT_EQ(msgs[0].data.getTag(), ChannelMessage::ChannelMessageContents::Tag::workDuration);
+ auto actual = msgs[0].data.get<ChannelMessage::ChannelMessageContents::Tag::workDuration>();
+ ret.workPeriodStartTimestampNanos = actual.workPeriodStartTimestampNanos;
+ ret.cpuDurationNanos = actual.cpuDurationNanos;
+ ret.gpuDurationNanos = actual.gpuDurationNanos;
+ ret.durationNanos = actual.durationNanos;
+ } else {
+ std::vector<aidl::android::hardware::power::WorkDuration> durationReq;
+ EXPECT_CALL(*mMockPowerHintSession, reportActualWorkDuration(_))
+ .Times(1)
+ .WillOnce(DoAll(testing::SaveArg<0>(&durationReq),
+ testing::Return(testing::ByMove(HalResult<void>::ok()))));
+ mPowerAdvisor->reportActualWorkDuration();
+ ASSERT_EQ(durationReq.size(), 1u);
+ ret = std::move(durationReq[0]);
+ }
}
Duration PowerAdvisorTest::getFenceWaitDelayDuration(bool skipValidate) {
@@ -375,13 +478,6 @@
mPowerAdvisor->reportActualWorkDuration();
}
-TEST_F(PowerAdvisorTest, hintSessionOnlyCreatedOnce) {
- EXPECT_CALL(*mMockPowerHalController, createHintSessionWithConfig(_, _, _, _, _, _)).Times(1);
- mPowerAdvisor->onBootFinished();
- startPowerHintSession();
- mPowerAdvisor->startPowerHintSession({1, 2, 3});
-}
-
TEST_F(PowerAdvisorTest, hintSessionTestNotifyReportRace) {
// notifyDisplayUpdateImminentAndCpuReset or notifyCpuLoadUp gets called in background
// reportActual gets called during callback and sees true session, passes ensure
@@ -464,15 +560,21 @@
}
TEST_F(PowerAdvisorTest, legacyHintSessionCreationStillWorks) {
- SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel, false);
mPowerAdvisor->onBootFinished();
mMockPowerHintSession = std::make_shared<NiceMock<MockPowerHintSessionWrapper>>();
+ EXPECT_CALL(*mMockPowerHalController, createHintSessionWithConfig)
+ .Times(1)
+ .WillOnce(Return(HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
+ fromStatus(ndk::ScopedAStatus::fromExceptionCode(
+ EX_UNSUPPORTED_OPERATION),
+ nullptr)));
+
EXPECT_CALL(*mMockPowerHalController, createHintSession)
.Times(1)
.WillOnce(Return(HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
fromStatus(binder::Status::ok(), mMockPowerHintSession)));
mPowerAdvisor->enablePowerHintSession(true);
- mPowerAdvisor->startPowerHintSession({1, 2, 3});
+ ASSERT_TRUE(mPowerAdvisor->startPowerHintSession({1, 2, 3}));
}
TEST_F(PowerAdvisorTest, setGpuFenceTime_cpuThenGpuFrames) {
@@ -487,7 +589,8 @@
.frame1RequiresRenderEngine = false,
.frame2RequiresRenderEngine = true,
};
- WorkDuration res = testGpuScenario(config);
+ WorkDuration res;
+ testGpuScenario(config, res);
EXPECT_EQ(res.gpuDurationNanos, 0L);
EXPECT_EQ(res.cpuDurationNanos, 0L);
EXPECT_GE(res.durationNanos, toNanos(30ms + getErrorMargin()));
@@ -505,7 +608,8 @@
.frame1RequiresRenderEngine = false,
.frame2RequiresRenderEngine = true,
};
- WorkDuration res = testGpuScenario(config);
+ WorkDuration res;
+ testGpuScenario(config, res);
EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
EXPECT_EQ(res.cpuDurationNanos, toNanos(10ms));
EXPECT_EQ(res.durationNanos, toNanos(30ms + getErrorMargin()));
@@ -523,7 +627,8 @@
.frame1RequiresRenderEngine = true,
.frame2RequiresRenderEngine = false,
};
- WorkDuration res = testGpuScenario(config);
+ WorkDuration res;
+ testGpuScenario(config, res);
EXPECT_EQ(res.gpuDurationNanos, 0L);
EXPECT_EQ(res.cpuDurationNanos, 0L);
EXPECT_EQ(res.durationNanos, toNanos(10ms + getErrorMargin()));
@@ -540,7 +645,8 @@
.frame1RequiresRenderEngine = true,
.frame2RequiresRenderEngine = false,
};
- WorkDuration res = testGpuScenario(config);
+ WorkDuration res;
+ testGpuScenario(config, res);
EXPECT_EQ(res.gpuDurationNanos, 0L);
EXPECT_EQ(res.cpuDurationNanos, toNanos(10ms));
EXPECT_EQ(res.durationNanos, toNanos(10ms + getErrorMargin()));
@@ -559,7 +665,8 @@
.frame1RequiresRenderEngine = true,
.frame2RequiresRenderEngine = true,
};
- WorkDuration res = testGpuScenario(config);
+ WorkDuration res;
+ testGpuScenario(config, res);
EXPECT_EQ(res.gpuDurationNanos, 0L);
EXPECT_EQ(res.cpuDurationNanos, 0L);
EXPECT_GE(res.durationNanos, toNanos(50ms + getErrorMargin()));
@@ -577,7 +684,8 @@
.frame1RequiresRenderEngine = true,
.frame2RequiresRenderEngine = true,
};
- WorkDuration res = testGpuScenario(config);
+ WorkDuration res;
+ testGpuScenario(config, res);
EXPECT_EQ(res.gpuDurationNanos, toNanos(50ms));
EXPECT_EQ(res.cpuDurationNanos, toNanos(10ms));
EXPECT_EQ(res.durationNanos, toNanos(50ms + getErrorMargin()));
@@ -594,7 +702,8 @@
.frame1RequiresRenderEngine = true,
.frame2RequiresRenderEngine = true,
};
- WorkDuration res = testGpuScenario(config);
+ WorkDuration res;
+ testGpuScenario(config, res);
EXPECT_EQ(res.gpuDurationNanos, 0L);
EXPECT_EQ(res.cpuDurationNanos, 0L);
EXPECT_GE(res.durationNanos, toNanos(30ms + getErrorMargin()));
@@ -612,11 +721,122 @@
.frame1RequiresRenderEngine = true,
.frame2RequiresRenderEngine = true,
};
- WorkDuration res = testGpuScenario(config);
+ WorkDuration res;
+ testGpuScenario(config, res);
EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
}
+TEST_F(PowerAdvisorTest, fmq_sendTargetAndActualDuration) {
+ GpuTestConfig config{
+ .adpfGpuFlagOn = true,
+ .frame1GpuFenceDuration = 30ms,
+ .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
+ .vsyncPeriod = 10ms,
+ .presentDuration = 22ms,
+ .postCompDuration = 88ms,
+ .frame1RequiresRenderEngine = true,
+ .frame2RequiresRenderEngine = true,
+ .usesFmq = true,
+ .usesSharedFmqFlag = true,
+ };
+ WorkDuration res;
+ testGpuScenario(config, res);
+ EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
+ EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
+ EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendTargetAndActualDuration_noSharedFlag) {
+ GpuTestConfig config{
+ .adpfGpuFlagOn = true,
+ .frame1GpuFenceDuration = 30ms,
+ .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
+ .vsyncPeriod = 10ms,
+ .presentDuration = 22ms,
+ .postCompDuration = 88ms,
+ .frame1RequiresRenderEngine = true,
+ .frame2RequiresRenderEngine = true,
+ .usesFmq = true,
+ .usesSharedFmqFlag = false,
+ };
+ WorkDuration res;
+ testGpuScenario(config, res);
+ EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
+ EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
+ EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendTargetAndActualDuration_queueFull) {
+ GpuTestConfig config{.adpfGpuFlagOn = true,
+ .frame1GpuFenceDuration = 30ms,
+ .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
+ .vsyncPeriod = 10ms,
+ .presentDuration = 22ms,
+ .postCompDuration = 88ms,
+ .frame1RequiresRenderEngine = true,
+ .frame2RequiresRenderEngine = true,
+ .usesFmq = true,
+ .usesSharedFmqFlag = true,
+ .fmqFull = true};
+ WorkDuration res;
+ testGpuScenario(config, res);
+ EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
+ EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
+ EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendHint) {
+ SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
+ mPowerAdvisor->onBootFinished();
+ SetUpFmq(true, false);
+ auto startTime = uptimeNanos();
+ mPowerAdvisor->notifyCpuLoadUp();
+ std::vector<ChannelMessage> msgs;
+ ASSERT_EQ(mBackendFmq->availableToRead(), 1uL);
+ msgs.resize(1);
+ ASSERT_TRUE(mBackendFmq->readBlocking(msgs.data(), 1, mReadFlagBitmask, mWriteFlagBitmask,
+ std::chrono::nanoseconds(1ms).count(), mEventFlag));
+ ASSERT_EQ(msgs[0].sessionID, mSessionId);
+ ASSERT_GE(msgs[0].timeStampNanos, startTime);
+ ASSERT_EQ(msgs[0].data.getTag(), ChannelMessage::ChannelMessageContents::Tag::hint);
+ auto hint = msgs[0].data.get<ChannelMessage::ChannelMessageContents::Tag::hint>();
+ ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendHint_noSharedFlag) {
+ SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
+ mPowerAdvisor->onBootFinished();
+ SetUpFmq(false, false);
+ SessionHint hint;
+ EXPECT_CALL(*mMockPowerHintSession, sendHint(_))
+ .Times(1)
+ .WillOnce(DoAll(testing::SaveArg<0>(&hint),
+ testing::Return(testing::ByMove(HalResult<void>::ok()))));
+ mPowerAdvisor->notifyCpuLoadUp();
+ ASSERT_EQ(mBackendFmq->availableToRead(), 0uL);
+ ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
+}
+
+TEST_F(PowerAdvisorTest, fmq_sendHint_queueFull) {
+ SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
+ mPowerAdvisor->onBootFinished();
+ SetUpFmq(true, true);
+ ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
+ SessionHint hint;
+ EXPECT_CALL(*mMockPowerHintSession, sendHint(_))
+ .Times(1)
+ .WillOnce(DoAll(testing::SaveArg<0>(&hint),
+ testing::Return(testing::ByMove(HalResult<void>::ok()))));
+ std::vector<ChannelMessage> msgs;
+ msgs.resize(1);
+ mBackendFmq->writeBlocking(msgs.data(), 1, mReadFlagBitmask, mWriteFlagBitmask,
+ std::chrono::nanoseconds(1ms).count(), mEventFlag);
+ mPowerAdvisor->notifyCpuLoadUp();
+ ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
+ ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
+}
+
} // namespace
} // namespace android::Hwc2::impl
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index a4c75a4..a0c1372 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -476,7 +476,7 @@
return mFlinger->setPowerModeInternal(display, mode);
}
- auto renderScreenImpl(std::shared_ptr<const RenderArea> renderArea,
+ auto renderScreenImpl(std::unique_ptr<const RenderArea> renderArea,
SurfaceFlinger::GetLayerSnapshotsFunction traverseLayers,
const std::shared_ptr<renderengine::ExternalTexture>& buffer,
bool regionSampling) {