/*
 * Copyright (C) 2020 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.
 */

#ifndef ANDROID_AUDIO_TRACKMETRICS_H
#define ANDROID_AUDIO_TRACKMETRICS_H

#include <binder/IActivityManager.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <mutex>

namespace android {

/**
 * TrackMetrics handles the AudioFlinger track metrics.
 *
 * We aggregate metrics for a particular device for proper analysis.
 * This includes power, performance, and usage metrics.
 *
 * This class is thread-safe with a lock for safety.  There is no risk of deadlock
 * as this class only executes external one-way calls in Mediametrics and does not
 * call any other AudioFlinger class.
 *
 * Terminology:
 * An AudioInterval is a contiguous playback segment.
 * An AudioIntervalGroup is a group of continuous playback segments on the same device.
 *
 * We currently deliver metrics based on an AudioIntervalGroup.
 */
class TrackMetrics final {


public:
    TrackMetrics(std::string metricsId, bool isOut, int clientUid)
        : mMetricsId(std::move(metricsId))
        , mIsOut(isOut)
        , mUid(clientUid)
        {}  // we don't log a constructor item, we wait for more info in logConstructor().

    ~TrackMetrics() {
        logEndInterval();
        std::lock_guard l(mLock);
        deliverCumulativeMetrics(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP);
        // we don't log a destructor item here.
    }

    // Called under the following circumstances
    // 1) when we are added to the Thread
    // 2) when we have a createPatch in the Thread.
    void logBeginInterval(const std::string& devices) {
        std::lock_guard l(mLock);
        if (mDevices != devices) {
            deliverCumulativeMetrics(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP);
            mDevices = devices;
            resetIntervalGroupMetrics();
            deliverDeviceMetrics(
                    AMEDIAMETRICS_PROP_EVENT_VALUE_BEGINAUDIOINTERVALGROUP, devices.c_str());
        }
        ++mIntervalCount;
        const auto& mActivityManager = getActivityManager();
        if (mActivityManager) {
            if (mIsOut) {
                mActivityManager->logFgsApiBegin(AUDIO_API,
                    mUid,
                    IPCThreadState::self() -> getCallingPid());
            } else {
                mActivityManager->logFgsApiBegin(MICROPHONE_API,
                    mUid,
                    IPCThreadState::self() -> getCallingPid());
            }
        }
    }

    void logConstructor(pid_t creatorPid, uid_t creatorUid, int32_t internalTrackId,
            const std::string& traits = {},
            audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT) const {
        // Once this item is logged by the server, the client can add properties.
        // no lock required, all local or const variables.
        mediametrics::LogItem item(mMetricsId);
        item.setPid(creatorPid)
            .setUid(creatorUid)
            .set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)creatorUid)
            .set(AMEDIAMETRICS_PROP_EVENT,
                    AMEDIAMETRICS_PROP_PREFIX_SERVER AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
            .set(AMEDIAMETRICS_PROP_INTERNALTRACKID, internalTrackId)
            .set(AMEDIAMETRICS_PROP_TRAITS, traits);
        // log streamType from the service, since client doesn't know chosen streamType.
        if (streamType != AUDIO_STREAM_DEFAULT) {
            item.set(AMEDIAMETRICS_PROP_STREAMTYPE, toString(streamType).c_str());
        }
        item.record();
    }

    // Called when we are removed from the Thread.
    void logEndInterval() {
        std::lock_guard l(mLock);
        if (mLastVolumeChangeTimeNs != 0) {
            logVolume_l(mVolume); // flush out the last volume.
            mLastVolumeChangeTimeNs = 0;
        }
        const auto& mActivityManager = getActivityManager();
        if (mActivityManager) {
            if (mIsOut) {
                mActivityManager->logFgsApiEnd(AUDIO_API,
                    mUid,
                    IPCThreadState::self() -> getCallingPid());
            } else {
                mActivityManager->logFgsApiEnd(MICROPHONE_API,
                    mUid,
                    IPCThreadState::self() -> getCallingPid());
            }
        }
    }

