Adding render stats APIs to UiAutomation (framework native).
bug:12927198 Change-Id: Ibb1c07f7d89e11281e5c1f27f412a29ac6f9c4ab
This commit is contained in:
parent
f74865eb52
commit
d85084b2b6
19 changed files with 384 additions and 21 deletions
|
@ -22,9 +22,12 @@
|
|||
|
||||
#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,
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
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));
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -18,6 +18,7 @@ include $(CLEAR_VARS)
|
|||
LOCAL_SRC_FILES:= \
|
||||
Fence.cpp \
|
||||
FramebufferNativeWindow.cpp \
|
||||
FrameStats.cpp \
|
||||
GraphicBuffer.cpp \
|
||||
GraphicBufferAllocator.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);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue