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