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