Merge "Remove installd support for compiled views" into main
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index e286a84..550b374 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -131,6 +131,24 @@
}
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 b2e8baa..dfcf766 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -146,7 +146,7 @@
#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 89fd7a3..316a79c 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 @@
/**
* 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 3c615ed..f9f135d 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -54,6 +54,10 @@
/// 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 5884dbe..1340ea1 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 f0beed2..f367b41 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -66,6 +66,11 @@
},
// 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 @@
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 @@
},
// 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 05e2ddf..a351811 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2604,7 +2604,7 @@
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 b057653..f605177 100644
--- a/libs/gui/aidl/android/gui/DisplayMode.aidl
+++ b/libs/gui/aidl/android/gui/DisplayMode.aidl
@@ -30,7 +30,7 @@
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 662e9fe..d4b8dbe 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -394,7 +394,7 @@
// 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 a4cd239..e2feabc 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -613,14 +613,14 @@
}
#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 bf0805b..e3be3bc 100644
--- a/libs/nativedisplay/ADisplay.cpp
+++ b/libs/nativedisplay/ADisplay.cpp
@@ -155,7 +155,7 @@
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 a469c78..ddb9bbd 100644
--- a/libs/ui/include/ui/DisplayMode.h
+++ b/libs/ui/include/ui/DisplayMode.h
@@ -38,7 +38,7 @@
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 1f17c16..016ae04 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -39,7 +39,7 @@
// 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 c34cd53..de836e9 100644
--- a/services/inputflinger/NotifyArgs.cpp
+++ b/services/inputflinger/NotifyArgs.cpp
@@ -190,7 +190,7 @@
// 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 be2bfed..69264f8 100644
--- a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
+++ b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
@@ -239,7 +239,7 @@
// 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 892bb8f..6807c8e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -147,6 +147,8 @@
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 1f409c6..1643ad0 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -1450,6 +1450,20 @@
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 b1b57a4..7693a80 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -240,6 +240,8 @@
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 e942587..6704d88 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -298,6 +298,8 @@
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 812621f..fb6089d 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 @@
}();
displayData.validateWasSkipped = false;
+ displayData.lastExpectedPresentTimestamp = expectedPresentTime;
if (canSkipValidate) {
sp<Fence> outPresentFence;
uint32_t state = UINT32_MAX;
@@ -876,6 +878,30 @@
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 b4d3d28..726a8ea 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -60,6 +60,7 @@
struct DisplayedFrameStats;
class GraphicBuffer;
class TestableSurfaceFlinger;
+struct HWComposerTest;
struct CompositionInfo;
namespace Hwc2 {
@@ -300,6 +301,9 @@
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 @@
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 @@
private:
// For unit tests
friend TestableSurfaceFlinger;
+ friend HWComposerTest;
struct DisplayData {
std::unique_ptr<HWC2::Display> hwcDisplay;
@@ -490,6 +497,8 @@
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 70d48de..c13e568 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -1378,6 +1378,10 @@
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 26d2222..1004ddd 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -348,6 +348,7 @@
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 c4c9fa5..f467670 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
@@ -40,16 +40,18 @@
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 @@
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 @@
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 9b9a67a..fc51721 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -266,7 +266,7 @@
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 @@
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 @@
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 66c8f33..a765078 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -371,5 +371,9 @@
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 a080420..65ebe2a 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -101,6 +101,8 @@
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 a22a778..8978971 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp
@@ -23,12 +23,19 @@
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 @@
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 @@
}
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::process() {
- mFrameTracer->registerDataSource();
+ std::vector<int32_t> layerIds =
+ generateLayerIds(mFdp.ConsumeIntegralInRange<size_t>(kMinLayerIds, kMaxLayerIds));
- 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*/);
+ 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 be29be4..0ad5ac9 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -495,3 +495,15 @@
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 ba88acc..0017300 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -65,6 +65,11 @@
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 4be961b..0a951d4 100644
--- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp
+++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
@@ -75,8 +75,8 @@
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 2bdb8a4..9269e7c 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -299,7 +299,7 @@
// 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 8a45f17..4f545a9 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 b8fdce1..1dc5498 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -759,6 +759,8 @@
// 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 @@
{.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, scheduleUpdatesDoesNotAffectSchedulingState) {
+ SET_FLAG_FOR_TEST(flags::dont_skip_on_early, false);
+
EXPECT_CALL(mMockClock, alarmAt(_, 600));
CountingCallback cb(mDispatch);
@@ -843,6 +870,26 @@
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, updatesVsyncTimeForCloseWakeupTime) {
+ SET_FLAG_FOR_TEST(flags::dont_skip_on_early, false);
+
Sequence seq;
EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
@@ -1065,6 +1114,29 @@
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 @@
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 95004a4..0b07745 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -178,6 +178,7 @@
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