/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "AudioAnalytics"
#include <android-base/logging.h>
#include <utils/Log.h>

#include "AudioAnalytics.h"

#include <aaudio/AAudio.h>        // error codes
#include <audio_utils/clock.h>    // clock conversions
#include <cutils/properties.h>
#include <stats_media_metrics.h>             // statsd
#include <system/audio.h>

#include "AudioTypes.h"           // string to int conversions
#include "MediaMetricsService.h"  // package info
#include "StringUtils.h"
#include "ValidateId.h"

#define PROP_AUDIO_ANALYTICS_CLOUD_ENABLED "persist.audio.analytics.cloud.enabled"

namespace android::mediametrics {

// Enable for testing of delivery to statsd. Caution if this is enabled, all protos MUST exist.
#define STATSD_ENABLE

#ifdef STATSD_ENABLE
#define CONDITION(INT_VALUE) (INT_VALUE)  // allow value
#else
#define CONDITION(INT_VALUE) (int(0))     // mask value since the proto may not be defined yet.
#endif

// Maximum length of a device name.
// static constexpr size_t STATSD_DEVICE_NAME_MAX_LENGTH = 32; // unused since we suppress

// Transmit Enums to statsd in integer or strings  (this must match the atoms.proto)
static constexpr bool STATSD_USE_INT_FOR_ENUM = false;

// derive types based on integer or strings.
using short_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int32_t, std::string>;
using long_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int64_t, std::string>;

// Convert std::string to char *
template <typename T>
auto ENUM_EXTRACT(const T& x) {
    if constexpr (std::is_same_v<std::decay_t<T>, std::string>) {
        return x.c_str();
    } else {
        return x;
    }
}

// The status variable contains status_t codes which are used by
// the core audio framework. We also consider AAudio status codes.
//
// Compare with mediametrics::statusToStatusString
//
inline constexpr const char* extendedStatusToStatusString(status_t status) {
    switch (status) {
    case BAD_VALUE:           // status_t
    case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
    case AAUDIO_ERROR_INVALID_FORMAT:
    case AAUDIO_ERROR_INVALID_RATE:
    case AAUDIO_ERROR_NULL:
    case AAUDIO_ERROR_OUT_OF_RANGE:
        return AMEDIAMETRICS_PROP_STATUS_VALUE_ARGUMENT;
    case DEAD_OBJECT:         // status_t
    case FAILED_TRANSACTION:  // status_t
    case AAUDIO_ERROR_DISCONNECTED:
    case AAUDIO_ERROR_INVALID_HANDLE:
    case AAUDIO_ERROR_NO_SERVICE:
        return AMEDIAMETRICS_PROP_STATUS_VALUE_IO;
    case NO_MEMORY:           // status_t
    case AAUDIO_ERROR_NO_FREE_HANDLES:
    case AAUDIO_ERROR_NO_MEMORY:
        return AMEDIAMETRICS_PROP_STATUS_VALUE_MEMORY;
    case PERMISSION_DENIED:   // status_t
        return AMEDIAMETRICS_PROP_STATUS_VALUE_SECURITY;
    case INVALID_OPERATION:   // status_t
    case NO_INIT:             // status_t
    case AAUDIO_ERROR_INVALID_STATE:
    case AAUDIO_ERROR_UNAVAILABLE:
    case AAUDIO_ERROR_UNIMPLEMENTED:
        return AMEDIAMETRICS_PROP_STATUS_VALUE_STATE;
    case WOULD_BLOCK:         // status_t
    case AAUDIO_ERROR_TIMEOUT:
    case AAUDIO_ERROR_WOULD_BLOCK:
        return AMEDIAMETRICS_PROP_STATUS_VALUE_TIMEOUT;
    default:
        if (status >= 0) return AMEDIAMETRICS_PROP_STATUS_VALUE_OK; // non-negative values "OK"
        [[fallthrough]];            // negative values are error.
    case UNKNOWN_ERROR:       // status_t
        return AMEDIAMETRICS_PROP_STATUS_VALUE_UNKNOWN;
    }
}

static constexpr const auto LOG_LEVEL = android::base::VERBOSE;

static constexpr int PREVIOUS_STATE_EXPIRE_SEC = 60 * 60; // 1 hour.

static constexpr const char * SUPPRESSED = "SUPPRESSED";

/*
 * For logging purposes, we list all of the MediaMetrics atom fields,
 * which can then be associated with consecutive arguments to the statsd write.
 */

static constexpr const char * const AudioRecordDeviceUsageFields[] = {
    "mediametrics_audiorecorddeviceusage_reported", // proto number
    "devices",
    "device_names",
    "device_time_nanos",
    "encoding",
    "frame_count",
    "interval_count",
    "sample_rate",
    "flags",
    "package_name",
    "selected_device_id",
    "caller",
    "source",
    "log_session_id",
};

static constexpr const char * const AudioThreadDeviceUsageFields[] = {
    "mediametrics_audiothreaddeviceusage_reported",
    "devices",
    "device_names",
    "device_time_nanos",
    "encoding",
    "frame_count",
    "interval_count",
    "sample_rate",
    "flags",
    "xruns",
    "type",
};

static constexpr const char * const AudioTrackDeviceUsageFields[] = {
    "mediametrics_audiotrackdeviceusage_reported",
    "devices",
    "device_names",
    "device_time_nanos",
    "encoding",
    "frame_count",
    "interval_count",
    "sample_rate",
    "flags",
    "xruns",
    "package_name",
    "device_latency_millis",
    "device_startup_millis",
    "device_volume",
    "selected_device_id",
    "stream_type",
    "usage",
    "content_type",
    "caller",
    "traits",
    "log_session_id",
};

static constexpr const char * const AudioRecordStatusFields[] {
    "mediametrics_audiorecordstatus_reported",
    "status",
    "debug_message",
    "status_subcode",
    "uid",
    "event",
    "input_flags",
    "source",
    "encoding",
    "channel_mask",
    "buffer_frame_count",
    "sample_rate",
};

static constexpr const char * const AudioTrackStatusFields[] {
    "mediametrics_audiotrackstatus_reported",
    "status",
    "debug_message",
    "status_subcode",
    "uid",
    "event",
    "output_flags",
    "content_type",
    "usage",
    "encoding",
    "channel_mask",
    "buffer_frame_count",
    "sample_rate",
    "speed",
    "pitch",
};

static constexpr const char * const AudioDeviceConnectionFields[] = {
    "mediametrics_audiodeviceconnection_reported",
    "input_devices",
    "output_devices",
    "device_names",
    "result",
    "time_to_connect_millis",
    "connection_count",
};

static constexpr const char * const AAudioStreamFields[] {
    "mediametrics_aaudiostream_reported",
    "path",
    "direction",
    "frames_per_burst",
    "buffer_size",
    "buffer_capacity",
    "channel_count",
    "total_frames_transferred",
    "perf_mode_requested",
    "perf_mode_actual",
    "sharing",
    "xrun_count",
    "device_type",
    "format_app",
    "format_device",
    "log_session_id",
    "sample_rate",
    "content_type",
    "sharing_requested",
    "format_hardware",
    "channel_count_hardware",
    "sample_rate_hardware",
    "uid",
    "sample_rate_client",
};

static constexpr const char * HeadTrackerDeviceEnabledFields[] {
    "mediametrics_headtrackerdeviceenabled_reported",
    "type",
    "event",
    "enabled",
};

static constexpr const char * HeadTrackerDeviceSupportedFields[] {
    "mediametrics_headtrackerdevicesupported_reported",
    "type",
    "event",
    "supported",
};

static constexpr const char * SpatializerCapabilitiesFields[] {
    "mediametrics_spatializer_reported",
    "head_tracking_modes",
    "spatializer_levels",
    "spatializer_modes",
    "channel_masks",
};

static constexpr const char * SpatializerDeviceEnabledFields[] {
    "mediametrics_spatializerdeviceenabled_reported",
    "type",
    "event",
    "enabled",
};

static constexpr const char * const MidiDeviceCloseFields[] {
    "mediametrics_midi_device_close_reported",
    "uid",
    "midi_device_id",
    "input_port_count",
    "output_port_count",
    "device_type",
    "is_shared",
    "supports_ump",
    "using_alsa",
    "duration_ns",
    "opened_count",
    "closed_count",
    "device_disconnected",
    "total_input_bytes",
    "total_output_bytes",
};

/**
 * printFields is a helper method that prints the fields and corresponding values
 * in a human readable style.
 */
template <size_t N, typename ...Types>
std::string printFields(const char * const (& fields)[N], Types ... args)
{
    std::stringstream ss;
    ss << " { ";
    stringutils::fieldPrint(ss, fields, args...);
    ss << "}";
    return ss.str();
}

/**
 * sendToStatsd is a helper method that sends the arguments to statsd
 */
template <typename ...Types>
int sendToStatsd(Types ... args)
{
    int result = 0;

#ifdef STATSD_ENABLE
    result = stats::media_metrics::stats_write(args...);
#endif
    return result;
}

/**
 * sendToStatsd is a helper method that sends the arguments to statsd
 * and returns a pair { result, summary_string }.
 */
template <size_t N, typename ...Types>
std::pair<int, std::string> sendToStatsd(const char * const (& fields)[N], Types ... args)
{
    int result = 0;
    std::stringstream ss;

#ifdef STATSD_ENABLE
    result = stats::media_metrics::stats_write(args...);
    ss << "result:" << result;
#endif
    ss << " { ";
    stringutils::fieldPrint(ss, fields, args...);
    ss << "}";
    return { result, ss.str() };
}

AudioAnalytics::AudioAnalytics(const std::shared_ptr<StatsdLog>& statsdLog)
    : mDeliverStatistics(property_get_bool(PROP_AUDIO_ANALYTICS_CLOUD_ENABLED, true))
    , mStatsdLog(statsdLog)
    , mAudioPowerUsage(this, statsdLog)
{
    SetMinimumLogSeverity(android::base::DEBUG); // for LOG().
    ALOGD("%s", __func__);

    // Add action to save AnalyticsState if audioserver is restarted.
    // This triggers on AudioFlinger or AudioPolicy ctors and onFirstRef,
    // as well as TimeCheck events.
    mActions.addAction(
        AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mHealth.onAudioServerStart(Health::Module::AUDIOFLINGER, item);
            }));
    mActions.addAction(
        AMEDIAMETRICS_KEY_AUDIO_POLICY "." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mHealth.onAudioServerStart(Health::Module::AUDIOPOLICY, item);
            }));
    mActions.addAction(
        AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_TIMEOUT),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mHealth.onAudioServerTimeout(Health::Module::AUDIOFLINGER, item);
            }));
    mActions.addAction(
        AMEDIAMETRICS_KEY_AUDIO_POLICY "." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_TIMEOUT),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mHealth.onAudioServerTimeout(Health::Module::AUDIOPOLICY, item);
            }));

    // Handle legacy aaudio playback stream statistics
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
                mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
            }));

    // Handle legacy aaudio capture stream statistics
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
                mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
            }));

    // Handle mmap aaudio stream statistics
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
                mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_MMAP);
            }));

    // Handle device use record statistics
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mDeviceUse.endAudioIntervalGroup(item, DeviceUse::RECORD);
            }));

    // Handle device use thread statistics
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mDeviceUse.endAudioIntervalGroup(item, DeviceUse::THREAD);
            }));

    // Handle device use track statistics
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mDeviceUse.endAudioIntervalGroup(item, DeviceUse::TRACK);
            }));


    // Handle device connection statistics

    // We track connections (not disconnections) for the time to connect.
    // TODO: consider BT requests in their A2dp service
    // AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
    // AudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
    // AudioDeviceBroker.postA2dpActiveDeviceChange
    mActions.addAction(
        "audio.device.a2dp.state",
        "connected",
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mDeviceConnection.a2dpConnected(item);
            }));
    // If audio is active, we expect to see a createAudioPatch after the device is connected.
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
        std::string("createAudioPatch"),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mDeviceConnection.createPatch(item);
            }));

    // Called from BT service
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE
        "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent"
        "." AMEDIAMETRICS_PROP_STATE,
        "connected",
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mDeviceConnection.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(item);
            }));

    // Handle power usage
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mAudioPowerUsage.checkTrackRecord(item, true /* isTrack */);
            }));

    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mAudioPowerUsage.checkTrackRecord(item, false /* isTrack */);
            }));

    mActions.addAction(
        AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                // ALOGD("(key=%s) Audioflinger setMode", item->getKey().c_str());
                mAudioPowerUsage.checkMode(item);
            }));

    mActions.addAction(
        AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                // ALOGD("(key=%s) Audioflinger setVoiceVolume", item->getKey().c_str());
                mAudioPowerUsage.checkVoiceVolume(item);
            }));

    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
        std::string("createAudioPatch"),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mAudioPowerUsage.checkCreatePatch(item);
            }));

    // Handle Spatializer - these keys are prefixed by "audio.spatializer."
    mActions.addAction(
        AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER "*." AMEDIAMETRICS_PROP_EVENT,
        std::monostate{}, /* match any event */
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
                mSpatializer.onEvent(item);
            }));

    // Handle MIDI
    mActions.addAction(
        AMEDIAMETRICS_KEY_AUDIO_MIDI "." AMEDIAMETRICS_PROP_EVENT,
        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_DEVICECLOSED),
        std::make_shared<AnalyticsActions::Function>(
            [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
                mMidiLogging.onEvent(item);
            }));
}

