Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0894bfb7 authored by Glenn Kasten's avatar Glenn Kasten Committed by Android (Google) Code Review
Browse files

Merge "Update tee sink"

parents 4bc4a384 da6ef132
Loading
Loading
Loading
Loading
+0 −8
Original line number Original line Diff line number Diff line
@@ -66,14 +66,6 @@ LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"'


LOCAL_CFLAGS += -UFAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE
LOCAL_CFLAGS += -UFAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE


# uncomment for dumpsys to write most recent audio output to .wav file
# 47.5 seconds at 44.1 kHz, 8 megabytes
# LOCAL_CFLAGS += -DTEE_SINK_FRAMES=0x200000

# uncomment for dumpsys to write most recent audio input to .wav file
# 47.5 seconds at 44.1 kHz, 8 megabytes
# LOCAL_CFLAGS += -DTEE_SINK_INPUT_FRAMES=0x200000

# uncomment to enable the audio watchdog
# uncomment to enable the audio watchdog
# LOCAL_SRC_FILES += AudioWatchdog.cpp
# LOCAL_SRC_FILES += AudioWatchdog.cpp
# LOCAL_CFLAGS += -DAUDIO_WATCHDOG
# LOCAL_CFLAGS += -DAUDIO_WATCHDOG
+101 −10
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#define LOG_TAG "AudioFlinger"
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
//#define LOG_NDEBUG 0


#include <dirent.h>
#include <math.h>
#include <math.h>
#include <signal.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/time.h>
@@ -61,6 +62,9 @@


#include <media/IMediaLogService.h>
#include <media/IMediaLogService.h>


#include <media/nbaio/Pipe.h>
#include <media/nbaio/PipeReader.h>

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------


// Note: the following macro is used for extremely verbose logging message.  In
// Note: the following macro is used for extremely verbose logging message.  In
@@ -86,6 +90,14 @@ nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;


uint32_t AudioFlinger::mScreenState;
uint32_t AudioFlinger::mScreenState;


bool AudioFlinger::mTeeSinkInputEnabled = false;
bool AudioFlinger::mTeeSinkOutputEnabled = false;
bool AudioFlinger::mTeeSinkTrackEnabled = false;

size_t AudioFlinger::mTeeSinkInputFrames = kTeeSinkInputFramesDefault;
size_t AudioFlinger::mTeeSinkOutputFrames = kTeeSinkOutputFramesDefault;
size_t AudioFlinger::mTeeSinkTrackFrames = kTeeSinkTrackFramesDefault;

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------


static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
@@ -134,6 +146,19 @@ AudioFlinger::AudioFlinger()
    if (doLog) {
    if (doLog) {
        mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters");
        mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters");
    }
    }
    (void) property_get("ro.debuggable", value, "0");
    int debuggable = atoi(value);
    int teeEnabled = 0;
    if (debuggable) {
        (void) property_get("af.tee", value, "0");
        teeEnabled = atoi(value);
    }
    if (teeEnabled & 1)
        mTeeSinkInputEnabled = true;
    if (teeEnabled & 2)
        mTeeSinkOutputEnabled = true;
    if (teeEnabled & 4)
        mTeeSinkTrackEnabled = true;
}
}


void AudioFlinger::onFirstRef()
void AudioFlinger::onFirstRef()
@@ -1602,7 +1627,6 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
        // Try to re-use most recently used Pipe to archive a copy of input for dumpsys,
        // Try to re-use most recently used Pipe to archive a copy of input for dumpsys,
        // or (re-)create if current Pipe is idle and does not match the new format
        // or (re-)create if current Pipe is idle and does not match the new format
        sp<NBAIO_Sink> teeSink;
        sp<NBAIO_Sink> teeSink;
