blob: b56059679bbcaea66b1a35a8fbc9a26d22d376c8 [file] [log] [blame]
Pavlin Radoslavov08406e92016-09-23 16:36:47 -07001/******************************************************************************
2 *
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07003 * Copyright 2016 The Android Open Source Project
4 * Copyright 2009-2012 Broadcom Corporation
Pavlin Radoslavov08406e92016-09-23 16:36:47 -07005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************************/
19
20#define LOG_TAG "bt_btif_a2dp_source"
Philip Cuadrac02b5d42017-06-09 14:36:06 -070021#define ATRACE_TAG ATRACE_TAG_AUDIO
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070022
Jack Hef2af1c42016-12-13 01:59:12 -080023#include <base/logging.h>
Pavlin Radoslavovd7522292017-11-24 19:12:11 -080024#include <base/run_loop.h>
Jakub Pawlowskid3988fd2017-07-14 21:08:47 -070025#ifndef OS_GENERIC
Philip Cuadrac02b5d42017-06-09 14:36:06 -070026#include <cutils/trace.h>
Jakub Pawlowskid3988fd2017-07-14 21:08:47 -070027#endif
Jakub Pawlowski3fa7cce2016-10-13 16:49:07 -070028#include <limits.h>
Jakub Pawlowski5baa8752016-10-18 18:45:21 -070029#include <string.h>
Jack Hef3175622016-12-08 19:29:00 -080030#include <algorithm>
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070031
Pavlin Radoslavov304ceeb2017-04-05 16:18:26 -070032#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070033#include "bt_common.h"
34#include "bta_av_ci.h"
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070035#include "btif_a2dp.h"
36#include "btif_a2dp_control.h"
37#include "btif_a2dp_source.h"
38#include "btif_av.h"
39#include "btif_av_co.h"
40#include "btif_util.h"
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070041#include "osi/include/fixed_queue.h"
42#include "osi/include/log.h"
43#include "osi/include/metrics.h"
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070044#include "osi/include/osi.h"
45#include "osi/include/thread.h"
46#include "osi/include/time.h"
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070047#include "uipc.h"
48
Jack Heabc34b42018-02-07 17:33:16 -080049#include <condition_variable>
50#include <mutex>
51
Jack Hef3175622016-12-08 19:29:00 -080052using system_bt_osi::BluetoothMetricsLogger;
53using system_bt_osi::A2dpSessionMetrics;
54
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070055/**
56 * The typical runlevel of the tx queue size is ~1 buffer
57 * but due to link flow control or thread preemption in lower
58 * layers we might need to temporarily buffer up data.
59 */
60#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ (MAX_PCM_FRAME_NUM_PER_TICK * 2)
61
Pavlin Radoslavovd7522292017-11-24 19:12:11 -080062class SchedulingStats {
63 public:
64 SchedulingStats() { Reset(); }
65 void Reset() {
66 total_updates = 0;
67 last_update_us = 0;
68 overdue_scheduling_count = 0;
69 total_overdue_scheduling_delta_us = 0;
70 max_overdue_scheduling_delta_us = 0;
71 premature_scheduling_count = 0;
72 total_premature_scheduling_delta_us = 0;
73 max_premature_scheduling_delta_us = 0;
74 exact_scheduling_count = 0;
75 total_scheduling_time_us = 0;
76 }
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070077
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -070078 // Counter for total updates
79 size_t total_updates;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070080
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -070081 // Last update timestamp (in us)
82 uint64_t last_update_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070083
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -070084 // Counter for overdue scheduling
85 size_t overdue_scheduling_count;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070086
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -070087 // Accumulated overdue scheduling deviations (in us)
88 uint64_t total_overdue_scheduling_delta_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070089
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -070090 // Max. overdue scheduling delta time (in us)
91 uint64_t max_overdue_scheduling_delta_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070092
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -070093 // Counter for premature scheduling
94 size_t premature_scheduling_count;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070095
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -070096 // Accumulated premature scheduling deviations (in us)
97 uint64_t total_premature_scheduling_delta_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -070098
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -070099 // Max. premature scheduling delta time (in us)
100 uint64_t max_premature_scheduling_delta_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700101
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700102 // Counter for exact scheduling
103 size_t exact_scheduling_count;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700104
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700105 // Accumulated and counted scheduling time (in us)
106 uint64_t total_scheduling_time_us;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800107};
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700108
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800109class BtifMediaStats {
110 public:
111 BtifMediaStats() { Reset(); }
112 void Reset() {
113 session_start_us = 0;
114 session_end_us = 0;
115 tx_queue_enqueue_stats.Reset();
116 tx_queue_dequeue_stats.Reset();
117 tx_queue_total_frames = 0;
118 tx_queue_max_frames_per_packet = 0;
119 tx_queue_total_queueing_time_us = 0;
120 tx_queue_max_queueing_time_us = 0;
121 tx_queue_total_readbuf_calls = 0;
122 tx_queue_last_readbuf_us = 0;
123 tx_queue_total_flushed_messages = 0;
124 tx_queue_last_flushed_us = 0;
125 tx_queue_total_dropped_messages = 0;
126 tx_queue_max_dropped_messages = 0;
127 tx_queue_dropouts = 0;
128 tx_queue_last_dropouts_us = 0;
129 media_read_total_underflow_bytes = 0;
130 media_read_total_underflow_count = 0;
131 media_read_last_underflow_us = 0;
132 }
133
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700134 uint64_t session_start_us;
Jack Hef3175622016-12-08 19:29:00 -0800135 uint64_t session_end_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700136
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800137 SchedulingStats tx_queue_enqueue_stats;
138 SchedulingStats tx_queue_dequeue_stats;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700139
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700140 size_t tx_queue_total_frames;
141 size_t tx_queue_max_frames_per_packet;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700142
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700143 uint64_t tx_queue_total_queueing_time_us;
144 uint64_t tx_queue_max_queueing_time_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700145
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700146 size_t tx_queue_total_readbuf_calls;
147 uint64_t tx_queue_last_readbuf_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700148
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700149 size_t tx_queue_total_flushed_messages;
150 uint64_t tx_queue_last_flushed_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700151
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700152 size_t tx_queue_total_dropped_messages;
153 size_t tx_queue_max_dropped_messages;
154 size_t tx_queue_dropouts;
155 uint64_t tx_queue_last_dropouts_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700156
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700157 size_t media_read_total_underflow_bytes;
158 size_t media_read_total_underflow_count;
159 uint64_t media_read_last_underflow_us;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800160};
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700161
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800162class BtWorkerThread {
163 public:
164 BtWorkerThread(const std::string& thread_name)
165 : thread_name_(thread_name),
166 message_loop_(nullptr),
167 run_loop_(nullptr),
Jack Heabc34b42018-02-07 17:33:16 -0800168 message_loop_thread_(nullptr),
169 started_(false) {}
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800170
171 void StartUp() {
172 if (message_loop_thread_ != nullptr) {
173 return; // Already started up
174 }
Jack Heabc34b42018-02-07 17:33:16 -0800175 message_loop_thread_ = thread_new(thread_name_.c_str());
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800176 CHECK(message_loop_thread_ != nullptr);
Jack Heabc34b42018-02-07 17:33:16 -0800177 started_ = false;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800178 thread_post(message_loop_thread_, &BtWorkerThread::RunThread, this);
Jack Heabc34b42018-02-07 17:33:16 -0800179 {
180 // Block until run_loop_ is allocated and ready to run
181 std::unique_lock<std::mutex> start_lock(start_up_mutex_);
182 while (!started_) {
183 start_up_cv_.wait(start_lock);
184 }
185 }
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800186 }
187
Jack Heabc34b42018-02-07 17:33:16 -0800188 bool DoInThread(const tracked_objects::Location& from_here,
189 const base::Closure& task) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800190 if ((message_loop_ == nullptr) || !message_loop_->task_runner().get()) {
191 LOG_ERROR(
192 LOG_TAG,
193 "%s: Dropping message for thread %s: message loop is not initialized",
194 __func__, thread_name_.c_str());
Jack Heabc34b42018-02-07 17:33:16 -0800195 return false;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800196 }
197 if (!message_loop_->task_runner()->PostTask(from_here, task)) {
198 LOG_ERROR(LOG_TAG,
199 "%s: Posting task to message loop for thread %s failed",
200 __func__, thread_name_.c_str());
Jack Heabc34b42018-02-07 17:33:16 -0800201 return false;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800202 }
Jack Heabc34b42018-02-07 17:33:16 -0800203 return true;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800204 }
205
206 void ShutDown() {
207 if ((run_loop_ != nullptr) && (message_loop_ != nullptr)) {
208 message_loop_->task_runner()->PostTask(FROM_HERE,
209 run_loop_->QuitClosure());
210 }
211 thread_free(message_loop_thread_);
212 message_loop_thread_ = nullptr;
213 }
214
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800215 private:
216 static void RunThread(void* context) {
Jack Heabc34b42018-02-07 17:33:16 -0800217 auto wt = static_cast<BtWorkerThread*>(context);
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800218 wt->Run();
219 }
220
221 void Run() {
Jack Heabc34b42018-02-07 17:33:16 -0800222 LOG_INFO(LOG_TAG, "%s: message loop for thread %s started", __func__,
223 thread_name_.c_str());
224 message_loop_ = new base::MessageLoop();
225 run_loop_ = new base::RunLoop();
226 {
227 std::unique_lock<std::mutex> start_lock(start_up_mutex_);
228 started_ = true;
229 start_up_cv_.notify_all();
230 }
231 // Blocking util ShutDown() is called
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800232 run_loop_->Run();
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800233 delete message_loop_;
234 message_loop_ = nullptr;
235 delete run_loop_;
236 run_loop_ = nullptr;
Jack Heabc34b42018-02-07 17:33:16 -0800237 LOG_INFO(LOG_TAG, "%s: message loop for thread %s finished", __func__,
238 thread_name_.c_str());
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800239 }
240
241 std::string thread_name_;
242 base::MessageLoop* message_loop_;
243 base::RunLoop* run_loop_;
244 thread_t* message_loop_thread_;
Jack Heabc34b42018-02-07 17:33:16 -0800245 // For start-up
246 bool started_;
247 std::mutex start_up_mutex_;
248 std::condition_variable start_up_cv_;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800249};
250
251class BtifA2dpSource {
252 public:
253 enum RunState {
254 kStateOff,
255 kStateStartingUp,
256 kStateRunning,
257 kStateShuttingDown
258 };
259
260 BtifA2dpSource()
261 : tx_audio_queue(nullptr),
262 tx_flush(false),
263 media_alarm(nullptr),
264 encoder_interface(nullptr),
265 encoder_interval_ms(0),
266 state_(kStateOff) {}
267
268 void Reset() {
269 fixed_queue_free(tx_audio_queue, nullptr);
270 tx_audio_queue = nullptr;
271 tx_flush = false;
272 alarm_free(media_alarm);
273 media_alarm = nullptr;
274 encoder_interface = nullptr;
275 encoder_interval_ms = 0;
276 stats.Reset();
277 accumulated_stats.Reset();
278 state_ = kStateOff;
279 }
280
281 BtifA2dpSource::RunState State() const { return state_; }
282 void SetState(BtifA2dpSource::RunState state) { state_ = state; }
283
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700284 fixed_queue_t* tx_audio_queue;
285 bool tx_flush; /* Discards any outgoing data when true */
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700286 alarm_t* media_alarm;
287 const tA2DP_ENCODER_INTERFACE* encoder_interface;
288 period_ms_t encoder_interval_ms; /* Local copy of the encoder interval */
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800289 BtifMediaStats stats;
290 BtifMediaStats accumulated_stats;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700291
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800292 private:
293 BtifA2dpSource::RunState state_;
294};
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700295
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800296static BtWorkerThread btif_a2dp_source_thread("btif_a2dp_source_thread");
297static BtifA2dpSource btif_a2dp_source_cb;
298
299static void btif_a2dp_source_startup_delayed(void);
300static void btif_a2dp_source_shutdown_delayed(void);
Pavlin Radoslavov1394c192016-10-02 18:34:46 -0700301static void btif_a2dp_source_audio_tx_start_event(void);
302static void btif_a2dp_source_audio_tx_stop_event(void);
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800303static void btif_a2dp_source_audio_tx_flush_event(void);
304static void btif_a2dp_source_encoder_init_event(
305 const tA2DP_ENCODER_INIT_PEER_PARAMS& peer_params,
306 const RawAddress& peer_address);
307static void btif_a2dp_source_encoder_user_config_update_event(
308 const RawAddress& peer_address,
309 const btav_a2dp_codec_config_t& codec_user_config);
310static void btif_a2dp_source_audio_feeding_update_event(
311 const btav_a2dp_codec_config_t& codec_audio_config);
Pavlin Radoslavov1394c192016-10-02 18:34:46 -0700312static bool btif_a2dp_source_audio_tx_flush_req(void);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700313static void btif_a2dp_source_alarm_cb(void* context);
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800314static void btif_a2dp_source_audio_handle_timer(void);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700315static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len);
316static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n);
317static void log_tstamps_us(const char* comment, uint64_t timestamp_us);
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800318static void update_scheduling_stats(SchedulingStats* stats, uint64_t now_us,
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700319 uint64_t expected_delta);
320static void btm_read_rssi_cb(void* data);
Pavlin Radoslavov6ab749f2017-08-31 22:06:11 -0700321static void btm_read_failed_contact_counter_cb(void* data);
Pavlin Radoslavovb8568ae2017-09-01 16:09:27 -0700322static void btm_read_automatic_flush_timeout_cb(void* data);
Pavlin Radoslavovc7bf47c2017-09-01 16:40:59 -0700323static void btm_read_tx_power_cb(void* data);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700324
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800325void btif_a2dp_source_accumulate_scheduling_stats(SchedulingStats* src,
326 SchedulingStats* dst) {
Jack Hef3175622016-12-08 19:29:00 -0800327 dst->total_updates += src->total_updates;
328 dst->last_update_us = src->last_update_us;
329 dst->overdue_scheduling_count += src->overdue_scheduling_count;
330 dst->total_overdue_scheduling_delta_us +=
331 src->total_overdue_scheduling_delta_us;
332 dst->max_overdue_scheduling_delta_us =
333 std::max(dst->max_overdue_scheduling_delta_us,
334 src->max_overdue_scheduling_delta_us);
335 dst->premature_scheduling_count += src->premature_scheduling_count;
336 dst->total_premature_scheduling_delta_us +=
337 src->total_premature_scheduling_delta_us;
338 dst->max_premature_scheduling_delta_us =
339 std::max(dst->max_premature_scheduling_delta_us,
340 src->max_premature_scheduling_delta_us);
341 dst->exact_scheduling_count += src->exact_scheduling_count;
342 dst->total_scheduling_time_us += src->total_scheduling_time_us;
343}
344
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800345void btif_a2dp_source_accumulate_stats(BtifMediaStats* src,
346 BtifMediaStats* dst) {
Jack Hef3175622016-12-08 19:29:00 -0800347 dst->tx_queue_total_frames += src->tx_queue_total_frames;
348 dst->tx_queue_max_frames_per_packet = std::max(
349 dst->tx_queue_max_frames_per_packet, src->tx_queue_max_frames_per_packet);
350 dst->tx_queue_total_queueing_time_us += src->tx_queue_total_queueing_time_us;
351 dst->tx_queue_max_queueing_time_us = std::max(
352 dst->tx_queue_max_queueing_time_us, src->tx_queue_max_queueing_time_us);
353 dst->tx_queue_total_readbuf_calls += src->tx_queue_total_readbuf_calls;
354 dst->tx_queue_last_readbuf_us = src->tx_queue_last_readbuf_us;
355 dst->tx_queue_total_flushed_messages += src->tx_queue_total_flushed_messages;
356 dst->tx_queue_last_flushed_us = src->tx_queue_last_flushed_us;
357 dst->tx_queue_total_dropped_messages += src->tx_queue_total_dropped_messages;
358 dst->tx_queue_max_dropped_messages = std::max(
359 dst->tx_queue_max_dropped_messages, src->tx_queue_max_dropped_messages);
360 dst->tx_queue_dropouts += src->tx_queue_dropouts;
361 dst->tx_queue_last_dropouts_us = src->tx_queue_last_dropouts_us;
362 dst->media_read_total_underflow_bytes +=
363 src->media_read_total_underflow_bytes;
364 dst->media_read_total_underflow_count +=
365 src->media_read_total_underflow_count;
366 dst->media_read_last_underflow_us = src->media_read_last_underflow_us;
367 btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_enqueue_stats,
368 &dst->tx_queue_enqueue_stats);
369 btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_dequeue_stats,
370 &dst->tx_queue_dequeue_stats);
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800371 src->Reset();
Jack Hef3175622016-12-08 19:29:00 -0800372}
373
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700374bool btif_a2dp_source_startup(void) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800375 if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateOff) {
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700376 APPL_TRACE_ERROR("%s: A2DP Source media task already running", __func__);
377 return false;
378 }
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700379
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800380 btif_a2dp_source_cb.Reset();
381 btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateStartingUp);
382 btif_a2dp_source_cb.tx_audio_queue = fixed_queue_new(SIZE_MAX);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700383
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700384 APPL_TRACE_EVENT("## A2DP SOURCE START MEDIA THREAD ##");
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700385
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700386 /* Start A2DP Source media task */
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800387 btif_a2dp_source_thread.StartUp();
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700388
389 APPL_TRACE_EVENT("## A2DP SOURCE MEDIA THREAD STARTED ##");
390
391 /* Schedule the rest of the startup operations */
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800392 btif_a2dp_source_thread.DoInThread(
393 FROM_HERE, base::Bind(&btif_a2dp_source_startup_delayed));
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700394
395 return true;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700396}
397
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800398static void btif_a2dp_source_startup_delayed(void) {
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700399 raise_priority_a2dp(TASK_HIGH_MEDIA);
400 btif_a2dp_control_init();
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800401 btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateRunning);
Jack Hef3175622016-12-08 19:29:00 -0800402 BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
403 system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700404}
405
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700406void btif_a2dp_source_shutdown(void) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800407 if ((btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) ||
408 (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateShuttingDown)) {
Sanket Agarwalf436d2f2016-11-02 11:56:44 -0700409 return;
410 }
411
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700412 /* Make sure no channels are restarted while shutting down */
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800413 btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateShuttingDown);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700414
415 APPL_TRACE_EVENT("## A2DP SOURCE STOP MEDIA THREAD ##");
416
417 // Stop the timer
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700418 alarm_free(btif_a2dp_source_cb.media_alarm);
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800419 btif_a2dp_source_cb.media_alarm = nullptr;
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700420
421 // Exit the thread
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800422 btif_a2dp_source_thread.DoInThread(
423 FROM_HERE, base::Bind(&btif_a2dp_source_shutdown_delayed));
424 btif_a2dp_source_thread.ShutDown();
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700425}
426
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800427static void btif_a2dp_source_shutdown_delayed(void) {
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700428 btif_a2dp_control_cleanup();
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800429 fixed_queue_free(btif_a2dp_source_cb.tx_audio_queue, nullptr);
430 btif_a2dp_source_cb.tx_audio_queue = nullptr;
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700431
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800432 btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateOff);
Jack Hea3f831c2017-01-17 15:41:30 -0800433 BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
434 system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700435}
436
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700437bool btif_a2dp_source_media_task_is_running(void) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800438 return (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateRunning);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700439}
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700440
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700441bool btif_a2dp_source_media_task_is_shutting_down(void) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800442 return (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateShuttingDown);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700443}
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700444
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700445bool btif_a2dp_source_is_streaming(void) {
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800446 return alarm_is_scheduled(btif_a2dp_source_cb.media_alarm);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700447}
448
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800449void btif_a2dp_source_setup_codec(const RawAddress& peer_address) {
450 APPL_TRACE_EVENT("## A2DP SOURCE SETUP CODEC (peer %s) ##",
451 peer_address.ToString().c_str());
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700452
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800453 // Check to make sure the platform has 8 bits/byte since
454 // we're using that in frame size calculations now.
455 CHECK(CHAR_BIT == 8);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700456
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800457 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
458 bta_av_co_get_peer_params(peer_address, &peer_params);
459 btif_a2dp_source_thread.DoInThread(
460 FROM_HERE, base::Bind(&btif_a2dp_source_encoder_init_event, peer_params,
461 peer_address));
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700462}
463
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700464void btif_a2dp_source_start_audio_req(void) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800465 btif_a2dp_source_thread.DoInThread(
466 FROM_HERE, base::Bind(&btif_a2dp_source_audio_tx_start_event));
467 btif_a2dp_source_cb.stats.Reset();
Jack Heee5c2572017-01-20 11:17:44 -0800468 // Assign session_start_us to 1 when time_get_os_boottime_us() is 0 to
469 // indicate btif_a2dp_source_start_audio_req() has been called
Jack Hef3175622016-12-08 19:29:00 -0800470 btif_a2dp_source_cb.stats.session_start_us = time_get_os_boottime_us();
Jack Heee5c2572017-01-20 11:17:44 -0800471 if (btif_a2dp_source_cb.stats.session_start_us == 0) {
472 btif_a2dp_source_cb.stats.session_start_us = 1;
473 }
Jack Hef3175622016-12-08 19:29:00 -0800474 btif_a2dp_source_cb.stats.session_end_us = 0;
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700475}
476
477void btif_a2dp_source_stop_audio_req(void) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800478 btif_a2dp_source_thread.DoInThread(
479 FROM_HERE, base::Bind(&btif_a2dp_source_audio_tx_stop_event));
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700480
Jack Hef3175622016-12-08 19:29:00 -0800481 btif_a2dp_source_cb.stats.session_end_us = time_get_os_boottime_us();
482 btif_a2dp_source_update_metrics();
483 btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats,
484 &btif_a2dp_source_cb.accumulated_stats);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700485}
486
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800487static void btif_a2dp_source_encoder_init_event(
488 const tA2DP_ENCODER_INIT_PEER_PARAMS& peer_params,
489 const RawAddress& peer_address) {
490 APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
491 peer_address.ToString().c_str());
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700492
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800493 if (!bta_av_co_set_active_peer(peer_address)) {
494 APPL_TRACE_ERROR("%s: Cannot stream audio: cannot set active peer to %s",
495 __func__, peer_address.ToString().c_str());
496 return;
497 }
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700498 btif_a2dp_source_cb.encoder_interface = bta_av_co_get_encoder_interface();
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800499 if (btif_a2dp_source_cb.encoder_interface == nullptr) {
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700500 APPL_TRACE_ERROR("%s: Cannot stream audio: no source encoder interface",
501 __func__);
502 return;
503 }
504
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800505 A2dpCodecConfig* a2dp_codec_config = bta_av_get_a2dp_current_codec();
506 if (a2dp_codec_config == nullptr) {
507 APPL_TRACE_ERROR("%s: Cannot stream audio: current codec is not set",
508 __func__);
509 return;
510 }
511
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700512 btif_a2dp_source_cb.encoder_interface->encoder_init(
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800513 &peer_params, a2dp_codec_config, btif_a2dp_source_read_callback,
514 btif_a2dp_source_enqueue_callback);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700515
516 // Save a local copy of the encoder_interval_ms
517 btif_a2dp_source_cb.encoder_interval_ms =
518 btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms();
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700519}
520
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800521void btif_a2dp_source_encoder_user_config_update_req(
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800522 const RawAddress& peer_address,
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800523 const btav_a2dp_codec_config_t& codec_user_config) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800524 btif_a2dp_source_thread.DoInThread(
525 FROM_HERE, base::Bind(&btif_a2dp_source_encoder_user_config_update_event,
526 peer_address, codec_user_config));
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700527}
528
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800529static void btif_a2dp_source_encoder_user_config_update_event(
530 const RawAddress& peer_address,
531 const btav_a2dp_codec_config_t& codec_user_config) {
532 APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
533 peer_address.ToString().c_str());
534 if (!bta_av_co_set_codec_user_config(peer_address, codec_user_config)) {
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800535 APPL_TRACE_ERROR("%s: cannot update codec user configuration", __func__);
536 }
537}
538
539void btif_a2dp_source_feeding_update_req(
540 const btav_a2dp_codec_config_t& codec_audio_config) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800541 btif_a2dp_source_thread.DoInThread(
542 FROM_HERE, base::Bind(&btif_a2dp_source_audio_feeding_update_event,
543 codec_audio_config));
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800544}
545
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800546static void btif_a2dp_source_audio_feeding_update_event(
547 const btav_a2dp_codec_config_t& codec_audio_config) {
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800548 APPL_TRACE_DEBUG("%s", __func__);
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800549 if (!bta_av_co_set_codec_audio_config(codec_audio_config)) {
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800550 APPL_TRACE_ERROR("%s: cannot update codec audio feeding parameters",
551 __func__);
552 }
553}
554
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700555void btif_a2dp_source_on_idle(void) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800556 if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700557
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700558 /* Make sure media task is stopped */
559 btif_a2dp_source_stop_audio_req();
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700560}
561
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700562void btif_a2dp_source_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) {
563 APPL_TRACE_EVENT("## ON A2DP SOURCE STOPPED ##");
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700564
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800565 if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700566
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700567 /* allow using this api for other than suspend */
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800568 if (p_av_suspend != nullptr) {
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700569 if (p_av_suspend->status != BTA_AV_SUCCESS) {
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700570 APPL_TRACE_EVENT("AV STOP FAILED (%d)", p_av_suspend->status);
571 if (p_av_suspend->initiator) {
572 APPL_TRACE_WARNING("%s: A2DP stop request failed: status = %d",
573 __func__, p_av_suspend->status);
574 btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
575 }
576 return;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700577 }
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700578 }
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700579
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700580 /* ensure tx frames are immediately suspended */
581 btif_a2dp_source_cb.tx_flush = true;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700582
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700583 /* request to stop media task */
584 btif_a2dp_source_audio_tx_flush_req();
585 btif_a2dp_source_stop_audio_req();
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700586
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700587 /* once stream is fully stopped we will ack back */
588}
589
590void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) {
591 APPL_TRACE_EVENT("## ON A2DP SOURCE SUSPENDED ##");
592
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800593 if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return;
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700594
595 /* check for status failures */
596 if (p_av_suspend->status != BTA_AV_SUCCESS) {
597 if (p_av_suspend->initiator) {
598 APPL_TRACE_WARNING("%s: A2DP suspend request failed: status = %d",
599 __func__, p_av_suspend->status);
600 btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
601 }
602 }
603
604 /* once stream is fully stopped we will ack back */
605
606 /* ensure tx frames are immediately flushed */
607 btif_a2dp_source_cb.tx_flush = true;
608
609 /* stop timer tick */
610 btif_a2dp_source_stop_audio_req();
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700611}
612
613/* when true media task discards any tx frames */
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700614void btif_a2dp_source_set_tx_flush(bool enable) {
615 APPL_TRACE_EVENT("## DROP TX %d ##", enable);
616 btif_a2dp_source_cb.tx_flush = enable;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700617}
618
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700619static void btif_a2dp_source_audio_tx_start_event(void) {
620 APPL_TRACE_DEBUG(
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800621 "%s media_alarm is %srunning, streaming %s", __func__,
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700622 alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ",
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800623 btif_a2dp_source_is_streaming() ? "true" : "false");
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700624
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700625 /* Reset the media feeding state */
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800626 CHECK(btif_a2dp_source_cb.encoder_interface != nullptr);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700627 btif_a2dp_source_cb.encoder_interface->feeding_reset();
628
629 APPL_TRACE_EVENT(
630 "starting timer %dms",
631 btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms());
632
633 alarm_free(btif_a2dp_source_cb.media_alarm);
634 btif_a2dp_source_cb.media_alarm =
635 alarm_new_periodic("btif.a2dp_source_media_alarm");
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800636 if (btif_a2dp_source_cb.media_alarm == nullptr) {
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700637 LOG_ERROR(LOG_TAG, "%s unable to allocate media alarm", __func__);
638 return;
639 }
640
641 alarm_set(btif_a2dp_source_cb.media_alarm,
642 btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms(),
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800643 btif_a2dp_source_alarm_cb, nullptr);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700644}
645
646static void btif_a2dp_source_audio_tx_stop_event(void) {
647 APPL_TRACE_DEBUG(
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800648 "%s media_alarm is %srunning, streaming %s", __func__,
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700649 alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ",
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800650 btif_a2dp_source_is_streaming() ? "true" : "false");
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700651
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800652 const bool send_ack = btif_a2dp_source_is_streaming();
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700653
654 /* Stop the timer first */
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700655 alarm_free(btif_a2dp_source_cb.media_alarm);
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800656 btif_a2dp_source_cb.media_alarm = nullptr;
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700657
Hansong Zhangf88552c2018-02-01 18:02:53 -0800658 UIPC_Close(UIPC_CH_ID_AV_AUDIO, UIPC_USER_A2DP);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700659
660 /*
661 * Try to send acknowldegment once the media stream is
662 * stopped. This will make sure that the A2DP HAL layer is
663 * un-blocked on wait for acknowledgment for the sent command.
664 * This resolves a corner cases AVDTP SUSPEND collision
665 * when the DUT and the remote device issue SUSPEND simultaneously
666 * and due to the processing of the SUSPEND request from the remote,
667 * the media path is torn down. If the A2DP HAL happens to wait
668 * for ACK for the initiated SUSPEND, it would never receive it casuing
669 * a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed
670 * to get the ACK for any pending command in such cases.
671 */
672
673 if (send_ack) btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
674
675 /* audio engine stopped, reset tx suspended flag */
676 btif_a2dp_source_cb.tx_flush = false;
677
678 /* Reset the media feeding state */
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800679 if (btif_a2dp_source_cb.encoder_interface != nullptr)
Pavlin Radoslavov1394c192016-10-02 18:34:46 -0700680 btif_a2dp_source_cb.encoder_interface->feeding_reset();
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700681}
682
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700683static void btif_a2dp_source_alarm_cb(UNUSED_ATTR void* context) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800684 btif_a2dp_source_thread.DoInThread(
685 FROM_HERE, base::Bind(&btif_a2dp_source_audio_handle_timer));
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700686}
687
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800688static void btif_a2dp_source_audio_handle_timer(void) {
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700689 uint64_t timestamp_us = time_get_os_boottime_us();
690 log_tstamps_us("A2DP Source tx timer", timestamp_us);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700691
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700692 if (alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800693 CHECK(btif_a2dp_source_cb.encoder_interface != nullptr);
Philip Cuadrac02b5d42017-06-09 14:36:06 -0700694 size_t transmit_queue_length =
695 fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue);
Jakub Pawlowskid3988fd2017-07-14 21:08:47 -0700696#ifndef OS_GENERIC
Philip Cuadrac02b5d42017-06-09 14:36:06 -0700697 ATRACE_INT("btif TX queue", transmit_queue_length);
Jakub Pawlowskid3988fd2017-07-14 21:08:47 -0700698#endif
fen wangdfc02a92017-03-15 14:52:52 +0900699 if (btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length !=
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800700 nullptr) {
fen wangdfc02a92017-03-15 14:52:52 +0900701 btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length(
702 transmit_queue_length);
703 }
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700704 btif_a2dp_source_cb.encoder_interface->send_frames(timestamp_us);
705 bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
Jack Heee5c2572017-01-20 11:17:44 -0800706 update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_enqueue_stats,
707 timestamp_us,
708 btif_a2dp_source_cb.encoder_interval_ms * 1000);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700709 } else {
710 APPL_TRACE_ERROR("ERROR Media task Scheduled after Suspend");
711 }
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700712}
713
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700714static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len) {
715 uint16_t event;
716 uint32_t bytes_read = UIPC_Read(UIPC_CH_ID_AV_AUDIO, &event, p_buf, len);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700717
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700718 if (bytes_read < len) {
719 LOG_WARN(LOG_TAG, "%s: UNDERFLOW: ONLY READ %d BYTES OUT OF %d", __func__,
720 bytes_read, len);
721 btif_a2dp_source_cb.stats.media_read_total_underflow_bytes +=
722 (len - bytes_read);
723 btif_a2dp_source_cb.stats.media_read_total_underflow_count++;
724 btif_a2dp_source_cb.stats.media_read_last_underflow_us =
725 time_get_os_boottime_us();
726 }
727
728 return bytes_read;
729}
730
731static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n) {
732 uint64_t now_us = time_get_os_boottime_us();
733
734 /* Check if timer was stopped (media task stopped) */
735 if (!alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) {
736 osi_free(p_buf);
737 return false;
738 }
739
740 /* Check if the transmission queue has been flushed */
741 if (btif_a2dp_source_cb.tx_flush) {
742 LOG_VERBOSE(LOG_TAG, "%s: tx suspended, discarded frame", __func__);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700743
744 btif_a2dp_source_cb.stats.tx_queue_total_flushed_messages +=
Pavlin Radoslavov1394c192016-10-02 18:34:46 -0700745 fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700746 btif_a2dp_source_cb.stats.tx_queue_last_flushed_us = now_us;
Pavlin Radoslavov1394c192016-10-02 18:34:46 -0700747 fixed_queue_flush(btif_a2dp_source_cb.tx_audio_queue, osi_free);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700748
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700749 osi_free(p_buf);
750 return false;
751 }
752
753 // Check for TX queue overflow
754 // TODO: Using frames_n here is probably wrong: should be "+ 1" instead.
755 if (fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue) + frames_n >
756 MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ) {
757 LOG_WARN(LOG_TAG, "%s: TX queue buffer size now=%u adding=%u max=%d",
758 __func__,
759 (uint32_t)fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue),
760 (uint32_t)frames_n, MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ);
761 // Keep track of drop-outs
762 btif_a2dp_source_cb.stats.tx_queue_dropouts++;
763 btif_a2dp_source_cb.stats.tx_queue_last_dropouts_us = now_us;
764
765 // Flush all queued buffers
766 size_t drop_n = fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue);
Jack Hef3175622016-12-08 19:29:00 -0800767 btif_a2dp_source_cb.stats.tx_queue_max_dropped_messages = std::max(
768 drop_n, btif_a2dp_source_cb.stats.tx_queue_max_dropped_messages);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700769 while (fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue)) {
770 btif_a2dp_source_cb.stats.tx_queue_total_dropped_messages++;
771 osi_free(fixed_queue_try_dequeue(btif_a2dp_source_cb.tx_audio_queue));
772 }
773
Pavlin Radoslavovb8568ae2017-09-01 16:09:27 -0700774 // Request additional debug info if we had to flush buffers
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800775 RawAddress peer_bda = btif_av_source_active_peer();
Pavlin Radoslavov6ab749f2017-08-31 22:06:11 -0700776 tBTM_STATUS status = BTM_ReadRSSI(peer_bda, btm_read_rssi_cb);
777 if (status != BTM_CMD_STARTED) {
778 LOG_WARN(LOG_TAG, "%s: Cannot read RSSI: status %d", __func__, status);
779 }
780 status = BTM_ReadFailedContactCounter(peer_bda,
781 btm_read_failed_contact_counter_cb);
782 if (status != BTM_CMD_STARTED) {
783 LOG_WARN(LOG_TAG, "%s: Cannot read Failed Contact Counter: status %d",
784 __func__, status);
785 }
Pavlin Radoslavovb8568ae2017-09-01 16:09:27 -0700786 status = BTM_ReadAutomaticFlushTimeout(peer_bda,
787 btm_read_automatic_flush_timeout_cb);
788 if (status != BTM_CMD_STARTED) {
789 LOG_WARN(LOG_TAG, "%s: Cannot read Automatic Flush Timeout: status %d",
790 __func__, status);
791 }
Pavlin Radoslavovc7bf47c2017-09-01 16:40:59 -0700792 status =
793 BTM_ReadTxPower(peer_bda, BT_TRANSPORT_BR_EDR, btm_read_tx_power_cb);
794 if (status != BTM_CMD_STARTED) {
795 LOG_WARN(LOG_TAG, "%s: Cannot read Tx Power: status %d", __func__,
796 status);
797 }
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700798 }
799
800 /* Update the statistics */
801 btif_a2dp_source_cb.stats.tx_queue_total_frames += frames_n;
Jack Hef3175622016-12-08 19:29:00 -0800802 btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet = std::max(
803 frames_n, btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet);
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800804 CHECK(btif_a2dp_source_cb.encoder_interface != nullptr);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700805
806 fixed_queue_enqueue(btif_a2dp_source_cb.tx_audio_queue, p_buf);
807
808 return true;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700809}
810
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800811static void btif_a2dp_source_audio_tx_flush_event(void) {
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700812 /* Flush all enqueued audio buffers (encoded) */
813 APPL_TRACE_DEBUG("%s", __func__);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700814
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800815 if (btif_a2dp_source_cb.encoder_interface != nullptr)
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700816 btif_a2dp_source_cb.encoder_interface->feeding_flush();
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700817
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700818 btif_a2dp_source_cb.stats.tx_queue_total_flushed_messages +=
819 fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue);
820 btif_a2dp_source_cb.stats.tx_queue_last_flushed_us =
821 time_get_os_boottime_us();
822 fixed_queue_flush(btif_a2dp_source_cb.tx_audio_queue, osi_free);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700823
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800824 UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REQ_RX_FLUSH, nullptr);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700825}
826
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700827static bool btif_a2dp_source_audio_tx_flush_req(void) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800828 btif_a2dp_source_thread.DoInThread(
829 FROM_HERE, base::Bind(&btif_a2dp_source_audio_tx_flush_event));
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700830 return true;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700831}
832
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700833BT_HDR* btif_a2dp_source_audio_readbuf(void) {
834 uint64_t now_us = time_get_os_boottime_us();
835 BT_HDR* p_buf =
836 (BT_HDR*)fixed_queue_try_dequeue(btif_a2dp_source_cb.tx_audio_queue);
837
838 btif_a2dp_source_cb.stats.tx_queue_total_readbuf_calls++;
839 btif_a2dp_source_cb.stats.tx_queue_last_readbuf_us = now_us;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800840 if (p_buf != nullptr) {
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700841 // Update the statistics
842 update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_dequeue_stats,
843 now_us,
844 btif_a2dp_source_cb.encoder_interval_ms * 1000);
845 }
846
847 return p_buf;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700848}
849
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700850static void log_tstamps_us(const char* comment, uint64_t timestamp_us) {
851 static uint64_t prev_us = 0;
852 APPL_TRACE_DEBUG("[%s] ts %08llu, diff : %08llu, queue sz %d", comment,
853 timestamp_us, timestamp_us - prev_us,
854 fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue));
855 prev_us = timestamp_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700856}
857
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800858static void update_scheduling_stats(SchedulingStats* stats, uint64_t now_us,
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700859 uint64_t expected_delta) {
860 uint64_t last_us = stats->last_update_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700861
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700862 stats->total_updates++;
863 stats->last_update_us = now_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700864
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700865 if (last_us == 0) return; // First update: expected delta doesn't apply
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700866
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700867 uint64_t deadline_us = last_us + expected_delta;
868 if (deadline_us < now_us) {
869 // Overdue scheduling
870 uint64_t delta_us = now_us - deadline_us;
871 // Ignore extreme outliers
872 if (delta_us < 10 * expected_delta) {
Jack Hef3175622016-12-08 19:29:00 -0800873 stats->max_overdue_scheduling_delta_us =
874 std::max(delta_us, stats->max_overdue_scheduling_delta_us);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700875 stats->total_overdue_scheduling_delta_us += delta_us;
876 stats->overdue_scheduling_count++;
877 stats->total_scheduling_time_us += now_us - last_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700878 }
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700879 } else if (deadline_us > now_us) {
880 // Premature scheduling
881 uint64_t delta_us = deadline_us - now_us;
882 // Ignore extreme outliers
883 if (delta_us < 10 * expected_delta) {
Jack Hef3175622016-12-08 19:29:00 -0800884 stats->max_premature_scheduling_delta_us =
885 std::max(delta_us, stats->max_premature_scheduling_delta_us);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700886 stats->total_premature_scheduling_delta_us += delta_us;
887 stats->premature_scheduling_count++;
888 stats->total_scheduling_time_us += now_us - last_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700889 }
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700890 } else {
891 // On-time scheduling
892 stats->exact_scheduling_count++;
893 stats->total_scheduling_time_us += now_us - last_us;
894 }
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700895}
896
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700897void btif_a2dp_source_debug_dump(int fd) {
Jack Hef3175622016-12-08 19:29:00 -0800898 btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats,
899 &btif_a2dp_source_cb.accumulated_stats);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700900 uint64_t now_us = time_get_os_boottime_us();
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800901 BtifMediaStats* accumulated_stats = &btif_a2dp_source_cb.accumulated_stats;
902 SchedulingStats* enqueue_stats = &accumulated_stats->tx_queue_enqueue_stats;
903 SchedulingStats* dequeue_stats = &accumulated_stats->tx_queue_dequeue_stats;
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700904 size_t ave_size;
905 uint64_t ave_time_us;
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700906
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700907 dprintf(fd, "\nA2DP State:\n");
908 dprintf(fd, " TxQueue:\n");
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700909
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700910 dprintf(fd,
911 " Counts (enqueue/dequeue/readbuf) : %zu / "
912 "%zu / %zu\n",
913 enqueue_stats->total_updates, dequeue_stats->total_updates,
Jack Hef3175622016-12-08 19:29:00 -0800914 accumulated_stats->tx_queue_total_readbuf_calls);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700915
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700916 dprintf(
917 fd,
918 " Last update time ago in ms (enqueue/dequeue/readbuf) : %llu / %llu "
919 "/ %llu\n",
920 (enqueue_stats->last_update_us > 0)
921 ? (unsigned long long)(now_us - enqueue_stats->last_update_us) / 1000
922 : 0,
923 (dequeue_stats->last_update_us > 0)
924 ? (unsigned long long)(now_us - dequeue_stats->last_update_us) / 1000
925 : 0,
Jack Hef3175622016-12-08 19:29:00 -0800926 (accumulated_stats->tx_queue_last_readbuf_us > 0)
927 ? (unsigned long long)(now_us -
928 accumulated_stats->tx_queue_last_readbuf_us) /
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700929 1000
930 : 0);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700931
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700932 ave_size = 0;
933 if (enqueue_stats->total_updates != 0)
Jack Hef3175622016-12-08 19:29:00 -0800934 ave_size =
935 accumulated_stats->tx_queue_total_frames / enqueue_stats->total_updates;
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700936 dprintf(fd,
937 " Frames per packet (total/max/ave) : %zu / "
938 "%zu / %zu\n",
Jack Hef3175622016-12-08 19:29:00 -0800939 accumulated_stats->tx_queue_total_frames,
940 accumulated_stats->tx_queue_max_frames_per_packet, ave_size);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700941
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700942 dprintf(fd,
943 " Counts (flushed/dropped/dropouts) : %zu / "
944 "%zu / %zu\n",
Jack Hef3175622016-12-08 19:29:00 -0800945 accumulated_stats->tx_queue_total_flushed_messages,
946 accumulated_stats->tx_queue_total_dropped_messages,
947 accumulated_stats->tx_queue_dropouts);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -0700948
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700949 dprintf(fd,
950 " Counts (max dropped) : %zu\n",
Jack Hef3175622016-12-08 19:29:00 -0800951 accumulated_stats->tx_queue_max_dropped_messages);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700952
953 dprintf(
954 fd,
955 " Last update time ago in ms (flushed/dropped) : %llu / "
956 "%llu\n",
Jack Hef3175622016-12-08 19:29:00 -0800957 (accumulated_stats->tx_queue_last_flushed_us > 0)
958 ? (unsigned long long)(now_us -
959 accumulated_stats->tx_queue_last_flushed_us) /
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700960 1000
961 : 0,
Jack Hef3175622016-12-08 19:29:00 -0800962 (accumulated_stats->tx_queue_last_dropouts_us > 0)
963 ? (unsigned long long)(now_us -
964 accumulated_stats->tx_queue_last_dropouts_us) /
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700965 1000
966 : 0);
967
968 dprintf(fd,
969 " Counts (underflow) : %zu\n",
Jack Hef3175622016-12-08 19:29:00 -0800970 accumulated_stats->media_read_total_underflow_count);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700971
972 dprintf(fd,
973 " Bytes (underflow) : %zu\n",
Jack Hef3175622016-12-08 19:29:00 -0800974 accumulated_stats->media_read_total_underflow_bytes);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700975
Jack Hef3175622016-12-08 19:29:00 -0800976 dprintf(fd,
977 " Last update time ago in ms (underflow) : %llu\n",
978 (accumulated_stats->media_read_last_underflow_us > 0)
979 ? (unsigned long long)(now_us -
980 accumulated_stats
981 ->media_read_last_underflow_us) /
982 1000
983 : 0);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -0700984
985 //
986 // TxQueue enqueue stats
987 //
988 dprintf(
989 fd,
990 " Enqueue deviation counts (overdue/premature) : %zu / %zu\n",
991 enqueue_stats->overdue_scheduling_count,
992 enqueue_stats->premature_scheduling_count);
993
994 ave_time_us = 0;
995 if (enqueue_stats->overdue_scheduling_count != 0) {
996 ave_time_us = enqueue_stats->total_overdue_scheduling_delta_us /
997 enqueue_stats->overdue_scheduling_count;
998 }
999 dprintf(
1000 fd,
1001 " Enqueue overdue scheduling time in ms (total/max/ave) : %llu / %llu "
1002 "/ %llu\n",
1003 (unsigned long long)enqueue_stats->total_overdue_scheduling_delta_us /
1004 1000,
1005 (unsigned long long)enqueue_stats->max_overdue_scheduling_delta_us / 1000,
1006 (unsigned long long)ave_time_us / 1000);
1007
1008 ave_time_us = 0;
1009 if (enqueue_stats->premature_scheduling_count != 0) {
1010 ave_time_us = enqueue_stats->total_premature_scheduling_delta_us /
1011 enqueue_stats->premature_scheduling_count;
1012 }
1013 dprintf(
1014 fd,
1015 " Enqueue premature scheduling time in ms (total/max/ave) : %llu / %llu "
1016 "/ %llu\n",
1017 (unsigned long long)enqueue_stats->total_premature_scheduling_delta_us /
1018 1000,
1019 (unsigned long long)enqueue_stats->max_premature_scheduling_delta_us /
1020 1000,
1021 (unsigned long long)ave_time_us / 1000);
1022
1023 //
1024 // TxQueue dequeue stats
1025 //
1026 dprintf(
1027 fd,
1028 " Dequeue deviation counts (overdue/premature) : %zu / %zu\n",
1029 dequeue_stats->overdue_scheduling_count,
1030 dequeue_stats->premature_scheduling_count);
1031
1032 ave_time_us = 0;
1033 if (dequeue_stats->overdue_scheduling_count != 0) {
1034 ave_time_us = dequeue_stats->total_overdue_scheduling_delta_us /
1035 dequeue_stats->overdue_scheduling_count;
1036 }
1037 dprintf(
1038 fd,
1039 " Dequeue overdue scheduling time in ms (total/max/ave) : %llu / %llu "
1040 "/ %llu\n",
1041 (unsigned long long)dequeue_stats->total_overdue_scheduling_delta_us /
1042 1000,
1043 (unsigned long long)dequeue_stats->max_overdue_scheduling_delta_us / 1000,
1044 (unsigned long long)ave_time_us / 1000);
1045
1046 ave_time_us = 0;
1047 if (dequeue_stats->premature_scheduling_count != 0) {
1048 ave_time_us = dequeue_stats->total_premature_scheduling_delta_us /
1049 dequeue_stats->premature_scheduling_count;
1050 }
1051 dprintf(
1052 fd,
1053 " Dequeue premature scheduling time in ms (total/max/ave) : %llu / %llu "
1054 "/ %llu\n",
1055 (unsigned long long)dequeue_stats->total_premature_scheduling_delta_us /
1056 1000,
1057 (unsigned long long)dequeue_stats->max_premature_scheduling_delta_us /
1058 1000,
1059 (unsigned long long)ave_time_us / 1000);
Pavlin Radoslavov08406e92016-09-23 16:36:47 -07001060}
Pavlin Radoslavov1394c192016-10-02 18:34:46 -07001061
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001062void btif_a2dp_source_update_metrics(void) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001063 const BtifMediaStats& stats = btif_a2dp_source_cb.stats;
1064 const SchedulingStats& enqueue_stats = stats.tx_queue_enqueue_stats;
Jack Hef3175622016-12-08 19:29:00 -08001065 A2dpSessionMetrics metrics;
Jack Heee5c2572017-01-20 11:17:44 -08001066 // session_start_us is 0 when btif_a2dp_source_start_audio_req() is not called
1067 // mark the metric duration as invalid (-1) in this case
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001068 if (stats.session_start_us != 0) {
1069 int64_t session_end_us = stats.session_end_us == 0
Jack Heee5c2572017-01-20 11:17:44 -08001070 ? time_get_os_boottime_us()
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001071 : stats.session_end_us;
Jack Heee5c2572017-01-20 11:17:44 -08001072 metrics.audio_duration_ms =
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001073 (session_end_us - stats.session_start_us) / 1000;
Jack Heee5c2572017-01-20 11:17:44 -08001074 }
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001075
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001076 if (enqueue_stats.total_updates > 1) {
Jack Hef3175622016-12-08 19:29:00 -08001077 metrics.media_timer_min_ms =
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001078 btif_a2dp_source_cb.encoder_interval_ms -
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001079 (enqueue_stats.max_premature_scheduling_delta_us / 1000);
Jack Hef3175622016-12-08 19:29:00 -08001080 metrics.media_timer_max_ms =
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001081 btif_a2dp_source_cb.encoder_interval_ms +
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001082 (enqueue_stats.max_overdue_scheduling_delta_us / 1000);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001083
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001084 metrics.total_scheduling_count = enqueue_stats.overdue_scheduling_count +
1085 enqueue_stats.premature_scheduling_count +
1086 enqueue_stats.exact_scheduling_count;
Jack Hef3175622016-12-08 19:29:00 -08001087 if (metrics.total_scheduling_count > 0) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001088 metrics.media_timer_avg_ms = enqueue_stats.total_scheduling_time_us /
Jack Hef3175622016-12-08 19:29:00 -08001089 (1000 * metrics.total_scheduling_count);
Pavlin Radoslavov1394c192016-10-02 18:34:46 -07001090 }
1091
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001092 metrics.buffer_overruns_max_count = stats.tx_queue_max_dropped_messages;
1093 metrics.buffer_overruns_total = stats.tx_queue_total_dropped_messages;
1094 metrics.buffer_underruns_count = stats.media_read_total_underflow_count;
Jack Heee5c2572017-01-20 11:17:44 -08001095 metrics.buffer_underruns_average = 0;
Jack Hef3175622016-12-08 19:29:00 -08001096 if (metrics.buffer_underruns_count > 0) {
1097 metrics.buffer_underruns_average =
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001098 stats.media_read_total_underflow_bytes /
Jack Hef3175622016-12-08 19:29:00 -08001099 metrics.buffer_underruns_count;
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001100 }
1101 }
Jack Hef3175622016-12-08 19:29:00 -08001102 BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics);
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001103}
1104
1105static void btm_read_rssi_cb(void* data) {
Andre Eisenbachce8e8582016-11-03 15:05:22 -07001106 if (data == nullptr) {
Pavlin Radoslavovb8568ae2017-09-01 16:09:27 -07001107 LOG_ERROR(LOG_TAG, "%s Read RSSI request timed out", __func__);
Andre Eisenbachce8e8582016-11-03 15:05:22 -07001108 return;
1109 }
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001110
Pavlin Radoslavovc7bf47c2017-09-01 16:40:59 -07001111 tBTM_RSSI_RESULT* result = (tBTM_RSSI_RESULT*)data;
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001112 if (result->status != BTM_SUCCESS) {
1113 LOG_ERROR(LOG_TAG, "%s unable to read remote RSSI (status %d)", __func__,
1114 result->status);
1115 return;
1116 }
1117
Pavlin Radoslavov397e5a52016-10-14 16:13:54 -07001118 LOG_WARN(LOG_TAG, "%s device: %s, rssi: %d", __func__,
Jakub Pawlowskib707f442017-07-03 15:39:36 -07001119 result->rem_bda.ToString().c_str(), result->rssi);
Pavlin Radoslavov1394c192016-10-02 18:34:46 -07001120}
Pavlin Radoslavov6ab749f2017-08-31 22:06:11 -07001121
1122static void btm_read_failed_contact_counter_cb(void* data) {
1123 if (data == nullptr) {
Pavlin Radoslavovb8568ae2017-09-01 16:09:27 -07001124 LOG_ERROR(LOG_TAG, "%s Read Failed Contact Counter request timed out",
1125 __func__);
Pavlin Radoslavov6ab749f2017-08-31 22:06:11 -07001126 return;
1127 }
1128
1129 tBTM_FAILED_CONTACT_COUNTER_RESULT* result =
1130 (tBTM_FAILED_CONTACT_COUNTER_RESULT*)data;
1131 if (result->status != BTM_SUCCESS) {
Pavlin Radoslavovb8568ae2017-09-01 16:09:27 -07001132 LOG_ERROR(LOG_TAG, "%s unable to read Failed Contact Counter (status %d)",
Pavlin Radoslavov6ab749f2017-08-31 22:06:11 -07001133 __func__, result->status);
1134 return;
1135 }
1136
1137 LOG_WARN(LOG_TAG, "%s device: %s, Failed Contact Counter: %u", __func__,
1138 result->rem_bda.ToString().c_str(), result->failed_contact_counter);
1139}
Pavlin Radoslavovb8568ae2017-09-01 16:09:27 -07001140
1141static void btm_read_automatic_flush_timeout_cb(void* data) {
1142 if (data == nullptr) {
1143 LOG_ERROR(LOG_TAG, "%s Read Automatic Flush Timeout request timed out",
1144 __func__);
1145 return;
1146 }
1147
1148 tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT* result =
1149 (tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT*)data;
1150 if (result->status != BTM_SUCCESS) {
1151 LOG_ERROR(LOG_TAG, "%s unable to read Automatic Flush Timeout (status %d)",
1152 __func__, result->status);
1153 return;
1154 }
1155
1156 LOG_WARN(LOG_TAG, "%s device: %s, Automatic Flush Timeout: %u", __func__,
1157 result->rem_bda.ToString().c_str(), result->automatic_flush_timeout);
1158}
Pavlin Radoslavovc7bf47c2017-09-01 16:40:59 -07001159
1160static void btm_read_tx_power_cb(void* data) {
1161 if (data == nullptr) {
1162 LOG_ERROR(LOG_TAG, "%s Read Tx Power request timed out", __func__);
1163 return;
1164 }
1165
1166 tBTM_TX_POWER_RESULT* result = (tBTM_TX_POWER_RESULT*)data;
1167 if (result->status != BTM_SUCCESS) {
1168 LOG_ERROR(LOG_TAG, "%s unable to read Tx Power (status %d)", __func__,
1169 result->status);
1170 return;
1171 }
1172
1173 LOG_WARN(LOG_TAG, "%s device: %s, Tx Power: %d", __func__,
1174 result->rem_bda.ToString().c_str(), result->tx_power);
1175}