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

Commit c97cab19 authored by Andy Hung's avatar Andy Hung Committed by Gerrit Code Review
Browse files

Merge changes I7a7e6759,Ifce10352

* changes:
  AudioFlinger: Util clang-tidy fixes
  AudioFlinger: Update utils for clang tidy
parents d4c9da8c 6cc98c61
Loading
Loading
Loading
Loading
+98 −1
Original line number Diff line number Diff line
@@ -7,11 +7,108 @@ package {
    default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
}

audioflinger_utils_tidy_errors = [
    // https://clang.llvm.org/extra/clang-tidy/checks/list.html
    // For many categories, the checks are too many to specify individually.
    // Feel free to disable as needed - as warnings are generally ignored,
    // we treat warnings as errors.
    "android-*",
    "bugprone-*",
    "cert-*",
    "clang-analyzer-security*",
    "google-*",
    "misc-*",
    //"modernize-*",  // explicitly list the modernize as they can be subjective.
    "modernize-avoid-bind",
    //"modernize-avoid-c-arrays", // std::array<> can be verbose
    "modernize-concat-nested-namespaces",
    //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
    "modernize-deprecated-ios-base-aliases",
    "modernize-loop-convert",
    "modernize-make-shared",
    "modernize-make-unique",
    // "modernize-pass-by-value",
    "modernize-raw-string-literal",
    "modernize-redundant-void-arg",
    "modernize-replace-auto-ptr",
    "modernize-replace-random-shuffle",
    "modernize-return-braced-init-list",
    "modernize-shrink-to-fit",
    "modernize-unary-static-assert",
    // "modernize-use-auto",  // found in MediaMetricsService.h, debatable - auto can obscure type
    "modernize-use-bool-literals",
    "modernize-use-default-member-init",
    "modernize-use-emplace",
    "modernize-use-equals-default",
    "modernize-use-equals-delete",
    // "modernize-use-nodiscard",
    "modernize-use-noexcept",
    "modernize-use-nullptr",
    "modernize-use-override",
    //"modernize-use-trailing-return-type", // not necessarily more readable
    "modernize-use-transparent-functors",
    "modernize-use-uncaught-exceptions",
    "modernize-use-using",
    "performance-*",

    // Remove some pedantic stylistic requirements.
    "-google-readability-casting", // C++ casts not always necessary and may be verbose
    "-google-readability-todo",    // do not require TODO(info)

    "-bugprone-unhandled-self-assignment",
    "-bugprone-suspicious-string-compare",
    "-cert-oop54-cpp", // found in TransactionLog.h
    "-bugprone-narrowing-conversions", // b/182410845

    // TODO(b/275642749) Reenable these warnings
    "-misc-non-private-member-variables-in-classes",
]

// Eventually use common tidy defaults
cc_defaults {
    name: "audioflinger_utils_flags_defaults",
    // https://clang.llvm.org/docs/UsersManual.html#command-line-options
    // https://clang.llvm.org/docs/DiagnosticsReference.html
    cflags: [
        "-Wall",
        "-Wdeprecated",
        "-Werror",
        "-Werror=implicit-fallthrough",
        "-Werror=sometimes-uninitialized",
        "-Werror=conditional-uninitialized",
        "-Wextra",

        // suppress some warning chatter.
        "-Wno-deprecated-copy-with-dtor",
        "-Wno-deprecated-copy-with-user-provided-dtor",

        "-Wredundant-decls",
        "-Wshadow",
        "-Wstrict-aliasing",
        "-fstrict-aliasing",
        "-Wthread-safety",
        //"-Wthread-safety-negative", // experimental - looks broken in R.
        "-Wunreachable-code",
        "-Wunreachable-code-break",
        "-Wunreachable-code-return",
        "-Wunused",
        "-Wused-but-marked-unused",
        "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
    ],
    // https://clang.llvm.org/extra/clang-tidy/
    tidy: true,
    tidy_checks: audioflinger_utils_tidy_errors,
    tidy_checks_as_errors: audioflinger_utils_tidy_errors,
    tidy_flags: [
      "-format-style=file",
    ],
}

cc_library {
    name: "libaudioflinger_utils",

    defaults: [
        "audioflinger_flags_defaults",
        "audioflinger_utils_flags_defaults",
    ],

    srcs: [
+13 −11
Original line number Diff line number Diff line
@@ -38,12 +38,12 @@ void AudioWatchdogDump::dump(int fd)
            mUnderruns, mLogs, buf);
}

