Adding render stats APIs to UiAutomation (framework native).
bug:12927198
Change-Id: Ibb1c07f7d89e11281e5c1f27f412a29ac6f9c4ab
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 975631c..f7d32d0 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -155,5 +155,23 @@
return mFlinger->onLayerRemoved(this, handle);
}
+status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
+ sp<Layer> layer = getLayerUser(handle);
+ if (layer == NULL) {
+ return NAME_NOT_FOUND;
+ }
+ layer->clearFrameStats();
+ return NO_ERROR;
+}
+
+status_t Client::getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const {
+ sp<Layer> layer = getLayerUser(handle);
+ if (layer == NULL) {
+ return NAME_NOT_FOUND;
+ }
+ layer->getFrameStats(outStats);
+ return NO_ERROR;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index 84e649f..b6d7381 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -60,6 +60,10 @@
virtual status_t destroySurface(const sp<IBinder>& handle);
+ virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const;
+
+ virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const;
+
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp
index 2fb665e..c09bbe4 100644
--- a/services/surfaceflinger/FrameTracker.cpp
+++ b/services/surfaceflinger/FrameTracker.cpp
@@ -22,6 +22,7 @@
#include <cutils/log.h>
#include <ui/Fence.h>
+#include <ui/FrameStats.h>
#include <utils/String8.h>
@@ -100,7 +101,7 @@
processFencesLocked();
}
-void FrameTracker::clear() {
+void FrameTracker::clearStats() {
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) {
mFrameRecords[i].desiredPresentTime = 0;
@@ -115,6 +116,32 @@
mFrameRecords[mOffset].actualPresentTime = INT64_MAX;
}
+void FrameTracker::getStats(FrameStats* outStats) const {
+ Mutex::Autolock lock(mMutex);
+ processFencesLocked();
+
+ outStats->refreshPeriodNano = mDisplayPeriod;
+
+ const size_t offset = mOffset;
+ for (size_t i = 1; i < NUM_FRAME_RECORDS; i++) {
+ const size_t index = (offset + i) % NUM_FRAME_RECORDS;
+
+ // Skip frame records with no data (if buffer not yet full).
+ if (mFrameRecords[index].desiredPresentTime == 0) {
+ continue;
+ }
+
+ nsecs_t desiredPresentTimeNano = mFrameRecords[index].desiredPresentTime;
+ outStats->desiredPresentTimesNano.push_back(desiredPresentTimeNano);
+
+ nsecs_t actualPresentTimeNano = mFrameRecords[index].actualPresentTime;
+ outStats->actualPresentTimesNano.push_back(actualPresentTimeNano);
+
+ nsecs_t frameReadyTimeNano = mFrameRecords[index].frameReadyTime;
+ outStats->frameReadyTimesNano.push_back(frameReadyTimeNano);
+ }
+}
+
void FrameTracker::logAndResetStats(const String8& name) {
Mutex::Autolock lock(mMutex);
logStatsLocked(name);
@@ -206,7 +233,7 @@
mFrameRecords[idx].actualPresentTime < INT64_MAX;
}
-void FrameTracker::dump(String8& result) const {
+void FrameTracker::dumpStats(String8& result) const {
Mutex::Autolock lock(mMutex);
processFencesLocked();
diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h
index 9233247..cd5e3f3 100644
--- a/services/surfaceflinger/FrameTracker.h
+++ b/services/surfaceflinger/FrameTracker.h
@@ -78,15 +78,18 @@
// advanceFrame advances the frame tracker to the next frame.
void advanceFrame();
- // clear resets all the tracked frame data to zero.
- void clear();
+ // clearStats clears the tracked frame stats.
+ void clearStats();
+
+ // getStats gets the tracked frame stats.
+ void getStats(FrameStats* outStats) const;
// logAndResetStats dumps the current statistics to the binary event log
// and then resets the accumulated statistics to their initial values.
void logAndResetStats(const String8& name);
- // dump appends the current frame display time history to the result string.
- void dump(String8& result) const;
+ // dumpStats dump appends the current frame display time history to the result string.
+ void dumpStats(String8& result) const;
private:
struct FrameRecord {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7f2ee2a..9920525 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1244,18 +1244,22 @@
}
}
-void Layer::dumpStats(String8& result) const {
- mFrameTracker.dump(result);
+void Layer::dumpFrameStats(String8& result) const {
+ mFrameTracker.dumpStats(result);
}
-void Layer::clearStats() {
- mFrameTracker.clear();
+void Layer::clearFrameStats() {
+ mFrameTracker.clearStats();
}
void Layer::logFrameStats() {
mFrameTracker.logAndResetStats(mName);
}
+void Layer::getFrameStats(FrameStats* outStats) const {
+ mFrameTracker.getStats(outStats);
+}
+
// ---------------------------------------------------------------------------
Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8f8989e..62970c3 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -27,6 +27,7 @@
#include <utils/String8.h>
#include <utils/Timers.h>
+#include <ui/FrameStats.h>
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
#include <ui/Region.h>
@@ -288,9 +289,10 @@
/* always call base class first */
void dump(String8& result, Colorizer& colorizer) const;
- void dumpStats(String8& result) const;
- void clearStats();
+ void dumpFrameStats(String8& result) const;
+ void clearFrameStats();
void logFrameStats();
+ void getFrameStats(FrameStats* outStats) const;
protected:
// constant
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d084bf5..a346520 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -574,6 +574,18 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::clearAnimationFrameStats() {
+ Mutex::Autolock _l(mStateLock);
+ mAnimFrameTracker.clearStats();
+ return NO_ERROR;
+}
+
+status_t SurfaceFlinger::getAnimationFrameStats(FrameStats* outStats) const {
+ Mutex::Autolock _l(mStateLock);
+ mAnimFrameTracker.getStats(outStats);
+ return NO_ERROR;
+}
+
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
@@ -2255,14 +2267,14 @@
result.appendFormat("%" PRId64 "\n", period);
if (name.isEmpty()) {
- mAnimFrameTracker.dump(result);
+ mAnimFrameTracker.dumpStats(result);
} else {
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
const size_t count = currentLayers.size();
for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(currentLayers[i]);
if (name == layer->getName()) {
- layer->dumpStats(result);
+ layer->dumpFrameStats(result);
}
}
}
@@ -2282,11 +2294,11 @@
for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(currentLayers[i]);
if (name.isEmpty() || (name == layer->getName())) {
- layer->clearStats();
+ layer->clearFrameStats();
}
}
- mAnimFrameTracker.clear();
+ mAnimFrameTracker.clearStats();
}
// This should only be called from the main thread. Otherwise it would need
@@ -2500,6 +2512,8 @@
case BOOT_FINISHED:
case BLANK:
case UNBLANK:
+ case CLEAR_ANIMATION_FRAME_STATS:
+ case GET_ANIMATION_FRAME_STATS:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 630f4b7..717ee66 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -210,6 +210,8 @@
// called when screen is turning back on
virtual void unblank(const sp<IBinder>& display);
virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info);
+ virtual status_t clearAnimationFrameStats();
+ virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
/* ------------------------------------------------------------------------
* DeathRecipient interface