AudioAnalytics::~AudioAnalytics()
{
    ALOGD("%s", __func__);
    mTimedAction.quit(); // ensure no deferred access during destructor.
}

status_t AudioAnalytics::submit(
        const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted)
{
    if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE;
    status_t status = mAnalyticsState->submit(item, isTrusted);

    // Status is selectively authenticated.
    processStatus(item);

    if (status != NO_ERROR) return status;  // may not be permitted.

    // Only if the item was successfully submitted (permission)
    // do we check triggered actions.
    processActions(item);
    return NO_ERROR;
}

std::pair<std::string, int32_t> AudioAnalytics::dump(
        int32_t lines, int64_t sinceNs, const char *prefix) const
{
    std::stringstream ss;
    int32_t ll = lines;

    if (ll > 0) {
        auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix);
        ss << s;
        ll -= l;
    }
    if (ll > 0) {
        ss << "Prior audioserver state:\n";
        --ll;
    }
    if (ll > 0) {
        auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix);
        ss << s;
        ll -= l;
    }

    if (ll > 0 && prefix == nullptr) {
        auto [s, l] = mAudioPowerUsage.dump(ll);
        ss << s;
        ll -= l;
    }

    return { ss.str(), lines - ll };
}

void AudioAnalytics::processActions(const std::shared_ptr<const mediametrics::Item>& item)
{
    auto actions = mActions.getActionsForItem(item); // internally locked.
    // Execute actions with no lock held.
    for (const auto& action : actions) {
        (*action)(item);
    }
}