#ifdef TEE_SINK_INPUT_FRAMES
        enum {
        enum {
            TEE_SINK_NO,    // don't copy input
            TEE_SINK_NO,    // don't copy input
            TEE_SINK_NEW,   // copy input using a new pipe
            TEE_SINK_NEW,   // copy input using a new pipe
@@ -1610,7 +1634,9 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
        } kind;
        } kind;
        NBAIO_Format format = Format_from_SR_C(inStream->common.get_sample_rate(&inStream->common),
        NBAIO_Format format = Format_from_SR_C(inStream->common.get_sample_rate(&inStream->common),
                                        popcount(inStream->common.get_channels(&inStream->common)));
                                        popcount(inStream->common.get_channels(&inStream->common)));
        if (format == Format_Invalid) {
        if (!mTeeSinkInputEnabled) {
            kind = TEE_SINK_NO;
        } else if (format == Format_Invalid) {
            kind = TEE_SINK_NO;
            kind = TEE_SINK_NO;
        } else if (mRecordTeeSink == 0) {
        } else if (mRecordTeeSink == 0) {
            kind = TEE_SINK_NEW;
            kind = TEE_SINK_NEW;
@@ -1623,7 +1649,7 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
        }
        }
        switch (kind) {
        switch (kind) {
        case TEE_SINK_NEW: {
        case TEE_SINK_NEW: {
            Pipe *pipe = new Pipe(TEE_SINK_INPUT_FRAMES, format);
            Pipe *pipe = new Pipe(mTeeSinkInputFrames, format);
            size_t numCounterOffers = 0;
            size_t numCounterOffers = 0;
            const NBAIO_Format offers[1] = {format};
            const NBAIO_Format offers[1] = {format};
            ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
            ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
@@ -1644,7 +1670,7 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
        default:
        default:
            break;
            break;
        }
        }
#endif

        AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
        AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);


        // Start record thread
        // Start record thread
@@ -2199,19 +2225,80 @@ status_t AudioFlinger::moveEffectChain_l(int sessionId,
    return NO_ERROR;
    return NO_ERROR;
}
}


struct Entry {
#define MAX_NAME 32     // %Y%m%d%H%M%S_%d.wav
    char mName[MAX_NAME];
};

int comparEntry(const void *p1, const void *p2)
{
    return strcmp(((const Entry *) p1)->mName, ((const Entry *) p2)->mName);
}

void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_handle_t id)
void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_handle_t id)
{
{
    NBAIO_Source *teeSource = source.get();
    NBAIO_Source *teeSource = source.get();
    if (teeSource != NULL) {
    if (teeSource != NULL) {
        // .wav rotation
        // There is a benign race condition if 2 threads call this simultaneously.
        // They would both traverse the directory, but the result would simply be
        // failures at unlink() which are ignored.  It's also unlikely since
        // normally dumpsys is only done by bugreport or from the command line.
        char teePath[32+256];
        strcpy(teePath, "/data/misc/media");
        size_t teePathLen = strlen(teePath);
        DIR *dir = opendir(teePath);
        teePath[teePathLen++] = '/';
        if (dir != NULL) {
#define MAX_SORT 20 // number of entries to sort
#define MAX_KEEP 10 // number of entries to keep
            struct Entry entries[MAX_SORT];
            size_t entryCount = 0;
            while (entryCount < MAX_SORT) {
                struct dirent de;
                struct dirent *result = NULL;
                int rc = readdir_r(dir, &de, &result);
                if (rc != 0) {
                    ALOGW("readdir_r failed %d", rc);
                    break;
                }
                if (result == NULL) {
                    break;
                }
                if (result != &de) {
                    ALOGW("readdir_r returned unexpected result %p != %p", result, &de);
                    break;
                }
                // ignore non .wav file entries
                size_t nameLen = strlen(de.d_name);
                if (nameLen <= 4 || nameLen >= MAX_NAME ||
                        strcmp(&de.d_name[nameLen - 4], ".wav")) {
                    continue;
                }
                strcpy(entries[entryCount++].mName, de.d_name);
            }
            (void) closedir(dir);
            if (entryCount > MAX_KEEP) {
                qsort(entries, entryCount, sizeof(Entry), comparEntry);
                for (size_t i = 0; i < entryCount - MAX_KEEP; ++i) {
                    strcpy(&teePath[teePathLen], entries[i].mName);
                    (void) unlink(teePath);
                }
            }
        } else {
            if (fd >= 0) {
                fdprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno));
            }
        }
        char teeTime[16];
        char teeTime[16];
        struct timeval tv;
        struct timeval tv;
        gettimeofday(&tv, NULL);
        gettimeofday(&tv, NULL);
        struct tm tm;
        struct tm tm;
        localtime_r(&tv.tv_sec, &tm);
        localtime_r(&tv.tv_sec, &tm);
        strftime(teeTime, sizeof(teeTime), "%T", &tm);
        strftime(teeTime, sizeof(teeTime), "%Y%m%d%H%M%S", &tm);
        char teePath[64];
        snprintf(&teePath[teePathLen], sizeof(teePath) - teePathLen, "%s_%d.wav", teeTime, id);
        sprintf(teePath, "/data/misc/media/%s_%d.wav", teeTime, id);
        // if 2 dumpsys are done within 1 second, and rotation didn't work, then discard 2nd
        int teeFd = open(teePath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
        int teeFd = open(teePath, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, S_IRUSR | S_IWUSR);
        if (teeFd >= 0) {
        if (teeFd >= 0) {
            char wavHeader[44];
            char wavHeader[44];
            memcpy(wavHeader,
            memcpy(wavHeader,
@@ -2253,9 +2340,13 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand
            temp =  total * channelCount * sizeof(short);
            temp =  total * channelCount * sizeof(short);
            write(teeFd, &temp, sizeof(temp));
            write(teeFd, &temp, sizeof(temp));
            close(teeFd);
            close(teeFd);
            fdprintf(fd, "FastMixer tee copied to %s\n", teePath);
            if (fd >= 0) {
                fdprintf(fd, "tee copied to %s\n", teePath);
            }
        } else {
        } else {
            fdprintf(fd, "FastMixer unable to create tee %s: \n", strerror(errno));
            if (fd >= 0) {
                fdprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno));
            }
        }
        }
    }
    }
}
}
+17 −0
Original line number Original line Diff line number Diff line
@@ -593,7 +593,24 @@ private:
    sp<NBAIO_Source> mRecordTeeSource;
    sp<NBAIO_Source> mRecordTeeSource;


