Merge "Fix early firing when adding event listeners" into qt-dev
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index 23bfc02..55efcbf 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -84,9 +84,6 @@
explicit SurfaceControl(const sp<SurfaceControl>& other);
- SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbp, bool owned);
-
private:
// can't be copied
SurfaceControl& operator = (SurfaceControl& rhs);
@@ -95,6 +92,12 @@
friend class SurfaceComposerClient;
friend class Surface;
+ SurfaceControl(
+ const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& handle,
+ const sp<IGraphicBufferProducer>& gbp,
+ bool owned);
+
~SurfaceControl();
sp<Surface> generateSurfaceLocked() const;
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 12947b2..226d58f 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -339,53 +339,6 @@
if ((cnx->major == 1) && (cnx->minor == 5)) {
mVersionString = sVersionString15;
cnx->driverVersion = EGL_MAKE_VERSION(1, 5, 0);
- } else if ((cnx->major == 1) && (cnx->minor == 4)) {
- /* Querying extension strings for type Client */
- std::string typesExtString;
- static const char* clientExtensions =
- cnx->egl.eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
- if (clientExtensions != nullptr && strlen(clientExtensions) > 0) {
- typesExtString.append(clientExtensions);
- typesExtString.append(" ");
- }
-
- /* Adding extension strings for type Display */
- typesExtString.append(disp.queryString.extensions);
- mVersionString = sVersionString14;
- // Extensions needed for an EGL 1.4 implementation to be
- // able to support EGL 1.5 functionality
- std::vector<const char*> egl15extensions = {
- "EGL_EXT_client_extensions",
- // "EGL_EXT_platform_base", // implemented by EGL runtime
- "EGL_KHR_image_base",
- "EGL_KHR_fence_sync",
- "EGL_KHR_wait_sync",
- "EGL_KHR_create_context",
- "EGL_EXT_create_context_robustness",
- "EGL_KHR_gl_colorspace",
- "EGL_ANDROID_native_fence_sync",
- };
- bool extensionsFound = true;
- for (const auto& name : egl15extensions) {
- extensionsFound &= findExtension(typesExtString.c_str(), name);
- ALOGV("Extension %s: %s", name,
- findExtension(typesExtString.c_str(), name) ? "Found" : "Missing");
- }
- // NOTE: From the spec:
- // Creation of fence sync objects requires support from the bound
- // client API, and will not succeed unless the client API satisfies:
- // client API is OpenGL ES, and either the OpenGL ES version is 3.0
- // or greater, or the GL_OES_EGL_sync extension is supported.
- // We don't have a way to check the GL_EXTENSIONS string at this
- // point in the code, assume that GL_OES_EGL_sync is supported
- // because EGL_KHR_fence_sync is supported (as verified above).
- if (extensionsFound) {
- // Have everything needed to emulate EGL 1.5 so report EGL 1.5
- // to the application.
- mVersionString = sVersionString15;
- cnx->major = 1;
- cnx->minor = 5;
- }
}
if (mVersionString.empty()) {
ALOGW("Unexpected driver version: %d.%d, want 1.4 or 1.5", cnx->major, cnx->minor);
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index a6ed75f..6570704 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -579,10 +579,9 @@
}
if (info.batchParams.indexOfKey(ident) >= 0) {
- if (info.numActiveClients() == 1) {
- // This is the first connection, we need to activate the underlying h/w sensor.
- actuateHardware = true;
- }
+ if (info.numActiveClients() > 0 && !info.isActive) {
+ actuateHardware = true;
+ }
} else {
// Log error. Every activate call should be preceded by a batch() call.
ALOGE("\t >>>ERROR: activate called without batch");
@@ -631,6 +630,11 @@
if (err != NO_ERROR && enabled) {
// Failure when enabling the sensor. Clean up on failure.
info.removeBatchParamsForIdent(ident);
+ } else {
+ // Update the isActive flag if there is no error. If there is an error when disabling a
+ // sensor, still set the flag to false since the batch parameters have already been
+ // removed. This ensures that everything remains in-sync.
+ info.isActive = enabled;
}
}
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 71b918f..e8685c2 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -165,6 +165,9 @@
// requested by the client.
KeyedVector<void*, BatchParams> batchParams;
+ // Flag to track if the sensor is active
+ bool isActive = false;
+
// Sets batch parameters for this ident. Returns error if this ident is not already present
// in the KeyedVector above.
status_t setBatchParamsForIdent(void* ident, int flags, int64_t samplingPeriodNs,
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 508be13..e54b460 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -76,9 +76,18 @@
uint32_t flags, const sp<IBinder>& parentHandle,
LayerMetadata metadata, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) {
+ sp<Layer> parent = nullptr;
+ if (parentHandle != nullptr) {
+ auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
+ parent = layerHandle->owner.promote();
+ if (parent == nullptr) {
+ return NAME_NOT_FOUND;
+ }
+ }
+
// We rely on createLayer to check permissions.
return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
- parentHandle);
+ &parent);
}
status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0211df9..2bbac72 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -130,6 +130,7 @@
}
mFrameTracker.logAndResetStats(mName);
+
mFlinger->onLayerDestroyed();
}
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 240c84e..e70bfe4 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -31,9 +31,9 @@
const status_t ret =
mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, 0, 0,
PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor,
- LayerMetadata(), &mIBinder, &mGbp, nullptr);
+ LayerMetadata(), &mIBinder, &mGbp, &mLayer);
if (ret) {
- ALOGE("failed to create color layer");
+ ALOGE("failed to color layer");
return false;
}
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 5aab616..871f556 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -210,8 +210,7 @@
const nsecs_t baseTime = now - mReferenceTime;
const nsecs_t numPeriodsSinceReference = baseTime / mPeriod;
const nsecs_t predictedReference = mReferenceTime + numPeriodsSinceReference * mPeriod;
- const nsecs_t phaseCorrection = mPhase + listener.mPhase;
- listener.mLastEventTime = predictedReference + phaseCorrection;
+ listener.mLastEventTime = predictedReference + mPhase + listener.mPhase;
// If we're very close in time to the predicted last event time,
// and we're not very close to the next predicted last event time
// then we need to back up the last event time so that we can
@@ -282,7 +281,6 @@
return NO_ERROR;
}
}
-
return BAD_VALUE;
}
@@ -528,21 +526,40 @@
mNumResyncSamples = 0;
}
-bool DispSync::addResyncSample(nsecs_t timestamp) {
+bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) {
Mutex::Autolock lock(mMutex);
ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
- size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
+ *periodChanged = false;
+ const size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
mResyncSamples[idx] = timestamp;
if (mNumResyncSamples == 0) {
mPhase = 0;
- mReferenceTime = timestamp;
ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
"mReferenceTime = %" PRId64,
- mName, ns2us(mPeriod), ns2us(mReferenceTime));
- mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+ mName, ns2us(mPeriod), ns2us(timestamp));
+ } else if (mPendingPeriod > 0) {
+ // mNumResyncSamples > 0, so priorIdx won't overflow
+ const size_t priorIdx = (mFirstResyncSample + mNumResyncSamples - 1) % MAX_RESYNC_SAMPLES;
+ 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.
+ resetLocked();
+ mPeriod = mPendingPeriod;
+ mPendingPeriod = 0;
+ if (mTraceDetailedInfo) {
+ ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod);
+ }
+ *periodChanged = true;
+ }
}
+ // Always update the reference time with the most recent timestamp.
+ mReferenceTime = timestamp;
+ mThread->updateModel(mPeriod, mPhase, mReferenceTime);
if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
mNumResyncSamples++;
@@ -565,7 +582,7 @@
// Check against kErrorThreshold / 2 to add some hysteresis before having to
// resync again
- bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2);
+ bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2) && mPendingPeriod == 0;
ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked");
return !modelLocked;
}
@@ -597,9 +614,10 @@
void DispSync::setPeriod(nsecs_t period) {
Mutex::Autolock lock(mMutex);
- mPeriod = period;
- mPhase = 0;
- mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+ if (mTraceDetailedInfo) {
+ ATRACE_INT("DispSync:PendingPeriod", period);
+ }
+ mPendingPeriod = period;
}
nsecs_t DispSync::getPeriod() {
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index de2b874..8f8b8e7 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) = 0;
+ virtual bool addResyncSample(nsecs_t timestamp, bool* periodChanged) = 0;
virtual void endResync() = 0;
virtual void setPeriod(nsecs_t period) = 0;
virtual nsecs_t getPeriod() = 0;
@@ -119,7 +119,13 @@
// addPresentFence returns true indicating that the model has drifted away
// from the hardware vsync events.
void beginResync() override;
- bool addResyncSample(nsecs_t timestamp) 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
+ // 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;
void endResync() override;
// The setPeriod method sets the vsync event model's period to a specific
@@ -199,6 +205,12 @@
// nanoseconds.
nsecs_t mPeriod;
+ // 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
+ // vsync frequency.
+ nsecs_t mPendingPeriod = 0;
+
// mPhase is the phase offset of the modeled vsync events. It is the
// number of nanoseconds from time 0 to the first vsync event.
nsecs_t mPhase;
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 6e89648..00948ae 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -87,19 +87,7 @@
}
}
-void DispSyncSource::pauseVsyncCallback(bool pause) {
- std::lock_guard lock(mVsyncMutex);
- mCallbackPaused = pause;
-}
-
void DispSyncSource::onDispSyncEvent(nsecs_t when) {
- {
- std::lock_guard lock(mVsyncMutex);
- if (mCallbackPaused) {
- return;
- }
- }
-
VSyncSource::Callback* callback;
{
std::lock_guard lock(mCallbackMutex);
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 2858678..4759699 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -33,7 +33,6 @@
void setVSyncEnabled(bool enable) override;
void setCallback(VSyncSource::Callback* callback) override;
void setPhaseOffset(nsecs_t phaseOffset) override;
- void pauseVsyncCallback(bool pause) override;
private:
// The following method is the implementation of the DispSync::Callback.
@@ -55,7 +54,6 @@
std::mutex mVsyncMutex;
nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
bool mEnabled GUARDED_BY(mVsyncMutex) = false;
- bool mCallbackPaused GUARDED_BY(mVsyncMutex) = false;
};
} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index a760079..a6c7e6c 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -210,12 +210,6 @@
mVSyncSource->setPhaseOffset(phaseOffset);
}
-void EventThread::pauseVsyncCallback(bool pause) {
- std::lock_guard<std::mutex> lock(mMutex);
- ATRACE_INT("vsyncPaused", pause);
- mVSyncSource->pauseVsyncCallback(pause);
-}
-
sp<EventThreadConnection> EventThread::createEventConnection(
ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) const {
return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 67e6de9..7107d63 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -66,9 +66,6 @@
virtual void setVSyncEnabled(bool enable) = 0;
virtual void setCallback(Callback* callback) = 0;
virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
-
- // pause/resume vsync callback generation
- virtual void pauseVsyncCallback(bool pause) = 0;
};
class EventThreadConnection : public BnDisplayEventConnection {
@@ -125,8 +122,6 @@
// Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer.
virtual void requestNextVsync(const sp<EventThreadConnection>& connection,
bool resetIdleTimer) = 0;
-
- virtual void pauseVsyncCallback(bool pause) = 0;
};
namespace impl {
@@ -162,8 +157,6 @@
void setPhaseOffset(nsecs_t phaseOffset) override;
- void pauseVsyncCallback(bool pause) override;
-
private:
friend EventThreadTest;
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index cbcaade..a85660a 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -68,8 +68,8 @@
void dump(std::string& result) const override;
private:
- Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
- Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
+ Offsets getDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
+ Offsets getHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType =
RefreshRateConfigs::RefreshRateType::DEFAULT;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index b1c39ef..1b154a4 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -178,12 +178,6 @@
mConnections[handle->id]->thread->setPhaseOffset(phaseOffset);
}
-void Scheduler::pauseVsyncCallback(const android::sp<android::Scheduler::ConnectionHandle>& handle,
- bool pause) {
- RETURN_IF_INVALID();
- mConnections[handle->id]->thread->pauseVsyncCallback(pause);
-}
-
void Scheduler::getDisplayStatInfo(DisplayStatInfo* stats) {
stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
@@ -255,7 +249,6 @@
void Scheduler::setVsyncPeriod(const nsecs_t period) {
std::lock_guard<std::mutex> lock(mHWVsyncLock);
- mPrimaryDispSync->reset();
mPrimaryDispSync->setPeriod(period);
if (!mPrimaryHWVsyncEnabled) {
@@ -265,12 +258,13 @@
}
}
-void Scheduler::addResyncSample(const nsecs_t timestamp) {
+void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodChanged) {
bool needsHwVsync = false;
+ *periodChanged = false;
{ // Scope for the lock
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (mPrimaryHWVsyncEnabled) {
- needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
+ needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodChanged);
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 1318fbb..134dc0b 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -131,9 +131,6 @@
// Offers ability to modify phase offset in the event thread.
void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
- // pause/resume vsync callback generation to avoid sending vsync callbacks during config switch
- void pauseVsyncCallback(const sp<ConnectionHandle>& handle, bool pause);
-
void getDisplayStatInfo(DisplayStatInfo* stats);
void enableHardwareVsync();
@@ -142,7 +139,9 @@
// Creates a callback for resyncing.
ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod);
void setRefreshSkipCount(int count);
- void addResyncSample(const nsecs_t timestamp);
+ // 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);
void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
void setIgnorePresentFences(bool ignore);
nsecs_t expectedPresentTime();
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index dab2003..1a0de08 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -30,9 +30,10 @@
*/
class VSyncModulator {
private:
- // Number of frames we'll keep the early phase offsets once they are activated. This acts as a
- // low-pass filter in case the client isn't quick enough in sending new transactions.
- const int MIN_EARLY_FRAME_COUNT = 2;
+ // Number of frames we'll keep the early phase offsets once they are activated for a
+ // transaction. This acts as a low-pass filter in case the client isn't quick enough in
+ // sending new transactions.
+ const int MIN_EARLY_FRAME_COUNT_TRANSACTION = 2;
public:
struct Offsets {
@@ -85,7 +86,7 @@
void setTransactionStart(Scheduler::TransactionStart transactionStart) {
if (transactionStart == Scheduler::TransactionStart::EARLY) {
- mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT;
+ mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
}
// An early transaction stays an early transaction.
@@ -103,6 +104,26 @@
updateOffsets();
}
+ // Called when we send a refresh rate change to hardware composer, so that
+ // we can move into early offsets.
+ void onRefreshRateChangeInitiated() {
+ if (mRefreshRateChangePending) {
+ return;
+ }
+ mRefreshRateChangePending = true;
+ updateOffsets();
+ }
+
+ // 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() {
+ if (!mRefreshRateChangePending) {
+ return;
+ }
+ mRefreshRateChangePending = false;
+ updateOffsets();
+ }
+
void onRefreshed(bool usedRenderEngine) {
bool updateOffsetsNeeded = false;
if (mRemainingEarlyFrameCount > 0) {
@@ -147,8 +168,10 @@
}
Offsets getOffsets() {
+ // Early offsets are used if we're in the middle of a refresh rate
+ // change, or if we recently begin a transaction.
if (mTransactionStart == Scheduler::TransactionStart::EARLY ||
- mRemainingEarlyFrameCount > 0) {
+ mRemainingEarlyFrameCount > 0 || mRefreshRateChangePending) {
return mEarlyOffsets;
} else if (mLastFrameUsedRenderEngine) {
return mEarlyGlOffsets;
@@ -173,6 +196,7 @@
std::atomic<Scheduler::TransactionStart> mTransactionStart =
Scheduler::TransactionStart::NORMAL;
std::atomic<bool> mLastFrameUsedRenderEngine = false;
+ std::atomic<bool> mRefreshRateChangePending = false;
std::atomic<int> mRemainingEarlyFrameCount = 0;
};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bd3f156..3c25564 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -922,11 +922,15 @@
mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig;
if (!mDesiredActiveConfigChanged) {
- // This is the first time we set the desired
- mScheduler->pauseVsyncCallback(mAppConnectionHandle, true);
-
// This will trigger HWC refresh without resetting the idle timer.
repaintEverythingForHWC();
+ // Start receiving vsync samples now, so that we can detect a period
+ // switch.
+ mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+ mPhaseOffsets->setRefreshRateType(info.type);
+ const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+ mVsyncModulator.onRefreshRateChangeInitiated();
+ mVsyncModulator.setPhaseOffsets(early, gl, late);
}
mDesiredActiveConfigChanged = true;
ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
@@ -959,6 +963,7 @@
display->setActiveConfig(mUpcomingActiveConfig.configId);
mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+ mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
mVsyncModulator.setPhaseOffsets(early, gl, late);
ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
@@ -1000,8 +1005,6 @@
// display is not valid or we are already in the requested mode
// on both cases there is nothing left to do
std::lock_guard<std::mutex> lock(mActiveConfigLock);
- mScheduler->pauseVsyncCallback(mAppConnectionHandle, false);
- mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
mDesiredActiveConfigChanged = false;
ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
return false;
@@ -1012,6 +1015,7 @@
// Make sure the desired config is still allowed
if (!isDisplayConfigAllowed(desiredActiveConfig.configId)) {
std::lock_guard<std::mutex> lock(mActiveConfigLock);
+ mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
mDesiredActiveConfig.configId = display->getActiveConfig();
return false;
}
@@ -1403,7 +1407,11 @@
return;
}
- mScheduler->addResyncSample(timestamp);
+ bool periodChanged = false;
+ mScheduler->addResyncSample(timestamp, &periodChanged);
+ if (periodChanged) {
+ mVsyncModulator.onRefreshRateChangeDetected();
+ }
}
void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
@@ -1436,8 +1444,6 @@
return;
}
- mPhaseOffsets->setRefreshRateType(refreshRate);
-
if (desiredConfigId == display->getActiveConfig()) {
return;
}
@@ -3393,20 +3399,12 @@
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc,
const sp<Layer>& lbc,
- const sp<IBinder>& parentHandle,
+ const sp<Layer>& parent,
bool addToCurrentState)
{
// add this layer to the current state list
{
Mutex::Autolock _l(mStateLock);
- sp<Layer> parent;
- if (parentHandle != nullptr) {
- parent = fromHandle(parentHandle);
- if (parent == nullptr) {
- return NAME_NOT_FOUND;
- }
- }
-
if (mNumLayers >= MAX_LAYERS) {
ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
MAX_LAYERS);
@@ -4015,10 +4013,10 @@
return flags;
}
-status_t SurfaceFlinger::createLayer(
- const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags, LayerMetadata metadata, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, const sp<IBinder>& parentHandle) {
+status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
+ uint32_t h, PixelFormat format, uint32_t flags,
+ LayerMetadata metadata, sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent) {
if (int32_t(w|h) < 0) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
@@ -4083,14 +4081,12 @@
return result;
}
- mLayersByLocalBinderToken.emplace((*handle)->localBinder(), layer);
-
if (primaryDisplayOnly) {
layer->setPrimaryDisplayOnly();
}
bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
- result = addClientLayer(client, *handle, *gbp, layer, parentHandle,
+ result = addClientLayer(client, *handle, *gbp, layer, *parent,
addToCurrentState);
if (result != NO_ERROR) {
return result;
@@ -4208,16 +4204,6 @@
mCurrentState.layersSortedByZ.remove(layer);
}
markLayerPendingRemovalLocked(layer);
-
- auto it = mLayersByLocalBinderToken.begin();
- while (it != mLayersByLocalBinderToken.end()) {
- if (it->second == layer) {
- it = mLayersByLocalBinderToken.erase(it);
- } else {
- it++;
- }
- }
-
layer.clear();
}
@@ -5485,50 +5471,34 @@
const bool mChildrenOnly;
};
- int reqWidth = 0;
- int reqHeight = 0;
- sp<Layer> parent;
+ auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
+ auto parent = layerHandle->owner.promote();
+
+ if (parent == nullptr || parent->isRemovedFromCurrentState()) {
+ ALOGE("captureLayers called with a removed parent");
+ return NAME_NOT_FOUND;
+ }
+
+ const int uid = IPCThreadState::self()->getCallingUid();
+ const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
+ if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
+ ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
+ return PERMISSION_DENIED;
+ }
+
Rect crop(sourceCrop);
- std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
+ if (sourceCrop.width() <= 0) {
+ crop.left = 0;
+ crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
+ }
- {
- Mutex::Autolock _l(mStateLock);
+ if (sourceCrop.height() <= 0) {
+ crop.top = 0;
+ crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
+ }
- parent = fromHandle(layerHandleBinder);
- if (parent == nullptr || parent->isRemovedFromCurrentState()) {
- ALOGE("captureLayers called with an invalid or removed parent");
- return NAME_NOT_FOUND;
- }
-
- const int uid = IPCThreadState::self()->getCallingUid();
- const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
- if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
- ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
- return PERMISSION_DENIED;
- }
-
- if (sourceCrop.width() <= 0) {
- crop.left = 0;
- crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
- }
-
- if (sourceCrop.height() <= 0) {
- crop.top = 0;
- crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
- }
- reqWidth = crop.width() * frameScale;
- reqHeight = crop.height() * frameScale;
-
- for (const auto& handle : excludeHandles) {
- sp<Layer> excludeLayer = fromHandle(handle);
- if (excludeLayer != nullptr) {
- excludeLayers.emplace(excludeLayer);
- } else {
- ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
- return NAME_NOT_FOUND;
- }
- }
- } // mStateLock
+ int32_t reqWidth = crop.width() * frameScale;
+ int32_t reqHeight = crop.height() * frameScale;
// really small crop or frameScale
if (reqWidth <= 0) {
@@ -5538,6 +5508,18 @@
reqHeight = 1;
}
+ std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
+ for (const auto& handle : excludeHandles) {
+ BBinder* local = handle->localBinder();
+ if (local != nullptr) {
+ auto layerHandle = reinterpret_cast<Layer::Handle*>(local);
+ excludeLayers.emplace(layerHandle->owner.promote());
+ } else {
+ ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
+ return NAME_NOT_FOUND;
+ }
+ }
+
LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, reqDataspace, childrenOnly);
auto traverseLayers = [parent, childrenOnly,
&excludeLayers](const LayerVector::Visitor& visitor) {
@@ -5884,18 +5866,6 @@
mFlinger->setInputWindowsFinished();
}
-sp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
- BBinder *b = handle->localBinder();
- if (b == nullptr) {
- return nullptr;
- }
- auto it = mLayersByLocalBinderToken.find(b);
- if (it != mLayersByLocalBinderToken.end()) {
- return it->second.promote();
- }
- return nullptr;
-}
-
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d8108c5..4c482a1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -313,8 +313,6 @@
return mTransactionCompletedThread;
}
- sp<Layer> fromHandle(const sp<IBinder>& handle) REQUIRES(mStateLock);
-
private:
friend class BufferLayer;
friend class BufferQueueLayer;
@@ -575,10 +573,9 @@
/* ------------------------------------------------------------------------
* Layer management
*/
- status_t createLayer(
- const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags, LayerMetadata metadata,
- sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, const sp<IBinder>& parentHandle);
+ status_t createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t flags, LayerMetadata metadata,
+ sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
status_t createBufferQueueLayer(const sp<Client>& client, const String8& name, uint32_t w,
uint32_t h, uint32_t flags, LayerMetadata metadata,
@@ -610,7 +607,7 @@
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc,
const sp<Layer>& lbc,
- const sp<IBinder>& parentHandle,
+ const sp<Layer>& parent,
bool addToCurrentState);
// Traverse through all the layers and compute and cache its bounds.
@@ -984,9 +981,6 @@
std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays;
std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
- // protected by mStateLock
- std::unordered_map<BBinder*, wp<Layer>> mLayersByLocalBinderToken;
-
// don't use a lock for these, we don't care
int mDebugRegion = 0;
bool mDebugDisableHWC = false;
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index d3c87bf..f121a95 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -19,7 +19,6 @@
srcs: [
"BufferGenerator.cpp",
"Credentials_test.cpp",
- "InvalidHandles_test.cpp",
"Stress_test.cpp",
"SurfaceInterceptor_test.cpp",
"Transaction_test.cpp",
diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp
deleted file mode 100644
index 42d1f5a..0000000
--- a/services/surfaceflinger/tests/InvalidHandles_test.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <binder/Binder.h>
-
-#include <gtest/gtest.h>
-
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
-#include <private/gui/ComposerService.h>
-#include <ui/Rect.h>
-
-namespace android {
-namespace {
-
-class NotALayer : public BBinder {};
-
-/**
- * For all of these tests we make a SurfaceControl with an invalid layer handle
- * and verify we aren't able to trick SurfaceFlinger.
- */
-class InvalidHandleTest : public ::testing::Test {
-protected:
- sp<SurfaceComposerClient> mScc;
- sp<SurfaceControl> mNotSc;
- void SetUp() override {
- mScc = new SurfaceComposerClient;
- ASSERT_EQ(NO_ERROR, mScc->initCheck());
- mNotSc = makeNotSurfaceControl();
- }
-
- sp<SurfaceControl> makeNotSurfaceControl() {
- return new SurfaceControl(mScc, new NotALayer(), nullptr, true);
- }
-};
-
-TEST_F(InvalidHandleTest, createSurfaceInvalidHandle) {
- auto notSc = makeNotSurfaceControl();
- ASSERT_EQ(nullptr,
- mScc->createSurface(String8("lolcats"), 19, 47, PIXEL_FORMAT_RGBA_8888, 0,
- notSc.get())
- .get());
-}
-
-TEST_F(InvalidHandleTest, captureLayersInvalidHandle) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<GraphicBuffer> outBuffer;
-
- ASSERT_EQ(NAME_NOT_FOUND,
- sf->captureLayers(mNotSc->getHandle(), &outBuffer, Rect::EMPTY_RECT, 1.0f));
-}
-
-} // namespace
-} // namespace android
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index a8d09ea..be862c9 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
{
"presubmit": {
- "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*"
+ "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*"
}
}
diff --git a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
index 92bdebd..2e705da 100644
--- a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
@@ -142,23 +142,5 @@
}
}
-TEST_F(DispSyncSourceTest, pauseCallbacks) {
- createDispSyncSource();
- EXPECT_TRUE(mDispSyncSource);
-
- mDispSyncSource->setVSyncEnabled(true);
- EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count());
- mDispSync->triggerCallback();
- EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value());
-
- mDispSyncSource->pauseVsyncCallback(true);
- mDispSync->triggerCallback();
- EXPECT_FALSE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value());
-
- mDispSyncSource->pauseVsyncCallback(false);
- mDispSync->triggerCallback();
- EXPECT_TRUE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value());
-}
-
} // namespace
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index d83f1bd..a13b888 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -2830,7 +2830,6 @@
struct DispSyncIsSupportedVariant {
static void setupBeginResyncCallExpectations(DisplayTransactionTest* test) {
- EXPECT_CALL(*test->mPrimaryDispSync, reset()).Times(1);
EXPECT_CALL(*test->mPrimaryDispSync, setPeriod(DEFAULT_REFRESH_RATE)).Times(1);
EXPECT_CALL(*test->mPrimaryDispSync, beginResync()).Times(1);
}
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 249c78f..83a92c8 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -73,7 +73,6 @@
void expectVSyncSetEnabledCallReceived(bool expectedState);
void expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset);
- void expectVSyncPauseVsyncCallbackCallReceived(bool expectedPause);
VSyncSource::Callback* expectVSyncSetCallbackCallReceived();
void expectInterceptCallReceived(nsecs_t expectedTimestamp);
void expectVsyncEventReceivedByConnection(const char* name,
@@ -88,7 +87,6 @@
AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
AsyncCallRecorder<void (*)(nsecs_t)> mVSyncSetPhaseOffsetCallRecorder;
- AsyncCallRecorder<void (*)(bool)> mVSyncPauseVsyncCallbackCallRecorder;
AsyncCallRecorder<void (*)()> mResyncCallRecorder;
AsyncCallRecorder<void (*)()> mResetIdleTimerCallRecorder;
AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
@@ -114,9 +112,6 @@
EXPECT_CALL(mVSyncSource, setPhaseOffset(_))
.WillRepeatedly(Invoke(mVSyncSetPhaseOffsetCallRecorder.getInvocable()));
- EXPECT_CALL(mVSyncSource, pauseVsyncCallback(_))
- .WillRepeatedly(Invoke(mVSyncPauseVsyncCallbackCallRecorder.getInvocable()));
-
createThread();
mConnection = createConnection(mConnectionEventCallRecorder);
@@ -166,12 +161,6 @@
EXPECT_EQ(expectedPhaseOffset, std::get<0>(args.value()));
}
-void EventThreadTest::expectVSyncPauseVsyncCallbackCallReceived(bool expectedPause) {
- auto args = mVSyncPauseVsyncCallbackCallRecorder.waitForCall();
- ASSERT_TRUE(args.has_value());
- EXPECT_EQ(expectedPause, std::get<0>(args.value()));
-}
-
VSyncSource::Callback* EventThreadTest::expectVSyncSetCallbackCallReceived() {
auto callbackSet = mVSyncSetCallbackCallRecorder.waitForCall();
return callbackSet.has_value() ? std::get<0>(callbackSet.value()) : nullptr;
@@ -431,16 +420,6 @@
expectVSyncSetPhaseOffsetCallReceived(321);
}
-TEST_F(EventThreadTest, pauseVsyncCallbackForwardsToVSyncSource) {
- mThread->pauseVsyncCallback(true);
- expectVSyncPauseVsyncCallbackCallReceived(true);
-}
-
-TEST_F(EventThreadTest, resumeVsyncCallbackForwardsToVSyncSource) {
- mThread->pauseVsyncCallback(false);
- expectVSyncPauseVsyncCallbackCallReceived(false);
-}
-
TEST_F(EventThreadTest, postHotplugInternalDisconnect) {
mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false);
expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index afcda5b..12a349d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -31,7 +31,7 @@
MOCK_METHOD0(reset, void());
MOCK_METHOD1(addPresentFence, bool(const std::shared_ptr<FenceTime>&));
MOCK_METHOD0(beginResync, void());
- MOCK_METHOD1(addResyncSample, bool(nsecs_t));
+ MOCK_METHOD2(addResyncSample, bool(nsecs_t, bool*));
MOCK_METHOD0(endResync, void());
MOCK_METHOD1(setPeriod, void(nsecs_t));
MOCK_METHOD0(getPeriod, nsecs_t());