Framework code for Attached Choreographer.
Allows a direct association of a Layer (via LayerHistory) to attached
choreographer.
The EventThread checks whether the vsync is in phase for a
choreographer.
Bug: 255838011
Test: atest AttachedChoreographerNativeTest
Change-Id: I9cb35bced5e6d4509609ad7698ab2902a31d5b98
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 76e9416..5e79a5c 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -532,6 +532,12 @@
const sp<EventThreadConnection>& connection) const {
const auto throttleVsync = [&] {
const auto& vsyncData = event.vsync.vsyncData;
+ if (connection->frameRate.isValid()) {
+ return !mVsyncSchedule->getTracker()
+ .isVSyncInPhase(vsyncData.preferredExpectedPresentationTime(),
+ connection->frameRate);
+ }
+
const auto expectedPresentTime =
TimePoint::fromNs(vsyncData.preferredExpectedPresentationTime());
return !mEventThreadCallback.isVsyncTargetForUid(expectedPresentTime,
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index b86553b..aa27091 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -97,6 +97,9 @@
const uid_t mOwnerUid;
const EventRegistrationFlags mEventRegistration;
+ /** The frame rate set to the attached choreographer. */
+ Fps frameRate;
+
private:
virtual void onFirstRef();
EventThread* const mEventThread;
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 55fa402..e853833 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -32,6 +32,7 @@
#include <utility>
#include "../Layer.h"
+#include "EventThread.h"
#include "LayerInfo.h"
namespace android::scheduler {
@@ -140,6 +141,22 @@
info->setLastPresentTime(presentTime, now, updateType, mModeChangePending, layerProps);
+ // Set frame rate to attached choreographer.
+ // TODO(b/260898223): Change to use layer hierarchy and handle frame rate vote.
+ if (updateType == LayerUpdateType::SetFrameRate) {
+ auto range = mAttachedChoreographers.equal_range(id);
+ auto it = range.first;
+ while (it != range.second) {
+ sp<EventThreadConnection> choreographerConnection = it->second.promote();
+ if (choreographerConnection) {
+ choreographerConnection->frameRate = layer->getFrameRateForLayerTree().rate;
+ it++;
+ } else {
+ it = mAttachedChoreographers.erase(it);
+ }
+ }
+ }
+
// Activate layer if inactive.
if (found == LayerStatus::LayerInInactiveMap) {
mActiveLayerInfos.insert(
@@ -294,6 +311,12 @@
return 0.f;
}
+void LayerHistory::attachChoreographer(int32_t layerId,
+ const sp<EventThreadConnection>& choreographerConnection) {
+ std::lock_guard lock(mLock);
+ mAttachedChoreographers.insert({layerId, wp<EventThreadConnection>(choreographerConnection)});
+}
+
auto LayerHistory::findLayer(int32_t id) -> std::pair<LayerStatus, LayerPair*> {
// the layer could be in either the active or inactive map, try both
auto it = mActiveLayerInfos.find(id);
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 5022906..68e7030 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -27,6 +27,8 @@
#include <utility>
#include <vector>
+#include "EventThread.h"
+
#include "RefreshRateSelector.h"
namespace android {
@@ -80,6 +82,9 @@
// return the frames per second of the layer with the given sequence id.
float getLayerFramerate(nsecs_t now, int32_t id) const;
+ void attachChoreographer(int32_t layerId,
+ const sp<EventThreadConnection>& choreographerConnection);
+
private:
friend class LayerHistoryTest;
friend class TestableScheduler;
@@ -117,6 +122,10 @@
LayerInfos mActiveLayerInfos GUARDED_BY(mLock);
LayerInfos mInactiveLayerInfos GUARDED_BY(mLock);
+ // Map keyed by layer ID (sequence) to choreographer connections.
+ std::unordered_multimap<int32_t, wp<EventThreadConnection>> mAttachedChoreographers
+ GUARDED_BY(mLock);
+
uint32_t mDisplayArea = 0;
// Whether to emit systrace output and debug logs.
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index e6f4665..eed57ef 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -47,6 +47,7 @@
#include "Display/DisplayMap.h"
#include "EventThread.h"
#include "FrameRateOverrideMappings.h"
+#include "FrontEnd/LayerHandle.h"
#include "OneShotTimer.h"
#include "SurfaceFlingerProperties.h"
#include "VSyncPredictor.h"
@@ -232,15 +233,21 @@
}
sp<EventThreadConnection> Scheduler::createConnectionInternal(
- EventThread* eventThread, EventRegistrationFlags eventRegistration) {
- return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
+ EventThread* eventThread, EventRegistrationFlags eventRegistration,
+ const sp<IBinder>& layerHandle) {
+ int32_t layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle));
+ auto connection = eventThread->createEventConnection([&] { resync(); }, eventRegistration);
+ mLayerHistory.attachChoreographer(layerId, connection);
+ return connection;
}
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
- ConnectionHandle handle, EventRegistrationFlags eventRegistration) {
+ ConnectionHandle handle, EventRegistrationFlags eventRegistration,
+ const sp<IBinder>& layerHandle) {
std::lock_guard<std::mutex> lock(mConnectionsLock);
RETURN_IF_INVALID_HANDLE(handle, nullptr);
- return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
+ return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration,
+ layerHandle);
}
sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 8dc2def..8c8fc21 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -147,7 +147,8 @@
std::chrono::nanoseconds readyDuration);
sp<IDisplayEventConnection> createDisplayEventConnection(
- ConnectionHandle, EventRegistrationFlags eventRegistration = {});
+ ConnectionHandle, EventRegistrationFlags eventRegistration = {},
+ const sp<IBinder>& layerHandle = nullptr);
sp<EventThreadConnection> getEventConnection(ConnectionHandle);
@@ -302,7 +303,8 @@
// Create a connection on the given EventThread.
ConnectionHandle createConnection(std::unique_ptr<EventThread>);
sp<EventThreadConnection> createConnectionInternal(
- EventThread*, EventRegistrationFlags eventRegistration = {});
+ EventThread*, EventRegistrationFlags eventRegistration = {},
+ const sp<IBinder>& layerHandle = nullptr);
// Update feature state machine to given state when corresponding timer resets or expires.
void kernelIdleTimerCallback(TimerState) EXCLUDES(mDisplayLock);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6020aba..4b3f9a1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1988,13 +1988,14 @@
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
- gui::ISurfaceComposer::VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) {
+ gui::ISurfaceComposer::VsyncSource vsyncSource, EventRegistrationFlags eventRegistration,
+ const sp<IBinder>& layerHandle) {
const auto& handle =
vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger
? mSfConnectionHandle
: mAppConnectionHandle;
- return mScheduler->createDisplayEventConnection(handle, eventRegistration);
+ return mScheduler->createDisplayEventConnection(handle, eventRegistration, layerHandle);
}
void SurfaceFlinger::scheduleCommit(FrameHint hint) {
@@ -7455,9 +7456,9 @@
binder::Status SurfaceComposerAIDL::createDisplayEventConnection(
VsyncSource vsyncSource, EventRegistration eventRegistration,
- sp<IDisplayEventConnection>* outConnection) {
+ const sp<IBinder>& layerHandle, sp<IDisplayEventConnection>* outConnection) {
sp<IDisplayEventConnection> conn =
- mFlinger->createDisplayEventConnection(vsyncSource, eventRegistration);
+ mFlinger->createDisplayEventConnection(vsyncSource, eventRegistration, layerHandle);
if (conn == nullptr) {
*outConnection = nullptr;
return binderStatusFromStatusT(BAD_VALUE);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1eb1fda..e7d4f77 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -509,7 +509,8 @@
sp<IDisplayEventConnection> createDisplayEventConnection(
gui::ISurfaceComposer::VsyncSource vsyncSource =
gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp,
- EventRegistrationFlags eventRegistration = {});
+ EventRegistrationFlags eventRegistration = {},
+ const sp<IBinder>& layerHandle = nullptr);
status_t captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
@@ -1391,6 +1392,7 @@
binder::Status bootFinished() override;
binder::Status createDisplayEventConnection(
VsyncSource vsyncSource, EventRegistration eventRegistration,
+ const sp<IBinder>& layerHandle,
sp<gui::IDisplayEventConnection>* outConnection) override;
binder::Status createConnection(sp<gui::ISurfaceComposerClient>* outClient) override;
binder::Status createDisplay(const std::string& displayName, bool secure,