    void logInvalidate() const {
        // no lock required, all local or const variables.
        mediametrics::LogItem(mMetricsId)
            .set(AMEDIAMETRICS_PROP_EVENT,
                 AMEDIAMETRICS_PROP_EVENT_VALUE_INVALIDATE)
            .record();
    }

    void logLatencyAndStartup(double latencyMs, double startupMs) {
        mediametrics::LogItem(mMetricsId)
            .set(AMEDIAMETRICS_PROP_LATENCYMS, latencyMs)
            .set(AMEDIAMETRICS_PROP_STARTUPMS, startupMs)
            .record();
        std::lock_guard l(mLock);
        mDeviceLatencyMs.add(latencyMs);
        mDeviceStartupMs.add(startupMs);
    }

    void updateMinMaxVolume_l(int64_t durationNs, double deviceVolume)
            REQUIRES(mLock) {
        if (deviceVolume > mMaxVolume) {
            mMaxVolume = deviceVolume;
            mMaxVolumeDurationNs = durationNs;
        } else if (deviceVolume == mMaxVolume) {
            mMaxVolumeDurationNs += durationNs;
        }
        if (deviceVolume < mMinVolume) {
            mMinVolume = deviceVolume;
            mMinVolumeDurationNs = durationNs;
        } else if (deviceVolume == mMinVolume) {
            mMinVolumeDurationNs += durationNs;
        }
    }

    // may be called multiple times during an interval
    void logVolume(float volume) {
        std::lock_guard l(mLock);
        logVolume_l(volume);
    }

    // Use absolute numbers returned by AudioTrackShared.
    void logUnderruns(size_t count, size_t frames) {
        std::lock_guard l(mLock);
        mUnderrunCount = count;
        mUnderrunFrames = frames;
        // Consider delivering a message here (also be aware of excessive spam).
    }

private:

    // no lock required - all arguments and constants.
    void deliverDeviceMetrics(const char *eventName, const char *devices) const {
        mediametrics::LogItem(mMetricsId)
            .set(AMEDIAMETRICS_PROP_EVENT, eventName)
            .set(mIsOut ? AMEDIAMETRICS_PROP_OUTPUTDEVICES
                   : AMEDIAMETRICS_PROP_INPUTDEVICES, devices)
           .record();
    }

    void logVolume_l(float volume) REQUIRES(mLock) {
        const int64_t timeNs = systemTime();
        const int64_t durationNs = mLastVolumeChangeTimeNs == 0
                ? 0 : timeNs - mLastVolumeChangeTimeNs;
        if (durationNs > 0) {
            // See West's algorithm for weighted averages
            // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
            mDeviceVolume += (mVolume - mDeviceVolume) * durationNs
                      / (durationNs + mDeviceTimeNs);
            mDeviceTimeNs += durationNs;
            mCumulativeTimeNs += durationNs;
        }
        updateMinMaxVolume_l(durationNs, mVolume); // always update.
        mVolume = volume;
        mLastVolumeChangeTimeNs = timeNs;
    }

    void deliverCumulativeMetrics(const char *eventName) const REQUIRES(mLock) {
        if (mIntervalCount > 0) {
            mediametrics::LogItem item(mMetricsId);
            item.set(AMEDIAMETRICS_PROP_CUMULATIVETIMENS, mCumulativeTimeNs)
                .set(AMEDIAMETRICS_PROP_DEVICETIMENS, mDeviceTimeNs)
                .set(AMEDIAMETRICS_PROP_EVENT, eventName)
                .set(AMEDIAMETRICS_PROP_INTERVALCOUNT, (int32_t)mIntervalCount);
            if (mIsOut) {
                item.set(AMEDIAMETRICS_PROP_DEVICEVOLUME, mDeviceVolume)
                    .set(AMEDIAMETRICS_PROP_DEVICEMAXVOLUMEDURATIONNS, mMaxVolumeDurationNs)
                    .set(AMEDIAMETRICS_PROP_DEVICEMAXVOLUME, mMaxVolume)
                    .set(AMEDIAMETRICS_PROP_DEVICEMINVOLUMEDURATIONNS, mMinVolumeDurationNs)
                    .set(AMEDIAMETRICS_PROP_DEVICEMINVOLUME, mMinVolume);
            }
            if (mDeviceLatencyMs.getN() > 0) {
                item.set(AMEDIAMETRICS_PROP_DEVICELATENCYMS, mDeviceLatencyMs.getMean())
                    .set(AMEDIAMETRICS_PROP_DEVICESTARTUPMS, mDeviceStartupMs.getMean());
            }
            if (mUnderrunCount > 0) {
                item.set(AMEDIAMETRICS_PROP_UNDERRUN,
                        (int32_t)(mUnderrunCount - mUnderrunCountSinceIntervalGroup))
                    .set(AMEDIAMETRICS_PROP_UNDERRUNFRAMES,
                        (int64_t)(mUnderrunFrames - mUnderrunFramesSinceIntervalGroup));
            }
            item.record();
        }
    }

