111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten/* 211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * Copyright (C) 2013 The Android Open Source Project 311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * 411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * you may not use this file except in compliance with the License. 611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * You may obtain a copy of the License at 711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * 811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * 1011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * Unless required by applicable law or agreed to in writing, software 1111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 1211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * See the License for the specific language governing permissions and 1411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten * limitations under the License. 1511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten */ 1611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 1711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Non-blocking event logger intended for safe communication between processes via shared memory 1811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 1911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#ifndef ANDROID_MEDIA_NBLOG_H 2011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#define ANDROID_MEDIA_NBLOG_H 2111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 2211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <binder/IMemory.h> 2311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <utils/Mutex.h> 2453dbe77b9f50cdd0de88b9d25dd643e90c8ba68bGlenn Kasten#include <audio_utils/roundup.h> 2511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 2611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastennamespace android { 2711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 284e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kastenclass String8; 294e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten 3011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass NBLog { 3111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 3211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 3311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 3411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Writer; 3511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Reader; 3611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 3711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 3811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 3911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenenum Event { 4011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten EVENT_RESERVED, 4111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten EVENT_STRING, // ASCII string, not NUL-terminated 4211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten EVENT_TIMESTAMP, // clock_gettime(CLOCK_MONOTONIC) 4311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 4411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 4511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 4611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 4711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// representation of a single log entry in private memory 4811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenstruct Entry { 4911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Entry(Event event, const void *data, size_t length) 5011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten : mEvent(event), mLength(length), mData(data) { } 5111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten /*virtual*/ ~Entry() { } 5211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 5311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten int readAt(size_t offset) const; 5411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 5511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 5611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten friend class Writer; 5711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Event mEvent; // event type 5811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten size_t mLength; // length of additional data, 0 <= mLength <= 255 5911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten const void *mData; // event type-specific data 6011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 6111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 6211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// representation of a single log entry in shared memory 6311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[0] mEvent 6411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[1] mLength 6511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[2] mData[0] 6611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ... 6711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[2+i] mData[i] 6811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ... 6911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[2+mLength-1] mData[mLength-1] 7011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[2+mLength] duplicate copy of mLength to permit reverse scan 7111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// byte[3+mLength] start of next log entry 7211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 7311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// located in shared memory 7411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenstruct Shared { 7511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Shared() : mRear(0) { } 7611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten /*virtual*/ ~Shared() { } 7711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 7811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten volatile int32_t mRear; // index one byte past the end of most recent Entry 7911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten char mBuffer[0]; // circular buffer for entries 8011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 8111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 8211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 8311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 8411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 8511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 8611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// FIXME Timeline was intended to wrap Writer and Reader, but isn't actually used yet. 8711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// For now it is just a namespace for sharedSize(). 8811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Timeline : public RefBase { 8911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 9011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#if 0 9111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Timeline(size_t size, void *shared = NULL); 9211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual ~Timeline(); 9311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif 9411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 95fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // Input parameter 'size' is the desired size of the timeline in byte units. 96fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // Returns the size rounded up to a power-of-2, plus the constant size overhead for indices. 9711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten static size_t sharedSize(size_t size); 9811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 9911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#if 0 10011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 10111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten friend class Writer; 10211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten friend class Reader; 10311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 10411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten const size_t mSize; // circular buffer size in bytes, must be a power of 2 10511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool mOwn; // whether I own the memory at mShared 10611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Shared* const mShared; // pointer to shared memory 10711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif 10811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 10911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 11011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 11111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 11211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Writer is thread-safe with respect to Reader, but not with respect to multiple threads 11311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// calling Writer methods. If you need multi-thread safety for writing, use LockedWriter. 11411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Writer : public RefBase { 11511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 11611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer(); // dummy nop implementation without shared memory 117fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten 118fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // Input parameter 'size' is the desired size of the timeline in byte units. 119fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // The size of the shared memory must be at least Timeline::sharedSize(size). 12011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer(size_t size, void *shared); 12111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Writer(size_t size, const sp<IMemory>& iMemory); 122fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten 12311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual ~Writer() { } 12411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 12511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void log(const char *string); 126ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); 12711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logvf(const char *fmt, va_list ap); 12811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logTimestamp(); 12911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logTimestamp(const struct timespec& ts); 13011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 13111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual bool isEnabled() const; 13211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 13311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten // return value for all of these is the previous isEnabled() 13411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual bool setEnabled(bool enabled); // but won't enable if no shared memory 13511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool enable() { return setEnabled(true); } 13611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool disable() { return setEnabled(false); } 13711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 13811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten sp<IMemory> getIMemory() const { return mIMemory; } 13911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 14011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 14111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten void log(Event event, const void *data, size_t length); 14211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten void log(const Entry *entry, bool trusted = false); 14311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 14411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten const size_t mSize; // circular buffer size in bytes, must be a power of 2 14511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Shared* const mShared; // raw pointer to shared memory 14611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten const sp<IMemory> mIMemory; // ref-counted version 14711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten int32_t mRear; // my private copy of mShared->mRear 14811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool mEnabled; // whether to actually log 14911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 15011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 15111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 15211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 15311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Similar to Writer, but safe for multiple threads to call concurrently 15411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass LockedWriter : public Writer { 15511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 15611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten LockedWriter(); 15711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten LockedWriter(size_t size, void *shared); 15811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 15911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void log(const char *string); 160ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); 16111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logvf(const char *fmt, va_list ap); 16211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logTimestamp(); 16311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual void logTimestamp(const struct timespec& ts); 16411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 16511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual bool isEnabled() const; 16611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual bool setEnabled(bool enabled); 16711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 16811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 16911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten mutable Mutex mLock; 17011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 17111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 17211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// --------------------------------------------------------------------------- 17311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 17411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Reader : public RefBase { 17511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic: 176fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten 177fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // Input parameter 'size' is the desired size of the timeline in byte units. 178fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten // The size of the shared memory must be at least Timeline::sharedSize(size). 17911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Reader(size_t size, const void *shared); 18011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten Reader(size_t size, const sp<IMemory>& iMemory); 181fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten 18211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten virtual ~Reader() { } 18311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 18411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten void dump(int fd, size_t indent = 0); 18511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten bool isIMemory(const sp<IMemory>& iMemory) const; 18611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 18711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate: 18811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten const size_t mSize; // circular buffer size in bytes, must be a power of 2 18911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten const Shared* const mShared; // raw pointer to shared memory 19011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten const sp<IMemory> mIMemory; // ref-counted version 19111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten int32_t mFront; // index of oldest acknowledged Entry 1924e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten int mFd; // file descriptor 1934e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten int mIndent; // indentation level 1944e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten 1954e01ef6b2f6d288b9aa83b5817adad02cecc429fGlenn Kasten void dumpLine(const String8& timestamp, String8& body); 19611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 19711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps 19811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; 19911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 20011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}; // class NBLog 20111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 20211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten} // namespace android 20311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten 20411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif // ANDROID_MEDIA_NBLOG_H 205