blob: 9089d6fd9c8f57d9205b81b82708dcd89d4da2be [file] [log] [blame]
Andy Hung06f3aba2019-12-03 16:36:42 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
Andy Hungce9b6632020-04-28 20:15:17 -070019#include <android-base/thread_annotations.h>
Andy Hung0f7ad8c2020-01-03 13:24:34 -080020#include "AnalyticsActions.h"
21#include "AnalyticsState.h"
Joey Poomarin52989982020-03-05 17:40:49 +080022#include "AudioPowerUsage.h"
Andy Hungce9b6632020-04-28 20:15:17 -070023#include "TimedAction.h"
Andy Hung0f7ad8c2020-01-03 13:24:34 -080024#include "Wrap.h"
Andy Hung06f3aba2019-12-03 16:36:42 -080025
26namespace android::mediametrics {
27
28class AudioAnalytics
29{
Joey Poomarin52989982020-03-05 17:40:49 +080030 // AudioAnalytics action / state helper classes
31 friend AudioPowerUsage;
32
Andy Hung06f3aba2019-12-03 16:36:42 -080033public:
34 AudioAnalytics();
35 ~AudioAnalytics();
36
Andy Hung06f3aba2019-12-03 16:36:42 -080037 /**
38 * Returns success if AudioAnalytics recognizes item.
39 *
40 * AudioAnalytics requires the item key to start with "audio.".
41 *
42 * A trusted source can create a new key, an untrusted source
43 * can only modify the key if the uid will match that authorized
44 * on the existing key.
45 *
46 * \param item the item to be submitted.
47 * \param isTrusted whether the transaction comes from a trusted source.
48 * In this case, a trusted source is verified by binder
49 * UID to be a system service by MediaMetrics service.
50 * Do not use true if you haven't really checked!
Andy Hung0f7ad8c2020-01-03 13:24:34 -080051 *
52 * \return NO_ERROR on success,
53 * PERMISSION_DENIED if the item cannot be put into the AnalyticsState,
54 * BAD_VALUE if the item key does not start with "audio.".
Andy Hung06f3aba2019-12-03 16:36:42 -080055 */
Ray Essickf27e9872019-12-07 06:28:46 -080056 status_t submit(const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted);
Andy Hung06f3aba2019-12-03 16:36:42 -080057
58 /**
59 * Returns a pair consisting of the dump string, and the number of lines in the string.
60 *
61 * The number of lines in the returned pair is used as an optimization
62 * for subsequent line limiting.
63 *
64 * The TimeMachine and the TransactionLog are dumped separately under
65 * different locks, so may not be 100% consistent with the last data
66 * delivered.
67 *
68 * \param lines the maximum number of lines in the string returned.
Andy Hung709b91e2020-04-04 14:23:36 -070069 * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
70 * \param prefix the desired key prefix to match (nullptr shows all)
Andy Hung06f3aba2019-12-03 16:36:42 -080071 */
Andy Hung709b91e2020-04-04 14:23:36 -070072 std::pair<std::string, int32_t> dump(
73 int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const;
74
75 void clear() {
76 // underlying state is locked.
77 mPreviousAnalyticsState->clear();
78 mAnalyticsState->clear();
Joey Poomarin52989982020-03-05 17:40:49 +080079
80 // Clear power usage state.
81 mAudioPowerUsage.clear();
Andy Hung709b91e2020-04-04 14:23:36 -070082 }
Andy Hung06f3aba2019-12-03 16:36:42 -080083
84private:
Andy Hung0f7ad8c2020-01-03 13:24:34 -080085
Andy Hungea840382020-05-05 21:50:17 -070086 /*
87 * AudioAnalytics class does not contain a monitor mutex.
88 * Instead, all of its variables are individually locked for access.
89 * Since data and items are generally added only (gc removes it), this is a reasonable
90 * compromise for availability/concurrency versus consistency.
91 *
92 * It is possible for concurrent threads to be reading and writing inside of AudioAnalytics.
93 * Reads based on a prior time (e.g. one second) in the past from the TimeMachine can be
94 * used to achieve better consistency if needed.
95 */
96
Andy Hung0f7ad8c2020-01-03 13:24:34 -080097 /**
98 * Checks for any pending actions for a particular item.
99 *
100 * \param item to check against the current AnalyticsActions.
101 */
102 void checkActions(const std::shared_ptr<const mediametrics::Item>& item);
103
Andy Hungea186fa2020-01-09 18:13:15 -0800104 // HELPER METHODS
105 /**
106 * Return the audio thread associated with an audio track name.
107 * e.g. "audio.track.32" -> "audio.thread.10" if the associated
108 * threadId for the audio track is 10.
109 */
110 std::string getThreadFromTrack(const std::string& track) const;
111
Andy Hungce9b6632020-04-28 20:15:17 -0700112 const bool mDeliverStatistics __unused = true;
113
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800114 // Actions is individually locked
115 AnalyticsActions mActions;
116
117 // AnalyticsState is individually locked, and we use SharedPtrWrap
118 // to allow safe access even if the shared pointer changes underneath.
119
120 SharedPtrWrap<AnalyticsState> mAnalyticsState;
121 SharedPtrWrap<AnalyticsState> mPreviousAnalyticsState;
Andy Hungce9b6632020-04-28 20:15:17 -0700122
123 TimedAction mTimedAction; // locked internally
124
125 // DeviceUse is a nested class which handles audio device usage accounting.
126 // We define this class at the end to ensure prior variables all properly constructed.
127 // TODO: Track / Thread interaction
128 // TODO: Consider statistics aggregation.
129 class DeviceUse {
130 public:
Andy Hungea840382020-05-05 21:50:17 -0700131 enum ItemType {
132 RECORD = 0,
133 THREAD = 1,
134 TRACK = 2,
135 };
136
Andy Hungce9b6632020-04-28 20:15:17 -0700137 explicit DeviceUse(AudioAnalytics &audioAnalytics) : mAudioAnalytics{audioAnalytics} {}
138
139 // Called every time an endAudioIntervalGroup message is received.
140 void endAudioIntervalGroup(
141 const std::shared_ptr<const android::mediametrics::Item> &item,
Andy Hungea840382020-05-05 21:50:17 -0700142 ItemType itemType) const;
143
Andy Hungce9b6632020-04-28 20:15:17 -0700144 private:
145 AudioAnalytics &mAudioAnalytics;
146 } mDeviceUse{*this};
147
148 // DeviceConnected is a nested class which handles audio device connection
149 // We define this class at the end to ensure prior variables all properly constructed.
150 // TODO: Track / Thread interaction
151 // TODO: Consider statistics aggregation.
152 class DeviceConnection {
153 public:
154 explicit DeviceConnection(AudioAnalytics &audioAnalytics)
155 : mAudioAnalytics{audioAnalytics} {}
156
157 // Called every time an endAudioIntervalGroup message is received.
158 void a2dpConnected(
159 const std::shared_ptr<const android::mediametrics::Item> &item);
160
161 // Called when we have an AudioFlinger createPatch
162 void createPatch(
163 const std::shared_ptr<const android::mediametrics::Item> &item);
164
Andy Hungea840382020-05-05 21:50:17 -0700165 // Called through AudioManager when the BT service wants to notify connection
166 void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
167 const std::shared_ptr<const android::mediametrics::Item> &item);
168
Andy Hungce9b6632020-04-28 20:15:17 -0700169 // When the timer expires.
170 void expire();
171
172 private:
173 AudioAnalytics &mAudioAnalytics;
174
175 mutable std::mutex mLock;
Andy Hungea840382020-05-05 21:50:17 -0700176 int64_t mA2dpConnectionRequestNs GUARDED_BY(mLock) = 0; // Time for BT service request.
177 int64_t mA2dpConnectionServiceNs GUARDED_BY(mLock) = 0; // Time audio service agrees.
178
179 int32_t mA2dpConnectionRequests GUARDED_BY(mLock) = 0;
180 int32_t mA2dpConnectionServices GUARDED_BY(mLock) = 0;
181
182 // See the statsd atoms.proto
183 int32_t mA2dpConnectionSuccesses GUARDED_BY(mLock) = 0;
184 int32_t mA2dpConnectionJavaServiceCancels GUARDED_BY(mLock) = 0;
185 int32_t mA2dpConnectionUnknowns GUARDED_BY(mLock) = 0;
Andy Hungce9b6632020-04-28 20:15:17 -0700186 } mDeviceConnection{*this};
Joey Poomarin52989982020-03-05 17:40:49 +0800187
188 AudioPowerUsage mAudioPowerUsage{this};
Andy Hung06f3aba2019-12-03 16:36:42 -0800189};
190
191} // namespace android::mediametrics