    void resetIntervalGroupMetrics() REQUIRES(mLock) {
        // mDevices is not reset by resetIntervalGroupMetrics.

        mIntervalCount = 0;
        // mCumulativeTimeNs is not reset by resetIntervalGroupMetrics.
        mDeviceTimeNs = 0;

        mVolume = 0.f;
        mDeviceVolume = 0.f;
        mLastVolumeChangeTimeNs = 0;  // last time volume logged, cleared on endInterval
        mMinVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
        mMaxVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
        mMinVolumeDurationNs = 0;
        mMaxVolumeDurationNs = 0;

        mDeviceLatencyMs.reset();
        mDeviceStartupMs.reset();

        mUnderrunCountSinceIntervalGroup = mUnderrunCount;
        mUnderrunFramesSinceIntervalGroup = mUnderrunFrames;
        // do not reset mUnderrunCount - it keeps continuously running for tracks.
    }

    // Meyer's singleton is thread-safe.
    static const sp<IActivityManager>& getActivityManager() {
        static const auto activityManager = []() -> sp<IActivityManager> {
            const sp<IServiceManager> sm(defaultServiceManager());
            if (sm != nullptr) {
                 return interface_cast<IActivityManager>(sm->checkService(String16("activity")));
            }
            return nullptr;
        }();
        return activityManager;
    }

    const std::string mMetricsId;
    const bool        mIsOut;  // if true, than a playback track, otherwise used for record.

    static constexpr int AUDIO_API = 5;
    static constexpr int MICROPHONE_API = 6;
    const int         mUid;

    mutable           std::mutex mLock;

    // Devices in the interval group.
    std::string       mDevices GUARDED_BY(mLock);

    // Number of intervals and playing time
    int32_t           mIntervalCount GUARDED_BY(mLock) = 0;
    int64_t           mCumulativeTimeNs GUARDED_BY(mLock) = 0; // total time.
    int64_t           mDeviceTimeNs GUARDED_BY(mLock) = 0;     // time on device.

    // Average volume
    double            mVolume GUARDED_BY(mLock) = 0.f;       // last set volume.
    double            mDeviceVolume GUARDED_BY(mLock) = 0.f; // running average volume.
    int64_t           mLastVolumeChangeTimeNs GUARDED_BY(mLock) = 0;

    // Min/Max volume
    double            mMinVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
    double            mMaxVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
    int64_t           mMinVolumeDurationNs GUARDED_BY(mLock) = 0;
    int64_t           mMaxVolumeDurationNs GUARDED_BY(mLock) = 0;

    // latency and startup for each interval.
    audio_utils::Statistics<double> mDeviceLatencyMs GUARDED_BY(mLock);
    audio_utils::Statistics<double> mDeviceStartupMs GUARDED_BY(mLock);

    // underrun count and frames
    int64_t           mUnderrunCount GUARDED_BY(mLock) = 0;
    int64_t           mUnderrunFrames GUARDED_BY(mLock) = 0;
    int64_t           mUnderrunCountSinceIntervalGroup GUARDED_BY(mLock) = 0;
    int64_t           mUnderrunFramesSinceIntervalGroup GUARDED_BY(mLock) = 0;
};

} // namespace android

#endif // ANDROID_AUDIO_TRACKMETRICS_H
