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