SF: Permit changing DispSync offsets at runtime

This modifies EventThread such that its phase offsets for both
Choreographer and SurfaceFlinger may be modified at runtime. It also
plumbs this functionality up to the SurfaceFlinger debug interface so
that it is possible to rapidly test different offsets without
restarting the framework.

Change-Id: I426873f8553f931250dfebc9a8a4a78e9f1f4309
This commit is contained in:
Dan Stoza 2015-04-14 11:34:01 -07:00
parent e7d20eb000
commit db4ac3ce63
3 changed files with 69 additions and 8 deletions

View File

@ -71,6 +71,11 @@ void EventThread::sendVsyncHintOff() {
mVsyncHintSent = false;
}
void EventThread::setPhaseOffset(nsecs_t phaseOffset) {
Mutex::Autolock _l(mLock);
mVSyncSource->setPhaseOffset(phaseOffset);
}
void EventThread::sendVsyncHintOnLocked() {
struct itimerspec ts;
if(!mVsyncHintSent) {

View File

@ -51,6 +51,7 @@ public:
virtual ~VSyncSource() {}
virtual void setVSyncEnabled(bool enable) = 0;
virtual void setCallback(const sp<Callback>& callback) = 0;
virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
};
class EventThread : public Thread, private VSyncSource::Callback {
@ -99,6 +100,8 @@ public:
void dump(String8& result) const;
void sendVsyncHintOff();
void setPhaseOffset(nsecs_t phaseOffset);
private:
virtual bool threadLoop();
virtual void onFirstRef();

View File

@ -320,17 +320,20 @@ public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
const char* label) :
mValue(0),
mPhaseOffset(phaseOffset),
mTraceVsync(traceVsync),
mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
mVsyncEventLabel(String8::format("VSYNC-%s", label)),
mDispSync(dispSync) {}
mDispSync(dispSync),
mCallbackMutex(),
mCallback(),
mVsyncMutex(),
mPhaseOffset(phaseOffset),
mEnabled(false) {}
virtual ~DispSyncSource() {}
virtual void setVSyncEnabled(bool enable) {
// Do NOT lock the mutex here so as to avoid any mutex ordering issues
// with locking it in the onDispSyncEvent callback.
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
status_t err = mDispSync->addEventListener(mPhaseOffset,
static_cast<DispSync::Callback*>(this));
@ -348,18 +351,54 @@ public:
}
//ATRACE_INT(mVsyncOnLabel.string(), 0);
}
mEnabled = enable;
}
virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
Mutex::Autolock lock(mMutex);
Mutex::Autolock lock(mCallbackMutex);
mCallback = callback;
}
virtual void setPhaseOffset(nsecs_t phaseOffset) {
Mutex::Autolock lock(mVsyncMutex);
// Normalize phaseOffset to [0, period)
auto period = mDispSync->getPeriod();
phaseOffset %= period;
if (phaseOffset < 0) {
// If we're here, then phaseOffset is in (-period, 0). After this
// operation, it will be in (0, period)
phaseOffset += period;
}
mPhaseOffset = phaseOffset;
// If we're not enabled, we don't need to mess with the listeners
if (!mEnabled) {
return;
}
// Remove the listener with the old offset
status_t err = mDispSync->removeEventListener(
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error unregistering vsync callback: %s (%d)",
strerror(-err), err);
}
// Add a listener with the new offset
err = mDispSync->addEventListener(mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
strerror(-err), err);
}
}
private:
virtual void onDispSyncEvent(nsecs_t when) {
sp<VSyncSource::Callback> callback;
{
Mutex::Autolock lock(mMutex);
Mutex::Autolock lock(mCallbackMutex);
callback = mCallback;
if (mTraceVsync) {
@ -375,14 +414,18 @@ private:
int mValue;
const nsecs_t mPhaseOffset;
const bool mTraceVsync;
const String8 mVsyncOnLabel;
const String8 mVsyncEventLabel;
DispSync* mDispSync;
Mutex mCallbackMutex; // Protects the following
sp<VSyncSource::Callback> mCallback;
Mutex mMutex;
Mutex mVsyncMutex; // Protects the following
nsecs_t mPhaseOffset;
bool mEnabled;
};
void SurfaceFlinger::init() {
@ -2887,6 +2930,16 @@ status_t SurfaceFlinger::onTransact(
mForceFullDamage = static_cast<bool>(n);
return NO_ERROR;
}
case 1018: { // Modify Choreographer's phase offset
n = data.readInt32();
mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
return NO_ERROR;
}
case 1019: { // Modify SurfaceFlinger's phase offset
n = data.readInt32();
mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
return NO_ERROR;
}
}
}
return err;