From d85084b2b65828442eafaff9b811e9b6c9ca9fad Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Thu, 20 Mar 2014 10:28:31 -0700 Subject: [PATCH] Adding render stats APIs to UiAutomation (framework native). bug:12927198 Change-Id: Ibb1c07f7d89e11281e5c1f27f412a29ac6f9c4ab --- include/gui/ISurfaceComposer.h | 18 +++++ include/gui/ISurfaceComposerClient.h | 11 +++ include/gui/SurfaceComposerClient.h | 7 ++ include/gui/SurfaceControl.h | 10 ++- include/ui/FrameStats.h | 63 ++++++++++++++++ libs/gui/ISurfaceComposer.cpp | 29 ++++++++ libs/gui/ISurfaceComposerClient.cpp | 39 +++++++++- libs/gui/SurfaceComposerClient.cpp | 23 ++++++ libs/gui/SurfaceControl.cpp | 14 ++++ libs/ui/Android.mk | 1 + libs/ui/FrameStats.cpp | 84 ++++++++++++++++++++++ services/surfaceflinger/Client.cpp | 18 +++++ services/surfaceflinger/Client.h | 4 ++ services/surfaceflinger/FrameTracker.cpp | 31 +++++++- services/surfaceflinger/FrameTracker.h | 11 +-- services/surfaceflinger/Layer.cpp | 12 ++-- services/surfaceflinger/Layer.h | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 22 ++++-- services/surfaceflinger/SurfaceFlinger.h | 2 + 19 files changed, 384 insertions(+), 21 deletions(-) create mode 100644 include/ui/FrameStats.h create mode 100644 libs/ui/FrameStats.cpp diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 35dcd4e8f..efde5db6a 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -22,9 +22,12 @@ #include #include +#include +#include #include +#include #include #include @@ -122,6 +125,19 @@ public: uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, 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, CONNECT_DISPLAY, CAPTURE_SCREEN, + CLEAR_ANIMATION_FRAME_STATS, + GET_ANIMATION_FRAME_STATS }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/include/gui/ISurfaceComposerClient.h b/include/gui/ISurfaceComposerClient.h index cb9816fb2..58c1f6a55 100644 --- a/include/gui/ISurfaceComposerClient.h +++ b/include/gui/ISurfaceComposerClient.h @@ -25,6 +25,7 @@ #include +#include #include namespace android { @@ -65,6 +66,16 @@ public: * Requires ACCESS_SURFACE_FLINGER permission */ virtual status_t destroySurface(const sp& handle) = 0; + + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ + virtual status_t clearLayerFrameStats(const sp& handle) const = 0; + + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ + virtual status_t getLayerFrameStats(const sp& handle, FrameStats* outStats) const = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index ac53f02de..6a53ccbea 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -125,6 +126,12 @@ public: status_t setLayerStack(const sp& id, uint32_t layerStack); status_t destroySurface(const sp& id); + status_t clearLayerFrameStats(const sp& token) const; + status_t getLayerFrameStats(const sp& token, FrameStats* outStats) const; + + static status_t clearAnimationFrameStats(); + static status_t getAnimationFrameStats(FrameStats* outStats); + static void setDisplaySurface(const sp& token, const sp& bufferProducer); static void setDisplayLayerStack(const sp& token, diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h index f27754c22..84fb9f999 100644 --- a/include/gui/SurfaceControl.h +++ b/include/gui/SurfaceControl.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -52,10 +53,10 @@ public: static bool isSameSurface( const sp& lhs, const sp& rhs); - + // release surface data from java void clear(); - + status_t setLayerStack(int32_t layerStack); status_t setLayer(int32_t layer); status_t setPosition(float x, float y); @@ -73,6 +74,9 @@ public: sp getSurface() const; + status_t clearLayerFrameStats() const; + status_t getLayerFrameStats(FrameStats* outStats) const; + private: // can't be copied SurfaceControl& operator = (SurfaceControl& rhs); @@ -90,7 +94,7 @@ private: status_t validate() const; void destroy(); - + sp mClient; sp mHandle; sp mGraphicBufferProducer; diff --git a/include/ui/FrameStats.h b/include/ui/FrameStats.h new file mode 100644 index 000000000..5fdf94d92 --- /dev/null +++ b/include/ui/FrameStats.h @@ -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 +#include +#include + +namespace android { + +class FrameStats : public LightFlattenable { +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 desiredPresentTimesNano; + + /* + * The times in milliseconds for when the frame contents were presented on the screen. + */ + Vector 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 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 diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index e96cc54c7..c06724442 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -229,6 +229,21 @@ public: memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo)); 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"); @@ -351,6 +366,20 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(result); 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: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 1adc134e4..3da6423f4 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -39,7 +39,9 @@ namespace android { enum { CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION, - DESTROY_SURFACE + DESTROY_SURFACE, + CLEAR_LAYER_FRAME_STATS, + GET_LAYER_FRAME_STATS }; class BpSurfaceComposerClient : public BpInterface @@ -73,6 +75,23 @@ public: remote()->transact(DESTROY_SURFACE, data, &reply); return reply.readInt32(); } + + virtual status_t clearLayerFrameStats(const sp& 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& 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"); @@ -101,7 +120,23 @@ status_t BnSurfaceComposerClient::onTransact( } break; case DESTROY_SURFACE: { 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 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 handle = data.readStrongBinder(); + FrameStats stats; + status_t result = getLayerFrameStats(handle, &stats); + reply->write(stats); + reply->writeInt32(result); return NO_ERROR; } break; default: diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6b20eaffc..b7af4152c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -515,6 +515,21 @@ status_t SurfaceComposerClient::destroySurface(const sp& sid) { return err; } +status_t SurfaceComposerClient::clearLayerFrameStats(const sp& token) const { + if (mStatus != NO_ERROR) { + return mStatus; + } + return mClient->clearLayerFrameStats(token); +} + +status_t SurfaceComposerClient::getLayerFrameStats(const sp& token, + FrameStats* outStats) const { + if (mStatus != NO_ERROR) { + return mStatus; + } + return mClient->getLayerFrameStats(token, outStats); +} + inline Composer& SurfaceComposerClient::getComposer() { return mComposer; } @@ -622,6 +637,14 @@ void SurfaceComposerClient::unblankDisplay(const sp& 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( diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index de182eec4..7c6dfb809 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -156,6 +156,20 @@ status_t SurfaceControl::setCrop(const Rect& crop) { return client->setCrop(mHandle, crop); } +status_t SurfaceControl::clearLayerFrameStats() const { + status_t err = validate(); + if (err < 0) return err; + const sp& client(mClient); + return client->clearLayerFrameStats(mHandle); +} + +status_t SurfaceControl::getLayerFrameStats(FrameStats* outStats) const { + status_t err = validate(); + if (err < 0) return err; + const sp& client(mClient); + return client->getLayerFrameStats(mHandle, outStats); +} + status_t SurfaceControl::validate() const { if (mHandle==0 || mClient==0) { diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index 008446b06..eec97be0c 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -18,6 +18,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ Fence.cpp \ FramebufferNativeWindow.cpp \ + FrameStats.cpp \ GraphicBuffer.cpp \ GraphicBufferAllocator.cpp \ GraphicBufferMapper.cpp \ diff --git a/libs/ui/FrameStats.cpp b/libs/ui/FrameStats.cpp new file mode 100644 index 000000000..acbe27e37 --- /dev/null +++ b/libs/ui/FrameStats.cpp @@ -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 + +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(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(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 diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 975631c5e..f7d32d014 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -155,5 +155,23 @@ status_t Client::destroySurface(const sp& handle) { return mFlinger->onLayerRemoved(this, handle); } +status_t Client::clearLayerFrameStats(const sp& handle) const { + sp layer = getLayerUser(handle); + if (layer == NULL) { + return NAME_NOT_FOUND; + } + layer->clearFrameStats(); + return NO_ERROR; +} + +status_t Client::getLayerFrameStats(const sp& handle, FrameStats* outStats) const { + sp 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 84e649f4f..b6d738125 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -60,6 +60,10 @@ private: virtual status_t destroySurface(const sp& handle); + virtual status_t clearLayerFrameStats(const sp& handle) const; + + virtual status_t getLayerFrameStats(const sp& 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 2fb665e47..c09bbe408 100644 --- a/services/surfaceflinger/FrameTracker.cpp +++ b/services/surfaceflinger/FrameTracker.cpp @@ -22,6 +22,7 @@ #include #include +#include #include @@ -100,7 +101,7 @@ void FrameTracker::advanceFrame() { 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 @@ void FrameTracker::clear() { 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 @@ bool FrameTracker::isFrameValidLocked(size_t idx) const { 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 92332471f..cd5e3f3cf 100644 --- a/services/surfaceflinger/FrameTracker.h +++ b/services/surfaceflinger/FrameTracker.h @@ -78,15 +78,18 @@ public: // 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 7f2ee2a80..9920525a8 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1244,18 +1244,22 @@ void Layer::dump(String8& result, Colorizer& colorizer) const } } -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& flinger, diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8f8989e93..62970c304 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -288,9 +289,10 @@ public: /* 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 d084bf522..a3465200b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -574,6 +574,18 @@ status_t SurfaceFlinger::getDisplayInfo(const sp& display, DisplayInfo* 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 SurfaceFlinger::createDisplayEventConnection() { @@ -2255,14 +2267,14 @@ void SurfaceFlinger::dumpStatsLocked(const Vector& args, size_t& index 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& layer(currentLayers[i]); if (name == layer->getName()) { - layer->dumpStats(result); + layer->dumpFrameStats(result); } } } @@ -2282,11 +2294,11 @@ void SurfaceFlinger::clearStatsLocked(const Vector& args, size_t& inde for (size_t i=0 ; i& 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 @@ status_t SurfaceFlinger::onTransact( 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 630f4b709..717ee666d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -210,6 +210,8 @@ private: // called when screen is turning back on virtual void unblank(const sp& display); virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info); + virtual status_t clearAnimationFrameStats(); + virtual status_t getAnimationFrameStats(FrameStats* outStats) const; /* ------------------------------------------------------------------------ * DeathRecipient interface