SurfaceFlinger: throttle applications based on uid
Add the ability for SurfaceFlinger to be able to throttle down to
a divider of the refresh rate (i.e. for 30/45 for 90Hz)
Change-Id: I6bfd6f43ee1f30e771a136c558d8ae9a6d7fbe0f
Test: Manually via 1039 SF backdoor
Bug: 170502573
Bug: 169270763
Bug: 169271059
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index bf2a509..bf5be47 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -31,6 +31,8 @@
#include <android-base/stringprintf.h>
+#include <binder/IPCThreadState.h>
+
#include <cutils/compiler.h>
#include <cutils/sched_policy.h>
@@ -123,11 +125,12 @@
} // namespace
-EventThreadConnection::EventThreadConnection(EventThread* eventThread,
+EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid,
ResyncCallback resyncCallback,
ISurfaceComposer::ConfigChanged configChanged)
: resyncCallback(std::move(resyncCallback)),
mConfigChanged(configChanged),
+ mOwnerUid(callingUid),
mEventThread(eventThread),
mChannel(gui::BitTube::DefaultSize) {}
@@ -170,10 +173,12 @@
EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
android::frametimeline::TokenManager* tokenManager,
- InterceptVSyncsCallback interceptVSyncsCallback)
+ InterceptVSyncsCallback interceptVSyncsCallback,
+ ThrottleVsyncCallback throttleVsyncCallback)
: mVSyncSource(std::move(vsyncSource)),
mTokenManager(tokenManager),
mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
+ mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
mThreadName(mVSyncSource->getName()) {
mVSyncSource->setCallback(this);
@@ -216,8 +221,9 @@
sp<EventThreadConnection> EventThread::createEventConnection(
ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const {
- return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
- configChanged);
+ return new EventThreadConnection(const_cast<EventThread*>(this),
+ IPCThreadState::self()->getCallingUid(),
+ std::move(resyncCallback), configChanged);
}
status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -443,6 +449,11 @@
bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
const sp<EventThreadConnection>& connection) const {
+ const auto throttleVsync = [&] {
+ return mThrottleVsyncCallback &&
+ mThrottleVsyncCallback(event.vsync.expectedVSyncTimestamp, connection->mOwnerUid);
+ };
+
switch (event.header.type) {
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
return true;
@@ -458,12 +469,22 @@
case VSyncRequest::SingleSuppressCallback:
connection->vsyncRequest = VSyncRequest::None;
return false;
- case VSyncRequest::Single:
+ case VSyncRequest::Single: {
+ if (throttleVsync()) {
+ return false;
+ }
connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
return true;
+ }
case VSyncRequest::Periodic:
+ if (throttleVsync()) {
+ return false;
+ }
return true;
default:
+ // We don't throttle vsync if the app set a vsync request rate
+ // since there is no easy way to do that and this is a very
+ // rare case
return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
}