bool AudioWatchdog::threadLoop()
bool AudioWatchdog::threadLoop() NO_THREAD_SAFETY_ANALYSIS // unique_lock
{
    {
        AutoMutex _l(mMyLock);
        std::unique_lock _l(mLock);
        if (mPaused) {
            mMyCond.wait(mMyLock);
            mCond.wait(_l);
            // ignore previous timestamp after resume()
            mOldTsValid = false;
            // force an immediate log on first underrun after resume()
@@ -65,7 +65,7 @@ bool AudioWatchdog::threadLoop()
        return true;
    }
    time_t sec = newTs.tv_sec - mOldTs.tv_sec;
    long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
    auto nsec = newTs.tv_nsec - mOldTs.tv_nsec;
    if (nsec < 0) {
        --sec;
        nsec += 1000000000;
@@ -81,7 +81,8 @@ bool AudioWatchdog::threadLoop()
        }
    }
    mLogTs.tv_sec += sec;
    if ((mLogTs.tv_nsec += nsec) >= 1000000000) {
    mLogTs.tv_nsec += nsec;
    if (mLogTs.tv_nsec >= 1000000000) {
        mLogTs.tv_sec++;
        mLogTs.tv_nsec -= 1000000000;
    }
@@ -89,7 +90,7 @@ bool AudioWatchdog::threadLoop()
        mDump->mUnderruns = ++mUnderruns;
        if (mLogTs.tv_sec >= MIN_TIME_BETWEEN_LOGS_SEC) {
            mDump->mLogs = ++mLogs;
            mDump->mMostRecent = time(NULL);
            mDump->mMostRecent = time(nullptr /* tloc */);
            ALOGW("Insufficient CPU for load: expected=%.1f actual=%.1f ms; underruns=%u logs=%u",
                mPeriodNs * 1e-6, cycleNs * 1e-6, mUnderruns, mLogs);
            mLogTs.tv_sec = 0;
@@ -99,7 +100,7 @@ bool AudioWatchdog::threadLoop()
    struct timespec req;
    req.tv_sec = 0;
    req.tv_nsec = mPeriodNs;
    rc = nanosleep(&req, NULL);
    rc = nanosleep(&req, nullptr /* remaining */);
    if (!((rc == 0) || (rc == -1 && errno == EINTR))) {
        pause();
        return false;
@@ -116,22 +117,23 @@ void AudioWatchdog::requestExit()

void AudioWatchdog::pause()
{
    AutoMutex _l(mMyLock);
    const std::lock_guard _l(mLock);
    mPaused = true;
}

void AudioWatchdog::resume()
{
    AutoMutex _l(mMyLock);
    const std::lock_guard _l(mLock);
    if (mPaused) {
        mPaused = false;
        mMyCond.signal();
        mCond.notify_one();
    }
}

void AudioWatchdog::setDump(AudioWatchdogDump *dump)
{
    mDump = dump != NULL ? dump : &mDummyDump;
    const std::lock_guard _l(mLock);
    mDump = dump != nullptr ? dump : &mDummyDump;
}

}   // namespace android
+27 −32
Original line number Diff line number Diff line
@@ -19,9 +19,9 @@
//       as soon as possible when there appears to be a CPU shortage
//   (b) monitor the other threads [not yet implemented]

#ifndef AUDIO_WATCHDOG_H
#define AUDIO_WATCHDOG_H
#pragma once

#include <mutex>
#include <time.h>
#include <utils/Thread.h>

@@ -30,33 +30,26 @@ namespace android {
// Keeps a cache of AudioWatchdog statistics that can be logged by dumpsys.
// The usual caveats about atomicity of information apply.
struct AudioWatchdogDump {
    AudioWatchdogDump() : mUnderruns(0), mLogs(0), mMostRecent(0) { }
    /*virtual*/ ~AudioWatchdogDump() { }
    uint32_t mUnderruns;    // total number of underruns
    uint32_t mLogs;         // total number of log messages
    time_t   mMostRecent;   // time of most recent log
    uint32_t mUnderruns = 0;    // total number of underruns
    uint32_t mLogs = 0;         // total number of log messages
    time_t   mMostRecent = 0;   // time of most recent log
    void     dump(int fd);  // should only be called on a stable copy, not the original
};

class AudioWatchdog : public Thread {

public:
    explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/), mPaused(false),
            mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2),
            // mOldTs
            // mLogTs initialized below
            mOldTsValid(false), mUnderruns(0), mLogs(0), mDump(&mDummyDump)
    explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/),
            mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2)
        {
#define MIN_TIME_BETWEEN_LOGS_SEC 60
            // force an immediate log on first underrun
            mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
            mLogTs.tv_nsec = 0;
        }
    virtual         ~AudioWatchdog() { }

     // Do not call Thread::requestExitAndWait() without first calling requestExit().
    // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
    virtual void        requestExit();
    void            requestExit() override;

    // FIXME merge API and implementation with AudioTrackThread
    void            pause();   // suspend thread from execution at next loop boundary
@@ -66,23 +59,25 @@ public:
    void            setDump(AudioWatchdogDump* dump);

private:
    virtual bool    threadLoop();

    Mutex           mMyLock;        // Thread::mLock is private
    Condition       mMyCond;        // Thread::mThreadExitedCondition is private
    bool            mPaused;        // whether thread is currently paused

    uint32_t        mPeriodNs;      // nominal period
    uint32_t        mMaxCycleNs;    // maximum allowed time of one cycle before declaring underrun
    struct timespec mOldTs;         // monotonic time when threadLoop last ran
    struct timespec mLogTs;         // time since last log
    bool            mOldTsValid;    // whether mOldTs is valid
    uint32_t        mUnderruns;     // total number of underruns
    uint32_t        mLogs;          // total number of logs
    AudioWatchdogDump*  mDump;      // where to store the dump, always non-NULL
    bool            threadLoop() override;

    static constexpr int32_t MIN_TIME_BETWEEN_LOGS_SEC = 60;
    const uint32_t  mPeriodNs;       // nominal period
    const uint32_t  mMaxCycleNs;     // maximum allowed time of one cycle before declaring underrun

    mutable std::mutex mLock;      // Thread::mLock is private
    std::condition_variable mCond; // Thread::mThreadExitedCondition is private
    bool            mPaused GUARDED_BY(mLock) = false; // whether thread is currently paused
    bool            mOldTsValid GUARDED_BY(mLock) = false;  // whether mOldTs is valid
    struct timespec mOldTs GUARDED_BY(mLock);          // monotonic time when threadLoop last ran
    struct timespec mLogTs GUARDED_BY(mLock);          // time since last log (ctor init).
    uint32_t        mUnderruns GUARDED_BY(mLock) = 0;  // total number of underruns
    uint32_t        mLogs GUARDED_BY(mLock) = 0;       // total number of logs

    // where to store the dump, always non-NULL
    AudioWatchdogDump*  mDump GUARDED_BY(mLock) = &mDummyDump;
    AudioWatchdogDump   mDummyDump; // default area for dump in case setDump() is not called
};

}   // namespace android
#endif  // AUDIO_WATCHDOG_H
+25 −39
Original line number Diff line number Diff line
@@ -28,12 +28,14 @@

