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

Commit 84e84a5d authored by Ray Essick's avatar Ray Essick
Browse files

collect more media metrics around audio

new fields in the media metrics 'audiorecord' record for more detail
length of time recorded, error conditions
add new media metrics type 'audiopolicy' that describes attempts to get
microphone access -- success, failure on contention, what type of access
was requested, and (important for the contention) which programs are
doing the requesting and holding of the microphones.

whitelist the 'audiopolicy' metrics type with the  media.metrics service.

Bug: 78595399
Test: concurrent/serial recordings, dumpsys media.metrics
Change-Id: Ia17860940d4c329b0215b4cf97c6dacacb6a8e32
parent 527da4c9
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -99,6 +99,11 @@ void AudioRecord::MediaMetrics::gather(const AudioRecord *record)
    static constexpr char kAudioRecordLatency[] = "android.media.audiorecord.latency";
    static constexpr char kAudioRecordSampleRate[] = "android.media.audiorecord.samplerate";
    static constexpr char kAudioRecordChannelCount[] = "android.media.audiorecord.channels";
    static constexpr char kAudioRecordCreated[] = "android.media.audiorecord.createdMs";
    static constexpr char kAudioRecordDuration[] = "android.media.audiorecord.durationMs";
    static constexpr char kAudioRecordCount[] = "android.media.audiorecord.n";
    static constexpr char kAudioRecordError[] = "android.media.audiorecord.errcode";
    static constexpr char kAudioRecordErrorFunction[] = "android.media.audiorecord.errfunc";

    // constructor guarantees mAnalyticsItem is valid

@@ -109,6 +114,24 @@ void AudioRecord::MediaMetrics::gather(const AudioRecord *record)
                               audioFormatTypeString(record->mFormat).c_str());
    mAnalyticsItem->setCString(kAudioRecordSource,
                               audioSourceString(record->mAttributes.source).c_str());

    // log total duration recording, including anything currently running [and count].
    nsecs_t active = 0;
    if (mStartedNs != 0) {
        active = systemTime() - mStartedNs;
    }
    mAnalyticsItem->setInt64(kAudioRecordDuration, (mDurationNs + active) / (1000 * 1000));
    mAnalyticsItem->setInt32(kAudioRecordCount, mCount);

    // XXX I don't know that this adds a lot of value, long term
    if (mCreatedNs != 0) {
        mAnalyticsItem->setInt64(kAudioRecordCreated, mCreatedNs / (1000 * 1000));
    }

    if (mLastError != NO_ERROR) {
        mAnalyticsItem->setInt32(kAudioRecordError, mLastError);
        mAnalyticsItem->setCString(kAudioRecordErrorFunction, mLastErrorFunc.c_str());
    }
}

// hand the user a snapshot of the metrics.
@@ -354,6 +377,9 @@ status_t AudioRecord::set(

exit:
    mStatus = status;
    if (status != NO_ERROR) {
        mMediaMetrics.markError(status, __FUNCTION__);
    }
    return status;
}

@@ -412,8 +438,14 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t tri
            get_sched_policy(0, &mPreviousSchedulingGroup);
            androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
        }

        // we've successfully started, log that time
        mMediaMetrics.logStart(systemTime());
    }

    if (status != NO_ERROR) {
        mMediaMetrics.markError(status, __FUNCTION__);
    }
    return status;
}

@@ -438,6 +470,9 @@ void AudioRecord::stop()
        setpriority(PRIO_PROCESS, 0, mPreviousPriority);
        set_sched_policy(0, mPreviousSchedulingGroup);
    }

    // we've successfully started, log that time
    mMediaMetrics.logStop(systemTime());
}

