diff options
13 files changed, 492 insertions, 143 deletions
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h index b1ab7b0f9a..2929bce897 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 @@ binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) __INT * 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 73a15be897..82f528e831 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 5c4b88912c..560166c2bd 100644 --- a/libs/input/input_flags.aconfig +++ b/libs/input/input_flags.aconfig @@ -16,13 +16,6 @@ flag { } 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 8d43f79950..f20b213823 100644 --- a/services/sensorservice/senserservice_flags.aconfig +++ b/services/sensorservice/senserservice_flags.aconfig @@ -13,4 +13,11 @@ flag { 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 96d5ca6155..6c1a81314d 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp @@ -46,10 +46,21 @@ PowerAdvisor::~PowerAdvisor() = default; 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 @@ void PowerAdvisor::notifyCpuLoadUp() { 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 @@ void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() { 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 @@ bool PowerAdvisor::shouldCreateSessionWithConfig() { 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 @@ bool PowerAdvisor::ensurePowerHintSessionRunning() { &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 @@ bool PowerAdvisor::ensurePowerHintSessionRunning() { 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 @@ void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) { 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 @@ void PowerAdvisor::reportActualWorkDuration() { } { - 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 @@ bool PowerAdvisor::startPowerHintSession(std::vector<int32_t>&& threadIds) { } 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 161ca6372a..bc4a41bf84 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 @@ private: 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 @@ private: 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 @@ private: // 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 2ec20ad5c2..2b4e234604 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -279,14 +279,6 @@ void RegionSamplingThread::captureSample() { 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 @@ void RegionSamplingThread::captureSample() { 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 496185e49b..0d2e5142bc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -7899,13 +7899,6 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, } } - 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 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, 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 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args 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 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args 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 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, 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 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, 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 @@ bool SurfaceFlinger::layersHasProtectedLayer( 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 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, 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 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot( } 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> SurfaceFlinger::captureScreenshot( } 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 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot( }; // 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::captureScreenshot( } 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 24444241c9..4cb5aa3da5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -192,6 +192,9 @@ enum class LatchUnsignaledConfig { Always, }; +struct DisplayRenderAreaBuilder; +struct LayerRenderAreaBuilder; + using DisplayColorSetting = compositionengine::OutputColorSetting; class SurfaceFlinger : public BnSurfaceComposer, @@ -383,7 +386,7 @@ private: 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 @@ private: // 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 @@ private: // 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 f074b7d48a..45b3290b2b 100644 --- a/services/surfaceflinger/common/FlagManager.cpp +++ b/services/surfaceflinger/common/FlagManager.cpp @@ -249,5 +249,6 @@ FLAG_MANAGER_SERVER_FLAG_IMPORTED(adpf_use_fmq_channel, "", android::os) /// 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 0acf754f34..592e7745c9 100644 --- a/services/surfaceflinger/common/include/common/FlagManager.h +++ b/services/surfaceflinger/common/include/common/FlagManager.h @@ -51,6 +51,7 @@ public: 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 86ad86eae2..e74f64305c 100644 --- a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp +++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp @@ -45,6 +45,7 @@ namespace android::Hwc2::impl { 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 @@ public: 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 @@ void PowerAdvisorTest::SetUp() { 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 @@ void PowerAdvisorTest::allowReportActualToAcquireMutex() { 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 @@ WorkDuration PowerAdvisorTest::testGpuScenario(GpuTestConfig& config) { // 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 @@ WorkDuration PowerAdvisorTest::testGpuScenario(GpuTestConfig& config) { 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 @@ WorkDuration PowerAdvisorTest::testGpuScenario(GpuTestConfig& config) { 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 @@ TEST_F(PowerAdvisorTest, hintSessionValidWhenNullFromPowerHAL) { 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, hintSessionTestNotifyReportRace) { } 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 @@ TEST_F(PowerAdvisorTest, setGpuFenceTime_cpuThenGpuFrames) { .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 @@ TEST_F(PowerAdvisorTest, setGpuFenceTime_cpuThenGpuFrames_flagOn) { .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 @@ TEST_F(PowerAdvisorTest, setGpuFenceTime_gpuThenCpuFrames) { .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 @@ TEST_F(PowerAdvisorTest, setGpuFenceTime_gpuThenCpuFrames_flagOn) { .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 @@ TEST_F(PowerAdvisorTest, setGpuFenceTime_twoSignaledGpuFrames) { .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 @@ TEST_F(PowerAdvisorTest, setGpuFenceTime_twoSignaledGpuFenceFrames_flagOn) { .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 @@ TEST_F(PowerAdvisorTest, setGpuFenceTime_UnsingaledGpuFenceFrameUsingPreviousFra .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 @@ TEST_F(PowerAdvisorTest, setGpuFenceTime_UnsingaledGpuFenceFrameUsingPreviousFra .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 a4c75a44ce..a0c13720c0 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -476,7 +476,7 @@ public: 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) { |