1 /*
2 * Copyright 2022 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 #include "metrics_collector.h"
18
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 #include <unistd.h>
22
23 #include <cstdint>
24 #include <vector>
25
26 #include "types/raw_address.h"
27
28 // TODO(b/369381361) Enfore -Wmissing-prototypes
29 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
30
31 using testing::_;
32 using testing::AnyNumber;
33 using testing::AtLeast;
34 using testing::AtMost;
35 using testing::DoAll;
36 using testing::Invoke;
37 using testing::Mock;
38 using testing::MockFunction;
39 using testing::NotNull;
40 using testing::Return;
41 using testing::SaveArg;
42 using testing::SetArgPointee;
43 using testing::Test;
44 using testing::WithArg;
45
46 int log_count = 0;
47 int32_t last_group_size;
48 int32_t last_group_metric_id;
49 int64_t last_connection_duration_nanos;
50 int64_t last_broadcast_duration_nanos;
51 std::vector<int64_t> last_device_connecting_offset_nanos;
52 std::vector<int64_t> last_device_connected_offset_nanos;
53 std::vector<int64_t> last_device_connection_duration_nanos;
54 std::vector<int32_t> last_device_connection_status;
55 std::vector<int32_t> last_device_disconnection_status;
56 std::vector<RawAddress> last_device_address;
57 std::vector<int64_t> last_streaming_offset_nanos;
58 std::vector<int64_t> last_streaming_duration_nanos;
59 std::vector<int32_t> last_streaming_context_type;
60
61 namespace bluetooth {
62 namespace common {
63
LogLeAudioConnectionSessionReported(int32_t group_size,int32_t group_metric_id,int64_t connection_duration_nanos,const std::vector<int64_t> & device_connecting_offset_nanos,const std::vector<int64_t> & device_connected_offset_nanos,const std::vector<int64_t> & device_connection_duration_nanos,const std::vector<int32_t> & device_connection_status,const std::vector<int32_t> & device_disconnection_status,const std::vector<RawAddress> & device_address,const std::vector<int64_t> & streaming_offset_nanos,const std::vector<int64_t> & streaming_duration_nanos,const std::vector<int32_t> & streaming_context_type)64 void LogLeAudioConnectionSessionReported(
65 int32_t group_size, int32_t group_metric_id, int64_t connection_duration_nanos,
66 const std::vector<int64_t>& device_connecting_offset_nanos,
67 const std::vector<int64_t>& device_connected_offset_nanos,
68 const std::vector<int64_t>& device_connection_duration_nanos,
69 const std::vector<int32_t>& device_connection_status,
70 const std::vector<int32_t>& device_disconnection_status,
71 const std::vector<RawAddress>& device_address,
72 const std::vector<int64_t>& streaming_offset_nanos,
73 const std::vector<int64_t>& streaming_duration_nanos,
74 const std::vector<int32_t>& streaming_context_type) {
75 log_count++;
76 last_group_size = group_size;
77 last_group_metric_id = group_metric_id;
78 last_connection_duration_nanos = connection_duration_nanos;
79 last_device_connecting_offset_nanos = device_connecting_offset_nanos;
80 last_device_connected_offset_nanos = device_connected_offset_nanos;
81 last_device_connection_duration_nanos = device_connection_duration_nanos;
82 last_device_connection_status = device_connection_status;
83 last_device_disconnection_status = device_disconnection_status;
84 last_device_address = device_address;
85 last_streaming_offset_nanos = streaming_offset_nanos;
86 last_streaming_duration_nanos = streaming_duration_nanos;
87 last_streaming_context_type = streaming_context_type;
88 }
89
LogLeAudioBroadcastSessionReported(int64_t duration_nanos)90 void LogLeAudioBroadcastSessionReported(int64_t duration_nanos) {
91 last_broadcast_duration_nanos = duration_nanos;
92 }
93
94 } // namespace common
95 } // namespace bluetooth
96
97 namespace bluetooth::le_audio {
98
99 const int32_t group_id1 = 1;
100 const RawAddress device1 = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
101
102 const int32_t group_id2 = 2;
103 const RawAddress device2 = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x67});
104 const RawAddress device3 = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x68});
105
106 class MockMetricsCollector : public MetricsCollector {
107 public:
MockMetricsCollector()108 MockMetricsCollector() {}
109 };
110
111 class MetricsCollectorTest : public Test {
112 protected:
113 std::unique_ptr<MetricsCollector> collector;
114
SetUp()115 void SetUp() override {
116 collector = std::make_unique<MockMetricsCollector>();
117
118 log_count = 0;
119 last_group_size = 0;
120 last_group_metric_id = 0;
121 last_broadcast_duration_nanos = 0;
122 last_connection_duration_nanos = 0;
123 last_device_connecting_offset_nanos = {};
124 last_device_connected_offset_nanos = {};
125 last_device_connection_duration_nanos = {};
126 last_device_connection_status = {};
127 last_device_disconnection_status = {};
128 last_device_address = {};
129 last_streaming_offset_nanos = {};
130 last_streaming_duration_nanos = {};
131 last_streaming_context_type = {};
132 }
133
TearDown()134 void TearDown() override { collector = nullptr; }
135 };
136
TEST_F(MetricsCollectorTest,Initialize)137 TEST_F(MetricsCollectorTest, Initialize) { ASSERT_EQ(log_count, 0); }
138
TEST_F(MetricsCollectorTest,ConnectionFailed)139 TEST_F(MetricsCollectorTest, ConnectionFailed) {
140 collector->OnConnectionStateChanged(group_id1, device1,
141 bluetooth::le_audio::ConnectionState::CONNECTING,
142 ConnectionStatus::UNKNOWN);
143 collector->OnConnectionStateChanged(group_id1, device1,
144 bluetooth::le_audio::ConnectionState::CONNECTED,
145 ConnectionStatus::FAILED);
146
147 ASSERT_EQ(log_count, 1);
148 ASSERT_EQ(last_group_metric_id, group_id1);
149 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 1UL);
150 ASSERT_EQ(last_device_connection_status.size(), 1UL);
151 ASSERT_EQ(last_device_connection_status.back(), ConnectionStatus::FAILED);
152 }
153
TEST_F(MetricsCollectorTest,ConnectingConnectedDisconnected)154 TEST_F(MetricsCollectorTest, ConnectingConnectedDisconnected) {
155 collector->OnConnectionStateChanged(group_id1, device1,
156 bluetooth::le_audio::ConnectionState::CONNECTING,
157 ConnectionStatus::UNKNOWN);
158 collector->OnConnectionStateChanged(group_id1, device1,
159 bluetooth::le_audio::ConnectionState::CONNECTED,
160 ConnectionStatus::SUCCESS);
161 collector->OnConnectionStateChanged(group_id1, device1,
162 bluetooth::le_audio::ConnectionState::DISCONNECTED,
163 ConnectionStatus::SUCCESS);
164
165 ASSERT_EQ(log_count, 1);
166 ASSERT_EQ(last_group_metric_id, group_id1);
167 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 1UL);
168 ASSERT_EQ(last_device_connection_status.size(), 1UL);
169 ASSERT_EQ(last_device_disconnection_status.size(), 1UL);
170 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 1UL);
171 ASSERT_EQ(last_device_connected_offset_nanos.size(), 1UL);
172 ASSERT_EQ(last_device_connection_duration_nanos.size(), 1UL);
173 ASSERT_EQ(last_device_connection_status.back(), ConnectionStatus::SUCCESS);
174 ASSERT_EQ(last_device_disconnection_status.back(), ConnectionStatus::SUCCESS);
175 }
176
TEST_F(MetricsCollectorTest,SingleDeviceTwoConnections)177 TEST_F(MetricsCollectorTest, SingleDeviceTwoConnections) {
178 collector->OnConnectionStateChanged(group_id1, device1,
179 bluetooth::le_audio::ConnectionState::CONNECTING,
180 ConnectionStatus::UNKNOWN);
181 collector->OnConnectionStateChanged(group_id1, device1,
182 bluetooth::le_audio::ConnectionState::CONNECTED,
183 ConnectionStatus::SUCCESS);
184 collector->OnConnectionStateChanged(group_id1, device1,
185 bluetooth::le_audio::ConnectionState::DISCONNECTED,
186 ConnectionStatus::SUCCESS);
187
188 ASSERT_EQ(log_count, 1);
189 ASSERT_EQ(last_group_metric_id, group_id1);
190 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 1UL);
191 ASSERT_EQ(last_device_connection_status.size(), 1UL);
192 ASSERT_EQ(last_device_disconnection_status.size(), 1UL);
193 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 1UL);
194 ASSERT_EQ(last_device_connected_offset_nanos.size(), 1UL);
195 ASSERT_EQ(last_device_connection_duration_nanos.size(), 1UL);
196 ASSERT_EQ(last_device_connection_status.back(), ConnectionStatus::SUCCESS);
197 ASSERT_EQ(last_device_disconnection_status.back(), ConnectionStatus::SUCCESS);
198
199 collector->OnConnectionStateChanged(group_id1, device1,
200 bluetooth::le_audio::ConnectionState::CONNECTING,
201 ConnectionStatus::UNKNOWN);
202 collector->OnConnectionStateChanged(group_id1, device1,
203 bluetooth::le_audio::ConnectionState::CONNECTED,
204 ConnectionStatus::SUCCESS);
205 collector->OnConnectionStateChanged(group_id1, device1,
206 bluetooth::le_audio::ConnectionState::DISCONNECTED,
207 ConnectionStatus::SUCCESS);
208
209 ASSERT_EQ(log_count, 2);
210 ASSERT_EQ(last_group_metric_id, group_id1);
211 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 1UL);
212 ASSERT_EQ(last_device_connection_status.size(), 1UL);
213 ASSERT_EQ(last_device_disconnection_status.size(), 1UL);
214 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 1UL);
215 ASSERT_EQ(last_device_connected_offset_nanos.size(), 1UL);
216 ASSERT_EQ(last_device_connection_duration_nanos.size(), 1UL);
217 ASSERT_EQ(last_device_connection_status.back(), ConnectionStatus::SUCCESS);
218 ASSERT_EQ(last_device_disconnection_status.back(), ConnectionStatus::SUCCESS);
219 }
220
TEST_F(MetricsCollectorTest,StereoGroupBasicTest)221 TEST_F(MetricsCollectorTest, StereoGroupBasicTest) {
222 collector->OnConnectionStateChanged(group_id2, device2,
223 bluetooth::le_audio::ConnectionState::CONNECTING,
224 ConnectionStatus::UNKNOWN);
225 collector->OnConnectionStateChanged(group_id2, device2,
226 bluetooth::le_audio::ConnectionState::CONNECTED,
227 ConnectionStatus::SUCCESS);
228 collector->OnConnectionStateChanged(group_id2, device3,
229 bluetooth::le_audio::ConnectionState::CONNECTED,
230 ConnectionStatus::SUCCESS);
231 collector->OnConnectionStateChanged(group_id2, device3,
232 bluetooth::le_audio::ConnectionState::DISCONNECTED,
233 ConnectionStatus::SUCCESS);
234 collector->OnConnectionStateChanged(group_id2, device2,
235 bluetooth::le_audio::ConnectionState::DISCONNECTED,
236 ConnectionStatus::SUCCESS);
237
238 ASSERT_EQ(log_count, 1);
239 ASSERT_EQ(last_group_metric_id, group_id2);
240 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 2UL);
241 ASSERT_EQ(last_device_connection_status.size(), 2UL);
242 ASSERT_EQ(last_device_disconnection_status.size(), 2UL);
243 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 2UL);
244 ASSERT_EQ(last_device_connected_offset_nanos.size(), 2UL);
245 ASSERT_EQ(last_device_connection_duration_nanos.size(), 2UL);
246 }
247
TEST_F(MetricsCollectorTest,StereoGroupMultiReconnections)248 TEST_F(MetricsCollectorTest, StereoGroupMultiReconnections) {
249 collector->OnConnectionStateChanged(group_id2, device2,
250 bluetooth::le_audio::ConnectionState::CONNECTING,
251 ConnectionStatus::UNKNOWN);
252 collector->OnConnectionStateChanged(group_id2, device2,
253 bluetooth::le_audio::ConnectionState::CONNECTED,
254 ConnectionStatus::SUCCESS);
255 collector->OnConnectionStateChanged(group_id2, device3,
256 bluetooth::le_audio::ConnectionState::CONNECTED,
257 ConnectionStatus::SUCCESS);
258 collector->OnConnectionStateChanged(group_id2, device3,
259 bluetooth::le_audio::ConnectionState::DISCONNECTED,
260 ConnectionStatus::SUCCESS);
261 collector->OnConnectionStateChanged(group_id2, device3,
262 bluetooth::le_audio::ConnectionState::CONNECTED,
263 ConnectionStatus::SUCCESS);
264 collector->OnConnectionStateChanged(group_id2, device3,
265 bluetooth::le_audio::ConnectionState::DISCONNECTED,
266 ConnectionStatus::SUCCESS);
267 collector->OnConnectionStateChanged(group_id2, device2,
268 bluetooth::le_audio::ConnectionState::DISCONNECTED,
269 ConnectionStatus::SUCCESS);
270
271 ASSERT_EQ(log_count, 1);
272 ASSERT_EQ(last_group_metric_id, group_id2);
273 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 3UL);
274 ASSERT_EQ(last_device_connection_status.size(), 3UL);
275 ASSERT_EQ(last_device_disconnection_status.size(), 3UL);
276 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 3UL);
277 ASSERT_EQ(last_device_connected_offset_nanos.size(), 3UL);
278 ASSERT_EQ(last_device_connection_duration_nanos.size(), 3UL);
279 }
280
TEST_F(MetricsCollectorTest,MixGroups)281 TEST_F(MetricsCollectorTest, MixGroups) {
282 collector->OnConnectionStateChanged(group_id1, device1,
283 bluetooth::le_audio::ConnectionState::CONNECTING,
284 ConnectionStatus::UNKNOWN);
285 collector->OnConnectionStateChanged(group_id1, device1,
286 bluetooth::le_audio::ConnectionState::CONNECTED,
287 ConnectionStatus::SUCCESS);
288 collector->OnConnectionStateChanged(group_id2, device2,
289 bluetooth::le_audio::ConnectionState::CONNECTING,
290 ConnectionStatus::UNKNOWN);
291 collector->OnConnectionStateChanged(group_id2, device2,
292 bluetooth::le_audio::ConnectionState::CONNECTED,
293 ConnectionStatus::SUCCESS);
294 collector->OnConnectionStateChanged(group_id2, device3,
295 bluetooth::le_audio::ConnectionState::CONNECTED,
296 ConnectionStatus::SUCCESS);
297 collector->OnConnectionStateChanged(group_id2, device3,
298 bluetooth::le_audio::ConnectionState::DISCONNECTED,
299 ConnectionStatus::SUCCESS);
300 collector->OnConnectionStateChanged(group_id2, device2,
301 bluetooth::le_audio::ConnectionState::DISCONNECTED,
302 ConnectionStatus::SUCCESS);
303
304 ASSERT_EQ(log_count, 1);
305 ASSERT_EQ(last_group_metric_id, group_id2);
306 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 2UL);
307 ASSERT_EQ(last_device_connection_status.size(), 2UL);
308 ASSERT_EQ(last_device_disconnection_status.size(), 2UL);
309 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 2UL);
310 ASSERT_EQ(last_device_connected_offset_nanos.size(), 2UL);
311 ASSERT_EQ(last_device_connection_duration_nanos.size(), 2UL);
312
313 collector->OnConnectionStateChanged(group_id1, device1,
314 bluetooth::le_audio::ConnectionState::DISCONNECTED,
315 ConnectionStatus::SUCCESS);
316
317 ASSERT_EQ(log_count, 2);
318 ASSERT_EQ(last_group_metric_id, group_id1);
319 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 1UL);
320 ASSERT_EQ(last_device_connection_status.size(), 1UL);
321 ASSERT_EQ(last_device_disconnection_status.size(), 1UL);
322 ASSERT_EQ(last_device_connecting_offset_nanos.size(), 1UL);
323 ASSERT_EQ(last_device_connected_offset_nanos.size(), 1UL);
324 ASSERT_EQ(last_device_connection_duration_nanos.size(), 1UL);
325 }
326
TEST_F(MetricsCollectorTest,GroupSizeUpdated)327 TEST_F(MetricsCollectorTest, GroupSizeUpdated) {
328 collector->OnGroupSizeUpdate(group_id2, 1);
329 collector->OnGroupSizeUpdate(group_id1, 2);
330 collector->OnConnectionStateChanged(group_id1, device1,
331 bluetooth::le_audio::ConnectionState::CONNECTING,
332 ConnectionStatus::UNKNOWN);
333 collector->OnConnectionStateChanged(group_id1, device1,
334 bluetooth::le_audio::ConnectionState::CONNECTED,
335 ConnectionStatus::SUCCESS);
336 collector->OnConnectionStateChanged(group_id1, device1,
337 bluetooth::le_audio::ConnectionState::DISCONNECTED,
338 ConnectionStatus::SUCCESS);
339
340 ASSERT_EQ(log_count, 1);
341 ASSERT_EQ(last_group_metric_id, group_id1);
342 ASSERT_EQ(last_group_size, 2);
343 }
344
TEST_F(MetricsCollectorTest,StreamingSessions)345 TEST_F(MetricsCollectorTest, StreamingSessions) {
346 collector->OnConnectionStateChanged(group_id1, device1,
347 bluetooth::le_audio::ConnectionState::CONNECTING,
348 ConnectionStatus::UNKNOWN);
349 collector->OnConnectionStateChanged(group_id1, device1,
350 bluetooth::le_audio::ConnectionState::CONNECTED,
351 ConnectionStatus::SUCCESS);
352 collector->OnStreamStarted(group_id1, bluetooth::le_audio::types::LeAudioContextType::MEDIA);
353 collector->OnStreamEnded(group_id1);
354 collector->OnStreamStarted(group_id1,
355 bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL);
356 collector->OnStreamEnded(group_id1);
357 collector->OnConnectionStateChanged(group_id1, device1,
358 bluetooth::le_audio::ConnectionState::DISCONNECTED,
359 ConnectionStatus::SUCCESS);
360
361 ASSERT_EQ(log_count, 1);
362 ASSERT_EQ(last_group_metric_id, group_id1);
363 ASSERT_EQ(last_streaming_offset_nanos.size(), 2UL);
364 ASSERT_EQ(last_streaming_duration_nanos.size(), 2UL);
365 ASSERT_EQ(last_streaming_context_type.size(), 2UL);
366
367 ASSERT_GT(last_streaming_offset_nanos[0], 0L);
368 ASSERT_GT(last_streaming_offset_nanos[1], 0L);
369 ASSERT_GT(last_streaming_duration_nanos[0], 0L);
370 ASSERT_GT(last_streaming_duration_nanos[1], 0L);
371 ASSERT_EQ(last_streaming_context_type[0], static_cast<int32_t>(LeAudioMetricsContextType::MEDIA));
372 ASSERT_EQ(last_streaming_context_type[1],
373 static_cast<int32_t>(LeAudioMetricsContextType::COMMUNICATION));
374 }
375
TEST_F(MetricsCollectorTest,BroadastSessions)376 TEST_F(MetricsCollectorTest, BroadastSessions) {
377 last_broadcast_duration_nanos = 0;
378 collector->OnBroadcastStateChanged(true);
379 collector->OnBroadcastStateChanged(false);
380 ASSERT_GT(last_broadcast_duration_nanos, 0);
381 last_broadcast_duration_nanos = 0;
382 collector->OnBroadcastStateChanged(true);
383 collector->OnBroadcastStateChanged(false);
384 ASSERT_GT(last_broadcast_duration_nanos, 0);
385 }
386
387 } // namespace bluetooth::le_audio
388