• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2017 Google, Inc.
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 #define LOG_TAG "btif_a2dp_audio_interface"
20 
21 #include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioHost.h>
22 #include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioOffload.h>
23 #include <android/hardware/bluetooth/a2dp/1.0/types.h>
24 #include <base/bind.h>
25 #include <base/callback.h>
26 #include <base/location.h>
27 #include <hwbinder/ProcessState.h>
28 #include <mutex>
29 
30 #include "audio_a2dp_hw/include/audio_a2dp_hw.h"
31 #include "bta/av/bta_av_int.h"
32 #include "bta/include/bta_av_api.h"
33 #include "btif/include/btif_a2dp_source.h"
34 #include "btif/include/btif_av.h"
35 #include "btif/include/btif_av_co.h"
36 #include "btif/include/btif_hf.h"
37 #include "common/metrics.h"
38 #include "common/time_util.h"
39 #include "osi/include/log.h"
40 #include "stack/include/a2dp_codec_api.h"
41 #include "stack/include/avdt_api.h"
42 #include "stack/include/btu.h"  // do_in_main_thread
43 
44 using bluetooth::common::A2dpSessionMetrics;
45 using bluetooth::common::BluetoothMetricsLogger;
46 
47 using android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload;
48 using android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost;
49 using android::hardware::bluetooth::a2dp::V1_0::Status;
50 using android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration;
51 using android::hardware::bluetooth::a2dp::V1_0::CodecType;
52 using android::hardware::bluetooth::a2dp::V1_0::SampleRate;
53 using android::hardware::bluetooth::a2dp::V1_0::BitsPerSample;
54 using android::hardware::bluetooth::a2dp::V1_0::ChannelMode;
55 using android::hardware::ProcessState;
56 using ::android::hardware::Return;
57 using ::android::hardware::Void;
58 using ::android::hardware::hidl_death_recipient;
59 using ::android::hardware::hidl_vec;
60 using ::android::sp;
61 using ::android::wp;
62 android::sp<IBluetoothAudioOffload> btAudio;
63 
64 #define CASE_RETURN_STR(const) \
65   case const:                  \
66     return #const;
67 static uint8_t a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
68 static Status mapToStatus(uint8_t resp);
69 uint8_t btif_a2dp_audio_process_request(uint8_t cmd);
70 
71 static void btif_a2dp_audio_send_start_req();
72 static void btif_a2dp_audio_send_suspend_req();
73 static void btif_a2dp_audio_send_stop_req();
74 static void btif_a2dp_audio_interface_init();
75 static void btif_a2dp_audio_interface_deinit();
76 static void btif_a2dp_audio_interface_restart_session();
77 // Delay reporting
78 // static void btif_a2dp_audio_send_sink_latency();
79 
80 class A2dpOffloadAudioStats {
81  public:
A2dpOffloadAudioStats()82   A2dpOffloadAudioStats() { Reset(); }
Reset()83   void Reset() {
84     std::lock_guard<std::recursive_mutex> lock(lock_);
85     ResetPreserveSession();
86     codec_index_ = -1;
87   }
ResetPreserveSession()88   void ResetPreserveSession() {
89     std::lock_guard<std::recursive_mutex> lock(lock_);
90     audio_start_time_ms_ = -1;
91     audio_stop_time_ms_ = -1;
92   }
StoreMetrics()93   void StoreMetrics() {
94     std::lock_guard<std::recursive_mutex> lock(lock_);
95     if (audio_start_time_ms_ < 0 || audio_stop_time_ms_ < 0) {
96       return;
97     }
98     A2dpSessionMetrics metrics;
99     metrics.codec_index = codec_index_;
100     metrics.is_a2dp_offload = true;
101     if (audio_stop_time_ms_ > audio_start_time_ms_) {
102       metrics.audio_duration_ms = audio_stop_time_ms_ - audio_start_time_ms_;
103     }
104     BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics);
105   }
LogAudioStart()106   void LogAudioStart() {
107     std::lock_guard<std::recursive_mutex> lock(lock_);
108     audio_start_time_ms_ = bluetooth::common::time_get_os_boottime_ms();
109   }
LogAudioStop()110   void LogAudioStop() {
111     std::lock_guard<std::recursive_mutex> lock(lock_);
112     audio_stop_time_ms_ = bluetooth::common::time_get_os_boottime_ms();
113   }
LogAudioStopMetricsAndReset()114   void LogAudioStopMetricsAndReset() {
115     std::lock_guard<std::recursive_mutex> lock(lock_);
116     LogAudioStop();
117     StoreMetrics();
118     ResetPreserveSession();
119   }
SetCodecIndex(int64_t codec_index)120   void SetCodecIndex(int64_t codec_index) {
121     std::lock_guard<std::recursive_mutex> lock(lock_);
122     codec_index_ = codec_index;
123   }
124 
125  private:
126   std::recursive_mutex lock_;
127   int64_t audio_start_time_ms_ = -1;
128   int64_t audio_stop_time_ms_ = -1;
129   int64_t codec_index_ = -1;
130 };
131 
132 static A2dpOffloadAudioStats a2dp_offload_audio_stats;
133 
134 class BluetoothAudioHost : public IBluetoothAudioHost {
135  public:
startStream()136   Return<void> startStream() override {
137     btif_a2dp_audio_send_start_req();
138     return Void();
139   }
suspendStream()140   Return<void> suspendStream() override {
141     btif_a2dp_audio_send_suspend_req();
142     return Void();
143   }
stopStream()144   Return<void> stopStream() override {
145     btif_a2dp_audio_send_stop_req();
146     return Void();
147   }
148 
149   // TODO : Delay reporting
150   /*    Return<void> a2dp_get_sink_latency() {
151           LOG_INFO("%s:start ", __func__);
152           btif_a2dp_audio_send_sink_latency();
153           return Void();
154       }*/
155 };
156 
157 class BluetoothAudioDeathRecipient : public hidl_death_recipient {
158  public:
serviceDied(uint64_t,const wp<::android::hidl::base::V1_0::IBase> &)159   void serviceDied(
160       uint64_t /*cookie*/,
161       const wp<::android::hidl::base::V1_0::IBase>& /*who*/) override {
162     LOG_ERROR("%s", __func__);
163     // Restart the session on the correct thread
164     do_in_main_thread(FROM_HERE,
165                       base::Bind(&btif_a2dp_audio_interface_restart_session));
166   }
167 };
168 sp<BluetoothAudioDeathRecipient> bluetoothAudioDeathRecipient =
169     new BluetoothAudioDeathRecipient();
170 
mapToStatus(uint8_t resp)171 static Status mapToStatus(uint8_t resp) {
172   switch (resp) {
173     case A2DP_CTRL_ACK_SUCCESS:
174       return Status::SUCCESS;
175       break;
176     case A2DP_CTRL_ACK_PENDING:
177       return Status::PENDING;
178       break;
179     case A2DP_CTRL_ACK_FAILURE:
180     case A2DP_CTRL_ACK_INCALL_FAILURE:
181     case A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS:
182       return Status::FAILURE;
183     default:
184       APPL_TRACE_WARNING("%s: unknown status recevied :%d", __func__, resp);
185       return Status::FAILURE;
186       break;
187   }
188 }
189 
btif_a2dp_get_codec_configuration(CodecConfiguration * p_codec_info)190 static void btif_a2dp_get_codec_configuration(
191     CodecConfiguration* p_codec_info) {
192   LOG_INFO("%s", __func__);
193   tBT_A2DP_OFFLOAD a2dp_offload;
194   A2dpCodecConfig* a2dpCodecConfig = bta_av_get_a2dp_current_codec();
195   a2dpCodecConfig->getCodecSpecificConfig(&a2dp_offload);
196   btav_a2dp_codec_config_t codec_config;
197   codec_config = a2dpCodecConfig->getCodecConfig();
198   a2dp_offload_audio_stats.SetCodecIndex(a2dpCodecConfig->codecIndex());
199   switch (codec_config.codec_type) {
200     case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
201       p_codec_info->codecType =
202           (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
203               BTA_AV_CODEC_TYPE_SBC;
204       p_codec_info->codecSpecific.sbcData.codecParameters =
205           a2dp_offload.codec_info[0];
206       LOG_INFO(" %s: codec parameters =%d", __func__,
207                a2dp_offload.codec_info[0]);
208       p_codec_info->codecSpecific.sbcData.minBitpool =
209           a2dp_offload.codec_info[1];
210       p_codec_info->codecSpecific.sbcData.maxBitpool =
211           a2dp_offload.codec_info[2];
212       break;
213     case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
214       p_codec_info->codecType =
215           (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
216               BTA_AV_CODEC_TYPE_AAC;
217       break;
218     case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
219       p_codec_info->codecType =
220           (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
221               BTA_AV_CODEC_TYPE_APTX;
222       break;
223     case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
224       p_codec_info->codecType =
225           (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
226               BTA_AV_CODEC_TYPE_APTXHD;
227       break;
228     case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
229       p_codec_info->codecType =
230           (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
231               BTA_AV_CODEC_TYPE_LDAC;
232       p_codec_info->codecSpecific.ldacData.bitrateIndex =
233           a2dp_offload.codec_info[6];
234       break;
235     default:
236       APPL_TRACE_ERROR("%s: Unknown Codec type :%d ", __func__,
237                        codec_config.codec_type);
238   }
239 
240   // Obtain the MTU
241   RawAddress peer_addr = btif_av_source_active_peer();
242   tA2DP_ENCODER_INIT_PEER_PARAMS peer_param;
243   bta_av_co_get_peer_params(peer_addr, &peer_param);
244   int effectiveMtu = a2dpCodecConfig->getEffectiveMtu();
245   if (effectiveMtu > 0 && effectiveMtu < peer_param.peer_mtu) {
246     p_codec_info->peerMtu = effectiveMtu;
247   } else {
248     p_codec_info->peerMtu = peer_param.peer_mtu;
249   }
250   LOG_INFO("%s: peer MTU: %d effective MTU: %d result MTU: %d", __func__,
251            peer_param.peer_mtu, effectiveMtu, p_codec_info->peerMtu);
252 
253   p_codec_info->sampleRate =
254       (::android::hardware::bluetooth::a2dp::V1_0::SampleRate)
255           codec_config.sample_rate;
256   p_codec_info->bitsPerSample =
257       (::android::hardware::bluetooth::a2dp::V1_0::BitsPerSample)
258           codec_config.bits_per_sample;
259   p_codec_info->channelMode =
260       (::android::hardware::bluetooth::a2dp::V1_0::ChannelMode)
261           codec_config.channel_mode;
262   p_codec_info->encodedAudioBitrate = a2dpCodecConfig->getTrackBitRate();
263 }
264 
btif_a2dp_audio_interface_init()265 static void btif_a2dp_audio_interface_init() {
266   LOG_INFO("%s", __func__);
267 
268   btAudio = IBluetoothAudioOffload::getService();
269   CHECK(btAudio != nullptr);
270 
271   auto death_link = btAudio->linkToDeath(bluetoothAudioDeathRecipient, 0);
272   if (!death_link.isOk()) {
273     LOG_ERROR("%s: Cannot observe the Bluetooth Audio HAL's death", __func__);
274   }
275 
276   LOG_INFO("%s: IBluetoothAudioOffload::getService() returned %p (%s)",
277            __func__, btAudio.get(), (btAudio->isRemote() ? "remote" : "local"));
278 
279   LOG_INFO("%s:Init returned", __func__);
280 }
281 
btif_a2dp_audio_interface_deinit()282 static void btif_a2dp_audio_interface_deinit() {
283   LOG_INFO("%s: start", __func__);
284   if (btAudio != nullptr) {
285     auto death_unlink = btAudio->unlinkToDeath(bluetoothAudioDeathRecipient);
286     if (!death_unlink.isOk()) {
287       LOG_ERROR("%s: Error unlinking death observer from Bluetooth Audio HAL",
288                 __func__);
289     }
290   }
291   btAudio = nullptr;
292 }
293 
btif_a2dp_audio_interface_start_session()294 void btif_a2dp_audio_interface_start_session() {
295   LOG_INFO("%s", __func__);
296   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
297       bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
298   a2dp_offload_audio_stats.Reset();
299   btif_a2dp_audio_interface_init();
300   CHECK(btAudio != nullptr);
301   CodecConfiguration codec_info;
302   btif_a2dp_get_codec_configuration(&codec_info);
303   android::sp<IBluetoothAudioHost> host_if = new BluetoothAudioHost();
304   btAudio->startSession(host_if, codec_info);
305 }
306 
btif_a2dp_audio_interface_end_session()307 void btif_a2dp_audio_interface_end_session() {
308   LOG_INFO("%s", __func__);
309   a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
310   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
311       bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0);
312   a2dp_offload_audio_stats.Reset();
313   if (btAudio == nullptr) return;
314   auto ret = btAudio->endSession();
315   if (!ret.isOk()) {
316     LOG_ERROR("HAL server is dead");
317   }
318   btif_a2dp_audio_interface_deinit();
319 }
320 
321 // Conditionally restart the session only if it was started before
btif_a2dp_audio_interface_restart_session()322 static void btif_a2dp_audio_interface_restart_session() {
323   LOG_INFO("%s", __func__);
324   if (btAudio == nullptr) {
325     LOG_INFO("%s: nothing to restart - session was not started", __func__);
326     return;
327   }
328   btAudio = nullptr;
329   btif_a2dp_audio_interface_start_session();
330 }
331 
btif_a2dp_audio_on_started(tBTA_AV_STATUS status)332 void btif_a2dp_audio_on_started(tBTA_AV_STATUS status) {
333   LOG_INFO("%s: status = %d", __func__, status);
334   if (btAudio != nullptr) {
335     if (a2dp_cmd_pending == A2DP_CTRL_CMD_START) {
336       if (status != A2DP_CTRL_ACK_PENDING) {
337         a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
338       }
339       LOG_INFO("%s: calling method onStarted", __func__);
340       auto hal_status = mapToStatus(status);
341       btAudio->streamStarted(hal_status);
342       if (hal_status == Status::SUCCESS) {
343         a2dp_offload_audio_stats.LogAudioStart();
344       }
345     }
346   }
347 }
348 
btif_a2dp_audio_on_suspended(tBTA_AV_STATUS status)349 void btif_a2dp_audio_on_suspended(tBTA_AV_STATUS status) {
350   LOG_INFO("%s: status = %d", __func__, status);
351   if (btAudio != nullptr) {
352     if (a2dp_cmd_pending == A2DP_CTRL_CMD_SUSPEND) {
353       if (status != A2DP_CTRL_ACK_PENDING) {
354         a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
355       }
356       LOG_INFO("calling method onSuspended");
357       auto hal_status = mapToStatus(status);
358       btAudio->streamSuspended(hal_status);
359       if (hal_status == Status::SUCCESS) {
360         a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
361       }
362     }
363   }
364 }
365 
btif_a2dp_audio_on_stopped(tBTA_AV_STATUS status)366 void btif_a2dp_audio_on_stopped(tBTA_AV_STATUS status) {
367   LOG_INFO("%s: status = %d", __func__, status);
368   if (btAudio != nullptr && a2dp_cmd_pending == A2DP_CTRL_CMD_START) {
369     a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
370     LOG_INFO("%s: Remote disconnected when start under progress", __func__);
371     btAudio->streamStarted(mapToStatus(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS));
372     a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
373   }
374 }
btif_a2dp_audio_send_start_req()375 void btif_a2dp_audio_send_start_req() {
376   LOG_INFO("%s", __func__);
377   uint8_t resp;
378   resp = btif_a2dp_audio_process_request(A2DP_CTRL_CMD_START);
379   if (btAudio != nullptr) {
380     auto status = mapToStatus(resp);
381     auto ret = btAudio->streamStarted(status);
382     if (status == Status::SUCCESS) {
383       a2dp_offload_audio_stats.LogAudioStart();
384     }
385     if (!ret.isOk()) LOG_ERROR("HAL server died");
386   }
387 }
btif_a2dp_audio_send_suspend_req()388 void btif_a2dp_audio_send_suspend_req() {
389   LOG_INFO("%s", __func__);
390   uint8_t resp;
391   resp = btif_a2dp_audio_process_request(A2DP_CTRL_CMD_SUSPEND);
392   if (btAudio != nullptr) {
393     auto status = mapToStatus(resp);
394     auto ret = btAudio->streamSuspended(status);
395     if (status == Status::SUCCESS) {
396       a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
397     }
398     if (!ret.isOk()) LOG_ERROR("HAL server died");
399   }
400 }
401 
btif_a2dp_audio_send_stop_req()402 void btif_a2dp_audio_send_stop_req() {
403   LOG_INFO("%s", __func__);
404   btif_a2dp_audio_process_request(A2DP_CTRL_CMD_STOP);
405   a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
406 }
407 
408 /*void btif_a2dp_audio_send_sink_latency()
409 {
410   LOG_INFO("%s", __func__);
411   uint16_t sink_latency = btif_av_get_sink_latency();
412   if (btAudio != nullptr) {
413     auto ret = btAudio->a2dp_on_get_sink_latency(sink_latency);
414     if (!ret.isOk()) LOG_ERROR("server died");
415   }
416 }*/
417 
btif_a2dp_audio_process_request(uint8_t cmd)418 uint8_t btif_a2dp_audio_process_request(uint8_t cmd) {
419   LOG_INFO("%s: cmd: %s", __func__,
420            audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd));
421   uint8_t status;
422   switch (cmd) {
423     case A2DP_CTRL_CMD_START:
424       /*
425        * Don't send START request to stack while we are in a call.
426        * Some headsets such as "Sony MW600", don't allow AVDTP START
427        * while in a call, and respond with BAD_STATE.
428        */
429       if (!bluetooth::headset::IsCallIdle()) {
430         APPL_TRACE_WARNING("%s: A2DP command %s failed as call state is busy",
431                            __func__,
432                            audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd));
433         status = A2DP_CTRL_ACK_INCALL_FAILURE;
434         break;
435       }
436       if (btif_av_stream_started_ready()) {
437         /*
438          * Already started, setup audio data channel listener and ACK
439          * back immediately.
440          */
441         status = A2DP_CTRL_ACK_SUCCESS;
442         break;
443       }
444       if (btif_av_stream_ready()) {
445         /*
446          * Post start event and wait for audio path to open.
447          * If we are the source, the ACK will be sent after the start
448          * procedure is completed, othewise send it now.
449          */
450         btif_av_stream_start();
451         if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) {
452           status = A2DP_CTRL_ACK_SUCCESS;
453           break;
454         }
455         /*Return pending and ack when start stream cfm received from remote*/
456         status = A2DP_CTRL_ACK_PENDING;
457         break;
458       }
459 
460       APPL_TRACE_WARNING("%s: A2DP command %s while AV stream is not ready",
461                          __func__,
462                          audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd));
463       status = A2DP_CTRL_ACK_FAILURE;
464       break;
465 
466     case A2DP_CTRL_CMD_STOP:
467       if (btif_av_get_peer_sep() == AVDT_TSEP_SNK &&
468           !btif_a2dp_source_is_streaming()) {
469         /* We are already stopped, just ack back */
470         status = A2DP_CTRL_ACK_SUCCESS;
471         break;
472       }
473       btif_av_stream_stop(RawAddress::kEmpty);
474       status = A2DP_CTRL_ACK_SUCCESS;
475       break;
476 
477     case A2DP_CTRL_CMD_SUSPEND:
478       /* Local suspend */
479       if (btif_av_stream_started_ready()) {
480         btif_av_stream_suspend();
481         status = A2DP_CTRL_ACK_PENDING;
482         break;
483       }
484       /* If we are not in started state, just ack back ok and let
485        * audioflinger close the channel. This can happen if we are
486        * remotely suspended, clear REMOTE SUSPEND flag.
487        */
488       btif_av_clear_remote_suspend_flag();
489       status = A2DP_CTRL_ACK_SUCCESS;
490       break;
491 
492     case A2DP_CTRL_CMD_OFFLOAD_START:
493       btif_av_stream_start_offload();
494       status = A2DP_CTRL_ACK_PENDING;
495       break;
496 
497     default:
498       APPL_TRACE_ERROR("UNSUPPORTED CMD (%d)", cmd);
499       status = A2DP_CTRL_ACK_FAILURE;
500       break;
501   }
502   LOG_INFO("a2dp-ctrl-cmd : %s DONE returning status %d",
503            audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd), status);
504   if (status == A2DP_CTRL_ACK_PENDING) {
505     a2dp_cmd_pending = cmd;
506   } else {
507     a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
508   }
509   return status;
510 }
511