Adding render stats APIs to UiAutomation (framework native).

bug:12927198

Change-Id: Ibb1c07f7d89e11281e5c1f27f412a29ac6f9c4ab
This commit is contained in:
Svetoslav 2014-03-20 10:28:31 -07:00
parent f74865eb52
commit d85084b2b6
19 changed files with 384 additions and 21 deletions

View File

@ -22,9 +22,12 @@
#include <utils/RefBase.h> #include <utils/RefBase.h>
#include <utils/Errors.h> #include <utils/Errors.h>
#include <utils/Timers.h>
#include <utils/Vector.h>
#include <binder/IInterface.h> #include <binder/IInterface.h>
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h> #include <ui/PixelFormat.h>
#include <gui/IGraphicBufferAlloc.h> #include <gui/IGraphicBufferAlloc.h>
@ -122,6 +125,19 @@ public:
uint32_t reqWidth, uint32_t reqHeight, uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ, uint32_t minLayerZ, uint32_t maxLayerZ,
bool useIdentityTransform) = 0; bool useIdentityTransform) = 0;
/* Clears the frame statistics for animations.
*
* Requires the ACCESS_SURFACE_FLINGER permission.
*/
virtual status_t clearAnimationFrameStats() = 0;
/* Gets the frame statistics for animations.
*
* Requires the ACCESS_SURFACE_FLINGER permission.
*/
virtual status_t getAnimationFrameStats(FrameStats* outStats) const = 0;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -145,6 +161,8 @@ public:
GET_DISPLAY_INFO, GET_DISPLAY_INFO,
CONNECT_DISPLAY, CONNECT_DISPLAY,
CAPTURE_SCREEN, CAPTURE_SCREEN,
CLEAR_ANIMATION_FRAME_STATS,
GET_ANIMATION_FRAME_STATS
}; };
virtual status_t onTransact(uint32_t code, const Parcel& data, virtual status_t onTransact(uint32_t code, const Parcel& data,

View File

@ -25,6 +25,7 @@
#include <binder/IInterface.h> #include <binder/IInterface.h>
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h> #include <ui/PixelFormat.h>
namespace android { namespace android {
@ -65,6 +66,16 @@ public:
* Requires ACCESS_SURFACE_FLINGER permission * Requires ACCESS_SURFACE_FLINGER permission
*/ */
virtual status_t destroySurface(const sp<IBinder>& handle) = 0; virtual status_t destroySurface(const sp<IBinder>& handle) = 0;
/*
* Requires ACCESS_SURFACE_FLINGER permission
*/
virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const = 0;
/*
* Requires ACCESS_SURFACE_FLINGER permission
*/
virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const = 0;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -28,6 +28,7 @@
#include <utils/SortedVector.h> #include <utils/SortedVector.h>
#include <utils/threads.h> #include <utils/threads.h>
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h> #include <ui/PixelFormat.h>
#include <gui/CpuConsumer.h> #include <gui/CpuConsumer.h>
@ -125,6 +126,12 @@ public:
status_t setLayerStack(const sp<IBinder>& id, uint32_t layerStack); status_t setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
status_t destroySurface(const sp<IBinder>& id); status_t destroySurface(const sp<IBinder>& id);
status_t clearLayerFrameStats(const sp<IBinder>& token) const;
status_t getLayerFrameStats(const sp<IBinder>& token, FrameStats* outStats) const;
static status_t clearAnimationFrameStats();
static status_t getAnimationFrameStats(FrameStats* outStats);
static void setDisplaySurface(const sp<IBinder>& token, static void setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer); const sp<IGraphicBufferProducer>& bufferProducer);
static void setDisplayLayerStack(const sp<IBinder>& token, static void setDisplayLayerStack(const sp<IBinder>& token,

View File

@ -24,6 +24,7 @@
#include <utils/RefBase.h> #include <utils/RefBase.h>
#include <utils/threads.h> #include <utils/threads.h>
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h> #include <ui/PixelFormat.h>
#include <ui/Region.h> #include <ui/Region.h>
@ -52,10 +53,10 @@ public:
static bool isSameSurface( static bool isSameSurface(
const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs); const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
// release surface data from java // release surface data from java
void clear(); void clear();
status_t setLayerStack(int32_t layerStack); status_t setLayerStack(int32_t layerStack);
status_t setLayer(int32_t layer); status_t setLayer(int32_t layer);
status_t setPosition(float x, float y); status_t setPosition(float x, float y);
@ -73,6 +74,9 @@ public:
sp<Surface> getSurface() const; sp<Surface> getSurface() const;
status_t clearLayerFrameStats() const;
status_t getLayerFrameStats(FrameStats* outStats) const;
private: private:
// can't be copied // can't be copied
SurfaceControl& operator = (SurfaceControl& rhs); SurfaceControl& operator = (SurfaceControl& rhs);
@ -90,7 +94,7 @@ private:
status_t validate() const; status_t validate() const;
void destroy(); void destroy();
sp<SurfaceComposerClient> mClient; sp<SurfaceComposerClient> mClient;
sp<IBinder> mHandle; sp<IBinder> mHandle;
sp<IGraphicBufferProducer> mGraphicBufferProducer; sp<IGraphicBufferProducer> mGraphicBufferProducer;

63
include/ui/FrameStats.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_UI_FRAME_STATS_H
#define ANDROID_UI_FRAME_STATS_H
#include <utils/Flattenable.h>
#include <utils/Timers.h>
#include <utils/Vector.h>
namespace android {
class FrameStats : public LightFlattenable<FrameStats> {
public:
/*
* Approximate refresh time, in nanoseconds.
*/
nsecs_t refreshPeriodNano;
/*
* The times in nanoseconds for when the frame contents were posted by the producer (e.g.
* the application). They are either explicitly set or defaulted to the time when
* Surface::queueBuffer() was called.
*/
Vector<nsecs_t> desiredPresentTimesNano;
/*
* The times in milliseconds for when the frame contents were presented on the screen.
*/
Vector<nsecs_t> actualPresentTimesNano;
/*
* The times in nanoseconds for when the frame contents were ready to be presented. Note that
* a frame can be posted and still it contents being rendered asynchronously in GL. In such a
* case these are the times when the frame contents were completely rendered (i.e. their fences
* signaled).
*/
Vector<nsecs_t> frameReadyTimesNano;
// LightFlattenable
bool isFixedSize() const;
size_t getFlattenedSize() const;
status_t flatten(void* buffer, size_t size) const;
status_t unflatten(void const* buffer, size_t size);
};
}; // namespace android
#endif // ANDROID_UI_FRAME_STATS_H

View File

@ -229,6 +229,21 @@ public:
memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo)); memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo));
return reply.readInt32(); return reply.readInt32();
} }
virtual status_t clearAnimationFrameStats() {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::CLEAR_ANIMATION_FRAME_STATS, data, &reply);
return reply.readInt32();
}
virtual status_t getAnimationFrameStats(FrameStats* outStats) const {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::GET_ANIMATION_FRAME_STATS, data, &reply);
reply.read(*outStats);
return reply.readInt32();
}
}; };
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
@ -351,6 +366,20 @@ status_t BnSurfaceComposer::onTransact(
reply->writeInt32(result); reply->writeInt32(result);
return NO_ERROR; return NO_ERROR;
} }
case CLEAR_ANIMATION_FRAME_STATS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
status_t result = clearAnimationFrameStats();
reply->writeInt32(result);
return NO_ERROR;
}
case GET_ANIMATION_FRAME_STATS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
FrameStats stats;
status_t result = getAnimationFrameStats(&stats);
reply->write(stats);
reply->writeInt32(result);
return NO_ERROR;
}
default: { default: {
return BBinder::onTransact(code, data, reply, flags); return BBinder::onTransact(code, data, reply, flags);
} }

