NBLog.h revision 11d8dfcc063425ae7d59229f54b6752fd8987c10
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>
2411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#include <media/nbaio/roundup.h>
2511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
2611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastennamespace android {
2711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
2811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass NBLog {
2911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
3011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
3111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
3211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Writer;
3311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Reader;
3411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
3511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
3611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
3711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenenum Event {
3811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    EVENT_RESERVED,
3911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    EVENT_STRING,               // ASCII string, not NUL-terminated
4011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    EVENT_TIMESTAMP,            // clock_gettime(CLOCK_MONOTONIC)
4111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
4211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
4311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ---------------------------------------------------------------------------
4411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
4511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// representation of a single log entry in private memory
4611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenstruct Entry {
4711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Entry(Event event, const void *data, size_t length)
4811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten        : mEvent(event), mLength(length), mData(data) { }
4911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    /*virtual*/ ~Entry() { }
5011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
5111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    int     readAt(size_t offset) const;
5211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
5311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
5411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    friend class Writer;
5511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Event       mEvent;     // event type
5611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    size_t      mLength;    // length of additional data, 0 <= mLength <= 255
5711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    const void *mData;      // event type-specific data
5811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
5911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
6011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// representation of a single log entry in shared memory
6111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[0]             mEvent
6211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[1]             mLength
6311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[2]             mData[0]
6411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  ...
6511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[2+i]           mData[i]
6611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  ...
6711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[2+mLength-1]   mData[mLength-1]
6811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[2+mLength]     duplicate copy of mLength to permit reverse scan
6911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten//  byte[3+mLength]     start of next log entry
7011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
7111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// located in shared memory
7211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenstruct Shared {
7311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Shared() : mRear(0) { }
7411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    /*virtual*/ ~Shared() { }
7511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
7611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    volatile int32_t mRear;     // index one byte past the end of most recent Entry
7711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    char    mBuffer[0];         // circular buffer for entries
7811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
7911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
8011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
8111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
8211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ---------------------------------------------------------------------------
8311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
8411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// FIXME Timeline was intended to wrap Writer and Reader, but isn't actually used yet.
8511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// For now it is just a namespace for sharedSize().
8611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Timeline : public RefBase {
8711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
8811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#if 0
8911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Timeline(size_t size, void *shared = NULL);
9011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual ~Timeline();
9111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif
9211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
9311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    static size_t sharedSize(size_t size);
9411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
9511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#if 0
9611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
9711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    friend class    Writer;
9811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    friend class    Reader;
9911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
10011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
10111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    bool            mOwn;       // whether I own the memory at mShared
10211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Shared* const   mShared;    // pointer to shared memory
10311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif
10411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
10511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
10611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ---------------------------------------------------------------------------
10711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
10811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Writer is thread-safe with respect to Reader, but not with respect to multiple threads
10911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// calling Writer methods.  If you need multi-thread safety for writing, use LockedWriter.
11011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Writer : public RefBase {
11111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
11211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Writer();                   // dummy nop implementation without shared memory
11311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Writer(size_t size, void *shared);
11411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Writer(size_t size, const sp<IMemory>& iMemory);
11511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual ~Writer() { }
11611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
11711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    log(const char *string);
11811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logf(const char *fmt, ...);
11911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logvf(const char *fmt, va_list ap);
12011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logTimestamp();
12111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logTimestamp(const struct timespec& ts);
12211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
12311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual bool    isEnabled() const;
12411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
12511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    // return value for all of these is the previous isEnabled()
12611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual bool    setEnabled(bool enabled);   // but won't enable if no shared memory
12711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten            bool    enable()    { return setEnabled(true); }
12811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten            bool    disable()   { return setEnabled(false); }
12911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
13011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    sp<IMemory>     getIMemory() const  { return mIMemory; }
13111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
13211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
13311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    void    log(Event event, const void *data, size_t length);
13411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    void    log(const Entry *entry, bool trusted = false);
13511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
13611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
13711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Shared* const   mShared;    // raw pointer to shared memory
13811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    const sp<IMemory> mIMemory; // ref-counted version
13911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    int32_t         mRear;      // my private copy of mShared->mRear
14011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    bool            mEnabled;   // whether to actually log
14111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
14211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
14311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ---------------------------------------------------------------------------
14411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
14511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// Similar to Writer, but safe for multiple threads to call concurrently
14611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass LockedWriter : public Writer {
14711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
14811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    LockedWriter();
14911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    LockedWriter(size_t size, void *shared);
15011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
15111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    log(const char *string);
15211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logf(const char *fmt, ...);
15311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logvf(const char *fmt, va_list ap);
15411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logTimestamp();
15511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual void    logTimestamp(const struct timespec& ts);
15611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
15711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual bool    isEnabled() const;
15811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual bool    setEnabled(bool enabled);
15911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
16011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
16111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    mutable Mutex   mLock;
16211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
16311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
16411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten// ---------------------------------------------------------------------------
16511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
16611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenclass Reader : public RefBase {
16711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenpublic:
16811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Reader(size_t size, const void *shared);
16911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    Reader(size_t size, const sp<IMemory>& iMemory);
17011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    virtual ~Reader() { }
17111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
17211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    void    dump(int fd, size_t indent = 0);
17311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    bool    isIMemory(const sp<IMemory>& iMemory) const;
17411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
17511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kastenprivate:
17611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    const size_t    mSize;      // circular buffer size in bytes, must be a power of 2
17711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    const Shared* const mShared; // raw pointer to shared memory
17811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    const sp<IMemory> mIMemory; // ref-counted version
17911d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    int32_t     mFront;         // index of oldest acknowledged Entry
18011d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
18111d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten    static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
18211d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};
18311d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
18411d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten};  // class NBLog
18511d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
18611d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten}   // namespace android
18711d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten
18811d8dfcc063425ae7d59229f54b6752fd8987c10Glenn Kasten#endif  // ANDROID_MEDIA_NBLOG_H
189