Buffer Log functionality for AudioFlinger
Similar to ALOGV, this allows to capture to file audio samples from
within audioservice for debuggin purposes.
Test: manual. Mostly used for debugging
Change-Id: I4d43f573926805a27be910e343476c3f1be51579
diff --git a/services/audioflinger/BufLog.h b/services/audioflinger/BufLog.h
new file mode 100644
index 0000000..1b402f4
--- /dev/null
+++ b/services/audioflinger/BufLog.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ANDROID_AUDIO_BUFLOG_H
+#define ANDROID_AUDIO_BUFLOG_H
+
+/*
+ * BUFLOG creates up to BUFLOG_MAXSTREAMS simultaneous streams [0:15] of audio buffer data
+ * and saves them to disk. The files are stored in the path specified in BUFLOG_BASE_PATH and
+ * are named following this format:
+ * YYYYMMDDHHMMSS_id_format_channels_samplingrate.raw
+ *
+ * Normally we strip BUFLOG dumps from release builds.
+ * You can modify this (for example with "#define BUFLOG_NDEBUG 0"
+ * at the top of your source file) to change that behavior.
+ *
+ * usage:
+ * - Add this to the top of the source file you want to debug:
+ * #define BUFLOG_NDEBUG 0
+ * #include "BufLog.h"
+ *
+ * - dump an audio buffer
+ * BUFLOG(buff_id, buff_tag, format, channels, sampling_rate, max_bytes, buff_pointer, buff_size);
+ *
+ * buff_id: int [0:15] buffer id. If a buffer doesn't exist, it is created the first time.
+ * buff_tag: char* string tag used on stream filename and logs
+ * format: int Audio format (audio_format_t see audio.h)
+ * channels: int Channel Count
+ * sampling_rate: int Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc
+ * max_bytes: int [0 or positive number]
+ * Maximum size of the file (in bytes) to be output.
+ * If the value is 0, no limit.
+ * buff_pointer: void * Pointer to audio buffer.
+ * buff_size: int Size (in bytes) of the current audio buffer to be stored.
+ *
+ *
+ * Example usage:
+ * int format = mConfig.outputCfg.format;
+ * int channels = audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
+ * int samplingRate = mConfig.outputCfg.samplingRate;
+ * int frameCount = mConfig.outputCfg.buffer.frameCount;
+ * int frameSize = audio_bytes_per_sample((audio_format_t)format) * channels;
+ * int buffSize = frameCount * frameSize;
+ * long maxBytes = 10 * samplingRate * frameSize; //10 seconds max
+ * BUFLOG(11, "loudnes_enhancer_out", format, channels, samplingRate, maxBytes,
+ * mConfig.outputCfg.buffer.raw, buffSize);
+ *
+ * Other macros:
+ * BUFLOG_EXISTS returns true if there is an instance of BufLog
+ *
+ * BUFLOG_RESET If an instance of BufLog exists, it stops the capture and closes all
+ * streams.
+ * If a new call to BUFLOG(..) is done, new streams are created.
+ */
+
+#ifndef BUFLOG_NDEBUG
+#ifdef NDEBUG
+#define BUFLOG_NDEBUG 1
+#else
+#define BUFLOG_NDEBUG 0
+#endif
+#endif
+
+/*
+ * Simplified macro to send a buffer.
+ */
+#ifndef BUFLOG
+#define __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \
+ BufLogSingleton::instance()->write(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, \
+ BUF, SIZE)
+#if BUFLOG_NDEBUG
+#define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \
+ do { if (0) { } } while (0)
+#else
+#define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \
+ __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE)
+#endif
+#endif
+
+#ifndef BUFLOG_EXISTS
+#define BUFLOG_EXISTS BufLogSingleton::instanceExists()
+#endif
+
+#ifndef BUFLOG_RESET
+#define BUFLOG_RESET do { if (BufLogSingleton::instanceExists()) { \
+ BufLogSingleton::instance()->reset(); } } while (0)
+#endif
+
+
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <utils/Mutex.h>
+
+//BufLog configuration
+#define BUFLOGSTREAM_MAX_TAGSIZE 32
+#define BUFLOG_BASE_PATH "/data/misc/audioserver"
+#define BUFLOG_MAX_PATH_SIZE 300
+
+class BufLogStream {
+public:
+ BufLogStream(unsigned int id,
+ const char *tag,
+ unsigned int format,
+ unsigned int channels,
+ unsigned int samplingRate,
+ size_t maxBytes);
+ ~BufLogStream();
+
+ // write buffer to stream
+ // buf: pointer to buffer
+ // size: number of bytes to write
+ size_t write(const void *buf, size_t size);
+
+ // pause/resume stream
+ // pause: true = paused, false = not paused
+ // return value: previous state of stream (paused or not).
+ bool setPause(bool pause);
+
+ // will stop the stream and close any open file
+ // the stream can't be reopen. Instead, a new stream (and file) should be created.
+ void finalize();
+
+private:
+ bool mPaused;
+ const unsigned int mId;
+ char mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1];
+ const unsigned int mFormat;
+ const unsigned int mChannels;
+ const unsigned int mSamplingRate;
+ const size_t mMaxBytes;
+ size_t mByteCount;
+ FILE *mFile;
+ mutable android::Mutex mLock;
+
+ void closeStream_l();
+};
+
+
+class BufLog {
+public:
+ BufLog();
+ ~BufLog();
+ BufLog(BufLog const&) {};
+
+ // streamid: int [0:BUFLOG_MAXSTREAMS-1] buffer id.
+ // If a buffer doesn't exist, it is created the first time is referenced
+ // tag: char* string tag used on stream filename and logs
+ // format: int Audio format (audio_format_t see audio.h)
+ // channels: int Channel Count
+ // samplingRate: int Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc
+ // maxBytes: int [0 or positive number]
+ // Maximum size of the file (in bytes) to be output.
+ // If the value is 0, no limit.
+ // size: int Size (in bytes) of the current audio buffer to be written.
+ // buf: void * Pointer to audio buffer.
+ size_t write(int streamid,
+ const char *tag,
+ int format,
+ int channels,
+ int samplingRate,
+ size_t maxBytes,
+ const void *buf,
+ size_t size);
+
+ // reset will stop and close all active streams, thus finalizing any open file.
+ // New streams will be created if write() is called again.
+ void reset();
+
+protected:
+ static const unsigned int BUFLOG_MAXSTREAMS = 16;
+ BufLogStream *mStreams[BUFLOG_MAXSTREAMS];
+ mutable android::Mutex mLock;
+};
+
+class BufLogSingleton {
+public:
+ static BufLog *instance();
+ static bool instanceExists();
+
+private:
+ static void initOnce();
+ static BufLog *mInstance;
+};
+
+#endif //ANDROID_AUDIO_BUFLOG_H