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