Adding render stats APIs to UiAutomation (framework native).

bug:12927198

Change-Id: Ibb1c07f7d89e11281e5c1f27f412a29ac6f9c4ab
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index e96cc54..c067244 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -229,6 +229,21 @@
         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 @@
             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 1adc134..3da6423 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -39,7 +39,9 @@
 
 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 @@
         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 @@
         } 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:
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 6b20eaf..b7af415 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -515,6 +515,21 @@
     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 @@
     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 de182ee..7c6dfb8 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -156,6 +156,20 @@
     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) {
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 008446b..eec97be 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -18,6 +18,7 @@
 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 0000000..acbe27e
--- /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 <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