Merge "surfaceflinger: Pass proper transform orientation to setProjection()"
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index f3d4b7e..296e3f6 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -51,7 +51,7 @@
"IpPrefix.cpp",
]
-cc_library_shared {
+cc_library {
name: "libbinder",
// for vndbinder
@@ -101,6 +101,11 @@
target: {
android: {
srcs: libbinder_device_interface_sources,
+
+ // NOT static to keep the wire protocol unfrozen
+ static: {
+ enabled: false,
+ },
},
vendor: {
exclude_srcs: libbinder_device_interface_sources,
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index c57b955..ab7b8ba 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -143,7 +143,7 @@
}
Mutex::Autolock lock(mQueueItemLock);
- return mQueueItems[0].mTimestamp <= mFlinger->mScheduler->expectedPresentTime();
+ return mQueueItems[0].mTimestamp <= mFlinger->getExpectedPresentTime();
}
nsecs_t BufferQueueLayer::getDesiredPresentTime() {
@@ -201,7 +201,7 @@
uint64_t frameNumber = mQueueItems[0].mFrameNumber;
// The head of the queue will be dropped if there are signaled and timely frames behind it
- nsecs_t expectedPresentTime = mFlinger->mScheduler->expectedPresentTime();
+ nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
if (isRemovedFromCurrentState()) {
expectedPresentTime = 0;
@@ -280,7 +280,7 @@
getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
getTransformToDisplayInverse(), mFreezeGeometryUpdates);
- nsecs_t expectedPresentTime = mFlinger->mScheduler->expectedPresentTime();
+ nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
if (isRemovedFromCurrentState()) {
expectedPresentTime = 0;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 05c721f..203bd72 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -380,7 +380,7 @@
return true;
}
- return mDesiredPresentTime <= mFlinger->mScheduler->expectedPresentTime();
+ return mDesiredPresentTime <= mFlinger->getExpectedPresentTime();
}
nsecs_t BufferStateLayer::getDesiredPresentTime() {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 1318bc0..f4284fe 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -153,7 +153,6 @@
mRemoteSyncPoints.clear();
{
- Mutex::Autolock pendingStateLock(mPendingStateMutex);
for (State pendingState : mPendingStates) {
pendingState.barrierLayer_legacy = nullptr;
}
@@ -907,6 +906,7 @@
// Commit the transaction
commitTransaction(c);
+ mPendingStatesSnapshot = mPendingStates;
mCurrentState.callbackHandles = {};
return flags;
}
@@ -1874,14 +1874,61 @@
setTransactionFlags(eTransactionNeeded);
}
-void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
- uint32_t traceFlags) {
+void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) const {
+ ui::Transform transform = getTransform();
+
+ if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
+ for (const auto& pendingState : mPendingStatesSnapshot) {
+ auto barrierLayer = pendingState.barrierLayer_legacy.promote();
+ if (barrierLayer != nullptr) {
+ BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
+ barrierLayerProto->set_id(barrierLayer->sequence);
+ barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
+ }
+ }
+
+ auto buffer = mActiveBuffer;
+ if (buffer != nullptr) {
+ LayerProtoHelper::writeToProto(buffer,
+ [&]() { return layerInfo->mutable_active_buffer(); });
+ LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
+ layerInfo->mutable_buffer_transform());
+ }
+ layerInfo->set_invalidate(contentDirty);
+ layerInfo->set_is_protected(isProtected());
+ layerInfo->set_dataspace(
+ dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
+ layerInfo->set_queued_frames(getQueuedFrameCount());
+ layerInfo->set_refresh_pending(isBufferLatched());
+ layerInfo->set_curr_frame(mCurrentFrameNumber);
+ layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
+
+ layerInfo->set_corner_radius(getRoundedCornerState().radius);
+ LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
+ LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
+ [&]() { return layerInfo->mutable_position(); });
+ LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
+ LayerProtoHelper::writeToProto(visibleRegion,
+ [&]() { return layerInfo->mutable_visible_region(); });
+ LayerProtoHelper::writeToProto(surfaceDamageRegion,
+ [&]() { return layerInfo->mutable_damage_region(); });
+ }
+
+ if (traceFlags & SurfaceTracing::TRACE_EXTRA) {
+ LayerProtoHelper::writeToProto(mSourceBounds,
+ [&]() { return layerInfo->mutable_source_bounds(); });
+ LayerProtoHelper::writeToProto(mScreenBounds,
+ [&]() { return layerInfo->mutable_screen_bounds(); });
+ }
+}
+
+void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+ uint32_t traceFlags) const {
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
const State& state = useDrawing ? mDrawingState : mCurrentState;
ui::Transform requestedTransform = state.active_legacy.transform;
- ui::Transform transform = getTransform();
if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
layerInfo->set_id(sequence);
@@ -1901,17 +1948,10 @@
LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
[&]() { return layerInfo->mutable_transparent_region(); });
- LayerProtoHelper::writeToProto(visibleRegion,
- [&]() { return layerInfo->mutable_visible_region(); });
- LayerProtoHelper::writeToProto(surfaceDamageRegion,
- [&]() { return layerInfo->mutable_damage_region(); });
layerInfo->set_layer_stack(getLayerStack());
layerInfo->set_z(state.z);
- LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
- [&]() { return layerInfo->mutable_position(); });
-
LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(),
[&]() {
return layerInfo->mutable_requested_position();
@@ -1922,15 +1962,9 @@
LayerProtoHelper::writeToProto(state.crop_legacy,
[&]() { return layerInfo->mutable_crop(); });
- layerInfo->set_corner_radius(getRoundedCornerState().radius);
layerInfo->set_is_opaque(isOpaque(state));
- layerInfo->set_invalidate(contentDirty);
- layerInfo->set_is_protected(isProtected());
- // XXX (b/79210409) mCurrentDataSpace is not protected
- layerInfo->set_dataspace(
- dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
LayerProtoHelper::writeToProto(getColor(), [&]() { return layerInfo->mutable_color(); });
@@ -1938,7 +1972,6 @@
[&]() { return layerInfo->mutable_requested_color(); });
layerInfo->set_flags(state.flags);
- LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
LayerProtoHelper::writeToProto(requestedTransform,
layerInfo->mutable_requested_transform());
@@ -1955,29 +1988,6 @@
} else {
layerInfo->set_z_order_relative_of(-1);
}
-
- auto buffer = mActiveBuffer;
- if (buffer != nullptr) {
- LayerProtoHelper::writeToProto(buffer,
- [&]() { return layerInfo->mutable_active_buffer(); });
- LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
- layerInfo->mutable_buffer_transform());
- }
-
- layerInfo->set_queued_frames(getQueuedFrameCount());
- layerInfo->set_refresh_pending(isBufferLatched());
- layerInfo->set_curr_frame(mCurrentFrameNumber);
- layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
-
- for (const auto& pendingState : mPendingStates) {
- auto barrierLayer = pendingState.barrierLayer_legacy.promote();
- if (barrierLayer != nullptr) {
- BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
- barrierLayerProto->set_id(barrierLayer->sequence);
- barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
- }
- }
- LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
}
if (traceFlags & SurfaceTracing::TRACE_INPUT) {
@@ -1990,23 +2000,19 @@
for (const auto& entry : state.metadata.mMap) {
(*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
}
- LayerProtoHelper::writeToProto(mEffectiveTransform,
- layerInfo->mutable_effective_transform());
- LayerProtoHelper::writeToProto(mSourceBounds,
- [&]() { return layerInfo->mutable_source_bounds(); });
- LayerProtoHelper::writeToProto(mScreenBounds,
- [&]() { return layerInfo->mutable_screen_bounds(); });
}
}
-void Layer::writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
- uint32_t traceFlags) {
+void Layer::writeToProtoCompositionState(LayerProto* layerInfo,
+ const sp<DisplayDevice>& displayDevice,
+ uint32_t traceFlags) const {
auto outputLayer = findOutputLayerForDisplay(displayDevice);
if (!outputLayer) {
return;
}
- writeToProto(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
+ writeToProtoDrawingState(layerInfo, traceFlags);
+ writeToProtoCommonState(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
const auto& compositionState = outputLayer->getState();
@@ -2024,13 +2030,6 @@
static_cast<int32_t>(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType
: Hwc2::IComposerClient::Composition::CLIENT);
layerInfo->set_hwc_composition_type(compositionType);
-
- if (std::strcmp(getTypeId(), "BufferLayer") == 0 &&
- static_cast<BufferLayer*>(this)->isProtected()) {
- layerInfo->set_is_protected(true);
- } else {
- layerInfo->set_is_protected(false);
- }
}
bool Layer::isRemovedFromCurrentState() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8a80e15..132b4cf 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -438,11 +438,21 @@
bool isRemovedFromCurrentState() const;
- void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
-
- void writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
+ // Write states that are modified by the main thread. This includes drawing
+ // state as well as buffer data. This should be called in the main or tracing
+ // thread.
+ void writeToProtoDrawingState(LayerProto* layerInfo,
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ // Write states that are modified by the main thread. This includes drawing
+ // state as well as buffer data and composition data for layers on the specified
+ // display. This should be called in the main or tracing thread.
+ void writeToProtoCompositionState(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ // Write drawing or current state. If writing current state, the caller should hold the
+ // external mStateLock. If writing drawing state, this function should be called on the
+ // main or tracing thread.
+ void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
@@ -832,13 +842,15 @@
bool mPrimaryDisplayOnly = false;
- // these are protected by an external lock
- State mCurrentState;
+ // These are only accessed by the main thread or the tracing thread.
State mDrawingState;
- std::atomic<uint32_t> mTransactionFlags{0};
+ // Store a copy of the pending state so that the drawing thread can access the
+ // states without a lock.
+ Vector<State> mPendingStatesSnapshot;
- // Accessed from main thread and binder threads
- Mutex mPendingStateMutex;
+ // these are protected by an external lock (mStateLock)
+ State mCurrentState;
+ std::atomic<uint32_t> mTransactionFlags{0};
Vector<State> mPendingStates;
// Timestamp history for UIAutomation. Thread safe.
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index cd6fa41..95ff9d0 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -79,11 +79,7 @@
Mutex::Autolock lock(mMutex);
mPhase = phase;
- if (mReferenceTime != referenceTime) {
- for (auto& eventListener : mEventListeners) {
- eventListener.mHasFired = false;
- }
- }
+ const bool referenceTimeChanged = mReferenceTime != referenceTime;
mReferenceTime = referenceTime;
if (mPeriod != 0 && mPeriod != period && mReferenceTime != 0) {
// Inflate the reference time to be the most recent predicted
@@ -94,6 +90,13 @@
mReferenceTime = mReferenceTime + (numOldPeriods)*mPeriod;
}
mPeriod = period;
+ if (!mModelLocked && referenceTimeChanged) {
+ for (auto& eventListener : mEventListeners) {
+ eventListener.mHasFired = false;
+ eventListener.mLastEventTime =
+ mReferenceTime - mPeriod + mPhase + eventListener.mPhase;
+ }
+ }
if (mTraceDetailedInfo) {
ATRACE_INT64("DispSync:Period", mPeriod);
ATRACE_INT64("DispSync:Phase", mPhase + mPeriod / 2);
@@ -115,11 +118,20 @@
void lockModel() {
Mutex::Autolock lock(mMutex);
mModelLocked = true;
+ ATRACE_INT("DispSync:ModelLocked", mModelLocked);
}
void unlockModel() {
Mutex::Autolock lock(mMutex);
+ if (mModelLocked) {
+ for (auto& eventListener : mEventListeners) {
+ if (eventListener.mLastEventTime > mReferenceTime) {
+ eventListener.mHasFired = true;
+ }
+ }
+ }
mModelLocked = false;
+ ATRACE_INT("DispSync:ModelLocked", mModelLocked);
}
virtual bool threadLoop() {
@@ -247,6 +259,10 @@
listener.mLastCallbackTime = lastCallbackTime;
}
+ if (!mModelLocked && listener.mLastEventTime > mReferenceTime) {
+ listener.mHasFired = true;
+ }
+
mEventListeners.push_back(listener);
mCond.signal();
@@ -493,7 +509,6 @@
ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
}
- reset();
beginResync();
if (mTraceDetailedInfo && kEnableZeroPhaseTracer) {
@@ -545,17 +560,15 @@
void DispSync::beginResync() {
Mutex::Autolock lock(mMutex);
ALOGV("[%s] beginResync", mName);
- mThread->unlockModel();
- mModelUpdated = false;
- mNumResyncSamples = 0;
+ resetLocked();
}
-bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) {
+bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodFlushed) {
Mutex::Autolock lock(mMutex);
ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
- *periodChanged = false;
+ *periodFlushed = false;
const size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
mResyncSamples[idx] = timestamp;
if (mNumResyncSamples == 0) {
@@ -569,16 +582,20 @@
const nsecs_t lastTimestamp = mResyncSamples[priorIdx];
const nsecs_t observedVsync = std::abs(timestamp - lastTimestamp);
- if (std::abs(observedVsync - mPendingPeriod) < std::abs(observedVsync - mPeriod)) {
- // Observed vsync is closer to the pending period, so reset the
- // model and flush the pending period.
+ if (std::abs(observedVsync - mPendingPeriod) <= std::abs(observedVsync - mIntendedPeriod)) {
+ // Either the observed vsync is closer to the pending period, (and
+ // thus we detected a period change), or the period change will
+ // no-op. In either case, reset the model and flush the pending
+ // period.
resetLocked();
+ mIntendedPeriod = mPendingPeriod;
mPeriod = mPendingPeriod;
mPendingPeriod = 0;
if (mTraceDetailedInfo) {
ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod);
+ ATRACE_INT("DispSync:IntendedPeriod", mIntendedPeriod);
}
- *periodChanged = true;
+ *periodFlushed = true;
}
}
// Always update the reference time with the most recent timestamp.
@@ -609,6 +626,7 @@
bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2) && mPendingPeriod == 0;
ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked");
if (modelLocked) {
+ *periodFlushed = true;
mThread->lockModel();
}
return !modelLocked;
@@ -643,10 +661,17 @@
void DispSync::setPeriod(nsecs_t period) {
Mutex::Autolock lock(mMutex);
- if (mTraceDetailedInfo) {
- ATRACE_INT("DispSync:PendingPeriod", period);
+
+ const bool pendingPeriodShouldChange =
+ period != mIntendedPeriod || (period == mIntendedPeriod && mPendingPeriod != 0);
+
+ if (pendingPeriodShouldChange) {
+ mPendingPeriod = period;
}
- mPendingPeriod = period;
+ if (mTraceDetailedInfo) {
+ ATRACE_INT("DispSync:IntendedPeriod", mIntendedPeriod);
+ ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod);
+ }
}
nsecs_t DispSync::getPeriod() {
@@ -764,6 +789,9 @@
mPresentSampleOffset = 0;
mError = 0;
mZeroErrSamplesCount = 0;
+ if (mTraceDetailedInfo) {
+ ATRACE_INT64("DispSync:Error", mError);
+ }
for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
mPresentFences[i] = FenceTime::NO_FENCE;
}
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index 8f8b8e7..3e33c7e 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -49,7 +49,7 @@
virtual void reset() = 0;
virtual bool addPresentFence(const std::shared_ptr<FenceTime>&) = 0;
virtual void beginResync() = 0;
- virtual bool addResyncSample(nsecs_t timestamp, bool* periodChanged) = 0;
+ virtual bool addResyncSample(nsecs_t timestamp, bool* periodFlushed) = 0;
virtual void endResync() = 0;
virtual void setPeriod(nsecs_t period) = 0;
virtual nsecs_t getPeriod() = 0;
@@ -120,17 +120,19 @@
// from the hardware vsync events.
void beginResync() override;
// Adds a vsync sample to the dispsync model. The timestamp is the time
- // of the vsync event that fired. periodChanged will return true if the
+ // of the vsync event that fired. periodFlushed will return true if the
// vsync period was detected to have changed to mPendingPeriod.
//
// This method will return true if more vsync samples are needed to lock
// down the DispSync model, and false otherwise.
- bool addResyncSample(nsecs_t timestamp, bool* periodChanged) override;
+ // periodFlushed will be set to true if mPendingPeriod is flushed to
+ // mIntendedPeriod, and false otherwise.
+ bool addResyncSample(nsecs_t timestamp, bool* periodFlushed) override;
void endResync() override;
// The setPeriod method sets the vsync event model's period to a specific
- // value. This should be used to prime the model when a display is first
- // turned on. It should NOT be used after that.
+ // value. This should be used to prime the model when a display is first
+ // turned on, or when a refresh rate change is requested.
void setPeriod(nsecs_t period) override;
// The getPeriod method returns the current vsync period.
@@ -205,6 +207,11 @@
// nanoseconds.
nsecs_t mPeriod;
+ // mIntendedPeriod is the intended period of the modeled vsync events in
+ // nanoseconds. Under ideal conditions this should be similar if not the
+ // same as mPeriod, plus or minus an observed error.
+ nsecs_t mIntendedPeriod = 0;
+
// mPendingPeriod is the proposed period change in nanoseconds.
// If mPendingPeriod differs from mPeriod and is nonzero, it will
// be flushed to mPeriod when we detect that the hardware switched
@@ -236,8 +243,8 @@
// process to store information about the hardware vsync event times used
// to compute the model.
nsecs_t mResyncSamples[MAX_RESYNC_SAMPLES] = {0};
- size_t mFirstResyncSample;
- size_t mNumResyncSamples;
+ size_t mFirstResyncSample = 0;
+ size_t mNumResyncSamples = 0;
int mNumResyncSamplesSincePresent;
// These member variables store information about the present fences used
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 513436a..1d899df 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -280,13 +280,13 @@
}
}
-void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodChanged) {
+void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodFlushed) {
bool needsHwVsync = false;
- *periodChanged = false;
+ *periodFlushed = false;
{ // Scope for the lock
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (mPrimaryHWVsyncEnabled) {
- needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodChanged);
+ needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodFlushed);
}
}
@@ -309,7 +309,7 @@
mPrimaryDispSync->setIgnorePresentFences(ignore);
}
-nsecs_t Scheduler::expectedPresentTime() {
+nsecs_t Scheduler::getDispSyncExpectedPresentTime() {
return mPrimaryDispSync->expectedPresentTime();
}
@@ -415,7 +415,7 @@
ATRACE_INT("ExpiredKernelIdleTimer", 0);
std::lock_guard<std::mutex> lock(mCallbackLock);
if (mGetVsyncPeriod) {
- resyncToHardwareVsync(false, mGetVsyncPeriod());
+ resyncToHardwareVsync(true, mGetVsyncPeriod());
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 96d4bd5..a32bd41 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -135,16 +135,21 @@
void enableHardwareVsync();
void disableHardwareVsync(bool makeUnavailable);
+ // Resyncs the scheduler to hardware vsync.
+ // If makeAvailable is true, then hardware vsync will be turned on.
+ // Otherwise, if hardware vsync is not already enabled then this method will
+ // no-op.
+ // The period is the vsync period from the current display configuration.
void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
// Creates a callback for resyncing.
ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod);
void setRefreshSkipCount(int count);
- // Passes a vsync sample to DispSync. periodChange will be true if DipSync
- // detected that the vsync period changed, and false otherwise.
- void addResyncSample(const nsecs_t timestamp, bool* periodChanged);
+ // Passes a vsync sample to DispSync. periodFlushed will be true if
+ // DispSync detected that the vsync period changed, and false otherwise.
+ void addResyncSample(const nsecs_t timestamp, bool* periodFlushed);
void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
void setIgnorePresentFences(bool ignore);
- nsecs_t expectedPresentTime();
+ nsecs_t getDispSyncExpectedPresentTime();
// Registers the layer in the scheduler, and returns the handle for future references.
std::unique_ptr<scheduler::LayerHistory::LayerHandle> registerLayer(std::string const& name,
int windowType);
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 81a7864..21dad12 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -116,7 +116,7 @@
// Called when we detect from vsync signals that the refresh rate changed.
// This way we can move out of early offsets if no longer necessary.
- void onRefreshRateChangeDetected() {
+ void onRefreshRateChangeCompleted() {
if (!mRefreshRateChangePending) {
return;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ad0ac6b..a15cf4a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -940,9 +940,14 @@
// Start receiving vsync samples now, so that we can detect a period
// switch.
mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+ // We should only move to early offsets when we know that the refresh
+ // rate will change. Otherwise, we may be stuck in early offsets
+ // forever, as onRefreshRateChangeDetected will not be called.
+ if (mDesiredActiveConfig.event == Scheduler::ConfigEvent::Changed) {
+ mVsyncModulator.onRefreshRateChangeInitiated();
+ }
mPhaseOffsets->setRefreshRateType(info.type);
const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
- mVsyncModulator.onRefreshRateChangeInitiated();
mVsyncModulator.setPhaseOffsets(early, gl, late);
}
mDesiredActiveConfigChanged = true;
@@ -1019,6 +1024,10 @@
std::lock_guard<std::mutex> lock(mActiveConfigLock);
mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
mDesiredActiveConfigChanged = false;
+ // Update scheduler with the correct vsync period as a no-op.
+ // Otherwise, there exists a race condition where we get stuck in the
+ // incorrect vsync period.
+ mScheduler->resyncToHardwareVsync(false, getVsyncPeriod());
ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
return false;
}
@@ -1031,6 +1040,10 @@
mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
mDesiredActiveConfig.configId = display->getActiveConfig();
mDesiredActiveConfigChanged = false;
+ // Update scheduler with the current vsync period as a no-op.
+ // Otherwise, there exists a race condition where we get stuck in the
+ // incorrect vsync period.
+ mScheduler->resyncToHardwareVsync(false, getVsyncPeriod());
ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
return false;
}
@@ -1453,10 +1466,10 @@
return;
}
- bool periodChanged = false;
- mScheduler->addResyncSample(timestamp, &periodChanged);
- if (periodChanged) {
- mVsyncModulator.onRefreshRateChangeDetected();
+ bool periodFlushed = false;
+ mScheduler->addResyncSample(timestamp, &periodFlushed);
+ if (periodFlushed) {
+ mVsyncModulator.onRefreshRateChangeCompleted();
}
}
@@ -1642,6 +1655,18 @@
return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled);
}
+nsecs_t SurfaceFlinger::getExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS {
+ DisplayStatInfo stats;
+ mScheduler->getDisplayStatInfo(&stats);
+ const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime();
+ // Inflate the expected present time if we're targetting the next vsync.
+ const nsecs_t correctedTime =
+ mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
+ ? presentTime
+ : presentTime + stats.vsyncPeriod;
+ return correctedTime;
+}
+
void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
switch (what) {
@@ -1767,6 +1792,12 @@
mVsyncModulator.onRefreshed(mHadClientComposition);
mLayersWithQueuedFrames.clear();
+ if (mVisibleRegionsDirty) {
+ mVisibleRegionsDirty = false;
+ if (mTracingEnabled) {
+ mTracing.notify("visibleRegionsDirty");
+ }
+ }
}
@@ -1776,9 +1807,6 @@
if (mVisibleRegionsDirty) {
computeLayerBounds();
- if (mTracingEnabled) {
- mTracing.notify("visibleRegionsDirty");
- }
}
for (auto& layer : mLayersPendingRefresh) {
@@ -2180,7 +2208,6 @@
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
ATRACE_NAME("rebuildLayerStacks VR Dirty");
- mVisibleRegionsDirty = false;
invalidateHwcGeometry();
for (const auto& pair : mDisplays) {
@@ -3250,8 +3277,7 @@
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (layer->hasReadyFrame()) {
frameQueued = true;
- nsecs_t expectedPresentTime;
- expectedPresentTime = mScheduler->expectedPresentTime();
+ const nsecs_t expectedPresentTime = getExpectedPresentTime();
if (layer->shouldPresentNow(expectedPresentTime)) {
mLayersWithQueuedFrames.push_back(layer);
} else {
@@ -3648,7 +3674,7 @@
bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
const Vector<ComposerState>& states) {
- nsecs_t expectedPresentTime = mScheduler->expectedPresentTime();
+ nsecs_t expectedPresentTime = getExpectedPresentTime();
// Do not present if the desiredPresentTime has not passed unless it is more than one second
// in the future. We ignore timestamps more than 1 second in the future for stability reasons.
if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime &&
@@ -4559,18 +4585,22 @@
if (const auto it = dumpers.find(flag); it != dumpers.end()) {
(it->second)(args, asProto, result);
- } else {
- if (asProto) {
- LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
- result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
- } else {
- dumpAllLocked(args, result);
- }
+ } else if (!asProto) {
+ dumpAllLocked(args, result);
}
if (locked) {
mStateLock.unlock();
}
+
+ LayersProto layersProto = dumpProtoFromMainThread();
+ if (asProto) {
+ result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+ } else {
+ auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+ result.append(LayerProtoParser::layerTreeToString(layerTree));
+ result.append("\n");
+ }
}
write(fd, result.c_str(), result.size());
return NO_ERROR;
@@ -4803,19 +4833,23 @@
result.append("\n");
}
-LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet,
- uint32_t traceFlags) const {
+LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
LayersProto layersProto;
- const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
- const State& state = useDrawing ? mDrawingState : mCurrentState;
- state.traverseInZOrder([&](Layer* layer) {
+ mDrawingState.traverseInZOrder([&](Layer* layer) {
LayerProto* layerProto = layersProto.add_layers();
- layer->writeToProto(layerProto, stateSet, traceFlags);
+ layer->writeToProtoDrawingState(layerProto, traceFlags);
+ layer->writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
});
return layersProto;
}
+LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
+ LayersProto layersProto;
+ postMessageSync(new LambdaMessage([&]() { layersProto = dumpDrawingStateProto(traceFlags); }));
+ return layersProto;
+}
+
LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(
const sp<DisplayDevice>& displayDevice) const {
LayersProto layersProto;
@@ -4836,7 +4870,7 @@
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (!layer->visibleRegion.isEmpty() && !display->getOutputLayersOrderedByZ().empty()) {
LayerProto* layerProto = layersProto.add_layers();
- layer->writeToProto(layerProto, displayDevice);
+ layer->writeToProtoCompositionState(layerProto, displayDevice);
}
});
@@ -4901,13 +4935,6 @@
colorizer.reset(result);
{
- LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
- auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
- result.append(LayerProtoParser::layerTreeToString(layerTree));
- result.append("\n");
- }
-
- {
StringAppendF(&result, "Composition layers\n");
mDrawingState.traverseInZOrder([&](Layer* layer) {
auto compositionLayer = layer->getCompositionLayer();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 63e74f5..49a048c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -263,7 +263,8 @@
status_t postMessageAsync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0);
// post a synchronous message to the main thread
- status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0);
+ status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0)
+ EXCLUDES(mStateLock);
// force full composition on all displays
void repaintEverything();
@@ -298,6 +299,11 @@
// TODO: this should be made accessible only to MessageQueue
void onMessageReceived(int32_t what);
+ // Returns the expected present time for this frame.
+ // When we are in negative offsets, we perform a correction so that the
+ // predicted vsync for the *next* frame is used instead.
+ nsecs_t getExpectedPresentTime();
+
// for debugging only
// TODO: this should be made accessible only to HWComposer
const Vector<sp<Layer>>& getLayerSortedByZForHwcDisplay(DisplayId displayId);
@@ -883,8 +889,9 @@
void dumpBufferingStats(std::string& result) const;
void dumpDisplayIdentificationData(std::string& result) const;
void dumpWideColorInfo(std::string& result) const;
- LayersProto dumpProtoInfo(LayerVector::StateSet stateSet,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL)
+ EXCLUDES(mStateLock);
void withTracingLock(std::function<void()> operation) REQUIRES(mStateLock);
LayersProto dumpVisibleLayersProtoInfo(const sp<DisplayDevice>& display) const;
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index c4ab066..9053f2c 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -162,7 +162,7 @@
LayersTraceProto entry;
entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
entry.set_where(where);
- LayersProto layers(mFlinger.dumpProtoInfo(LayerVector::StateSet::Drawing, mTraceFlags));
+ LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
entry.mutable_layers()->Swap(&layers);
return entry;
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index 12a349d..9ca116d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -35,6 +35,7 @@
MOCK_METHOD0(endResync, void());
MOCK_METHOD1(setPeriod, void(nsecs_t));
MOCK_METHOD0(getPeriod, nsecs_t());
+ MOCK_METHOD0(getIntendedPeriod, nsecs_t());
MOCK_METHOD1(setRefreshSkipCount, void(int));
MOCK_CONST_METHOD1(computeNextRefresh, nsecs_t(int));
MOCK_METHOD1(setIgnorePresentFences, void(bool));