public:
public:
    // tee sink, if enabled by property, allows dumpsys to write most recent audio to .wav file
    static void dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_handle_t id = 0);
    static void dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_handle_t id = 0);

    // whether tee sink is enabled by property
    static bool mTeeSinkInputEnabled;
    static bool mTeeSinkOutputEnabled;
    static bool mTeeSinkTrackEnabled;

    // runtime configured size of each tee sink pipe, in frames
    static size_t mTeeSinkInputFrames;
    static size_t mTeeSinkOutputFrames;
    static size_t mTeeSinkTrackFrames;

    // compile-time default size of tee sink pipes, in frames
    // 0x200000 stereo 16-bit PCM frames = 47.5 seconds at 44.1 kHz, 8 megabytes
    static const size_t kTeeSinkInputFramesDefault = 0x200000;
    static const size_t kTeeSinkOutputFramesDefault = 0x200000;
    static const size_t kTeeSinkTrackFramesDefault = 0x1000;
};
};


#undef INCLUDING_FROM_AUDIOFLINGER_H
#undef INCLUDING_FROM_AUDIOFLINGER_H
+13 −13
Original line number Original line Diff line number Diff line
@@ -2124,9 +2124,9 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud
                (monoPipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2);
                (monoPipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2);
        mPipeSink = monoPipe;
        mPipeSink = monoPipe;


#ifdef TEE_SINK_FRAMES
        if (mTeeSinkOutputEnabled) {
            // create a Pipe to archive a copy of FastMixer's output for dumpsys
            // create a Pipe to archive a copy of FastMixer's output for dumpsys
        Pipe *teeSink = new Pipe(TEE_SINK_FRAMES, format);
            Pipe *teeSink = new Pipe(mTeeSinkOutputFrames, format);
            numCounterOffers = 0;
            numCounterOffers = 0;
            index = teeSink->negotiate(offers, 1, NULL, numCounterOffers);
            index = teeSink->negotiate(offers, 1, NULL, numCounterOffers);
            ALOG_ASSERT(index == 0);
            ALOG_ASSERT(index == 0);
@@ -2136,7 +2136,7 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud
            index = teeSource->negotiate(offers, 1, NULL, numCounterOffers);
            index = teeSource->negotiate(offers, 1, NULL, numCounterOffers);
            ALOG_ASSERT(index == 0);
            ALOG_ASSERT(index == 0);
            mTeeSource = teeSource;
            mTeeSource = teeSource;
#endif
        }


        // create fast mixer and configure it initially with just one fast track for our submix
        // create fast mixer and configure it initially with just one fast track for our submix
        mFastMixer = new FastMixer();
        mFastMixer = new FastMixer();
+3 −0
Original line number Original line Diff line number Diff line
@@ -141,4 +141,7 @@ protected:
    Vector < sp<SyncEvent> >mSyncEvents;
    Vector < sp<SyncEvent> >mSyncEvents;
    const bool          mIsOut;
    const bool          mIsOut;
    ServerProxy*        mServerProxy;
    ServerProxy*        mServerProxy;
    const int           mId;
    sp<NBAIO_Sink>      mTeeSink;
    sp<NBAIO_Source>    mTeeSource;
};
};
Loading