void AudioAnalytics::processStatus(const std::shared_ptr<const mediametrics::Item>& item)
{
    int32_t status;
    if (!item->get(AMEDIAMETRICS_PROP_STATUS, &status)) return;

    // Any record with a status will automatically be added to a heat map.
    // Standard information.
    const auto key = item->getKey();
    const auto uid = item->getUid();

    // from audio.track.10 ->  prefix = audio.track, suffix = 10
    // from audio.track.error -> prefix = audio.track, suffix = error
    const auto [prefixKey, suffixKey] = stringutils::splitPrefixKey(key);

    std::string message;
    item->get(AMEDIAMETRICS_PROP_STATUSMESSAGE, &message); // optional

    int32_t subCode = 0; // not used
    (void)item->get(AMEDIAMETRICS_PROP_STATUSSUBCODE, &subCode); // optional

    std::string eventStr; // optional
    item->get(AMEDIAMETRICS_PROP_EVENT, &eventStr);

    const std::string statusString = extendedStatusToStatusString(status);

    // Add to the heat map - we automatically track every item's status to see
    // the types of errors and the frequency of errors.
    mHeatMap.add(prefixKey, suffixKey, eventStr, statusString, uid, message, subCode);

    // Certain keys/event pairs are sent to statsd.  If we get a match (true) we return early.
    if (reportAudioRecordStatus(item, key, eventStr, statusString, uid, message, subCode)) return;
    if (reportAudioTrackStatus(item, key, eventStr, statusString, uid, message, subCode)) return;
}

bool AudioAnalytics::reportAudioRecordStatus(
        const std::shared_ptr<const mediametrics::Item>& item,
        const std::string& key, const std::string& eventStr,
        const std::string& statusString, uid_t uid, const std::string& message,
        int32_t subCode) const
{
    // Note that the prefixes often end with a '.' so we use startsWith.
    if (!startsWith(key, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD)) return false;
    if (eventStr == AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE) {
        const int atom_status = types::lookup<types::STATUS, int32_t>(statusString);

        // currently we only send create status events.
        const int32_t event = stats::media_metrics::
                MEDIAMETRICS_AUDIO_RECORD_STATUS_REPORTED__EVENT__AUDIO_RECORD_EVENT_CREATE;

        // The following fields should all be present in a create event.
        std::string flagsStr;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ORIGINALFLAGS, &flagsStr),
                "%s: %s missing %s field", __func__,
                AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_ORIGINALFLAGS);
        const auto flags = types::lookup<types::INPUT_FLAG, int32_t>(flagsStr);

        // AMEDIAMETRICS_PROP_SESSIONID omitted from atom

        std::string sourceStr;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_SOURCE, &sourceStr),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_SOURCE);
        const int32_t source = types::lookup<types::SOURCE_TYPE, int32_t>(sourceStr);

        // AMEDIAMETRICS_PROP_SELECTEDDEVICEID omitted from atom

        std::string encodingStr;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ENCODING, &encodingStr),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_ENCODING);
        const auto encoding = types::lookup<types::ENCODING, int32_t>(encodingStr);

        int32_t channelMask = 0;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_CHANNELMASK);
        int32_t frameCount = 0;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_FRAMECOUNT);
        int32_t sampleRate = 0;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_SAMPLERATE);

        const auto [ result, str ] = sendToStatsd(AudioRecordStatusFields,
                CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED)
                , atom_status
                , message.c_str()
                , subCode
                , uid
                , event
                , flags
                , source
                , encoding
                , (int64_t)channelMask
                , frameCount
                , sampleRate
                );
        ALOGV("%s: statsd %s", __func__, str.c_str());
        mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED, str);
        return true;
    }
    return false;
}

bool AudioAnalytics::reportAudioTrackStatus(
        const std::shared_ptr<const mediametrics::Item>& item,
        const std::string& key, const std::string& eventStr,
        const std::string& statusString, uid_t uid, const std::string& message,
        int32_t subCode) const
{
    // Note that the prefixes often end with a '.' so we use startsWith.
    if (!startsWith(key, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)) return false;
    if (eventStr == AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE) {
        const int atom_status = types::lookup<types::STATUS, int32_t>(statusString);

        // currently we only send create status events.
        const int32_t event = stats::media_metrics::
                MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__EVENT__AUDIO_TRACK_EVENT_CREATE;

        // The following fields should all be present in a create event.
        std::string flagsStr;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ORIGINALFLAGS, &flagsStr),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_ORIGINALFLAGS);
        const auto flags = types::lookup<types::OUTPUT_FLAG, int32_t>(flagsStr);

        // AMEDIAMETRICS_PROP_SESSIONID omitted from atom

        std::string contentTypeStr;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_CONTENTTYPE, &contentTypeStr),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_CONTENTTYPE);
        const auto contentType = types::lookup<types::CONTENT_TYPE, int32_t>(contentTypeStr);

        std::string usageStr;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_USAGE, &usageStr),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_USAGE);
        const auto usage = types::lookup<types::USAGE, int32_t>(usageStr);

        // AMEDIAMETRICS_PROP_SELECTEDDEVICEID omitted from atom

        std::string encodingStr;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ENCODING, &encodingStr),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_ENCODING);
        const auto encoding = types::lookup<types::ENCODING, int32_t>(encodingStr);

        int32_t channelMask = 0;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_CHANNELMASK);
        int32_t frameCount = 0;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_FRAMECOUNT);
        int32_t sampleRate = 0;
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate),
                "%s: %s missing %s field",
                __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_SAMPLERATE);
        double speed = 0.f;  // default is 1.f
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &speed),
                "%s: %s missing %s field",
                __func__,
                AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_PLAYBACK_SPEED);
        double pitch = 0.f;  // default is 1.f
        ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &pitch),
                "%s: %s missing %s field",
                __func__,
                AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_PLAYBACK_PITCH);
        const auto [ result, str ] = sendToStatsd(AudioTrackStatusFields,
                CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED)
                , atom_status
                , message.c_str()
                , subCode
                , uid
                , event
                , flags
                , contentType
                , usage
                , encoding
                , (int64_t)channelMask
                , frameCount
                , sampleRate
                , (float)speed
                , (float)pitch
                );
        ALOGV("%s: statsd %s", __func__, str.c_str());
        mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED, str);
        return true;
    }
    return false;
}

// HELPER METHODS

std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const
{
    int32_t threadId_int32{};
    if (mAnalyticsState->timeMachine().get(
            track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) {
        return {};
    }
    return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32);
}

