summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy McFadden <fadden@android.com>2014-06-10 14:43:32 -0700
committerAndy McFadden <fadden@android.com>2014-06-11 10:19:08 -0700
commit645b1f7ffb41d21a60765d1ec54ba82f14a36a59 (patch)
treee5e55c7fa254cc9ba69af1c8de3a1a1711042921
parent5167ec68fed047bf65b1eb0c6091534682135eef (diff)
downloadframeworks_native-645b1f7ffb41d21a60765d1ec54ba82f14a36a59.zip
frameworks_native-645b1f7ffb41d21a60765d1ec54ba82f14a36a59.tar.gz
frameworks_native-645b1f7ffb41d21a60765d1ec54ba82f14a36a59.tar.bz2
Replace "lower power mode" experiment
This replaces the previous low-power mode experiment, which discarded refresh events, with a new experiment that alters the refresh period. (see also I2849e5ea335c0d2509fea1c315392bce7f20451d ) The feature is enabled by specifying a nonzero value for the "refresh skip count", which indicates the number of periods to skip. For example, the command: adb shell service call SurfaceFlinger 1016 i32 1 sets a skip count of '1', yielding a 30Hz refresh rate on a device with a 60Hz display. Changing the last value to '2' would set the refresh to 20Hz. '0' returns to the default behavior. Bug 15523257 Change-Id: I00039c22a55750e74035644c63800e4bee1c774a
-rw-r--r--services/surfaceflinger/DispSync.cpp49
-rw-r--r--services/surfaceflinger/DispSync.h10
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp7
3 files changed, 32 insertions, 34 deletions
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index c60834e..12da9a5 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -53,10 +53,7 @@ class DispSyncThread: public Thread {
public:
DispSyncThread():
- mLowPowerMode(false),
mStop(false),
- mLastVsyncSent(false),
- mLastBufferFull(false),
mPeriod(0),
mPhase(0),
mWakeupLatency(0) {
@@ -140,18 +137,7 @@ public:
}
if (callbackInvocations.size() > 0) {
- if (mLowPowerMode) {
- if (!mLastVsyncSent || !mLastBufferFull) {
- fireCallbackInvocations(callbackInvocations);
- mLastVsyncSent = true;
- } else
- mLastVsyncSent = false;
- } else {
- fireCallbackInvocations(callbackInvocations);
- }
- mLastBufferFull = true;
- } else {
- mLastBufferFull = false;
+ fireCallbackInvocations(callbackInvocations);
}
}
@@ -205,7 +191,6 @@ public:
return !mEventListeners.empty();
}
- bool mLowPowerMode;
private:
struct EventListener {
@@ -278,8 +263,6 @@ private:
}
bool mStop;
- bool mLastVsyncSent;
- bool mLastBufferFull;
nsecs_t mPeriod;
nsecs_t mPhase;
@@ -304,8 +287,10 @@ private:
bool mParity;
};
-DispSync::DispSync() {
- mThread = new DispSyncThread();
+DispSync::DispSync() :
+ mRefreshSkipCount(0),
+ mThread(new DispSyncThread()) {
+
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
reset();
@@ -404,8 +389,11 @@ status_t DispSync::addEventListener(nsecs_t phase,
return mThread->addEventListener(phase, callback);
}
-void DispSync::setLowPowerMode(bool enabled) {
- mThread->mLowPowerMode = enabled;
+void DispSync::setRefreshSkipCount(int count) {
+ Mutex::Autolock lock(mMutex);
+ ALOGD("setRefreshSkipCount(%d)", count);
+ mRefreshSkipCount = count;
+ updateModelLocked();
}
status_t DispSync::removeEventListener(const sp<Callback>& callback) {
@@ -456,6 +444,9 @@ void DispSync::updateModelLocked() {
ATRACE_INT64("DispSync:Phase", mPhase);
}
+ // Artificially inflate the period if requested.
+ mPeriod += mPeriod * mRefreshSkipCount;
+
mThread->updateModel(mPeriod, mPhase);
}
}
@@ -465,15 +456,19 @@ void DispSync::updateErrorLocked() {
return;
}
+ // Need to compare present fences against the un-adjusted refresh period,
+ // since they might arrive between two events.
+ nsecs_t period = mPeriod / (1 + mRefreshSkipCount);
+
int numErrSamples = 0;
nsecs_t sqErrSum = 0;
for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
nsecs_t sample = mPresentTimes[i];
if (sample > mPhase) {
- nsecs_t sampleErr = (sample - mPhase) % mPeriod;
- if (sampleErr > mPeriod / 2) {
- sampleErr -= mPeriod;
+ nsecs_t sampleErr = (sample - mPhase) % period;
+ if (sampleErr > period / 2) {
+ sampleErr -= period;
}
sqErrSum += sampleErr * sampleErr;
numErrSamples++;
@@ -510,8 +505,8 @@ void DispSync::dump(String8& result) const {
Mutex::Autolock lock(mMutex);
result.appendFormat("present fences are %s\n",
kIgnorePresentFences ? "ignored" : "used");
- result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps)\n",
- mPeriod, 1000000000.0 / mPeriod);
+ result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n",
+ mPeriod, 1000000000.0 / mPeriod, mRefreshSkipCount);
result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase);
result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n",
mError, sqrt(mError));
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 5106bc8..7a26df3 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -67,6 +67,7 @@ public:
DispSync();
~DispSync();
+ // reset clears the resync samples and error value.
void reset();
// addPresentFence adds a fence for use in validating the current vsync
@@ -100,8 +101,11 @@ public:
// turned on. It should NOT be used after that.
void setPeriod(nsecs_t period);
- // Setting the low power mode reduces the frame rate to half of the default
- void setLowPowerMode(bool enabled);
+ // setRefreshSkipCount specifies an additional number of refresh
+ // cycles to skip. For example, on a 60Hz display, a skip count of 1
+ // will result in events happening at 30Hz. Default is zero. The idea
+ // is to sacrifice smoothness for battery life.
+ void setRefreshSkipCount(int count);
// addEventListener registers a callback to be called repeatedly at the
// given phase offset from the hardware vsync events. The callback is
@@ -161,6 +165,8 @@ private:
nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES];
size_t mPresentSampleOffset;
+ int mRefreshSkipCount;
+
// mThread is the thread from which all the callbacks are called.
sp<DispSyncThread> mThread;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3bdbb4f..f06db5c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2682,11 +2682,8 @@ status_t SurfaceFlinger::onTransact(
// This is an experimental interface
// Needs to be shifted to proper binder interface when we productize
case 1016: {
- mPrimaryDispSync.setLowPowerMode(true);
- return NO_ERROR;
- }
- case 1017: {
- mPrimaryDispSync.setLowPowerMode(false);
+ n = data.readInt32();
+ mPrimaryDispSync.setRefreshSkipCount(n);
return NO_ERROR;
}
}