View File

@ -39,7 +39,9 @@ namespace android {
enum { enum {
CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION, CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
DESTROY_SURFACE DESTROY_SURFACE,
CLEAR_LAYER_FRAME_STATS,
GET_LAYER_FRAME_STATS
}; };
class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient> class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient>
@ -73,6 +75,23 @@ public:
remote()->transact(DESTROY_SURFACE, data, &reply); remote()->transact(DESTROY_SURFACE, data, &reply);
return reply.readInt32(); return reply.readInt32();
} }
virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
data.writeStrongBinder(handle);
remote()->transact(CLEAR_LAYER_FRAME_STATS, data, &reply);
return reply.readInt32();
}
virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
data.writeStrongBinder(handle);
remote()->transact(GET_LAYER_FRAME_STATS, data, &reply);
reply.read(*outStats);
return reply.readInt32();
}
}; };
IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient"); IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");
@ -101,7 +120,23 @@ status_t BnSurfaceComposerClient::onTransact(
} break; } break;
case DESTROY_SURFACE: { case DESTROY_SURFACE: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply); CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
reply->writeInt32( destroySurface( data.readStrongBinder() ) ); reply->writeInt32(destroySurface( data.readStrongBinder() ) );
return NO_ERROR;
} break;
case CLEAR_LAYER_FRAME_STATS: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
sp<IBinder> handle = data.readStrongBinder();
status_t result = clearLayerFrameStats(handle);
reply->writeInt32(result);
return NO_ERROR;
} break;
case GET_LAYER_FRAME_STATS: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
sp<IBinder> handle = data.readStrongBinder();
FrameStats stats;
status_t result = getLayerFrameStats(handle, &stats);
reply->write(stats);
reply->writeInt32(result);
return NO_ERROR; return NO_ERROR;
} break; } break;
default: default:

