diff options
35 files changed, 341 insertions, 67 deletions
diff --git a/data/etc/Android.bp b/data/etc/Android.bp index e286a8405b..550b37482b 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -131,6 +131,24 @@ prebuilt_etc { } prebuilt_etc { + name: "android.hardware.se.omapi.ese.prebuilt.xml", + src: "android.hardware.se.omapi.ese.xml", + defaults: ["frameworks_native_data_etc_defaults"], +} + +prebuilt_etc { + name: "android.hardware.se.omapi.sd.prebuilt.xml", + src: "android.hardware.se.omapi.sd.xml", + defaults: ["frameworks_native_data_etc_defaults"], +} + +prebuilt_etc { + name: "android.hardware.se.omapi.uicc.prebuilt.xml", + src: "android.hardware.se.omapi.uicc.xml", + defaults: ["frameworks_native_data_etc_defaults"], +} + +prebuilt_etc { name: "android.hardware.sensor.accelerometer_limited_axes_uncalibrated.prebuilt.xml", src: "android.hardware.sensor.accelerometer_limited_axes_uncalibrated.xml", defaults: ["frameworks_native_data_etc_defaults"], diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index b2e8baade3..dfcf766402 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -146,7 +146,7 @@ public: #ifdef __linux__ /* Reads a key map from a parcel. */ - static std::shared_ptr<KeyCharacterMap> readFromParcel(Parcel* parcel); + static std::unique_ptr<KeyCharacterMap> readFromParcel(Parcel* parcel); /* Writes a key map to a parcel. */ void writeToParcel(Parcel* parcel) const; diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h index 89fd7a38c1..316a79cfee 100644 --- a/libs/binder/ndk/include_platform/android/binder_manager.h +++ b/libs/binder/ndk/include_platform/android/binder_manager.h @@ -120,7 +120,7 @@ binder_status_t AServiceManager_registerLazyService(AIBinder* binder, const char /** * Gets a binder object with this specific instance name. Efficiently waits for the service. - * If the service is not declared, it will wait indefinitely. Requires the threadpool + * If the service is not ever registered, it will wait indefinitely. Requires the threadpool * to be started in the service. * This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible * for calling AIBinder_decStrong). diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs index 3c615edbc0..f9f135d572 100644 --- a/libs/binder/rust/src/parcel.rs +++ b/libs/binder/rust/src/parcel.rs @@ -54,6 +54,10 @@ pub struct Parcel { /// Safety: This type guarantees that it owns the AParcel and that all access to /// the AParcel happens through the Parcel, so it is ok to send across threads. +/// +/// It would not be okay to implement Sync, because that would allow you to call +/// the reading methods from several threads in parallel, which would be a data +/// race on the cursor position inside the AParcel. unsafe impl Send for Parcel {} /// Container for a message (data and object references) that can be sent diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 5884dbe66f..1340ea1d2c 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -14,7 +14,10 @@ * limitations under the License. */ +#ifndef __ANDROID_VENDOR__ +// only used on NDK tests outside of vendor #include <aidl/IBinderRpcTest.h> +#endif #include <android-base/stringprintf.h> #include <chrono> diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp index f0beed234b..f367b419af 100644 --- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp +++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp @@ -66,6 +66,11 @@ void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOpti }, // write FD [&]() { + // b/296516864 - Limit number of objects written to a parcel. + if (p->objectsCount() > 100) { + return; + } + if (options->extraFds.size() > 0 && provider.ConsumeBool()) { const base::unique_fd& fd = options->extraFds.at( provider.ConsumeIntegralInRange<size_t>(0, @@ -82,7 +87,6 @@ void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOpti CHECK(OK == p->writeFileDescriptor(fds.begin()->release(), true /*takeOwnership*/)); - options->extraFds.insert(options->extraFds.end(), std::make_move_iterator(fds.begin() + 1), std::make_move_iterator(fds.end())); @@ -90,6 +94,11 @@ void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOpti }, // write binder [&]() { + // b/296516864 - Limit number of objects written to a parcel. + if (p->objectsCount() > 100) { + return; + } + sp<IBinder> binder; if (options->extraBinders.size() > 0 && provider.ConsumeBool()) { binder = options->extraBinders.at( diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 05e2ddf198..a3518110cd 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2604,7 +2604,7 @@ void SurfaceComposerClient::getDynamicDisplayInfoInternal(gui::DynamicDisplayInf outMode.resolution.height = mode.resolution.height; outMode.xDpi = mode.xDpi; outMode.yDpi = mode.yDpi; - outMode.refreshRate = mode.refreshRate; + outMode.peakRefreshRate = mode.peakRefreshRate; outMode.vsyncRate = mode.vsyncRate; outMode.appVsyncOffset = mode.appVsyncOffset; outMode.sfVsyncOffset = mode.sfVsyncOffset; diff --git a/libs/gui/aidl/android/gui/DisplayMode.aidl b/libs/gui/aidl/android/gui/DisplayMode.aidl index b057653200..f605177cfd 100644 --- a/libs/gui/aidl/android/gui/DisplayMode.aidl +++ b/libs/gui/aidl/android/gui/DisplayMode.aidl @@ -30,7 +30,7 @@ parcelable DisplayMode { int[] supportedHdrTypes; // Some modes have peak refresh rate lower than the panel vsync rate. - float refreshRate = 0.0f; + float peakRefreshRate = 0.0f; float vsyncRate = 0.0f; long appVsyncOffset = 0; long sfVsyncOffset = 0; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 662e9fe74a..d4b8dbeeb9 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -394,7 +394,7 @@ public: // After a new buffer is queued, SurfaceFlinger is notified and will // latch the new buffer on next vsync. Let's heuristically wait for 3 // vsyncs. - mBufferPostDelay = static_cast<int32_t>(1e6 / mode.refreshRate) * 3; + mBufferPostDelay = static_cast<int32_t>(1e6 / mode.peakRefreshRate) * 3; } void TearDown() { diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index a4cd239a92..e2feabcbbe 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -613,14 +613,14 @@ void KeyCharacterMap::addLockedMetaKey(Vector<KeyEvent>& outEvents, } #ifdef __linux__ -std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { +std::unique_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { if (parcel == nullptr) { ALOGE("%s: Null parcel", __func__); return nullptr; } std::string loadFileName = parcel->readCString(); - std::shared_ptr<KeyCharacterMap> map = - std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap(loadFileName)); + std::unique_ptr<KeyCharacterMap> map = + std::make_unique<KeyCharacterMap>(KeyCharacterMap(loadFileName)); map->mType = static_cast<KeyCharacterMap::KeyboardType>(parcel->readInt32()); map->mLayoutOverlayApplied = parcel->readBool(); size_t numKeys = parcel->readInt32(); diff --git a/libs/nativedisplay/ADisplay.cpp b/libs/nativedisplay/ADisplay.cpp index bf0805b46c..e3be3bc8f8 100644 --- a/libs/nativedisplay/ADisplay.cpp +++ b/libs/nativedisplay/ADisplay.cpp @@ -155,7 +155,7 @@ int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) { const ui::DisplayMode& mode = modes[j]; modesPerDisplay[i].emplace_back( DisplayConfigImpl{static_cast<size_t>(mode.id), mode.resolution.getWidth(), - mode.resolution.getHeight(), mode.refreshRate, + mode.resolution.getHeight(), mode.peakRefreshRate, mode.sfVsyncOffset, mode.appVsyncOffset}); } } diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h index a469c78070..ddb9bbd4bc 100644 --- a/libs/ui/include/ui/DisplayMode.h +++ b/libs/ui/include/ui/DisplayMode.h @@ -38,7 +38,7 @@ struct DisplayMode { std::vector<ui::Hdr> supportedHdrTypes; // Some modes have peak refresh rate lower than the panel vsync rate. - float refreshRate = 0.f; + float peakRefreshRate = 0.f; float vsyncRate = 0.f; nsecs_t appVsyncOffset = 0; nsecs_t sfVsyncOffset = 0; diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp index 1f17c165d5..016ae045a9 100644 --- a/services/inputflinger/InputListener.cpp +++ b/services/inputflinger/InputListener.cpp @@ -39,7 +39,7 @@ std::list<NotifyArgs>& operator+=(std::list<NotifyArgs>& keep, std::list<NotifyA // Helper to std::visit with lambdas. template <typename... V> -struct Visitor : V... {}; +struct Visitor : V... { using V::operator()...; }; // explicit deduction guide (not needed as of C++20) template <typename... V> Visitor(V...) -> Visitor<V...>; diff --git a/services/inputflinger/NotifyArgs.cpp b/services/inputflinger/NotifyArgs.cpp index c34cd5346e..de836e93a4 100644 --- a/services/inputflinger/NotifyArgs.cpp +++ b/services/inputflinger/NotifyArgs.cpp @@ -190,7 +190,7 @@ NotifyPointerCaptureChangedArgs::NotifyPointerCaptureChangedArgs( // Helper to std::visit with lambdas. template <typename... V> -struct Visitor : V... {}; +struct Visitor : V... { using V::operator()...; }; // explicit deduction guide (not needed as of C++20) template <typename... V> Visitor(V...) -> Visitor<V...>; diff --git a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp index be2bfed691..69264f84ed 100644 --- a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp +++ b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp @@ -239,7 +239,7 @@ namespace { // Helper to std::visit with lambdas. template <typename... V> -struct Visitor : V... {}; +struct Visitor : V... { using V::operator()...; }; // explicit deduction guide (not needed as of C++20) template <typename... V> Visitor(V...) -> Visitor<V...>; diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h index 892bb8f726..6807c8e5d7 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h @@ -147,6 +147,8 @@ public: MOCK_METHOD(const aidl::android::hardware::graphics::composer3::OverlayProperties&, getOverlaySupport, (), (const, override)); MOCK_METHOD(status_t, setRefreshRateChangedCallbackDebugEnabled, (PhysicalDisplayId, bool)); + MOCK_METHOD(status_t, notifyExpectedPresentIfRequired, + (PhysicalDisplayId, nsecs_t, int32_t, int32_t)); }; } // namespace mock diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp index 1f409c6ee7..1643ad0659 100644 --- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp @@ -1450,6 +1450,20 @@ Error AidlComposer::setRefreshRateChangedCallbackDebugEnabled(Display displayId, return Error::NONE; } +Error AidlComposer::notifyExpectedPresent(Display displayId, nsecs_t expectedPresentTime, + int32_t frameIntervalNs) { + const auto status = + mAidlComposerClient->notifyExpectedPresent(translate<int64_t>(displayId), + ClockMonotonicTimestamp{expectedPresentTime}, + frameIntervalNs); + + if (!status.isOk()) { + ALOGE("notifyExpectedPresent failed %s", status.getDescription().c_str()); + return static_cast<Error>(status.getServiceSpecificError()); + } + return Error::NONE; +} + Error AidlComposer::getClientTargetProperty( Display display, ClientTargetPropertyWithBrightness* outClientTargetProperty) { Error error = Error::NONE; diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h index b1b57a4528..7693a80a76 100644 --- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h @@ -240,6 +240,8 @@ public: Error getHdrConversionCapabilities(std::vector<HdrConversionCapability>*) override; Error setHdrConversionStrategy(HdrConversionStrategy, Hdr*) override; Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) override; + Error notifyExpectedPresent(Display, nsecs_t expectedPresentTime, + int32_t frameIntervalNs) override; private: // Many public functions above simply write a command into the command diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index e94258707b..6704d88696 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -298,6 +298,8 @@ public: virtual Error setHdrConversionStrategy( ::aidl::android::hardware::graphics::common::HdrConversionStrategy, Hdr*) = 0; virtual Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) = 0; + virtual Error notifyExpectedPresent(Display, nsecs_t expectedPresentTime, + int32_t frameIntervalNs) = 0; }; } // namespace Hwc2 diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 812621f40a..fb6089dfbe 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -31,6 +31,7 @@ #include <compositionengine/OutputLayer.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <ftl/concat.h> +#include <gui/TraceUtils.h> #include <log/log.h> #include <ui/DebugUtils.h> #include <ui/GraphicBuffer.h> @@ -484,6 +485,7 @@ status_t HWComposer::getDeviceCompositionChanges( }(); displayData.validateWasSkipped = false; + displayData.lastExpectedPresentTimestamp = expectedPresentTime; if (canSkipValidate) { sp<Fence> outPresentFence; uint32_t state = UINT32_MAX; @@ -876,6 +878,30 @@ status_t HWComposer::setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId return NO_ERROR; } +status_t HWComposer::notifyExpectedPresentIfRequired(PhysicalDisplayId displayId, + nsecs_t expectedPresentTime, + int32_t frameIntervalNs, int32_t timeoutNs) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + + auto& displayData = mDisplayData[displayId]; + if (expectedPresentTime >= displayData.lastExpectedPresentTimestamp && + expectedPresentTime < displayData.lastExpectedPresentTimestamp + timeoutNs) { + return NO_ERROR; + } + + displayData.lastExpectedPresentTimestamp = expectedPresentTime; + ATRACE_FORMAT("%s ExpectedPresentTime %" PRId64 " frameIntervalNs %d", __func__, + expectedPresentTime, frameIntervalNs); + const auto error = mComposer->notifyExpectedPresent(displayData.hwcDisplay->getId(), + expectedPresentTime, frameIntervalNs); + + if (error != hal::Error::NONE) { + ALOGE("Error in notifyExpectedPresent call %s", to_string(error).c_str()); + return INVALID_OPERATION; + } + return NO_ERROR; +} + status_t HWComposer::getDisplayDecorationSupport( PhysicalDisplayId displayId, std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>* diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index b4d3d28a35..726a8eafbf 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -60,6 +60,7 @@ namespace hal = hardware::graphics::composer::hal; struct DisplayedFrameStats; class GraphicBuffer; class TestableSurfaceFlinger; +struct HWComposerTest; struct CompositionInfo; namespace Hwc2 { @@ -300,6 +301,9 @@ public: aidl::android::hardware::graphics::common::HdrConversionStrategy, aidl::android::hardware::graphics::common::Hdr*) = 0; virtual status_t setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId, bool enabled) = 0; + virtual status_t notifyExpectedPresentIfRequired(PhysicalDisplayId, nsecs_t expectedPresentTime, + int32_t frameIntervalNs, + int32_t timeoutNs) = 0; }; static inline bool operator==(const android::HWComposer::DeviceRequestedChanges& lhs, @@ -458,6 +462,8 @@ public: aidl::android::hardware::graphics::common::HdrConversionStrategy, aidl::android::hardware::graphics::common::Hdr*) override; status_t setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId, bool enabled) override; + status_t notifyExpectedPresentIfRequired(PhysicalDisplayId, nsecs_t expectedPresentTime, + int32_t frameIntervalNs, int32_t timeoutNs) override; // for debugging ---------------------------------------------------------- void dump(std::string& out) const override; @@ -483,6 +489,7 @@ public: private: // For unit tests friend TestableSurfaceFlinger; + friend HWComposerTest; struct DisplayData { std::unique_ptr<HWC2::Display> hwcDisplay; @@ -490,6 +497,8 @@ private: sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires nsecs_t lastPresentTimestamp = 0; + nsecs_t lastExpectedPresentTimestamp = 0; + std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; bool validateWasSkipped; diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp index 70d48de75a..c13e568936 100644 --- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp @@ -1378,6 +1378,10 @@ Error HidlComposer::setRefreshRateChangedCallbackDebugEnabled(Display, bool) { return Error::UNSUPPORTED; } +Error HidlComposer::notifyExpectedPresent(Display, nsecs_t, int32_t) { + return Error::UNSUPPORTED; +} + Error HidlComposer::getClientTargetProperty( Display display, ClientTargetPropertyWithBrightness* outClientTargetProperty) { IComposerClient::ClientTargetProperty property; diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h index 26d22227ce..1004ddd011 100644 --- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h @@ -348,6 +348,7 @@ public: Error setHdrConversionStrategy(aidl::android::hardware::graphics::common::HdrConversionStrategy, Hdr*) override; Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) override; + Error notifyExpectedPresent(Display, nsecs_t, int32_t) override; private: class CommandWriter : public CommandWriterBase { diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp index c4c9fa56ff..f4676706fd 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp +++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp @@ -40,16 +40,18 @@ using base::StringAppendF; namespace { -nsecs_t getExpectedCallbackTime(nsecs_t nextVsyncTime, +nsecs_t getExpectedCallbackTime(nsecs_t now, nsecs_t nextVsyncTime, const VSyncDispatch::ScheduleTiming& timing) { - return nextVsyncTime - timing.readyDuration - timing.workDuration; + const auto expectedCallbackTime = nextVsyncTime - timing.readyDuration - timing.workDuration; + const auto baseTime = flags::dont_skip_on_early() ? now : expectedCallbackTime; + return std::max(baseTime, expectedCallbackTime); } nsecs_t getExpectedCallbackTime(VSyncTracker& tracker, nsecs_t now, const VSyncDispatch::ScheduleTiming& timing) { const auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom( std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration)); - return getExpectedCallbackTime(nextVsyncTime, timing); + return getExpectedCallbackTime(now, nextVsyncTime, timing); } } // namespace @@ -105,11 +107,11 @@ ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTim mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance))); if (flags::dont_skip_on_early()) { if (wouldSkipAVsyncTarget || wouldSkipAWakeup) { - return getExpectedCallbackTime(mArmedInfo->mActualVsyncTime, timing); + return getExpectedCallbackTime(now, mArmedInfo->mActualVsyncTime, timing); } } else { if (wouldSkipAVsyncTarget && wouldSkipAWakeup) { - return getExpectedCallbackTime(nextVsyncTime, timing); + return getExpectedCallbackTime(now, nextVsyncTime, timing); } } @@ -119,7 +121,7 @@ ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTim auto const nextReadyTime = nextVsyncTime - timing.readyDuration; mScheduleTiming = timing; mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime}; - return getExpectedCallbackTime(nextVsyncTime, timing); + return getExpectedCallbackTime(now, nextVsyncTime, timing); } void VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate(VSyncDispatch::ScheduleTiming timing) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9b9a67aa5f..fc517212ea 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -266,7 +266,7 @@ bool getKernelIdleTimerSyspropConfig(DisplayId displayId) { bool isAbove4k30(const ui::DisplayMode& outMode) { using fps_approx_ops::operator>; - Fps refreshRate = Fps::fromValue(outMode.refreshRate); + Fps refreshRate = Fps::fromValue(outMode.peakRefreshRate); return outMode.resolution.getWidth() >= FOUR_K_WIDTH && outMode.resolution.getHeight() >= FOUR_K_HEIGHT && refreshRate > 30_Hz; } @@ -1046,11 +1046,11 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info outMode.yDpi = yDpi; const auto peakFps = mode->getPeakFps(); - outMode.refreshRate = peakFps.getValue(); + outMode.peakRefreshRate = peakFps.getValue(); outMode.vsyncRate = mode->getVsyncRate().getValue(); - const auto vsyncConfigSet = - mVsyncConfiguration->getConfigsForRefreshRate(Fps::fromValue(outMode.refreshRate)); + const auto vsyncConfigSet = mVsyncConfiguration->getConfigsForRefreshRate( + Fps::fromValue(outMode.peakRefreshRate)); outMode.appVsyncOffset = vsyncConfigSet.late.appOffset; outMode.sfVsyncOffset = vsyncConfigSet.late.sfOffset; outMode.group = mode->getGroup(); @@ -9221,7 +9221,7 @@ void SurfaceComposerAIDL::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo& outMode.resolution.height = mode.resolution.height; outMode.xDpi = mode.xDpi; outMode.yDpi = mode.yDpi; - outMode.refreshRate = mode.refreshRate; + outMode.peakRefreshRate = mode.peakRefreshRate; outMode.vsyncRate = mode.vsyncRate; outMode.appVsyncOffset = mode.appVsyncOffset; outMode.sfVsyncOffset = mode.sfVsyncOffset; diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp index 66c8f33fe5..a7650783b4 100644 --- a/services/surfaceflinger/SurfaceFlingerProperties.cpp +++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp @@ -371,5 +371,9 @@ bool clear_slots_with_set_layer_buffer(bool defaultValue) { return SurfaceFlingerProperties::clear_slots_with_set_layer_buffer().value_or(defaultValue); } +int32_t game_default_frame_rate_override(int32_t defaultValue) { + return SurfaceFlingerProperties::game_default_frame_rate_override().value_or(defaultValue); +} + } // namespace sysprop } // namespace android diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h index a08042009b..65ebe2af21 100644 --- a/services/surfaceflinger/SurfaceFlingerProperties.h +++ b/services/surfaceflinger/SurfaceFlingerProperties.h @@ -101,6 +101,8 @@ bool ignore_hdr_camera_layers(bool defaultValue); bool clear_slots_with_set_layer_buffer(bool defaultValue); +int32_t game_default_frame_rate_override(int32_t defaultValue); + } // namespace sysprop } // namespace android #endif // SURFACEFLINGERPROPERTIES_H_ diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp index a22a778989..8978971539 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp @@ -23,12 +23,19 @@ namespace android::fuzz { using namespace google::protobuf; -constexpr size_t kMaxStringSize = 100; +constexpr size_t kMaxStringSize = 256; constexpr size_t kMinLayerIds = 1; constexpr size_t kMaxLayerIds = 10; +constexpr int32_t kMinRange = 0; constexpr int32_t kConfigDuration = 500; constexpr int32_t kBufferSize = 1024; constexpr int32_t kTimeOffset = 100000; +constexpr perfetto::BackendType backendTypes[] = { + perfetto::kUnspecifiedBackend, + perfetto::kInProcessBackend, + perfetto::kSystemBackend, + perfetto::kCustomBackend, +}; class FrameTracerFuzzer { public: @@ -47,24 +54,25 @@ public: void process(); private: - std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest(); void traceTimestamp(); - std::vector<int32_t> generateLayerIds(size_t numLayerIds); void traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds); void traceFence(std::vector<int32_t> layerIds, size_t numLayerIds); + std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest(); std::unique_ptr<android::FrameTracer> mFrameTracer = nullptr; - FuzzedDataProvider mFdp; + std::vector<int32_t> generateLayerIds(size_t numLayerIds); android::FenceToFenceTimeMap mFenceFactory; + FuzzedDataProvider mFdp; }; std::unique_ptr<perfetto::TracingSession> FrameTracerFuzzer::getTracingSessionForTest() { perfetto::TraceConfig cfg; - cfg.set_duration_ms(kConfigDuration); - cfg.add_buffers()->set_size_kb(kBufferSize); + cfg.set_duration_ms(mFdp.ConsumeIntegralInRange<int32_t>(kMinRange, kConfigDuration)); + cfg.add_buffers()->set_size_kb(mFdp.ConsumeIntegralInRange<int32_t>(kMinRange, kBufferSize)); auto* dsCfg = cfg.add_data_sources()->mutable_config(); dsCfg->set_name(android::FrameTracer::kFrameTracerDataSource); - auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); + auto tracingSession = + perfetto::Tracing::NewTrace(mFdp.PickValueInArray<perfetto::BackendType>(backendTypes)); tracingSession->Setup(cfg); return tracingSession; } @@ -78,17 +86,23 @@ std::vector<int32_t> FrameTracerFuzzer::generateLayerIds(size_t numLayerIds) { } void FrameTracerFuzzer::traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds) { - int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1)); + uint32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1)); + android::FrameTracer::FrameEvent::BufferEventType type = static_cast< + android::FrameTracer::FrameEvent::BufferEventType>( + mFdp.ConsumeIntegralInRange<uint32_t>(android::FrameTracer::FrameEvent::UNSPECIFIED, + android::FrameTracer::FrameEvent::CANCEL)); mFrameTracer->traceTimestamp(layerId, mFdp.ConsumeIntegral<uint64_t>() /*bufferID*/, mFdp.ConsumeIntegral<uint64_t>() /*frameNumber*/, - mFdp.ConsumeIntegral<nsecs_t>() /*timestamp*/, - android::FrameTracer::FrameEvent::UNSPECIFIED, + mFdp.ConsumeIntegral<nsecs_t>() /*timestamp*/, type, mFdp.ConsumeIntegral<nsecs_t>() /*duration*/); } void FrameTracerFuzzer::traceFence(std::vector<int32_t> layerIds, size_t numLayerIds) { - const nsecs_t signalTime = systemTime(); - const nsecs_t startTime = signalTime + kTimeOffset; + const nsecs_t signalTime = + mFdp.ConsumeBool() ? android::Fence::SIGNAL_TIME_PENDING : systemTime(); + const nsecs_t startTime = (signalTime == android::Fence::SIGNAL_TIME_PENDING) + ? signalTime - kTimeOffset + : signalTime + kTimeOffset; auto fence = mFenceFactory.createFenceTimeForTest(android::Fence::NO_FENCE); mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, signalTime); int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1)); @@ -98,26 +112,30 @@ void FrameTracerFuzzer::traceFence(std::vector<int32_t> layerIds, size_t numLaye } void FrameTracerFuzzer::process() { - mFrameTracer->registerDataSource(); - - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - - size_t numLayerIds = mFdp.ConsumeIntegralInRange<size_t>(kMinLayerIds, kMaxLayerIds); - std::vector<int32_t> layerIds = generateLayerIds(numLayerIds); - - for (auto it = layerIds.begin(); it != layerIds.end(); ++it) { - mFrameTracer->traceNewLayer(*it /*layerId*/, - mFdp.ConsumeRandomLengthString(kMaxStringSize) /*layerName*/); + std::vector<int32_t> layerIds = + generateLayerIds(mFdp.ConsumeIntegralInRange<size_t>(kMinLayerIds, kMaxLayerIds)); + + while (mFdp.remaining_bytes()) { + auto invokeFrametracerAPI = mFdp.PickValueInArray<const std::function<void()>>({ + [&]() { mFrameTracer->registerDataSource(); }, + [&]() { + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + }, + [&]() { traceTimestamp(layerIds, layerIds.size()); }, + [&]() { traceFence(layerIds, layerIds.size()); }, + [&]() { + for (auto it = layerIds.begin(); it != layerIds.end(); ++it) { + mFrameTracer->traceNewLayer(*it /*layerId*/, + mFdp.ConsumeRandomLengthString( + kMaxStringSize) /*layerName*/); + } + }, + [&]() { mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, systemTime()); }, + }); + invokeFrametracerAPI(); } - traceTimestamp(layerIds, numLayerIds); - traceFence(layerIds, numLayerIds); - - mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, systemTime()); - - tracingSession->StopBlocking(); - for (auto it = layerIds.begin(); it != layerIds.end(); ++it) { mFrameTracer->onDestroy(*it); } diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop index be29be4ef4..0ad5ac9956 100644 --- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop +++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop @@ -495,3 +495,15 @@ prop { access: Readonly prop_name: "ro.surface_flinger.clear_slots_with_set_layer_buffer" } + +# Controls the default frame rate override of game applications. Ideally, game applications set +# desired frame rate via setFrameRate() API. However, to cover the scenario when the game didn't +# have a set frame rate, we introduce the default frame rate. The priority of this override is the +# lowest among setFrameRate() and game intervention override. +prop { + api_name: "game_default_frame_rate_override" + type: Integer + scope: Public + access: Readonly + prop_name: "ro.surface_flinger.game_default_frame_rate_override" +} diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt index ba88acc2fb..00173009f5 100644 --- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt +++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt @@ -65,6 +65,11 @@ props { prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays" } prop { + api_name: "game_default_frame_rate_override" + type: Integer + prop_name: "ro.surface_flinger.game_default_frame_rate_override" + } + prop { api_name: "has_HDR_display" prop_name: "ro.surface_flinger.has_HDR_display" } diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index 4be961bda1..0a951d49e3 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -75,8 +75,8 @@ TEST_F(RefreshRateRangeTest, setAllConfigs) { setSpecs.allowGroupSwitching = false; for (size_t i = 0; i < modes.size(); i++) { setSpecs.defaultMode = modes[i].id; - setSpecs.primaryRanges.physical.min = modes[i].refreshRate; - setSpecs.primaryRanges.physical.max = modes[i].refreshRate; + setSpecs.primaryRanges.physical.min = modes[i].peakRefreshRate; + setSpecs.primaryRanges.physical.max = modes[i].peakRefreshRate; setSpecs.primaryRanges.render = setSpecs.primaryRanges.physical; setSpecs.appRequestRanges = setSpecs.primaryRanges; res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, setSpecs); diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 2bdb8a452d..9269e7c8a0 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -299,7 +299,7 @@ private: // After a new buffer is queued, SurfaceFlinger is notified and will // latch the new buffer on next vsync. Let's heuristically wait for 3 // vsyncs. - mBufferPostDelay = static_cast<int32_t>(1e6 / mode.refreshRate) * 3; + mBufferPostDelay = static_cast<int32_t>(1e6 / mode.peakRefreshRate) * 3; mBlackBgSurface = createSurface(mClient, "BaseSurface", 0 /* buffer width */, 0 /* buffer height */, diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp index 8a45f17e2f..4f545a9ef3 100644 --- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp +++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp @@ -32,6 +32,7 @@ #include <gui/LayerMetadata.h> #include <log/log.h> +#include <chrono> #include "DisplayHardware/DisplayMode.h" #include "DisplayHardware/HWComposer.h" @@ -44,11 +45,11 @@ #pragma clang diagnostic pop // ignored "-Wconversion" namespace android { -namespace { namespace V2_1 = hardware::graphics::composer::V2_1; namespace V2_4 = hardware::graphics::composer::V2_4; namespace aidl = aidl::android::hardware::graphics::composer3; +using namespace std::chrono_literals; using Hwc2::Config; @@ -77,6 +78,12 @@ struct HWComposerTest : testing::Test { EXPECT_CALL(*mHal, setVsyncEnabled(hwcDisplayId, Hwc2::IComposerClient::Vsync::DISABLE)); EXPECT_CALL(*mHal, onHotplugConnect(hwcDisplayId)); } + + void setDisplayData(HalDisplayId displayId, nsecs_t lastExpectedPresentTimestamp) { + ASSERT_TRUE(mHwc.mDisplayData.find(displayId) != mHwc.mDisplayData.end()); + auto& displayData = mHwc.mDisplayData.at(displayId); + displayData.lastExpectedPresentTimestamp = lastExpectedPresentTimestamp; + } }; TEST_F(HWComposerTest, isHeadless) { @@ -227,12 +234,19 @@ TEST_F(HWComposerTest, getModesWithDisplayConfigurations) { constexpr int32_t kHeight = 720; constexpr int32_t kConfigGroup = 1; constexpr int32_t kVsyncPeriod = 16666667; - hal::DisplayConfiguration displayConfiguration; - displayConfiguration.configId = kConfigId; - displayConfiguration.configGroup = kConfigGroup; - displayConfiguration.height = kHeight; - displayConfiguration.width = kWidth; - displayConfiguration.vsyncPeriod = kVsyncPeriod; + const hal::VrrConfig vrrConfig = + hal::VrrConfig{.minFrameIntervalNs = static_cast<Fps>(120_Hz).getPeriodNsecs(), + .notifyExpectedPresentConfig = hal::VrrConfig:: + NotifyExpectedPresentConfig{.notifyExpectedPresentHeadsUpNs = + ms2ns(30), + .notifyExpectedPresentTimeoutNs = + ms2ns(30)}}; + hal::DisplayConfiguration displayConfiguration{.configId = kConfigId, + .width = kWidth, + .height = kHeight, + .configGroup = kConfigGroup, + .vsyncPeriod = kVsyncPeriod, + .vrrConfig = vrrConfig}; EXPECT_CALL(*mHal, getDisplayConfigurations(kHwcDisplayId, _, _)) .WillOnce(DoAll(SetArgPointee<2>(std::vector<hal::DisplayConfiguration>{ @@ -247,6 +261,7 @@ TEST_F(HWComposerTest, getModesWithDisplayConfigurations) { EXPECT_EQ(modes.front().height, kHeight); EXPECT_EQ(modes.front().configGroup, kConfigGroup); EXPECT_EQ(modes.front().vsyncPeriod, kVsyncPeriod); + EXPECT_EQ(modes.front().vrrConfig, vrrConfig); EXPECT_EQ(modes.front().dpiX, -1); EXPECT_EQ(modes.front().dpiY, -1); @@ -266,6 +281,7 @@ TEST_F(HWComposerTest, getModesWithDisplayConfigurations) { EXPECT_EQ(modes.front().height, kHeight); EXPECT_EQ(modes.front().configGroup, kConfigGroup); EXPECT_EQ(modes.front().vsyncPeriod, kVsyncPeriod); + EXPECT_EQ(modes.front().vrrConfig, vrrConfig); EXPECT_EQ(modes.front().dpiX, kDpi); EXPECT_EQ(modes.front().dpiY, kDpi); } @@ -299,6 +315,55 @@ TEST_F(HWComposerTest, onVsyncInvalid) { EXPECT_FALSE(displayIdOpt); } +TEST_F(HWComposerTest, notifyExpectedPresentTimeout) { + constexpr hal::HWDisplayId kHwcDisplayId = 2; + expectHotplugConnect(kHwcDisplayId); + const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED); + ASSERT_TRUE(info); + + auto expectedPresentTime = systemTime() + ms2ns(10); + const int32_t frameIntervalNs = static_cast<Fps>(60_Hz).getPeriodNsecs(); + static constexpr nsecs_t kTimeoutNs = ms2ns(30); + + ASSERT_NO_FATAL_FAILURE(setDisplayData(info->id, /* lastExpectedPresentTimestamp= */ 0)); + + { + // Very first ExpectedPresent after idle, no previous timestamp + EXPECT_CALL(*mHal, + notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs)) + .WillOnce(Return(HalError::NONE)); + mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs, + kTimeoutNs); + } + { + // ExpectedPresent is after the timeoutNs + expectedPresentTime += ms2ns(50); + EXPECT_CALL(*mHal, + notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs)) + .WillOnce(Return(HalError::NONE)); + mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs, + kTimeoutNs); + } + { + // ExpectedPresent is after the last reported ExpectedPresent. + expectedPresentTime += ms2ns(10); + EXPECT_CALL(*mHal, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0); + mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs, + kTimeoutNs); + } + { + // ExpectedPresent is before the last reported ExpectedPresent but after the timeoutNs, + // representing we changed our decision and want to present earlier than previously + // reported. + expectedPresentTime -= ms2ns(20); + EXPECT_CALL(*mHal, + notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs)) + .WillOnce(Return(HalError::NONE)); + mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs, + kTimeoutNs); + } +} + struct MockHWC2ComposerCallback final : StrictMock<HWC2::ComposerCallback> { MOCK_METHOD2(onComposerHalHotplug, void(hal::HWDisplayId, hal::Connection)); MOCK_METHOD1(onComposerHalRefresh, void(hal::HWDisplayId)); @@ -423,5 +488,4 @@ TEST_F(HWComposerLayerGenericMetadataTest, forwardsSupportedMetadata) { EXPECT_EQ(hal::Error::UNSUPPORTED, result); } -} // namespace } // namespace android diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp index b8fdce1dce..1dc5498221 100644 --- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp @@ -759,6 +759,8 @@ TEST_F(VSyncDispatchTimerQueueTest, canMoveCallbackBackwardsInTime) { // b/1450138150 TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) { + SET_FLAG_FOR_TEST(flags::dont_skip_on_early, false); + EXPECT_CALL(mMockClock, alarmAt(_, 500)); CountingCallback cb(mDispatch); auto result = @@ -772,6 +774,29 @@ TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipASchedule {.workDuration = 800, .readyDuration = 0, .earliestVsync = 1000}); EXPECT_TRUE(result.has_value()); EXPECT_EQ(1200, *result); + + advanceToNextCallback(); + ASSERT_THAT(cb.mCalls.size(), Eq(1)); +} + +// b/1450138150 +TEST_F(VSyncDispatchTimerQueueTest, movesCallbackBackwardsAndSkipAScheduledTargetVSync) { + SET_FLAG_FOR_TEST(flags::dont_skip_on_early, true); + + EXPECT_CALL(mMockClock, alarmAt(_, 500)); + CountingCallback cb(mDispatch); + auto result = + mDispatch->schedule(cb, + {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(500, *result); + mMockClock.advanceBy(400); + + result = mDispatch->schedule(cb, + {.workDuration = 800, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(400, *result); + advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); } @@ -826,6 +851,8 @@ TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) { } TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) { + SET_FLAG_FOR_TEST(flags::dont_skip_on_early, false); + EXPECT_CALL(mMockClock, alarmAt(_, 600)); CountingCallback cb(mDispatch); @@ -843,6 +870,26 @@ TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) advanceToNextCallback(); } +TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesAffectSchedulingState) { + SET_FLAG_FOR_TEST(flags::dont_skip_on_early, true); + + EXPECT_CALL(mMockClock, alarmAt(_, 600)); + + CountingCallback cb(mDispatch); + auto result = + mDispatch->schedule(cb, + {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(600, *result); + + result = mDispatch->schedule(cb, + {.workDuration = 1400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(0, *result); + + advanceToNextCallback(); +} + TEST_F(VSyncDispatchTimerQueueTest, helperMove) { EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1); EXPECT_CALL(mMockClock, alarmCancel()).Times(1); @@ -1045,6 +1092,8 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithReadyDuration) { } TEST_F(VSyncDispatchTimerQueueTest, updatesVsyncTimeForCloseWakeupTime) { + SET_FLAG_FOR_TEST(flags::dont_skip_on_early, false); + Sequence seq; EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); @@ -1065,6 +1114,29 @@ TEST_F(VSyncDispatchTimerQueueTest, updatesVsyncTimeForCloseWakeupTime) { EXPECT_THAT(cb.mReadyTime[0], Eq(2000)); } +TEST_F(VSyncDispatchTimerQueueTest, doesNotUpdatesVsyncTimeForCloseWakeupTime) { + SET_FLAG_FOR_TEST(flags::dont_skip_on_early, true); + + Sequence seq; + EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); + + CountingCallback cb(mDispatch); + + mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch->schedule(cb, {.workDuration = 1400, .readyDuration = 0, .earliestVsync = 1000}); + + advanceToNextCallback(); + + advanceToNextCallback(); + + ASSERT_THAT(cb.mCalls.size(), Eq(1)); + EXPECT_THAT(cb.mCalls[0], Eq(1000)); + ASSERT_THAT(cb.mWakeupTime.size(), Eq(1)); + EXPECT_THAT(cb.mWakeupTime[0], Eq(600)); + ASSERT_THAT(cb.mReadyTime.size(), Eq(1)); + EXPECT_THAT(cb.mReadyTime[0], Eq(1000)); +} + TEST_F(VSyncDispatchTimerQueueTest, skipAVsyc) { SET_FLAG_FOR_TEST(flags::dont_skip_on_early, false); @@ -1101,7 +1173,7 @@ TEST_F(VSyncDispatchTimerQueueTest, dontskipAVsyc) { result = mDispatch->schedule(cb, {.workDuration = 800, .readyDuration = 0, .earliestVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(200, *result); + EXPECT_EQ(300, *result); advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index 95004a485b..0b0774551a 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -178,6 +178,7 @@ public: MOCK_METHOD1(onHotplugConnect, void(Display)); MOCK_METHOD1(onHotplugDisconnect, void(Display)); MOCK_METHOD(Error, setRefreshRateChangedCallbackDebugEnabled, (Display, bool)); + MOCK_METHOD(Error, notifyExpectedPresent, (Display, nsecs_t, int32_t)); }; } // namespace Hwc2::mock |