// DeviceUse helper class.
void AudioAnalytics::DeviceUse::endAudioIntervalGroup(
       const std::shared_ptr<const android::mediametrics::Item> &item, ItemType itemType) const {
    const std::string& key = item->getKey();
    const std::string id = key.substr(
            (itemType == THREAD ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD)
            : itemType == TRACK ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
            : sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD))
             - 1);
    // deliver statistics
    int64_t deviceTimeNs = 0;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs);
    std::string encoding;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_ENCODING, &encoding);
    int32_t frameCount = 0;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount);
    int32_t intervalCount = 0;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_INTERVALCOUNT, &intervalCount);
    int32_t sampleRate = 0;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
    std::string flags;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_FLAGS, &flags);

    switch (itemType) {
    case RECORD: {
        std::string inputDevicePairs;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs);

        const auto [ inputDeviceStatsd, inputDevices ] =
                stringutils::parseInputDevicePairs(inputDevicePairs);
        const std::string inputDeviceNames;  // not filled currently.

        std::string callerName;
        const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;

        std::string packageName;
        int64_t versionCode = 0;
        int32_t uid = -1;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
        if (uid != -1) {
            std::tie(packageName, versionCode) =
                    MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
        }

        int32_t selectedDeviceId = 0;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
        std::string source;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_SOURCE, &source);
        // Android S
        std::string logSessionId;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);

        const auto callerNameForStats =
                types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
        const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
        const auto flagsForStats = types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags);
        const auto sourceForStats = types::lookup<types::SOURCE_TYPE, short_enum_type_t>(source);
        // Android S
        const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);

        LOG(LOG_LEVEL) << "key:" << key
              << " id:" << id
              << " inputDevices:" << inputDevices << "(" << inputDeviceStatsd
              << ") inputDeviceNames:" << inputDeviceNames
              << " deviceTimeNs:" << deviceTimeNs
              << " encoding:" << encoding << "(" << encodingForStats
              << ") frameCount:" << frameCount
              << " intervalCount:" << intervalCount
              << " sampleRate:" << sampleRate
              << " flags:" << flags << "(" << flagsForStats
              << ") packageName:" << packageName
              << " selectedDeviceId:" << selectedDeviceId
              << " callerName:" << callerName << "(" << callerNameForStats
              << ") source:" << source << "(" << sourceForStats
              << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
              << ")";
        if (clientCalled  // only log if client app called AudioRecord.
                && mAudioAnalytics.mDeliverStatistics) {
            const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
                    CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
                    , ENUM_EXTRACT(inputDeviceStatsd)
                    , inputDeviceNames.c_str()
                    , deviceTimeNs
                    , ENUM_EXTRACT(encodingForStats)
                    , frameCount
                    , intervalCount
                    , sampleRate
                    , ENUM_EXTRACT(flagsForStats)

                    , packageName.c_str()
                    , selectedDeviceId
                    , ENUM_EXTRACT(callerNameForStats)
                    , ENUM_EXTRACT(sourceForStats)
                    , logSessionIdForStats.c_str()
                    );
            ALOGV("%s: statsd %s", __func__, str.c_str());
            mAudioAnalytics.mStatsdLog->log(
                    stats::media_metrics::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED, str);
        }
    } break;
    case THREAD: {
        std::string type;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_TYPE, &type);
        int32_t underrun = 0; // zero for record types
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);

        const bool isInput = types::isInputThreadType(type);

        // get device information
        std::string devicePairs;
        std::string deviceStatsd;
        std::string devices;
        std::string deviceNames;
        if (isInput) {
            // Note we get the "last" device which is the one associated with group.
            item->get(AMEDIAMETRICS_PROP_PREFIX_LAST AMEDIAMETRICS_PROP_INPUTDEVICES,
                    &devicePairs);
            std::tie(deviceStatsd, devices) = stringutils::parseInputDevicePairs(devicePairs);
        } else {
            // Note we get the "last" device which is the one associated with group.
            item->get(AMEDIAMETRICS_PROP_PREFIX_LAST AMEDIAMETRICS_PROP_OUTPUTDEVICES,
                    &devicePairs);
            std::tie(deviceStatsd, devices) = stringutils::parseOutputDevicePairs(devicePairs);
            deviceNames = mAudioAnalytics.getDeviceNamesFromOutputDevices(devices);
        }

        const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
        const auto flagsForStats =
                (isInput ? types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags)
                        : types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags));
        const auto typeForStats = types::lookup<types::THREAD_TYPE, short_enum_type_t>(type);

         LOG(LOG_LEVEL) << "key:" << key
              << " id:" << id
              << " devices:" << devices << "(" << deviceStatsd
              << ") deviceNames:" << deviceNames
              << " deviceTimeNs:" << deviceTimeNs
              << " encoding:" << encoding << "(" << encodingForStats
              << ") frameCount:" << frameCount
              << " intervalCount:" << intervalCount
              << " sampleRate:" << sampleRate
              << " underrun:" << underrun
              << " flags:" << flags << "(" << flagsForStats
              << ") type:" << type << "(" << typeForStats
              << ")";
        if (mAudioAnalytics.mDeliverStatistics) {
            const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
                CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
                , ENUM_EXTRACT(deviceStatsd)
                , deviceNames.c_str()
                , deviceTimeNs
                , ENUM_EXTRACT(encodingForStats)
                , frameCount
                , intervalCount
                , sampleRate
                , ENUM_EXTRACT(flagsForStats)
                , underrun
                , ENUM_EXTRACT(typeForStats)
            );
            ALOGV("%s: statsd %s", __func__, str.c_str());
            mAudioAnalytics.mStatsdLog->log(
                    stats::media_metrics::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED, str);
        }
    } break;
    case TRACK: {
        std::string outputDevicePairs;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs);

        const auto [ outputDeviceStatsd, outputDevices ] =
                stringutils::parseOutputDevicePairs(outputDevicePairs);
        const std::string outputDeviceNames =
                mAudioAnalytics.getDeviceNamesFromOutputDevices(outputDevices);

        std::string callerName;
        const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;

        std::string contentType;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentType);
        double deviceLatencyMs = 0.;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_DEVICELATENCYMS, &deviceLatencyMs);
        double deviceStartupMs = 0.;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_DEVICESTARTUPMS, &deviceStartupMs);
        double deviceVolume = 0.;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume);
        std::string packageName;
        int64_t versionCode = 0;
        int32_t uid = -1;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
        if (uid != -1) {
            std::tie(packageName, versionCode) =
                    MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
        }
        double playbackPitch = 0.;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &playbackPitch);
        double playbackSpeed = 0.;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &playbackSpeed);
        int32_t selectedDeviceId = 0;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
        std::string streamType;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_STREAMTYPE, &streamType);
        std::string traits;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_TRAITS, &traits);
        int32_t underrun = 0;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
        std::string usage;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_USAGE, &usage);
        // Android S
        std::string logSessionId;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);

        const auto callerNameForStats =
                types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
        const auto contentTypeForStats =
                types::lookup<types::CONTENT_TYPE, short_enum_type_t>(contentType);
        const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
        const auto flagsForStats = types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags);
        const auto streamTypeForStats =
                types::lookup<types::STREAM_TYPE, short_enum_type_t>(streamType);
        const auto traitsForStats =
                 types::lookup<types::TRACK_TRAITS, short_enum_type_t>(traits);
        const auto usageForStats = types::lookup<types::USAGE, short_enum_type_t>(usage);
        // Android S
        const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);

        LOG(LOG_LEVEL) << "key:" << key
              << " id:" << id
              << " outputDevices:" << outputDevices << "(" << outputDeviceStatsd
              << ") outputDeviceNames:" << outputDeviceNames
              << " deviceTimeNs:" << deviceTimeNs
              << " encoding:" << encoding << "(" << encodingForStats
              << ") frameCount:" << frameCount
              << " intervalCount:" << intervalCount
              << " sampleRate:" << sampleRate
              << " underrun:" << underrun
              << " flags:" << flags << "(" << flagsForStats
              << ") callerName:" << callerName << "(" << callerNameForStats
              << ") contentType:" << contentType << "(" << contentTypeForStats
              << ") deviceLatencyMs:" << deviceLatencyMs
              << " deviceStartupMs:" << deviceStartupMs
              << " deviceVolume:" << deviceVolume
              << " packageName:" << packageName
              << " playbackPitch:" << playbackPitch
              << " playbackSpeed:" << playbackSpeed
              << " selectedDeviceId:" << selectedDeviceId
              << " streamType:" << streamType << "(" << streamTypeForStats
              << ") traits:" << traits << "(" << traitsForStats
              << ") usage:" << usage << "(" << usageForStats
              << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
              << ")";
        if (clientCalled // only log if client app called AudioTracks
                && mAudioAnalytics.mDeliverStatistics) {
            const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
                    CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
                    , ENUM_EXTRACT(outputDeviceStatsd)
                    , outputDeviceNames.c_str()
                    , deviceTimeNs
                    , ENUM_EXTRACT(encodingForStats)
                    , frameCount
                    , intervalCount
                    , sampleRate
                    , ENUM_EXTRACT(flagsForStats)
                    , underrun
                    , packageName.c_str()
                    , (float)deviceLatencyMs
                    , (float)deviceStartupMs
                    , (float)deviceVolume
                    , selectedDeviceId
                    , ENUM_EXTRACT(streamTypeForStats)
                    , ENUM_EXTRACT(usageForStats)
                    , ENUM_EXTRACT(contentTypeForStats)
                    , ENUM_EXTRACT(callerNameForStats)
                    , ENUM_EXTRACT(traitsForStats)
                    , logSessionIdForStats.c_str()
                    );
            ALOGV("%s: statsd %s", __func__, str.c_str());
            mAudioAnalytics.mStatsdLog->log(
                    stats::media_metrics::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED, str);
        }
        } break;
    }
}

