• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2018 The Android Open Source Project
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #pragma once
20 
21 #include <base/callback_forward.h>
22 #include <hardware/bt_hearing_aid.h>
23 #include <deque>
24 #include <future>
25 #include <vector>
26 
27 constexpr uint16_t HEARINGAID_MAX_NUM_UUIDS = 1;
28 
29 constexpr uint16_t HA_INTERVAL_10_MS = 10;
30 constexpr uint16_t HA_INTERVAL_20_MS = 20;
31 
32 // Masks for checking capability support
33 constexpr uint8_t CAPABILITY_SIDE = 0x01;
34 constexpr uint8_t CAPABILITY_BINAURAL = 0x02;
35 constexpr uint8_t CAPABILITY_RESERVED = 0xFC;
36 
37 /** Implementations of HearingAid will also implement this interface */
38 class HearingAidAudioReceiver {
39  public:
40   virtual ~HearingAidAudioReceiver() = default;
41   virtual void OnAudioDataReady(const std::vector<uint8_t>& data) = 0;
42   virtual void OnAudioSuspend(std::promise<void> do_suspend_promise) = 0;
43   virtual void OnAudioResume(std::promise<void> do_resume_promise) = 0;
44 };
45 
46 // Number of rssi reads to attempt when requested
47 constexpr int READ_RSSI_NUM_TRIES = 10;
48 constexpr int PERIOD_TO_READ_RSSI_IN_INTERVALS = 5;
49 // Depth of RSSI History in DumpSys
50 constexpr int MAX_RSSI_HISTORY = 15;
51 
52 struct rssi_log {
53   struct timespec timestamp;
54   std::vector<int8_t> rssi;
55 };
56 
57 struct AudioStats {
58   size_t packet_flush_count;
59   size_t packet_send_count;
60   size_t frame_flush_count;
61   size_t frame_send_count;
62   std::deque<rssi_log> rssi_history;
63 
AudioStatsAudioStats64   AudioStats() { Reset(); }
65 
ResetAudioStats66   void Reset() {
67     packet_flush_count = 0;
68     packet_send_count = 0;
69     frame_flush_count = 0;
70     frame_send_count = 0;
71   }
72 };
73 
74 /** Possible states for the Connection Update status */
75 typedef enum {
76   NONE,      // Not Connected
77   AWAITING,  // Waiting for start the Connection Update operation
78   STARTED,   // Connection Update has started
79   COMPLETED  // Connection Update is completed successfully
80 } connection_update_status_t;
81 
82 struct HearingDevice {
83   RawAddress address;
84   /* This is true only during first connection to profile, until we store the
85    * device */
86   bool first_connection;
87   bool service_changed_rcvd;
88 
89   /* we are making active attempt to connect to this device, 'direct connect'.
90    * This is true only during initial phase of first connection. */
91   bool connecting_actively;
92 
93   /* For two hearing aids, you must update their parameters one after another,
94    * not simulteanously, to ensure start of connection events for both devices
95    * are far from each other. This status tracks whether this device is waiting
96    * for update of parameters, that should happen after "LE Connection Update
97    * Complete" event
98    */
99   connection_update_status_t connection_update_status;
100   uint16_t requested_connection_interval;
101 
102   /* if true, we are connected, L2CAP socket is open, we can stream audio.
103      However, the actual audio stream also depends on whether the
104      Audio Service has resumed.
105    */
106   bool accepting_audio;
107 
108   uint16_t conn_id;
109   uint16_t gap_handle;
110   uint16_t audio_control_point_handle;
111   uint16_t audio_status_handle;
112   uint16_t audio_status_ccc_handle;
113   uint16_t service_changed_ccc_handle;
114   uint16_t volume_handle;
115   uint16_t read_psm_handle;
116 
117   uint8_t capabilities;
118   uint64_t hi_sync_id;
119   uint16_t render_delay;
120   uint16_t preparation_delay;
121   uint16_t codecs;
122 
123   AudioStats audio_stats;
124   /* Keep tracks of whether the "Start Cmd" has been send to this device. When
125      the "Stop Cmd" is send or when this device disconnects, then this flag is
126      cleared. Please note that the "Start Cmd" is not send during device
127      connection in the case when the audio is suspended. */
128   bool playback_started;
129   /* This tracks whether the last command to Hearing Aids device is
130    * ACKnowledged. */
131   bool command_acked;
132 
133   /* When read_rssi_count is > 0, then read the rssi. The interval between rssi
134      reads is tracked by num_intervals_since_last_rssi_read. */
135   int read_rssi_count;
136   int num_intervals_since_last_rssi_read;
137 
HearingDeviceHearingDevice138   HearingDevice(const RawAddress& address, uint8_t capabilities,
139                 uint16_t codecs, uint16_t audio_control_point_handle,
140                 uint16_t audio_status_handle, uint16_t audio_status_ccc_handle,
141                 uint16_t service_changed_ccc_handle, uint16_t volume_handle,
142                 uint16_t read_psm_handle, uint64_t hiSyncId,
143                 uint16_t render_delay, uint16_t preparation_delay)
144       : address(address),
145         first_connection(false),
146         service_changed_rcvd(false),
147         connecting_actively(false),
148         connection_update_status(NONE),
149         accepting_audio(false),
150         conn_id(0),
151         gap_handle(0),
152         audio_control_point_handle(audio_control_point_handle),
153         audio_status_handle(audio_status_handle),
154         audio_status_ccc_handle(audio_status_ccc_handle),
155         service_changed_ccc_handle(service_changed_ccc_handle),
156         volume_handle(volume_handle),
157         read_psm_handle(read_psm_handle),
158         capabilities(capabilities),
159         hi_sync_id(hiSyncId),
160         render_delay(render_delay),
161         preparation_delay(preparation_delay),
162         codecs(codecs),
163         playback_started(false),
164         command_acked(false),
165         read_rssi_count(0) {}
166 
HearingDeviceHearingDevice167   HearingDevice(const RawAddress& address, bool first_connection)
168       : address(address),
169         first_connection(first_connection),
170         service_changed_rcvd(false),
171         connecting_actively(first_connection),
172         connection_update_status(NONE),
173         accepting_audio(false),
174         conn_id(0),
175         gap_handle(0),
176         audio_status_handle(0),
177         audio_status_ccc_handle(0),
178         service_changed_ccc_handle(0),
179         read_psm_handle(0),
180         capabilities(0),
181         hi_sync_id(0),
182         render_delay(0),
183         preparation_delay(0),
184         codecs(0),
185         playback_started(false),
186         command_acked(false),
187         read_rssi_count(0) {}
188 
HearingDeviceHearingDevice189   HearingDevice() : HearingDevice(RawAddress::kEmpty, false) {}
190 
191   /* return true if this device represents left Hearing Aid. Returned value is
192    * valid only after capabilities are discovered */
isLeftHearingDevice193   bool isLeft() const { return !(capabilities & CAPABILITY_SIDE); }
194 };
195 
196 class HearingAid {
197  public:
198   virtual ~HearingAid() = default;
199 
200   static void Initialize(bluetooth::hearing_aid::HearingAidCallbacks* callbacks,
201                          base::Closure initCb);
202   static void CleanUp();
203   static bool IsHearingAidRunning();
204   static HearingAid* Get();
205   static void DebugDump(int fd);
206 
207   static void AddFromStorage(const HearingDevice& dev_info,
208                              uint16_t is_white_listed);
209 
210   static int GetDeviceCount();
211 
212   virtual void Connect(const RawAddress& address) = 0;
213   virtual void Disconnect(const RawAddress& address) = 0;
214   virtual void AddToWhiteList(const RawAddress& address) = 0;
215   virtual void SetVolume(int8_t volume) = 0;
216 };
217 
218 /* Represents configuration of audio codec, as exchanged between hearing aid and
219  * phone.
220  * It can also be passed to the audio source to configure its parameters.
221  */
222 struct CodecConfiguration {
223   /** sampling rate that the codec expects to receive from audio framework */
224   uint32_t sample_rate;
225 
226   /** bitrate that codec expects to receive from audio framework in bits per
227    * channel */
228   uint32_t bit_rate;
229 
230   /** Data interval determines how often we send samples to the remote. This
231    * should match how often we grab data from audio source, optionally we can
232    * grab data every 2 or 3 intervals, but this would increase latency.
233    *
234    * Value is provided in ms, must be divisable by 1.25 to make sure the
235    * connection interval is integer.
236    */
237   uint16_t data_interval_ms;
238 };
239 
240 /** Represents source of audio for hearing aids */
241 class HearingAidAudioSource {
242  public:
243   static void Start(const CodecConfiguration& codecConfiguration,
244                     HearingAidAudioReceiver* audioReceiver,
245                     uint16_t remote_delay_ms);
246   static void Stop();
247   static void Initialize();
248   static void CleanUp();
249   static void DebugDump(int fd);
250 };
251