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:
parent
ae772278fe
commit
85cce376cb
@ -18,6 +18,8 @@ LOCAL_SRC_FILES:= \
|
||||
DisplayHardware/HWComposer.cpp \
|
||||
DisplayHardware/PowerHAL.cpp \
|
||||
DisplayHardware/VirtualDisplaySurface.cpp \
|
||||
EventLog/EventLogTags.logtags \
|
||||
EventLog/EventLog.cpp
|
||||
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
|
||||
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
|
||||
|
128
services/surfaceflinger/EventLog/EventLog.cpp
Normal file
128
services/surfaceflinger/EventLog/EventLog.cpp
Normal 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
|
||||
|
||||
// ---------------------------------------------------------------------------
|
83
services/surfaceflinger/EventLog/EventLog.h
Normal file
83
services/surfaceflinger/EventLog/EventLog.h
Normal 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 */
|
38
services/surfaceflinger/EventLog/EventLogTags.logtags
Normal file
38
services/surfaceflinger/EventLog/EventLogTags.logtags
Normal 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.
|
Loading…
Reference in New Issue
Block a user