// DeviceConnection helper class.
void AudioAnalytics::DeviceConnection::a2dpConnected(
       const std::shared_ptr<const android::mediametrics::Item> &item) {
    const std::string& key = item->getKey();
    const int64_t atNs = item->getTimestamp();
    {
        std::lock_guard l(mLock);
        mA2dpConnectionServiceNs = atNs;
        ++mA2dpConnectionServices;

        if (mA2dpConnectionRequestNs == 0) {
            mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
        }
        // This sets the time we were connected.  Now we look for the delta in the future.
    }
    std::string name;
    item->get(AMEDIAMETRICS_PROP_NAME, &name);
    ALOGD("(key=%s) a2dp connected device:%s atNs:%lld",
            key.c_str(), name.c_str(), (long long)atNs);
}

void AudioAnalytics::DeviceConnection::createPatch(
       const std::shared_ptr<const android::mediametrics::Item> &item) {
    std::lock_guard l(mLock);
    if (mA2dpConnectionServiceNs == 0) return; // patch unrelated to us.
    const std::string& key = item->getKey();
    std::string outputDevices;
    item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices);
    if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP") != std::string::npos) {
        // TODO compare address
        int64_t timeDiffNs = item->getTimestamp();
        if (mA2dpConnectionRequestNs == 0) {
            ALOGD("%s: A2DP create patch didn't see a connection request", __func__);
            timeDiffNs -= mA2dpConnectionServiceNs;
        } else {
            timeDiffNs -= mA2dpConnectionRequestNs;
        }

        mA2dpConnectionRequestNs = 0;
        mA2dpConnectionServiceNs = 0;
        ++mA2dpConnectionSuccesses;

        const auto connectionTimeMs = float((double)timeDiffNs * 1e-6);

        const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
                "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");

        LOG(LOG_LEVEL) << "key:" << key
                << " A2DP SUCCESS"
                << " outputDevices:" << outputDeviceBits
                << " deviceName:" << mA2dpDeviceName
                << " connectionTimeMs:" <<  connectionTimeMs;
        if (mAudioAnalytics.mDeliverStatistics) {
            const long_enum_type_t inputDeviceBits{};

            const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
                    CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
                    , ENUM_EXTRACT(inputDeviceBits)
                    , ENUM_EXTRACT(outputDeviceBits)
                    , mA2dpDeviceName.c_str()
                    , types::DEVICE_CONNECTION_RESULT_SUCCESS
                    , connectionTimeMs
                    , /* connection_count */ 1
                    );
            ALOGV("%s: statsd %s", __func__, str.c_str());
            mAudioAnalytics.mStatsdLog->log(
                    stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
        }
    }
}

// Called through AudioManager when the BT service wants to enable
void AudioAnalytics::DeviceConnection::postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
        const std::shared_ptr<const android::mediametrics::Item> &item) {
    const int64_t atNs = item->getTimestamp();
    const std::string& key = item->getKey();
    std::string state;
    item->get(AMEDIAMETRICS_PROP_STATE, &state);
    if (state != "connected") return;

    std::string name;
    item->get(AMEDIAMETRICS_PROP_NAME, &name);
    {
        std::lock_guard l(mLock);
        mA2dpConnectionRequestNs = atNs;
        ++mA2dpConnectionRequests;
        mA2dpDeviceName = SUPPRESSED; // TODO(b/161554630) sanitize name
    }
    ALOGD("(key=%s) a2dp connection name:%s request atNs:%lld",
            key.c_str(), name.c_str(), (long long)atNs);
    // TODO: attempt to cancel a timed event, rather than let it expire.
    mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
}

void AudioAnalytics::DeviceConnection::expire() {
    std::lock_guard l(mLock);
    if (mA2dpConnectionRequestNs == 0) return; // ignore (this was an internal connection).

    const long_enum_type_t inputDeviceBits{};
    const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
            "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");

    if (mA2dpConnectionServiceNs == 0) {
        ++mA2dpConnectionJavaServiceCancels;  // service did not connect to A2DP

        LOG(LOG_LEVEL) << "A2DP CANCEL"
                << " outputDevices:" << outputDeviceBits
                << " deviceName:" << mA2dpDeviceName;
        if (mAudioAnalytics.mDeliverStatistics) {
            const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
                    CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
                    , ENUM_EXTRACT(inputDeviceBits)
                    , ENUM_EXTRACT(outputDeviceBits)
                    , mA2dpDeviceName.c_str()
                    , types::DEVICE_CONNECTION_RESULT_JAVA_SERVICE_CANCEL
                    , /* connection_time_ms */ 0.f
                    , /* connection_count */ 1
                    );
            ALOGV("%s: statsd %s", __func__, str.c_str());
            mAudioAnalytics.mStatsdLog->log(
                    stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
        }
        return;
    }

    // AudioFlinger didn't play - an expiration may occur because there is no audio playing.
    // Should we check elsewhere?
    // TODO: disambiguate this case.
    mA2dpConnectionRequestNs = 0;
    mA2dpConnectionServiceNs = 0;
    ++mA2dpConnectionUnknowns;  // connection result unknown

    LOG(LOG_LEVEL) << "A2DP UNKNOWN"
            << " outputDevices:" << outputDeviceBits
            << " deviceName:" << mA2dpDeviceName;
    if (mAudioAnalytics.mDeliverStatistics) {
        const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
                CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
                , ENUM_EXTRACT(inputDeviceBits)
                , ENUM_EXTRACT(outputDeviceBits)
                , mA2dpDeviceName.c_str()
                , types::DEVICE_CONNECTION_RESULT_UNKNOWN
                , /* connection_time_ms */ 0.f
                , /* connection_count */ 1
                );
        ALOGV("%s: statsd %s", __func__, str.c_str());
        mAudioAnalytics.mStatsdLog->log(
                stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
    }
}