View File

@ -515,6 +515,21 @@ status_t SurfaceComposerClient::destroySurface(const sp<IBinder>& sid) {
return err; return err;
} }
status_t SurfaceComposerClient::clearLayerFrameStats(const sp<IBinder>& token) const {
if (mStatus != NO_ERROR) {
return mStatus;
}
return mClient->clearLayerFrameStats(token);
}
status_t SurfaceComposerClient::getLayerFrameStats(const sp<IBinder>& token,
FrameStats* outStats) const {
if (mStatus != NO_ERROR) {
return mStatus;
}
return mClient->getLayerFrameStats(token, outStats);
}
inline Composer& SurfaceComposerClient::getComposer() { inline Composer& SurfaceComposerClient::getComposer() {
return mComposer; return mComposer;
} }
@ -622,6 +637,14 @@ void SurfaceComposerClient::unblankDisplay(const sp<IBinder>& token) {
ComposerService::getComposerService()->unblank(token); ComposerService::getComposerService()->unblank(token);
} }
status_t SurfaceComposerClient::clearAnimationFrameStats() {
return ComposerService::getComposerService()->clearAnimationFrameStats();
}
status_t SurfaceComposerClient::getAnimationFrameStats(FrameStats* outStats) {
return ComposerService::getComposerService()->getAnimationFrameStats(outStats);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
status_t ScreenshotClient::capture( status_t ScreenshotClient::capture(

View File

@ -156,6 +156,20 @@ status_t SurfaceControl::setCrop(const Rect& crop) {
return client->setCrop(mHandle, crop); return client->setCrop(mHandle, crop);
} }
status_t SurfaceControl::clearLayerFrameStats() const {
status_t err = validate();
if (err < 0) return err;
const sp<SurfaceComposerClient>& client(mClient);
return client->clearLayerFrameStats(mHandle);
}
status_t SurfaceControl::getLayerFrameStats(FrameStats* outStats) const {
status_t err = validate();
if (err < 0) return err;
const sp<SurfaceComposerClient>& client(mClient);
return client->getLayerFrameStats(mHandle, outStats);
}
status_t SurfaceControl::validate() const status_t SurfaceControl::validate() const
{ {
if (mHandle==0 || mClient==0) { if (mHandle==0 || mClient==0) {

View File

@ -18,6 +18,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \ LOCAL_SRC_FILES:= \
Fence.cpp \ Fence.cpp \
FramebufferNativeWindow.cpp \ FramebufferNativeWindow.cpp \
FrameStats.cpp \
GraphicBuffer.cpp \ GraphicBuffer.cpp \
GraphicBufferAllocator.cpp \ GraphicBufferAllocator.cpp \
GraphicBufferMapper.cpp \ GraphicBufferMapper.cpp \

84
libs/ui/FrameStats.cpp Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <ui/FrameStats.h>
namespace android {
bool FrameStats::isFixedSize() const {
return false;
}
size_t FrameStats::getFlattenedSize() const {
const size_t timestampSize = sizeof(nsecs_t);
size_t size = timestampSize;
size += 3 * desiredPresentTimesNano.size() * timestampSize;
return size;
}
status_t FrameStats::flatten(void* buffer, size_t size) const {
if (size < getFlattenedSize()) {
return NO_MEMORY;
}
nsecs_t* timestamps = reinterpret_cast<nsecs_t*>(buffer);
const size_t timestampSize = sizeof(nsecs_t);
size_t frameCount = desiredPresentTimesNano.size();
memcpy(timestamps, &refreshPeriodNano, timestampSize);
timestamps += 1;
memcpy(timestamps, desiredPresentTimesNano.array(), frameCount * timestampSize);
timestamps += frameCount;
memcpy(timestamps, actualPresentTimesNano.array(), frameCount * timestampSize);
timestamps += frameCount;
memcpy(timestamps, frameReadyTimesNano.array(), frameCount * timestampSize);
return NO_ERROR;
}
status_t FrameStats::unflatten(void const* buffer, size_t size) {
const size_t timestampSize = sizeof(nsecs_t);
if (size < timestampSize) {
return NO_MEMORY;
}
nsecs_t const* timestamps = reinterpret_cast<nsecs_t const*>(buffer);
size_t frameCount = (size - timestampSize) / (3 * timestampSize);
memcpy(&refreshPeriodNano, timestamps, timestampSize);
timestamps += 1;
desiredPresentTimesNano.resize(frameCount);
memcpy(desiredPresentTimesNano.editArray(), timestamps, frameCount * timestampSize);
timestamps += frameCount;
actualPresentTimesNano.resize(frameCount);
memcpy(actualPresentTimesNano.editArray(), timestamps, frameCount * timestampSize);
timestamps += frameCount;
frameReadyTimesNano.resize(frameCount);
memcpy(frameReadyTimesNano.editArray(), timestamps, frameCount * timestampSize);
return NO_ERROR;
}
} // namespace android

View File

@ -155,5 +155,23 @@ status_t Client::destroySurface(const sp<IBinder>& handle) {
return mFlinger->onLayerRemoved(this, handle); 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 }; // namespace android

View File

@ -60,6 +60,10 @@ private:
virtual status_t destroySurface(const sp<IBinder>& handle); 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( virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);

View File

@ -22,6 +22,7 @@
#include <cutils/log.h> #include <cutils/log.h>
#include <ui/Fence.h> #include <ui/Fence.h>
#include <ui/FrameStats.h>
#include <utils/String8.h> #include <utils/String8.h>
@ -100,7 +101,7 @@ void FrameTracker::advanceFrame() {
processFencesLocked(); processFencesLocked();
} }
void FrameTracker::clear() { void FrameTracker::clearStats() {
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) { for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) {
mFrameRecords[i].desiredPresentTime = 0; mFrameRecords[i].desiredPresentTime = 0;
@ -115,6 +116,32 @@ void FrameTracker::clear() {
mFrameRecords[mOffset].actualPresentTime = INT64_MAX; 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) { void FrameTracker::logAndResetStats(const String8& name) {
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
logStatsLocked(name); logStatsLocked(name);
@ -206,7 +233,7 @@ bool FrameTracker::isFrameValidLocked(size_t idx) const {
mFrameRecords[idx].actualPresentTime < INT64_MAX; mFrameRecords[idx].actualPresentTime < INT64_MAX;
} }
void FrameTracker::dump(String8& result) const { void FrameTracker::dumpStats(String8& result) const {
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
processFencesLocked(); processFencesLocked();

View File

@ -78,15 +78,18 @@ public:
// advanceFrame advances the frame tracker to the next frame. // advanceFrame advances the frame tracker to the next frame.
void advanceFrame(); void advanceFrame();
// clear resets all the tracked frame data to zero. // clearStats clears the tracked frame stats.
void clear(); void clearStats();
// getStats gets the tracked frame stats.
void getStats(FrameStats* outStats) const;
// logAndResetStats dumps the current statistics to the binary event log // logAndResetStats dumps the current statistics to the binary event log
// and then resets the accumulated statistics to their initial values. // and then resets the accumulated statistics to their initial values.
void logAndResetStats(const String8& name); void logAndResetStats(const String8& name);
// dump appends the current frame display time history to the result string. // dumpStats dump appends the current frame display time history to the result string.
void dump(String8& result) const; void dumpStats(String8& result) const;
private: private:
struct FrameRecord { struct FrameRecord {

View File

@ -1244,18 +1244,22 @@ void Layer::dump(String8& result, Colorizer& colorizer) const
} }
} }
void Layer::dumpStats(String8& result) const { void Layer::dumpFrameStats(String8& result) const {
mFrameTracker.dump(result); mFrameTracker.dumpStats(result);
} }
void Layer::clearStats() { void Layer::clearFrameStats() {
mFrameTracker.clear(); mFrameTracker.clearStats();
} }
void Layer::logFrameStats() { void Layer::logFrameStats() {
mFrameTracker.logAndResetStats(mName); mFrameTracker.logAndResetStats(mName);
} }
void Layer::getFrameStats(FrameStats* outStats) const {
mFrameTracker.getStats(outStats);
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger, Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,

View File

@ -27,6 +27,7 @@
#include <utils/String8.h> #include <utils/String8.h>
#include <utils/Timers.h> #include <utils/Timers.h>
#include <ui/FrameStats.h>
#include <ui/GraphicBuffer.h> #include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h> #include <ui/PixelFormat.h>
#include <ui/Region.h> #include <ui/Region.h>
@ -288,9 +289,10 @@ public:
/* always call base class first */ /* always call base class first */
void dump(String8& result, Colorizer& colorizer) const; void dump(String8& result, Colorizer& colorizer) const;
void dumpStats(String8& result) const; void dumpFrameStats(String8& result) const;
void clearStats(); void clearFrameStats();
void logFrameStats(); void logFrameStats();
void getFrameStats(FrameStats* outStats) const;
protected: protected:
// constant // constant

View File

@ -574,6 +574,18 @@ status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo*
return NO_ERROR; 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() { sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
@ -2255,14 +2267,14 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index
result.appendFormat("%" PRId64 "\n", period); result.appendFormat("%" PRId64 "\n", period);
if (name.isEmpty()) { if (name.isEmpty()) {
mAnimFrameTracker.dump(result); mAnimFrameTracker.dumpStats(result);
} else { } else {
const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
const size_t count = currentLayers.size(); const size_t count = currentLayers.size();
for (size_t i=0 ; i<count ; i++) { for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(currentLayers[i]); const sp<Layer>& layer(currentLayers[i]);
if (name == layer->getName()) { if (name == layer->getName()) {
layer->dumpStats(result); layer->dumpFrameStats(result);
} }
} }
} }
@ -2282,11 +2294,11 @@ void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& inde
for (size_t i=0 ; i<count ; i++) { for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(currentLayers[i]); const sp<Layer>& layer(currentLayers[i]);
if (name.isEmpty() || (name == layer->getName())) { 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 // This should only be called from the main thread. Otherwise it would need
@ -2500,6 +2512,8 @@ status_t SurfaceFlinger::onTransact(
case BOOT_FINISHED: case BOOT_FINISHED:
case BLANK: case BLANK:
case UNBLANK: case UNBLANK:
case CLEAR_ANIMATION_FRAME_STATS:
case GET_ANIMATION_FRAME_STATS:
{ {
// codes that require permission check // codes that require permission check
IPCThreadState* ipc = IPCThreadState::self(); IPCThreadState* ipc = IPCThreadState::self();

View File

@ -210,6 +210,8 @@ private:
// called when screen is turning back on // called when screen is turning back on
virtual void unblank(const sp<IBinder>& display); virtual void unblank(const sp<IBinder>& display);
virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info); virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info);
virtual status_t clearAnimationFrameStats();
virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
* DeathRecipient interface * DeathRecipient interface