OSDN Git Service

Adding render stats APIs to UiAutomation (framework native).
authorSvetoslav <svetoslavganov@google.com>
Thu, 20 Mar 2014 17:28:31 +0000 (10:28 -0700)
committerSvetoslav <svetoslavganov@google.com>
Thu, 10 Apr 2014 19:32:19 +0000 (12:32 -0700)
bug:12927198

Change-Id: Ibb1c07f7d89e11281e5c1f27f412a29ac6f9c4ab

19 files changed:
include/gui/ISurfaceComposer.h
include/gui/ISurfaceComposerClient.h
include/gui/SurfaceComposerClient.h
include/gui/SurfaceControl.h
include/ui/FrameStats.h [new file with mode: 0644]
libs/gui/ISurfaceComposer.cpp
libs/gui/ISurfaceComposerClient.cpp
libs/gui/SurfaceComposerClient.cpp
libs/gui/SurfaceControl.cpp
libs/ui/Android.mk
libs/ui/FrameStats.cpp [new file with mode: 0644]
services/surfaceflinger/Client.cpp
services/surfaceflinger/Client.h
services/surfaceflinger/FrameTracker.cpp
services/surfaceflinger/FrameTracker.h
services/surfaceflinger/Layer.cpp
services/surfaceflinger/Layer.h
services/surfaceflinger/SurfaceFlinger.cpp
services/surfaceflinger/SurfaceFlinger.h

index 35dcd4e..efde5db 100644 (file)
 
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
 
 #include <binder/IInterface.h>
 
+#include <ui/FrameStats.h>
 #include <ui/PixelFormat.h>
 
 #include <gui/IGraphicBufferAlloc.h>
@@ -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,
index cb9816f..58c1f6a 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <binder/IInterface.h>
 
+#include <ui/FrameStats.h>
 #include <ui/PixelFormat.h>
 
 namespace android {
@@ -65,6 +66,16 @@ public:
      * Requires ACCESS_SURFACE_FLINGER permission
      */
     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;
 };
 
 // ----------------------------------------------------------------------------
index ac53f02..6a53ccb 100644 (file)
@@ -28,6 +28,7 @@
 #include <utils/SortedVector.h>
 #include <utils/threads.h>
 
+#include <ui/FrameStats.h>
 #include <ui/PixelFormat.h>
 
 #include <gui/CpuConsumer.h>
@@ -125,6 +126,12 @@ public:
     status_t    setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
     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,
             const sp<IGraphicBufferProducer>& bufferProducer);
     static void setDisplayLayerStack(const sp<IBinder>& token,
index f27754c..84fb9f9 100644 (file)
@@ -24,6 +24,7 @@
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 
+#include <ui/FrameStats.h>
 #include <ui/PixelFormat.h>
 #include <ui/Region.h>
 
@@ -52,10 +53,10 @@ public:
 
     static bool isSameSurface(
             const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& 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<Surface> 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<SurfaceComposerClient>   mClient;
     sp<IBinder>                 mHandle;
     sp<IGraphicBufferProducer>  mGraphicBufferProducer;
diff --git a/include/ui/FrameStats.h b/include/ui/FrameStats.h
new file mode 100644 (file)
index 0000000..5fdf94d
--- /dev/null
@@ -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
index e96cc54..c067244 100644 (file)
@@ -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);
         }
index 1adc134..3da6423 100644 (file)
@@ -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<ISurfaceComposerClient>
@@ -73,6 +75,23 @@ public:
         remote()->transact(DESTROY_SURFACE, data, &reply);
         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");
@@ -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<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;
         } break;
         default:
index 6b20eaf..b7af415 100644 (file)
@@ -515,6 +515,21 @@ status_t SurfaceComposerClient::destroySurface(const sp<IBinder>& sid) {
     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() {
     return mComposer;
 }
@@ -622,6 +637,14 @@ void SurfaceComposerClient::unblankDisplay(const sp<IBinder>& 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(
index de182ee..7c6dfb8 100644 (file)
@@ -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<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
 {
     if (mHandle==0 || mClient==0) {
index 008446b..eec97be 100644 (file)
@@ -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 (file)
index 0000000..acbe27e
--- /dev/null
@@ -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
index 975631c..f7d32d0 100644 (file)
@@ -155,5 +155,23 @@ status_t Client::destroySurface(const sp<IBinder>& 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
index 84e649f..b6d7381 100644 (file)
@@ -60,6 +60,10 @@ private:
 
     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);
 
index 2fb665e..c09bbe4 100644 (file)
@@ -22,6 +22,7 @@
 #include <cutils/log.h>
 
 #include <ui/Fence.h>
+#include <ui/FrameStats.h>
 
 #include <utils/String8.h>
 
@@ -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();
 
index 9233247..cd5e3f3 100644 (file)
@@ -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 {
index 7f2ee2a..9920525 100644 (file)
@@ -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<SurfaceFlinger>& flinger,
index 8f8989e..62970c3 100644 (file)
@@ -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 @@ 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
index d084bf5..a346520 100644 (file)
@@ -574,6 +574,18 @@ status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& 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<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
@@ -2255,14 +2267,14 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& 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<count ; i++) {
             const sp<Layer>& layer(currentLayers[i]);
             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++) {
         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 @@ 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();
index 630f4b7..717ee66 100644 (file)
@@ -210,6 +210,8 @@ private:
     // 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