void AudioAnalytics::AAudioStreamInfo::endAAudioStream(
        const std::shared_ptr<const android::mediametrics::Item> &item, CallerPath path) const {
    const std::string& key = item->getKey();

    std::string directionStr;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_DIRECTION, &directionStr);
    const auto direction = types::lookup<types::AAUDIO_DIRECTION, int32_t>(directionStr);

    int32_t framesPerBurst = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_BURSTFRAMES, &framesPerBurst);

    int32_t bufferSizeInFrames = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, &bufferSizeInFrames);

    int32_t bufferCapacityInFrames = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, &bufferCapacityInFrames);

    int32_t channelCount = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount);
    if (channelCount == -1) {
        // Try to get channel count from channel mask. From the legacy path,
        // only channel mask are logged.
        int32_t channelMask = 0;
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
                key, AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask);
        if (channelMask != 0) {
            switch (direction) {
                case 1: // Output, keep sync with AudioTypes#getAAudioDirection()
                    channelCount = (int32_t)audio_channel_count_from_out_mask(channelMask);
                    break;
                case 2: // Input, keep sync with AudioTypes#getAAudioDirection()
                    channelCount = (int32_t)audio_channel_count_from_in_mask(channelMask);
                    break;
                default:
                    ALOGW("Invalid direction %d", direction);
            }
        }
    }

    int64_t totalFramesTransferred = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_FRAMESTRANSFERRED, &totalFramesTransferred);

    std::string perfModeRequestedStr;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_PERFORMANCEMODE, &perfModeRequestedStr);
    const auto perfModeRequested =
            types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr);

    std::string perfModeActualStr;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL, &perfModeActualStr);
    const auto perfModeActual =
            types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeActualStr);

    std::string sharingModeActualStr;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_SHARINGMODEACTUAL, &sharingModeActualStr);
    const auto sharingModeActual =
            types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeActualStr);

    int32_t xrunCount = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_UNDERRUN, &xrunCount);

    std::string serializedDeviceTypes;
    // TODO: only routed device id is logged, but no device type

    std::string formatAppStr;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_ENCODINGCLIENT, &formatAppStr);
    const auto formatApp = types::lookup<types::ENCODING, int32_t>(formatAppStr);

    std::string formatDeviceStr;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_ENCODING, &formatDeviceStr);
    const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr);

    std::string logSessionId;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);

    int32_t sampleRate = 0;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);

    std::string contentTypeStr;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentTypeStr);
    const auto contentType = types::lookup<types::CONTENT_TYPE, int32_t>(contentTypeStr);

    std::string sharingModeRequestedStr;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeRequestedStr);
    const auto sharingModeRequested =
            types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeRequestedStr);

    std::string formatHardwareStr;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_ENCODINGHARDWARE, &formatHardwareStr);
    const auto formatHardware = types::lookup<types::ENCODING, int32_t>(formatHardwareStr);

    int32_t channelCountHardware = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_CHANNELCOUNTHARDWARE, &channelCountHardware);

    int32_t sampleRateHardware = 0;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_SAMPLERATEHARDWARE, &sampleRateHardware);

    const auto uid = item->getUid();

    int32_t sampleRateClient = 0;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_SAMPLERATECLIENT, &sampleRateClient);

    LOG(LOG_LEVEL) << "key:" << key
            << " path:" << path
            << " direction:" << direction << "(" << directionStr << ")"
            << " frames_per_burst:" << framesPerBurst
            << " buffer_size:" << bufferSizeInFrames
            << " buffer_capacity:" << bufferCapacityInFrames
            << " channel_count:" << channelCount
            << " total_frames_transferred:" << totalFramesTransferred
            << " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
            << " perf_mode_actual:" << perfModeActual << "(" << perfModeActualStr << ")"
            << " sharing:" << sharingModeActual << "(" << sharingModeActualStr << ")"
            << " xrun_count:" << xrunCount
            << " device_type:" << serializedDeviceTypes
            << " format_app:" << formatApp << "(" << formatAppStr << ")"
            << " format_device: " << formatDevice << "(" << formatDeviceStr << ")"
            << " log_session_id: " << logSessionId
            << " sample_rate: " << sampleRate
            << " content_type: " << contentType << "(" << contentTypeStr << ")"
            << " sharing_requested:" << sharingModeRequested
                    << "(" << sharingModeRequestedStr << ")"
            << " format_hardware:" << formatHardware << "(" << formatHardwareStr << ")"
            << " channel_count_hardware:" << channelCountHardware
            << " sample_rate_hardware: " << sampleRateHardware
            << " uid: " << uid
            << " sample_rate_client: " << sampleRateClient;

    if (mAudioAnalytics.mDeliverStatistics) {
        const stats::media_metrics::BytesField bf_serialized(
            serializedDeviceTypes.c_str(), serializedDeviceTypes.size());
        const auto result = sendToStatsd(
                CONDITION(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
                , path
                , direction
                , framesPerBurst
                , bufferSizeInFrames
                , bufferCapacityInFrames
                , channelCount
                , totalFramesTransferred
                , perfModeRequested
                , perfModeActual
                , sharingModeActual
                , xrunCount
                , bf_serialized
                , formatApp
                , formatDevice
                , logSessionId.c_str()
                , sampleRate
                , contentType
                , sharingModeRequested
                , formatHardware
                , channelCountHardware
                , sampleRateHardware
                , uid
                , sampleRateClient
                );
        std::stringstream ss;
        ss << "result:" << result;
        const auto fieldsStr = printFields(AAudioStreamFields,
                CONDITION(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
                , path
                , direction
                , framesPerBurst
                , bufferSizeInFrames
                , bufferCapacityInFrames
                , channelCount
                , totalFramesTransferred
                , perfModeRequested
                , perfModeActual
                , sharingModeActual
                , xrunCount
                , serializedDeviceTypes.c_str()
                , formatApp
                , formatDevice
                , logSessionId.c_str()
                , sampleRate
                , contentType
                , sharingModeRequested
                , formatHardware
                , channelCountHardware
                , sampleRateHardware
                , uid
                , sampleRateClient
                );
        ss << " " << fieldsStr;
        std::string str = ss.str();
        ALOGV("%s: statsd %s", __func__, str.c_str());
        mAudioAnalytics.mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED, str);
    }
}

// Create new state, typically occurs after an AudioFlinger ctor event.
void AudioAnalytics::newState()
{
    mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>(
            *mAnalyticsState.get()));
    // Note: get returns shared_ptr temp, whose lifetime is extended
    // to end of full expression.
    mAnalyticsState->clear();  // TODO: filter the analytics state.
    // Perhaps report this.

    // Set up a timer to expire the previous audio state to save space.
    // Use the transaction log size as a cookie to see if it is the
    // same as before.  A benign race is possible where a state is cleared early.
    const size_t size = mPreviousAnalyticsState->transactionLog().size();
    mTimedAction.postIn(
            std::chrono::seconds(PREVIOUS_STATE_EXPIRE_SEC), [this, size](){
        if (mPreviousAnalyticsState->transactionLog().size() == size) {
            ALOGD("expiring previous audio state after %d seconds.",
                    PREVIOUS_STATE_EXPIRE_SEC);
            mPreviousAnalyticsState->clear();  // removes data from the state.
        }
    });
}