bool AudioRecord::stopped() const
+16 −1
Original line number Diff line number Diff line
@@ -704,7 +704,10 @@ private:
private:
    class MediaMetrics {
      public:
        MediaMetrics() : mAnalyticsItem(new MediaAnalyticsItem("audiorecord")) {
        MediaMetrics() : mAnalyticsItem(new MediaAnalyticsItem("audiorecord")),
                         mCreatedNs(systemTime(SYSTEM_TIME_REALTIME)),
                         mStartedNs(0), mDurationNs(0), mCount(0),
                         mLastError(NO_ERROR) {
        }
        ~MediaMetrics() {
            // mAnalyticsItem alloc failure will be flagged in the constructor
@@ -715,8 +718,20 @@ private:
        }
        void gather(const AudioRecord *record);
        MediaAnalyticsItem *dup() { return mAnalyticsItem->dup(); }

        void logStart(nsecs_t when) { mStartedNs = when; mCount++; }
        void logStop(nsecs_t when) { mDurationNs += (when-mStartedNs); mStartedNs = 0;}
        void markError(status_t errcode, const char *func)
                 { mLastError = errcode; mLastErrorFunc = func;}
      private:
        std::unique_ptr<MediaAnalyticsItem> mAnalyticsItem;
        nsecs_t mCreatedNs;     // XXX: perhaps not worth it in production
        nsecs_t mStartedNs;
        nsecs_t mDurationNs;
        int32_t mCount;

        status_t mLastError;
        std::string mLastErrorFunc;
    };
    MediaMetrics mMediaMetrics;
};
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ LOCAL_SHARED_LIBRARIES := \
    libserviceutility \
    libaudiopolicymanager \
    libmedia_helper \
    libmediametrics \
    libeffectsconfig

LOCAL_STATIC_LIBRARIES := \
@@ -60,6 +61,7 @@ LOCAL_REQUIRED_MODULES := \
    audio_policy_criteria.conf \

LOCAL_C_INCLUDES += frameworks/av/services/audiopolicy/engineconfigurable/include
LOCAL_C_INCLUDES += frameworks/av/include

LOCAL_SHARED_LIBRARIES += libaudiopolicyengineconfigurable

@@ -78,6 +80,7 @@ LOCAL_STATIC_LIBRARIES := \
    libaudiopolicycomponents

LOCAL_SHARED_LIBRARIES += libmedia_helper
LOCAL_SHARED_LIBRARIES += libmediametrics

ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
LOCAL_SHARED_LIBRARIES += libicuuc libxml2
+5 −1
Original line number Diff line number Diff line
@@ -69,8 +69,12 @@ public:
        API_INPUT_CONCURRENCY_NONE = 0,
        API_INPUT_CONCURRENCY_CALL = (1 << 0),      // Concurrency with a call
        API_INPUT_CONCURRENCY_CAPTURE = (1 << 1),   // Concurrency with another capture
        API_INPUT_CONCURRENCY_HOTWORD = (1 << 2),   // Concurrency with a hotword
        API_INPUT_CONCURRENCY_PREEMPT = (1 << 3),   // pre-empted someone
                // NB: preempt is marked on a successful return, others are on failing calls
        API_INPUT_CONCURRENCY_LAST = (1 << 4),

        API_INPUT_CONCURRENCY_ALL = (API_INPUT_CONCURRENCY_CALL | API_INPUT_CONCURRENCY_CAPTURE),
        API_INPUT_CONCURRENCY_ALL = (API_INPUT_CONCURRENCY_LAST - 1),
    };

    typedef uint32_t concurrency_type__mask_t;
+5 −0
Original line number Diff line number Diff line
@@ -1878,6 +1878,7 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
        if (mCallTxPatch != 0 &&
            inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
            ALOGW("startInput(%d) failed: call in progress", input);
            *concurrency |= API_INPUT_CONCURRENCY_CALL;
            return INVALID_OPERATION;
        }

@@ -1920,17 +1921,20 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
                        ALOGW("startInput(%d) failed for HOTWORD: "
                                "other input %d already started for HOTWORD",
                              input, activeDesc->mIoHandle);
                        *concurrency |= API_INPUT_CONCURRENCY_HOTWORD;
                        return INVALID_OPERATION;
                    }
                } else {
                    ALOGV("startInput(%d) failed for HOTWORD: other input %d already started",
                          input, activeDesc->mIoHandle);
                    *concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
                    return INVALID_OPERATION;
                }
            } else {
                if (activeSource != AUDIO_SOURCE_HOTWORD) {
                    ALOGW("startInput(%d) failed: other input %d already started",
                          input, activeDesc->mIoHandle);
                    *concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
                    return INVALID_OPERATION;
                }
            }
@@ -1955,6 +1959,7 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
                audio_session_t activeSession = activeSessions.keyAt(0);
                audio_io_handle_t activeHandle = activeDesc->mIoHandle;
                SortedVector<audio_session_t> sessions = activeDesc->getPreemptedSessions();
                *concurrency |= API_INPUT_CONCURRENCY_PREEMPT;
                sessions.add(activeSession);
                inputDesc->setPreemptedSessions(sessions);
                stopInput(activeHandle, activeSession);
Loading