xref: /aosp_15_r20/frameworks/av/services/audioflinger/datapath/TrackMetrics.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #pragma once
18*ec779b8eSAndroid Build Coastguard Worker 
19*ec779b8eSAndroid Build Coastguard Worker #include <binder/IActivityManager.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaMetricsItem.h>
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker #include <mutex>
25*ec779b8eSAndroid Build Coastguard Worker 
26*ec779b8eSAndroid Build Coastguard Worker namespace android {
27*ec779b8eSAndroid Build Coastguard Worker 
28*ec779b8eSAndroid Build Coastguard Worker /**
29*ec779b8eSAndroid Build Coastguard Worker  * TrackMetrics handles the AudioFlinger track metrics.
30*ec779b8eSAndroid Build Coastguard Worker  *
31*ec779b8eSAndroid Build Coastguard Worker  * We aggregate metrics for a particular device for proper analysis.
32*ec779b8eSAndroid Build Coastguard Worker  * This includes power, performance, and usage metrics.
33*ec779b8eSAndroid Build Coastguard Worker  *
34*ec779b8eSAndroid Build Coastguard Worker  * This class is thread-safe with a lock for safety.  There is no risk of deadlock
35*ec779b8eSAndroid Build Coastguard Worker  * as this class only executes external one-way calls in Mediametrics and does not
36*ec779b8eSAndroid Build Coastguard Worker  * call any other AudioFlinger class.
37*ec779b8eSAndroid Build Coastguard Worker  *
38*ec779b8eSAndroid Build Coastguard Worker  * Terminology:
39*ec779b8eSAndroid Build Coastguard Worker  * An AudioInterval is a contiguous playback segment.
40*ec779b8eSAndroid Build Coastguard Worker  * An AudioIntervalGroup is a group of continuous playback segments on the same device.
41*ec779b8eSAndroid Build Coastguard Worker  *
42*ec779b8eSAndroid Build Coastguard Worker  * We currently deliver metrics based on an AudioIntervalGroup.
43*ec779b8eSAndroid Build Coastguard Worker  */
44*ec779b8eSAndroid Build Coastguard Worker class TrackMetrics final {
45*ec779b8eSAndroid Build Coastguard Worker 
46*ec779b8eSAndroid Build Coastguard Worker 
47*ec779b8eSAndroid Build Coastguard Worker public:
TrackMetrics(std::string metricsId,bool isOut,int clientUid)48*ec779b8eSAndroid Build Coastguard Worker     TrackMetrics(std::string metricsId, bool isOut, int clientUid)
49*ec779b8eSAndroid Build Coastguard Worker         : mMetricsId(std::move(metricsId))
50*ec779b8eSAndroid Build Coastguard Worker         , mIsOut(isOut)
51*ec779b8eSAndroid Build Coastguard Worker         , mUid(clientUid)
52*ec779b8eSAndroid Build Coastguard Worker         {}  // we don't log a constructor item, we wait for more info in logConstructor().
53*ec779b8eSAndroid Build Coastguard Worker 
~TrackMetrics()54*ec779b8eSAndroid Build Coastguard Worker     ~TrackMetrics() {
55*ec779b8eSAndroid Build Coastguard Worker         logEndInterval();
56*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard l(mLock);
57*ec779b8eSAndroid Build Coastguard Worker         deliverCumulativeMetrics(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP);
58*ec779b8eSAndroid Build Coastguard Worker         // we don't log a destructor item here.
59*ec779b8eSAndroid Build Coastguard Worker     }
60*ec779b8eSAndroid Build Coastguard Worker 
61*ec779b8eSAndroid Build Coastguard Worker     // Called under the following circumstances
62*ec779b8eSAndroid Build Coastguard Worker     // 1) when we are added to the Thread
63*ec779b8eSAndroid Build Coastguard Worker     // 2) when we have a createPatch in the Thread.
logBeginInterval(const std::string & devices)64*ec779b8eSAndroid Build Coastguard Worker     void logBeginInterval(const std::string& devices) {
65*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard l(mLock);
66*ec779b8eSAndroid Build Coastguard Worker         if (mDevices != devices) {
67*ec779b8eSAndroid Build Coastguard Worker             deliverCumulativeMetrics(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP);
68*ec779b8eSAndroid Build Coastguard Worker             mDevices = devices;
69*ec779b8eSAndroid Build Coastguard Worker             resetIntervalGroupMetrics();
70*ec779b8eSAndroid Build Coastguard Worker             deliverDeviceMetrics(
71*ec779b8eSAndroid Build Coastguard Worker                     AMEDIAMETRICS_PROP_EVENT_VALUE_BEGINAUDIOINTERVALGROUP, devices.c_str());
72*ec779b8eSAndroid Build Coastguard Worker         }
73*ec779b8eSAndroid Build Coastguard Worker         ++mIntervalCount;
74*ec779b8eSAndroid Build Coastguard Worker         const auto& mActivityManager = getActivityManager();
75*ec779b8eSAndroid Build Coastguard Worker         if (mActivityManager) {
76*ec779b8eSAndroid Build Coastguard Worker             if (mIsOut) {
77*ec779b8eSAndroid Build Coastguard Worker                 mActivityManager->logFgsApiBegin(AUDIO_API,
78*ec779b8eSAndroid Build Coastguard Worker                     mUid,
79*ec779b8eSAndroid Build Coastguard Worker                     IPCThreadState::self() -> getCallingPid());
80*ec779b8eSAndroid Build Coastguard Worker             } else {
81*ec779b8eSAndroid Build Coastguard Worker                 mActivityManager->logFgsApiBegin(MICROPHONE_API,
82*ec779b8eSAndroid Build Coastguard Worker                     mUid,
83*ec779b8eSAndroid Build Coastguard Worker                     IPCThreadState::self() -> getCallingPid());
84*ec779b8eSAndroid Build Coastguard Worker             }
85*ec779b8eSAndroid Build Coastguard Worker         }
86*ec779b8eSAndroid Build Coastguard Worker     }
87*ec779b8eSAndroid Build Coastguard Worker 
88*ec779b8eSAndroid Build Coastguard Worker     void logConstructor(pid_t creatorPid, uid_t creatorUid, int32_t internalTrackId,
89*ec779b8eSAndroid Build Coastguard Worker             const std::string& traits = {},
90*ec779b8eSAndroid Build Coastguard Worker             audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT) const {
91*ec779b8eSAndroid Build Coastguard Worker         // Once this item is logged by the server, the client can add properties.
92*ec779b8eSAndroid Build Coastguard Worker         // no lock required, all local or const variables.
93*ec779b8eSAndroid Build Coastguard Worker         mediametrics::LogItem item(mMetricsId);
94*ec779b8eSAndroid Build Coastguard Worker         item.setPid(creatorPid)
95*ec779b8eSAndroid Build Coastguard Worker             .setUid(creatorUid)
96*ec779b8eSAndroid Build Coastguard Worker             .set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)creatorUid)
97*ec779b8eSAndroid Build Coastguard Worker             .set(AMEDIAMETRICS_PROP_EVENT,
98*ec779b8eSAndroid Build Coastguard Worker                     AMEDIAMETRICS_PROP_PREFIX_SERVER AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
99*ec779b8eSAndroid Build Coastguard Worker             .set(AMEDIAMETRICS_PROP_INTERNALTRACKID, internalTrackId)
100*ec779b8eSAndroid Build Coastguard Worker             .set(AMEDIAMETRICS_PROP_TRAITS, traits);
101*ec779b8eSAndroid Build Coastguard Worker         // log streamType from the service, since client doesn't know chosen streamType.
102*ec779b8eSAndroid Build Coastguard Worker         if (streamType != AUDIO_STREAM_DEFAULT) {
103*ec779b8eSAndroid Build Coastguard Worker             item.set(AMEDIAMETRICS_PROP_STREAMTYPE, toString(streamType).c_str());
104*ec779b8eSAndroid Build Coastguard Worker         }
105*ec779b8eSAndroid Build Coastguard Worker         item.record();
106*ec779b8eSAndroid Build Coastguard Worker     }
107*ec779b8eSAndroid Build Coastguard Worker 
108*ec779b8eSAndroid Build Coastguard Worker     // Called when we are removed from the Thread.
logEndInterval()109*ec779b8eSAndroid Build Coastguard Worker     void logEndInterval() {
110*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard l(mLock);
111*ec779b8eSAndroid Build Coastguard Worker         if (mLastVolumeChangeTimeNs != 0) {
112*ec779b8eSAndroid Build Coastguard Worker             logVolume_l(mVolume); // flush out the last volume.
113*ec779b8eSAndroid Build Coastguard Worker             mLastVolumeChangeTimeNs = 0;
114*ec779b8eSAndroid Build Coastguard Worker         }
115*ec779b8eSAndroid Build Coastguard Worker         const auto& mActivityManager = getActivityManager();
116*ec779b8eSAndroid Build Coastguard Worker         if (mActivityManager) {
117*ec779b8eSAndroid Build Coastguard Worker             if (mIsOut) {
118*ec779b8eSAndroid Build Coastguard Worker                 mActivityManager->logFgsApiEnd(AUDIO_API,
119*ec779b8eSAndroid Build Coastguard Worker                     mUid,
120*ec779b8eSAndroid Build Coastguard Worker                     IPCThreadState::self() -> getCallingPid());
121*ec779b8eSAndroid Build Coastguard Worker             } else {
122*ec779b8eSAndroid Build Coastguard Worker                 mActivityManager->logFgsApiEnd(MICROPHONE_API,
123*ec779b8eSAndroid Build Coastguard Worker                     mUid,
124*ec779b8eSAndroid Build Coastguard Worker                     IPCThreadState::self() -> getCallingPid());
125*ec779b8eSAndroid Build Coastguard Worker             }
126*ec779b8eSAndroid Build Coastguard Worker         }
127*ec779b8eSAndroid Build Coastguard Worker     }
128*ec779b8eSAndroid Build Coastguard Worker 
logInvalidate()129*ec779b8eSAndroid Build Coastguard Worker     void logInvalidate() const {
130*ec779b8eSAndroid Build Coastguard Worker         // no lock required, all local or const variables.
131*ec779b8eSAndroid Build Coastguard Worker         mediametrics::LogItem(mMetricsId)
132*ec779b8eSAndroid Build Coastguard Worker             .set(AMEDIAMETRICS_PROP_EVENT,
133*ec779b8eSAndroid Build Coastguard Worker                  AMEDIAMETRICS_PROP_EVENT_VALUE_INVALIDATE)
134*ec779b8eSAndroid Build Coastguard Worker             .record();
135*ec779b8eSAndroid Build Coastguard Worker     }
136*ec779b8eSAndroid Build Coastguard Worker 
logLatencyAndStartup(double latencyMs,double startupMs)137*ec779b8eSAndroid Build Coastguard Worker     void logLatencyAndStartup(double latencyMs, double startupMs) {
138*ec779b8eSAndroid Build Coastguard Worker         mediametrics::LogItem(mMetricsId)
139*ec779b8eSAndroid Build Coastguard Worker             .set(AMEDIAMETRICS_PROP_LATENCYMS, latencyMs)
140*ec779b8eSAndroid Build Coastguard Worker             .set(AMEDIAMETRICS_PROP_STARTUPMS, startupMs)
141*ec779b8eSAndroid Build Coastguard Worker             .record();
142*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard l(mLock);
143*ec779b8eSAndroid Build Coastguard Worker         mDeviceLatencyMs.add(latencyMs);
144*ec779b8eSAndroid Build Coastguard Worker         mDeviceStartupMs.add(startupMs);
145*ec779b8eSAndroid Build Coastguard Worker     }
146*ec779b8eSAndroid Build Coastguard Worker 
updateMinMaxVolume_l(int64_t durationNs,double deviceVolume)147*ec779b8eSAndroid Build Coastguard Worker     void updateMinMaxVolume_l(int64_t durationNs, double deviceVolume)
148*ec779b8eSAndroid Build Coastguard Worker             REQUIRES(mLock) {
149*ec779b8eSAndroid Build Coastguard Worker         if (deviceVolume > mMaxVolume) {
150*ec779b8eSAndroid Build Coastguard Worker             mMaxVolume = deviceVolume;
151*ec779b8eSAndroid Build Coastguard Worker             mMaxVolumeDurationNs = durationNs;
152*ec779b8eSAndroid Build Coastguard Worker         } else if (deviceVolume == mMaxVolume) {
153*ec779b8eSAndroid Build Coastguard Worker             mMaxVolumeDurationNs += durationNs;
154*ec779b8eSAndroid Build Coastguard Worker         }
155*ec779b8eSAndroid Build Coastguard Worker         if (deviceVolume < mMinVolume) {
156*ec779b8eSAndroid Build Coastguard Worker             mMinVolume = deviceVolume;
157*ec779b8eSAndroid Build Coastguard Worker             mMinVolumeDurationNs = durationNs;
158*ec779b8eSAndroid Build Coastguard Worker         } else if (deviceVolume == mMinVolume) {
159*ec779b8eSAndroid Build Coastguard Worker             mMinVolumeDurationNs += durationNs;
160*ec779b8eSAndroid Build Coastguard Worker         }
161*ec779b8eSAndroid Build Coastguard Worker     }
162*ec779b8eSAndroid Build Coastguard Worker 
163*ec779b8eSAndroid Build Coastguard Worker     // may be called multiple times during an interval
logVolume(float volume)164*ec779b8eSAndroid Build Coastguard Worker     void logVolume(float volume) {
165*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard l(mLock);
166*ec779b8eSAndroid Build Coastguard Worker         logVolume_l(volume);
167*ec779b8eSAndroid Build Coastguard Worker     }
168*ec779b8eSAndroid Build Coastguard Worker 
169*ec779b8eSAndroid Build Coastguard Worker     // Use absolute numbers returned by AudioTrackShared.
logUnderruns(size_t count,size_t frames)170*ec779b8eSAndroid Build Coastguard Worker     void logUnderruns(size_t count, size_t frames) {
171*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard l(mLock);
172*ec779b8eSAndroid Build Coastguard Worker         mUnderrunCount = count;
173*ec779b8eSAndroid Build Coastguard Worker         mUnderrunFrames = frames;
174*ec779b8eSAndroid Build Coastguard Worker         // Consider delivering a message here (also be aware of excessive spam).
175*ec779b8eSAndroid Build Coastguard Worker     }
176*ec779b8eSAndroid Build Coastguard Worker 
177*ec779b8eSAndroid Build Coastguard Worker private:
178*ec779b8eSAndroid Build Coastguard Worker 
179*ec779b8eSAndroid Build Coastguard Worker     // no lock required - all arguments and constants.
deliverDeviceMetrics(const char * eventName,const char * devices)180*ec779b8eSAndroid Build Coastguard Worker     void deliverDeviceMetrics(const char *eventName, const char *devices) const {
181*ec779b8eSAndroid Build Coastguard Worker         mediametrics::LogItem(mMetricsId)
182*ec779b8eSAndroid Build Coastguard Worker             .set(AMEDIAMETRICS_PROP_EVENT, eventName)
183*ec779b8eSAndroid Build Coastguard Worker             .set(mIsOut ? AMEDIAMETRICS_PROP_OUTPUTDEVICES
184*ec779b8eSAndroid Build Coastguard Worker                    : AMEDIAMETRICS_PROP_INPUTDEVICES, devices)
185*ec779b8eSAndroid Build Coastguard Worker            .record();
186*ec779b8eSAndroid Build Coastguard Worker     }
187*ec779b8eSAndroid Build Coastguard Worker 
logVolume_l(float volume)188*ec779b8eSAndroid Build Coastguard Worker     void logVolume_l(float volume) REQUIRES(mLock) {
189*ec779b8eSAndroid Build Coastguard Worker         const int64_t timeNs = systemTime();
190*ec779b8eSAndroid Build Coastguard Worker         const int64_t durationNs = mLastVolumeChangeTimeNs == 0
191*ec779b8eSAndroid Build Coastguard Worker                 ? 0 : timeNs - mLastVolumeChangeTimeNs;
192*ec779b8eSAndroid Build Coastguard Worker         if (durationNs > 0) {
193*ec779b8eSAndroid Build Coastguard Worker             // See West's algorithm for weighted averages
194*ec779b8eSAndroid Build Coastguard Worker             // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
195*ec779b8eSAndroid Build Coastguard Worker             mDeviceVolume += (mVolume - mDeviceVolume) * durationNs
196*ec779b8eSAndroid Build Coastguard Worker                       / (durationNs + mDeviceTimeNs);
197*ec779b8eSAndroid Build Coastguard Worker             mDeviceTimeNs += durationNs;
198*ec779b8eSAndroid Build Coastguard Worker             mCumulativeTimeNs += durationNs;
199*ec779b8eSAndroid Build Coastguard Worker         }
200*ec779b8eSAndroid Build Coastguard Worker         updateMinMaxVolume_l(durationNs, mVolume); // always update.
201*ec779b8eSAndroid Build Coastguard Worker         mVolume = volume;
202*ec779b8eSAndroid Build Coastguard Worker         mLastVolumeChangeTimeNs = timeNs;
203*ec779b8eSAndroid Build Coastguard Worker     }
204*ec779b8eSAndroid Build Coastguard Worker 
deliverCumulativeMetrics(const char * eventName)205*ec779b8eSAndroid Build Coastguard Worker     void deliverCumulativeMetrics(const char *eventName) const REQUIRES(mLock) {
206*ec779b8eSAndroid Build Coastguard Worker         if (mIntervalCount > 0) {
207*ec779b8eSAndroid Build Coastguard Worker             mediametrics::LogItem item(mMetricsId);
208*ec779b8eSAndroid Build Coastguard Worker             item.set(AMEDIAMETRICS_PROP_CUMULATIVETIMENS, mCumulativeTimeNs)
209*ec779b8eSAndroid Build Coastguard Worker                 .set(AMEDIAMETRICS_PROP_DEVICETIMENS, mDeviceTimeNs)
210*ec779b8eSAndroid Build Coastguard Worker                 .set(AMEDIAMETRICS_PROP_EVENT, eventName)
211*ec779b8eSAndroid Build Coastguard Worker                 .set(AMEDIAMETRICS_PROP_INTERVALCOUNT, (int32_t)mIntervalCount);
212*ec779b8eSAndroid Build Coastguard Worker             if (mIsOut) {
213*ec779b8eSAndroid Build Coastguard Worker                 item.set(AMEDIAMETRICS_PROP_DEVICEVOLUME, mDeviceVolume)
214*ec779b8eSAndroid Build Coastguard Worker                     .set(AMEDIAMETRICS_PROP_DEVICEMAXVOLUMEDURATIONNS, mMaxVolumeDurationNs)
215*ec779b8eSAndroid Build Coastguard Worker                     .set(AMEDIAMETRICS_PROP_DEVICEMAXVOLUME, mMaxVolume)
216*ec779b8eSAndroid Build Coastguard Worker                     .set(AMEDIAMETRICS_PROP_DEVICEMINVOLUMEDURATIONNS, mMinVolumeDurationNs)
217*ec779b8eSAndroid Build Coastguard Worker                     .set(AMEDIAMETRICS_PROP_DEVICEMINVOLUME, mMinVolume);
218*ec779b8eSAndroid Build Coastguard Worker             }
219*ec779b8eSAndroid Build Coastguard Worker             if (mDeviceLatencyMs.getN() > 0) {
220*ec779b8eSAndroid Build Coastguard Worker                 item.set(AMEDIAMETRICS_PROP_DEVICELATENCYMS, mDeviceLatencyMs.getMean())
221*ec779b8eSAndroid Build Coastguard Worker                     .set(AMEDIAMETRICS_PROP_DEVICESTARTUPMS, mDeviceStartupMs.getMean());
222*ec779b8eSAndroid Build Coastguard Worker             }
223*ec779b8eSAndroid Build Coastguard Worker             if (mUnderrunCount > 0) {
224*ec779b8eSAndroid Build Coastguard Worker                 item.set(AMEDIAMETRICS_PROP_UNDERRUN,
225*ec779b8eSAndroid Build Coastguard Worker                         (int32_t)(mUnderrunCount - mUnderrunCountSinceIntervalGroup))
226*ec779b8eSAndroid Build Coastguard Worker                     .set(AMEDIAMETRICS_PROP_UNDERRUNFRAMES,
227*ec779b8eSAndroid Build Coastguard Worker                         (int64_t)(mUnderrunFrames - mUnderrunFramesSinceIntervalGroup));
228*ec779b8eSAndroid Build Coastguard Worker             }
229*ec779b8eSAndroid Build Coastguard Worker             item.record();
230*ec779b8eSAndroid Build Coastguard Worker         }
231*ec779b8eSAndroid Build Coastguard Worker     }
232*ec779b8eSAndroid Build Coastguard Worker 
resetIntervalGroupMetrics()233*ec779b8eSAndroid Build Coastguard Worker     void resetIntervalGroupMetrics() REQUIRES(mLock) {
234*ec779b8eSAndroid Build Coastguard Worker         // mDevices is not reset by resetIntervalGroupMetrics.
235*ec779b8eSAndroid Build Coastguard Worker 
236*ec779b8eSAndroid Build Coastguard Worker         mIntervalCount = 0;
237*ec779b8eSAndroid Build Coastguard Worker         // mCumulativeTimeNs is not reset by resetIntervalGroupMetrics.
238*ec779b8eSAndroid Build Coastguard Worker         mDeviceTimeNs = 0;
239*ec779b8eSAndroid Build Coastguard Worker 
240*ec779b8eSAndroid Build Coastguard Worker         mVolume = 0.f;
241*ec779b8eSAndroid Build Coastguard Worker         mDeviceVolume = 0.f;
242*ec779b8eSAndroid Build Coastguard Worker         mLastVolumeChangeTimeNs = 0;  // last time volume logged, cleared on endInterval
243*ec779b8eSAndroid Build Coastguard Worker         mMinVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
244*ec779b8eSAndroid Build Coastguard Worker         mMaxVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
245*ec779b8eSAndroid Build Coastguard Worker         mMinVolumeDurationNs = 0;
246*ec779b8eSAndroid Build Coastguard Worker         mMaxVolumeDurationNs = 0;
247*ec779b8eSAndroid Build Coastguard Worker 
248*ec779b8eSAndroid Build Coastguard Worker         mDeviceLatencyMs.reset();
249*ec779b8eSAndroid Build Coastguard Worker         mDeviceStartupMs.reset();
250*ec779b8eSAndroid Build Coastguard Worker 
251*ec779b8eSAndroid Build Coastguard Worker         mUnderrunCountSinceIntervalGroup = mUnderrunCount;
252*ec779b8eSAndroid Build Coastguard Worker         mUnderrunFramesSinceIntervalGroup = mUnderrunFrames;
253*ec779b8eSAndroid Build Coastguard Worker         // do not reset mUnderrunCount - it keeps continuously running for tracks.
254*ec779b8eSAndroid Build Coastguard Worker     }
255*ec779b8eSAndroid Build Coastguard Worker 
256*ec779b8eSAndroid Build Coastguard Worker     // Meyer's singleton is thread-safe.
getActivityManager()257*ec779b8eSAndroid Build Coastguard Worker     static const sp<IActivityManager>& getActivityManager() {
258*ec779b8eSAndroid Build Coastguard Worker         static const auto activityManager = []() -> sp<IActivityManager> {
259*ec779b8eSAndroid Build Coastguard Worker             const sp<IServiceManager> sm(defaultServiceManager());
260*ec779b8eSAndroid Build Coastguard Worker             if (sm != nullptr) {
261*ec779b8eSAndroid Build Coastguard Worker                  return interface_cast<IActivityManager>(sm->checkService(String16("activity")));
262*ec779b8eSAndroid Build Coastguard Worker             }
263*ec779b8eSAndroid Build Coastguard Worker             return nullptr;
264*ec779b8eSAndroid Build Coastguard Worker         }();
265*ec779b8eSAndroid Build Coastguard Worker         return activityManager;
266*ec779b8eSAndroid Build Coastguard Worker     }
267*ec779b8eSAndroid Build Coastguard Worker 
268*ec779b8eSAndroid Build Coastguard Worker     const std::string mMetricsId;
269*ec779b8eSAndroid Build Coastguard Worker     const bool        mIsOut;  // if true, than a playback track, otherwise used for record.
270*ec779b8eSAndroid Build Coastguard Worker 
271*ec779b8eSAndroid Build Coastguard Worker     static constexpr int AUDIO_API = 5;
272*ec779b8eSAndroid Build Coastguard Worker     static constexpr int MICROPHONE_API = 6;
273*ec779b8eSAndroid Build Coastguard Worker     const int         mUid;
274*ec779b8eSAndroid Build Coastguard Worker 
275*ec779b8eSAndroid Build Coastguard Worker     mutable           std::mutex mLock;
276*ec779b8eSAndroid Build Coastguard Worker 
277*ec779b8eSAndroid Build Coastguard Worker     // Devices in the interval group.
278*ec779b8eSAndroid Build Coastguard Worker     std::string       mDevices GUARDED_BY(mLock);
279*ec779b8eSAndroid Build Coastguard Worker 
280*ec779b8eSAndroid Build Coastguard Worker     // Number of intervals and playing time
281*ec779b8eSAndroid Build Coastguard Worker     int32_t           mIntervalCount GUARDED_BY(mLock) = 0;
282*ec779b8eSAndroid Build Coastguard Worker     int64_t           mCumulativeTimeNs GUARDED_BY(mLock) = 0; // total time.
283*ec779b8eSAndroid Build Coastguard Worker     int64_t           mDeviceTimeNs GUARDED_BY(mLock) = 0;     // time on device.
284*ec779b8eSAndroid Build Coastguard Worker 
285*ec779b8eSAndroid Build Coastguard Worker     // Average volume
286*ec779b8eSAndroid Build Coastguard Worker     double            mVolume GUARDED_BY(mLock) = 0.f;       // last set volume.
287*ec779b8eSAndroid Build Coastguard Worker     double            mDeviceVolume GUARDED_BY(mLock) = 0.f; // running average volume.
288*ec779b8eSAndroid Build Coastguard Worker     int64_t           mLastVolumeChangeTimeNs GUARDED_BY(mLock) = 0;
289*ec779b8eSAndroid Build Coastguard Worker 
290*ec779b8eSAndroid Build Coastguard Worker     // Min/Max volume
291*ec779b8eSAndroid Build Coastguard Worker     double            mMinVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
292*ec779b8eSAndroid Build Coastguard Worker     double            mMaxVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
293*ec779b8eSAndroid Build Coastguard Worker     int64_t           mMinVolumeDurationNs GUARDED_BY(mLock) = 0;
294*ec779b8eSAndroid Build Coastguard Worker     int64_t           mMaxVolumeDurationNs GUARDED_BY(mLock) = 0;
295*ec779b8eSAndroid Build Coastguard Worker 
296*ec779b8eSAndroid Build Coastguard Worker     // latency and startup for each interval.
297*ec779b8eSAndroid Build Coastguard Worker     audio_utils::Statistics<double> mDeviceLatencyMs GUARDED_BY(mLock);
298*ec779b8eSAndroid Build Coastguard Worker     audio_utils::Statistics<double> mDeviceStartupMs GUARDED_BY(mLock);
299*ec779b8eSAndroid Build Coastguard Worker 
300*ec779b8eSAndroid Build Coastguard Worker     // underrun count and frames
301*ec779b8eSAndroid Build Coastguard Worker     int64_t           mUnderrunCount GUARDED_BY(mLock) = 0;
302*ec779b8eSAndroid Build Coastguard Worker     int64_t           mUnderrunFrames GUARDED_BY(mLock) = 0;
303*ec779b8eSAndroid Build Coastguard Worker     int64_t           mUnderrunCountSinceIntervalGroup GUARDED_BY(mLock) = 0;
304*ec779b8eSAndroid Build Coastguard Worker     int64_t           mUnderrunFramesSinceIntervalGroup GUARDED_BY(mLock) = 0;
305*ec779b8eSAndroid Build Coastguard Worker };
306*ec779b8eSAndroid Build Coastguard Worker 
307*ec779b8eSAndroid Build Coastguard Worker } // namespace android
308