void AudioAnalytics::Health::onAudioServerStart(Module module,
        const std::shared_ptr<const android::mediametrics::Item> &item)
{
    const auto nowTime = std::chrono::system_clock::now();
    if (module == Module::AUDIOFLINGER) {
       {
            std::lock_guard lg(mLock);
            // reset state on AudioFlinger construction.
            // AudioPolicy is created after AudioFlinger.
            mAudioFlingerCtorTime = nowTime;
            mSimpleLog.log("AudioFlinger ctor");
        }
        mAudioAnalytics.newState();
        return;
    }
    if (module == Module::AUDIOPOLICY) {
        // A start event occurs when audioserver
        //
        // (1) Starts the first time
        // (2) Restarts because of the TimeCheck watchdog
        // (3) Restarts not because of the TimeCheck watchdog.
        int64_t executionTimeNs = 0;
        (void)item->get(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, &executionTimeNs);
        const float loadTimeMs = executionTimeNs * 1e-6f;
        std::lock_guard lg(mLock);
        const int64_t restarts = mStartCount;
        if (mStopCount == mStartCount) {
            mAudioPolicyCtorTime = nowTime;
            ++mStartCount;
            if (mStopCount == 0) {
                // (1) First time initialization.
                ALOGW("%s: (key=%s) AudioPolicy ctor, loadTimeMs:%f",
                        __func__, item->getKey().c_str(), loadTimeMs);
                mSimpleLog.log("AudioPolicy ctor, loadTimeMs:%f", loadTimeMs);
            } else {
                // (2) Previous failure caught due to TimeCheck.  We know how long restart takes.
                const float restartMs =
                        std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(
                                mAudioFlingerCtorTime - mStopTime).count();
                ALOGW("%s: (key=%s) AudioPolicy ctor, "
                        "restarts:%lld restartMs:%f loadTimeMs:%f",
                        __func__, item->getKey().c_str(),
                        (long long)restarts, restartMs, loadTimeMs);
                mSimpleLog.log("AudioPolicy ctor restarts:%lld restartMs:%f loadTimeMs:%f",
                        (long long)restarts, restartMs, loadTimeMs);
            }
        } else {
            // (3) Previous failure is NOT due to TimeCheck, so we don't know the restart time.
            // However we can estimate the uptime from the delta time from previous ctor.
            const float uptimeMs =
                    std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(
                            nowTime - mAudioFlingerCtorTime).count();
            mStopCount = mStartCount;
            mAudioPolicyCtorTime = nowTime;
            ++mStartCount;

            ALOGW("%s: (key=%s) AudioPolicy ctor after uncaught failure, "
                    "mStartCount:%lld mStopCount:%lld uptimeMs:%f loadTimeMs:%f",
                    __func__, item->getKey().c_str(),
                    (long long)mStartCount, (long long)mStopCount, uptimeMs, loadTimeMs);
            mSimpleLog.log("AudioPolicy ctor after uncaught failure, "
                    "restarts:%lld uptimeMs:%f loadTimeMs:%f",
                    (long long)restarts, uptimeMs, loadTimeMs);
        }
    }
}

void AudioAnalytics::Health::onAudioServerTimeout(Module module,
        const std::shared_ptr<const android::mediametrics::Item> &item)
{
    std::string moduleName = getModuleName(module);
    int64_t methodCode{};
    std::string methodName;
    (void)item->get(AMEDIAMETRICS_PROP_METHODCODE, &methodCode);
    (void)item->get(AMEDIAMETRICS_PROP_METHODNAME, &methodName);

    std::lock_guard lg(mLock);
    if (mStopCount >= mStartCount) {
        ALOGD("%s: (key=%s) %s timeout %s(%lld) "
            "unmatched mStopCount(%lld) >= mStartCount(%lld), ignoring",
            __func__, item->getKey().c_str(), moduleName.c_str(),
            methodName.c_str(), (long long)methodCode,
            (long long)mStopCount, (long long)mStartCount);
        return;
    }

    const int64_t restarts = mStartCount - 1;
    ++mStopCount;
    mStopTime = std::chrono::system_clock::now();
    const float uptimeMs = std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(
            mStopTime - mAudioFlingerCtorTime).count();
    ALOGW("%s: (key=%s) %s timeout %s(%lld) restarts:%lld uptimeMs:%f",
         __func__, item->getKey().c_str(), moduleName.c_str(),
         methodName.c_str(), (long long)methodCode,
         (long long)restarts, uptimeMs);
    mSimpleLog.log("%s timeout %s(%lld) restarts:%lld uptimeMs:%f",
            moduleName.c_str(), methodName.c_str(), (long long)methodCode,
            (long long)restarts, uptimeMs);
}

std::pair<std::string, int32_t> AudioAnalytics::Health::dump(
        int32_t lines, const char *prefix) const
{
    std::lock_guard lg(mLock);
    std::string s = mSimpleLog.dumpToString(prefix == nullptr ? "" : prefix, lines);
    size_t n = std::count(s.begin(), s.end(), '\n');
    return { s, n };
}

// Classifies the setting event for statsd (use generated statsd enums.proto constants).
static int32_t classifySettingEvent(bool isSetAlready, bool withinBoot) {
    if (isSetAlready) {
        return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_NORMAL;
    }
    if (withinBoot) {
        return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_BOOT;
    }
    return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_FIRST;
}

