Basic binary event-log helpers

EventLog can be used from SurfaceFlinger to log jank
statistics events to the binary event log.

Change-Id: If0fbbe7d7111f10957697166d37fd0c3418109bb
This commit is contained in:
Mathias Agopian 2013-06-04 21:50:31 -07:00
parent ae772278fe
commit 85cce376cb
4 changed files with 251 additions and 0 deletions

View File

@ -18,6 +18,8 @@ LOCAL_SRC_FILES:= \
DisplayHardware/HWComposer.cpp \ DisplayHardware/HWComposer.cpp \
DisplayHardware/PowerHAL.cpp \ DisplayHardware/PowerHAL.cpp \
DisplayHardware/VirtualDisplaySurface.cpp \ DisplayHardware/VirtualDisplaySurface.cpp \
EventLog/EventLogTags.logtags \
EventLog/EventLog.cpp
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES

View File

@ -0,0 +1,128 @@
/*
* Copyright 2013 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 <stdio.h>
#include <stdlib.h>
#include <cutils/log.h>
#include <utils/String8.h>
#include "EventLog.h"
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
ANDROID_SINGLETON_STATIC_INSTANCE(EventLog)
EventLog::EventLog() {
}
void EventLog::doLogJank(const String8& window, int32_t value) {
EventLog::TagBuffer buffer(LOGTAG_SF_JANK);
buffer.startList(2);
buffer.writeString8(window);
buffer.writeInt32(value);
buffer.endList();
buffer.log();
}
void EventLog::logJank(const String8& window, int32_t value) {
EventLog::getInstance().doLogJank(window, value);
}
// ---------------------------------------------------------------------------
EventLog::TagBuffer::TagBuffer(int32_t tag)
: mPos(0), mTag(tag), mOverflow(false) {
}
void EventLog::TagBuffer::log() {
if (mOverflow) {
ALOGW("couldn't log to binary event log: overflow.");
} else if (android_bWriteLog(mTag, mStorage, mPos) < 0) {
ALOGE("couldn't log to EventLog: %s", strerror(errno));
}
// purge the buffer
mPos = 0;
mOverflow = false;
}
void EventLog::TagBuffer::startList(int8_t count) {
if (mOverflow) return;
const size_t needed = 1 + sizeof(count);
if (mPos + needed > STORAGE_MAX_SIZE) {
mOverflow = true;
return;
}
mStorage[mPos + 0] = EVENT_TYPE_LIST;
mStorage[mPos + 1] = count;
mPos += needed;
}
void EventLog::TagBuffer::endList() {
if (mOverflow) return;
const size_t needed = 1;
if (mPos + needed > STORAGE_MAX_SIZE) {
mOverflow = true;
return;
}
mStorage[mPos + 0] = '\n';
mPos += needed;
}
void EventLog::TagBuffer::writeInt32(int32_t value) {
if (mOverflow) return;
const size_t needed = 1 + sizeof(value);
if (mPos + needed > STORAGE_MAX_SIZE) {
mOverflow = true;
return;
}
mStorage[mPos + 0] = EVENT_TYPE_INT;
memcpy(&mStorage[mPos + 1], &value, sizeof(value));
mPos += needed;
}
void EventLog::TagBuffer::writeInt64(int64_t value) {
if (mOverflow) return;
const size_t needed = 1 + sizeof(value);
if (mPos + needed > STORAGE_MAX_SIZE) {
mOverflow = true;
return;
}
mStorage[mPos + 0] = EVENT_TYPE_LONG;
memcpy(&mStorage[mPos + 1], &value, sizeof(value));
mPos += needed;
}
void EventLog::TagBuffer::writeString8(const String8& value) {
if (mOverflow) return;
const int32_t stringLen = value.length();
const size_t needed = 1 + sizeof(int32_t) + stringLen;
if (mPos + needed > STORAGE_MAX_SIZE) {
mOverflow = true;
return;
}
mStorage[mPos + 0] = EVENT_TYPE_STRING;
memcpy(&mStorage[mPos + 1], &stringLen, sizeof(int32_t));
memcpy(&mStorage[mPos + 5], value.string(), stringLen);
mPos += needed;
}
// ---------------------------------------------------------------------------
}// namespace android
// ---------------------------------------------------------------------------

View File

@ -0,0 +1,83 @@
/*
* Copyright 2013 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 <stdint.h>
#include <utils/Errors.h>
#include <utils/Singleton.h>
#ifndef ANDROID_SF_EVENTLOG_H
#define ANDROID_SF_EVENTLOG_H
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
class String8;
class EventLog : public Singleton<EventLog> {
public:
static void logJank(const String8& window, int32_t value);
protected:
EventLog();
private:
/*
* EventLogBuffer is a helper class to construct an in-memory event log
* tag. In this version the buffer is not dynamic, so write operation can
* fail if there is not enough space in the temporary buffer.
* Once constructed, the buffer can be logger by calling the log()
* method.
*/
class TagBuffer {
enum { STORAGE_MAX_SIZE = 128 };
int32_t mPos;
int32_t mTag;
bool mOverflow;
char mStorage[STORAGE_MAX_SIZE];
public:
TagBuffer(int32_t tag);
// starts list of items
void startList(int8_t count);
// terminates the list
void endList();
// write a 32-bit integer
void writeInt32(int32_t value);
// write a 64-bit integer
void writeInt64(int64_t value);
// write a C string
void writeString8(const String8& value);
// outputs the the buffer to the log
void log();
};
friend class Singleton<EventLog>;
EventLog(const EventLog&);
EventLog& operator =(const EventLog&);
enum { LOGTAG_SF_JANK = 60100 };
void doLogJank(const String8& window, int32_t value);
};
// ---------------------------------------------------------------------------
}// namespace android
// ---------------------------------------------------------------------------
#endif /* ANDROID_SF_EVENTLOG_H */

View File

@ -0,0 +1,38 @@
# The entries in this file map a sparse set of log tag numbers to tag names.
# This is installed on the device, in /system/etc, and parsed by logcat.
#
# Tag numbers are decimal integers, from 0 to 2^31. (Let's leave the
# negative values alone for now.)
#
# Tag names are one or more ASCII letters and numbers or underscores, i.e.
# "[A-Z][a-z][0-9]_". Do not include spaces or punctuation (the former
# impacts log readability, the latter makes regex searches more annoying).
#
# Tag numbers and names are separated by whitespace. Blank lines and lines
# starting with '#' are ignored.
#
# Optionally, after the tag names can be put a description for the value(s)
# of the tag. Description are in the format
# (<name>|data type[|data unit])
# Multiple values are separated by commas.
#
# The data type is a number from the following values:
# 1: int
# 2: long
# 3: string
# 4: list
#
# The data unit is a number taken from the following list:
# 1: Number of objects
# 2: Number of bytes
# 3: Number of milliseconds
# 4: Number of allocations
# 5: Id
# 6: Percent
# Default value for data of type int/long is 2 (bytes).
# surfaceflinger
60100 sf_jank (window|3),(value|1)
# NOTE - the range 1000000-2000000 is reserved for partners and others who
# want to define their own log tags without conflicting with the core platform.