Adding render stats APIs to UiAutomation (framework native).
bug:12927198 Change-Id: Ibb1c07f7d89e11281e5c1f27f412a29ac6f9c4ab
This commit is contained in:
parent
f74865eb52
commit
d85084b2b6
@ -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,
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
|
|
||||||
@ -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);
|
||||||
|
63
include/ui/FrameStats.h
Normal file
63
include/ui/FrameStats.h
Normal 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
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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(
|
||||||
|
@ -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) {
|
||||||
|
@ -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
84
libs/ui/FrameStats.cpp
Normal 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
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user