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 #pragma once
18 
19 #include <hardware/bt_le_audio.h>
20 
21 #include <chrono>
22 #include <cstdint>
23 #include <memory>
24 #include <unordered_map>
25 
26 #include "le_audio_types.h"
27 #include "types/raw_address.h"
28 
29 namespace bluetooth::le_audio {
30 
31 namespace metrics {
32 using ClockTimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
33 }
34 
35 enum ConnectionStatus : int32_t {
36   UNKNOWN = 0,
37   SUCCESS = 1,
38   FAILED = 2,
39 };
40 
41 /* android.bluetooth.leaudio.ContextType */
42 enum class LeAudioMetricsContextType : int32_t {
43   INVALID = 0,
44   UNSPECIFIED = 1,
45   COMMUNICATION = 2,
46   MEDIA = 3,
47   INSTRUCTIONAL = 4,
48   ATTENTION_SEEKING = 5,
49   IMMEDIATE_ALERT = 6,
50   MAN_MACHINE = 7,
51   EMERGENCY_ALERT = 8,
52   RINGTONE = 9,
53   TV = 10,
54   LIVE = 11,
55   GAME = 12,
56   RFU = 13,
57 };
58 
59 class GroupMetrics {
60 public:
GroupMetrics()61   GroupMetrics() {}
62 
~GroupMetrics()63   virtual ~GroupMetrics() {}
64 
65   virtual void AddStateChangedEvent(const RawAddress& address,
66                                     bluetooth::le_audio::ConnectionState state,
67                                     ConnectionStatus status) = 0;
68 
69   virtual void AddStreamStartedEvent(
70           bluetooth::le_audio::types::LeAudioContextType context_type) = 0;
71 
72   virtual void AddStreamEndedEvent() = 0;
73 
74   virtual void SetGroupSize(int32_t group_size) = 0;
75 
76   virtual bool IsClosed() = 0;
77 
78   virtual void WriteStats() = 0;
79 
80   virtual void Flush() = 0;
81 };
82 
83 class MetricsCollector {
84 public:
85   static MetricsCollector* Get();
86 
87   /**
88    * Update the size of given group which will be used in the
89    * LogMetricBluetoothLeAudioConnectionStateChanged()
90    *
91    * @param group_id ID of target group
92    * @param group_size Size of target group
93    */
94   void OnGroupSizeUpdate(int32_t group_id, int32_t group_size);
95 
96   /**
97    * When there is a change in Bluetooth LE Audio connection state
98    *
99    * @param group_id Group ID of the associated device.
100    * @param address Address of the associated device.
101    * @param state New LE Audio connetion state.
102    * @param status status or reason of the state transition. Ignored at
103    * CONNECTING states.
104    */
105   void OnConnectionStateChanged(int32_t group_id, const RawAddress& address,
106                                 bluetooth::le_audio::ConnectionState state,
107                                 ConnectionStatus status);
108 
109   /**
110    * When there is a change in LE Audio stream started
111    *
112    * @param group_id Group ID of the associated stream.
113    */
114   void OnStreamStarted(int32_t group_id,
115                        bluetooth::le_audio::types::LeAudioContextType context_type);
116 
117   /**
118    * When there is a change in LE Audio stream started
119    *
120    * @param group_id Group ID of the associated stream.
121    */
122   void OnStreamEnded(int32_t group_id);
123 
124   /**
125    * When there is a change in Bluetooth LE Audio broadcast state
126    *
127    * @param started if broadcast streaming is started.
128    */
129   void OnBroadcastStateChanged(bool started);
130 
131   /**
132    * Flush all log to statsd
133    *
134    * @param group_id Group ID of the associated stream.
135    */
136   void Flush();
137 
138 protected:
MetricsCollector()139   MetricsCollector() {}
140 
141 private:
142   static MetricsCollector* instance;
143 
144   std::unordered_map<int32_t, std::unique_ptr<GroupMetrics>> opened_groups_;
145   std::unordered_map<int32_t, int32_t> group_size_table_;
146 
147   metrics::ClockTimePoint broadcast_beginning_timepoint_;
148 };
149 
150 }  // namespace bluetooth::le_audio
151