#define MIN(a, b) ((a) < (b) ? (a) : (b))

namespace android {

// ------------------------------
// BufLogSingleton
// ------------------------------
pthread_once_t onceControl = PTHREAD_ONCE_INIT;

BufLog *BufLogSingleton::mInstance = NULL;
BufLog *BufLogSingleton::mInstance = nullptr;

void BufLogSingleton::initOnce() {
    mInstance = new BufLog();
@@ -49,55 +51,39 @@ BufLog *BufLogSingleton::instance() {
}

bool BufLogSingleton::instanceExists() {
    return mInstance != NULL;
    return mInstance != nullptr;
}

// ------------------------------
// BufLog
// ------------------------------

BufLog::BufLog() {
    memset(mStreams, 0, sizeof(mStreams));
}

BufLog::~BufLog() {
    android::Mutex::Autolock autoLock(mLock);

    for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
        BufLogStream *pBLStream = mStreams[id];
        if (pBLStream != NULL) {
            delete pBLStream ;
            mStreams[id] = NULL;
        }
    }
    reset();
}

size_t BufLog::write(int streamid, const char *tag, int format, int channels,
        int samplingRate, size_t maxBytes, const void *buf, size_t size) {
    unsigned int id = streamid % BUFLOG_MAXSTREAMS;
    android::Mutex::Autolock autoLock(mLock);
    const unsigned int id = streamid % BUFLOG_MAXSTREAMS;
    const std::lock_guard autoLock(mLock);

    BufLogStream *pBLStream = mStreams[id];

    if (pBLStream == NULL) {
    if (pBLStream == nullptr) {
        pBLStream = mStreams[id] = new BufLogStream(id, tag, format, channels,
                samplingRate, maxBytes);
        ALOG_ASSERT(pBLStream != NULL, "BufLogStream Failed to be created");
    }

    return pBLStream->write(buf, size);
}

void BufLog::reset() {
    android::Mutex::Autolock autoLock(mLock);
    ALOGV("Resetting all BufLogs");
    const std::lock_guard autoLock(mLock);
    int count = 0;

    for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
        BufLogStream *pBLStream = mStreams[id];
        if (pBLStream != NULL) {
    for (auto &pBLStream : mStreams) {
        if (pBLStream != nullptr) {
            delete pBLStream;
            mStreams[id] = NULL;
            pBLStream = nullptr;
            count++;
        }
    }
@@ -115,9 +101,7 @@ BufLogStream::BufLogStream(unsigned int id,
        unsigned int samplingRate,
        size_t maxBytes = 0) : mId(id), mFormat(format), mChannels(channels),
                mSamplingRate(samplingRate), mMaxBytes(maxBytes) {
    mByteCount = 0;
    mPaused = false;
    if (tag != NULL) {
    if (tag != nullptr) {
        (void)audio_utils_strlcpy(mTag, tag);
    } else {
        mTag[0] = 0;
@@ -129,7 +113,7 @@ BufLogStream::BufLogStream(unsigned int id,
    //timestamp
    char timeStr[16];   //size 16: format %Y%m%d%H%M%S 14 chars + string null terminator
    struct timeval tv;
    gettimeofday(&tv, NULL);
    gettimeofday(&tv, nullptr);
    struct tm tm;
    localtime_r(&tv.tv_sec, &tm);
    strftime(timeStr, sizeof(timeStr), "%Y%m%d%H%M%S", &tm);
@@ -139,7 +123,7 @@ BufLogStream::BufLogStream(unsigned int id,
    ALOGV("data output: %s", logPath);

    mFile = fopen(logPath, "wb");
    if (mFile != NULL) {
    if (mFile != nullptr) {
        ALOGV("Success creating file at: %p", mFile);
    } else {
        ALOGE("Error: could not create file BufLogStream %s", strerror(errno));
@@ -148,24 +132,24 @@ BufLogStream::BufLogStream(unsigned int id,

void BufLogStream::closeStream_l() {
    ALOGV("Closing BufLogStream id:%d tag:%s", mId, mTag);
    if (mFile != NULL) {
    if (mFile != nullptr) {
        fclose(mFile);
        mFile = NULL;
        mFile = nullptr;
    }
}

BufLogStream::~BufLogStream() {
    ALOGV("Destroying BufLogStream id:%d tag:%s", mId, mTag);
    android::Mutex::Autolock autoLock(mLock);
    const std::lock_guard autoLock(mLock);
    closeStream_l();
}

size_t BufLogStream::write(const void *buf, size_t size) {

    size_t bytes = 0;
    if (!mPaused && mFile != NULL) {
        if (size > 0 && buf != NULL) {
            android::Mutex::Autolock autoLock(mLock);
    if (!mPaused && mFile != nullptr) {
        if (size > 0 && buf != nullptr) {
            const std::lock_guard autoLock(mLock);
            if (mMaxBytes > 0) {
                size = MIN(size, mMaxBytes - mByteCount);
            }
@@ -185,12 +169,14 @@ size_t BufLogStream::write(const void *buf, size_t size) {
}

bool BufLogStream::setPause(bool pause) {
    bool old = mPaused;
    const bool old = mPaused;
    mPaused = pause;
    return old;
}

void BufLogStream::finalize() {
    android::Mutex::Autolock autoLock(mLock);
    const std::lock_guard autoLock(mLock);
    closeStream_l();
}

} // namespace android
+14 −16
Original line number Diff line number Diff line
@@ -14,8 +14,7 @@
 * limitations under the License.
 */

#ifndef ANDROID_AUDIO_BUFLOG_H
#define ANDROID_AUDIO_BUFLOG_H
#pragma once

/*
 * BUFLOG creates up to BUFLOG_MAXSTREAMS simultaneous streams [0:15] of audio buffer data
@@ -99,17 +98,18 @@
    BufLogSingleton::instance()->reset(); } } while (0)
#endif


#include <mutex>
#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

namespace android {

class BufLogStream {
public:
    BufLogStream(unsigned int id,
@@ -135,26 +135,24 @@ public:
    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;
    char                mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1]; // const, set in ctor.

    mutable std::mutex  mLock;
    bool                mPaused = false;
    size_t              mByteCount = 0;
    FILE                *mFile; // set in ctor

    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
@@ -181,9 +179,9 @@ public:
    void            reset();

protected:
    static const unsigned int BUFLOG_MAXSTREAMS = 16;
    BufLogStream    *mStreams[BUFLOG_MAXSTREAMS];
    mutable android::Mutex mLock;
    static constexpr size_t BUFLOG_MAXSTREAMS = 16;
    mutable std::mutex mLock;
    BufLogStream *mStreams[BUFLOG_MAXSTREAMS]{};
};

class BufLogSingleton {
@@ -196,4 +194,4 @@ private:
    static BufLog   *mInstance;
};

#endif //ANDROID_AUDIO_BUFLOG_H
} // namespace android
Loading