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