void AudioAnalytics::Spatializer::onEvent(
        const std::shared_ptr<const android::mediametrics::Item> &item)
{
    const auto key = item->getKey();

    if (!startsWith(key, AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER)) return;

    const std::string suffix =
            key.substr(std::size(AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER) - 1);

    std::string eventStr; // optional - find the actual event string.
    (void)item->get(AMEDIAMETRICS_PROP_EVENT, &eventStr);

    const size_t delim = suffix.find('.'); // note could use split.
    if (delim == suffix.npos) {
        // on create with suffix == "0" for the first spatializer effect.

        std::string headTrackingModes;
        (void)item->get(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, &headTrackingModes);

        std::string levels;
        (void)item->get(AMEDIAMETRICS_PROP_LEVELS, &levels);

        std::string modes;
        (void)item->get(AMEDIAMETRICS_PROP_MODES, &modes);

        std::string channelMasks;
        (void)item->get(AMEDIAMETRICS_PROP_CHANNELMASKS, &channelMasks);

        LOG(LOG_LEVEL) << "key:" << key
                << " headTrackingModes:" << headTrackingModes
                << " levels:" << levels
                << " modes:" << modes
                << " channelMasks:" << channelMasks
                ;

        const std::vector<int32_t> headTrackingModesVector =
                types::vectorFromMap(headTrackingModes, types::getHeadTrackingModeMap());
        const std::vector<int32_t> levelsVector =
                types::vectorFromMap(levels, types::getSpatializerLevelMap());
        const std::vector<int32_t> modesVector =
                types::vectorFromMap(modes, types::getSpatializerModeMap());
        const std::vector<int64_t> channelMasksVector =
                types::channelMaskVectorFromString(channelMasks);

        const auto [ result, str ] = sendToStatsd(SpatializerCapabilitiesFields,
                CONDITION(stats::media_metrics::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED)
                , headTrackingModesVector
                , levelsVector
                , modesVector
                , channelMasksVector
                );

        mAudioAnalytics.mStatsdLog->log(
                stats::media_metrics::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED, str);

        std::lock_guard lg(mLock);
        if (mFirstCreateTimeNs == 0) {
            // Only update the create time once to prevent audioserver restart
            // from looking like a boot.
            mFirstCreateTimeNs = item->getTimestamp();
        }
        mSimpleLog.log("%s suffix: %s item: %s",
                __func__, suffix.c_str(), item->toString().c_str());
    } else {
        std::string subtype = suffix.substr(0, delim);
        if (subtype != "device") return; // not a device.

        const std::string deviceType = suffix.substr(std::size("device.") - 1);

        const int32_t deviceTypeStatsd =
                types::lookup<types::AUDIO_DEVICE_INFO_TYPE, int32_t>(deviceType);

        std::string address;
        (void)item->get(AMEDIAMETRICS_PROP_ADDRESS, &address);
        std::string enabled;
        (void)item->get(AMEDIAMETRICS_PROP_ENABLED, &enabled);
        std::string hasHeadTracker;
        (void)item->get(AMEDIAMETRICS_PROP_HASHEADTRACKER, &hasHeadTracker);
        std::string headTrackerEnabled;
        (void)item->get(AMEDIAMETRICS_PROP_HEADTRACKERENABLED, &headTrackerEnabled);

        std::lock_guard lg(mLock);

        // Validate from our cached state

        // Our deviceKey takes the device type and appends the address if any.
        // This distinguishes different wireless devices for the purposes of tracking.
        std::string deviceKey(deviceType);
        deviceKey.append("_").append(address);
        DeviceState& deviceState = mDeviceStateMap[deviceKey];

        // check whether the settings event is within a certain time of spatializer creation.
        const bool withinBoot =
                item->getTimestamp() - mFirstCreateTimeNs < kBootDurationThreshold;

        if (!enabled.empty()) {
            if (enabled != deviceState.enabled) {
                const int32_t settingEventStatsd =
                        classifySettingEvent(!deviceState.enabled.empty(), withinBoot);
                deviceState.enabled = enabled;
                const bool enabledStatsd = enabled == "true";
                const auto [ result, str ] = sendToStatsd(SpatializerDeviceEnabledFields,
                        CONDITION(stats::media_metrics::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED)
                        , deviceTypeStatsd
                        , settingEventStatsd
                        , enabledStatsd
                        );
                mAudioAnalytics.mStatsdLog->log(
                        stats::media_metrics::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED, str);
            }
        }
        if (!hasHeadTracker.empty()) {
            if (hasHeadTracker != deviceState.hasHeadTracker) {
                const int32_t settingEventStatsd =
                        classifySettingEvent(!deviceState.hasHeadTracker.empty(), withinBoot);
                deviceState.hasHeadTracker = hasHeadTracker;
                const bool supportedStatsd = hasHeadTracker == "true";
                const auto [ result, str ] = sendToStatsd(HeadTrackerDeviceSupportedFields,
                        CONDITION(stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED)
                        , deviceTypeStatsd
                        , settingEventStatsd
                        , supportedStatsd
                        );
                mAudioAnalytics.mStatsdLog->log(
                        stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED, str);
            }
        }
        if (!headTrackerEnabled.empty()) {
            if (headTrackerEnabled != deviceState.headTrackerEnabled) {
                const int32_t settingEventStatsd =
                        classifySettingEvent(!deviceState.headTrackerEnabled.empty(), withinBoot);
                deviceState.headTrackerEnabled = headTrackerEnabled;
                const bool enabledStatsd = headTrackerEnabled == "true";
                const auto [ result, str ] = sendToStatsd(HeadTrackerDeviceEnabledFields,
                        CONDITION(stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED)
                        , deviceTypeStatsd
                        , settingEventStatsd
                        , enabledStatsd
                        );
                mAudioAnalytics.mStatsdLog->log(
                        stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED, str);
            }
        }
        mSimpleLog.log("%s deviceKey: %s item: %s",
                __func__, deviceKey.c_str(), item->toString().c_str());
    }
}

std::pair<std::string, int32_t> AudioAnalytics::Spatializer::dump(
        int32_t lines, const char *prefix) const
{
    std::lock_guard lg(mLock);
    std::string s = mSimpleLog.dumpToString(prefix == nullptr ? "" : prefix, lines);
    size_t n = std::count(s.begin(), s.end(), '\n');
    return { s, n };
}

void AudioAnalytics::MidiLogging::onEvent(
        const std::shared_ptr<const android::mediametrics::Item> &item) const {
    const std::string& key = item->getKey();

    const auto uid = item->getUid();

    int32_t deviceId = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_DEVICEID, &deviceId);

    int32_t inputPortCount = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_INPUTPORTCOUNT, &inputPortCount);

    int32_t outputPortCount = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_OUTPUTPORTCOUNT, &outputPortCount);

    int32_t hardwareType = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_HARDWARETYPE, &hardwareType);

    std::string isSharedString;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_ISSHARED, &isSharedString);
    const bool isShared = (isSharedString == "true");

    std::string supportsMidiUmpString;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_SUPPORTSMIDIUMP, &supportsMidiUmpString);
    const bool supportsMidiUmp = (supportsMidiUmpString == "true");

    std::string usingAlsaString;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_USINGALSA, &usingAlsaString);
    const bool usingAlsa = (usingAlsaString == "true");

    int64_t durationNs = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_DURATIONNS, &durationNs);

    int32_t openedCount = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_OPENEDCOUNT, &openedCount);

    int32_t closedCount = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_CLOSEDCOUNT, &closedCount);

    std::string deviceDisconnectedString;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_DEVICEDISCONNECTED, &deviceDisconnectedString);
    const bool deviceDisconnected = (deviceDisconnectedString == "true");

    int32_t totalInputBytes = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_TOTALINPUTBYTES, &totalInputBytes);

    int32_t totalOutputBytes = -1;
    mAudioAnalytics.mAnalyticsState->timeMachine().get(
            key, AMEDIAMETRICS_PROP_TOTALOUTPUTBYTES, &totalOutputBytes);

    LOG(LOG_LEVEL) << "key:" << key
            << " uid:" << uid
            << " id:" << deviceId
            << " input_port_count:" << inputPortCount
            << " output_port_count:" << outputPortCount
            << " device_type:" << hardwareType
            << " is_shared:" << isSharedString
            << " supports_ump:" << supportsMidiUmpString
            << " using_alsa:" << usingAlsaString
            << " duration_opened_ms:" << durationNs
            << " opened_count:" << openedCount
            << " closed_count:" << closedCount
            << " device_disconnected:" << deviceDisconnectedString
            << " total_input_bytes:" << totalInputBytes
            << " total_output_bytes:" << totalOutputBytes;

    if (mAudioAnalytics.mDeliverStatistics) {
        const auto result = sendToStatsd(
                CONDITION(stats::media_metrics::MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED)
                , uid
                , deviceId
                , inputPortCount
                , outputPortCount
                , hardwareType
                , isShared
                , supportsMidiUmp
                , usingAlsa
                , durationNs
                , openedCount
                , closedCount
                , deviceDisconnected
                , totalInputBytes
                , totalOutputBytes);
        std::stringstream ss;
        ss << "result:" << result;
        const auto fieldsStr = printFields(MidiDeviceCloseFields,
                CONDITION(stats::media_metrics::MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED)
                , uid
                , deviceId
                , inputPortCount
                , outputPortCount
                , hardwareType
                , isShared
                , supportsMidiUmp
                , usingAlsa
                , durationNs
                , openedCount
                , closedCount
                , deviceDisconnected
                , totalInputBytes
                , totalOutputBytes);
        ss << " " << fieldsStr;
        std::string str = ss.str();
        ALOGV("%s: statsd %s", __func__, str.c_str());
        mAudioAnalytics.mStatsdLog->log(
                stats::media_metrics::MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED, str);
    }
}

// This method currently suppresses the name.
std::string AudioAnalytics::getDeviceNamesFromOutputDevices(std::string_view devices) const {
    std::string deviceNames;
    if (stringutils::hasBluetoothOutputDevice(devices)) {
        deviceNames = SUPPRESSED;
#if 0   // TODO(b/161554630) sanitize name
        mAudioAnalytics.mAnalyticsState->timeMachine().get(
            "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &deviceNames);
        // Remove | if present
        stringutils::replace(deviceNames, "|", '?');
        if (deviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) {
            deviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate
        }
#endif
    }
    return deviceNames;
}

} // namespace android::mediametrics
