• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #include "BufLog.h"
19 #define LOG_TAG "BufLog"
20 //#define LOG_NDEBUG 0
21 
22 #include <errno.h>
23 #include "log/log.h"
24 #include <pthread.h>
25 #include <stdio.h>
26 #include <string.h>
27 
28 #define MIN(a, b) ((a) < (b) ? (a) : (b))
29 
30 // ------------------------------
31 // BufLogSingleton
32 // ------------------------------
33 pthread_once_t onceControl = PTHREAD_ONCE_INIT;
34 
35 BufLog *BufLogSingleton::mInstance = NULL;
36 
initOnce()37 void BufLogSingleton::initOnce() {
38     mInstance = new BufLog();
39     ALOGW("=====================================\n" \
40             "Warning: BUFLOG is defined in some part of your code.\n" \
41             "This will create large audio dumps in %s.\n" \
42             "=====================================\n", BUFLOG_BASE_PATH);
43 }
44 
instance()45 BufLog *BufLogSingleton::instance() {
46     pthread_once(&onceControl, initOnce);
47     return mInstance;
48 }
49 
instanceExists()50 bool BufLogSingleton::instanceExists() {
51     return mInstance != NULL;
52 }
53 
54 // ------------------------------
55 // BufLog
56 // ------------------------------
57 
BufLog()58 BufLog::BufLog() {
59     memset(mStreams, 0, sizeof(mStreams));
60 }
61 
~BufLog()62 BufLog::~BufLog() {
63     android::Mutex::Autolock autoLock(mLock);
64 
65     for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
66         BufLogStream *pBLStream = mStreams[id];
67         if (pBLStream != NULL) {
68             delete pBLStream ;
69             mStreams[id] = NULL;
70         }
71     }
72 }
73 
write(int streamid,const char * tag,int format,int channels,int samplingRate,size_t maxBytes,const void * buf,size_t size)74 size_t BufLog::write(int streamid, const char *tag, int format, int channels,
75         int samplingRate, size_t maxBytes, const void *buf, size_t size) {
76     unsigned int id = streamid % BUFLOG_MAXSTREAMS;
77     android::Mutex::Autolock autoLock(mLock);
78 
79     BufLogStream *pBLStream = mStreams[id];
80 
81     if (pBLStream == NULL) {
82         pBLStream = mStreams[id] = new BufLogStream(id, tag, format, channels,
83                 samplingRate, maxBytes);
84         ALOG_ASSERT(pBLStream != NULL, "BufLogStream Failed to be created");
85     }
86 
87     return pBLStream->write(buf, size);
88 }
89 
reset()90 void BufLog::reset() {
91     android::Mutex::Autolock autoLock(mLock);
92     ALOGV("Resetting all BufLogs");
93     int count = 0;
94 
95     for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
96         BufLogStream *pBLStream = mStreams[id];
97         if (pBLStream != NULL) {
98             delete pBLStream;
99             mStreams[id] = NULL;
100             count++;
101         }
102     }
103     ALOGV("Reset %d BufLogs", count);
104 }
105 
106 // ------------------------------
107 // BufLogStream
108 // ------------------------------
109 
BufLogStream(unsigned int id,const char * tag,unsigned int format,unsigned int channels,unsigned int samplingRate,size_t maxBytes=0)110 BufLogStream::BufLogStream(unsigned int id,
111         const char *tag,
112         unsigned int format,
113         unsigned int channels,
114         unsigned int samplingRate,
115         size_t maxBytes = 0) : mId(id), mFormat(format), mChannels(channels),
116                 mSamplingRate(samplingRate), mMaxBytes(maxBytes) {
117     mByteCount = 0l;
118     mPaused = false;
119     if (tag != NULL) {
120         strncpy(mTag, tag, BUFLOGSTREAM_MAX_TAGSIZE);
121     } else {
122         mTag[0] = 0;
123     }
124     ALOGV("Creating BufLogStream id:%d tag:%s format:%d ch:%d sr:%d maxbytes:%zu", mId, mTag,
125             mFormat, mChannels, mSamplingRate, mMaxBytes);
126 
127     //open file (s), info about tag, format, etc.
128     //timestamp
129     char timeStr[16];   //size 16: format %Y%m%d%H%M%S 14 chars + string null terminator
130     struct timeval tv;
131     gettimeofday(&tv, NULL);
132     struct tm tm;
133     localtime_r(&tv.tv_sec, &tm);
134     strftime(timeStr, sizeof(timeStr), "%Y%m%d%H%M%S", &tm);
135     char logPath[BUFLOG_MAX_PATH_SIZE];
136     snprintf(logPath, BUFLOG_MAX_PATH_SIZE, "%s/%s_%d_%s_%d_%d_%d.raw", BUFLOG_BASE_PATH, timeStr,
137             mId, mTag, mFormat, mChannels, mSamplingRate);
138     ALOGV("data output: %s", logPath);
139 
140     mFile = fopen(logPath, "wb");
141     if (mFile != NULL) {
142         ALOGV("Success creating file at: %p", mFile);
143     } else {
144         ALOGE("Error: could not create file BufLogStream %s", strerror(errno));
145     }
146 }
147 
closeStream_l()148 void BufLogStream::closeStream_l() {
149     ALOGV("Closing BufLogStream id:%d tag:%s", mId, mTag);
150     if (mFile != NULL) {
151         fclose(mFile);
152         mFile = NULL;
153     }
154 }
155 
~BufLogStream()156 BufLogStream::~BufLogStream() {
157     ALOGV("Destroying BufLogStream id:%d tag:%s", mId, mTag);
158     android::Mutex::Autolock autoLock(mLock);
159     closeStream_l();
160 }
161 
write(const void * buf,size_t size)162 size_t BufLogStream::write(const void *buf, size_t size) {
163 
164     size_t bytes = 0;
165     if (!mPaused && mFile != NULL) {
166         if (size > 0 && buf != NULL) {
167             android::Mutex::Autolock autoLock(mLock);
168             if (mMaxBytes > 0) {
169                 size = MIN(size, mMaxBytes - mByteCount);
170             }
171             bytes = fwrite(buf, 1, size, mFile);
172             mByteCount += bytes;
173             if (mMaxBytes > 0 && mMaxBytes == mByteCount) {
174                 closeStream_l();
175             }
176         }
177         ALOGV("wrote %zu/%zu bytes to BufLogStream %d tag:%s. Total Bytes: %zu", bytes, size, mId,
178                 mTag, mByteCount);
179     } else {
180         ALOGV("Warning: trying to write to %s BufLogStream id:%d tag:%s",
181                 mPaused ? "paused" : "closed", mId, mTag);
182     }
183     return bytes;
184 }
185 
setPause(bool pause)186 bool BufLogStream::setPause(bool pause) {
187     bool old = mPaused;
188     mPaused = pause;
189     return old;
190 }
191 
finalize()192 void BufLogStream::finalize() {
193     android::Mutex::Autolock autoLock(mLock);
194     closeStream_l();
195 }
196