Merge changes from topic "am-2c2c464f-fb3a-4c93-8661-57c986c3e069-nyc-dev" into oc-dev am: 0d4898a05d am: a9fc38bcbf
am: a7d532c77c
Change-Id: Ic3bbfdf73d39b1455f6d27bf9294fb56011d0829
diff --git a/.clang-format b/.clang-format
index fa9d143..0b4b45a 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2016 The Android Open Source Project
+# Copyright 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/.gn b/.gn
index 947ebac..1c2396d 100644
--- a/.gn
+++ b/.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/Android.bp b/Android.bp
index 462b8be..fb0fdd9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,8 +1,10 @@
subdirs = [
+ "binder",
"build",
"btif",
"btcore",
"audio_a2dp_hw",
+ "audio_hearing_aid_hw",
"hci",
"utils",
"device",
@@ -10,6 +12,7 @@
"osi",
"embdrv",
"service",
+ "include",
"main",
"bta",
"vendor_libs",
@@ -17,4 +20,5 @@
"types",
"udrv",
"tools",
+ "proto",
]
diff --git a/BUILD.gn b/BUILD.gn
index 618de1c..04c32a1 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
# This pulls in main/BUILD.gn and all of its dependencies.
group("bluetooth") {
deps = [
- "//main:bluetooth.default",
+ "//main:bluetooth",
"//service:bluetoothtbd",
]
}
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 518119b..8be8c0a 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 The Android Open Source Project
+# Copyright 2007 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/OWNERS b/OWNERS
index a795df4..2ddc791 100644
--- a/OWNERS
+++ b/OWNERS
@@ -3,7 +3,6 @@
# Project owners
eisenbach@google.com
apanicke@google.com
-jamuraa@google.com
jpawlowski@google.com
mylesgw@google.com
pavlin@google.com
diff --git a/README.md b/README.md
index e937e81..869bc1f 100644
--- a/README.md
+++ b/README.md
@@ -35,7 +35,6 @@
git clone https://android.googlesource.com/platform/external/libldac
git clone https://android.googlesource.com/platform/external/modp_b64
git clone https://android.googlesource.com/platform/external/tinyxml2
-git clone https://android.googlesource.com/platform/hardware/libhardware
```
And third party dependencies of third party dependencies:
@@ -60,7 +59,6 @@
ln -s ../../../external/libldac libldac
ln -s ../../../external/modp_b64 modp_b64
ln -s ../../../external/tinyxml2 tinyxml2
-ln -s ../../../hardware/libhardware libhardware
ln -s ../../../external/googletest googletest
```
diff --git a/audio_a2dp_hw/Android.bp b/audio_a2dp_hw/Android.bp
index ae93e06..7a23e27 100644
--- a/audio_a2dp_hw/Android.bp
+++ b/audio_a2dp_hw/Android.bp
@@ -3,6 +3,7 @@
defaults: ["fluoride_defaults"],
include_dirs: [
"system/bt",
+ "system/bt/include",
"system/bt/audio_a2dp_hw/include",
]
}
@@ -19,6 +20,7 @@
],
shared_libs: [
"liblog",
+ "libcutils",
],
static_libs: ["libosi"],
}
diff --git a/audio_a2dp_hw/include/audio_a2dp_hw.h b/audio_a2dp_hw/include/audio_a2dp_hw.h
index d6c69e1..4d32432 100644
--- a/audio_a2dp_hw/include/audio_a2dp_hw.h
+++ b/audio_a2dp_hw/include/audio_a2dp_hw.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -85,13 +85,16 @@
A2DP_CTRL_GET_OUTPUT_AUDIO_CONFIG,
A2DP_CTRL_SET_OUTPUT_AUDIO_CONFIG,
A2DP_CTRL_CMD_OFFLOAD_START,
+ A2DP_CTRL_GET_PRESENTATION_POSITION,
} tA2DP_CTRL_CMD;
typedef enum {
A2DP_CTRL_ACK_SUCCESS,
A2DP_CTRL_ACK_FAILURE,
A2DP_CTRL_ACK_INCALL_FAILURE, /* Failure when in Call*/
- A2DP_CTRL_ACK_UNSUPPORTED
+ A2DP_CTRL_ACK_UNSUPPORTED,
+ A2DP_CTRL_ACK_PENDING,
+ A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS,
} tA2DP_CTRL_ACK;
typedef uint32_t tA2DP_SAMPLE_RATE;
@@ -140,12 +143,15 @@
//
// Returns the computed buffer size. If any of the input parameters is
// invalid, the return value is the default |AUDIO_STREAM_OUTPUT_BUFFER_SZ|.
-extern size_t audio_a2dp_hw_stream_compute_buffer_size(
+size_t audio_a2dp_hw_stream_compute_buffer_size(
btav_a2dp_codec_sample_rate_t codec_sample_rate,
btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample,
btav_a2dp_codec_channel_mode_t codec_channel_mode);
+// Returns whether the delay reporting property is set.
+bool delay_reporting_enabled();
+
// Returns a string representation of |event|.
-extern const char* audio_a2dp_hw_dump_ctrl_event(tA2DP_CTRL_CMD event);
+const char* audio_a2dp_hw_dump_ctrl_event(tA2DP_CTRL_CMD event);
#endif /* A2DP_AUDIO_HW_H */
diff --git a/audio_a2dp_hw/src/audio_a2dp_hw.cc b/audio_a2dp_hw/src/audio_a2dp_hw.cc
index 1fcc408..3622298 100644
--- a/audio_a2dp_hw/src/audio_a2dp_hw.cc
+++ b/audio_a2dp_hw/src/audio_a2dp_hw.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,6 +58,13 @@
#define USEC_PER_SEC 1000000L
#define SOCK_SEND_TIMEOUT_MS 2000 /* Timeout for sending */
#define SOCK_RECV_TIMEOUT_MS 5000 /* Timeout for receiving */
+#define SEC_TO_MS 1000
+#define SEC_TO_NS 1000000000
+#define MS_TO_NS 1000000
+#define DELAY_TO_NS 100000
+
+#define MIN_DELAY_MS 100
+#define MAX_DELAY_MS 1000
// set WRITE_POLL_MS to 0 for blocking sockets, nonzero for polled non-blocking
// sockets
@@ -105,6 +112,7 @@
struct a2dp_config {
uint32_t rate;
uint32_t channel_mask;
+ bool is_stereo_to_mono; // True if fetching Stereo and mixing into Mono
int format;
};
@@ -144,11 +152,14 @@
* Static variables
*****************************************************************************/
+static bool enable_delay_reporting = false;
+
/*****************************************************************************
* Static functions
*****************************************************************************/
static size_t out_get_buffer_size(const struct audio_stream* stream);
+static uint32_t out_get_latency(const struct audio_stream_out* stream);
/*****************************************************************************
* Externs
@@ -416,10 +427,12 @@
DEBUG("A2DP COMMAND %s", audio_a2dp_hw_dump_ctrl_event(cmd));
if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
- INFO("starting up or recovering from previous error");
+ INFO("starting up or recovering from previous error: command=%s",
+ audio_a2dp_hw_dump_ctrl_event(cmd));
a2dp_open_ctrl_path(common);
if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
- ERROR("failure to open ctrl path");
+ ERROR("failure to open ctrl path: command=%s",
+ audio_a2dp_hw_dump_ctrl_event(cmd));
return -1;
}
}
@@ -428,7 +441,8 @@
ssize_t sent;
OSI_NO_INTR(sent = send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL));
if (sent == -1) {
- ERROR("cmd failed (%s)", strerror(errno));
+ ERROR("cmd failed (%s): command=%s", strerror(errno),
+ audio_a2dp_hw_dump_ctrl_event(cmd));
skt_disconnect(common->ctrl_fd);
common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
return -1;
@@ -443,7 +457,10 @@
DEBUG("A2DP COMMAND %s DONE STATUS %d", audio_a2dp_hw_dump_ctrl_event(cmd),
ack);
- if (ack == A2DP_CTRL_ACK_INCALL_FAILURE) return ack;
+ if (ack == A2DP_CTRL_ACK_INCALL_FAILURE) {
+ ERROR("A2DP COMMAND %s error %d", audio_a2dp_hw_dump_ctrl_event(cmd), ack);
+ return ack;
+ }
if (ack != A2DP_CTRL_ACK_SUCCESS) {
ERROR("A2DP COMMAND %s error %d", audio_a2dp_hw_dump_ctrl_event(cmd), ack);
return -1;
@@ -591,27 +608,43 @@
switch (codec_config->channel_mode) {
case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
stream_config.channel_mask = AUDIO_CHANNEL_OUT_MONO;
+ stream_config.is_stereo_to_mono = true;
break;
case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
stream_config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ stream_config.is_stereo_to_mono = false;
break;
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
default:
ERROR("Invalid channel mode: 0x%x", codec_config->channel_mode);
return -1;
}
+ if (stream_config.is_stereo_to_mono) {
+ stream_config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ }
// Update the output stream configuration
if (update_stream_config) {
common->cfg.rate = stream_config.rate;
common->cfg.channel_mask = stream_config.channel_mask;
+ common->cfg.is_stereo_to_mono = stream_config.is_stereo_to_mono;
common->cfg.format = stream_config.format;
common->buffer_sz = audio_a2dp_hw_stream_compute_buffer_size(
codec_config->sample_rate, codec_config->bits_per_sample,
codec_config->channel_mode);
+ if (common->cfg.is_stereo_to_mono) {
+ // We need to fetch twice as much data from the Audio framework
+ common->buffer_sz *= 2;
+ }
}
INFO(
+ "got output codec config (update_stream_config=%s): "
+ "sample_rate=0x%x bits_per_sample=0x%x channel_mode=0x%x",
+ update_stream_config ? "true" : "false", codec_config->sample_rate,
+ codec_config->bits_per_sample, codec_config->channel_mode);
+
+ INFO(
"got output codec capability: sample_rate=0x%x bits_per_sample=0x%x "
"channel_mode=0x%x",
codec_capability->sample_rate, codec_capability->bits_per_sample,
@@ -679,7 +712,11 @@
codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
break;
case AUDIO_CHANNEL_OUT_STEREO:
- codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ if (common->cfg.is_stereo_to_mono) {
+ codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+ } else {
+ codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
break;
default:
ERROR("Invalid channel mask: 0x%x", common->cfg.channel_mask);
@@ -708,6 +745,41 @@
return 0;
}
+static int a2dp_get_presentation_position_cmd(struct a2dp_stream_common* common,
+ uint64_t* bytes, uint16_t* delay,
+ struct timespec* timestamp) {
+ if ((common->ctrl_fd == AUDIO_SKT_DISCONNECTED) ||
+ (common->state != AUDIO_A2DP_STATE_STARTED)) { // Audio is not streaming
+ return -1;
+ }
+
+ if (a2dp_command(common, A2DP_CTRL_GET_PRESENTATION_POSITION) < 0) {
+ return -1;
+ }
+
+ if (a2dp_ctrl_receive(common, bytes, sizeof(*bytes)) < 0) {
+ return -1;
+ }
+
+ if (a2dp_ctrl_receive(common, delay, sizeof(*delay)) < 0) {
+ return -1;
+ }
+
+ uint32_t seconds;
+ if (a2dp_ctrl_receive(common, &seconds, sizeof(seconds)) < 0) {
+ return -1;
+ }
+
+ uint32_t nsec;
+ if (a2dp_ctrl_receive(common, &nsec, sizeof(nsec)) < 0) {
+ return -1;
+ }
+
+ timestamp->tv_sec = seconds;
+ timestamp->tv_nsec = nsec;
+ return 0;
+}
+
static void a2dp_open_ctrl_path(struct a2dp_stream_common* common) {
int i;
@@ -782,6 +854,10 @@
}
}
common->state = (a2dp_state_t)AUDIO_A2DP_STATE_STARTED;
+
+ /* check to see if delay reporting is enabled */
+ enable_delay_reporting = delay_reporting_enabled();
+
return 0;
error:
@@ -844,6 +920,7 @@
size_t bytes) {
struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
int sent = -1;
+ size_t write_bytes = bytes;
DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd);
@@ -865,8 +942,21 @@
goto finish;
}
+ // Mix the stereo into mono if necessary
+ if (out->common.cfg.is_stereo_to_mono) {
+ const size_t frames = bytes / audio_stream_out_frame_size(stream);
+ int16_t* src = (int16_t*)buffer;
+ int16_t* dst = (int16_t*)buffer;
+ for (size_t i = 0; i < frames; i++, dst++, src += 2) {
+ *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
+ }
+ write_bytes /= 2;
+ DEBUG("stereo-to-mono mixing: write %zu bytes (fd %d)", write_bytes,
+ out->common.audio_fd);
+ }
+
lock.unlock();
- sent = skt_write(out->common.audio_fd, buffer, bytes);
+ sent = skt_write(out->common.audio_fd, buffer, write_bytes);
lock.lock();
if (sent == -1) {
@@ -1251,17 +1341,44 @@
FNLOG();
if (stream == NULL || frames == NULL || timestamp == NULL) return -EINVAL;
- int ret = -EWOULDBLOCK;
std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
+
+ // bytes is the total number of bytes sent by the Bluetooth stack to a
+ // remote headset
+ uint64_t bytes = 0;
+
+ // delay_report is the audio delay from the remote headset receiving data to
+ // the headset playing sound in units of 1/10ms
+ uint16_t delay_report = 0;
+
+ // If for some reason getting a delay fails or delay reports are disabled,
+ // default to old delay
+ if (enable_delay_reporting &&
+ a2dp_get_presentation_position_cmd(&out->common, &bytes, &delay_report,
+ timestamp) == 0) {
+ uint64_t delay_ns = delay_report * DELAY_TO_NS;
+ if (delay_ns > MIN_DELAY_MS * MS_TO_NS &&
+ delay_ns < MAX_DELAY_MS * MS_TO_NS) {
+ *frames = bytes / audio_stream_out_frame_size(stream);
+
+ timestamp->tv_nsec += delay_ns;
+ if (timestamp->tv_nsec > 1 * SEC_TO_NS) {
+ timestamp->tv_sec++;
+ timestamp->tv_nsec -= SEC_TO_NS;
+ }
+ return 0;
+ }
+ }
+
uint64_t latency_frames =
(uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000;
if (out->frames_presented >= latency_frames) {
+ clock_gettime(CLOCK_MONOTONIC, timestamp);
*frames = out->frames_presented - latency_frames;
- clock_gettime(CLOCK_MONOTONIC,
- timestamp); // could also be associated with out_write().
- ret = 0;
+ return 0;
}
- return ret;
+
+ return -EWOULDBLOCK;
}
static int out_get_render_position(const struct audio_stream_out* stream,
diff --git a/audio_a2dp_hw/src/audio_a2dp_hw_utils.cc b/audio_a2dp_hw/src/audio_a2dp_hw_utils.cc
index 199b0f9..984e46b 100644
--- a/audio_a2dp_hw/src/audio_a2dp_hw_utils.cc
+++ b/audio_a2dp_hw/src/audio_a2dp_hw_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
******************************************************************************/
#include "audio_a2dp_hw.h"
+#include "osi/include/properties.h"
#define CASE_RETURN_STR(const) \
case const: \
@@ -33,9 +34,12 @@
CASE_RETURN_STR(A2DP_CTRL_GET_OUTPUT_AUDIO_CONFIG)
CASE_RETURN_STR(A2DP_CTRL_SET_OUTPUT_AUDIO_CONFIG)
CASE_RETURN_STR(A2DP_CTRL_CMD_OFFLOAD_START)
- default:
- break;
+ CASE_RETURN_STR(A2DP_CTRL_GET_PRESENTATION_POSITION)
}
return "UNKNOWN A2DP_CTRL_CMD";
}
+
+bool delay_reporting_enabled() {
+ return !osi_property_get_bool("persist.bluetooth.disabledelayreports", false);
+}
diff --git a/audio_a2dp_hw/test/audio_a2dp_hw_test.cc b/audio_a2dp_hw/test/audio_a2dp_hw_test.cc
index f2cefa8..8fcbae5 100644
--- a/audio_a2dp_hw/test/audio_a2dp_hw_test.cc
+++ b/audio_a2dp_hw/test/audio_a2dp_hw_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,10 @@
return 176400;
case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
return 192000;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ return 16000;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
+ return 24000;
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
break;
}
diff --git a/audio_hearing_aid_hw/Android.bp b/audio_hearing_aid_hw/Android.bp
new file mode 100644
index 0000000..229fc25
--- /dev/null
+++ b/audio_hearing_aid_hw/Android.bp
@@ -0,0 +1,51 @@
+cc_defaults {
+ name: "audio_hearing_aid_hw_defaults",
+ defaults: ["fluoride_defaults"],
+ include_dirs: [
+ "system/bt",
+ "system/bt/include",
+ "system/bt/audio_hearing_aid_hw/include",
+ ]
+}
+
+// Audio A2DP shared library for target
+// ========================================================
+cc_library {
+ name: "audio.hearing_aid.default",
+ defaults: ["audio_hearing_aid_hw_defaults"],
+ relative_install_path: "hw",
+ srcs: [
+ "src/audio_hearing_aid_hw.cc",
+ "src/audio_hearing_aid_hw_utils.cc",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ static_libs: ["libosi"],
+}
+
+cc_library_static {
+ name: "libaudio-hearing-aid-hw-utils",
+ defaults: ["audio_hearing_aid_hw_defaults"],
+ srcs: [
+ "src/audio_hearing_aid_hw_utils.cc",
+ ],
+}
+
+// Audio A2DP library unit tests for target and host
+// ========================================================
+cc_test {
+ name: "net_test_audio_hearing_aid_hw",
+ test_suites: ["device-tests"],
+ defaults: ["audio_hearing_aid_hw_defaults"],
+ srcs: [
+ "test/audio_hearing_aid_hw_test.cc",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ static_libs: [
+ "audio.hearing_aid.default",
+ "libosi",
+ ],
+}
diff --git a/audio_hearing_aid_hw/include/audio_hearing_aid_hw.h b/audio_hearing_aid_hw/include/audio_hearing_aid_hw.h
new file mode 100644
index 0000000..56d8576
--- /dev/null
+++ b/audio_hearing_aid_hw/include/audio_hearing_aid_hw.h
@@ -0,0 +1,150 @@
+/******************************************************************************
+ *
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename: audio_hearing_aid_hw.h
+ *
+ * Description:
+ *
+ *****************************************************************************/
+
+#ifndef AUDIO_HEARING_AID_HW_H
+#define AUDIO_HEARING_AID_HW_H
+
+#include <stdint.h>
+
+#include <hardware/bt_av.h>
+
+/*****************************************************************************
+ * Constants & Macros
+ *****************************************************************************/
+
+#define HEARING_AID_AUDIO_HARDWARE_INTERFACE "audio.hearing_aid"
+#define HEARING_AID_CTRL_PATH "/data/misc/bluedroid/.hearing_aid_ctrl"
+#define HEARING_AID_DATA_PATH "/data/misc/bluedroid/.hearing_aid_data"
+
+// AUDIO_STREAM_OUTPUT_BUFFER_SZ controls the size of the audio socket buffer.
+// If one assumes the write buffer is always full during normal BT playback,
+// then increasing this value increases our playback latency.
+//
+// FIXME: The BT HAL should consume data at a constant rate.
+// AudioFlinger assumes that the HAL draws data at a constant rate, which is
+// true for most audio devices; however, the BT engine reads data at a variable
+// rate (over the short term), which confuses both AudioFlinger as well as
+// applications which deliver data at a (generally) fixed rate.
+//
+// 20 * 512 is not sufficient to smooth the variability for some BT devices,
+// resulting in mixer sleep and throttling. We increase this to 28 * 512 to help
+// reduce the effect of variable data consumption.
+#define AUDIO_STREAM_OUTPUT_BUFFER_SZ (28 * 512)
+#define AUDIO_STREAM_CONTROL_OUTPUT_BUFFER_SZ 256
+
+// AUDIO_STREAM_OUTPUT_BUFFER_PERIODS controls how the socket buffer is divided
+// for AudioFlinger data delivery. The AudioFlinger mixer delivers data in
+// chunks of AUDIO_STREAM_OUTPUT_BUFFER_SZ / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS.
+// If the number of periods is 2, the socket buffer represents "double
+// buffering" of the AudioFlinger mixer buffer.
+//
+// In general, AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * 16 * 4 should be a divisor
+// of AUDIO_STREAM_OUTPUT_BUFFER_SZ.
+//
+// These values should be chosen such that
+//
+// AUDIO_STREAM_BUFFER_SIZE * 1000 / (AUDIO_STREAM_OUTPUT_BUFFER_PERIODS
+// * AUDIO_STREAM_DEFAULT_RATE * 4) > 20 (ms)
+//
+// to avoid introducing the FastMixer in AudioFlinger. Using the FastMixer
+// results in unnecessary latency and CPU overhead for Bluetooth.
+#define AUDIO_STREAM_OUTPUT_BUFFER_PERIODS 2
+
+#define AUDIO_SKT_DISCONNECTED (-1)
+
+typedef enum {
+ HEARING_AID_CTRL_CMD_NONE,
+ HEARING_AID_CTRL_CMD_CHECK_READY,
+ HEARING_AID_CTRL_CMD_START,
+ HEARING_AID_CTRL_CMD_STOP,
+ HEARING_AID_CTRL_CMD_SUSPEND,
+ HEARING_AID_CTRL_GET_INPUT_AUDIO_CONFIG,
+ HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG,
+ HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG,
+ HEARING_AID_CTRL_CMD_OFFLOAD_START,
+} tHEARING_AID_CTRL_CMD;
+
+typedef enum {
+ HEARING_AID_CTRL_ACK_SUCCESS,
+ HEARING_AID_CTRL_ACK_FAILURE,
+ HEARING_AID_CTRL_ACK_INCALL_FAILURE, /* Failure when in Call*/
+ HEARING_AID_CTRL_ACK_UNSUPPORTED
+} tHEARING_AID_CTRL_ACK;
+
+typedef uint32_t tHA_SAMPLE_RATE;
+typedef uint8_t tHA_CHANNEL_COUNT;
+
+/*****************************************************************************
+ * Type definitions for callback functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Type definitions and return values
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Extern variables and functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Functions
+ *****************************************************************************/
+
+// Computes the Audio Hearing Aid HAL output buffer size.
+// |codec_sample_rate| is the sample rate of the output stream.
+// |codec_bits_per_sample| is the number of bits per sample of the output
+// stream.
+// |codec_channel_mode| is the channel mode of the output stream.
+//
+// The buffer size is computed by using the following formula:
+//
+// AUDIO_STREAM_OUTPUT_BUFFER_SIZE =
+// (TIME_PERIOD_MS * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS *
+// SAMPLE_RATE_HZ * NUMBER_OF_CHANNELS * (BITS_PER_SAMPLE / 8)) / 1000
+//
+// AUDIO_STREAM_OUTPUT_BUFFER_PERIODS controls how the socket buffer is
+// divided for AudioFlinger data delivery. The AudioFlinger mixer delivers
+// data in chunks of
+// (AUDIO_STREAM_OUTPUT_BUFFER_SIZE / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS) .
+// If the number of periods is 2, the socket buffer represents "double
+// buffering" of the AudioFlinger mixer buffer.
+//
+// Furthermore, the AudioFlinger expects the buffer size to be a multiple
+// of 16 frames.
+//
+// NOTE: Currently, the computation uses the conservative 20ms time period.
+//
+// Returns the computed buffer size. If any of the input parameters is
+// invalid, the return value is the default |AUDIO_STREAM_OUTPUT_BUFFER_SZ|.
+extern size_t audio_ha_hw_stream_compute_buffer_size(
+ btav_a2dp_codec_sample_rate_t codec_sample_rate,
+ btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample,
+ btav_a2dp_codec_channel_mode_t codec_channel_mode);
+
+// Returns a string representation of |event|.
+extern const char* audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event);
+
+#endif /* AUDIO_HEARING_AID_HW_H */
diff --git a/audio_hearing_aid_hw/src/audio_hearing_aid_hw.cc b/audio_hearing_aid_hw/src/audio_hearing_aid_hw.cc
new file mode 100644
index 0000000..f3f535e
--- /dev/null
+++ b/audio_hearing_aid_hw/src/audio_hearing_aid_hw.cc
@@ -0,0 +1,1889 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/* Implements hal for bluedroid ha audio device */
+
+#define LOG_TAG "bt_hearing_aid_hw"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <mutex>
+
+#include <hardware/audio.h>
+#include <hardware/hardware.h>
+#include <system/audio.h>
+
+#include "osi/include/hash_map_utils.h"
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+#include "osi/include/socket_utils/sockets.h"
+
+#include "audio_hearing_aid_hw.h"
+
+/*****************************************************************************
+ * Constants & Macros
+ *****************************************************************************/
+
+#define CTRL_CHAN_RETRY_COUNT 3
+#define USEC_PER_SEC 1000000L
+#define SOCK_SEND_TIMEOUT_MS 2000 /* Timeout for sending */
+#define SOCK_RECV_TIMEOUT_MS 5000 /* Timeout for receiving */
+
+// set WRITE_POLL_MS to 0 for blocking sockets, nonzero for polled non-blocking
+// sockets
+#define WRITE_POLL_MS 20
+
+#define FNLOG() LOG_VERBOSE(LOG_TAG, "%s", __func__);
+#define DEBUG(fmt, ...) \
+ LOG_VERBOSE(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
+#define INFO(fmt, ...) LOG_INFO(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
+#define WARN(fmt, ...) LOG_WARN(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
+#define ERROR(fmt, ...) LOG_ERROR(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
+
+#define ASSERTC(cond, msg, val) \
+ if (!(cond)) { \
+ ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, \
+ val); \
+ }
+
+/*****************************************************************************
+ * Local type definitions
+ *****************************************************************************/
+
+typedef enum {
+ AUDIO_HA_STATE_STARTING,
+ AUDIO_HA_STATE_STARTED,
+ AUDIO_HA_STATE_STOPPING,
+ AUDIO_HA_STATE_STOPPED,
+ /* need explicit set param call to resume (suspend=false) */
+ AUDIO_HA_STATE_SUSPENDED,
+ AUDIO_HA_STATE_STANDBY /* allows write to autoresume */
+} ha_state_t;
+
+struct ha_stream_in;
+struct ha_stream_out;
+
+struct ha_audio_device {
+ // Important: device must be first as an audio_hw_device* may be cast to
+ // ha_audio_device* when the type is implicitly known.
+ struct audio_hw_device device;
+ std::recursive_mutex* mutex; // See note below on mutex acquisition order.
+ struct ha_stream_in* input;
+ struct ha_stream_out* output;
+};
+
+struct ha_config {
+ uint32_t rate;
+ uint32_t channel_mask;
+ bool is_stereo_to_mono; // True if fetching Stereo and mixing into Mono
+ int format;
+};
+
+/* move ctrl_fd outside output stream and keep open until HAL unloaded ? */
+
+struct ha_stream_common {
+ std::recursive_mutex* mutex; // See note below on mutex acquisition order.
+ int ctrl_fd;
+ int audio_fd;
+ size_t buffer_sz;
+ struct ha_config cfg;
+ ha_state_t state;
+};
+
+struct ha_stream_out {
+ struct audio_stream_out stream;
+ struct ha_stream_common common;
+ uint64_t frames_presented; // frames written, never reset
+ uint64_t frames_rendered; // frames written, reset on standby
+};
+
+struct ha_stream_in {
+ struct audio_stream_in stream;
+ struct ha_stream_common common;
+};
+
+/*
+ * Mutex acquisition order:
+ *
+ * The ha_audio_device (adev) mutex must be acquired before
+ * the ha_stream_common (out or in) mutex.
+ *
+ * This may differ from other audio HALs.
+ */
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static functions
+ *****************************************************************************/
+
+static size_t out_get_buffer_size(const struct audio_stream* stream);
+
+/*****************************************************************************
+ * Externs
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Functions
+ *****************************************************************************/
+static void ha_open_ctrl_path(struct ha_stream_common* common);
+
+/*****************************************************************************
+ * Miscellaneous helper functions
+ *****************************************************************************/
+
+/* logs timestamp with microsec precision
+ pprev is optional in case a dedicated diff is required */
+static void ts_log(UNUSED_ATTR const char* tag, UNUSED_ATTR int val,
+ struct timespec* pprev_opt) {
+ struct timespec now;
+ static struct timespec prev = {0, 0};
+ unsigned long long now_us;
+ unsigned long long diff_us;
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ now_us = now.tv_sec * USEC_PER_SEC + now.tv_nsec / 1000;
+
+ if (pprev_opt) {
+ diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC +
+ (now.tv_nsec - prev.tv_nsec) / 1000;
+ *pprev_opt = now;
+ DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val);
+ } else {
+ diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC +
+ (now.tv_nsec - prev.tv_nsec) / 1000;
+ prev = now;
+ DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val);
+ }
+}
+
+static int calc_audiotime_usec(struct ha_config cfg, int bytes) {
+ int chan_count = audio_channel_count_from_out_mask(cfg.channel_mask);
+ int bytes_per_sample;
+
+ switch (cfg.format) {
+ case AUDIO_FORMAT_PCM_8_BIT:
+ bytes_per_sample = 1;
+ break;
+ case AUDIO_FORMAT_PCM_16_BIT:
+ bytes_per_sample = 2;
+ break;
+ case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+ bytes_per_sample = 3;
+ break;
+ case AUDIO_FORMAT_PCM_8_24_BIT:
+ bytes_per_sample = 4;
+ break;
+ case AUDIO_FORMAT_PCM_32_BIT:
+ bytes_per_sample = 4;
+ break;
+ default:
+ ASSERTC(false, "unsupported sample format", cfg.format);
+ bytes_per_sample = 2;
+ break;
+ }
+
+ return (
+ int)(((int64_t)bytes * (USEC_PER_SEC / (chan_count * bytes_per_sample))) /
+ cfg.rate);
+}
+
+/*****************************************************************************
+ *
+ * bluedroid stack adaptation
+ *
+ ****************************************************************************/
+
+static int skt_connect(const char* path, size_t buffer_sz) {
+ int ret;
+ int skt_fd;
+ int len;
+
+ INFO("connect to %s (sz %zu)", path, buffer_sz);
+
+ skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+
+ if (osi_socket_local_client_connect(
+ skt_fd, path, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0) {
+ ERROR("failed to connect (%s)", strerror(errno));
+ close(skt_fd);
+ return -1;
+ }
+
+ len = buffer_sz;
+ ret =
+ setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len));
+ if (ret < 0) ERROR("setsockopt failed (%s)", strerror(errno));
+
+ ret =
+ setsockopt(skt_fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, (int)sizeof(len));
+ if (ret < 0) ERROR("setsockopt failed (%s)", strerror(errno));
+
+ /* Socket send/receive timeout value */
+ struct timeval tv;
+ tv.tv_sec = SOCK_SEND_TIMEOUT_MS / 1000;
+ tv.tv_usec = (SOCK_SEND_TIMEOUT_MS % 1000) * 1000;
+
+ ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+ if (ret < 0) ERROR("setsockopt failed (%s)", strerror(errno));
+
+ tv.tv_sec = SOCK_RECV_TIMEOUT_MS / 1000;
+ tv.tv_usec = (SOCK_RECV_TIMEOUT_MS % 1000) * 1000;
+
+ ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+ if (ret < 0) ERROR("setsockopt failed (%s)", strerror(errno));
+
+ INFO("connected to stack fd = %d", skt_fd);
+
+ return skt_fd;
+}
+
+static int skt_read(int fd, void* p, size_t len) {
+ ssize_t read;
+
+ FNLOG();
+
+ ts_log("skt_read recv", len, NULL);
+
+ OSI_NO_INTR(read = recv(fd, p, len, MSG_NOSIGNAL));
+ if (read == -1) ERROR("read failed with errno=%d\n", errno);
+
+ return (int)read;
+}
+
+static int skt_write(int fd, const void* p, size_t len) {
+ ssize_t sent;
+ FNLOG();
+
+ ts_log("skt_write", len, NULL);
+
+ if (WRITE_POLL_MS == 0) {
+ // do not poll, use blocking send
+ OSI_NO_INTR(sent = send(fd, p, len, MSG_NOSIGNAL));
+ if (sent == -1) ERROR("write failed with error(%s)", strerror(errno));
+
+ return (int)sent;
+ }
+
+ // use non-blocking send, poll
+ int ms_timeout = SOCK_SEND_TIMEOUT_MS;
+ size_t count = 0;
+ while (count < len) {
+ OSI_NO_INTR(sent = send(fd, p, len - count, MSG_NOSIGNAL | MSG_DONTWAIT));
+ if (sent == -1) {
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
+ ERROR("write failed with error(%s)", strerror(errno));
+ return -1;
+ }
+ if (ms_timeout >= WRITE_POLL_MS) {
+ usleep(WRITE_POLL_MS * 1000);
+ ms_timeout -= WRITE_POLL_MS;
+ continue;
+ }
+ WARN("write timeout exceeded, sent %zu bytes", count);
+ return -1;
+ }
+ count += sent;
+ p = (const uint8_t*)p + sent;
+ }
+ return (int)count;
+}
+
+static int skt_disconnect(int fd) {
+ INFO("fd %d", fd);
+
+ if (fd != AUDIO_SKT_DISCONNECTED) {
+ shutdown(fd, SHUT_RDWR);
+ close(fd);
+ }
+ return 0;
+}
+
+/*****************************************************************************
+ *
+ * AUDIO CONTROL PATH
+ *
+ ****************************************************************************/
+
+static int ha_ctrl_receive(struct ha_stream_common* common, void* buffer,
+ size_t length) {
+ ssize_t ret;
+ int i;
+
+ for (i = 0;; i++) {
+ OSI_NO_INTR(ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL));
+ if (ret > 0) {
+ break;
+ }
+ if (ret == 0) {
+ ERROR("receive control data failed: peer closed");
+ break;
+ }
+ if (errno != EWOULDBLOCK && errno != EAGAIN) {
+ ERROR("receive control data failed: error(%s)", strerror(errno));
+ break;
+ }
+ if (i == (CTRL_CHAN_RETRY_COUNT - 1)) {
+ ERROR("receive control data failed: max retry count");
+ break;
+ }
+ INFO("receive control data failed (%s), retrying", strerror(errno));
+ }
+ if (ret <= 0) {
+ skt_disconnect(common->ctrl_fd);
+ common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+ }
+ return ret;
+}
+
+// Sends control info for stream |common|. The data to send is stored in
+// |buffer| and has size |length|.
+// On success, returns the number of octets sent, otherwise -1.
+static int ha_ctrl_send(struct ha_stream_common* common, const void* buffer,
+ size_t length) {
+ ssize_t sent;
+ size_t remaining = length;
+ int i;
+
+ if (length == 0) return 0; // Nothing to do
+
+ for (i = 0;; i++) {
+ OSI_NO_INTR(sent = send(common->ctrl_fd, buffer, remaining, MSG_NOSIGNAL));
+ if (sent == static_cast<ssize_t>(remaining)) {
+ remaining = 0;
+ break;
+ }
+ if (sent > 0) {
+ buffer = (static_cast<const char*>(buffer) + sent);
+ remaining -= sent;
+ continue;
+ }
+ if (sent < 0) {
+ if (errno != EWOULDBLOCK && errno != EAGAIN) {
+ ERROR("send control data failed: error(%s)", strerror(errno));
+ break;
+ }
+ INFO("send control data failed (%s), retrying", strerror(errno));
+ }
+ if (i >= (CTRL_CHAN_RETRY_COUNT - 1)) {
+ ERROR("send control data failed: max retry count");
+ break;
+ }
+ }
+ if (remaining > 0) {
+ skt_disconnect(common->ctrl_fd);
+ common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+ return -1;
+ }
+ return length;
+}
+
+static int ha_command(struct ha_stream_common* common,
+ tHEARING_AID_CTRL_CMD cmd) {
+ char ack;
+
+ DEBUG("HEARING_AID COMMAND %s", audio_ha_hw_dump_ctrl_event(cmd));
+
+ if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
+ INFO("starting up or recovering from previous error");
+ ha_open_ctrl_path(common);
+ if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
+ ERROR("failure to open ctrl path");
+ return -1;
+ }
+ }
+
+ /* send command */
+ ssize_t sent;
+ OSI_NO_INTR(sent = send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL));
+ if (sent == -1) {
+ ERROR("cmd failed (%s)", strerror(errno));
+ skt_disconnect(common->ctrl_fd);
+ common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+ return -1;
+ }
+
+ /* wait for ack byte */
+ if (ha_ctrl_receive(common, &ack, 1) < 0) {
+ ERROR("HEARING_AID COMMAND %s: no ACK", audio_ha_hw_dump_ctrl_event(cmd));
+ return -1;
+ }
+
+ DEBUG("HEARING_AID COMMAND %s DONE STATUS %d",
+ audio_ha_hw_dump_ctrl_event(cmd), ack);
+
+ if (ack == HEARING_AID_CTRL_ACK_INCALL_FAILURE) return ack;
+ if (ack != HEARING_AID_CTRL_ACK_SUCCESS) {
+ ERROR("HEARING_AID COMMAND %s error %d", audio_ha_hw_dump_ctrl_event(cmd),
+ ack);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int check_ha_ready(struct ha_stream_common* common) {
+ if (ha_command(common, HEARING_AID_CTRL_CMD_CHECK_READY) < 0) {
+ ERROR("check ha ready failed");
+ return -1;
+ }
+ return 0;
+}
+
+static int ha_read_input_audio_config(struct ha_stream_common* common) {
+ tHA_SAMPLE_RATE sample_rate;
+ tHA_CHANNEL_COUNT channel_count;
+
+ if (ha_command(common, HEARING_AID_CTRL_GET_INPUT_AUDIO_CONFIG) < 0) {
+ ERROR("get ha input audio config failed");
+ return -1;
+ }
+
+ if (ha_ctrl_receive(common, &sample_rate, sizeof(tHA_SAMPLE_RATE)) < 0)
+ return -1;
+ if (ha_ctrl_receive(common, &channel_count, sizeof(tHA_CHANNEL_COUNT)) < 0) {
+ return -1;
+ }
+
+ switch (sample_rate) {
+ case 16000:
+ case 24000:
+ case 44100:
+ case 48000:
+ common->cfg.rate = sample_rate;
+ break;
+ default:
+ ERROR("Invalid sample rate: %" PRIu32, sample_rate);
+ return -1;
+ }
+
+ switch (channel_count) {
+ case 1:
+ common->cfg.channel_mask = AUDIO_CHANNEL_IN_MONO;
+ break;
+ case 2:
+ common->cfg.channel_mask = AUDIO_CHANNEL_IN_STEREO;
+ break;
+ default:
+ ERROR("Invalid channel count: %" PRIu32, channel_count);
+ return -1;
+ }
+
+ // TODO: For now input audio format is always hard-coded as PCM 16-bit
+ common->cfg.format = AUDIO_FORMAT_PCM_16_BIT;
+
+ INFO("got input audio config %d %d", common->cfg.format, common->cfg.rate);
+
+ return 0;
+}
+
+static int ha_read_output_audio_config(
+ struct ha_stream_common* common, btav_a2dp_codec_config_t* codec_config,
+ btav_a2dp_codec_config_t* codec_capability, bool update_stream_config) {
+ struct ha_config stream_config;
+
+ if (ha_command(common, HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG) < 0) {
+ ERROR("get ha output audio config failed");
+ return -1;
+ }
+
+ // Receive the current codec config
+ if (ha_ctrl_receive(common, &codec_config->sample_rate,
+ sizeof(btav_a2dp_codec_sample_rate_t)) < 0) {
+ return -1;
+ }
+ if (ha_ctrl_receive(common, &codec_config->bits_per_sample,
+ sizeof(btav_a2dp_codec_bits_per_sample_t)) < 0) {
+ return -1;
+ }
+ if (ha_ctrl_receive(common, &codec_config->channel_mode,
+ sizeof(btav_a2dp_codec_channel_mode_t)) < 0) {
+ return -1;
+ }
+
+ // Receive the current codec capability
+ if (ha_ctrl_receive(common, &codec_capability->sample_rate,
+ sizeof(btav_a2dp_codec_sample_rate_t)) < 0) {
+ return -1;
+ }
+ if (ha_ctrl_receive(common, &codec_capability->bits_per_sample,
+ sizeof(btav_a2dp_codec_bits_per_sample_t)) < 0) {
+ return -1;
+ }
+ if (ha_ctrl_receive(common, &codec_capability->channel_mode,
+ sizeof(btav_a2dp_codec_channel_mode_t)) < 0) {
+ return -1;
+ }
+
+ // Check the codec config sample rate
+ switch (codec_config->sample_rate) {
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
+ stream_config.rate = 44100;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_48000:
+ stream_config.rate = 48000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_88200:
+ stream_config.rate = 88200;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
+ stream_config.rate = 96000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
+ stream_config.rate = 176400;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ stream_config.rate = 192000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ stream_config.rate = 16000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
+ stream_config.rate = 24000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
+ default:
+ ERROR("Invalid sample rate: 0x%x", codec_config->sample_rate);
+ return -1;
+ }
+
+ // Check the codec config bits per sample
+ switch (codec_config->bits_per_sample) {
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
+ stream_config.format = AUDIO_FORMAT_PCM_16_BIT;
+ break;
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
+ stream_config.format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ break;
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
+ stream_config.format = AUDIO_FORMAT_PCM_32_BIT;
+ break;
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE:
+ default:
+ ERROR("Invalid bits per sample: 0x%x", codec_config->bits_per_sample);
+ return -1;
+ }
+
+ // Check the codec config channel mode
+ switch (codec_config->channel_mode) {
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
+ stream_config.channel_mask = AUDIO_CHANNEL_OUT_MONO;
+ stream_config.is_stereo_to_mono = true;
+ break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
+ stream_config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ stream_config.is_stereo_to_mono = false;
+ break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
+ default:
+ ERROR("Invalid channel mode: 0x%x", codec_config->channel_mode);
+ return -1;
+ }
+ if (stream_config.is_stereo_to_mono) {
+ stream_config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ }
+
+ // Update the output stream configuration
+ if (update_stream_config) {
+ common->cfg.rate = stream_config.rate;
+ common->cfg.channel_mask = stream_config.channel_mask;
+ common->cfg.is_stereo_to_mono = stream_config.is_stereo_to_mono;
+ common->cfg.format = stream_config.format;
+ common->buffer_sz = audio_ha_hw_stream_compute_buffer_size(
+ codec_config->sample_rate, codec_config->bits_per_sample,
+ codec_config->channel_mode);
+ if (common->cfg.is_stereo_to_mono) {
+ // We need to fetch twice as much data from the Audio framework
+ common->buffer_sz *= 2;
+ }
+ }
+
+ INFO(
+ "got output codec config (update_stream_config=%s): "
+ "sample_rate=0x%x bits_per_sample=0x%x channel_mode=0x%x",
+ update_stream_config ? "true" : "false", codec_config->sample_rate,
+ codec_config->bits_per_sample, codec_config->channel_mode);
+
+ INFO(
+ "got output codec capability: sample_rate=0x%x bits_per_sample=0x%x "
+ "channel_mode=0x%x",
+ codec_capability->sample_rate, codec_capability->bits_per_sample,
+ codec_capability->channel_mode);
+
+ return 0;
+}
+
+static int ha_write_output_audio_config(struct ha_stream_common* common) {
+ btav_a2dp_codec_config_t codec_config;
+
+ if (ha_command(common, HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG) < 0) {
+ ERROR("set ha output audio config failed");
+ return -1;
+ }
+
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
+ codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE;
+ codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
+
+ switch (common->cfg.rate) {
+ case 44100:
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+ break;
+ case 48000:
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+ break;
+ case 88200:
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
+ break;
+ case 96000:
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
+ break;
+ case 176400:
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_176400;
+ break;
+ case 192000:
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_192000;
+ break;
+ case 16000:
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_16000;
+ break;
+ case 24000:
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_24000;
+ break;
+ default:
+ ERROR("Invalid sample rate: %" PRIu32, common->cfg.rate);
+ return -1;
+ }
+
+ switch (common->cfg.format) {
+ case AUDIO_FORMAT_PCM_16_BIT:
+ codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
+ break;
+ case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+ codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24;
+ break;
+ case AUDIO_FORMAT_PCM_32_BIT:
+ codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32;
+ break;
+ case AUDIO_FORMAT_PCM_8_24_BIT:
+ // FALLTHROUGH
+ // All 24-bit audio is expected in AUDIO_FORMAT_PCM_24_BIT_PACKED format
+ default:
+ ERROR("Invalid audio format: 0x%x", common->cfg.format);
+ return -1;
+ }
+
+ switch (common->cfg.channel_mask) {
+ case AUDIO_CHANNEL_OUT_MONO:
+ codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+ break;
+ case AUDIO_CHANNEL_OUT_STEREO:
+ if (common->cfg.is_stereo_to_mono) {
+ codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+ } else {
+ codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
+ break;
+ default:
+ ERROR("Invalid channel mask: 0x%x", common->cfg.channel_mask);
+ return -1;
+ }
+
+ // Send the current codec config that has been selected by us
+ if (ha_ctrl_send(common, &codec_config.sample_rate,
+ sizeof(btav_a2dp_codec_sample_rate_t)) < 0)
+ return -1;
+ if (ha_ctrl_send(common, &codec_config.bits_per_sample,
+ sizeof(btav_a2dp_codec_bits_per_sample_t)) < 0) {
+ return -1;
+ }
+ if (ha_ctrl_send(common, &codec_config.channel_mode,
+ sizeof(btav_a2dp_codec_channel_mode_t)) < 0) {
+ return -1;
+ }
+
+ INFO(
+ "sent output codec config: sample_rate=0x%x bits_per_sample=0x%x "
+ "channel_mode=0x%x",
+ codec_config.sample_rate, codec_config.bits_per_sample,
+ codec_config.channel_mode);
+
+ return 0;
+}
+
+static void ha_open_ctrl_path(struct ha_stream_common* common) {
+ int i;
+
+ if (common->ctrl_fd != AUDIO_SKT_DISCONNECTED) return; // already connected
+
+ /* retry logic to catch any timing variations on control channel */
+ for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++) {
+ /* connect control channel if not already connected */
+ if ((common->ctrl_fd = skt_connect(
+ HEARING_AID_CTRL_PATH, AUDIO_STREAM_CONTROL_OUTPUT_BUFFER_SZ)) >=
+ 0) {
+ /* success, now check if stack is ready */
+ if (check_ha_ready(common) == 0) break;
+
+ ERROR("error : ha not ready, wait 250 ms and retry");
+ usleep(250000);
+ skt_disconnect(common->ctrl_fd);
+ common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+ }
+
+ /* ctrl channel not ready, wait a bit */
+ usleep(250000);
+ }
+}
+
+/*****************************************************************************
+ *
+ * AUDIO DATA PATH
+ *
+ ****************************************************************************/
+
+static void ha_stream_common_init(struct ha_stream_common* common) {
+ FNLOG();
+
+ common->mutex = new std::recursive_mutex;
+
+ common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+ common->audio_fd = AUDIO_SKT_DISCONNECTED;
+ common->state = AUDIO_HA_STATE_STOPPED;
+
+ /* manages max capacity of socket pipe */
+ common->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
+}
+
+static void ha_stream_common_destroy(struct ha_stream_common* common) {
+ FNLOG();
+
+ delete common->mutex;
+ common->mutex = NULL;
+}
+
+static int start_audio_datapath(struct ha_stream_common* common) {
+ INFO("state %d", common->state);
+
+ int oldstate = common->state;
+ common->state = AUDIO_HA_STATE_STARTING;
+
+ int ha_status = ha_command(common, HEARING_AID_CTRL_CMD_START);
+ if (ha_status < 0) {
+ ERROR("Audiopath start failed (status %d)", ha_status);
+ goto error;
+ } else if (ha_status == HEARING_AID_CTRL_ACK_INCALL_FAILURE) {
+ ERROR("Audiopath start failed - in call, move to suspended");
+ goto error;
+ }
+
+ /* connect socket if not yet connected */
+ if (common->audio_fd == AUDIO_SKT_DISCONNECTED) {
+ common->audio_fd = skt_connect(HEARING_AID_DATA_PATH, common->buffer_sz);
+ if (common->audio_fd < 0) {
+ ERROR("Audiopath start failed - error opening data socket");
+ goto error;
+ }
+ }
+ common->state = (ha_state_t)AUDIO_HA_STATE_STARTED;
+ return 0;
+
+error:
+ common->state = (ha_state_t)oldstate;
+ return -1;
+}
+
+static int stop_audio_datapath(struct ha_stream_common* common) {
+ int oldstate = common->state;
+
+ INFO("state %d", common->state);
+
+ /* prevent any stray output writes from autostarting the stream
+ while stopping audiopath */
+ common->state = AUDIO_HA_STATE_STOPPING;
+
+ if (ha_command(common, HEARING_AID_CTRL_CMD_STOP) < 0) {
+ ERROR("audiopath stop failed");
+ common->state = (ha_state_t)oldstate;
+ return -1;
+ }
+
+ common->state = (ha_state_t)AUDIO_HA_STATE_STOPPED;
+
+ /* disconnect audio path */
+ skt_disconnect(common->audio_fd);
+ common->audio_fd = AUDIO_SKT_DISCONNECTED;
+
+ return 0;
+}
+
+static int suspend_audio_datapath(struct ha_stream_common* common,
+ bool standby) {
+ INFO("state %d", common->state);
+
+ if (common->state == AUDIO_HA_STATE_STOPPING) return -1;
+
+ if (ha_command(common, HEARING_AID_CTRL_CMD_SUSPEND) < 0) return -1;
+
+ if (standby)
+ common->state = AUDIO_HA_STATE_STANDBY;
+ else
+ common->state = AUDIO_HA_STATE_SUSPENDED;
+
+ /* disconnect audio path */
+ skt_disconnect(common->audio_fd);
+
+ common->audio_fd = AUDIO_SKT_DISCONNECTED;
+
+ return 0;
+}
+
+/*****************************************************************************
+ *
+ * audio output callbacks
+ *
+ ****************************************************************************/
+
+static ssize_t out_write(struct audio_stream_out* stream, const void* buffer,
+ size_t bytes) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+ int sent = -1;
+ size_t write_bytes = bytes;
+
+ DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd);
+
+ std::unique_lock<std::recursive_mutex> lock(*out->common.mutex);
+ if (out->common.state == AUDIO_HA_STATE_SUSPENDED ||
+ out->common.state == AUDIO_HA_STATE_STOPPING) {
+ DEBUG("stream suspended or closing");
+ goto finish;
+ }
+
+ /* only allow autostarting if we are in stopped or standby */
+ if ((out->common.state == AUDIO_HA_STATE_STOPPED) ||
+ (out->common.state == AUDIO_HA_STATE_STANDBY)) {
+ if (start_audio_datapath(&out->common) < 0) {
+ goto finish;
+ }
+ } else if (out->common.state != AUDIO_HA_STATE_STARTED) {
+ ERROR("stream not in stopped or standby");
+ goto finish;
+ }
+
+ // Mix the stereo into mono if necessary
+ if (out->common.cfg.is_stereo_to_mono) {
+ const size_t frames = bytes / audio_stream_out_frame_size(stream);
+ int16_t* src = (int16_t*)buffer;
+ int16_t* dst = (int16_t*)buffer;
+ for (size_t i = 0; i < frames; i++, dst++, src += 2) {
+ *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
+ }
+ write_bytes /= 2;
+ DEBUG("stereo-to-mono mixing: write %zu bytes (fd %d)", write_bytes,
+ out->common.audio_fd);
+ }
+
+ lock.unlock();
+ sent = skt_write(out->common.audio_fd, buffer, write_bytes);
+ lock.lock();
+
+ if (sent == -1) {
+ skt_disconnect(out->common.audio_fd);
+ out->common.audio_fd = AUDIO_SKT_DISCONNECTED;
+ if ((out->common.state != AUDIO_HA_STATE_SUSPENDED) &&
+ (out->common.state != AUDIO_HA_STATE_STOPPING)) {
+ out->common.state = AUDIO_HA_STATE_STOPPED;
+ } else {
+ ERROR("write failed : stream suspended, avoid resetting state");
+ }
+ goto finish;
+ }
+
+finish:;
+ const size_t frames = bytes / audio_stream_out_frame_size(stream);
+ out->frames_rendered += frames;
+ out->frames_presented += frames;
+ lock.unlock();
+
+ // If send didn't work out, sleep to emulate write delay.
+ if (sent == -1) {
+ const int us_delay = calc_audiotime_usec(out->common.cfg, bytes);
+ DEBUG("emulate ha write delay (%d us)", us_delay);
+ usleep(us_delay);
+ }
+ return bytes;
+}
+
+static uint32_t out_get_sample_rate(const struct audio_stream* stream) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+
+ DEBUG("rate %" PRIu32, out->common.cfg.rate);
+
+ return out->common.cfg.rate;
+}
+
+static int out_set_sample_rate(struct audio_stream* stream, uint32_t rate) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+
+ DEBUG("out_set_sample_rate : %" PRIu32, rate);
+
+ out->common.cfg.rate = rate;
+
+ return 0;
+}
+
+static size_t out_get_buffer_size(const struct audio_stream* stream) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+ // period_size is the AudioFlinger mixer buffer size.
+ const size_t period_size =
+ out->common.buffer_sz / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS;
+
+ DEBUG("socket buffer size: %zu period size: %zu", out->common.buffer_sz,
+ period_size);
+
+ return period_size;
+}
+
+size_t audio_ha_hw_stream_compute_buffer_size(
+ btav_a2dp_codec_sample_rate_t codec_sample_rate,
+ btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample,
+ btav_a2dp_codec_channel_mode_t codec_channel_mode) {
+ size_t buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ; // Default value
+ const uint64_t time_period_ms = 20; // Conservative 20ms
+ uint32_t sample_rate;
+ uint32_t bits_per_sample;
+ uint32_t number_of_channels;
+
+ // Check the codec config sample rate
+ switch (codec_sample_rate) {
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
+ sample_rate = 44100;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_48000:
+ sample_rate = 48000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_88200:
+ sample_rate = 88200;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
+ sample_rate = 96000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
+ sample_rate = 176400;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ sample_rate = 192000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ sample_rate = 16000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
+ sample_rate = 24000;
+ break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
+ default:
+ ERROR("Invalid sample rate: 0x%x", codec_sample_rate);
+ return buffer_sz;
+ }
+
+ // Check the codec config bits per sample
+ switch (codec_bits_per_sample) {
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
+ bits_per_sample = 16;
+ break;
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
+ bits_per_sample = 24;
+ break;
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
+ bits_per_sample = 32;
+ break;
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE:
+ default:
+ ERROR("Invalid bits per sample: 0x%x", codec_bits_per_sample);
+ return buffer_sz;
+ }
+
+ // Check the codec config channel mode
+ switch (codec_channel_mode) {
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
+ number_of_channels = 1;
+ break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
+ number_of_channels = 2;
+ break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
+ default:
+ ERROR("Invalid channel mode: 0x%x", codec_channel_mode);
+ return buffer_sz;
+ }
+
+ //
+ // The buffer size is computed by using the following formula:
+ //
+ // AUDIO_STREAM_OUTPUT_BUFFER_SIZE =
+ // (TIME_PERIOD_MS * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS *
+ // SAMPLE_RATE_HZ * NUMBER_OF_CHANNELS * (BITS_PER_SAMPLE / 8)) / 1000
+ //
+ // AUDIO_STREAM_OUTPUT_BUFFER_PERIODS controls how the socket buffer is
+ // divided for AudioFlinger data delivery. The AudioFlinger mixer delivers
+ // data in chunks of
+ // (AUDIO_STREAM_OUTPUT_BUFFER_SIZE / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS) .
+ // If the number of periods is 2, the socket buffer represents "double
+ // buffering" of the AudioFlinger mixer buffer.
+ //
+ // Furthermore, the AudioFlinger expects the buffer size to be a multiple
+ // of 16 frames.
+ const size_t divisor = (AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * 16 *
+ number_of_channels * bits_per_sample) /
+ 8;
+
+ buffer_sz = (time_period_ms * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS *
+ sample_rate * number_of_channels * (bits_per_sample / 8)) /
+ 1000;
+
+ // Adjust the buffer size so it can be divided by the divisor
+ const size_t remainder = buffer_sz % divisor;
+ if (remainder != 0) {
+ buffer_sz += divisor - remainder;
+ }
+
+ return buffer_sz;
+}
+
+static uint32_t out_get_channels(const struct audio_stream* stream) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+
+ DEBUG("channels 0x%" PRIx32, out->common.cfg.channel_mask);
+
+ return out->common.cfg.channel_mask;
+}
+
+static audio_format_t out_get_format(const struct audio_stream* stream) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+ DEBUG("format 0x%x", out->common.cfg.format);
+ return (audio_format_t)out->common.cfg.format;
+}
+
+static int out_set_format(UNUSED_ATTR struct audio_stream* stream,
+ UNUSED_ATTR audio_format_t format) {
+ DEBUG("setting format not yet supported (0x%x)", format);
+ return -ENOSYS;
+}
+
+static int out_standby(struct audio_stream* stream) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+ int retVal = 0;
+
+ FNLOG();
+
+ std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
+ // Do nothing in SUSPENDED state.
+ if (out->common.state != AUDIO_HA_STATE_SUSPENDED)
+ retVal = suspend_audio_datapath(&out->common, true);
+ out->frames_rendered = 0; // rendered is reset, presented is not
+
+ return retVal;
+}
+
+static int out_dump(UNUSED_ATTR const struct audio_stream* stream,
+ UNUSED_ATTR int fd) {
+ FNLOG();
+ return 0;
+}
+
+static int out_set_parameters(struct audio_stream* stream,
+ const char* kvpairs) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+
+ INFO("state %d kvpairs %s", out->common.state, kvpairs);
+
+ std::unordered_map<std::string, std::string> params =
+ hash_map_utils_new_from_string_params(kvpairs);
+ int status = 0;
+
+ if (params.empty()) return status;
+
+ std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
+
+ /* dump params */
+ hash_map_utils_dump_string_keys_string_values(params);
+
+ if (params["closing"].compare("true") == 0) {
+ DEBUG("stream closing, disallow any writes");
+ out->common.state = AUDIO_HA_STATE_STOPPING;
+ }
+
+ if (params["HearingAidSuspended"].compare("true") == 0) {
+ if (out->common.state == AUDIO_HA_STATE_STARTED)
+ status = suspend_audio_datapath(&out->common, false);
+ } else {
+ /* Do not start the streaming automatically. If the phone was streaming
+ * prior to being suspended, the next out_write shall trigger the
+ * AVDTP start procedure */
+ if (out->common.state == AUDIO_HA_STATE_SUSPENDED)
+ out->common.state = AUDIO_HA_STATE_STANDBY;
+ /* Irrespective of the state, return 0 */
+ }
+
+ return status;
+}
+
+static char* out_get_parameters(const struct audio_stream* stream,
+ const char* keys) {
+ FNLOG();
+
+ btav_a2dp_codec_config_t codec_config;
+ btav_a2dp_codec_config_t codec_capability;
+
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+
+ std::unordered_map<std::string, std::string> params =
+ hash_map_utils_new_from_string_params(keys);
+ std::unordered_map<std::string, std::string> return_params;
+
+ if (params.empty()) return strdup("");
+
+ std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
+
+ if (ha_read_output_audio_config(&out->common, &codec_config,
+ &codec_capability,
+ false /* update_stream_config */) < 0) {
+ ERROR("ha_read_output_audio_config failed");
+ goto done;
+ }
+
+ // Add the format
+ if (params.find(AUDIO_PARAMETER_STREAM_SUP_FORMATS) != params.end()) {
+ std::string param;
+ if (codec_capability.bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16) {
+ if (!param.empty()) param += "|";
+ param += "AUDIO_FORMAT_PCM_16_BIT";
+ }
+ if (codec_capability.bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24) {
+ if (!param.empty()) param += "|";
+ param += "AUDIO_FORMAT_PCM_24_BIT_PACKED";
+ }
+ if (codec_capability.bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32) {
+ if (!param.empty()) param += "|";
+ param += "AUDIO_FORMAT_PCM_32_BIT";
+ }
+ if (param.empty()) {
+ ERROR("Invalid codec capability bits_per_sample=0x%x",
+ codec_capability.bits_per_sample);
+ goto done;
+ } else {
+ return_params[AUDIO_PARAMETER_STREAM_SUP_FORMATS] = param;
+ }
+ }
+
+ // Add the sample rate
+ if (params.find(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES) != params.end()) {
+ std::string param;
+ if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_44100) {
+ if (!param.empty()) param += "|";
+ param += "44100";
+ }
+ if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_48000) {
+ if (!param.empty()) param += "|";
+ param += "48000";
+ }
+ if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_88200) {
+ if (!param.empty()) param += "|";
+ param += "88200";
+ }
+ if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_96000) {
+ if (!param.empty()) param += "|";
+ param += "96000";
+ }
+ if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_176400) {
+ if (!param.empty()) param += "|";
+ param += "176400";
+ }
+ if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_192000) {
+ if (!param.empty()) param += "|";
+ param += "192000";
+ }
+ if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_16000) {
+ if (!param.empty()) param += "|";
+ param += "16000";
+ }
+ if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_24000) {
+ if (!param.empty()) param += "|";
+ param += "24000";
+ }
+ if (param.empty()) {
+ ERROR("Invalid codec capability sample_rate=0x%x",
+ codec_capability.sample_rate);
+ goto done;
+ } else {
+ return_params[AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES] = param;
+ }
+ }
+
+ // Add the channel mask
+ if (params.find(AUDIO_PARAMETER_STREAM_SUP_CHANNELS) != params.end()) {
+ std::string param;
+ if (codec_capability.channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_MONO) {
+ if (!param.empty()) param += "|";
+ param += "AUDIO_CHANNEL_OUT_MONO";
+ }
+ if (codec_capability.channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO) {
+ if (!param.empty()) param += "|";
+ param += "AUDIO_CHANNEL_OUT_STEREO";
+ }
+ if (param.empty()) {
+ ERROR("Invalid codec capability channel_mode=0x%x",
+ codec_capability.channel_mode);
+ goto done;
+ } else {
+ return_params[AUDIO_PARAMETER_STREAM_SUP_CHANNELS] = param;
+ }
+ }
+
+done:
+ std::string result;
+ for (const auto& ptr : return_params) {
+ result += ptr.first + "=" + ptr.second + ";";
+ }
+
+ INFO("get parameters result = %s", result.c_str());
+
+ return strdup(result.c_str());
+}
+
+static uint32_t out_get_latency(const struct audio_stream_out* stream) {
+ int latency_us;
+
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+
+ FNLOG();
+
+ latency_us =
+ ((out->common.buffer_sz * 1000) /
+ audio_stream_out_frame_size(&out->stream) / out->common.cfg.rate) *
+ 1000;
+
+ return (latency_us / 1000) + 200;
+}
+
+static int out_set_volume(UNUSED_ATTR struct audio_stream_out* stream,
+ UNUSED_ATTR float left, UNUSED_ATTR float right) {
+ FNLOG();
+
+ /* volume controlled in audioflinger mixer (digital) */
+
+ return -ENOSYS;
+}
+
+static int out_get_presentation_position(const struct audio_stream_out* stream,
+ uint64_t* frames,
+ struct timespec* timestamp) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+
+ FNLOG();
+ if (stream == NULL || frames == NULL || timestamp == NULL) return -EINVAL;
+
+ int ret = -EWOULDBLOCK;
+ std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
+ uint64_t latency_frames =
+ (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000;
+ if (out->frames_presented >= latency_frames) {
+ *frames = out->frames_presented - latency_frames;
+ clock_gettime(CLOCK_MONOTONIC,
+ timestamp); // could also be associated with out_write().
+ ret = 0;
+ }
+ return ret;
+}
+
+static int out_get_render_position(const struct audio_stream_out* stream,
+ uint32_t* dsp_frames) {
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+
+ FNLOG();
+ if (stream == NULL || dsp_frames == NULL) return -EINVAL;
+
+ std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
+ uint64_t latency_frames =
+ (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000;
+ if (out->frames_rendered >= latency_frames) {
+ *dsp_frames = (uint32_t)(out->frames_rendered - latency_frames);
+ } else {
+ *dsp_frames = 0;
+ }
+ return 0;
+}
+
+static int out_add_audio_effect(UNUSED_ATTR const struct audio_stream* stream,
+ UNUSED_ATTR effect_handle_t effect) {
+ FNLOG();
+ return 0;
+}
+
+static int out_remove_audio_effect(
+ UNUSED_ATTR const struct audio_stream* stream,
+ UNUSED_ATTR effect_handle_t effect) {
+ FNLOG();
+ return 0;
+}
+
+/*
+ * AUDIO INPUT STREAM
+ */
+
+static uint32_t in_get_sample_rate(const struct audio_stream* stream) {
+ struct ha_stream_in* in = (struct ha_stream_in*)stream;
+
+ FNLOG();
+ return in->common.cfg.rate;
+}
+
+static int in_set_sample_rate(struct audio_stream* stream, uint32_t rate) {
+ struct ha_stream_in* in = (struct ha_stream_in*)stream;
+
+ FNLOG();
+
+ if (in->common.cfg.rate > 0 && in->common.cfg.rate == rate)
+ return 0;
+ else
+ return -1;
+}
+
+static size_t in_get_buffer_size(
+ UNUSED_ATTR const struct audio_stream* stream) {
+ FNLOG();
+ return 320;
+}
+
+static uint32_t in_get_channels(const struct audio_stream* stream) {
+ struct ha_stream_in* in = (struct ha_stream_in*)stream;
+
+ FNLOG();
+ return in->common.cfg.channel_mask;
+}
+
+static audio_format_t in_get_format(
+ UNUSED_ATTR const struct audio_stream* stream) {
+ FNLOG();
+ return AUDIO_FORMAT_PCM_16_BIT;
+}
+
+static int in_set_format(UNUSED_ATTR struct audio_stream* stream,
+ UNUSED_ATTR audio_format_t format) {
+ FNLOG();
+ if (format == AUDIO_FORMAT_PCM_16_BIT)
+ return 0;
+ else
+ return -1;
+}
+
+static int in_standby(UNUSED_ATTR struct audio_stream* stream) {
+ FNLOG();
+ return 0;
+}
+
+static int in_dump(UNUSED_ATTR const struct audio_stream* stream,
+ UNUSED_ATTR int fd) {
+ FNLOG();
+ return 0;
+}
+
+static int in_set_parameters(UNUSED_ATTR struct audio_stream* stream,
+ UNUSED_ATTR const char* kvpairs) {
+ FNLOG();
+ return 0;
+}
+
+static char* in_get_parameters(UNUSED_ATTR const struct audio_stream* stream,
+ UNUSED_ATTR const char* keys) {
+ FNLOG();
+ return strdup("");
+}
+
+static int in_set_gain(UNUSED_ATTR struct audio_stream_in* stream,
+ UNUSED_ATTR float gain) {
+ FNLOG();
+ return 0;
+}
+
+static ssize_t in_read(struct audio_stream_in* stream, void* buffer,
+ size_t bytes) {
+ struct ha_stream_in* in = (struct ha_stream_in*)stream;
+ int read;
+ int us_delay;
+
+ DEBUG("read %zu bytes, state: %d", bytes, in->common.state);
+
+ std::unique_lock<std::recursive_mutex> lock(*in->common.mutex);
+ if (in->common.state == AUDIO_HA_STATE_SUSPENDED ||
+ in->common.state == AUDIO_HA_STATE_STOPPING) {
+ DEBUG("stream suspended");
+ goto error;
+ }
+
+ /* only allow autostarting if we are in stopped or standby */
+ if ((in->common.state == AUDIO_HA_STATE_STOPPED) ||
+ (in->common.state == AUDIO_HA_STATE_STANDBY)) {
+ if (start_audio_datapath(&in->common) < 0) {
+ goto error;
+ }
+ } else if (in->common.state != AUDIO_HA_STATE_STARTED) {
+ ERROR("stream not in stopped or standby");
+ goto error;
+ }
+
+ lock.unlock();
+ read = skt_read(in->common.audio_fd, buffer, bytes);
+ lock.lock();
+ if (read == -1) {
+ skt_disconnect(in->common.audio_fd);
+ in->common.audio_fd = AUDIO_SKT_DISCONNECTED;
+ if ((in->common.state != AUDIO_HA_STATE_SUSPENDED) &&
+ (in->common.state != AUDIO_HA_STATE_STOPPING)) {
+ in->common.state = AUDIO_HA_STATE_STOPPED;
+ } else {
+ ERROR("read failed : stream suspended, avoid resetting state");
+ }
+ goto error;
+ } else if (read == 0) {
+ DEBUG("read time out - return zeros");
+ memset(buffer, 0, bytes);
+ read = bytes;
+ }
+ lock.unlock();
+
+ DEBUG("read %d bytes out of %zu bytes", read, bytes);
+ return read;
+
+error:
+ memset(buffer, 0, bytes);
+ us_delay = calc_audiotime_usec(in->common.cfg, bytes);
+ DEBUG("emulate ha read delay (%d us)", us_delay);
+
+ usleep(us_delay);
+ return bytes;
+}
+
+static uint32_t in_get_input_frames_lost(
+ UNUSED_ATTR struct audio_stream_in* stream) {
+ FNLOG();
+ return 0;
+}
+
+static int in_add_audio_effect(UNUSED_ATTR const struct audio_stream* stream,
+ UNUSED_ATTR effect_handle_t effect) {
+ FNLOG();
+ return 0;
+}
+
+static int in_remove_audio_effect(UNUSED_ATTR const struct audio_stream* stream,
+ UNUSED_ATTR effect_handle_t effect) {
+ FNLOG();
+
+ return 0;
+}
+
+static int adev_open_output_stream(struct audio_hw_device* dev,
+ UNUSED_ATTR audio_io_handle_t handle,
+ UNUSED_ATTR audio_devices_t devices,
+ UNUSED_ATTR audio_output_flags_t flags,
+ struct audio_config* config,
+ struct audio_stream_out** stream_out,
+ UNUSED_ATTR const char* address)
+
+{
+ struct ha_audio_device* ha_dev = (struct ha_audio_device*)dev;
+ struct ha_stream_out* out;
+ int ret = 0;
+
+ INFO("opening output");
+ // protect against adev->output and stream_out from being inconsistent
+ std::lock_guard<std::recursive_mutex> lock(*ha_dev->mutex);
+ out = (struct ha_stream_out*)calloc(1, sizeof(struct ha_stream_out));
+
+ if (!out) return -ENOMEM;
+
+ out->stream.common.get_sample_rate = out_get_sample_rate;
+ out->stream.common.set_sample_rate = out_set_sample_rate;
+ out->stream.common.get_buffer_size = out_get_buffer_size;
+ out->stream.common.get_channels = out_get_channels;
+ out->stream.common.get_format = out_get_format;
+ out->stream.common.set_format = out_set_format;
+ out->stream.common.standby = out_standby;
+ out->stream.common.dump = out_dump;
+ out->stream.common.set_parameters = out_set_parameters;
+ out->stream.common.get_parameters = out_get_parameters;
+ out->stream.common.add_audio_effect = out_add_audio_effect;
+ out->stream.common.remove_audio_effect = out_remove_audio_effect;
+ out->stream.get_latency = out_get_latency;
+ out->stream.set_volume = out_set_volume;
+ out->stream.write = out_write;
+ out->stream.get_render_position = out_get_render_position;
+ out->stream.get_presentation_position = out_get_presentation_position;
+
+ /* initialize ha specifics */
+ ha_stream_common_init(&out->common);
+
+ // Make sure we always have the feeding parameters configured
+ btav_a2dp_codec_config_t codec_config;
+ btav_a2dp_codec_config_t codec_capability;
+ if (ha_read_output_audio_config(&out->common, &codec_config,
+ &codec_capability,
+ true /* update_stream_config */) < 0) {
+ ERROR("ha_read_output_audio_config failed");
+ ret = -1;
+ goto err_open;
+ }
+ // ha_read_output_audio_config() opens the socket control path (or fails)
+
+ /* set output config values */
+ if (config != nullptr) {
+ // Try to use the config parameters and send it to the remote side
+ // TODO: Shall we use out_set_format() and similar?
+ if (config->format != 0) out->common.cfg.format = config->format;
+ if (config->sample_rate != 0) out->common.cfg.rate = config->sample_rate;
+ if (config->channel_mask != 0)
+ out->common.cfg.channel_mask = config->channel_mask;
+ if ((out->common.cfg.format != 0) || (out->common.cfg.rate != 0) ||
+ (out->common.cfg.channel_mask != 0)) {
+ if (ha_write_output_audio_config(&out->common) < 0) {
+ ERROR("ha_write_output_audio_config failed");
+ ret = -1;
+ goto err_open;
+ }
+ // Read again and make sure we use the same parameters as the remote side
+ if (ha_read_output_audio_config(&out->common, &codec_config,
+ &codec_capability,
+ true /* update_stream_config */) < 0) {
+ ERROR("ha_read_output_audio_config failed");
+ ret = -1;
+ goto err_open;
+ }
+ }
+ config->format = out_get_format((const struct audio_stream*)&out->stream);
+ config->sample_rate =
+ out_get_sample_rate((const struct audio_stream*)&out->stream);
+ config->channel_mask =
+ out_get_channels((const struct audio_stream*)&out->stream);
+
+ INFO(
+ "Output stream config: format=0x%x sample_rate=%d channel_mask=0x%x "
+ "buffer_sz=%zu",
+ config->format, config->sample_rate, config->channel_mask,
+ out->common.buffer_sz);
+ }
+ *stream_out = &out->stream;
+ ha_dev->output = out;
+
+ DEBUG("success");
+ /* Delay to ensure Headset is in proper state when START is initiated from
+ * DUT immediately after the connection due to ongoing music playback. */
+ usleep(250000);
+ return 0;
+
+err_open:
+ ha_stream_common_destroy(&out->common);
+ free(out);
+ *stream_out = NULL;
+ ha_dev->output = NULL;
+ ERROR("failed");
+ return ret;
+}
+
+static void adev_close_output_stream(struct audio_hw_device* dev,
+ struct audio_stream_out* stream) {
+ struct ha_audio_device* ha_dev = (struct ha_audio_device*)dev;
+ struct ha_stream_out* out = (struct ha_stream_out*)stream;
+
+ // prevent interference with adev_set_parameters.
+ std::lock_guard<std::recursive_mutex> lock(*ha_dev->mutex);
+ {
+ std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
+ const ha_state_t state = out->common.state;
+ INFO("closing output (state %d)", (int)state);
+ if ((state == AUDIO_HA_STATE_STARTED) ||
+ (state == AUDIO_HA_STATE_STOPPING)) {
+ stop_audio_datapath(&out->common);
+ }
+
+ skt_disconnect(out->common.ctrl_fd);
+ out->common.ctrl_fd = AUDIO_SKT_DISCONNECTED;
+ }
+
+ ha_stream_common_destroy(&out->common);
+ free(stream);
+ ha_dev->output = NULL;
+
+ DEBUG("done");
+}
+
+static int adev_set_parameters(struct audio_hw_device* dev,
+ const char* kvpairs) {
+ struct ha_audio_device* ha_dev = (struct ha_audio_device*)dev;
+ int retval = 0;
+
+ // prevent interference with adev_close_output_stream
+ std::lock_guard<std::recursive_mutex> lock(*ha_dev->mutex);
+ struct ha_stream_out* out = ha_dev->output;
+
+ if (out == NULL) return retval;
+
+ INFO("state %d", out->common.state);
+
+ retval =
+ out->stream.common.set_parameters((struct audio_stream*)out, kvpairs);
+
+ return retval;
+}
+
+static char* adev_get_parameters(UNUSED_ATTR const struct audio_hw_device* dev,
+ const char* keys) {
+ FNLOG();
+
+ std::unordered_map<std::string, std::string> params =
+ hash_map_utils_new_from_string_params(keys);
+ hash_map_utils_dump_string_keys_string_values(params);
+
+ return strdup("");
+}
+
+static int adev_init_check(UNUSED_ATTR const struct audio_hw_device* dev) {
+ FNLOG();
+
+ return 0;
+}
+
+static int adev_set_voice_volume(UNUSED_ATTR struct audio_hw_device* dev,
+ UNUSED_ATTR float volume) {
+ FNLOG();
+
+ return -ENOSYS;
+}
+
+static int adev_set_master_volume(UNUSED_ATTR struct audio_hw_device* dev,
+ UNUSED_ATTR float volume) {
+ FNLOG();
+
+ return -ENOSYS;
+}
+
+static int adev_set_mode(UNUSED_ATTR struct audio_hw_device* dev,
+ UNUSED_ATTR audio_mode_t mode) {
+ FNLOG();
+
+ return 0;
+}
+
+static int adev_set_mic_mute(UNUSED_ATTR struct audio_hw_device* dev,
+ UNUSED_ATTR bool state) {
+ FNLOG();
+
+ return -ENOSYS;
+}
+
+static int adev_get_mic_mute(UNUSED_ATTR const struct audio_hw_device* dev,
+ UNUSED_ATTR bool* state) {
+ FNLOG();
+
+ return -ENOSYS;
+}
+
+static size_t adev_get_input_buffer_size(
+ UNUSED_ATTR const struct audio_hw_device* dev,
+ UNUSED_ATTR const struct audio_config* config) {
+ FNLOG();
+
+ return 320;
+}
+
+static int adev_open_input_stream(struct audio_hw_device* dev,
+ UNUSED_ATTR audio_io_handle_t handle,
+ UNUSED_ATTR audio_devices_t devices,
+ UNUSED_ATTR struct audio_config* config,
+ struct audio_stream_in** stream_in,
+ UNUSED_ATTR audio_input_flags_t flags,
+ UNUSED_ATTR const char* address,
+ UNUSED_ATTR audio_source_t source) {
+ struct ha_audio_device* ha_dev = (struct ha_audio_device*)dev;
+ struct ha_stream_in* in;
+ int ret;
+
+ FNLOG();
+
+ // protect against adev->input and stream_in from being inconsistent
+ std::lock_guard<std::recursive_mutex> lock(*ha_dev->mutex);
+ in = (struct ha_stream_in*)calloc(1, sizeof(struct ha_stream_in));
+
+ if (!in) return -ENOMEM;
+
+ in->stream.common.get_sample_rate = in_get_sample_rate;
+ in->stream.common.set_sample_rate = in_set_sample_rate;
+ in->stream.common.get_buffer_size = in_get_buffer_size;
+ in->stream.common.get_channels = in_get_channels;
+ in->stream.common.get_format = in_get_format;
+ in->stream.common.set_format = in_set_format;
+ in->stream.common.standby = in_standby;
+ in->stream.common.dump = in_dump;
+ in->stream.common.set_parameters = in_set_parameters;
+ in->stream.common.get_parameters = in_get_parameters;
+ in->stream.common.add_audio_effect = in_add_audio_effect;
+ in->stream.common.remove_audio_effect = in_remove_audio_effect;
+ in->stream.set_gain = in_set_gain;
+ in->stream.read = in_read;
+ in->stream.get_input_frames_lost = in_get_input_frames_lost;
+
+ /* initialize ha specifics */
+ ha_stream_common_init(&in->common);
+
+ *stream_in = &in->stream;
+ ha_dev->input = in;
+
+ if (ha_read_input_audio_config(&in->common) < 0) {
+ ERROR("ha_read_input_audio_config failed (%s)", strerror(errno));
+ ret = -1;
+ goto err_open;
+ }
+ // ha_read_input_audio_config() opens socket control path (or fails)
+
+ DEBUG("success");
+ return 0;
+
+err_open:
+ ha_stream_common_destroy(&in->common);
+ free(in);
+ *stream_in = NULL;
+ ha_dev->input = NULL;
+ ERROR("failed");
+ return ret;
+}
+
+static void adev_close_input_stream(struct audio_hw_device* dev,
+ struct audio_stream_in* stream) {
+ struct ha_audio_device* ha_dev = (struct ha_audio_device*)dev;
+ struct ha_stream_in* in = (struct ha_stream_in*)stream;
+
+ std::lock_guard<std::recursive_mutex> lock(*ha_dev->mutex);
+ {
+ std::lock_guard<std::recursive_mutex> lock(*in->common.mutex);
+ const ha_state_t state = in->common.state;
+ INFO("closing input (state %d)", (int)state);
+
+ if ((state == AUDIO_HA_STATE_STARTED) || (state == AUDIO_HA_STATE_STOPPING))
+ stop_audio_datapath(&in->common);
+
+ skt_disconnect(in->common.ctrl_fd);
+ in->common.ctrl_fd = AUDIO_SKT_DISCONNECTED;
+ }
+ ha_stream_common_destroy(&in->common);
+ free(stream);
+ ha_dev->input = NULL;
+
+ DEBUG("done");
+}
+
+static int adev_dump(UNUSED_ATTR const audio_hw_device_t* device,
+ UNUSED_ATTR int fd) {
+ FNLOG();
+
+ return 0;
+}
+
+static int adev_close(hw_device_t* device) {
+ struct ha_audio_device* ha_dev = (struct ha_audio_device*)device;
+ FNLOG();
+
+ delete ha_dev->mutex;
+ ha_dev->mutex = nullptr;
+ free(device);
+ return 0;
+}
+
+static int adev_open(const hw_module_t* module, const char* name,
+ hw_device_t** device) {
+ struct ha_audio_device* adev;
+
+ INFO(" adev_open in ha_hw module");
+ FNLOG();
+
+ if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) {
+ ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE);
+ return -EINVAL;
+ }
+
+ adev = (struct ha_audio_device*)calloc(1, sizeof(struct ha_audio_device));
+
+ if (!adev) return -ENOMEM;
+
+ adev->mutex = new std::recursive_mutex;
+
+ adev->device.common.tag = HARDWARE_DEVICE_TAG;
+ adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
+ adev->device.common.module = (struct hw_module_t*)module;
+ adev->device.common.close = adev_close;
+
+ adev->device.init_check = adev_init_check;
+ adev->device.set_voice_volume = adev_set_voice_volume;
+ adev->device.set_master_volume = adev_set_master_volume;
+ adev->device.set_mode = adev_set_mode;
+ adev->device.set_mic_mute = adev_set_mic_mute;
+ adev->device.get_mic_mute = adev_get_mic_mute;
+ adev->device.set_parameters = adev_set_parameters;
+ adev->device.get_parameters = adev_get_parameters;
+ adev->device.get_input_buffer_size = adev_get_input_buffer_size;
+ adev->device.open_output_stream = adev_open_output_stream;
+ adev->device.close_output_stream = adev_close_output_stream;
+ adev->device.open_input_stream = adev_open_input_stream;
+ adev->device.close_input_stream = adev_close_input_stream;
+ adev->device.dump = adev_dump;
+
+ adev->output = NULL;
+
+ *device = &adev->device.common;
+
+ return 0;
+}
+
+static struct hw_module_methods_t hal_module_methods = {
+ .open = adev_open,
+};
+
+__attribute__((
+ visibility("default"))) struct audio_module HAL_MODULE_INFO_SYM = {
+ .common =
+ {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = AUDIO_HARDWARE_MODULE_ID,
+ .name = "Hearing Aid Audio HW HAL",
+ .author = "The Android Open Source Project",
+ .methods = &hal_module_methods,
+ },
+};
diff --git a/audio_hearing_aid_hw/src/audio_hearing_aid_hw_utils.cc b/audio_hearing_aid_hw/src/audio_hearing_aid_hw_utils.cc
new file mode 100644
index 0000000..2354632
--- /dev/null
+++ b/audio_hearing_aid_hw/src/audio_hearing_aid_hw_utils.cc
@@ -0,0 +1,41 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "audio_hearing_aid_hw.h"
+
+#define CASE_RETURN_STR(const) \
+ case const: \
+ return #const;
+
+const char* audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event) {
+ switch (event) {
+ CASE_RETURN_STR(HEARING_AID_CTRL_CMD_NONE)
+ CASE_RETURN_STR(HEARING_AID_CTRL_CMD_CHECK_READY)
+ CASE_RETURN_STR(HEARING_AID_CTRL_CMD_START)
+ CASE_RETURN_STR(HEARING_AID_CTRL_CMD_STOP)
+ CASE_RETURN_STR(HEARING_AID_CTRL_CMD_SUSPEND)
+ CASE_RETURN_STR(HEARING_AID_CTRL_GET_INPUT_AUDIO_CONFIG)
+ CASE_RETURN_STR(HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG)
+ CASE_RETURN_STR(HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG)
+ CASE_RETURN_STR(HEARING_AID_CTRL_CMD_OFFLOAD_START)
+ default:
+ break;
+ }
+
+ return "UNKNOWN HEARING_AID_CTRL_CMD";
+}
diff --git a/audio_hearing_aid_hw/test/audio_hearing_aid_hw_test.cc b/audio_hearing_aid_hw/test/audio_hearing_aid_hw_test.cc
new file mode 100644
index 0000000..c5d0e2b
--- /dev/null
+++ b/audio_hearing_aid_hw/test/audio_hearing_aid_hw_test.cc
@@ -0,0 +1,146 @@
+/******************************************************************************
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h"
+
+namespace {
+static uint32_t codec_sample_rate2value(
+ btav_a2dp_codec_sample_rate_t codec_sample_rate) {
+ switch (codec_sample_rate) {
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
+ return 44100;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_48000:
+ return 48000;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_88200:
+ return 88200;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
+ return 96000;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
+ return 176400;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ return 192000;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ return 16000;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
+ return 24000;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
+ break;
+ }
+ return 0;
+}
+
+static uint32_t codec_bits_per_sample2value(
+ btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample) {
+ switch (codec_bits_per_sample) {
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
+ return 16;
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
+ return 24;
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
+ return 32;
+ case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE:
+ break;
+ }
+ return 0;
+}
+
+static uint32_t codec_channel_mode2value(
+ btav_a2dp_codec_channel_mode_t codec_channel_mode) {
+ switch (codec_channel_mode) {
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
+ return 1;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
+ return 2;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
+ break;
+ }
+ return 0;
+}
+
+} // namespace
+
+class AudioA2dpHwTest : public ::testing::Test {
+ protected:
+ AudioA2dpHwTest() {}
+
+ private:
+};
+
+TEST_F(AudioA2dpHwTest, test_compute_buffer_size) {
+ const btav_a2dp_codec_sample_rate_t codec_sample_rate_array[] = {
+ BTAV_A2DP_CODEC_SAMPLE_RATE_NONE, BTAV_A2DP_CODEC_SAMPLE_RATE_44100,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_48000, BTAV_A2DP_CODEC_SAMPLE_RATE_88200,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_96000, BTAV_A2DP_CODEC_SAMPLE_RATE_176400,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_192000};
+
+ const btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample_array[] = {
+ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16,
+ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32};
+
+ const btav_a2dp_codec_channel_mode_t codec_channel_mode_array[] = {
+ BTAV_A2DP_CODEC_CHANNEL_MODE_NONE, BTAV_A2DP_CODEC_CHANNEL_MODE_MONO,
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO};
+
+ for (const auto codec_sample_rate : codec_sample_rate_array) {
+ for (const auto codec_bits_per_sample : codec_bits_per_sample_array) {
+ for (const auto codec_channel_mode : codec_channel_mode_array) {
+ size_t buffer_size = audio_ha_hw_stream_compute_buffer_size(
+ codec_sample_rate, codec_bits_per_sample, codec_channel_mode);
+
+ // Check for invalid input
+ if ((codec_sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) ||
+ (codec_bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) ||
+ (codec_channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) {
+ EXPECT_EQ(buffer_size,
+ static_cast<size_t>(AUDIO_STREAM_OUTPUT_BUFFER_SZ));
+ continue;
+ }
+
+ uint32_t sample_rate = codec_sample_rate2value(codec_sample_rate);
+ EXPECT_TRUE(sample_rate != 0);
+
+ uint32_t bits_per_sample =
+ codec_bits_per_sample2value(codec_bits_per_sample);
+ EXPECT_TRUE(bits_per_sample != 0);
+
+ uint32_t number_of_channels =
+ codec_channel_mode2value(codec_channel_mode);
+ EXPECT_TRUE(number_of_channels != 0);
+
+ const uint64_t time_period_ms = 20; // TODO: Must be a parameter
+ size_t expected_buffer_size =
+ (time_period_ms * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * sample_rate *
+ number_of_channels * (bits_per_sample / 8)) /
+ 1000;
+
+ // Compute the divisor and adjust the buffer size
+ const size_t divisor = (AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * 16 *
+ number_of_channels * bits_per_sample) /
+ 8;
+ const size_t remainder = expected_buffer_size % divisor;
+ if (remainder != 0) {
+ expected_buffer_size += divisor - remainder;
+ }
+
+ EXPECT_EQ(buffer_size, expected_buffer_size);
+ }
+ }
+ }
+}
diff --git a/binder/Android.bp b/binder/Android.bp
new file mode 100644
index 0000000..18428c2
--- /dev/null
+++ b/binder/Android.bp
@@ -0,0 +1,120 @@
+cc_library_shared {
+ name: "libbluetooth-binder",
+ product_variables: {
+ pdk: {
+ enabled: false,
+ },
+ },
+ srcs: [
+ "android/bluetooth/bluetooth_device.cc",
+ "android/bluetooth/IBluetoothSocketManager.aidl",
+ "android/os/parcel_file_descriptor.cc",
+ "android/os/parcel_uuid.cc",
+/* TODO: Uncomment this files as they get converted one-by-one into native implementation
+ "android/bluetooth/IBluetooth.aidl",
+ "android/bluetooth/IBluetoothA2dp.aidl",
+ "android/bluetooth/IBluetoothA2dpSink.aidl",
+ "android/bluetooth/IBluetoothAvrcpController.aidl",
+ "android/bluetooth/IBluetoothAvrcpTarget.aidl",
+ "android/bluetooth/IBluetoothCallback.aidl",
+ "android/bluetooth/IBluetoothProfileServiceConnection.aidl",
+ "android/bluetooth/IBluetoothHeadset.aidl",
+ "android/bluetooth/IBluetoothHeadsetPhone.aidl",
+ "android/bluetooth/IBluetoothHealth.aidl",
+ "android/bluetooth/IBluetoothHealthCallback.aidl",
+ "android/bluetooth/IBluetoothHearingAid.aidl",
+ "android/bluetooth/IBluetoothHidHost.aidl",
+ "android/bluetooth/IBluetoothPan.aidl",
+ "android/bluetooth/IBluetoothManager.aidl",
+ "android/bluetooth/IBluetoothManagerCallback.aidl",
+ "android/bluetooth/IBluetoothMap.aidl",
+ "android/bluetooth/IBluetoothMapClient.aidl",
+ "android/bluetooth/IBluetoothPbap.aidl",
+ "android/bluetooth/IBluetoothPbapClient.aidl",
+ "android/bluetooth/IBluetoothSap.aidl",
+ "android/bluetooth/IBluetoothStateChangeCallback.aidl",
+ "android/bluetooth/IBluetoothHeadsetClient.aidl",
+ "android/bluetooth/IBluetoothHidDevice.aidl",
+ "android/bluetooth/IBluetoothHidDeviceCallback.aidl",
+ "android/bluetooth/IBluetoothGatt.aidl",
+ "android/bluetooth/IBluetoothGattCallback.aidl",
+ "android/bluetooth/IBluetoothGattServerCallback.aidl",
+ "android/bluetooth/le/IAdvertisingSetCallback.aidl",
+ "android/bluetooth/le/IPeriodicAdvertisingCallback.aidl",
+ "android/bluetooth/le/IScannerCallback.aidl"
+*/
+ ],
+ export_include_dirs: [ "./"],
+ aidl: {
+ export_aidl_headers: true,
+ include_dirs: [
+ "frameworks/native/aidl/binder",
+
+ /* required for android.os.ParcelUuid, and android.os.ParcelFileDescriptor */
+ "frameworks/base/core/java",
+ "system/bt/binder",
+ ],
+ },
+ include_dirs: [
+ "libnativehelper/include/nativehelper",
+ "system/bt/types",
+ ],
+ shared_libs: [
+ "libandroid_runtime",
+ "libbinder",
+ "libchrome",
+ "libnativehelper",
+ "libcutils",
+ "libutils",
+ "liblog",
+ ],
+
+ static_libs: [
+ "libbluetooth-types",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-Wno-unused-parameter",
+ ],
+}
+
+// AIDL interface between libbluetooth-binder and framework.jar
+filegroup {
+ name: "libbluetooth-binder-aidl",
+ srcs: [
+ "android/bluetooth/IBluetooth.aidl",
+ "android/bluetooth/IBluetoothA2dp.aidl",
+ "android/bluetooth/IBluetoothA2dpSink.aidl",
+ "android/bluetooth/IBluetoothAvrcpController.aidl",
+ "android/bluetooth/IBluetoothAvrcpTarget.aidl",
+ "android/bluetooth/IBluetoothCallback.aidl",
+ "android/bluetooth/IBluetoothProfileServiceConnection.aidl",
+ "android/bluetooth/IBluetoothHeadset.aidl",
+ "android/bluetooth/IBluetoothHeadsetPhone.aidl",
+ "android/bluetooth/IBluetoothHealth.aidl",
+ "android/bluetooth/IBluetoothHealthCallback.aidl",
+ "android/bluetooth/IBluetoothHearingAid.aidl",
+ "android/bluetooth/IBluetoothHidHost.aidl",
+ "android/bluetooth/IBluetoothPan.aidl",
+ "android/bluetooth/IBluetoothManager.aidl",
+ "android/bluetooth/IBluetoothManagerCallback.aidl",
+ "android/bluetooth/IBluetoothMap.aidl",
+ "android/bluetooth/IBluetoothMapClient.aidl",
+ "android/bluetooth/IBluetoothPbap.aidl",
+ "android/bluetooth/IBluetoothPbapClient.aidl",
+ "android/bluetooth/IBluetoothSap.aidl",
+ "android/bluetooth/IBluetoothSocketManager.aidl",
+ "android/bluetooth/IBluetoothStateChangeCallback.aidl",
+ "android/bluetooth/IBluetoothHeadsetClient.aidl",
+ "android/bluetooth/IBluetoothHidDevice.aidl",
+ "android/bluetooth/IBluetoothHidDeviceCallback.aidl",
+ "android/bluetooth/IBluetoothGatt.aidl",
+ "android/bluetooth/IBluetoothGattCallback.aidl",
+ "android/bluetooth/IBluetoothGattServerCallback.aidl",
+ "android/bluetooth/le/IAdvertisingSetCallback.aidl",
+ "android/bluetooth/le/IPeriodicAdvertisingCallback.aidl",
+ "android/bluetooth/le/IScannerCallback.aidl",
+ ],
+}
diff --git a/binder/android/bluetooth/BluetoothActivityEnergyInfo.aidl b/binder/android/bluetooth/BluetoothActivityEnergyInfo.aidl
new file mode 100644
index 0000000..1410019
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothActivityEnergyInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothActivityEnergyInfo;
diff --git a/binder/android/bluetooth/BluetoothAudioConfig.aidl b/binder/android/bluetooth/BluetoothAudioConfig.aidl
new file mode 100644
index 0000000..2ef113d
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothAudioConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothAudioConfig;
diff --git a/binder/android/bluetooth/BluetoothAvrcpPlayerSettings.aidl b/binder/android/bluetooth/BluetoothAvrcpPlayerSettings.aidl
new file mode 100644
index 0000000..41b8af6
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothAvrcpPlayerSettings.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothAvrcpPlayerSettings;
diff --git a/binder/android/bluetooth/BluetoothClass.aidl b/binder/android/bluetooth/BluetoothClass.aidl
new file mode 100644
index 0000000..8699b1e
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothClass.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothClass;
diff --git a/binder/android/bluetooth/BluetoothCodecConfig.aidl b/binder/android/bluetooth/BluetoothCodecConfig.aidl
new file mode 100644
index 0000000..5890637
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothCodecConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothCodecConfig;
diff --git a/binder/android/bluetooth/BluetoothCodecStatus.aidl b/binder/android/bluetooth/BluetoothCodecStatus.aidl
new file mode 100644
index 0000000..f674db7
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothCodecStatus.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothCodecStatus;
diff --git a/binder/android/bluetooth/BluetoothDevice.aidl b/binder/android/bluetooth/BluetoothDevice.aidl
new file mode 100644
index 0000000..b9b0589
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothDevice.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothDevice cpp_header "android/bluetooth/bluetooth_device.h";
diff --git a/binder/android/bluetooth/BluetoothGattCharacteristic.aidl b/binder/android/bluetooth/BluetoothGattCharacteristic.aidl
new file mode 100644
index 0000000..463b7a7
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothGattCharacteristic.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothGattCharacteristic;
diff --git a/binder/android/bluetooth/BluetoothGattDescriptor.aidl b/binder/android/bluetooth/BluetoothGattDescriptor.aidl
new file mode 100644
index 0000000..6d4cdeb
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothGattDescriptor.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothGattDescriptor;
diff --git a/binder/android/bluetooth/BluetoothGattIncludedService.aidl b/binder/android/bluetooth/BluetoothGattIncludedService.aidl
new file mode 100644
index 0000000..d911973
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothGattIncludedService.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothGattIncludedService;
diff --git a/binder/android/bluetooth/BluetoothGattService.aidl b/binder/android/bluetooth/BluetoothGattService.aidl
new file mode 100644
index 0000000..8e72ba9
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothGattService.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothGattService;
diff --git a/binder/android/bluetooth/BluetoothHeadsetClientCall.aidl b/binder/android/bluetooth/BluetoothHeadsetClientCall.aidl
new file mode 100644
index 0000000..5403d51
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothHeadsetClientCall.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.bluetooth;
+
+parcelable BluetoothHeadsetClientCall;
diff --git a/binder/android/bluetooth/BluetoothHealthAppConfiguration.aidl b/binder/android/bluetooth/BluetoothHealthAppConfiguration.aidl
new file mode 100644
index 0000000..bc9e54f
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothHealthAppConfiguration.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.bluetooth;
+
+parcelable BluetoothHealthAppConfiguration;
diff --git a/binder/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl b/binder/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl
new file mode 100644
index 0000000..14f9114
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.bluetooth;
+
+parcelable BluetoothHidDeviceAppQosSettings;
diff --git a/binder/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl b/binder/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl
new file mode 100644
index 0000000..87dd10e
--- /dev/null
+++ b/binder/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.bluetooth;
+
+parcelable BluetoothHidDeviceAppSdpSettings;
diff --git a/binder/android/bluetooth/IBluetooth.aidl b/binder/android/bluetooth/IBluetooth.aidl
new file mode 100644
index 0000000..90c34b0
--- /dev/null
+++ b/binder/android/bluetooth/IBluetooth.aidl
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothSocketManager;
+import android.bluetooth.IBluetoothStateChangeCallback;
+import android.bluetooth.BluetoothActivityEnergyInfo;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.OobData;
+import android.os.ParcelUuid;
+import android.os.ParcelFileDescriptor;
+import android.os.ResultReceiver;
+
+/**
+ * System private API for talking with the Bluetooth service.
+ *
+ * {@hide}
+ */
+interface IBluetooth
+{
+ boolean isEnabled();
+ int getState();
+ boolean enable();
+ boolean enableNoAutoConnect();
+ boolean disable();
+
+ String getAddress();
+ ParcelUuid[] getUuids();
+ boolean setName(in String name);
+ String getName();
+ BluetoothClass getBluetoothClass();
+ boolean setBluetoothClass(in BluetoothClass bluetoothClass);
+
+ int getScanMode();
+ boolean setScanMode(int mode, int duration);
+
+ int getDiscoverableTimeout();
+ boolean setDiscoverableTimeout(int timeout);
+
+ boolean startDiscovery();
+ boolean cancelDiscovery();
+ boolean isDiscovering();
+ long getDiscoveryEndMillis();
+
+ int getAdapterConnectionState();
+ int getProfileConnectionState(int profile);
+
+ BluetoothDevice[] getBondedDevices();
+ boolean createBond(in BluetoothDevice device, in int transport);
+ boolean createBondOutOfBand(in BluetoothDevice device, in int transport, in OobData oobData);
+ boolean cancelBondProcess(in BluetoothDevice device);
+ boolean removeBond(in BluetoothDevice device);
+ int getBondState(in BluetoothDevice device);
+ boolean isBondingInitiatedLocally(in BluetoothDevice device);
+ long getSupportedProfiles();
+ int getConnectionState(in BluetoothDevice device);
+
+ String getRemoteName(in BluetoothDevice device);
+ int getRemoteType(in BluetoothDevice device);
+ String getRemoteAlias(in BluetoothDevice device);
+ boolean setRemoteAlias(in BluetoothDevice device, in String name);
+ int getRemoteClass(in BluetoothDevice device);
+ ParcelUuid[] getRemoteUuids(in BluetoothDevice device);
+ boolean fetchRemoteUuids(in BluetoothDevice device);
+ boolean sdpSearch(in BluetoothDevice device, in ParcelUuid uuid);
+ int getBatteryLevel(in BluetoothDevice device);
+ int getMaxConnectedAudioDevices();
+
+ boolean setPin(in BluetoothDevice device, boolean accept, int len, in byte[] pinCode);
+ boolean setPasskey(in BluetoothDevice device, boolean accept, int len, in byte[]
+ passkey);
+ boolean setPairingConfirmation(in BluetoothDevice device, boolean accept);
+
+ int getPhonebookAccessPermission(in BluetoothDevice device);
+ boolean setPhonebookAccessPermission(in BluetoothDevice device, int value);
+ int getMessageAccessPermission(in BluetoothDevice device);
+ boolean setMessageAccessPermission(in BluetoothDevice device, int value);
+ int getSimAccessPermission(in BluetoothDevice device);
+ boolean setSimAccessPermission(in BluetoothDevice device, int value);
+
+ void sendConnectionStateChange(in BluetoothDevice device, int profile, int state, int prevState);
+
+ void registerCallback(in IBluetoothCallback callback);
+ void unregisterCallback(in IBluetoothCallback callback);
+
+ // For Socket
+ IBluetoothSocketManager getSocketManager();
+
+ boolean factoryReset();
+
+ boolean isMultiAdvertisementSupported();
+ boolean isOffloadedFilteringSupported();
+ boolean isOffloadedScanBatchingSupported();
+ boolean isActivityAndEnergyReportingSupported();
+ boolean isLe2MPhySupported();
+ boolean isLeCodedPhySupported();
+ boolean isLeExtendedAdvertisingSupported();
+ boolean isLePeriodicAdvertisingSupported();
+ int getLeMaximumAdvertisingDataLength();
+ BluetoothActivityEnergyInfo reportActivityInfo();
+
+ /**
+ * Requests the controller activity info asynchronously.
+ * The implementor is expected to reply with the
+ * {@link android.bluetooth.BluetoothActivityEnergyInfo} object placed into the Bundle with the
+ * key {@link android.os.BatteryStats#RESULT_RECEIVER_CONTROLLER_KEY}.
+ * The result code is ignored.
+ */
+ oneway void requestActivityInfo(in ResultReceiver result);
+
+ void onLeServiceUp();
+ void onBrEdrDown();
+}
diff --git a/binder/android/bluetooth/IBluetoothA2dp.aidl b/binder/android/bluetooth/IBluetoothA2dp.aidl
new file mode 100644
index 0000000..6606a1b
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothA2dp.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * APIs for Bluetooth A2DP service
+ *
+ * @hide
+ */
+interface IBluetoothA2dp {
+ // Public API
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setActiveDevice(in BluetoothDevice device);
+ BluetoothDevice getActiveDevice();
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+ boolean isAvrcpAbsoluteVolumeSupported();
+ oneway void setAvrcpAbsoluteVolume(int volume);
+ boolean isA2dpPlaying(in BluetoothDevice device);
+ BluetoothCodecStatus getCodecStatus(in BluetoothDevice device);
+ oneway void setCodecConfigPreference(in BluetoothDevice device,
+ in BluetoothCodecConfig codecConfig);
+ oneway void enableOptionalCodecs(in BluetoothDevice device);
+ oneway void disableOptionalCodecs(in BluetoothDevice device);
+ int supportsOptionalCodecs(in BluetoothDevice device);
+ int getOptionalCodecsEnabled(in BluetoothDevice device);
+ oneway void setOptionalCodecsEnabled(in BluetoothDevice device, int value);
+}
diff --git a/binder/android/bluetooth/IBluetoothA2dpSink.aidl b/binder/android/bluetooth/IBluetoothA2dpSink.aidl
new file mode 100644
index 0000000..557eefc
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothA2dpSink.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothAudioConfig;
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * APIs for Bluetooth A2DP sink service
+ *
+ * @hide
+ */
+interface IBluetoothA2dpSink {
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ BluetoothAudioConfig getAudioConfig(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+ boolean isA2dpPlaying(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothAvrcpController.aidl b/binder/android/bluetooth/IBluetoothAvrcpController.aidl
new file mode 100644
index 0000000..fc5ff2d
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothAvrcpController.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothAvrcpPlayerSettings;
+import android.bluetooth.BluetoothDevice;
+import android.media.MediaMetadata;
+import android.media.session.PlaybackState;
+
+/**
+ * APIs for Bluetooth AVRCP controller service
+ *
+ * @hide
+ */
+interface IBluetoothAvrcpController {
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ BluetoothAvrcpPlayerSettings getPlayerSettings(in BluetoothDevice device);
+ boolean setPlayerApplicationSetting(in BluetoothAvrcpPlayerSettings plAppSetting);
+ void sendGroupNavigationCmd(in BluetoothDevice device, int keyCode, int keyState);
+}
diff --git a/binder/android/bluetooth/IBluetoothAvrcpTarget.aidl b/binder/android/bluetooth/IBluetoothAvrcpTarget.aidl
new file mode 100644
index 0000000..23f3608
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothAvrcpTarget.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+/**
+ * API for Bluetooth AVRCP Target Interface
+ *
+ * @hide
+ */
+interface IBluetoothAvrcpTarget {
+ /**
+ * @hide
+ */
+ void sendVolumeChanged(in int volume);
+}
diff --git a/binder/android/bluetooth/IBluetoothCallback.aidl b/binder/android/bluetooth/IBluetoothCallback.aidl
new file mode 100644
index 0000000..3c0680f
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothCallback.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+/**
+ * System private API for Bluetooth service callbacks.
+ *
+ * {@hide}
+ */
+interface IBluetoothCallback
+{
+ //void onRfcommChannelFound(int channel);
+ void onBluetoothStateChange(int prevState, int newState);
+}
diff --git a/binder/android/bluetooth/IBluetoothGatt.aidl b/binder/android/bluetooth/IBluetoothGatt.aidl
new file mode 100644
index 0000000..c9e1c4b
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothGatt.aidl
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertisingSetParameters;
+import android.bluetooth.le.PeriodicAdvertisingParameters;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
+import android.bluetooth.le.ResultStorageDescriptor;
+import android.os.ParcelUuid;
+import android.os.WorkSource;
+
+import android.bluetooth.IBluetoothGattCallback;
+import android.bluetooth.IBluetoothGattServerCallback;
+import android.bluetooth.le.IAdvertisingSetCallback;
+import android.bluetooth.le.IPeriodicAdvertisingCallback;
+import android.bluetooth.le.IScannerCallback;
+
+/**
+ * API for interacting with BLE / GATT
+ * @hide
+ */
+interface IBluetoothGatt {
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+
+ void registerScanner(in IScannerCallback callback, in WorkSource workSource);
+ void unregisterScanner(in int scannerId);
+ void startScan(in int scannerId, in ScanSettings settings, in List<ScanFilter> filters,
+ in List scanStorages, in String callingPackage);
+ void startScanForIntent(in PendingIntent intent, in ScanSettings settings, in List<ScanFilter> filters,
+ in String callingPackage);
+ void stopScanForIntent(in PendingIntent intent, in String callingPackage);
+ void stopScan(in int scannerId);
+ void flushPendingBatchResults(in int scannerId);
+
+ void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData,
+ in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters,
+ in AdvertiseData periodicData, in int duration, in int maxExtAdvEvents,
+ in IAdvertisingSetCallback callback);
+ void stopAdvertisingSet(in IAdvertisingSetCallback callback);
+
+ void getOwnAddress(in int advertiserId);
+ void enableAdvertisingSet(in int advertiserId, in boolean enable, in int duration, in int maxExtAdvEvents);
+ void setAdvertisingData(in int advertiserId, in AdvertiseData data);
+ void setScanResponseData(in int advertiserId, in AdvertiseData data);
+ void setAdvertisingParameters(in int advertiserId, in AdvertisingSetParameters parameters);
+ void setPeriodicAdvertisingParameters(in int advertiserId, in PeriodicAdvertisingParameters parameters);
+ void setPeriodicAdvertisingData(in int advertiserId, in AdvertiseData data);
+ void setPeriodicAdvertisingEnable(in int advertiserId, in boolean enable);
+
+ void registerSync(in ScanResult scanResult, in int skip, in int timeout, in IPeriodicAdvertisingCallback callback);
+ void unregisterSync(in IPeriodicAdvertisingCallback callback);
+
+ void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
+
+ void unregisterClient(in int clientIf);
+ void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport, in boolean opportunistic, in int phy);
+ void clientDisconnect(in int clientIf, in String address);
+ void clientSetPreferredPhy(in int clientIf, in String address, in int txPhy, in int rxPhy, in int phyOptions);
+ void clientReadPhy(in int clientIf, in String address);
+ void refreshDevice(in int clientIf, in String address);
+ void discoverServices(in int clientIf, in String address);
+ void discoverServiceByUuid(in int clientIf, in String address, in ParcelUuid uuid);
+ void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
+ void readUsingCharacteristicUuid(in int clientIf, in String address, in ParcelUuid uuid,
+ in int startHandle, in int endHandle, in int authReq);
+ void writeCharacteristic(in int clientIf, in String address, in int handle,
+ in int writeType, in int authReq, in byte[] value);
+ void readDescriptor(in int clientIf, in String address, in int handle, in int authReq);
+ void writeDescriptor(in int clientIf, in String address, in int handle,
+ in int authReq, in byte[] value);
+ void registerForNotification(in int clientIf, in String address, in int handle, in boolean enable);
+ void beginReliableWrite(in int clientIf, in String address);
+ void endReliableWrite(in int clientIf, in String address, in boolean execute);
+ void readRemoteRssi(in int clientIf, in String address);
+ void configureMTU(in int clientIf, in String address, in int mtu);
+ void connectionParameterUpdate(in int clientIf, in String address, in int connectionPriority);
+ void leConnectionUpdate(int clientIf, String address, int minInterval,
+ int maxInterval, int slaveLatency, int supervisionTimeout,
+ int minConnectionEventLen, int maxConnectionEventLen);
+
+ void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallback callback);
+ void unregisterServer(in int serverIf);
+ void serverConnect(in int serverIf, in String address, in boolean isDirect, in int transport);
+ void serverDisconnect(in int serverIf, in String address);
+ void serverSetPreferredPhy(in int clientIf, in String address, in int txPhy, in int rxPhy, in int phyOptions);
+ void serverReadPhy(in int clientIf, in String address);
+ void addService(in int serverIf, in BluetoothGattService service);
+ void removeService(in int serverIf, in int handle);
+ void clearServices(in int serverIf);
+ void sendResponse(in int serverIf, in String address, in int requestId,
+ in int status, in int offset, in byte[] value);
+ void sendNotification(in int serverIf, in String address, in int handle,
+ in boolean confirm, in byte[] value);
+ void disconnectAll();
+ void unregAll();
+ int numHwTrackFiltersAvailable();
+}
diff --git a/binder/android/bluetooth/IBluetoothGattCallback.aidl b/binder/android/bluetooth/IBluetoothGattCallback.aidl
new file mode 100644
index 0000000..123a851
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothGattCallback.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.bluetooth;
+
+import android.os.ParcelUuid;
+import android.bluetooth.BluetoothGattService;
+
+/**
+ * Callback definitions for interacting with BLE / GATT
+ * @hide
+ */
+oneway interface IBluetoothGattCallback {
+ void onClientRegistered(in int status, in int clientIf);
+ void onClientConnectionState(in int status, in int clientIf,
+ in boolean connected, in String address);
+ void onPhyUpdate(in String address, in int txPhy, in int rxPhy, in int status);
+ void onPhyRead(in String address, in int txPhy, in int rxPhy, in int status);
+ void onSearchComplete(in String address, in List<BluetoothGattService> services, in int status);
+ void onCharacteristicRead(in String address, in int status, in int handle, in byte[] value);
+ void onCharacteristicWrite(in String address, in int status, in int handle);
+ void onExecuteWrite(in String address, in int status);
+ void onDescriptorRead(in String address, in int status, in int handle, in byte[] value);
+ void onDescriptorWrite(in String address, in int status, in int handle);
+ void onNotify(in String address, in int handle, in byte[] value);
+ void onReadRemoteRssi(in String address, in int rssi, in int status);
+ void onConfigureMTU(in String address, in int mtu, in int status);
+ void onConnectionUpdated(in String address, in int interval, in int latency,
+ in int timeout, in int status);
+}
diff --git a/binder/android/bluetooth/IBluetoothGattServerCallback.aidl b/binder/android/bluetooth/IBluetoothGattServerCallback.aidl
new file mode 100644
index 0000000..3f0ee20
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothGattServerCallback.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.bluetooth;
+
+import android.bluetooth.BluetoothGattService;
+
+/**
+ * Callback definitions for interacting with BLE / GATT
+ * @hide
+ */
+oneway interface IBluetoothGattServerCallback {
+ void onServerRegistered(in int status, in int serverIf);
+ void onServerConnectionState(in int status, in int serverIf,
+ in boolean connected, in String address);
+ void onServiceAdded(in int status, in BluetoothGattService service);
+ void onCharacteristicReadRequest(in String address, in int transId, in int offset,
+ in boolean isLong, in int handle);
+ void onDescriptorReadRequest(in String address, in int transId,
+ in int offset, in boolean isLong,
+ in int handle);
+ void onCharacteristicWriteRequest(in String address, in int transId, in int offset,
+ in int length, in boolean isPrep, in boolean needRsp,
+ in int handle, in byte[] value);
+ void onDescriptorWriteRequest(in String address, in int transId, in int offset,
+ in int length, in boolean isPrep, in boolean needRsp,
+ in int handle, in byte[] value);
+ void onExecuteWrite(in String address, in int transId, in boolean execWrite);
+ void onNotificationSent(in String address, in int status);
+ void onMtuChanged(in String address, in int mtu);
+ void onPhyUpdate(in String address, in int txPhy, in int rxPhy, in int status);
+ void onPhyRead(in String address, in int txPhy, in int rxPhy, in int status);
+ void onConnectionUpdated(in String address, in int interval, in int latency,
+ in int timeout, in int status);
+}
diff --git a/binder/android/bluetooth/IBluetoothHeadset.aidl b/binder/android/bluetooth/IBluetoothHeadset.aidl
new file mode 100644
index 0000000..f8dfb65
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothHeadset.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth Headset service
+ *
+ * Note before adding anything new:
+ * Internal interactions within com.android.bluetooth should be handled through
+ * HeadsetService directly instead of going through binder
+ *
+ * {@hide}
+ */
+interface IBluetoothHeadset {
+ // Public API
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean startVoiceRecognition(in BluetoothDevice device);
+ boolean stopVoiceRecognition(in BluetoothDevice device);
+ boolean isAudioConnected(in BluetoothDevice device);
+ boolean sendVendorSpecificResultCode(in BluetoothDevice device,
+ in String command,
+ in String arg);
+
+ // Hidden API
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+ int getAudioState(in BluetoothDevice device);
+ boolean isAudioOn();
+ boolean connectAudio();
+ boolean disconnectAudio();
+ void setAudioRouteAllowed(boolean allowed);
+ boolean getAudioRouteAllowed();
+ void setForceScoAudio(boolean forced);
+ boolean startScoUsingVirtualVoiceCall();
+ boolean stopScoUsingVirtualVoiceCall();
+ oneway void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type);
+ void clccResponse(int index, int direction, int status, int mode, boolean mpty,
+ String number, int type);
+ boolean setActiveDevice(in BluetoothDevice device);
+ BluetoothDevice getActiveDevice();
+ boolean isInbandRingingEnabled();
+}
diff --git a/binder/android/bluetooth/IBluetoothHeadsetClient.aidl b/binder/android/bluetooth/IBluetoothHeadsetClient.aidl
new file mode 100644
index 0000000..13495ae
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothHeadsetClient.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadsetClientCall;
+import android.os.Bundle;
+
+/**
+ * API for Bluetooth Headset Client service (HFP HF Role)
+ *
+ * {@hide}
+ */
+interface IBluetoothHeadsetClient {
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+
+ boolean startVoiceRecognition(in BluetoothDevice device);
+ boolean stopVoiceRecognition(in BluetoothDevice device);
+
+ List<BluetoothHeadsetClientCall> getCurrentCalls(in BluetoothDevice device);
+ Bundle getCurrentAgEvents(in BluetoothDevice device);
+
+ boolean acceptCall(in BluetoothDevice device, int flag);
+ boolean holdCall(in BluetoothDevice device);
+ boolean rejectCall(in BluetoothDevice device);
+ boolean terminateCall(in BluetoothDevice device, in BluetoothHeadsetClientCall call);
+
+ boolean enterPrivateMode(in BluetoothDevice device, int index);
+ boolean explicitCallTransfer(in BluetoothDevice device);
+
+ BluetoothHeadsetClientCall dial(in BluetoothDevice device, String number);
+
+ boolean sendDTMF(in BluetoothDevice device, byte code);
+ boolean getLastVoiceTagNumber(in BluetoothDevice device);
+
+ int getAudioState(in BluetoothDevice device);
+ boolean connectAudio(in BluetoothDevice device);
+ boolean disconnectAudio(in BluetoothDevice device);
+ void setAudioRouteAllowed(in BluetoothDevice device, boolean allowed);
+ boolean getAudioRouteAllowed(in BluetoothDevice device);
+
+ Bundle getCurrentAgFeatures(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothHeadsetPhone.aidl b/binder/android/bluetooth/IBluetoothHeadsetPhone.aidl
new file mode 100644
index 0000000..8309780
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothHeadsetPhone.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+/**
+ * API for Bluetooth Headset Phone Service in phone app
+ *
+ * {@hide}
+ */
+interface IBluetoothHeadsetPhone {
+ // Internal functions, not be made public
+ boolean answerCall();
+ boolean hangupCall();
+ boolean sendDtmf(int dtmf);
+ boolean processChld(int chld);
+ String getNetworkOperator();
+ String getSubscriberNumber();
+ boolean listCurrentCalls();
+ boolean queryPhoneState();
+
+ // Internal for phone app to call
+ void updateBtHandsfreeAfterRadioTechnologyChange();
+ void cdmaSwapSecondCallState();
+ void cdmaSetSecondCallState(boolean state);
+}
diff --git a/binder/android/bluetooth/IBluetoothHealth.aidl b/binder/android/bluetooth/IBluetoothHealth.aidl
new file mode 100644
index 0000000..a3be367
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothHealth.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealthAppConfiguration;
+import android.bluetooth.IBluetoothHealthCallback;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * API for Bluetooth Health service
+ *
+ * {@hide}
+ */
+interface IBluetoothHealth
+{
+ boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config,
+ in IBluetoothHealthCallback callback);
+ boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config);
+ boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
+ boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
+ int channelType);
+ boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, int id);
+ ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
+ List<BluetoothDevice> getConnectedHealthDevices();
+ List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
+ int getHealthDeviceConnectionState(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothHealthCallback.aidl b/binder/android/bluetooth/IBluetoothHealthCallback.aidl
new file mode 100644
index 0000000..ef7c191
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothHealthCallback.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealthAppConfiguration;
+import android.os.ParcelFileDescriptor;
+
+/**
+ *@hide
+ */
+interface IBluetoothHealthCallback
+{
+ void onHealthAppConfigurationStatusChange(in BluetoothHealthAppConfiguration config, int status);
+ void onHealthChannelStateChange(in BluetoothHealthAppConfiguration config,
+ in BluetoothDevice device, int prevState, int newState, in
+ ParcelFileDescriptor fd, int id);
+}
diff --git a/binder/android/bluetooth/IBluetoothHearingAid.aidl b/binder/android/bluetooth/IBluetoothHearingAid.aidl
new file mode 100644
index 0000000..ad14192
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothHearingAid.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * APIs for Bluetooth Hearing Aid service
+ *
+ * @hide
+ */
+interface IBluetoothHearingAid {
+ // Public API
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setActiveDevice(in BluetoothDevice device);
+ List<BluetoothDevice> getActiveDevices();
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+ void adjustVolume(int direction);
+ void setVolume(int volume);
+ int getVolume();
+
+ const int HI_SYNC_ID_INVALID = 0;
+ long getHiSyncId(in BluetoothDevice device);
+
+ const int SIDE_LEFT = 0;
+ const int SIDE_RIGHT = 1;
+ int getDeviceSide(in BluetoothDevice device);
+
+ const int MODE_MONAURAL = 0;
+ const int MODE_BINAURAL = 1;
+ int getDeviceMode(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothHidDevice.aidl b/binder/android/bluetooth/IBluetoothHidDevice.aidl
new file mode 100644
index 0000000..5246262
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothHidDevice.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothHidDeviceCallback;
+import android.bluetooth.BluetoothHidDeviceAppSdpSettings;
+import android.bluetooth.BluetoothHidDeviceAppQosSettings;
+
+/** @hide */
+interface IBluetoothHidDevice {
+ boolean registerApp(in BluetoothHidDeviceAppSdpSettings sdp,
+ in BluetoothHidDeviceAppQosSettings inQos, in BluetoothHidDeviceAppQosSettings outQos,
+ in IBluetoothHidDeviceCallback callback);
+ boolean unregisterApp();
+ boolean sendReport(in BluetoothDevice device, in int id, in byte[] data);
+ boolean replyReport(in BluetoothDevice device, in byte type, in byte id, in byte[] data);
+ boolean reportError(in BluetoothDevice device, byte error);
+ boolean unplug(in BluetoothDevice device);
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ String getUserAppName();
+}
diff --git a/binder/android/bluetooth/IBluetoothHidDeviceCallback.aidl b/binder/android/bluetooth/IBluetoothHidDeviceCallback.aidl
new file mode 100644
index 0000000..8205c67
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothHidDeviceCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/** @hide */
+interface IBluetoothHidDeviceCallback {
+ void onAppStatusChanged(in BluetoothDevice device, boolean registered);
+ void onConnectionStateChanged(in BluetoothDevice device, in int state);
+ void onGetReport(in BluetoothDevice device, in byte type, in byte id, in int bufferSize);
+ void onSetReport(in BluetoothDevice device, in byte type, in byte id, in byte[] data);
+ void onSetProtocol(in BluetoothDevice device, in byte protocol);
+ void onInterruptData(in BluetoothDevice device, in byte reportId, in byte[] data);
+ void onVirtualCableUnplug(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothHidHost.aidl b/binder/android/bluetooth/IBluetoothHidHost.aidl
new file mode 100644
index 0000000..609da1b
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothHidHost.aidl
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth HID service
+ *
+ * {@hide}
+ */
+interface IBluetoothHidHost {
+ // Public API
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+ /**
+ * @hide
+ */
+ boolean getProtocolMode(in BluetoothDevice device);
+ /**
+ * @hide
+ */
+ boolean virtualUnplug(in BluetoothDevice device);
+ /**
+ * @hide
+ */
+ boolean setProtocolMode(in BluetoothDevice device, int protocolMode);
+ /**
+ * @hide
+ */
+ boolean getReport(in BluetoothDevice device, byte reportType, byte reportId, int bufferSize);
+ /**
+ * @hide
+ */
+ boolean setReport(in BluetoothDevice device, byte reportType, String report);
+ /**
+ * @hide
+ */
+ boolean sendData(in BluetoothDevice device, String report);
+ /**
+ * @hide
+ */
+ boolean getIdleTime(in BluetoothDevice device);
+ /**
+ * @hide
+ */
+ boolean setIdleTime(in BluetoothDevice device, byte idleTime);
+}
diff --git a/binder/android/bluetooth/IBluetoothManager.aidl b/binder/android/bluetooth/IBluetoothManager.aidl
new file mode 100644
index 0000000..a3ec1d8
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothManager.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothGatt;
+import android.bluetooth.IBluetoothManagerCallback;
+import android.bluetooth.IBluetoothProfileServiceConnection;
+import android.bluetooth.IBluetoothStateChangeCallback;
+
+/**
+ * System private API for talking with the Bluetooth service.
+ *
+ * {@hide}
+ */
+interface IBluetoothManager
+{
+ IBluetooth registerAdapter(in IBluetoothManagerCallback callback);
+ void unregisterAdapter(in IBluetoothManagerCallback callback);
+ void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);
+ void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
+ boolean isEnabled();
+ boolean enable(String packageName);
+ boolean enableNoAutoConnect(String packageName);
+ boolean disable(String packageName, boolean persist);
+ int getState();
+ IBluetoothGatt getBluetoothGatt();
+
+ boolean bindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);
+ void unbindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);
+
+ String getAddress();
+ String getName();
+
+ boolean isBleScanAlwaysAvailable();
+ int updateBleAppCount(IBinder b, boolean enable, String packageName);
+ boolean isBleAppPresent();
+}
+
diff --git a/binder/android/bluetooth/IBluetoothManagerCallback.aidl b/binder/android/bluetooth/IBluetoothManagerCallback.aidl
new file mode 100644
index 0000000..27ad2a0
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothManagerCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetooth;
+
+/**
+ * API for Communication between BluetoothAdapter and BluetoothManager
+ *
+ * {@hide}
+ */
+oneway interface IBluetoothManagerCallback {
+ void onBluetoothServiceUp(in IBluetooth bluetoothService);
+ void onBluetoothServiceDown();
+ void onBrEdrDown();
+}
diff --git a/binder/android/bluetooth/IBluetoothMap.aidl b/binder/android/bluetooth/IBluetoothMap.aidl
new file mode 100644
index 0000000..562490e
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothMap.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * System private API for Bluetooth MAP service
+ *
+ * {@hide}
+ */
+interface IBluetoothMap {
+ int getState();
+ BluetoothDevice getClient();
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ boolean isConnected(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothMapClient.aidl b/binder/android/bluetooth/IBluetoothMapClient.aidl
new file mode 100644
index 0000000..7ac91e9
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothMapClient.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
+import android.net.Uri;
+
+/**
+ * System private API for Bluetooth MAP MCE service
+ *
+ * {@hide}
+ */
+interface IBluetoothMapClient {
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ boolean isConnected(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device,in int priority);
+ int getPriority(in BluetoothDevice device);
+ boolean sendMessage(in BluetoothDevice device, in Uri[] contacts, in String message,
+ in PendingIntent sentIntent, in PendingIntent deliveryIntent);
+ boolean getUnreadMessages(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothPan.aidl b/binder/android/bluetooth/IBluetoothPan.aidl
new file mode 100644
index 0000000..16b6ddf
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothPan.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth Pan service
+ *
+ * {@hide}
+ */
+interface IBluetoothPan {
+ // Public API
+ boolean isTetheringOn();
+ void setBluetoothTethering(boolean value);
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothPbap.aidl b/binder/android/bluetooth/IBluetoothPbap.aidl
new file mode 100644
index 0000000..52caf77
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothPbap.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * System private API for Bluetooth pbap service
+ *
+ * {@hide}
+ */
+interface IBluetoothPbap {
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ void disconnect(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothPbapClient.aidl b/binder/android/bluetooth/IBluetoothPbapClient.aidl
new file mode 100644
index 0000000..52f9845
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothPbapClient.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth Phone Book Access Provile Client Side
+ *
+ * {@hide}
+ */
+interface IBluetoothPbapClient {
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothProfileServiceConnection.aidl b/binder/android/bluetooth/IBluetoothProfileServiceConnection.aidl
new file mode 100644
index 0000000..e5c3de9
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothProfileServiceConnection.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.content.ComponentName;
+import android.os.IBinder;
+
+/**
+ * Callback for bluetooth profile connections.
+ *
+ * {@hide}
+ */
+oneway interface IBluetoothProfileServiceConnection {
+ void onServiceConnected(in ComponentName comp, in IBinder service);
+ void onServiceDisconnected(in ComponentName comp);
+}
diff --git a/binder/android/bluetooth/IBluetoothSap.aidl b/binder/android/bluetooth/IBluetoothSap.aidl
new file mode 100644
index 0000000..0ea7afb
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothSap.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * System private API for Bluetooth SAP service
+ *
+ * {@hide}
+ */
+interface IBluetoothSap {
+ int getState();
+ BluetoothDevice getClient();
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ boolean isConnected(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothSocketManager.aidl b/binder/android/bluetooth/IBluetoothSocketManager.aidl
new file mode 100644
index 0000000..119988e
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothSocketManager.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.os.ParcelUuid;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * API for Bluetooth Sockets service.
+ *
+ * {@hide}
+ */
+interface IBluetoothSocketManager
+{
+ @nullable ParcelFileDescriptor connectSocket(in BluetoothDevice device, int type, in @nullable ParcelUuid uuid, int port, int flag);
+ @nullable ParcelFileDescriptor createSocketChannel(int type, in @nullable String serviceName, in @nullable ParcelUuid uuid, int port, int flag);
+ void requestMaximumTxDataLength(in BluetoothDevice device);
+}
diff --git a/binder/android/bluetooth/IBluetoothStateChangeCallback.aidl b/binder/android/bluetooth/IBluetoothStateChangeCallback.aidl
new file mode 100644
index 0000000..1716801
--- /dev/null
+++ b/binder/android/bluetooth/IBluetoothStateChangeCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+/**
+ * System private API for Bluetooth state change callback.
+ *
+ * {@hide}
+ */
+oneway interface IBluetoothStateChangeCallback
+{
+ void onBluetoothStateChange(boolean on);
+}
diff --git a/binder/android/bluetooth/OobData.aidl b/binder/android/bluetooth/OobData.aidl
new file mode 100644
index 0000000..529e0b0
--- /dev/null
+++ b/binder/android/bluetooth/OobData.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+parcelable OobData;
diff --git a/binder/android/bluetooth/bluetooth_device.cc b/binder/android/bluetooth/bluetooth_device.cc
new file mode 100644
index 0000000..e291ba2
--- /dev/null
+++ b/binder/android/bluetooth/bluetooth_device.cc
@@ -0,0 +1,46 @@
+//
+// Copyright 2017, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "android/bluetooth/bluetooth_device.h"
+
+#include <utils/String16.h>
+
+using android::OK;
+using android::Parcel;
+using android::status_t;
+using android::String16;
+using android::String8;
+
+namespace android {
+namespace bluetooth {
+
+status_t BluetoothDevice::writeToParcel(Parcel* parcel) const {
+ status_t status = parcel->writeString16(String16(address.ToString().c_str()));
+ return status;
+}
+
+status_t BluetoothDevice::readFromParcel(const Parcel* parcel) {
+ String16 tmp;
+
+ status_t status = parcel->readString16(&tmp);
+ if (status != OK) return status;
+
+ RawAddress::FromString(String8(tmp).string(), address);
+ return OK;
+}
+
+} // namespace bluetooth
+} // namespace android
\ No newline at end of file
diff --git a/binder/android/bluetooth/bluetooth_device.h b/binder/android/bluetooth/bluetooth_device.h
new file mode 100644
index 0000000..01bc00a
--- /dev/null
+++ b/binder/android/bluetooth/bluetooth_device.h
@@ -0,0 +1,50 @@
+//
+// Copyright 2017, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+
+#include <raw_address.h>
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothDevice : public android::Parcelable {
+ public:
+ BluetoothDevice() = default;
+ ~BluetoothDevice() = default;
+
+ // Write |this| parcelable to the given |parcel|. Keep in mind that
+ // implementations of writeToParcel must be manually kept in sync
+ // with readFromParcel and the Java equivalent versions of these methods.
+ //
+ // Returns android::OK on success and an appropriate error otherwise.
+ android::status_t writeToParcel(android::Parcel* parcel) const override;
+
+ // Read data from the given |parcel| into |this|. After readFromParcel
+ // completes, |this| should have equivalent state to the object that
+ // wrote itself to the parcel.
+ //
+ // Returns android::OK on success and an appropriate error otherwise.
+ android::status_t readFromParcel(const android::Parcel* parcel) override;
+
+ RawAddress address;
+};
+
+} // namespace bluetooth
+} // namespace android
diff --git a/binder/android/bluetooth/le/AdvertiseData.aidl b/binder/android/bluetooth/le/AdvertiseData.aidl
new file mode 100644
index 0000000..713635d
--- /dev/null
+++ b/binder/android/bluetooth/le/AdvertiseData.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.le;
+
+parcelable AdvertiseData;
diff --git a/binder/android/bluetooth/le/AdvertiseSettings.aidl b/binder/android/bluetooth/le/AdvertiseSettings.aidl
new file mode 100644
index 0000000..3677e75
--- /dev/null
+++ b/binder/android/bluetooth/le/AdvertiseSettings.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.le;
+
+parcelable AdvertiseSettings;
\ No newline at end of file
diff --git a/binder/android/bluetooth/le/AdvertisingSetParameters.aidl b/binder/android/bluetooth/le/AdvertisingSetParameters.aidl
new file mode 100644
index 0000000..3918864
--- /dev/null
+++ b/binder/android/bluetooth/le/AdvertisingSetParameters.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.le;
+
+parcelable AdvertisingSetParameters;
diff --git a/binder/android/bluetooth/le/IAdvertisingSetCallback.aidl b/binder/android/bluetooth/le/IAdvertisingSetCallback.aidl
new file mode 100644
index 0000000..2e3241c
--- /dev/null
+++ b/binder/android/bluetooth/le/IAdvertisingSetCallback.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.bluetooth.le;
+
+/**
+ * Callback definitions for interacting with Advertiser
+ * @hide
+ */
+oneway interface IAdvertisingSetCallback {
+ void onAdvertisingSetStarted(in int advertiserId, in int tx_power, in int status);
+ void onOwnAddressRead(in int advertiserId, in int addressType, in String address);
+ void onAdvertisingSetStopped(in int advertiserId);
+ void onAdvertisingEnabled(in int advertiserId, in boolean enable, in int status);
+ void onAdvertisingDataSet(in int advertiserId, in int status);
+ void onScanResponseDataSet(in int advertiserId, in int status);
+ void onAdvertisingParametersUpdated(in int advertiserId, in int tx_power, in int status);
+ void onPeriodicAdvertisingParametersUpdated(in int advertiserId, in int status);
+ void onPeriodicAdvertisingDataSet(in int advertiserId, in int status);
+ void onPeriodicAdvertisingEnabled(in int advertiserId, in boolean enable, in int status);
+}
diff --git a/binder/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl b/binder/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl
new file mode 100644
index 0000000..84bbc14
--- /dev/null
+++ b/binder/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.bluetooth.le;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.PeriodicAdvertisingReport;
+
+/**
+ * Callback definitions for interacting with Periodic Advertising
+ * @hide
+ */
+oneway interface IPeriodicAdvertisingCallback {
+
+ void onSyncEstablished(in int syncHandle, in BluetoothDevice device, in int advertisingSid,
+ in int skip, in int timeout, in int status);
+ void onPeriodicAdvertisingReport(in PeriodicAdvertisingReport report);
+ void onSyncLost(in int syncHandle);
+}
diff --git a/binder/android/bluetooth/le/IScannerCallback.aidl b/binder/android/bluetooth/le/IScannerCallback.aidl
new file mode 100644
index 0000000..025e7ff
--- /dev/null
+++ b/binder/android/bluetooth/le/IScannerCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.bluetooth.le;
+
+import android.bluetooth.le.ScanResult;
+
+/**
+ * Callback definitions for interacting with Advertiser
+ * @hide
+ */
+oneway interface IScannerCallback {
+ void onScannerRegistered(in int status, in int scannerId);
+
+ void onScanResult(in ScanResult scanResult);
+ void onBatchScanResults(in List<ScanResult> batchResults);
+ void onFoundOrLost(in boolean onFound, in ScanResult scanResult);
+ void onScanManagerErrorCallback(in int errorCode);
+}
diff --git a/binder/android/bluetooth/le/PeriodicAdvertisingParameters.aidl b/binder/android/bluetooth/le/PeriodicAdvertisingParameters.aidl
new file mode 100644
index 0000000..3f714f0
--- /dev/null
+++ b/binder/android/bluetooth/le/PeriodicAdvertisingParameters.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.le;
+
+parcelable PeriodicAdvertisingParameters;
diff --git a/binder/android/bluetooth/le/PeriodicAdvertisingReport.aidl b/binder/android/bluetooth/le/PeriodicAdvertisingReport.aidl
new file mode 100644
index 0000000..986ac61
--- /dev/null
+++ b/binder/android/bluetooth/le/PeriodicAdvertisingReport.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.le;
+
+parcelable PeriodicAdvertisingReport;
diff --git a/binder/android/bluetooth/le/ResultStorageDescriptor.aidl b/binder/android/bluetooth/le/ResultStorageDescriptor.aidl
new file mode 100644
index 0000000..afc1b41
--- /dev/null
+++ b/binder/android/bluetooth/le/ResultStorageDescriptor.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.le;
+
+/**
+ * {@hide}
+ */
+
+parcelable ResultStorageDescriptor;
diff --git a/binder/android/bluetooth/le/ScanFilter.aidl b/binder/android/bluetooth/le/ScanFilter.aidl
new file mode 100644
index 0000000..e3ebd85
--- /dev/null
+++ b/binder/android/bluetooth/le/ScanFilter.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.le;
+
+parcelable ScanFilter;
diff --git a/binder/android/bluetooth/le/ScanResult.aidl b/binder/android/bluetooth/le/ScanResult.aidl
new file mode 100644
index 0000000..f16dc18
--- /dev/null
+++ b/binder/android/bluetooth/le/ScanResult.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.le;
+
+parcelable ScanResult;
\ No newline at end of file
diff --git a/binder/android/bluetooth/le/ScanSettings.aidl b/binder/android/bluetooth/le/ScanSettings.aidl
new file mode 100644
index 0000000..e84e078
--- /dev/null
+++ b/binder/android/bluetooth/le/ScanSettings.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.le;
+
+parcelable ScanSettings;
diff --git a/binder/android/os/parcel_file_descriptor.cc b/binder/android/os/parcel_file_descriptor.cc
new file mode 100644
index 0000000..37bef6d
--- /dev/null
+++ b/binder/android/os/parcel_file_descriptor.cc
@@ -0,0 +1,43 @@
+//
+// Copyright 2017, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "android/os/parcel_file_descriptor.h"
+#include <base/logging.h>
+
+using android::OK;
+using android::Parcel;
+using android::status_t;
+
+namespace android {
+namespace os {
+
+status_t ParcelFileDescriptor::writeToParcel(Parcel* parcel) const {
+ CHECK(fd_ >= 0);
+ return parcel->writeParcelFileDescriptor(fd_, takeOwnership_);
+}
+
+status_t ParcelFileDescriptor::readFromParcel(const Parcel* parcel) {
+ LOG(FATAL) << "Don't know how to read ParcelFileDescriptor";
+ return OK;
+}
+
+void ParcelFileDescriptor::setFileDescriptor(int fd, bool takeOwnership) {
+ fd_ = fd;
+ takeOwnership_ = takeOwnership;
+}
+
+} // namespace os
+} // namespace android
diff --git a/binder/android/os/parcel_file_descriptor.h b/binder/android/os/parcel_file_descriptor.h
new file mode 100644
index 0000000..a37b49c
--- /dev/null
+++ b/binder/android/os/parcel_file_descriptor.h
@@ -0,0 +1,52 @@
+//
+// Copyright 2017, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace os {
+
+class ParcelFileDescriptor : public android::Parcelable {
+ public:
+ ParcelFileDescriptor() : fd_(-1), takeOwnership_(false) {}
+ ~ParcelFileDescriptor() = default;
+
+ // Write |this| parcelable to the given |parcel|. Keep in mind that
+ // implementations of writeToParcel must be manually kept in sync
+ // with readFromParcel and the Java equivalent versions of these methods.
+ //
+ // Returns android::OK on success and an appropriate error otherwise.
+ android::status_t writeToParcel(android::Parcel* parcel) const override;
+
+ // Read data from the given |parcel| into |this|. After readFromParcel
+ // completes, |this| should have equivalent state to the object that
+ // wrote itself to the parcel.
+ //
+ // Returns android::OK on success and an appropriate error otherwise.
+ android::status_t readFromParcel(const android::Parcel* parcel) override;
+
+ void setFileDescriptor(int fd, bool takeOwnership);
+
+ private:
+ int fd_;
+ bool takeOwnership_;
+};
+
+} // namespace os
+} // namespace android
diff --git a/binder/android/os/parcel_uuid.cc b/binder/android/os/parcel_uuid.cc
new file mode 100644
index 0000000..ea97104
--- /dev/null
+++ b/binder/android/os/parcel_uuid.cc
@@ -0,0 +1,81 @@
+//
+// Copyright 2017, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "android/os/parcel_uuid.h"
+
+using android::OK;
+using android::Parcel;
+using android::status_t;
+using ::bluetooth::Uuid;
+
+namespace android {
+namespace os {
+
+namespace {
+static uint64_t uuid_lsb(const Uuid& uuid) {
+ uint64_t lsb = 0;
+
+ auto uu = uuid.To128BitBE();
+ for (int i = 8; i <= 15; i++) {
+ lsb <<= 8;
+ lsb |= uu[i];
+ }
+
+ return lsb;
+}
+
+static uint64_t uuid_msb(const Uuid& uuid) {
+ uint64_t msb = 0;
+
+ auto uu = uuid.To128BitBE();
+ for (int i = 0; i <= 7; i++) {
+ msb <<= 8;
+ msb |= uu[i];
+ }
+
+ return msb;
+}
+} // namespace
+
+status_t ParcelUuid::writeToParcel(Parcel* parcel) const {
+ status_t status = parcel->writeInt64(uuid_msb(uuid));
+ if (status != OK) return status;
+
+ status = parcel->writeInt64(uuid_lsb(uuid));
+ return status;
+}
+
+status_t ParcelUuid::readFromParcel(const Parcel* parcel) {
+ int64_t uuid_msb, uuid_lsb;
+
+ status_t status = parcel->readInt64(&uuid_msb);
+ if (status != OK) return status;
+
+ status = parcel->readInt64(&uuid_lsb);
+ if (status != OK) return status;
+
+ std::array<uint8_t, Uuid::kNumBytes128> uu;
+ for (int i = 0; i < 8; i++) {
+ uu[7 - i] = (uuid_msb >> (8 * i)) & 0xFF;
+ uu[15 - i] = (uuid_lsb >> (8 * i)) & 0xFF;
+ }
+
+ uuid = Uuid::From128BitBE(uu);
+ return OK;
+}
+
+} // namespace os
+} // namespace android
\ No newline at end of file
diff --git a/binder/android/os/parcel_uuid.h b/binder/android/os/parcel_uuid.h
new file mode 100644
index 0000000..76bf9c4
--- /dev/null
+++ b/binder/android/os/parcel_uuid.h
@@ -0,0 +1,49 @@
+//
+// Copyright 2017, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <bluetooth/uuid.h>
+
+namespace android {
+namespace os {
+
+class ParcelUuid : public android::Parcelable {
+ public:
+ ParcelUuid() = default;
+ ~ParcelUuid() = default;
+
+ // Write |this| parcelable to the given |parcel|. Keep in mind that
+ // implementations of writeToParcel must be manually kept in sync
+ // with readFromParcel and the Java equivalent versions of these methods.
+ //
+ // Returns android::OK on success and an appropriate error otherwise.
+ android::status_t writeToParcel(android::Parcel* parcel) const override;
+
+ // Read data from the given |parcel| into |this|. After readFromParcel
+ // completes, |this| should have equivalent state to the object that
+ // wrote itself to the parcel.
+ //
+ // Returns android::OK on success and an appropriate error otherwise.
+ android::status_t readFromParcel(const android::Parcel* parcel) override;
+
+ ::bluetooth::Uuid uuid;
+};
+
+} // namespace os
+} // namespace android
diff --git a/bta/Android.bp b/bta/Android.bp
index a69e174..d6919de 100644
--- a/bta/Android.bp
+++ b/bta/Android.bp
@@ -12,8 +12,10 @@
"system/bt",
"system/bt/bta/include",
"system/bt/btcore/include",
+ "system/bt/btif/avrcp",
+ "system/bt/btif/include",
"system/bt/hci/include",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/stack/include",
"system/bt/stack/btm",
"system/bt/udrv/include",
@@ -23,6 +25,7 @@
shared_libs: [
"libcutils",
],
+ header_libs: ["libbluetooth_headers"],
cflags: ["-DBUILDCFG"],
}
@@ -36,7 +39,6 @@
"ag/bta_ag_api.cc",
"ag/bta_ag_at.cc",
"ag/bta_ag_cfg.cc",
- "ag/bta_ag_ci.cc",
"ag/bta_ag_cmd.cc",
"ag/bta_ag_main.cc",
"ag/bta_ag_rfc.cc",
@@ -56,16 +58,18 @@
"dm/bta_dm_ci.cc",
"dm/bta_dm_main.cc",
"dm/bta_dm_pm.cc",
- "dm/bta_dm_sco.cc",
"gatt/bta_gattc_act.cc",
"gatt/bta_gattc_api.cc",
"gatt/bta_gattc_cache.cc",
"gatt/bta_gattc_main.cc",
+ "gatt/bta_gattc_queue.cc",
"gatt/bta_gattc_utils.cc",
"gatt/bta_gatts_act.cc",
"gatt/bta_gatts_api.cc",
"gatt/bta_gatts_main.cc",
"gatt/bta_gatts_utils.cc",
+ "hearing_aid/hearing_aid.cc",
+ "hearing_aid/hearing_aid_audio_source.cc",
"hf_client/bta_hf_client_act.cc",
"hf_client/bta_hf_client_api.cc",
"hf_client/bta_hf_client_at.cc",
@@ -91,7 +95,6 @@
"jv/bta_jv_act.cc",
"jv/bta_jv_api.cc",
"jv/bta_jv_cfg.cc",
- "jv/bta_jv_main.cc",
"mce/bta_mce_act.cc",
"mce/bta_mce_api.cc",
"mce/bta_mce_cfg.cc",
@@ -108,6 +111,13 @@
"sys/bta_sys_main.cc",
"sys/utl.cc",
],
+ static_libs: [
+ "avrcp-target-service",
+ "lib-bt-packets",
+ ],
+ whole_static_libs: [
+ "libaudio-hearing-aid-hw-utils",
+ ],
}
// bta unit tests for target
@@ -117,9 +127,9 @@
defaults: ["fluoride_bta_defaults"],
srcs: [
"test/bta_hf_client_test.cc",
+ "test/gatt_cache_file_test.cc",
],
shared_libs: [
- "libhardware",
"liblog",
"libprotobuf-cpp-lite",
],
@@ -127,7 +137,7 @@
"libbtcore",
"libbt-bta",
"libbluetooth-types",
+ "libbt-protos-lite",
"libosi",
- "libbt-protos",
],
}
diff --git a/bta/BUILD.gn b/bta/BUILD.gn
index 07779d0..fa85e40 100644
--- a/bta/BUILD.gn
+++ b/bta/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -40,12 +40,12 @@
"dm/bta_dm_ci.cc",
"dm/bta_dm_main.cc",
"dm/bta_dm_pm.cc",
- "dm/bta_dm_sco.cc",
"gatt/bta_gattc_act.cc",
"gatt/bta_gattc_api.cc",
"gatt/bta_gattc_cache.cc",
"gatt/bta_gattc_main.cc",
"gatt/bta_gattc_utils.cc",
+ "gatt/bta_gattc_queue.cc",
"gatt/bta_gatts_act.cc",
"gatt/bta_gatts_api.cc",
"gatt/bta_gatts_main.cc",
@@ -75,7 +75,6 @@
"jv/bta_jv_act.cc",
"jv/bta_jv_api.cc",
"jv/bta_jv_cfg.cc",
- "jv/bta_jv_main.cc",
"mce/bta_mce_act.cc",
"mce/bta_mce_api.cc",
"mce/bta_mce_cfg.cc",
@@ -103,7 +102,7 @@
"//",
"//btcore/include",
"//hci/include",
- "//include",
+ "//internal_include",
"//stack/include",
"//stack/btm",
"//udrv/include",
diff --git a/bta/ag/bta_ag_act.cc b/bta/ag/bta_ag_act.cc
index ad40c5d..84860f9 100644
--- a/bta/ag/bta_ag_act.cc
+++ b/bta/ag/bta_ag_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,14 +22,14 @@
*
******************************************************************************/
-#include <string.h>
+#include <cstring>
#include "bta_ag_api.h"
-#include "bta_ag_co.h"
#include "bta_ag_int.h"
#include "bta_api.h"
#include "bta_dm_api.h"
#include "bta_sys.h"
+#include "btif_config.h"
#include "l2c_api.h"
#include "osi/include/osi.h"
#include "port_api.h"
@@ -74,22 +74,16 @@
* Returns void
*
******************************************************************************/
-static void bta_ag_cback_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data,
+static void bta_ag_cback_open(tBTA_AG_SCB* p_scb, const RawAddress& bd_addr,
tBTA_AG_STATUS status) {
- tBTA_AG_OPEN open;
+ tBTA_AG_OPEN open = {};
/* call app callback with open event */
open.hdr.handle = bta_ag_scb_to_idx(p_scb);
open.hdr.app_id = p_scb->app_id;
open.status = status;
open.service_id = bta_ag_svc_id[p_scb->conn_service];
- if (p_data) {
- /* if p_data is provided then we need to pick the bd address from the open
- * api structure */
- open.bd_addr = p_data->api_open.bd_addr;
- } else {
- open.bd_addr = p_scb->peer_addr;
- }
+ open.bd_addr = bd_addr;
(*bta_ag_cb.p_cback)(BTA_AG_OPEN_EVT, (tBTA_AG*)&open);
}
@@ -105,22 +99,21 @@
* Returns void
*
******************************************************************************/
-void bta_ag_register(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
- tBTA_AG_REGISTER reg;
-
+void bta_ag_register(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
/* initialize control block */
- p_scb->reg_services = p_data->api_register.services;
- p_scb->serv_sec_mask = p_data->api_register.sec_mask;
- p_scb->features = p_data->api_register.features;
- p_scb->app_id = p_data->api_register.app_id;
+ p_scb->reg_services = data.api_register.services;
+ p_scb->serv_sec_mask = data.api_register.sec_mask;
+ p_scb->features = data.api_register.features;
+ p_scb->app_id = data.api_register.app_id;
/* create SDP records */
- bta_ag_create_records(p_scb, p_data);
+ bta_ag_create_records(p_scb, data);
/* start RFCOMM servers */
bta_ag_start_servers(p_scb, p_scb->reg_services);
/* call app callback with register event */
+ tBTA_AG_REGISTER reg = {};
reg.hdr.handle = bta_ag_scb_to_idx(p_scb);
reg.hdr.app_id = p_scb->app_id;
reg.status = BTA_AG_SUCCESS;
@@ -138,12 +131,12 @@
* Returns void
*
******************************************************************************/
-void bta_ag_deregister(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_deregister(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
/* set dealloc */
p_scb->dealloc = true;
/* remove sdp records */
- bta_ag_del_records(p_scb, p_data);
+ bta_ag_del_records(p_scb);
/* remove rfcomm servers */
bta_ag_close_servers(p_scb, p_scb->reg_services);
@@ -162,12 +155,12 @@
* Returns void
*
******************************************************************************/
-void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
/* set dealloc */
p_scb->dealloc = true;
/* remove sdp records */
- bta_ag_del_records(p_scb, p_data);
+ bta_ag_del_records(p_scb);
}
/*******************************************************************************
@@ -180,22 +173,20 @@
* Returns void
*
******************************************************************************/
-void bta_ag_start_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
- RawAddress pending_bd_addr;
+void bta_ag_start_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
+ RawAddress pending_bd_addr = {};
/* store parameters */
- if (p_data) {
- p_scb->peer_addr = p_data->api_open.bd_addr;
- p_scb->open_services = p_data->api_open.services;
- p_scb->cli_sec_mask = p_data->api_open.sec_mask;
- }
+ p_scb->peer_addr = data.api_open.bd_addr;
+ p_scb->cli_sec_mask = data.api_open.sec_mask;
+ p_scb->open_services = p_scb->reg_services;
/* Check if RFCOMM has any incoming connection to avoid collision. */
if (PORT_IsOpening(pending_bd_addr)) {
/* Let the incoming connection goes through. */
/* Issue collision for this scb for now. */
/* We will decide what to do when we find incoming connetion later. */
- bta_ag_collision_cback(0, BTA_ID_AG, 0, &p_scb->peer_addr);
+ bta_ag_collision_cback(0, BTA_ID_AG, 0, p_scb->peer_addr);
return;
}
@@ -219,15 +210,14 @@
* Returns void
*
******************************************************************************/
-void bta_ag_disc_int_res(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_disc_int_res(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
uint16_t event = BTA_AG_DISC_FAIL_EVT;
- APPL_TRACE_DEBUG("bta_ag_disc_int_res: Status: %d",
- p_data->disc_result.status);
+ APPL_TRACE_DEBUG("bta_ag_disc_int_res: Status: %d", data.disc_result.status);
/* if found service */
- if (p_data->disc_result.status == SDP_SUCCESS ||
- p_data->disc_result.status == SDP_DB_FULL) {
+ if (data.disc_result.status == SDP_SUCCESS ||
+ data.disc_result.status == SDP_DB_FULL) {
/* get attributes */
if (bta_ag_sdp_find_attr(p_scb, p_scb->open_services)) {
/* set connected service */
@@ -239,13 +229,13 @@
}
/* free discovery db */
- bta_ag_free_db(p_scb, p_data);
+ bta_ag_free_db(p_scb, data);
/* if service not found check if we should search for other service */
if ((event == BTA_AG_DISC_FAIL_EVT) &&
- (p_data->disc_result.status == SDP_SUCCESS ||
- p_data->disc_result.status == SDP_DB_FULL ||
- p_data->disc_result.status == SDP_NO_RECS_MATCH)) {
+ (data.disc_result.status == SDP_SUCCESS ||
+ data.disc_result.status == SDP_DB_FULL ||
+ data.disc_result.status == SDP_NO_RECS_MATCH)) {
if ((p_scb->open_services & BTA_HFP_SERVICE_MASK) &&
(p_scb->open_services & BTA_HSP_SERVICE_MASK)) {
/* search for HSP */
@@ -258,11 +248,11 @@
bta_ag_do_disc(p_scb, p_scb->open_services);
} else {
/* send ourselves sdp ok/fail event */
- bta_ag_sm_execute(p_scb, event, p_data);
+ bta_ag_sm_execute(p_scb, event, data);
}
} else {
/* send ourselves sdp ok/fail event */
- bta_ag_sm_execute(p_scb, event, p_data);
+ bta_ag_sm_execute(p_scb, event, data);
}
}
@@ -276,16 +266,16 @@
* Returns void
*
******************************************************************************/
-void bta_ag_disc_acp_res(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_disc_acp_res(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
/* if found service */
- if (p_data->disc_result.status == SDP_SUCCESS ||
- p_data->disc_result.status == SDP_DB_FULL) {
+ if (data.disc_result.status == SDP_SUCCESS ||
+ data.disc_result.status == SDP_DB_FULL) {
/* get attributes */
bta_ag_sdp_find_attr(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
}
/* free discovery db */
- bta_ag_free_db(p_scb, p_data);
+ bta_ag_free_db(p_scb, data);
}
/*******************************************************************************
@@ -298,17 +288,19 @@
* Returns void
*
******************************************************************************/
-void bta_ag_disc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
+void bta_ag_disc_fail(tBTA_AG_SCB* p_scb,
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
/* reopen registered servers */
bta_ag_start_servers(p_scb, p_scb->reg_services);
/* reinitialize stuff */
/* clear the remote BD address */
+ RawAddress peer_addr = p_scb->peer_addr;
p_scb->peer_addr = RawAddress::kEmpty;
/* call open cback w. failure */
- bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP);
+ bta_ag_cback_open(p_scb, peer_addr, BTA_AG_FAIL_SDP);
}
/*******************************************************************************
@@ -321,9 +313,9 @@
* Returns void
*
******************************************************************************/
-void bta_ag_open_fail(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_open_fail(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
/* call open cback w. failure */
- bta_ag_cback_open(p_scb, p_data, BTA_AG_FAIL_RESOURCES);
+ bta_ag_cback_open(p_scb, data.api_open.bd_addr, BTA_AG_FAIL_RESOURCES);
}
/*******************************************************************************
@@ -336,7 +328,8 @@
* Returns void
*
******************************************************************************/
-void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
+void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
+ RawAddress peer_addr = p_scb->peer_addr;
/* reinitialize stuff */
p_scb->conn_handle = 0;
p_scb->conn_service = 0;
@@ -353,7 +346,7 @@
bta_ag_start_servers(p_scb, p_scb->reg_services);
/* call open cback w. failure */
- bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_RFCOMM);
+ bta_ag_cback_open(p_scb, peer_addr, BTA_AG_FAIL_RFCOMM);
}
/*******************************************************************************
@@ -366,8 +359,9 @@
* Returns void
*
******************************************************************************/
-void bta_ag_rfc_close(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
- tBTA_AG_CLOSE close;
+void bta_ag_rfc_close(tBTA_AG_SCB* p_scb,
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
+ tBTA_AG_CLOSE close = {};
tBTA_SERVICE_MASK services;
int i, num_active_conn = 0;
@@ -386,8 +380,12 @@
p_scb->hsp_version = HSP_VERSION_1_2;
bta_ag_at_reinit(&p_scb->at_cb);
- memset(&(p_scb->peer_hf_indicators), 0, sizeof(p_scb->peer_hf_indicators));
- memset(&(p_scb->local_hf_indicators), 0, sizeof(p_scb->local_hf_indicators));
+ for (auto& peer_hf_indicator : p_scb->peer_hf_indicators) {
+ peer_hf_indicator = {};
+ }
+ for (auto& local_hf_indicator : p_scb->local_hf_indicators) {
+ local_hf_indicator = {};
+ }
/* stop timers */
alarm_cancel(p_scb->ring_timer);
@@ -399,14 +397,15 @@
bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
- /* call close call-out */
- bta_ag_co_data_close(close.hdr.handle);
+ if (bta_ag_get_active_device() == p_scb->peer_addr) {
+ bta_clear_active_device();
+ }
/* call close cback */
(*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG*)&close);
/* if not deregistering (deallocating) reopen registered servers */
- if (p_scb->dealloc == false) {
+ if (!p_scb->dealloc) {
/* Clear peer bd_addr so instance can be reused */
p_scb->peer_addr = RawAddress::kEmpty;
@@ -421,10 +420,10 @@
p_scb->conn_handle = 0;
/* Make sure SCO state is BTA_AG_SCO_SHUTDOWN_ST */
- bta_ag_sco_shutdown(p_scb, NULL);
+ bta_ag_sco_shutdown(p_scb, tBTA_AG_DATA::kEmpty);
/* Check if all the SLCs are down */
- for (i = 0; i < BTA_AG_NUM_SCB; i++) {
+ for (i = 0; i < BTA_AG_MAX_NUM_CLIENTS; i++) {
if (bta_ag_cb.scb[i].in_use && bta_ag_cb.scb[i].svc_conn)
num_active_conn++;
}
@@ -451,7 +450,7 @@
* Returns void
*
******************************************************************************/
-void bta_ag_rfc_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_rfc_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
/* initialize AT feature variables */
p_scb->clip_enabled = false;
p_scb->ccwa_enabled = false;
@@ -459,23 +458,42 @@
p_scb->cmee_enabled = false;
p_scb->inband_enabled =
((p_scb->features & BTA_AG_FEAT_INBAND) == BTA_AG_FEAT_INBAND);
+ if (p_scb->conn_service == BTA_AG_HFP) {
+ size_t version_value_size = sizeof(p_scb->peer_version);
+ if (!btif_config_get_bin(
+ p_scb->peer_addr.ToString(), HFP_VERSION_CONFIG_KEY,
+ (uint8_t*)&p_scb->peer_version, &version_value_size)) {
+ APPL_TRACE_WARNING("%s: Failed read cached peer HFP version for %s",
+ __func__, p_scb->peer_addr.ToString().c_str());
+ p_scb->peer_version = HFP_HSP_VERSION_UNKNOWN;
+ }
+ size_t sdp_features_size = sizeof(p_scb->peer_sdp_features);
+ if (btif_config_get_bin(
+ p_scb->peer_addr.ToString(), HFP_SDP_FEATURES_CONFIG_KEY,
+ (uint8_t*)&p_scb->peer_sdp_features, &sdp_features_size)) {
+ bool sdp_wbs_support = p_scb->peer_sdp_features & BTA_AG_FEAT_WBS_SUPPORT;
+ if (!p_scb->received_at_bac && sdp_wbs_support) {
+ p_scb->codec_updated = true;
+ p_scb->peer_codecs = BTA_AG_CODEC_CVSD & BTA_AG_CODEC_MSBC;
+ p_scb->sco_codec = UUID_CODEC_MSBC;
+ }
+ } else {
+ APPL_TRACE_WARNING("%s: Failed read cached peer HFP SDP features for %s",
+ __func__, p_scb->peer_addr.ToString().c_str());
+ }
+ }
/* set up AT command interpreter */
- p_scb->at_cb.p_at_tbl = (tBTA_AG_AT_CMD*)bta_ag_at_tbl[p_scb->conn_service];
- p_scb->at_cb.p_cmd_cback =
- (tBTA_AG_AT_CMD_CBACK*)bta_ag_at_cback_tbl[p_scb->conn_service];
- p_scb->at_cb.p_err_cback = (tBTA_AG_AT_ERR_CBACK*)bta_ag_at_err_cback;
+ p_scb->at_cb.p_at_tbl = bta_ag_at_tbl[p_scb->conn_service];
+ p_scb->at_cb.p_cmd_cback = bta_ag_at_cback_tbl[p_scb->conn_service];
+ p_scb->at_cb.p_err_cback = bta_ag_at_err_cback;
p_scb->at_cb.p_user = p_scb;
p_scb->at_cb.cmd_max_len = BTA_AG_CMD_MAX;
bta_ag_at_init(&p_scb->at_cb);
- /* call app open call-out */
- bta_ag_co_data_open(bta_ag_scb_to_idx(p_scb),
- bta_ag_svc_id[p_scb->conn_service]);
-
bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
- bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS);
+ bta_ag_cback_open(p_scb, p_scb->peer_addr, BTA_AG_SUCCESS);
if (p_scb->conn_service == BTA_AG_HFP) {
/* if hfp start timer for service level conn */
@@ -483,7 +501,7 @@
BTA_AG_SVC_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));
} else {
/* else service level conn is open */
- bta_ag_svc_conn_open(p_scb, p_data);
+ bta_ag_svc_conn_open(p_scb, data);
}
}
@@ -497,13 +515,7 @@
* Returns void
*
******************************************************************************/
-void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
- uint16_t lcid;
- int i;
- tBTA_AG_SCB *ag_scb, *other_scb;
- RawAddress dev_addr;
- int status;
-
+void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
/* set role */
p_scb->role = BTA_AG_ACP;
@@ -511,49 +523,59 @@
p_scb->serv_handle[0], p_scb->serv_handle[1]);
/* get bd addr of peer */
- if (PORT_SUCCESS != (status = PORT_CheckConnection(p_data->rfc.port_handle,
- dev_addr, &lcid))) {
- APPL_TRACE_DEBUG(
- "bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d",
- status);
+ uint16_t lcid = 0;
+ RawAddress dev_addr = RawAddress::kEmpty;
+ int status = PORT_CheckConnection(data.rfc.port_handle, dev_addr, &lcid);
+ if (status != PORT_SUCCESS) {
+ LOG(ERROR) << __func__ << ", PORT_CheckConnection returned " << status;
+ return;
}
/* Collision Handling */
- for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++) {
- if (ag_scb->in_use && alarm_is_scheduled(ag_scb->collision_timer)) {
- alarm_cancel(ag_scb->collision_timer);
-
- if (dev_addr == ag_scb->peer_addr) {
- /* If incoming and outgoing device are same, nothing more to do. */
- /* Outgoing conn will be aborted because we have successful incoming
- * conn. */
- } else {
- /* Resume outgoing connection. */
- other_scb = bta_ag_get_other_idle_scb(p_scb);
- if (other_scb) {
- other_scb->peer_addr = ag_scb->peer_addr;
- other_scb->open_services = ag_scb->open_services;
- other_scb->cli_sec_mask = ag_scb->cli_sec_mask;
-
- bta_ag_resume_open(other_scb);
+ for (tBTA_AG_SCB& ag_scb : bta_ag_cb.scb) {
+ // Cancel any pending collision timers
+ if (ag_scb.in_use && alarm_is_scheduled(ag_scb.collision_timer)) {
+ VLOG(1) << __func__ << ": cancel collision alarm for "
+ << ag_scb.peer_addr;
+ alarm_cancel(ag_scb.collision_timer);
+ if (dev_addr != ag_scb.peer_addr && p_scb != &ag_scb) {
+ // Resume outgoing connection if incoming is not on the same device
+ bta_ag_resume_open(&ag_scb);
+ }
+ }
+ if (dev_addr == ag_scb.peer_addr && p_scb != &ag_scb) {
+ VLOG(1) << __func__ << ": fail outgoing connection before accepting "
+ << ag_scb.peer_addr;
+ // Fail the outgoing connection to clean up any upper layer states
+ bta_ag_rfc_fail(&ag_scb, tBTA_AG_DATA::kEmpty);
+ // If client port is opened, close it
+ if (ag_scb.conn_handle > 0) {
+ status = RFCOMM_RemoveConnection(ag_scb.conn_handle);
+ if (status != PORT_SUCCESS) {
+ LOG(WARNING) << __func__ << ": RFCOMM_RemoveConnection failed for "
+ << dev_addr << ", handle "
+ << std::to_string(ag_scb.conn_handle) << ", error "
+ << status;
}
}
-
- break;
}
+ VLOG(1) << __func__ << ": dev_addr=" << dev_addr
+ << ", peer_addr=" << ag_scb.peer_addr
+ << ", in_use=" << ag_scb.in_use
+ << ", index=" << bta_ag_scb_to_idx(p_scb);
}
p_scb->peer_addr = dev_addr;
/* determine connected service from port handle */
- for (i = 0; i < BTA_AG_NUM_IDX; i++) {
+ for (int i = 0; i < BTA_AG_NUM_IDX; i++) {
APPL_TRACE_DEBUG(
"bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d", i,
- p_scb->serv_handle[i], p_data->rfc.port_handle);
+ p_scb->serv_handle[i], data.rfc.port_handle);
- if (p_scb->serv_handle[i] == p_data->rfc.port_handle) {
+ if (p_scb->serv_handle[i] == data.rfc.port_handle) {
p_scb->conn_service = i;
- p_scb->conn_handle = p_data->rfc.port_handle;
+ p_scb->conn_handle = data.rfc.port_handle;
break;
}
}
@@ -569,7 +591,7 @@
bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
/* continue with common open processing */
- bta_ag_rfc_open(p_scb, p_data);
+ bta_ag_rfc_open(p_scb, data);
}
/*******************************************************************************
@@ -582,11 +604,9 @@
* Returns void
*
******************************************************************************/
-void bta_ag_rfc_data(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
+void bta_ag_rfc_data(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
uint16_t len;
- char buf[BTA_AG_RFC_READ_MAX];
-
- memset(buf, 0, BTA_AG_RFC_READ_MAX);
+ char buf[BTA_AG_RFC_READ_MAX] = "";
APPL_TRACE_DEBUG("%s", __func__);
@@ -595,11 +615,13 @@
/* read data from rfcomm; if bad status, we're done */
if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) !=
PORT_SUCCESS) {
+ LOG(ERROR) << __func__ << ": failed to read data " << p_scb->peer_addr;
break;
}
/* if no data, we're done */
if (len == 0) {
+ LOG(WARNING) << __func__ << ": no data for " << p_scb->peer_addr;
break;
}
@@ -631,7 +653,7 @@
* Returns void
*
******************************************************************************/
-void bta_ag_start_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_start_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
/* Take the link out of sniff and set L2C idle time to 0 */
bta_dm_pm_active(p_scb->peer_addr);
L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0, BT_TRANSPORT_BR_EDR);
@@ -641,11 +663,11 @@
p_scb->post_sco = BTA_AG_POST_SCO_CLOSE_RFC;
} else {
p_scb->post_sco = BTA_AG_POST_SCO_NONE;
- bta_ag_rfc_do_close(p_scb, p_data);
+ bta_ag_rfc_do_close(p_scb, data);
}
/* always do SCO shutdown to handle all SCO corner cases */
- bta_ag_sco_shutdown(p_scb, p_data);
+ bta_ag_sco_shutdown(p_scb, data);
}
/*******************************************************************************
@@ -658,10 +680,10 @@
* Returns void
*
******************************************************************************/
-void bta_ag_post_sco_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_post_sco_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
switch (p_scb->post_sco) {
case BTA_AG_POST_SCO_RING:
- bta_ag_send_ring(p_scb, p_data);
+ bta_ag_send_ring(p_scb, data);
p_scb->post_sco = BTA_AG_POST_SCO_NONE;
break;
@@ -685,10 +707,10 @@
* Returns void
*
******************************************************************************/
-void bta_ag_post_sco_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_post_sco_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
switch (p_scb->post_sco) {
case BTA_AG_POST_SCO_CLOSE_RFC:
- bta_ag_rfc_do_close(p_scb, p_data);
+ bta_ag_rfc_do_close(p_scb, data);
p_scb->post_sco = BTA_AG_POST_SCO_NONE;
break;
@@ -716,10 +738,10 @@
if (bta_ag_inband_enabled(p_scb) &&
!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
p_scb->post_sco = BTA_AG_POST_SCO_RING;
- bta_ag_sco_open(p_scb, p_data);
+ bta_ag_sco_open(p_scb, data);
} else {
p_scb->post_sco = BTA_AG_POST_SCO_NONE;
- bta_ag_send_ring(p_scb, p_data);
+ bta_ag_send_ring(p_scb, data);
}
break;
@@ -739,8 +761,8 @@
*
******************************************************************************/
void bta_ag_svc_conn_open(tBTA_AG_SCB* p_scb,
- UNUSED_ATTR tBTA_AG_DATA* p_data) {
- tBTA_AG_CONN evt;
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
+ tBTA_AG_CONN evt = {};
if (!p_scb->svc_conn) {
/* set state variable */
@@ -762,61 +784,15 @@
(p_scb->callsetup_ind != BTA_AG_CALLSETUP_NONE)) {
bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
}
-
+ if (bta_ag_get_active_device().IsEmpty()) {
+ bta_ag_api_set_active_device(p_scb->peer_addr);
+ }
(*bta_ag_cb.p_cback)(BTA_AG_CONN_EVT, (tBTA_AG*)&evt);
}
}
/*******************************************************************************
*
- * Function bta_ag_ci_rx_data
- *
- * Description Send result code
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_ag_ci_rx_data(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
- uint16_t len;
- tBTA_AG_CI_RX_WRITE* p_rx_write_msg = (tBTA_AG_CI_RX_WRITE*)p_data;
- char* p_data_area =
- (char*)(p_rx_write_msg + 1); /* Point to data area after header */
-
- APPL_TRACE_DEBUG("bta_ag_ci_rx_data:");
- /* send to RFCOMM */
- bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
- PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len);
- if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) && bta_ag_sco_is_open(p_scb)) {
- APPL_TRACE_DEBUG("bta_ag_rfc_data, change link policy for SCO");
- bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
- } else {
- bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
- }
-}
-
-/*******************************************************************************
- *
- * Function bta_ag_rcvd_slc_ready
- *
- * Description Handles SLC ready call-in in case of pass-through mode.
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_ag_rcvd_slc_ready(tBTA_AG_SCB* p_scb,
- UNUSED_ATTR tBTA_AG_DATA* p_data) {
- APPL_TRACE_DEBUG("bta_ag_rcvd_slc_ready: handle = %d",
- bta_ag_scb_to_idx(p_scb));
-
- if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH) {
- /* In pass-through mode, BTA knows that SLC is ready only through call-in.
- */
- bta_ag_svc_conn_open(p_scb, NULL);
- }
-}
-
-/*******************************************************************************
- *
* Function bta_ag_setcodec
*
* Description Handle API SetCodec
@@ -825,9 +801,10 @@
* Returns void
*
******************************************************************************/
-void bta_ag_setcodec(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
- tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec;
- tBTA_AG_VAL val;
+void bta_ag_setcodec(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
+ tBTA_AG_PEER_CODEC codec_type = data.api_setcodec.codec;
+ tBTA_AG_VAL val = {};
+ val.hdr.handle = bta_ag_scb_to_idx(p_scb);
/* Check if the requested codec type is valid */
if ((codec_type != BTA_AG_CODEC_NONE) && (codec_type != BTA_AG_CODEC_CVSD) &&
@@ -856,3 +833,32 @@
(*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG*)&val);
}
+
+static void bta_ag_collision_timer_cback(void* data) {
+ if (data == nullptr) {
+ LOG(ERROR) << __func__ << ": data should never be null in a timer callback";
+ return;
+ }
+ /* If the peer haven't opened AG connection */
+ /* we will restart opening process. */
+ bta_ag_resume_open(static_cast<tBTA_AG_SCB*>(data));
+}
+
+void bta_ag_handle_collision(tBTA_AG_SCB* p_scb,
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
+ /* Cancel SDP if it had been started. */
+ if (p_scb->p_disc_db) {
+ SDP_CancelServiceSearch(p_scb->p_disc_db);
+ bta_ag_free_db(p_scb, tBTA_AG_DATA::kEmpty);
+ }
+
+ /* reopen registered servers */
+ /* Collision may be detected before or after we close servers. */
+ if (bta_ag_is_server_closed(p_scb)) {
+ bta_ag_start_servers(p_scb, p_scb->reg_services);
+ }
+
+ /* Start timer to han */
+ alarm_set_on_mloop(p_scb->collision_timer, BTA_AG_COLLISION_TIMEOUT_MS,
+ bta_ag_collision_timer_cback, p_scb);
+}
diff --git a/bta/ag/bta_ag_api.cc b/bta/ag/bta_ag_api.cc
index 4c0e285..7497fa7 100644
--- a/bta/ag/bta_ag_api.cc
+++ b/bta/ag/bta_ag_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,8 @@
******************************************************************************/
#include "bta_ag_api.h"
-#include <string.h>
+#include <base/bind.h>
+#include <cstring>
#include "bt_common.h"
#include "bta_ag_int.h"
#include "bta_api.h"
@@ -36,6 +37,7 @@
****************************************************************************/
static const tBTA_SYS_REG bta_ag_reg = {bta_ag_hdl_event, BTA_AgDisable};
+const tBTA_AG_RES_DATA tBTA_AG_RES_DATA::kEmpty = {};
/*******************************************************************************
*
@@ -50,27 +52,16 @@
* Returns BTA_SUCCESS if OK, BTA_FAILURE otherwise.
*
******************************************************************************/
-tBTA_STATUS BTA_AgEnable(tBTA_AG_PARSE_MODE parse_mode,
- tBTA_AG_CBACK* p_cback) {
+tBTA_STATUS BTA_AgEnable(tBTA_AG_CBACK* p_cback) {
/* Error if AG is already enabled, or AG is in the middle of disabling. */
- for (int idx = 0; idx < BTA_AG_NUM_SCB; idx++) {
- if (bta_ag_cb.scb[idx].in_use) {
+ for (const tBTA_AG_SCB& scb : bta_ag_cb.scb) {
+ if (scb.in_use) {
APPL_TRACE_ERROR("BTA_AgEnable: FAILED, AG already enabled.");
return BTA_FAILURE;
}
}
-
- /* register with BTA system manager */
bta_sys_register(BTA_ID_AG, &bta_ag_reg);
-
- tBTA_AG_API_ENABLE* p_buf =
- (tBTA_AG_API_ENABLE*)osi_malloc(sizeof(tBTA_AG_API_ENABLE));
- p_buf->hdr.event = BTA_AG_API_ENABLE_EVT;
- p_buf->parse_mode = parse_mode;
- p_buf->p_cback = p_cback;
-
- bta_sys_sendmsg(p_buf);
-
+ do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_api_enable, p_cback));
return BTA_SUCCESS;
}
@@ -84,12 +75,8 @@
* Returns void
*
******************************************************************************/
-void BTA_AgDisable(void) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = BTA_AG_API_DISABLE_EVT;
-
- bta_sys_sendmsg(p_buf);
+void BTA_AgDisable() {
+ do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_api_disable));
}
/*******************************************************************************
@@ -103,24 +90,12 @@
*
******************************************************************************/
void BTA_AgRegister(tBTA_SERVICE_MASK services, tBTA_SEC sec_mask,
- tBTA_AG_FEAT features, const char* p_service_names[],
+ tBTA_AG_FEAT features,
+ const std::vector<std::string>& service_names,
uint8_t app_id) {
- tBTA_AG_API_REGISTER* p_buf =
- (tBTA_AG_API_REGISTER*)osi_malloc(sizeof(tBTA_AG_API_REGISTER));
-
- p_buf->hdr.event = BTA_AG_API_REGISTER_EVT;
- p_buf->features = features;
- p_buf->sec_mask = sec_mask;
- p_buf->services = services;
- p_buf->app_id = app_id;
- for (int i = 0; i < BTA_AG_NUM_IDX; i++) {
- if (p_service_names[i])
- strlcpy(p_buf->p_name[i], p_service_names[i], BTA_SERVICE_NAME_LEN);
- else
- p_buf->p_name[i][0] = 0;
- }
-
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(&bta_ag_api_register, services, sec_mask, features,
+ service_names, app_id));
}
/*******************************************************************************
@@ -134,12 +109,9 @@
*
******************************************************************************/
void BTA_AgDeregister(uint16_t handle) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = BTA_AG_API_DEREGISTER_EVT;
- p_buf->layer_specific = handle;
-
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&bta_ag_sm_execute_by_handle, handle,
+ BTA_AG_API_DEREGISTER_EVT, tBTA_AG_DATA::kEmpty));
}
/*******************************************************************************
@@ -155,18 +127,12 @@
* Returns void
*
******************************************************************************/
-void BTA_AgOpen(uint16_t handle, const RawAddress& bd_addr, tBTA_SEC sec_mask,
- tBTA_SERVICE_MASK services) {
- tBTA_AG_API_OPEN* p_buf =
- (tBTA_AG_API_OPEN*)osi_malloc(sizeof(tBTA_AG_API_OPEN));
-
- p_buf->hdr.event = BTA_AG_API_OPEN_EVT;
- p_buf->hdr.layer_specific = handle;
- p_buf->bd_addr = bd_addr;
- p_buf->services = services;
- p_buf->sec_mask = sec_mask;
-
- bta_sys_sendmsg(p_buf);
+void BTA_AgOpen(uint16_t handle, const RawAddress& bd_addr, tBTA_SEC sec_mask) {
+ tBTA_AG_DATA data = {};
+ data.api_open.bd_addr = bd_addr;
+ data.api_open.sec_mask = sec_mask;
+ do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
+ BTA_AG_API_OPEN_EVT, data));
}
/*******************************************************************************
@@ -181,12 +147,9 @@
*
******************************************************************************/
void BTA_AgClose(uint16_t handle) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = BTA_AG_API_CLOSE_EVT;
- p_buf->layer_specific = handle;
-
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&bta_ag_sm_execute_by_handle, handle,
+ BTA_AG_API_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
}
/*******************************************************************************
@@ -201,12 +164,9 @@
*
******************************************************************************/
void BTA_AgAudioOpen(uint16_t handle) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = BTA_AG_API_AUDIO_OPEN_EVT;
- p_buf->layer_specific = handle;
-
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&bta_ag_sm_execute_by_handle, handle,
+ BTA_AG_API_AUDIO_OPEN_EVT, tBTA_AG_DATA::kEmpty));
}
/*******************************************************************************
@@ -221,12 +181,9 @@
*
******************************************************************************/
void BTA_AgAudioClose(uint16_t handle) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = BTA_AG_API_AUDIO_CLOSE_EVT;
- p_buf->layer_specific = handle;
-
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
+ BTA_AG_API_AUDIO_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
}
/*******************************************************************************
@@ -242,16 +199,9 @@
*
******************************************************************************/
void BTA_AgResult(uint16_t handle, tBTA_AG_RES result,
- tBTA_AG_RES_DATA* p_data) {
- tBTA_AG_API_RESULT* p_buf =
- (tBTA_AG_API_RESULT*)osi_malloc(sizeof(tBTA_AG_API_RESULT));
-
- p_buf->hdr.event = BTA_AG_API_RESULT_EVT;
- p_buf->hdr.layer_specific = handle;
- p_buf->result = result;
- if (p_data) memcpy(&p_buf->data, p_data, sizeof(p_buf->data));
-
- bta_sys_sendmsg(p_buf);
+ const tBTA_AG_RES_DATA& data) {
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&bta_ag_api_result, handle, result, data));
}
/*******************************************************************************
@@ -267,22 +217,17 @@
*
******************************************************************************/
void BTA_AgSetCodec(uint16_t handle, tBTA_AG_PEER_CODEC codec) {
- tBTA_AG_API_SETCODEC* p_buf =
- (tBTA_AG_API_SETCODEC*)osi_malloc(sizeof(tBTA_AG_API_SETCODEC));
-
- p_buf->hdr.event = BTA_AG_API_SETCODEC_EVT;
- p_buf->hdr.layer_specific = handle;
- p_buf->codec = codec;
-
- bta_sys_sendmsg(p_buf);
+ tBTA_AG_DATA data = {};
+ data.api_setcodec.codec = codec;
+ do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
+ BTA_AG_API_SETCODEC_EVT, data));
}
void BTA_AgSetScoAllowed(bool value) {
- tBTA_AG_API_SET_SCO_ALLOWED* p_buf = (tBTA_AG_API_SET_SCO_ALLOWED*)osi_malloc(
- sizeof(tBTA_AG_API_SET_SCO_ALLOWED));
+ do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_set_sco_allowed, value));
+}
- p_buf->hdr.event = BTA_AG_API_SET_SCO_ALLOWED_EVT;
- p_buf->value = value;
-
- bta_sys_sendmsg(p_buf);
+void BTA_AgSetActiveDevice(const RawAddress& active_device_addr) {
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(&bta_ag_api_set_active_device, active_device_addr));
}
diff --git a/bta/ag/bta_ag_at.cc b/bta/ag/bta_ag_at.cc
index 3e4868b..ecd9053 100644
--- a/bta/ag/bta_ag_at.cc
+++ b/bta/ag/bta_ag_at.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
*
******************************************************************************/
-#include <string.h>
+#include <cstring>
#include "bt_common.h"
#include "bta_ag_at.h"
@@ -43,7 +43,7 @@
*
*****************************************************************************/
void bta_ag_at_init(tBTA_AG_AT_CB* p_cb) {
- p_cb->p_cmd_buf = NULL;
+ p_cb->p_cmd_buf = nullptr;
p_cb->cmd_pos = 0;
}
@@ -129,24 +129,26 @@
if (int_arg < (int16_t)p_cb->p_at_tbl[idx].min ||
int_arg > (int16_t)p_cb->p_at_tbl[idx].max) {
/* arg out of range; error */
- (*p_cb->p_err_cback)(p_cb->p_user, false, NULL);
+ (*p_cb->p_err_cback)((tBTA_AG_SCB*)p_cb->p_user, false, nullptr);
} else {
- (*p_cb->p_cmd_cback)(p_cb->p_user, p_cb->p_at_tbl[idx].command_id,
- arg_type, p_arg, int_arg);
+ (*p_cb->p_cmd_cback)((tBTA_AG_SCB*)p_cb->p_user,
+ p_cb->p_at_tbl[idx].command_id, arg_type, p_arg,
+ int_arg);
}
} else {
- (*p_cb->p_cmd_cback)(p_cb->p_user, p_cb->p_at_tbl[idx].command_id,
- arg_type, p_arg, int_arg);
+ (*p_cb->p_cmd_cback)((tBTA_AG_SCB*)p_cb->p_user,
+ p_cb->p_at_tbl[idx].command_id, arg_type, p_arg,
+ int_arg);
}
}
/* else error */
else {
- (*p_cb->p_err_cback)(p_cb->p_user, false, NULL);
+ (*p_cb->p_err_cback)((tBTA_AG_SCB*)p_cb->p_user, false, nullptr);
}
}
/* else no match call error callback */
else {
- (*p_cb->p_err_cback)(p_cb->p_user, true, p_cb->p_cmd_buf);
+ (*p_cb->p_err_cback)((tBTA_AG_SCB*)p_cb->p_user, true, p_cb->p_cmd_buf);
}
}
@@ -166,7 +168,7 @@
int i = 0;
char* p_save;
- if (p_cb->p_cmd_buf == NULL) {
+ if (p_cb->p_cmd_buf == nullptr) {
p_cb->p_cmd_buf = (char*)osi_malloc(p_cb->cmd_max_len);
p_cb->cmd_pos = 0;
}
@@ -197,7 +199,7 @@
} else if (p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1A ||
p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1B) {
p_cb->p_cmd_buf[++p_cb->cmd_pos] = 0;
- (*p_cb->p_err_cback)(p_cb->p_user, true, p_cb->p_cmd_buf);
+ (*p_cb->p_err_cback)((tBTA_AG_SCB*)p_cb->p_user, true, p_cb->p_cmd_buf);
p_cb->cmd_pos = 0;
} else {
++p_cb->cmd_pos;
diff --git a/bta/ag/bta_ag_at.h b/bta/ag/bta_ag_at.h
index 144bc38..f36e2f2 100644
--- a/bta/ag/bta_ag_at.h
+++ b/bta/ag/bta_ag_at.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,16 +54,18 @@
} tBTA_AG_AT_CMD;
/* callback function executed when command is parsed */
-typedef void(tBTA_AG_AT_CMD_CBACK)(void* p_user, uint16_t command_id,
+struct tBTA_AG_SCB;
+typedef void(tBTA_AG_AT_CMD_CBACK)(tBTA_AG_SCB* p_user, uint16_t command_id,
uint8_t arg_type, char* p_arg,
int16_t int_arg);
/* callback function executed to send "ERROR" result code */
-typedef void(tBTA_AG_AT_ERR_CBACK)(void* p_user, bool unknown, char* p_arg);
+typedef void(tBTA_AG_AT_ERR_CBACK)(tBTA_AG_SCB* p_user, bool unknown,
+ const char* p_arg);
/* AT command parsing control block */
typedef struct {
- tBTA_AG_AT_CMD* p_at_tbl; /* AT command table */
+ const tBTA_AG_AT_CMD* p_at_tbl; /* AT command table */
tBTA_AG_AT_CMD_CBACK* p_cmd_cback; /* command callback */
tBTA_AG_AT_ERR_CBACK* p_err_cback; /* error callback */
void* p_user; /* user-defined data */
diff --git a/bta/ag/bta_ag_cfg.cc b/bta/ag/bta_ag_cfg.cc
index bea4768..abb71b4 100644
--- a/bta/ag/bta_ag_cfg.cc
+++ b/bta/ag/bta_ag_cfg.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
#include "bt_common.h"
#include "bta_ag_api.h"
#include "bta_ag_int.h"
-#include "bta_api.h"
#ifndef BTA_AG_CIND_INFO
#define BTA_AG_CIND_INFO \
@@ -62,11 +61,11 @@
const tBTA_AG_HF_IND bta_ag_local_hf_ind_cfg[] = {
/* The first row contains the number of indicators. Need to be updated
accordingly */
- {BTA_AG_NUM_LOCAL_HF_IND, 0, 0, 0, 0},
+ {BTA_AG_NUM_LOCAL_HF_IND, false, false, 0, 0},
- {1, 1, 1, 0,
+ {1, true, true, 0,
1}, /* Enhanced Driver Status, supported, enabled, range 0 ~ 1 */
- {2, 1, 1, 0,
+ {2, true, true, 0,
100} /* Battery Level Status, supported, enabled, range 0 ~ 100 */
};
@@ -75,4 +74,4 @@
BTA_AG_SCO_PKT_TYPES, BTA_AG_CHLD_VAL_ECC,
BTA_AG_CHLD_VAL};
-tBTA_AG_CFG* p_bta_ag_cfg = (tBTA_AG_CFG*)&bta_ag_cfg;
+const tBTA_AG_CFG* p_bta_ag_cfg = &bta_ag_cfg;
diff --git a/bta/ag/bta_ag_ci.cc b/bta/ag/bta_ag_ci.cc
deleted file mode 100644
index 1fde9d8..0000000
--- a/bta/ag/bta_ag_ci.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2003-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * This is the implementation file for audio gateway call-in functions.
- *
- ******************************************************************************/
-
-#include <string.h>
-
-#include "bt_common.h"
-#include "bta_ag_api.h"
-#include "bta_ag_ci.h"
-#include "bta_ag_int.h"
-#include "bta_api.h"
-
-/******************************************************************************
- *
- * Function bta_ag_ci_rx_write
- *
- * Description This function is called to send data to the AG when the AG
- * is configured for AT command pass-through. The function
- * copies data to an event buffer and sends it.
- *
- * Returns void
- *
- *****************************************************************************/
-void bta_ag_ci_rx_write(uint16_t handle, char* p_data, uint16_t len) {
- uint16_t len_remaining = len;
- char* p_data_area;
-
- if (len > (RFCOMM_DATA_BUF_SIZE - sizeof(tBTA_AG_CI_RX_WRITE) - 1))
- len = RFCOMM_DATA_BUF_SIZE - sizeof(tBTA_AG_CI_RX_WRITE) - 1;
-
- while (len_remaining) {
- if (len_remaining < len) len = len_remaining;
-
- tBTA_AG_CI_RX_WRITE* p_buf =
- (tBTA_AG_CI_RX_WRITE*)osi_malloc(sizeof(tBTA_AG_CI_RX_WRITE) + len + 1);
- p_buf->hdr.event = BTA_AG_CI_RX_WRITE_EVT;
- p_buf->hdr.layer_specific = handle;
-
- p_data_area = (char*)(p_buf + 1); /* Point to data area after header */
- strncpy(p_data_area, p_data, len);
- p_data_area[len] = 0;
-
- bta_sys_sendmsg(p_buf);
-
- len_remaining -= len;
- p_data += len;
- }
-}
-
-/******************************************************************************
- *
- * Function bta_ag_ci_slc_ready
- *
- * Description This function is called to notify AG that SLC is up at
- * the application. This funcion is only used when the app
- * is running in pass-through mode.
- *
- * Returns void
- *
- *****************************************************************************/
-void bta_ag_ci_slc_ready(uint16_t handle) {
- tBTA_AG_DATA* p_buf = (tBTA_AG_DATA*)osi_malloc(sizeof(tBTA_AG_DATA));
-
- p_buf->hdr.event = BTA_AG_CI_SLC_READY_EVT;
- p_buf->hdr.layer_specific = handle;
-
- bta_sys_sendmsg(p_buf);
-}
diff --git a/bta/ag/bta_ag_cmd.cc b/bta/ag/bta_ag_cmd.cc
index 79028db..b9cf306 100644
--- a/bta/ag/bta_ag_cmd.cc
+++ b/bta/ag/bta_ag_cmd.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@
#define LOG_TAG "bta_ag_cmd"
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
+#include <cctype>
+#include <cstdio>
+#include <cstring>
#include "bt_common.h"
#include "bt_target.h"
@@ -63,7 +63,6 @@
BTA_AG_LOCAL_EVT_CMER,
BTA_AG_LOCAL_EVT_BRSF,
BTA_AG_LOCAL_EVT_CMEE,
- BTA_AG_LOCAL_EVT_BIA,
BTA_AG_LOCAL_EVT_BCC,
};
@@ -105,7 +104,7 @@
{"+COPS", BTA_AG_AT_COPS_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_STR,
0, 0},
{"+CMEE", BTA_AG_LOCAL_EVT_CMEE, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
- {"+BIA", BTA_AG_LOCAL_EVT_BIA, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 20},
+ {"+BIA", BTA_AG_AT_BIA_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 20},
{"+CBC", BTA_AG_AT_CBC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 100},
{"+BCC", BTA_AG_LOCAL_EVT_BCC, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
{"+BCS", BTA_AG_AT_BCS_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0,
@@ -173,7 +172,7 @@
i != sizeof(bta_ag_result_tbl) / sizeof(bta_ag_result_tbl[0]); ++i) {
if (code == bta_ag_result_tbl[i].result_id) return &bta_ag_result_tbl[i];
}
- return 0;
+ return nullptr;
}
const tBTA_AG_AT_CMD* bta_ag_at_tbl[BTA_AG_NUM_IDX] = {bta_ag_hsp_cmd,
@@ -215,15 +214,14 @@
static void bta_ag_send_result(tBTA_AG_SCB* p_scb, size_t code,
const char* p_arg, int16_t int_arg) {
const tBTA_AG_RESULT* result = bta_ag_result_by_code(code);
- if (result == 0) {
+ if (result == nullptr) {
LOG_ERROR(LOG_TAG, "%s Unable to lookup result for code %zu", __func__,
code);
return;
}
- char buf[BTA_AG_AT_MAX_LEN + 16];
+ char buf[BTA_AG_AT_MAX_LEN + 16] = "";
char* p = buf;
- memset(buf, 0, sizeof(buf));
/* init with \r\n */
*p++ = '\r';
@@ -274,7 +272,7 @@
*
******************************************************************************/
static void bta_ag_send_ok(tBTA_AG_SCB* p_scb) {
- bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_OK, NULL, 0);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_OK, nullptr, 0);
}
/*******************************************************************************
@@ -291,9 +289,9 @@
static void bta_ag_send_error(tBTA_AG_SCB* p_scb, int16_t errcode) {
/* If HFP and extended audio gateway error codes are enabled */
if (p_scb->conn_service == BTA_AG_HFP && p_scb->cmee_enabled)
- bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CMEE, NULL, errcode);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CMEE, nullptr, errcode);
else
- bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_ERROR, NULL, 0);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_ERROR, nullptr, 0);
}
/*******************************************************************************
@@ -321,39 +319,39 @@
/* Ensure we do not send duplicate indicators if not requested by app */
/* If it was requested by app, transmit CIEV even if it is duplicate. */
if (id == BTA_AG_IND_CALL) {
- if ((value == p_scb->call_ind) && (on_demand == false)) return;
+ if ((value == p_scb->call_ind) && (!on_demand)) return;
p_scb->call_ind = (uint8_t)value;
}
- if ((id == BTA_AG_IND_CALLSETUP) && (on_demand == false)) {
+ if ((id == BTA_AG_IND_CALLSETUP) && (!on_demand)) {
if (value == p_scb->callsetup_ind) return;
p_scb->callsetup_ind = (uint8_t)value;
}
- if ((id == BTA_AG_IND_SERVICE) && (on_demand == false)) {
+ if ((id == BTA_AG_IND_SERVICE) && (!on_demand)) {
if (value == p_scb->service_ind) return;
p_scb->service_ind = (uint8_t)value;
}
- if ((id == BTA_AG_IND_SIGNAL) && (on_demand == false)) {
+ if ((id == BTA_AG_IND_SIGNAL) && (!on_demand)) {
if (value == p_scb->signal_ind) return;
p_scb->signal_ind = (uint8_t)value;
}
- if ((id == BTA_AG_IND_ROAM) && (on_demand == false)) {
+ if ((id == BTA_AG_IND_ROAM) && (!on_demand)) {
if (value == p_scb->roam_ind) return;
p_scb->roam_ind = (uint8_t)value;
}
- if ((id == BTA_AG_IND_BATTCHG) && (on_demand == false)) {
+ if ((id == BTA_AG_IND_BATTCHG) && (!on_demand)) {
if (value == p_scb->battchg_ind) return;
p_scb->battchg_ind = (uint8_t)value;
}
- if ((id == BTA_AG_IND_CALLHELD) && (on_demand == false)) {
+ if ((id == BTA_AG_IND_CALLHELD) && (!on_demand)) {
/* call swap could result in sending callheld=1 multiple times */
if ((value != 1) && (value == p_scb->callheld_ind)) return;
@@ -392,7 +390,7 @@
*p = 0;
n[i] = utl_str2int(p_s);
p_s = p + 1;
- if (p_s == 0) {
+ if (p_s == nullptr) {
break;
}
}
@@ -424,7 +422,6 @@
******************************************************************************/
static uint8_t bta_ag_parse_chld(UNUSED_ATTR tBTA_AG_SCB* p_scb, char* p_s) {
uint8_t retval = 0;
- int16_t idx = -1;
if (!isdigit(p_s[0])) {
return BTA_AG_INVALID_CHLD;
@@ -432,7 +429,7 @@
if (p_s[1] != 0) {
/* p_idxstr++; point to beginning of call number */
- idx = utl_str2int(&p_s[1]);
+ int16_t idx = utl_str2int(&p_s[1]);
if (idx != -1 && idx < 255) {
retval = (uint8_t)idx;
} else {
@@ -455,7 +452,6 @@
static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB* p_scb, char* p_s) {
tBTA_AG_PEER_CODEC retval = BTA_AG_CODEC_NONE;
uint16_t uuid_codec;
- bool cont = false; /* Continue processing */
char* p;
while (p_s) {
@@ -463,13 +459,12 @@
for (p = p_s; *p != ',' && *p != 0; p++)
;
- /* get integre value */
+ /* get integer value */
+ bool cont = false; // Continue processing
if (*p != 0) {
*p = 0;
cont = true;
- } else
- cont = false;
-
+ }
uuid_codec = utl_str2int(p_s);
switch (uuid_codec) {
case UUID_CODEC_CVSD:
@@ -505,13 +500,11 @@
******************************************************************************/
static void bta_ag_process_unat_res(char* unat_result) {
- uint8_t str_leng;
- uint8_t i = 0;
uint8_t j = 0;
uint8_t pairs_of_nl_cr;
char trim_data[BTA_AG_AT_MAX_LEN];
- str_leng = strlen(unat_result);
+ uint8_t str_leng = strlen(unat_result);
/* If no extra CR and LF, just return */
if (str_leng < 4) return;
@@ -521,19 +514,17 @@
unat_result[str_leng - 2] == '\r' &&
unat_result[str_leng - 1] == '\n') {
pairs_of_nl_cr = 1;
- for (i = 0; i < (str_leng - 4 * pairs_of_nl_cr); i++) {
+ for (int i = 0; i < (str_leng - 4 * pairs_of_nl_cr); i++) {
trim_data[j++] = unat_result[i + pairs_of_nl_cr * 2];
}
/* Add EOF */
trim_data[j] = '\0';
str_leng = str_leng - 4;
strlcpy(unat_result, trim_data, str_leng + 1);
- i = 0;
j = 0;
if (str_leng < 4) return;
}
- return;
}
/*******************************************************************************
@@ -548,11 +539,7 @@
******************************************************************************/
bool bta_ag_inband_enabled(tBTA_AG_SCB* p_scb) {
/* if feature is enabled and no other scbs connected */
- if (p_scb->inband_enabled && !bta_ag_other_scb_open(p_scb)) {
- return true;
- } else {
- return false;
- }
+ return p_scb->inband_enabled && !bta_ag_other_scb_open(p_scb);
}
/*******************************************************************************
@@ -566,7 +553,7 @@
*
******************************************************************************/
void bta_ag_send_call_inds(tBTA_AG_SCB* p_scb, tBTA_AG_RES result) {
- uint8_t call = p_scb->call_ind;
+ uint8_t call;
/* set new call and callsetup values based on BTA_AgResult */
size_t callsetup = bta_ag_indicator_by_result_code(result);
@@ -603,7 +590,7 @@
bta_ag_send_ok(p_scb);
- tBTA_AG_VAL val;
+ tBTA_AG_VAL val = {};
val.hdr.handle = bta_ag_scb_to_idx(p_scb);
val.hdr.app_id = p_scb->app_id;
val.num = (uint16_t)int_arg;
@@ -678,9 +665,9 @@
******************************************************************************/
static bool bta_ag_parse_bind_set(tBTA_AG_SCB* p_scb, tBTA_AG_VAL val) {
char* p_token = strtok(val.str, ",");
- if (p_token == NULL) return false;
+ if (p_token == nullptr) return false;
- while (p_token != NULL) {
+ while (p_token != nullptr) {
uint16_t rcv_ind_id = atoi(p_token);
int index = bta_ag_find_empty_hf_ind(p_scb);
if (index == -1) {
@@ -691,7 +678,7 @@
p_scb->peer_hf_indicators[index].ind_id = rcv_ind_id;
APPL_TRACE_DEBUG("%s peer_hf_ind[%d] = %d", __func__, index, rcv_ind_id);
- p_token = strtok(NULL, ",");
+ p_token = strtok(nullptr, ",");
}
return true;
@@ -708,8 +695,7 @@
*
******************************************************************************/
static void bta_ag_bind_response(tBTA_AG_SCB* p_scb, uint8_t arg_type) {
- char buffer[BTA_AG_AT_MAX_LEN];
- memset(buffer, 0, BTA_AG_AT_MAX_LEN);
+ char buffer[BTA_AG_AT_MAX_LEN] = "";
if (arg_type == BTA_AG_AT_TEST) {
int index = 0;
@@ -750,15 +736,15 @@
p_scb->local_hf_indicators[i].ind_id);
/* Check whether local and peer sides support this indicator */
- if (p_scb->local_hf_indicators[i].is_supported == true &&
- peer_index != -1) {
+ if (p_scb->local_hf_indicators[i].is_supported && peer_index != -1) {
/* In the format of ind, state */
p += utl_itoa((uint16_t)p_scb->local_hf_indicators[i].ind_id, p);
*p++ = ',';
p += utl_itoa((uint16_t)p_scb->local_hf_indicators[i].is_enable, p);
bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0);
-
+ // have to use memset here because assigning to "" will not zero
+ // initialize the rest of the buffer
memset(buffer, 0, sizeof(buffer));
p = buffer;
} else {
@@ -770,7 +756,9 @@
bta_ag_send_ok(p_scb);
/* If the service level connection wan't already open, now it's open */
- if (!p_scb->svc_conn) bta_ag_svc_conn_open(p_scb, NULL);
+ if (!p_scb->svc_conn) {
+ bta_ag_svc_conn_open(p_scb, tBTA_AG_DATA::kEmpty);
+ }
}
}
@@ -788,7 +776,7 @@
char* p_token = strtok(val->str, ",");
uint16_t rcv_ind_id = atoi(p_token);
- p_token = strtok(NULL, ",");
+ p_token = strtok(nullptr, ",");
uint16_t rcv_ind_val = atoi(p_token);
APPL_TRACE_DEBUG("%s BIEV indicator id %d, value %d", __func__, rcv_ind_id,
@@ -805,8 +793,8 @@
int local_index = bta_ag_find_hf_ind_by_id(
p_scb->local_hf_indicators, BTA_AG_MAX_NUM_LOCAL_HF_IND, rcv_ind_id);
if (local_index == -1 ||
- p_scb->local_hf_indicators[local_index].is_supported != true ||
- p_scb->local_hf_indicators[local_index].is_enable != true) {
+ !p_scb->local_hf_indicators[local_index].is_supported ||
+ !p_scb->local_hf_indicators[local_index].is_enable) {
APPL_TRACE_WARNING("%s indicator id %d not supported or disabled", __func__,
rcv_ind_id);
return false;
@@ -837,11 +825,11 @@
******************************************************************************/
void bta_ag_at_hfp_cback(tBTA_AG_SCB* p_scb, uint16_t cmd, uint8_t arg_type,
char* p_arg, int16_t int_arg) {
- tBTA_AG_VAL val;
+ tBTA_AG_VAL val = {};
tBTA_AG_SCB* ag_scb;
uint32_t i, ind_id;
uint32_t bia_masked_out;
- if (p_arg == NULL) {
+ if (p_arg == nullptr) {
APPL_TRACE_ERROR("%s: p_arg is null, send error and return", __func__);
bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
return;
@@ -850,11 +838,10 @@
APPL_TRACE_DEBUG("%s: AT command %d, arg_type %d, int_arg %d, arg %s",
__func__, cmd, arg_type, int_arg, p_arg);
- memset(&val, 0, sizeof(tBTA_AG_VAL));
val.hdr.handle = bta_ag_scb_to_idx(p_scb);
val.hdr.app_id = p_scb->app_id;
val.hdr.status = BTA_AG_SUCCESS;
- val.num = int_arg;
+ val.num = static_cast<uint32_t>(int_arg);
val.bd_addr = p_scb->peer_addr;
strlcpy(val.str, p_arg, sizeof(val.str));
@@ -865,7 +852,9 @@
* callback is NOT invoked.
*/
tBTA_AG_EVT event = 0;
- if (cmd < BTA_AG_LOCAL_EVT_FIRST) event = cmd;
+ if (cmd < BTA_AG_LOCAL_EVT_FIRST) {
+ event = static_cast<tBTA_AG_EVT>(cmd);
+ }
switch (cmd) {
case BTA_AG_AT_A_EVT:
@@ -947,7 +936,7 @@
bta_ag_send_ok(p_scb);
/* if service level conn. not already open, now it's open */
- bta_ag_svc_conn_open(p_scb, NULL);
+ bta_ag_svc_conn_open(p_scb, tBTA_AG_DATA::kEmpty);
} else {
val.idx = bta_ag_parse_chld(p_scb, val.str);
@@ -970,7 +959,7 @@
** Application will set it back to 1
** callheld indicator will be sent across to the peer. */
if (val.str[0] == '2') {
- for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB;
+ for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_MAX_NUM_CLIENTS;
i++, ag_scb++) {
if (ag_scb->in_use) {
if ((ag_scb->call_ind == BTA_AG_CALL_ACTIVE) &&
@@ -1043,7 +1032,7 @@
if (!p_scb->svc_conn &&
!((p_scb->features & BTA_AG_FEAT_3WAY) &&
(p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY))) {
- bta_ag_svc_conn_open(p_scb, NULL);
+ bta_ag_svc_conn_open(p_scb, tBTA_AG_DATA::kEmpty);
}
} else {
bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
@@ -1090,7 +1079,8 @@
p_scb->peer_features, features);
/* send BRSF, send OK */
- bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BRSF, NULL, (int16_t)features);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BRSF, nullptr,
+ (int16_t)features);
bta_ag_send_ok(p_scb);
break;
}
@@ -1110,10 +1100,10 @@
if (p_scb->features & BTA_AG_FEAT_BTRH) {
/* If set command; send response and notify app */
if (arg_type == BTA_AG_AT_SET) {
- for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB;
+ for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_MAX_NUM_CLIENTS;
i++, ag_scb++) {
if (ag_scb->in_use) {
- bta_ag_send_result(ag_scb, BTA_AG_BTRH_RES, NULL, int_arg);
+ bta_ag_send_result(ag_scb, BTA_AG_BTRH_RES, nullptr, int_arg);
}
}
bta_ag_send_ok(p_scb);
@@ -1151,32 +1141,37 @@
event = 0;
break;
- case BTA_AG_LOCAL_EVT_BIA:
- /* don't call callback */
- event = 0;
-
+ case BTA_AG_AT_BIA_EVT:
bia_masked_out = p_scb->bia_masked_out;
/* Parse the indicator mask */
for (i = 0, ind_id = 1; (val.str[i] != 0) && (ind_id <= 20);
i++, ind_id++) {
- if (val.str[i] == ',') continue;
+ if (val.str[i] == ',') {
+ continue;
+ }
- if (val.str[i] == '0')
+ if (val.str[i] == '0') {
bia_masked_out |= ((uint32_t)1 << ind_id);
- else if (val.str[i] == '1')
+ } else if (val.str[i] == '1') {
bia_masked_out &= ~((uint32_t)1 << ind_id);
- else
+ } else {
break;
+ }
i++;
- if ((val.str[i] == 0) || (val.str[i] != ',')) break;
+ if (val.str[i] != ',') {
+ break;
+ }
}
if (val.str[i] == 0) {
p_scb->bia_masked_out = bia_masked_out;
+ val.num = bia_masked_out;
bta_ag_send_ok(p_scb);
- } else
+ } else {
+ event = 0;
bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX);
+ }
break;
case BTA_AG_AT_CNUM_EVT:
@@ -1191,6 +1186,7 @@
case BTA_AG_AT_BAC_EVT:
bta_ag_send_ok(p_scb);
+ p_scb->received_at_bac = true;
/* store available codecs from the peer */
if ((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) &&
@@ -1247,20 +1243,23 @@
else
codec_sent = p_scb->sco_codec;
- if (codec_type == codec_sent)
- bta_ag_sco_codec_nego(p_scb, true);
- else
- bta_ag_sco_codec_nego(p_scb, false);
+ bta_ag_sco_codec_nego(p_scb, codec_type == codec_sent);
/* send final codec info to callback */
val.num = codec_sent;
break;
}
- case BTA_AG_LOCAL_EVT_BCC:
+ case BTA_AG_LOCAL_EVT_BCC: {
+ if (!bta_ag_sco_is_active_device(p_scb->peer_addr)) {
+ LOG(WARNING) << __func__ << ": AT+BCC rejected as " << p_scb->peer_addr
+ << " is not the active device";
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_ALLOWED);
+ break;
+ }
bta_ag_send_ok(p_scb);
- bta_ag_sco_open(p_scb, NULL);
+ bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty);
break;
-
+ }
default:
bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
break;
@@ -1282,15 +1281,14 @@
* Returns void
*
******************************************************************************/
-void bta_ag_at_err_cback(tBTA_AG_SCB* p_scb, bool unknown, char* p_arg) {
- tBTA_AG_VAL val;
-
+void bta_ag_at_err_cback(tBTA_AG_SCB* p_scb, bool unknown, const char* p_arg) {
if (unknown && (!strlen(p_arg))) {
APPL_TRACE_DEBUG("Empty AT cmd string received");
bta_ag_send_ok(p_scb);
return;
}
+ tBTA_AG_VAL val = {};
/* if unknown AT command and configured to pass these to app */
if (unknown && (p_scb->features & BTA_AG_FEAT_UNAT)) {
val.hdr.handle = bta_ag_scb_to_idx(p_scb);
@@ -1314,13 +1312,13 @@
* Returns void
*
******************************************************************************/
-void bta_ag_hsp_result(tBTA_AG_SCB* p_scb, tBTA_AG_API_RESULT* p_result) {
- APPL_TRACE_DEBUG("bta_ag_hsp_result : res = %d", p_result->result);
+void bta_ag_hsp_result(tBTA_AG_SCB* p_scb, const tBTA_AG_API_RESULT& result) {
+ APPL_TRACE_DEBUG("bta_ag_hsp_result : res = %d", result.result);
- switch (p_result->result) {
+ switch (result.result) {
case BTA_AG_SPK_RES:
case BTA_AG_MIC_RES:
- bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
+ bta_ag_send_result(p_scb, result.result, nullptr, result.data.num);
break;
case BTA_AG_IN_CALL_RES:
@@ -1330,7 +1328,7 @@
/* if sco already opened or no inband ring send ring now */
if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
(p_scb->features & BTA_AG_FEAT_NOSCO)) {
- bta_ag_send_ring(p_scb, (tBTA_AG_DATA*)p_result);
+ bta_ag_send_ring(p_scb, tBTA_AG_DATA::kEmpty);
} else {
/* else open sco, send ring after sco opened */
/* HSPv1.2: AG shall not send RING if using in-band ring tone. */
@@ -1339,27 +1337,26 @@
} else {
p_scb->post_sco = BTA_AG_POST_SCO_RING;
}
- bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
+ bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty);
}
break;
case BTA_AG_IN_CALL_CONN_RES:
case BTA_AG_OUT_CALL_ORIG_RES:
/* if incoming call connected stop ring timer */
- if (p_result->result == BTA_AG_IN_CALL_CONN_RES) {
+ if (result.result == BTA_AG_IN_CALL_CONN_RES) {
alarm_cancel(p_scb->ring_timer);
}
if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
/* if audio connected to this scb AND sco is not opened, open sco */
- if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+ if (result.data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
!bta_ag_sco_is_open(p_scb)) {
- bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
- }
- /* else if no audio at call close sco */
- else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE &&
- bta_ag_sco_is_open(p_scb)) {
- bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
+ bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty);
+ } else if (result.data.audio_handle == BTA_AG_HANDLE_NONE &&
+ bta_ag_sco_is_open(p_scb)) {
+ /* else if no audio at call close sco */
+ bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty);
}
}
break;
@@ -1370,7 +1367,7 @@
/* close sco */
if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) &&
!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
- bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
+ bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty);
} else {
/* if av got suspended by this call, let it resume. */
bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
@@ -1378,17 +1375,17 @@
break;
case BTA_AG_INBAND_RING_RES:
- p_scb->inband_enabled = p_result->data.state;
+ p_scb->inband_enabled = result.data.state;
APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
break;
case BTA_AG_UNAT_RES:
- if (p_result->data.ok_flag != BTA_AG_OK_ERROR) {
- if (p_result->data.str[0] != 0) {
- bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+ if (result.data.ok_flag != BTA_AG_OK_ERROR) {
+ if (result.data.str[0] != 0) {
+ bta_ag_send_result(p_scb, result.result, result.data.str, 0);
}
- if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
+ if (result.data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
} else {
bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
}
@@ -1410,34 +1407,36 @@
* Returns void
*
******************************************************************************/
-void bta_ag_hfp_result(tBTA_AG_SCB* p_scb, tBTA_AG_API_RESULT* p_result) {
- APPL_TRACE_DEBUG("bta_ag_hfp_result : res = %d", p_result->result);
+void bta_ag_hfp_result(tBTA_AG_SCB* p_scb, const tBTA_AG_API_RESULT& result) {
+ APPL_TRACE_DEBUG("bta_ag_hfp_result : res = %d", result.result);
- switch (p_result->result) {
+ switch (result.result) {
case BTA_AG_SPK_RES:
case BTA_AG_MIC_RES:
- bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
+ bta_ag_send_result(p_scb, result.result, nullptr, result.data.num);
break;
- case BTA_AG_IN_CALL_RES:
+ case BTA_AG_IN_CALL_RES: {
/* tell sys to stop av if any */
bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
- /* store caller id string.
- * append type info at the end.
- * make sure a valid type info is passed.
- * otherwise add 129 as default type */
- if ((p_result->data.num < BTA_AG_CLIP_TYPE_MIN) ||
- (p_result->data.num > BTA_AG_CLIP_TYPE_MAX)) {
- if (p_result->data.num != BTA_AG_CLIP_TYPE_VOIP)
- p_result->data.num = BTA_AG_CLIP_TYPE_DEFAULT;
+ /* Store caller id string.
+ * Append type info at the end.
+ * Make sure a valid type info is passed.
+ * Otherwise add 129 as default type */
+ uint16_t clip_type = result.data.num;
+ if ((clip_type < BTA_AG_CLIP_TYPE_MIN) ||
+ (clip_type > BTA_AG_CLIP_TYPE_MAX)) {
+ if (clip_type != BTA_AG_CLIP_TYPE_VOIP) {
+ clip_type = BTA_AG_CLIP_TYPE_DEFAULT;
+ }
}
- APPL_TRACE_DEBUG("CLIP type :%d", p_result->data.num);
+ APPL_TRACE_DEBUG("CLIP type :%d", clip_type);
p_scb->clip[0] = 0;
- if (p_result->data.str[0] != 0)
- snprintf(p_scb->clip, sizeof(p_scb->clip), "%s,%d", p_result->data.str,
- p_result->data.num);
+ if (result.data.str[0] != 0)
+ snprintf(p_scb->clip, sizeof(p_scb->clip), "%s,%d", result.data.str,
+ clip_type);
/* send callsetup indicator */
if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END) {
@@ -1445,35 +1444,36 @@
* close. */
p_scb->post_sco = BTA_AG_POST_SCO_CALL_END_INCALL;
} else {
- bta_ag_send_call_inds(p_scb, p_result->result);
+ bta_ag_send_call_inds(p_scb, result.result);
/* if sco already opened or no inband ring send ring now */
if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
- (p_scb->features & BTA_AG_FEAT_NOSCO)) {
- bta_ag_send_ring(p_scb, (tBTA_AG_DATA*)p_result);
+ (p_scb->features & BTA_AG_FEAT_NOSCO) ||
+ (result.data.audio_handle != bta_ag_scb_to_idx(p_scb))) {
+ bta_ag_send_ring(p_scb, tBTA_AG_DATA::kEmpty);
} else {
/* else open sco, send ring after sco opened */
p_scb->post_sco = BTA_AG_POST_SCO_RING;
- bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
+ bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty);
}
}
break;
-
+ }
case BTA_AG_IN_CALL_CONN_RES:
alarm_cancel(p_scb->ring_timer);
/* if sco not opened and we need to open it, send indicators first
** then open sco.
*/
- bta_ag_send_call_inds(p_scb, p_result->result);
+ bta_ag_send_call_inds(p_scb, result.result);
if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
- if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+ if (result.data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
!bta_ag_sco_is_open(p_scb)) {
- bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
- } else if ((p_result->data.audio_handle == BTA_AG_HANDLE_NONE) &&
+ bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty);
+ } else if ((result.data.audio_handle == BTA_AG_HANDLE_NONE) &&
bta_ag_sco_is_open(p_scb)) {
- bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
+ bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty);
}
}
break;
@@ -1481,24 +1481,24 @@
case BTA_AG_IN_CALL_HELD_RES:
alarm_cancel(p_scb->ring_timer);
- bta_ag_send_call_inds(p_scb, p_result->result);
+ bta_ag_send_call_inds(p_scb, result.result);
break;
case BTA_AG_OUT_CALL_ORIG_RES:
- bta_ag_send_call_inds(p_scb, p_result->result);
- if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+ bta_ag_send_call_inds(p_scb, result.result);
+ if (result.data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
- bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
+ bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty);
}
break;
case BTA_AG_OUT_CALL_ALERT_RES:
/* send indicators */
- bta_ag_send_call_inds(p_scb, p_result->result);
- if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+ bta_ag_send_call_inds(p_scb, result.result);
+ if (result.data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
- bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
+ bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty);
}
break;
@@ -1506,30 +1506,31 @@
/* open SCO at SLC for this three way call */
APPL_TRACE_DEBUG("Headset Connected in three way call");
if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
- if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
- bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
- else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
- bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
+ if (result.data.audio_handle == bta_ag_scb_to_idx(p_scb)) {
+ bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty);
+ } else if (result.data.audio_handle == BTA_AG_HANDLE_NONE) {
+ bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty);
+ }
}
break;
case BTA_AG_OUT_CALL_CONN_RES:
/* send indicators */
- bta_ag_send_call_inds(p_scb, p_result->result);
+ bta_ag_send_call_inds(p_scb, result.result);
/* open or close sco */
if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
- if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb)) {
- bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
- } else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE) {
- bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
+ if (result.data.audio_handle == bta_ag_scb_to_idx(p_scb)) {
+ bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty);
+ } else if (result.data.audio_handle == BTA_AG_HANDLE_NONE) {
+ bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty);
}
}
break;
case BTA_AG_CALL_CANCEL_RES:
/* send indicators */
- bta_ag_send_call_inds(p_scb, p_result->result);
+ bta_ag_send_call_inds(p_scb, result.result);
break;
case BTA_AG_END_CALL_RES:
@@ -1539,13 +1540,13 @@
if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) &&
!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
- bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
+ bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty);
} else if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END_INCALL) {
/* sco closing for outgoing call because of incoming call */
/* Send only callsetup end indicator after sco close */
p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
} else {
- bta_ag_send_call_inds(p_scb, p_result->result);
+ bta_ag_send_call_inds(p_scb, result.result);
/* if av got suspended by this call, let it resume. */
bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
@@ -1553,24 +1554,24 @@
break;
case BTA_AG_INBAND_RING_RES:
- p_scb->inband_enabled = p_result->data.state;
+ p_scb->inband_enabled = result.data.state;
APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
- bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.state);
+ bta_ag_send_result(p_scb, result.result, nullptr, result.data.state);
break;
case BTA_AG_CIND_RES:
/* store local values */
- p_scb->call_ind = p_result->data.str[0] - '0';
- p_scb->callsetup_ind = p_result->data.str[2] - '0';
- p_scb->service_ind = p_result->data.str[4] - '0';
- p_scb->signal_ind = p_result->data.str[6] - '0';
- p_scb->roam_ind = p_result->data.str[8] - '0';
- p_scb->battchg_ind = p_result->data.str[10] - '0';
- p_scb->callheld_ind = p_result->data.str[12] - '0';
+ p_scb->call_ind = result.data.str[0] - '0';
+ p_scb->callsetup_ind = result.data.str[2] - '0';
+ p_scb->service_ind = result.data.str[4] - '0';
+ p_scb->signal_ind = result.data.str[6] - '0';
+ p_scb->roam_ind = result.data.str[8] - '0';
+ p_scb->battchg_ind = result.data.str[10] - '0';
+ p_scb->callheld_ind = result.data.str[12] - '0';
APPL_TRACE_DEBUG("cind call:%d callsetup:%d", p_scb->call_ind,
p_scb->callsetup_ind);
- bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+ bta_ag_send_result(p_scb, result.result, result.data.str, 0);
bta_ag_send_ok(p_scb);
break;
@@ -1578,58 +1579,67 @@
case BTA_AG_CNUM_RES:
case BTA_AG_CLCC_RES:
case BTA_AG_COPS_RES:
- if (p_result->data.ok_flag != BTA_AG_OK_ERROR) {
- if (p_result->data.str[0] != 0) {
- bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+ if (result.data.ok_flag != BTA_AG_OK_ERROR) {
+ if (result.data.str[0] != 0) {
+ bta_ag_send_result(p_scb, result.result, result.data.str, 0);
}
- if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
+ if (result.data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
} else {
- bta_ag_send_error(p_scb, p_result->data.errcode);
+ bta_ag_send_error(p_scb, result.data.errcode);
}
break;
- case BTA_AG_UNAT_RES:
- if (p_result->data.ok_flag != BTA_AG_OK_ERROR) {
- if (p_result->data.str[0] != 0) {
- bta_ag_process_unat_res(p_result->data.str);
- APPL_TRACE_DEBUG("BTA_AG_RES :%s", p_result->data.str);
- bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+ case BTA_AG_UNAT_RES: {
+ if (result.data.ok_flag != BTA_AG_OK_ERROR) {
+ if (result.data.str[0] != 0) {
+ tBTA_AG_API_RESULT result_copy(result);
+ bta_ag_process_unat_res(result_copy.data.str);
+ APPL_TRACE_DEBUG("BTA_AG_RES :%s", result_copy.data.str);
+ bta_ag_send_result(p_scb, result_copy.result, result_copy.data.str,
+ 0);
}
-
- if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
+ if (result.data.ok_flag == BTA_AG_OK_DONE) {
+ bta_ag_send_ok(p_scb);
+ }
} else {
- bta_ag_send_error(p_scb, p_result->data.errcode);
+ bta_ag_send_error(p_scb, result.data.errcode);
}
break;
+ }
case BTA_AG_CALL_WAIT_RES:
if (p_scb->ccwa_enabled) {
- bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
+ bta_ag_send_result(p_scb, result.result, result.data.str, 0);
}
- bta_ag_send_call_inds(p_scb, p_result->result);
+ bta_ag_send_call_inds(p_scb, result.result);
break;
case BTA_AG_IND_RES:
- bta_ag_send_ind(p_scb, p_result->data.ind.id, p_result->data.ind.value,
- false);
+ bta_ag_send_ind(p_scb, result.data.ind.id, result.data.ind.value, false);
+ break;
+
+ case BTA_AG_IND_RES_ON_DEMAND:
+ bta_ag_send_ind(p_scb, result.data.ind.id, result.data.ind.value, true);
break;
case BTA_AG_BVRA_RES:
- bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.state);
+ bta_ag_send_result(p_scb, result.result, nullptr, result.data.state);
break;
case BTA_AG_BTRH_RES:
- if (p_result->data.ok_flag != BTA_AG_OK_ERROR) {
+ if (result.data.ok_flag != BTA_AG_OK_ERROR) {
/* Don't respond to read if not in response & hold state */
- if (p_result->data.num != BTA_AG_BTRH_NO_RESP) {
- bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
+ if (result.data.num != BTA_AG_BTRH_NO_RESP) {
+ bta_ag_send_result(p_scb, result.result, nullptr, result.data.num);
}
/* In case of a response to a read request we need to send OK */
- if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
+ if (result.data.ok_flag == BTA_AG_OK_DONE) {
+ bta_ag_send_ok(p_scb);
+ }
} else {
- bta_ag_send_error(p_scb, p_result->data.errcode);
+ bta_ag_send_error(p_scb, result.data.errcode);
}
break;
@@ -1637,45 +1647,44 @@
/* Find whether ind_id is supported by local device or not */
int local_index = bta_ag_find_hf_ind_by_id(p_scb->local_hf_indicators,
BTA_AG_MAX_NUM_LOCAL_HF_IND,
- p_result->data.ind.id);
+ result.data.ind.id);
if (local_index == -1) {
APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__,
- p_result->data.ind.id);
+ result.data.ind.id);
return;
}
/* Find whether ind_id is supported by peer device or not */
int peer_index = bta_ag_find_hf_ind_by_id(p_scb->peer_hf_indicators,
BTA_AG_MAX_NUM_PEER_HF_IND,
- p_result->data.ind.id);
+ result.data.ind.id);
if (peer_index == -1) {
APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__,
- p_result->data.ind.id);
+ result.data.ind.id);
return;
} else {
/* If the current state is different from the one upper layer request
change current state and send out the result */
if (p_scb->local_hf_indicators[local_index].is_enable !=
- p_result->data.ind.on_demand) {
+ result.data.ind.on_demand) {
char buffer[BTA_AG_AT_MAX_LEN] = {0};
char* p = buffer;
p_scb->local_hf_indicators[local_index].is_enable =
- p_result->data.ind.on_demand;
- p += utl_itoa(p_result->data.ind.id, p);
+ result.data.ind.on_demand;
+ p += utl_itoa(result.data.ind.id, p);
*p++ = ',';
p += utl_itoa(p_scb->local_hf_indicators[local_index].is_enable, p);
- bta_ag_send_result(p_scb, p_result->result, buffer, 0);
+ bta_ag_send_result(p_scb, result.result, buffer, 0);
} else {
APPL_TRACE_DEBUG(
- "%s HF Indicator %d already %s", p_result->data.ind.id,
- (p_result->data.ind.on_demand == true) ? "Enabled" : "Disabled");
+ "%s HF Indicator %d already %s", result.data.ind.id,
+ (result.data.ind.on_demand) ? "Enabled" : "Disabled");
}
}
break;
}
-
default:
break;
}
@@ -1691,11 +1700,11 @@
* Returns void
*
******************************************************************************/
-void bta_ag_result(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_result(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
if (p_scb->conn_service == BTA_AG_HSP) {
- bta_ag_hsp_result(p_scb, &p_data->api_result);
+ bta_ag_hsp_result(p_scb, data.api_result);
} else {
- bta_ag_hfp_result(p_scb, &p_data->api_result);
+ bta_ag_hfp_result(p_scb, data.api_result);
}
}
@@ -1708,7 +1717,7 @@
* Returns void
*
******************************************************************************/
-void bta_ag_send_bcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_send_bcs(tBTA_AG_SCB* p_scb) {
uint16_t codec_uuid;
if (p_scb->codec_fallback) {
@@ -1734,7 +1743,7 @@
/* send +BCS */
APPL_TRACE_DEBUG("send +BCS codec is %d", codec_uuid);
- bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BCS, NULL, codec_uuid);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BCS, nullptr, codec_uuid);
}
/*******************************************************************************
@@ -1747,9 +1756,17 @@
* Returns void
*
******************************************************************************/
-void bta_ag_send_ring(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
+void bta_ag_send_ring(tBTA_AG_SCB* p_scb,
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
+ if ((p_scb->conn_service == BTA_AG_HFP) &&
+ p_scb->callsetup_ind != BTA_AG_CALLSETUP_INCOMING) {
+ LOG(WARNING) << __func__ << ": don't send RING, conn_service="
+ << std::to_string(p_scb->conn_service)
+ << ", callsetup_ind=" << std::to_string(p_scb->callsetup_ind);
+ return;
+ }
/* send RING */
- bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_RING, NULL, 0);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_RING, nullptr, 0);
/* if HFP and clip enabled and clip data send CLIP */
if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled &&
diff --git a/bta/ag/bta_ag_int.h b/bta/ag/bta_ag_int.h
index 3ebf369..c6b3230 100644
--- a/bta/ag/bta_ag_int.h
+++ b/bta/ag/bta_ag_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,11 +32,6 @@
/*****************************************************************************
* Constants
****************************************************************************/
-/* Number of SCBs (AG service instances that can be registered) */
-#ifndef BTA_AG_NUM_SCB
-#define BTA_AG_NUM_SCB 2
-#endif
-
/* Time to wait for retry in case of collision */
#ifndef BTA_AG_COLLISION_TIMEOUT_MS
#define BTA_AG_COLLISION_TIMEOUT_MS (2 * 1000) /* 2 seconds */
@@ -58,14 +53,6 @@
#define BTA_AG_ACP 0 /* accepted connection */
#define BTA_AG_INT 1 /* initiating connection */
-/* feature mask that matches spec */
-#define BTA_AG_BSRF_FEAT_SPEC \
- (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | BTA_AG_FEAT_VREC | \
- BTA_AG_FEAT_INBAND | BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT | \
- BTA_AG_FEAT_ECS | BTA_AG_FEAT_ECC | BTA_AG_FEAT_EXTERR | \
- BTA_AG_FEAT_CODEC | BTA_AG_FEAT_HF_IND | BTA_AG_FEAT_ESCO | \
- BTA_AG_FEAT_VOIP)
-
#define BTA_AG_SDP_FEAT_SPEC \
(BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | BTA_AG_FEAT_VREC | \
BTA_AG_FEAT_INBAND | BTA_AG_FEAT_VTAG)
@@ -90,17 +77,10 @@
BTA_AG_DISC_INT_RES_EVT,
BTA_AG_DISC_OK_EVT,
BTA_AG_DISC_FAIL_EVT,
- BTA_AG_CI_RX_WRITE_EVT,
BTA_AG_RING_TIMEOUT_EVT,
BTA_AG_SVC_TIMEOUT_EVT,
- BTA_AG_CI_SCO_DATA_EVT,
- BTA_AG_CI_SLC_READY_EVT,
+ BTA_AG_COLLISION_EVT,
BTA_AG_MAX_EVT,
-
- /* these events are handled outside of the state machine */
- BTA_AG_API_ENABLE_EVT,
- BTA_AG_API_DISABLE_EVT,
- BTA_AG_API_SET_SCO_ALLOWED_EVT
};
/* Actions to perform after a SCO event */
@@ -134,16 +114,8 @@
* Data types
****************************************************************************/
-/* data type for BTA_AG_API_ENABLE_EVT */
-typedef struct {
- BT_HDR hdr;
- tBTA_AG_PARSE_MODE parse_mode;
- tBTA_AG_CBACK* p_cback;
-} tBTA_AG_API_ENABLE;
-
/* data type for BTA_AG_API_REGISTER_EVT */
typedef struct {
- BT_HDR hdr;
char p_name[2][BTA_SERVICE_NAME_LEN + 1];
tBTA_SERVICE_MASK services;
tBTA_SEC sec_mask;
@@ -153,61 +125,58 @@
/* data type for BTA_AG_API_OPEN_EVT */
typedef struct {
- BT_HDR hdr;
RawAddress bd_addr;
- tBTA_SERVICE_MASK services;
tBTA_SEC sec_mask;
} tBTA_AG_API_OPEN;
/* data type for BTA_AG_API_RESULT_EVT */
typedef struct {
- BT_HDR hdr;
tBTA_AG_RES result;
tBTA_AG_RES_DATA data;
} tBTA_AG_API_RESULT;
/* data type for BTA_AG_API_SETCODEC_EVT */
typedef struct {
- BT_HDR hdr;
tBTA_AG_PEER_CODEC codec;
} tBTA_AG_API_SETCODEC;
-/* data type for BTA_AG_API_SET_SCO_ALLOWED_EVT */
-typedef struct {
- BT_HDR hdr;
- bool value;
-} tBTA_AG_API_SET_SCO_ALLOWED;
-
/* data type for BTA_AG_DISC_RESULT_EVT */
typedef struct {
- BT_HDR hdr;
uint16_t status;
} tBTA_AG_DISC_RESULT;
/* data type for RFCOMM events */
typedef struct {
- BT_HDR hdr;
uint16_t port_handle;
} tBTA_AG_RFC;
-/* data type for BTA_AG_CI_RX_WRITE_EVT */
-typedef struct {
- BT_HDR hdr;
- // char p_data[BTA_AG_MTU+1];
-} tBTA_AG_CI_RX_WRITE;
-
/* union of all event datatypes */
-typedef union {
- BT_HDR hdr;
- tBTA_AG_API_ENABLE api_enable;
+union tBTA_AG_DATA {
tBTA_AG_API_REGISTER api_register;
tBTA_AG_API_OPEN api_open;
tBTA_AG_API_RESULT api_result;
tBTA_AG_API_SETCODEC api_setcodec;
tBTA_AG_DISC_RESULT disc_result;
tBTA_AG_RFC rfc;
- tBTA_AG_CI_RX_WRITE ci_rx_write;
-} tBTA_AG_DATA;
+ static const tBTA_AG_DATA kEmpty;
+
+ /**
+ * Check if two tBTA_AG_DATA are equal in memory
+ *
+ * @param rhs other tBTA_AG_DATA
+ * @return true if both unions are equal in memory
+ */
+ bool operator==(const tBTA_AG_DATA& rhs) const {
+ return (std::memcmp(this, &rhs, sizeof(tBTA_AG_DATA)) == 0);
+ }
+
+ /**
+ * Check if this union is empty by comparing it to the kEmpty constant
+ *
+ * @return true if this union is empty
+ */
+ bool IsEmpty() const { return *this == kEmpty; }
+};
/* type for each profile */
typedef struct {
@@ -221,7 +190,7 @@
} tBTA_AG_SCO_MSBC_SETTINGS;
/* type for each service control block */
-typedef struct {
+struct tBTA_AG_SCB {
char clip[BTA_AG_AT_MAX_LEN + 1]; /* number string used for CLIP */
uint16_t serv_handle[BTA_AG_NUM_IDX]; /* RFCOMM server handles */
tBTA_AG_AT_CB at_cb; /* AT command interpreter */
@@ -234,6 +203,7 @@
tBTA_SEC cli_sec_mask; /* client security mask */
tBTA_AG_FEAT features; /* features registered by application */
tBTA_AG_PEER_FEAT peer_features; /* peer device features */
+ uint16_t peer_sdp_features; /* peer device SDP features */
uint16_t peer_version; /* profile version of peer device */
uint16_t hsp_version; /* HSP profile version before SDP */
uint16_t sco_idx; /* SCO handle */
@@ -262,6 +232,7 @@
alarm_t* collision_timer;
alarm_t* ring_timer;
alarm_t* codec_negotiation_timer;
+ bool received_at_bac; /* indicate AT+BAC is received at least once */
tBTA_AG_PEER_CODEC peer_codecs; /* codecs for eSCO supported by the peer */
tBTA_AG_PEER_CODEC sco_codec; /* codec to be used for eSCO connection */
tBTA_AG_PEER_CODEC
@@ -277,7 +248,7 @@
tBTA_AG_HF_IND
local_hf_indicators[BTA_AG_MAX_NUM_LOCAL_HF_IND]; /* Local supported
HF indicators */
-} tBTA_AG_SCB;
+};
/* type for sco data */
typedef struct {
@@ -291,11 +262,10 @@
/* type for AG control block */
typedef struct {
- tBTA_AG_SCB scb[BTA_AG_NUM_SCB]; /* service control blocks */
+ tBTA_AG_SCB scb[BTA_AG_MAX_NUM_CLIENTS]; /* service control blocks */
tBTA_AG_PROFILE profile[BTA_AG_NUM_IDX]; /* profile-specific data */
tBTA_AG_SCO_CB sco; /* SCO data */
tBTA_AG_CBACK* p_cback; /* application callback */
- tBTA_AG_PARSE_MODE parse_mode; /* parse/pass-through mode */
} tBTA_AG_CB;
/*****************************************************************************
@@ -311,12 +281,24 @@
extern tBTA_AG_CB bta_ag_cb;
/* config struct */
-extern tBTA_AG_CFG* p_bta_ag_cfg;
+extern const tBTA_AG_CFG* p_bta_ag_cfg;
extern const tBTA_AG_HF_IND bta_ag_local_hf_ind_cfg[];
/*****************************************************************************
* Function prototypes
****************************************************************************/
+bool bta_ag_hdl_event(BT_HDR* p_msg);
+
+/* API functions */
+extern void bta_ag_api_enable(tBTA_AG_CBACK* p_cback);
+extern void bta_ag_api_disable();
+extern void bta_ag_api_set_active_device(const RawAddress& new_active_device);
+extern void bta_ag_api_register(tBTA_SERVICE_MASK services, tBTA_SEC sec_mask,
+ tBTA_AG_FEAT features,
+ const std::vector<std::string>& service_names,
+ uint8_t app_id);
+extern void bta_ag_api_result(uint16_t handle, tBTA_AG_RES result,
+ const tBTA_AG_RES_DATA& result_data);
/* main functions */
extern void bta_ag_scb_dealloc(tBTA_AG_SCB* p_scb);
@@ -326,23 +308,23 @@
extern uint16_t bta_ag_idx_by_bdaddr(const RawAddress* peer_addr);
extern bool bta_ag_other_scb_open(tBTA_AG_SCB* p_curr_scb);
extern bool bta_ag_scb_open(tBTA_AG_SCB* p_curr_scb);
-extern tBTA_AG_SCB* bta_ag_get_other_idle_scb(tBTA_AG_SCB* p_curr_scb);
extern void bta_ag_sm_execute(tBTA_AG_SCB* p_scb, uint16_t event,
- tBTA_AG_DATA* p_data);
-extern bool bta_ag_hdl_event(BT_HDR* p_msg);
+ const tBTA_AG_DATA& data);
+extern void bta_ag_sm_execute_by_handle(uint16_t handle, uint16_t event,
+ const tBTA_AG_DATA& data);
extern void bta_ag_collision_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
- uint8_t app_id, const RawAddress* peer_addr);
+ uint8_t app_id, const RawAddress& peer_addr);
extern void bta_ag_resume_open(tBTA_AG_SCB* p_scb);
/* SDP functions */
-extern bool bta_ag_add_record(uint16_t service_uuid, char* p_service_name,
+extern bool bta_ag_add_record(uint16_t service_uuid, const char* p_service_name,
uint8_t scn, tBTA_AG_FEAT features,
uint32_t sdp_handle);
-extern void bta_ag_create_records(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_del_records(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
+extern void bta_ag_create_records(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_del_records(tBTA_AG_SCB* p_scb);
extern bool bta_ag_sdp_find_attr(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service);
extern void bta_ag_do_disc(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service);
-extern void bta_ag_free_db(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
+extern void bta_ag_free_db(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
/* RFCOMM functions */
extern void bta_ag_start_servers(tBTA_AG_SCB* p_scb,
@@ -350,57 +332,62 @@
extern void bta_ag_close_servers(tBTA_AG_SCB* p_scb,
tBTA_SERVICE_MASK services);
extern bool bta_ag_is_server_closed(tBTA_AG_SCB* p_scb);
-extern void bta_ag_rfc_do_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_rfc_do_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
+extern void bta_ag_rfc_do_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_rfc_do_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
/* SCO functions */
+extern bool bta_ag_sco_is_active_device(const RawAddress& bd_addr);
extern bool bta_ag_sco_is_open(tBTA_AG_SCB* p_scb);
extern bool bta_ag_sco_is_opening(tBTA_AG_SCB* p_scb);
extern void bta_ag_sco_conn_rsp(tBTA_AG_SCB* p_scb,
- tBTM_ESCO_CONN_REQ_EVT_DATA* p_data);
+ tBTM_ESCO_CONN_REQ_EVT_DATA* data);
/* AT command functions */
extern void bta_ag_at_hsp_cback(tBTA_AG_SCB* p_scb, uint16_t cmd,
uint8_t arg_type, char* p_arg, int16_t int_arg);
extern void bta_ag_at_hfp_cback(tBTA_AG_SCB* p_scb, uint16_t cmd,
uint8_t arg_type, char* p_arg, int16_t int_arg);
-extern void bta_ag_at_err_cback(tBTA_AG_SCB* p_scb, bool unknown, char* p_arg);
+extern void bta_ag_at_err_cback(tBTA_AG_SCB* p_scb, bool unknown,
+ const char* p_arg);
extern bool bta_ag_inband_enabled(tBTA_AG_SCB* p_scb);
extern void bta_ag_send_call_inds(tBTA_AG_SCB* p_scb, tBTA_AG_RES result);
/* Action functions */
-extern void bta_ag_register(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_deregister(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_start_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_start_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_disc_int_res(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_disc_acp_res(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_disc_fail(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_open_fail(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_rfc_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_rfc_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_rfc_data(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_sco_listen(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_sco_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_sco_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
+extern void bta_ag_register(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_deregister(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_start_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_start_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_disc_int_res(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_disc_acp_res(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_disc_fail(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_open_fail(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_rfc_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_rfc_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_rfc_data(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_sco_listen(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_sco_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_sco_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_sco_conn_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_post_sco_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_post_sco_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_svc_conn_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_result(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_setcodec(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_send_ring(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_handle_collision(tBTA_AG_SCB* p_scb,
+ const tBTA_AG_DATA& data);
+
+/* Internal utility functions */
extern void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result);
extern void bta_ag_codec_negotiate(tBTA_AG_SCB* p_scb);
-extern void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_sco_conn_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_post_sco_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_post_sco_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_svc_conn_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_result(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_setcodec(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_send_bcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_send_ring(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_ci_sco_data(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_ci_rx_data(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_rcvd_slc_ready(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
-extern void bta_ag_set_sco_allowed(tBTA_AG_DATA* p_data);
+extern void bta_ag_send_bcs(tBTA_AG_SCB* p_scb);
+extern void bta_ag_set_sco_allowed(bool value);
+extern const RawAddress& bta_ag_get_active_device();
+extern void bta_clear_active_device();
#endif /* BTA_AG_INT_H */
diff --git a/bta/ag/bta_ag_main.cc b/bta/ag/bta_ag_main.cc
index d33247e..996aa25 100644
--- a/bta/ag/bta_ag_main.cc
+++ b/bta/ag/bta_ag_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,9 +22,9 @@
*
******************************************************************************/
+#include <stack/include/bt_types.h>
#include <string.h>
-#include "bta_ag_co.h"
#include "bta_ag_int.h"
#include "bta_api.h"
#include "bta_sys.h"
@@ -34,15 +34,6 @@
/*****************************************************************************
* Constants and types
****************************************************************************/
-#ifndef BTA_AG_DEBUG
-#define BTA_AG_DEBUG FALSE
-#endif
-
-#if (BTA_AG_DEBUG == TRUE)
-static char* bta_ag_evt_str(uint16_t event, tBTA_AG_RES result);
-static char* bta_ag_state_str(uint8_t state);
-#endif
-
/* state machine states */
enum { BTA_AG_INIT_ST, BTA_AG_OPENING_ST, BTA_AG_OPEN_ST, BTA_AG_CLOSING_ST };
@@ -77,16 +68,88 @@
BTA_AG_RESULT,
BTA_AG_SETCODEC,
BTA_AG_SEND_RING,
- BTA_AG_CI_SCO_DATA,
- BTA_AG_CI_RX_DATA,
- BTA_AG_RCVD_SLC_READY,
+ BTA_AG_HANDLE_COLLISION,
BTA_AG_NUM_ACTIONS
};
#define BTA_AG_IGNORE BTA_AG_NUM_ACTIONS
/* type for action functions */
-typedef void (*tBTA_AG_ACTION)(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data);
+typedef void (*tBTA_AG_ACTION)(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+
+#define CASE_RETURN_STR(const) \
+ case const: \
+ return #const;
+
+static const char* bta_ag_res_str(tBTA_AG_RES result) {
+ switch (result) {
+ CASE_RETURN_STR(BTA_AG_SPK_RES)
+ CASE_RETURN_STR(BTA_AG_MIC_RES)
+ CASE_RETURN_STR(BTA_AG_INBAND_RING_RES)
+ CASE_RETURN_STR(BTA_AG_CIND_RES)
+ CASE_RETURN_STR(BTA_AG_BINP_RES)
+ CASE_RETURN_STR(BTA_AG_IND_RES)
+ CASE_RETURN_STR(BTA_AG_BVRA_RES)
+ CASE_RETURN_STR(BTA_AG_CNUM_RES)
+ CASE_RETURN_STR(BTA_AG_BTRH_RES)
+ CASE_RETURN_STR(BTA_AG_CLCC_RES)
+ CASE_RETURN_STR(BTA_AG_COPS_RES)
+ CASE_RETURN_STR(BTA_AG_IN_CALL_RES)
+ CASE_RETURN_STR(BTA_AG_IN_CALL_CONN_RES)
+ CASE_RETURN_STR(BTA_AG_CALL_WAIT_RES)
+ CASE_RETURN_STR(BTA_AG_OUT_CALL_ORIG_RES)
+ CASE_RETURN_STR(BTA_AG_OUT_CALL_ALERT_RES)
+ CASE_RETURN_STR(BTA_AG_OUT_CALL_CONN_RES)
+ CASE_RETURN_STR(BTA_AG_CALL_CANCEL_RES)
+ CASE_RETURN_STR(BTA_AG_END_CALL_RES)
+ CASE_RETURN_STR(BTA_AG_IN_CALL_HELD_RES)
+ CASE_RETURN_STR(BTA_AG_UNAT_RES)
+ CASE_RETURN_STR(BTA_AG_MULTI_CALL_RES)
+ CASE_RETURN_STR(BTA_AG_BIND_RES)
+ CASE_RETURN_STR(BTA_AG_IND_RES_ON_DEMAND)
+ default:
+ return "Unknown AG Result";
+ }
+}
+
+static const char* bta_ag_evt_str(uint16_t event) {
+ switch (event) {
+ CASE_RETURN_STR(BTA_AG_API_REGISTER_EVT)
+ CASE_RETURN_STR(BTA_AG_API_DEREGISTER_EVT)
+ CASE_RETURN_STR(BTA_AG_API_OPEN_EVT)
+ CASE_RETURN_STR(BTA_AG_API_CLOSE_EVT)
+ CASE_RETURN_STR(BTA_AG_API_AUDIO_OPEN_EVT)
+ CASE_RETURN_STR(BTA_AG_API_AUDIO_CLOSE_EVT)
+ CASE_RETURN_STR(BTA_AG_API_RESULT_EVT)
+ CASE_RETURN_STR(BTA_AG_API_SETCODEC_EVT)
+ CASE_RETURN_STR(BTA_AG_RFC_OPEN_EVT)
+ CASE_RETURN_STR(BTA_AG_RFC_CLOSE_EVT)
+ CASE_RETURN_STR(BTA_AG_RFC_SRV_CLOSE_EVT)
+ CASE_RETURN_STR(BTA_AG_RFC_DATA_EVT)
+ CASE_RETURN_STR(BTA_AG_SCO_OPEN_EVT)
+ CASE_RETURN_STR(BTA_AG_SCO_CLOSE_EVT)
+ CASE_RETURN_STR(BTA_AG_DISC_ACP_RES_EVT)
+ CASE_RETURN_STR(BTA_AG_DISC_INT_RES_EVT)
+ CASE_RETURN_STR(BTA_AG_DISC_OK_EVT)
+ CASE_RETURN_STR(BTA_AG_DISC_FAIL_EVT)
+ CASE_RETURN_STR(BTA_AG_RING_TIMEOUT_EVT)
+ CASE_RETURN_STR(BTA_AG_SVC_TIMEOUT_EVT)
+ CASE_RETURN_STR(BTA_AG_COLLISION_EVT)
+ default:
+ return "Unknown AG Event";
+ }
+}
+
+static const char* bta_ag_state_str(uint8_t state) {
+ switch (state) {
+ CASE_RETURN_STR(BTA_AG_INIT_ST)
+ CASE_RETURN_STR(BTA_AG_OPENING_ST)
+ CASE_RETURN_STR(BTA_AG_OPEN_ST)
+ CASE_RETURN_STR(BTA_AG_CLOSING_ST)
+ default:
+ return "Unknown AG State";
+ }
+}
/* action functions */
const tBTA_AG_ACTION bta_ag_action[] = {
@@ -99,8 +162,11 @@
bta_ag_sco_conn_close, bta_ag_sco_listen, bta_ag_sco_open,
bta_ag_sco_close, bta_ag_sco_shutdown, bta_ag_post_sco_open,
bta_ag_post_sco_close, bta_ag_svc_conn_open, bta_ag_result,
- bta_ag_setcodec, bta_ag_send_ring, bta_ag_ci_sco_data,
- bta_ag_ci_rx_data, bta_ag_rcvd_slc_ready};
+ bta_ag_setcodec, bta_ag_send_ring, bta_ag_handle_collision};
+
+static_assert(sizeof(bta_ag_action) / sizeof(tBTA_AG_ACTION) ==
+ BTA_AG_NUM_ACTIONS,
+ "bta_ag_action must handle all actions");
/* state table information */
#define BTA_AG_ACTIONS 2 /* number of actions */
@@ -128,18 +194,16 @@
/* DISC_INT_RES_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
/* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
/* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
- /* CI_RX_WRITE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
/* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
/* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
- /* CI_SCO_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
- /* CI_SLC_READY_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}};
+ /* COLLISION_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}};
/* state table for opening state */
const uint8_t bta_ag_st_opening[][BTA_AG_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
/* API_REGISTER_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
- /* API_DEREGISTER_EVT */ {BTA_AG_RFC_DO_CLOSE, BTA_AG_START_DEREG,
- BTA_AG_CLOSING_ST},
+ /* API_DEREGISTER_EVT */
+ {BTA_AG_RFC_DO_CLOSE, BTA_AG_START_DEREG, BTA_AG_CLOSING_ST},
/* API_OPEN_EVT */ {BTA_AG_OPEN_FAIL, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
/* API_CLOSE_EVT */ {BTA_AG_RFC_DO_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* API_AUDIO_OPEN_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
@@ -151,25 +215,24 @@
/* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
/* RFC_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
/* SCO_OPEN_EVT */ {BTA_AG_SCO_CONN_OPEN, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
- /* SCO_CLOSE_EVT */ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_IGNORE,
- BTA_AG_OPENING_ST},
+ /* SCO_CLOSE_EVT */
+ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
/* DISC_ACP_RES_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
- /* DISC_INT_RES_EVT */ {BTA_AG_DISC_INT_RES, BTA_AG_IGNORE,
- BTA_AG_OPENING_ST},
+ /* DISC_INT_RES_EVT */
+ {BTA_AG_DISC_INT_RES, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
/* DISC_OK_EVT */ {BTA_AG_RFC_DO_OPEN, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
/* DISC_FAIL_EVT */ {BTA_AG_DISC_FAIL, BTA_AG_IGNORE, BTA_AG_INIT_ST},
- /* CI_RX_WRITE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
/* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
/* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
- /* CI_SCO_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
- /* CI_SLC_READY_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST}};
+ /* COLLISION_EVT */
+ {BTA_AG_HANDLE_COLLISION, BTA_AG_IGNORE, BTA_AG_INIT_ST}};
/* state table for open state */
const uint8_t bta_ag_st_open[][BTA_AG_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
/* API_REGISTER_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
- /* API_DEREGISTER_EVT */ {BTA_AG_START_CLOSE, BTA_AG_START_DEREG,
- BTA_AG_CLOSING_ST},
+ /* API_DEREGISTER_EVT */
+ {BTA_AG_START_CLOSE, BTA_AG_START_DEREG, BTA_AG_CLOSING_ST},
/* API_OPEN_EVT */ {BTA_AG_OPEN_FAIL, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
/* API_CLOSE_EVT */ {BTA_AG_START_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* API_AUDIO_OPEN_EVT */ {BTA_AG_SCO_OPEN, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
@@ -180,27 +243,24 @@
/* RFC_CLOSE_EVT */ {BTA_AG_RFC_CLOSE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
/* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
/* RFC_DATA_EVT */ {BTA_AG_RFC_DATA, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
- /* SCO_OPEN_EVT */ {BTA_AG_SCO_CONN_OPEN, BTA_AG_POST_SCO_OPEN,
- BTA_AG_OPEN_ST},
- /* SCO_CLOSE_EVT */ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_POST_SCO_CLOSE,
- BTA_AG_OPEN_ST},
+ /* SCO_OPEN_EVT */
+ {BTA_AG_SCO_CONN_OPEN, BTA_AG_POST_SCO_OPEN, BTA_AG_OPEN_ST},
+ /* SCO_CLOSE_EVT */
+ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_POST_SCO_CLOSE, BTA_AG_OPEN_ST},
/* DISC_ACP_RES_EVT */ {BTA_AG_DISC_ACP_RES, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
/* DISC_INT_RES_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
/* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
/* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
- /* CI_RX_WRITE_EVT */ {BTA_AG_CI_RX_DATA, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
/* RING_TOUT_EVT */ {BTA_AG_SEND_RING, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
/* SVC_TOUT_EVT */ {BTA_AG_START_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
- /* CI_SCO_DATA_EVT */ {BTA_AG_CI_SCO_DATA, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
- /* CI_SLC_READY_EVT */
- {BTA_AG_RCVD_SLC_READY, BTA_AG_IGNORE, BTA_AG_OPEN_ST}};
+ /* COLLISION_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST}};
/* state table for closing state */
const uint8_t bta_ag_st_closing[][BTA_AG_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
/* API_REGISTER_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
- /* API_DEREGISTER_EVT */ {BTA_AG_START_DEREG, BTA_AG_IGNORE,
- BTA_AG_CLOSING_ST},
+ /* API_DEREGISTER_EVT */
+ {BTA_AG_START_DEREG, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* API_OPEN_EVT */ {BTA_AG_OPEN_FAIL, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* API_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* API_AUDIO_OPEN_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
@@ -212,17 +272,26 @@
/* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* RFC_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* SCO_OPEN_EVT */ {BTA_AG_SCO_CONN_OPEN, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
- /* SCO_CLOSE_EVT */ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_POST_SCO_CLOSE,
- BTA_AG_CLOSING_ST},
+ /* SCO_CLOSE_EVT */
+ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_POST_SCO_CLOSE, BTA_AG_CLOSING_ST},
/* DISC_ACP_RES_EVT */ {BTA_AG_FREE_DB, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* DISC_INT_RES_EVT */ {BTA_AG_FREE_DB, BTA_AG_IGNORE, BTA_AG_INIT_ST},
/* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
- /* CI_RX_WRITE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
/* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
- /* CI_SCO_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
- /* CI_SLC_READY_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}};
+ /* COLLISION_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}};
+
+constexpr size_t BTA_AG_NUM_EVENTS =
+ BTA_AG_MAX_EVT - BTA_SYS_EVT_START(BTA_ID_AG);
+static_assert(sizeof(bta_ag_st_init) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
+ "bta_ag_st_init must handle all AG events");
+static_assert(sizeof(bta_ag_st_opening) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
+ "bta_ag_st_opening must handle all AG events");
+static_assert(sizeof(bta_ag_st_open) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
+ "bta_ag_st_open must handle all AG events");
+static_assert(sizeof(bta_ag_st_closing) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
+ "bta_ag_st_closing must handle all AG events");
/* type for state table */
typedef const uint8_t (*tBTA_AG_ST_TBL)[BTA_AG_NUM_COLS];
@@ -237,6 +306,7 @@
/* AG control block */
tBTA_AG_CB bta_ag_cb;
+const tBTA_AG_DATA tBTA_AG_DATA::kEmpty = {};
/*******************************************************************************
*
@@ -252,15 +322,19 @@
tBTA_AG_SCB* p_scb = &bta_ag_cb.scb[0];
int i;
- for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++) {
+ for (i = 0; i < BTA_AG_MAX_NUM_CLIENTS; i++, p_scb++) {
if (!p_scb->in_use) {
/* initialize variables */
p_scb->in_use = true;
p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+ p_scb->received_at_bac = false;
p_scb->codec_updated = false;
p_scb->codec_fallback = false;
p_scb->peer_codecs = BTA_AG_CODEC_CVSD;
p_scb->sco_codec = BTA_AG_CODEC_CVSD;
+ p_scb->peer_version = HFP_HSP_VERSION_UNKNOWN;
+ p_scb->hsp_version = HSP_VERSION_1_2;
+ p_scb->peer_sdp_features = 0;
/* set up timers */
p_scb->ring_timer = alarm_new("bta_ag.scb_ring_timer");
p_scb->collision_timer = alarm_new("bta_ag.scb_collision_timer");
@@ -273,9 +347,9 @@
}
}
- if (i == BTA_AG_NUM_SCB) {
+ if (i == BTA_AG_MAX_NUM_CLIENTS) {
/* out of scbs */
- p_scb = NULL;
+ p_scb = nullptr;
APPL_TRACE_WARNING("%s: Out of scbs", __func__);
}
return p_scb;
@@ -303,12 +377,12 @@
alarm_free(p_scb->collision_timer);
/* initialize control block */
- memset(p_scb, 0, sizeof(tBTA_AG_SCB));
+ *p_scb = {};
p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
/* If all scbs are deallocated, callback with disable event */
if (!bta_sys_is_register(BTA_ID_AG)) {
- for (idx = 0; idx < BTA_AG_NUM_SCB; idx++) {
+ for (idx = 0; idx < BTA_AG_MAX_NUM_CLIENTS; idx++) {
if (bta_ag_cb.scb[idx].in_use) {
allocated = true;
break;
@@ -316,7 +390,7 @@
}
if (!allocated) {
- (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL);
+ (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, nullptr);
}
}
}
@@ -328,12 +402,12 @@
* Description Given a pointer to an scb, return its index.
*
*
- * Returns Index of scb.
+ * Returns Index of scb starting from 1
*
******************************************************************************/
uint16_t bta_ag_scb_to_idx(tBTA_AG_SCB* p_scb) {
/* use array arithmetic to determine index */
- return ((uint16_t)(p_scb - bta_ag_cb.scb)) + 1;
+ return static_cast<uint16_t>(p_scb - bta_ag_cb.scb + 1);
}
/*******************************************************************************
@@ -350,14 +424,14 @@
tBTA_AG_SCB* p_scb;
/* verify index */
- if (idx > 0 && idx <= BTA_AG_NUM_SCB) {
+ if (idx > 0 && idx <= BTA_AG_MAX_NUM_CLIENTS) {
p_scb = &bta_ag_cb.scb[idx - 1];
if (!p_scb->in_use) {
- p_scb = NULL;
+ p_scb = nullptr;
APPL_TRACE_WARNING("ag scb idx %d not allocated", idx);
}
} else {
- p_scb = NULL;
+ p_scb = nullptr;
APPL_TRACE_DEBUG("ag scb idx %d out of range", idx);
}
return p_scb;
@@ -393,10 +467,8 @@
******************************************************************************/
uint16_t bta_ag_idx_by_bdaddr(const RawAddress* peer_addr) {
tBTA_AG_SCB* p_scb = &bta_ag_cb.scb[0];
- uint16_t i;
-
- if (peer_addr != NULL) {
- for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++) {
+ if (peer_addr != nullptr) {
+ for (uint16_t i = 0; i < BTA_AG_MAX_NUM_CLIENTS; i++, p_scb++) {
if (p_scb->in_use && *peer_addr == p_scb->peer_addr) {
return (i + 1);
}
@@ -420,15 +492,12 @@
******************************************************************************/
bool bta_ag_other_scb_open(tBTA_AG_SCB* p_curr_scb) {
tBTA_AG_SCB* p_scb = &bta_ag_cb.scb[0];
- int i;
-
- for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++) {
+ for (int i = 0; i < BTA_AG_MAX_NUM_CLIENTS; i++, p_scb++) {
if (p_scb->in_use && p_scb != p_curr_scb &&
p_scb->state == BTA_AG_OPEN_ST) {
return true;
}
}
-
/* no other scb found */
APPL_TRACE_DEBUG("No other ag scb open");
return false;
@@ -445,57 +514,8 @@
*
******************************************************************************/
bool bta_ag_scb_open(tBTA_AG_SCB* p_curr_scb) {
- if (p_curr_scb && p_curr_scb->in_use && p_curr_scb->state == BTA_AG_OPEN_ST) {
- return true;
- }
-
- return false;
-}
-
-/*******************************************************************************
- *
- * Function bta_ag_get_other_idle_scb
- *
- * Description Return other scb if it is in INIT st.
- *
- *
- * Returns Pointer to other scb if INIT st, NULL otherwise.
- *
- ******************************************************************************/
-tBTA_AG_SCB* bta_ag_get_other_idle_scb(tBTA_AG_SCB* p_curr_scb) {
- tBTA_AG_SCB* p_scb = &bta_ag_cb.scb[0];
- uint8_t xx;
-
- for (xx = 0; xx < BTA_AG_NUM_SCB; xx++, p_scb++) {
- if (p_scb->in_use && (p_scb != p_curr_scb) &&
- (p_scb->state == BTA_AG_INIT_ST)) {
- return p_scb;
- }
- }
-
- /* no other scb found */
- APPL_TRACE_DEBUG("bta_ag_get_other_idle_scb: No idle AG scb");
- return NULL;
-}
-
-/*******************************************************************************
- *
- * Function bta_ag_collision_timer_cback
- *
- * Description AG connection collision timer callback
- *
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_ag_collision_timer_cback(void* data) {
- tBTA_AG_SCB* p_scb = (tBTA_AG_SCB*)data;
-
- APPL_TRACE_DEBUG("%s", __func__);
-
- /* If the peer haven't opened AG connection */
- /* we will restart opening process. */
- bta_ag_resume_open(p_scb);
+ return p_curr_scb && p_curr_scb->in_use &&
+ p_curr_scb->state == BTA_AG_OPEN_ST;
}
/*******************************************************************************
@@ -510,41 +530,23 @@
******************************************************************************/
void bta_ag_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status, uint8_t id,
UNUSED_ATTR uint8_t app_id,
- const RawAddress* peer_addr) {
- uint16_t handle;
- tBTA_AG_SCB* p_scb;
-
+ const RawAddress& peer_addr) {
/* Check if we have opening scb for the peer device. */
- handle = bta_ag_idx_by_bdaddr(peer_addr);
- p_scb = bta_ag_scb_by_idx(handle);
+ uint16_t handle = bta_ag_idx_by_bdaddr(&peer_addr);
+ tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
if (p_scb && (p_scb->state == BTA_AG_OPENING_ST)) {
- if (id == BTA_ID_SYS) /* ACL collision */
- {
- APPL_TRACE_WARNING("AG found collision (ACL) ...");
- } else if (id == BTA_ID_AG) /* RFCOMM collision */
- {
- APPL_TRACE_WARNING("AG found collision (RFCOMM) ...");
+ if (id == BTA_ID_SYS) {
+ LOG(WARNING) << __func__ << "AG found collision (ACL) for handle "
+ << unsigned(handle) << " device " << peer_addr;
+ } else if (id == BTA_ID_AG) {
+ LOG(WARNING) << __func__ << "AG found collision (RFCOMM) for handle "
+ << unsigned(handle) << " device " << peer_addr;
} else {
- APPL_TRACE_WARNING("AG found collision (\?\?\?) ...");
+ LOG(WARNING) << __func__ << "AG found collision (UNKNOWN) for handle "
+ << unsigned(handle) << " device " << peer_addr;
}
-
- p_scb->state = BTA_AG_INIT_ST;
-
- /* Cancel SDP if it had been started. */
- if (p_scb->p_disc_db) {
- (void)SDP_CancelServiceSearch(p_scb->p_disc_db);
- bta_ag_free_db(p_scb, NULL);
- }
-
- /* reopen registered servers */
- /* Collision may be detected before or after we close servers. */
- if (bta_ag_is_server_closed(p_scb))
- bta_ag_start_servers(p_scb, p_scb->reg_services);
-
- /* Start timer to han */
- alarm_set_on_mloop(p_scb->collision_timer, BTA_AG_COLLISION_TIMEOUT_MS,
- bta_ag_collision_timer_cback, p_scb);
+ bta_ag_sm_execute(p_scb, BTA_AG_COLLISION_EVT, tBTA_AG_DATA::kEmpty);
}
}
@@ -559,17 +561,15 @@
*
******************************************************************************/
void bta_ag_resume_open(tBTA_AG_SCB* p_scb) {
- if (p_scb) {
- APPL_TRACE_DEBUG("bta_ag_resume_open, Handle(%d)",
- bta_ag_scb_to_idx(p_scb));
-
- /* resume opening process. */
- if (p_scb->state == BTA_AG_INIT_ST) {
- p_scb->state = BTA_AG_OPENING_ST;
- bta_ag_start_open(p_scb, NULL);
- }
+ if (p_scb->state == BTA_AG_INIT_ST) {
+ LOG(INFO) << __func__ << ": Resume connection to " << p_scb->peer_addr
+ << ", handle" << bta_ag_scb_to_idx(p_scb);
+ tBTA_AG_DATA open_data = {.api_open.bd_addr = p_scb->peer_addr,
+ .api_open.sec_mask = p_scb->cli_sec_mask};
+ bta_ag_sm_execute(p_scb, BTA_AG_API_OPEN_EVT, open_data);
} else {
- APPL_TRACE_ERROR("bta_ag_resume_open, Null p_scb");
+ VLOG(1) << __func__ << ": device " << p_scb->peer_addr
+ << " is already in state " << std::to_string(p_scb->state);
}
}
@@ -583,26 +583,25 @@
* Returns void
*
******************************************************************************/
-static void bta_ag_api_enable(tBTA_AG_DATA* p_data) {
+void bta_ag_api_enable(tBTA_AG_CBACK* p_cback) {
/* initialize control block */
- for (size_t i = 0; i < BTA_AG_NUM_SCB; i++) {
- alarm_free(bta_ag_cb.scb[i].ring_timer);
- alarm_free(bta_ag_cb.scb[i].codec_negotiation_timer);
- alarm_free(bta_ag_cb.scb[i].collision_timer);
+ for (tBTA_AG_SCB& scb : bta_ag_cb.scb) {
+ alarm_free(scb.ring_timer);
+ alarm_free(scb.codec_negotiation_timer);
+ alarm_free(scb.collision_timer);
+ scb = {};
}
- memset(&bta_ag_cb, 0, sizeof(tBTA_AG_CB));
/* store callback function */
- bta_ag_cb.p_cback = p_data->api_enable.p_cback;
- bta_ag_cb.parse_mode = p_data->api_enable.parse_mode;
+ bta_ag_cb.p_cback = p_cback;
/* call init call-out */
- bta_ag_co_init();
+ BTM_WriteVoiceSettings(AG_VOICE_SETTINGS);
bta_sys_collision_register(BTA_ID_AG, bta_ag_collision_cback);
/* call callback with enable event */
- (*bta_ag_cb.p_cback)(BTA_AG_ENABLE_EVT, NULL);
+ (*bta_ag_cb.p_cback)(BTA_AG_ENABLE_EVT, nullptr);
}
/*******************************************************************************
@@ -615,7 +614,7 @@
* Returns void
*
******************************************************************************/
-static void bta_ag_api_disable(tBTA_AG_DATA* p_data) {
+void bta_ag_api_disable() {
/* deregister all scbs in use */
tBTA_AG_SCB* p_scb = &bta_ag_cb.scb[0];
bool do_dereg = false;
@@ -629,19 +628,19 @@
/* De-register with BTA system manager */
bta_sys_deregister(BTA_ID_AG);
- for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++) {
+ for (i = 0; i < BTA_AG_MAX_NUM_CLIENTS; i++, p_scb++) {
if (p_scb->in_use) {
- bta_ag_sm_execute(p_scb, BTA_AG_API_DEREGISTER_EVT, p_data);
+ bta_ag_sm_execute(p_scb, BTA_AG_API_DEREGISTER_EVT, tBTA_AG_DATA::kEmpty);
do_dereg = true;
}
}
if (!do_dereg) {
/* Done, send callback evt to app */
- (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL);
+ (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, nullptr);
}
- bta_sys_collision_register(BTA_ID_AG, NULL);
+ bta_sys_collision_register(BTA_ID_AG, nullptr);
}
/*******************************************************************************
@@ -654,18 +653,31 @@
* Returns void
*
******************************************************************************/
-static void bta_ag_api_register(tBTA_AG_DATA* p_data) {
- tBTA_AG_SCB* p_scb;
- tBTA_AG_REGISTER reg;
-
- /* allocate an scb */
- p_scb = bta_ag_scb_alloc();
- if (p_scb != NULL) {
+void bta_ag_api_register(tBTA_SERVICE_MASK services, tBTA_SEC sec_mask,
+ tBTA_AG_FEAT features,
+ const std::vector<std::string>& service_names,
+ uint8_t app_id) {
+ tBTA_AG_SCB* p_scb = bta_ag_scb_alloc();
+ if (p_scb) {
APPL_TRACE_DEBUG("bta_ag_api_register: p_scb 0x%08x ", p_scb);
- bta_ag_sm_execute(p_scb, p_data->hdr.event, p_data);
+ tBTA_AG_DATA data = {};
+ data.api_register.features = features;
+ data.api_register.sec_mask = sec_mask;
+ data.api_register.services = services;
+ data.api_register.app_id = app_id;
+ for (int i = 0; i < BTA_AG_NUM_IDX; i++) {
+ if (!service_names[i].empty()) {
+ strlcpy(data.api_register.p_name[i], service_names[i].c_str(),
+ BTA_SERVICE_NAME_LEN);
+ } else {
+ data.api_register.p_name[i][0] = 0;
+ }
+ }
+ bta_ag_sm_execute(p_scb, BTA_AG_API_REGISTER_EVT, data);
} else {
- reg.status = BTA_AG_FAIL_RESOURCES;
- (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG*)®);
+ tBTA_AG bta_ag = {};
+ bta_ag.reg.status = BTA_AG_FAIL_RESOURCES;
+ (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, &bta_ag);
}
}
@@ -679,21 +691,27 @@
* Returns void
*
******************************************************************************/
-static void bta_ag_api_result(tBTA_AG_DATA* p_data) {
+void bta_ag_api_result(uint16_t handle, tBTA_AG_RES result,
+ const tBTA_AG_RES_DATA& result_data) {
+ tBTA_AG_DATA event_data = {};
+ event_data.api_result.result = result;
+ event_data.api_result.data = result_data;
tBTA_AG_SCB* p_scb;
- int i;
-
- if (p_data->hdr.layer_specific != BTA_AG_HANDLE_ALL) {
- p_scb = bta_ag_scb_by_idx(p_data->hdr.layer_specific);
- if (p_scb != NULL) {
+ if (handle != BTA_AG_HANDLE_ALL) {
+ p_scb = bta_ag_scb_by_idx(handle);
+ if (p_scb) {
APPL_TRACE_DEBUG("bta_ag_api_result: p_scb 0x%08x ", p_scb);
- bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
+ bta_ag_sm_execute(p_scb, static_cast<uint16_t>(BTA_AG_API_RESULT_EVT),
+ event_data);
}
} else {
- for (i = 0, p_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, p_scb++) {
+ int i;
+ for (i = 0, p_scb = &bta_ag_cb.scb[0]; i < BTA_AG_MAX_NUM_CLIENTS;
+ i++, p_scb++) {
if (p_scb->in_use && p_scb->svc_conn) {
APPL_TRACE_DEBUG("bta_ag_api_result p_scb 0x%08x ", p_scb);
- bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
+ bta_ag_sm_execute(p_scb, static_cast<uint16_t>(BTA_AG_API_RESULT_EVT),
+ event_data);
}
}
}
@@ -710,30 +728,19 @@
*
******************************************************************************/
void bta_ag_sm_execute(tBTA_AG_SCB* p_scb, uint16_t event,
- tBTA_AG_DATA* p_data) {
+ const tBTA_AG_DATA& data) {
tBTA_AG_ST_TBL state_table;
uint8_t action;
int i;
-#if (BTA_AG_DEBUG == TRUE)
uint16_t previous_event = event;
uint8_t previous_state = p_scb->state;
- /* Ignore displaying of AT results when not connected (Ignored in state
- * machine) */
- if ((previous_event != BTA_AG_API_RESULT_EVT ||
- p_scb->state == BTA_AG_OPEN_ST) &&
- event != BTA_AG_CI_SCO_DATA_EVT) {
- APPL_TRACE_EVENT("%s: Handle 0x%04x, State %d (%s), Event 0x%04x (%s)",
- __func__, bta_ag_scb_to_idx(p_scb), p_scb->state,
- bta_ag_state_str(p_scb->state), event,
- bta_ag_evt_str(event, p_data->api_result.result));
- }
-#else
- if (event != BTA_AG_CI_SCO_DATA_EVT) {
- APPL_TRACE_EVENT("%s: Handle 0x%04x, State %d, Event 0x%04x", __func__,
- bta_ag_scb_to_idx(p_scb), p_scb->state, event);
- }
-#endif
+ APPL_TRACE_EVENT(
+ "%s: handle=0x%04x, bd_addr=%s, state=%s(0x%02x), "
+ "event=%s(0x%04x), result=%s(0x%02x)",
+ __func__, bta_ag_scb_to_idx(p_scb), p_scb->peer_addr.ToString().c_str(),
+ bta_ag_state_str(p_scb->state), p_scb->state, bta_ag_evt_str(event),
+ event, bta_ag_res_str(data.api_result.result), data.api_result.result);
event &= 0x00FF;
if (event >= (BTA_AG_MAX_EVT & 0x00FF)) {
@@ -751,182 +758,50 @@
for (i = 0; i < BTA_AG_ACTIONS; i++) {
action = state_table[event][i];
if (action != BTA_AG_IGNORE) {
- (*bta_ag_action[action])(p_scb, p_data);
+ (*bta_ag_action[action])(p_scb, data);
} else {
break;
}
}
-#if (BTA_AG_DEBUG == TRUE)
if (p_scb->state != previous_state) {
- APPL_TRACE_EVENT("%s: State Change: [%s] -> [%s] after Event [%s]",
- __func__, bta_ag_state_str(previous_state),
- bta_ag_state_str(p_scb->state),
- bta_ag_evt_str(previous_event, p_data->api_result.result));
+ APPL_TRACE_EVENT(
+ "%s: handle=0x%04x, bd_addr=%s, state_change[%s(0x%02x)]->[%s(0x%02x)],"
+ " event[%s(0x%04x)], result[%s(0x%02x)]",
+ __func__, bta_ag_scb_to_idx(p_scb), p_scb->peer_addr.ToString().c_str(),
+ bta_ag_state_str(previous_state), previous_state,
+ bta_ag_state_str(p_scb->state), p_scb->state,
+ bta_ag_evt_str(previous_event), previous_event,
+ bta_ag_res_str(data.api_result.result), data.api_result.result);
}
-#endif
}
-/*******************************************************************************
+void bta_ag_sm_execute_by_handle(uint16_t handle, uint16_t event,
+ const tBTA_AG_DATA& data) {
+ tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
+ if (p_scb) {
+ APPL_TRACE_DEBUG("%s: p_scb 0x%08x ", __func__, p_scb);
+ bta_ag_sm_execute(p_scb, event, data);
+ }
+}
+
+/**
+ * Handles event from bta_sys_sendmsg(). It is here to support legacy alarm
+ * implementation that is mainly for timeouts.
*
- * Function bta_ag_hdl_event
- *
- * Description Data gateway main event handling function.
- *
- *
- * Returns bool
- *
- ******************************************************************************/
+ * @param p_msg event message
+ * @return True to free p_msg, or False if p_msg is freed within this function
+ */
bool bta_ag_hdl_event(BT_HDR* p_msg) {
- tBTA_AG_SCB* p_scb;
-
- APPL_TRACE_DEBUG("bta_ag_hdl_event: Event 0x%04x ", p_msg->event);
switch (p_msg->event) {
- case BTA_AG_API_ENABLE_EVT:
- bta_ag_api_enable((tBTA_AG_DATA*)p_msg);
+ case BTA_AG_RING_TIMEOUT_EVT:
+ case BTA_AG_SVC_TIMEOUT_EVT:
+ bta_ag_sm_execute_by_handle(p_msg->layer_specific, p_msg->event,
+ tBTA_AG_DATA::kEmpty);
break;
-
- case BTA_AG_API_DISABLE_EVT:
- bta_ag_api_disable((tBTA_AG_DATA*)p_msg);
- break;
-
- case BTA_AG_API_REGISTER_EVT:
- bta_ag_api_register((tBTA_AG_DATA*)p_msg);
- break;
-
- case BTA_AG_API_RESULT_EVT:
- bta_ag_api_result((tBTA_AG_DATA*)p_msg);
- break;
-
- case BTA_AG_API_SET_SCO_ALLOWED_EVT:
- bta_ag_set_sco_allowed((tBTA_AG_DATA*)p_msg);
- break;
-
- /* all others reference scb by handle */
default:
- p_scb = bta_ag_scb_by_idx(p_msg->layer_specific);
- if (p_scb != NULL) {
- APPL_TRACE_DEBUG("bta_ag_hdl_event: p_scb 0x%08x ", p_scb);
- bta_ag_sm_execute(p_scb, p_msg->event, (tBTA_AG_DATA*)p_msg);
- }
+ LOG(FATAL) << __func__ << ": bad event " << p_msg->event
+ << " layer_specific=" << p_msg->layer_specific;
break;
}
return true;
}
-
-#if (BTA_AG_DEBUG == TRUE)
-static char* bta_ag_evt_str(uint16_t event, tBTA_AG_RES result) {
- switch (event) {
- case BTA_AG_API_REGISTER_EVT:
- return "Register Request";
- case BTA_AG_API_DEREGISTER_EVT:
- return "Deregister Request";
- case BTA_AG_API_OPEN_EVT:
- return "Open SLC Request";
- case BTA_AG_API_CLOSE_EVT:
- return "Close SLC Request";
- case BTA_AG_API_AUDIO_OPEN_EVT:
- return "Open Audio Request";
- case BTA_AG_API_AUDIO_CLOSE_EVT:
- return "Close Audio Request";
- case BTA_AG_API_RESULT_EVT:
- switch (result) {
- case BTA_AG_SPK_RES:
- return ("AT Result BTA_AG_SPK_RES");
- case BTA_AG_MIC_RES:
- return ("AT Result BTA_AG_MIC_RES");
- case BTA_AG_INBAND_RING_RES:
- return ("AT Result BTA_AG_INBAND_RING_RES");
- case BTA_AG_CIND_RES:
- return ("AT Result BTA_AG_CIND_RES");
- case BTA_AG_BINP_RES:
- return ("AT Result BTA_AG_BINP_RES");
- case BTA_AG_IND_RES:
- return ("AT Result BTA_AG_IND_RES");
- case BTA_AG_BVRA_RES:
- return ("AT Result BTA_AG_BVRA_RES");
- case BTA_AG_CNUM_RES:
- return ("AT Result BTA_AG_CNUM_RES");
- case BTA_AG_BTRH_RES:
- return ("AT Result BTA_AG_BTRH_RES");
- case BTA_AG_CLCC_RES:
- return ("AT Result BTA_AG_CLCC_RES");
- case BTA_AG_COPS_RES:
- return ("AT Result BTA_AG_COPS_RES");
- case BTA_AG_IN_CALL_RES:
- return ("AT Result BTA_AG_IN_CALL_RES");
- case BTA_AG_IN_CALL_CONN_RES:
- return ("AT Result BTA_AG_IN_CALL_CONN_RES");
- case BTA_AG_CALL_WAIT_RES:
- return ("AT Result BTA_AG_CALL_WAIT_RES");
- case BTA_AG_OUT_CALL_ORIG_RES:
- return ("AT Result BTA_AG_OUT_CALL_ORIG_RES");
- case BTA_AG_OUT_CALL_ALERT_RES:
- return ("AT Result BTA_AG_OUT_CALL_ALERT_RES");
- case BTA_AG_OUT_CALL_CONN_RES:
- return ("AT Result BTA_AG_OUT_CALL_CONN_RES");
- case BTA_AG_CALL_CANCEL_RES:
- return ("AT Result BTA_AG_CALL_CANCEL_RES");
- case BTA_AG_END_CALL_RES:
- return ("AT Result BTA_AG_END_CALL_RES");
- case BTA_AG_UNAT_RES:
- return ("AT Result BTA_AG_UNAT_RES");
- default:
- return ("Unknown AG Result");
- }
- case BTA_AG_API_SETCODEC_EVT:
- return "Set Codec Request";
- case BTA_AG_RFC_OPEN_EVT:
- return "RFC Opened";
- case BTA_AG_RFC_CLOSE_EVT:
- return "RFC Closed";
- case BTA_AG_RFC_SRV_CLOSE_EVT:
- return "RFC SRV Closed";
- case BTA_AG_RFC_DATA_EVT:
- return "RFC Data";
- case BTA_AG_SCO_OPEN_EVT:
- return "Audio Opened";
- case BTA_AG_SCO_CLOSE_EVT:
- return "Audio Closed";
- case BTA_AG_DISC_ACP_RES_EVT:
- return "Discovery ACP Result";
- case BTA_AG_DISC_INT_RES_EVT:
- return "Discovery INT Result";
- case BTA_AG_DISC_OK_EVT:
- return "Discovery OK";
- case BTA_AG_DISC_FAIL_EVT:
- return "Discovery Failed";
- case BTA_AG_CI_RX_WRITE_EVT:
- return "CI RX Write";
- case BTA_AG_RING_TIMEOUT_EVT:
- return "Ring Timeout";
- case BTA_AG_SVC_TIMEOUT_EVT:
- return "Service Timeout";
- case BTA_AG_API_ENABLE_EVT:
- return "Enable AG";
- case BTA_AG_API_DISABLE_EVT:
- return "Disable AG";
- case BTA_AG_CI_SCO_DATA_EVT:
- return "SCO data Callin";
- case BTA_AG_CI_SLC_READY_EVT:
- return "SLC Ready Callin";
- default:
- return "Unknown AG Event";
- }
-}
-
-static char* bta_ag_state_str(uint8_t state) {
- switch (state) {
- case BTA_AG_INIT_ST:
- return "Initial";
- case BTA_AG_OPENING_ST:
- return "Opening";
- case BTA_AG_OPEN_ST:
- return "Open";
- case BTA_AG_CLOSING_ST:
- return "Closing";
- default:
- return "Unknown AG State";
- }
-}
-
-#endif
diff --git a/bta/ag/bta_ag_rfc.cc b/bta/ag/bta_ag_rfc.cc
index 02729d5..ba9bd7f 100644
--- a/bta/ag/bta_ag_rfc.cc
+++ b/bta/ag/bta_ag_rfc.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,14 +23,13 @@
*
******************************************************************************/
-#include <string.h>
+#include <cstring>
+
+#include <base/bind.h>
#include "bt_common.h"
#include "bta_ag_api.h"
-#include "bta_ag_co.h"
#include "bta_ag_int.h"
-#include "bta_api.h"
-#include "bta_sys.h"
#include "btm_api.h"
#include "osi/include/osi.h"
#include "port_api.h"
@@ -44,26 +43,25 @@
void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle);
void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle);
void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle);
-
+void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle);
+void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle);
+void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle);
void bta_ag_mgmt_cback_1(uint32_t code, uint16_t port_handle);
void bta_ag_mgmt_cback_2(uint32_t code, uint16_t port_handle);
void bta_ag_mgmt_cback_3(uint32_t code, uint16_t port_handle);
-
-int bta_ag_data_cback_1(uint16_t port_handle, void* p_data, uint16_t len);
-int bta_ag_data_cback_2(uint16_t port_handle, void* p_data, uint16_t len);
-int bta_ag_data_cback_3(uint16_t port_handle, void* p_data, uint16_t len);
+void bta_ag_mgmt_cback_4(uint32_t code, uint16_t port_handle);
+void bta_ag_mgmt_cback_5(uint32_t code, uint16_t port_handle);
+void bta_ag_mgmt_cback_6(uint32_t code, uint16_t port_handle);
/* rfcomm callback function tables */
typedef tPORT_CALLBACK* tBTA_AG_PORT_CBACK;
const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = {
- bta_ag_port_cback_1, bta_ag_port_cback_2, bta_ag_port_cback_3};
+ bta_ag_port_cback_1, bta_ag_port_cback_2, bta_ag_port_cback_3,
+ bta_ag_port_cback_4, bta_ag_port_cback_5, bta_ag_port_cback_6};
const tBTA_AG_PORT_CBACK bta_ag_mgmt_cback_tbl[] = {
- bta_ag_mgmt_cback_1, bta_ag_mgmt_cback_2, bta_ag_mgmt_cback_3};
-
-typedef tPORT_DATA_CALLBACK* tBTA_AG_DATA_CBACK;
-const tBTA_AG_DATA_CBACK bta_ag_data_cback_tbl[] = {
- bta_ag_data_cback_1, bta_ag_data_cback_2, bta_ag_data_cback_3};
+ bta_ag_mgmt_cback_1, bta_ag_mgmt_cback_2, bta_ag_mgmt_cback_3,
+ bta_ag_mgmt_cback_4, bta_ag_mgmt_cback_5, bta_ag_mgmt_cback_6};
/*******************************************************************************
*
@@ -77,22 +75,23 @@
******************************************************************************/
static void bta_ag_port_cback(UNUSED_ATTR uint32_t code, uint16_t port_handle,
uint16_t handle) {
- tBTA_AG_SCB* p_scb;
-
- p_scb = bta_ag_scb_by_idx(handle);
- if (p_scb != NULL) {
+ tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
+ if (p_scb != nullptr) {
/* ignore port events for port handles other than connected handle */
if (port_handle != p_scb->conn_handle) {
- APPL_TRACE_DEBUG(
+ APPL_TRACE_ERROR(
"ag_port_cback ignoring handle:%d conn_handle = %d other handle = %d",
port_handle, p_scb->conn_handle, handle);
return;
}
-
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
- p_buf->event = BTA_AG_RFC_DATA_EVT;
- p_buf->layer_specific = handle;
- bta_sys_sendmsg(p_buf);
+ if (!bta_ag_scb_open(p_scb)) {
+ LOG(ERROR) << __func__ << ": rfcomm data on an unopened control block "
+ << handle << " peer_addr " << p_scb->peer_addr << " state "
+ << std::to_string(p_scb->state);
+ }
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&bta_ag_sm_execute_by_handle, handle,
+ BTA_AG_RFC_DATA_EVT, tBTA_AG_DATA::kEmpty));
}
}
@@ -108,78 +107,61 @@
******************************************************************************/
static void bta_ag_mgmt_cback(uint32_t code, uint16_t port_handle,
uint16_t handle) {
- tBTA_AG_SCB* p_scb;
+ tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
+ APPL_TRACE_DEBUG("%s: code=%d, port_handle=%d, scb_handle=%d, p_scb=0x%08x",
+ __func__, code, port_handle, handle, p_scb);
+ if (p_scb == nullptr) {
+ LOG(WARNING) << __func__ << ": cannot find scb, code=" << code
+ << ", port_handle=" << port_handle << ", handle=" << handle;
+ return;
+ }
+ /* ignore close event for port handles other than connected handle */
+ if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle)) {
+ LOG(WARNING) << __func__ << ": ignore open failure for unmatched "
+ << "port_handle " << port_handle << ", scb_handle=" << handle;
+ return;
+ }
uint16_t event;
- uint8_t i;
- bool found_handle = false;
-
- APPL_TRACE_DEBUG("ag_mgmt_cback : code = %d, port_handle = %d, handle = %d",
- code, port_handle, handle);
-
- p_scb = bta_ag_scb_by_idx(handle);
- if (p_scb != NULL) {
- /* ignore close event for port handles other than connected handle */
- if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle)) {
- APPL_TRACE_DEBUG("ag_mgmt_cback ignoring handle:%d", port_handle);
- return;
- }
-
- if (code == PORT_SUCCESS) {
- if (p_scb->conn_handle) /* Outgoing connection */
- {
- if (port_handle == p_scb->conn_handle) found_handle = true;
- } else /* Incoming connection */
- {
- for (i = 0; i < BTA_AG_NUM_IDX; i++) {
- if (port_handle == p_scb->serv_handle[i]) found_handle = true;
+ if (code == PORT_SUCCESS) {
+ bool found_handle = false;
+ if (p_scb->conn_handle) {
+ /* Outgoing connection */
+ if (port_handle == p_scb->conn_handle) {
+ found_handle = true;
+ }
+ } else {
+ /* Incoming connection */
+ for (uint16_t service_port_handle : p_scb->serv_handle) {
+ if (port_handle == service_port_handle) {
+ found_handle = true;
+ break;
}
}
-
- if (!found_handle) {
- APPL_TRACE_ERROR(
- "bta_ag_mgmt_cback: PORT_SUCCESS, ignoring handle = %d",
- port_handle);
- return;
- }
-
- event = BTA_AG_RFC_OPEN_EVT;
}
+ if (!found_handle) {
+ LOG(ERROR) << __func__ << ": port opened successfully, but port_handle "
+ << port_handle << " is unknown"
+ << ", scb_handle=" << handle;
+ return;
+ }
+ event = BTA_AG_RFC_OPEN_EVT;
+ } else if (port_handle == p_scb->conn_handle) {
/* distinguish server close events */
- else if (port_handle == p_scb->conn_handle) {
- event = BTA_AG_RFC_CLOSE_EVT;
- } else {
- event = BTA_AG_RFC_SRV_CLOSE_EVT;
- }
-
- tBTA_AG_RFC* p_buf = (tBTA_AG_RFC*)osi_malloc(sizeof(tBTA_AG_RFC));
- p_buf->hdr.event = event;
- p_buf->hdr.layer_specific = handle;
- p_buf->port_handle = port_handle;
- bta_sys_sendmsg(p_buf);
+ event = BTA_AG_RFC_CLOSE_EVT;
+ } else {
+ event = BTA_AG_RFC_SRV_CLOSE_EVT;
}
+
+ tBTA_AG_DATA data = {};
+ data.rfc.port_handle = port_handle;
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle, event, data));
}
/*******************************************************************************
*
- * Function bta_ag_data_cback
- *
- * Description RFCOMM data callback
- *
- *
- * Returns void
- *
- ******************************************************************************/
-static int bta_ag_data_cback(UNUSED_ATTR uint16_t port_handle, void* p_data,
- uint16_t len, uint16_t handle) {
- /* call data call-out directly */
- bta_ag_co_tx_write(handle, (uint8_t*)p_data, len);
- return 0;
-}
-
-/*******************************************************************************
- *
- * Function bta_ag_port_cback_1 to 3
- * bta_ag_mgmt_cback_1 to 3
+ * Function bta_ag_port_cback_1 to 6
+ * bta_ag_mgmt_cback_1 to 6
*
* Description RFCOMM callback functions. This is an easy way to
* distinguish scb from the callback.
@@ -188,44 +170,41 @@
* Returns void
*
******************************************************************************/
-void bta_ag_mgmt_cback_1(uint32_t code, uint16_t handle) {
- bta_ag_mgmt_cback(code, handle, 1);
+void bta_ag_mgmt_cback_1(uint32_t code, uint16_t port_handle) {
+ bta_ag_mgmt_cback(code, port_handle, 1);
}
-void bta_ag_mgmt_cback_2(uint32_t code, uint16_t handle) {
- bta_ag_mgmt_cback(code, handle, 2);
+void bta_ag_mgmt_cback_2(uint32_t code, uint16_t port_handle) {
+ bta_ag_mgmt_cback(code, port_handle, 2);
}
-void bta_ag_mgmt_cback_3(uint32_t code, uint16_t handle) {
- bta_ag_mgmt_cback(code, handle, 3);
+void bta_ag_mgmt_cback_3(uint32_t code, uint16_t port_handle) {
+ bta_ag_mgmt_cback(code, port_handle, 3);
}
-void bta_ag_port_cback_1(uint32_t code, uint16_t handle) {
- bta_ag_port_cback(code, handle, 1);
+void bta_ag_mgmt_cback_4(uint32_t code, uint16_t port_handle) {
+ bta_ag_mgmt_cback(code, port_handle, 4);
}
-void bta_ag_port_cback_2(uint32_t code, uint16_t handle) {
- bta_ag_port_cback(code, handle, 2);
+void bta_ag_mgmt_cback_5(uint32_t code, uint16_t port_handle) {
+ bta_ag_mgmt_cback(code, port_handle, 5);
}
-void bta_ag_port_cback_3(uint32_t code, uint16_t handle) {
- bta_ag_port_cback(code, handle, 3);
+void bta_ag_mgmt_cback_6(uint32_t code, uint16_t port_handle) {
+ bta_ag_mgmt_cback(code, port_handle, 6);
}
-
-/*******************************************************************************
- *
- * Function bta_ag_data_cback_1 to 3
- *
- * Description RFCOMM data callback functions. This is an easy way to
- * distinguish scb from the callback.
- *
- *
- * Returns void
- *
- ******************************************************************************/
-int bta_ag_data_cback_1(uint16_t port_handle, void* p_data, uint16_t len) {
- return bta_ag_data_cback(port_handle, p_data, len, 1);
+void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle) {
+ bta_ag_port_cback(code, port_handle, 1);
}
-int bta_ag_data_cback_2(uint16_t port_handle, void* p_data, uint16_t len) {
- return bta_ag_data_cback(port_handle, p_data, len, 2);
+void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle) {
+ bta_ag_port_cback(code, port_handle, 2);
}
-int bta_ag_data_cback_3(uint16_t port_handle, void* p_data, uint16_t len) {
- return bta_ag_data_cback(port_handle, p_data, len, 3);
+void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle) {
+ bta_ag_port_cback(code, port_handle, 3);
+}
+void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle) {
+ bta_ag_port_cback(code, port_handle, 4);
+}
+void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle) {
+ bta_ag_port_cback(code, port_handle, 5);
+}
+void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle) {
+ bta_ag_port_cback(code, port_handle, 6);
}
/*******************************************************************************
@@ -239,15 +218,17 @@
*
******************************************************************************/
void bta_ag_setup_port(tBTA_AG_SCB* p_scb, uint16_t handle) {
- uint16_t i = bta_ag_scb_to_idx(p_scb) - 1;
-
- /* set up data callback if using pass through mode */
- if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH) {
- PORT_SetDataCallback(handle, bta_ag_data_cback_tbl[i]);
- }
-
+ int port_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
+ CHECK_GE(port_callback_index, 0)
+ << "invalid callback index, handle=" << handle << ", bd_addr"
+ << p_scb->peer_addr;
+ CHECK_LT(port_callback_index,
+ static_cast<int>(sizeof(bta_ag_port_cback_tbl) /
+ sizeof(bta_ag_port_cback_tbl[0])))
+ << "callback index out of bound, handle=" << handle << ", bd_addr"
+ << p_scb->peer_addr;
PORT_SetEventMask(handle, BTA_AG_PORT_EV_MASK);
- PORT_SetEventCallback(handle, bta_ag_port_cback_tbl[i]);
+ PORT_SetEventCallback(handle, bta_ag_port_cback_tbl[port_callback_index]);
}
/*******************************************************************************
@@ -261,30 +242,36 @@
*
******************************************************************************/
void bta_ag_start_servers(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK services) {
- int i;
- int bta_ag_port_status;
-
services >>= BTA_HSP_SERVICE_ID;
- for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
+ for (int i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
/* if service is set in mask */
if (services & 1) {
BTM_SetSecurityLevel(false, "", bta_ag_sec_id[i], p_scb->serv_sec_mask,
BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM,
bta_ag_cb.profile[i].scn);
-
- bta_ag_port_status = RFCOMM_CreateConnection(
+ int management_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
+ CHECK_GE(management_callback_index, 0)
+ << "invalid callback index, services=" << loghex(services)
+ << ", bd_addr=" << p_scb->peer_addr;
+ CHECK_LT(management_callback_index,
+ static_cast<int>(sizeof(bta_ag_mgmt_cback_tbl) /
+ sizeof(bta_ag_mgmt_cback_tbl[0])))
+ << "callback index out of bound, services=" << loghex(services)
+ << ", bd_addr" << p_scb->peer_addr;
+ int status = RFCOMM_CreateConnection(
bta_ag_uuid[i], bta_ag_cb.profile[i].scn, true, BTA_AG_MTU,
RawAddress::kAny, &(p_scb->serv_handle[i]),
- bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
-
- if (bta_ag_port_status == PORT_SUCCESS) {
+ bta_ag_mgmt_cback_tbl[management_callback_index]);
+ if (status == PORT_SUCCESS) {
bta_ag_setup_port(p_scb, p_scb->serv_handle[i]);
} else {
/* TODO: CR#137125 to handle to error properly */
- APPL_TRACE_DEBUG(
- "bta_ag_start_servers: RFCOMM_CreateConnection returned error:%d",
- bta_ag_port_status);
+ LOG(ERROR) << __func__ << ": RFCOMM_CreateConnection ERROR " << status
+ << ", p_scb=" << p_scb << ", services=" << loghex(services)
+ << ", mgmt_cback_index=" << management_callback_index;
}
+ APPL_TRACE_DEBUG("%s: p_scb=0x%08x, services=0x%04x, mgmt_cback_index=%d",
+ __func__, p_scb, services, management_callback_index);
}
}
}
@@ -300,10 +287,8 @@
*
******************************************************************************/
void bta_ag_close_servers(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK services) {
- int i;
-
services >>= BTA_HSP_SERVICE_ID;
- for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
+ for (int i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
/* if service is set in mask */
if (services & 1) {
RFCOMM_RemoveServer(p_scb->serv_handle[i]);
@@ -343,23 +328,27 @@
* Returns void
*
******************************************************************************/
-void bta_ag_rfc_do_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_rfc_do_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
BTM_SetSecurityLevel(true, "", bta_ag_sec_id[p_scb->conn_service],
p_scb->cli_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM,
p_scb->peer_scn);
- if (RFCOMM_CreateConnection(
- bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn, false, BTA_AG_MTU,
- p_scb->peer_addr, &(p_scb->conn_handle),
- bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]) ==
- PORT_SUCCESS) {
+ int management_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
+ int status = RFCOMM_CreateConnection(
+ bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn, false, BTA_AG_MTU,
+ p_scb->peer_addr, &(p_scb->conn_handle),
+ bta_ag_mgmt_cback_tbl[management_callback_index]);
+ APPL_TRACE_DEBUG(
+ "%s: p_scb=0x%08x, conn_handle=%d, mgmt_cback_index=%d,"
+ " status=%d",
+ __func__, p_scb, p_scb->conn_handle, management_callback_index, status);
+ if (status == PORT_SUCCESS) {
bta_ag_setup_port(p_scb, p_scb->conn_handle);
- APPL_TRACE_DEBUG("bta_ag_rfc_do_open : conn_handle = %d",
- p_scb->conn_handle);
- }
- /* RFCOMM create connection failed; send ourselves RFCOMM close event */
- else {
- bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, p_data);
+ } else {
+ /* RFCOMM create connection failed; send ourselves RFCOMM close event */
+ LOG(ERROR) << __func__ << ": RFCOMM_CreateConnection ERROR " << status
+ << " for " << p_scb->peer_addr;
+ bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, data);
}
}
@@ -373,17 +362,18 @@
* Returns void
*
******************************************************************************/
-void bta_ag_rfc_do_close(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
+void bta_ag_rfc_do_close(tBTA_AG_SCB* p_scb,
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
if (p_scb->conn_handle) {
RFCOMM_RemoveConnection(p_scb->conn_handle);
} else {
/* Close API was called while AG is in Opening state. */
/* Need to trigger the state machine to send callback to the app */
/* and move back to INIT state. */
- tBTA_AG_RFC* p_buf = (tBTA_AG_RFC*)osi_malloc(sizeof(tBTA_AG_RFC));
- p_buf->hdr.event = BTA_AG_RFC_CLOSE_EVT;
- p_buf->hdr.layer_specific = bta_ag_scb_to_idx(p_scb);
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(
+ FROM_HERE,
+ base::Bind(&bta_ag_sm_execute_by_handle, bta_ag_scb_to_idx(p_scb),
+ BTA_AG_RFC_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
/* Cancel SDP if it had been started. */
/*
diff --git a/bta/ag/bta_ag_sco.cc b/bta/ag/bta_ag_sco.cc
index f118988..083108b 100644
--- a/bta/ag/bta_ag_sco.cc
+++ b/bta/ag/bta_ag_sco.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,41 +22,25 @@
*
******************************************************************************/
-#include <stddef.h>
+#include <cstddef>
#include "bt_common.h"
#include "bta_ag_api.h"
-#include "bta_ag_co.h"
#include "bta_ag_int.h"
#include "bta_api.h"
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
-#include "bta_dm_co.h"
-#endif
#include "btm_api.h"
#include "device/include/controller.h"
#include "device/include/esco_parameters.h"
#include "osi/include/osi.h"
#include "utl.h"
-#ifndef BTA_AG_SCO_DEBUG
-#define BTA_AG_SCO_DEBUG FALSE
-#endif
-
/* Codec negotiation timeout */
#ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS
#define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (3 * 1000) /* 3 seconds */
#endif
-#if (BTA_AG_SCO_DEBUG == TRUE)
-static char* bta_ag_sco_evt_str(uint8_t event);
-static char* bta_ag_sco_state_str(uint8_t state);
-#endif
-
static bool sco_allowed = true;
-
-#define BTA_AG_NO_EDR_ESCO \
- (ESCO_PKT_TYPES_MASK_NO_2_EV3 | ESCO_PKT_TYPES_MASK_NO_3_EV3 | \
- ESCO_PKT_TYPES_MASK_NO_2_EV5 | ESCO_PKT_TYPES_MASK_NO_3_EV5)
+static RawAddress active_device_addr = {};
/* sco events */
enum {
@@ -69,9 +53,57 @@
BTA_AG_SCO_SHUTDOWN_E, /* shutdown request */
BTA_AG_SCO_CONN_OPEN_E, /* sco open */
BTA_AG_SCO_CONN_CLOSE_E, /* sco closed */
- BTA_AG_SCO_CI_DATA_E /* SCO data ready */
};
+#define CASE_RETURN_STR(const) \
+ case const: \
+ return #const;
+
+static const char* bta_ag_sco_evt_str(uint8_t event) {
+ switch (event) {
+ CASE_RETURN_STR(BTA_AG_SCO_LISTEN_E)
+ CASE_RETURN_STR(BTA_AG_SCO_OPEN_E)
+ CASE_RETURN_STR(BTA_AG_SCO_XFER_E)
+ CASE_RETURN_STR(BTA_AG_SCO_CN_DONE_E)
+ CASE_RETURN_STR(BTA_AG_SCO_REOPEN_E)
+ CASE_RETURN_STR(BTA_AG_SCO_CLOSE_E)
+ CASE_RETURN_STR(BTA_AG_SCO_SHUTDOWN_E)
+ CASE_RETURN_STR(BTA_AG_SCO_CONN_OPEN_E)
+ CASE_RETURN_STR(BTA_AG_SCO_CONN_CLOSE_E)
+ default:
+ return "Unknown SCO Event";
+ }
+}
+
+static const char* bta_ag_sco_state_str(uint8_t state) {
+ switch (state) {
+ CASE_RETURN_STR(BTA_AG_SCO_SHUTDOWN_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_LISTEN_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_CODEC_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_OPENING_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_OPEN_CL_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_OPEN_XFER_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_OPEN_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_CLOSING_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_CLOSE_OP_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_CLOSE_XFER_ST)
+ CASE_RETURN_STR(BTA_AG_SCO_SHUTTING_ST)
+ default:
+ return "Unknown SCO State";
+ }
+}
+
+/**
+ * Check if bd_addr is the current active device.
+ *
+ * @param bd_addr target device address
+ * @return True if bd_addr is the current active device, False otherwise or if
+ * no active device is set (i.e. active_device_addr is empty)
+ */
+bool bta_ag_sco_is_active_device(const RawAddress& bd_addr) {
+ return !active_device_addr.IsEmpty() && active_device_addr == bd_addr;
+}
+
static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local);
/*******************************************************************************
@@ -89,7 +121,7 @@
tBTA_AG_SCB* p_scb;
/* match callback to scb; first check current sco scb */
- if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use) {
+ if (bta_ag_cb.sco.p_curr_scb != nullptr && bta_ag_cb.sco.p_curr_scb->in_use) {
handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
}
/* then check for scb connected to this peer */
@@ -101,13 +133,12 @@
}
if (handle != 0) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
- p_buf->event = BTA_AG_SCO_OPEN_EVT;
- p_buf->layer_specific = handle;
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&bta_ag_sm_execute_by_handle, handle,
+ BTA_AG_SCO_OPEN_EVT, tBTA_AG_DATA::kEmpty));
} else {
/* no match found; disconnect sco, init sco variables */
- bta_ag_cb.sco.p_curr_scb = NULL;
+ bta_ag_cb.sco.p_curr_scb = nullptr;
bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
BTM_RemoveSco(sco_idx);
}
@@ -143,7 +174,7 @@
bta_ag_cb.scb[1].state);
/* match callback to scb */
- if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use) {
+ if (bta_ag_cb.sco.p_curr_scb != nullptr && bta_ag_cb.sco.p_curr_scb->in_use) {
/* We only care about callbacks for the active SCO */
if (bta_ag_cb.sco.p_curr_scb->sco_idx != sco_idx) {
if (bta_ag_cb.sco.p_curr_scb->sco_idx != 0xFFFF) return;
@@ -152,14 +183,6 @@
}
if (handle != 0) {
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
-
- tBTM_STATUS status =
- BTM_ConfigScoPath(ESCO_DATA_PATH_PCM, NULL, NULL, true);
- APPL_TRACE_DEBUG("%s: sco close config status = %d", __func__, status);
- /* SCO clean up here */
- bta_dm_sco_co_close();
-#endif
/* Restore settings */
if (bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC) {
@@ -193,43 +216,22 @@
bta_ag_cb.sco.p_curr_scb->inuse_codec = BTA_AG_CODEC_NONE;
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
- p_buf->event = BTA_AG_SCO_CLOSE_EVT;
- p_buf->layer_specific = handle;
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&bta_ag_sm_execute_by_handle, handle,
+ BTA_AG_SCO_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
} else {
/* no match found */
APPL_TRACE_DEBUG("no scb for ag_sco_disc_cback");
/* sco could be closed after scb dealloc'ed */
- if (bta_ag_cb.sco.p_curr_scb != NULL) {
+ if (bta_ag_cb.sco.p_curr_scb != nullptr) {
bta_ag_cb.sco.p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
- bta_ag_cb.sco.p_curr_scb = NULL;
+ bta_ag_cb.sco.p_curr_scb = nullptr;
bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
}
}
}
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
-/*******************************************************************************
- *
- * Function bta_ag_sco_read_cback
- *
- * Description Callback function is the callback function for incoming
- * SCO data over HCI.
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_ag_sco_read_cback(uint16_t sco_inx, BT_HDR* p_data,
- tBTM_SCO_DATA_FLAG status) {
- if (status != BTM_SCO_DATA_CORRECT) {
- APPL_TRACE_DEBUG("%s: status %d", __func__, status);
- }
- /* Callout function must free the data. */
- bta_dm_sco_co_in_data(p_data, status);
-}
-#endif
/*******************************************************************************
*
* Function bta_ag_remove_sco
@@ -272,14 +274,13 @@
******************************************************************************/
static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event,
tBTM_ESCO_EVT_DATA* p_data) {
- tBTA_AG_SCB* p_scb;
- uint16_t handle;
- uint16_t sco_inx = p_data->conn_evt.sco_inx;
-
/* Only process connection requests */
if (event == BTM_ESCO_CONN_REQ_EVT) {
- if ((handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_inx))) != 0 &&
- ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) && p_scb->svc_conn) {
+ uint16_t sco_inx = p_data->conn_evt.sco_inx;
+ const RawAddress* remote_bda = BTM_ReadScoBdAddr(sco_inx);
+ tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(bta_ag_idx_by_bdaddr(remote_bda));
+ if (remote_bda && bta_ag_sco_is_active_device(*remote_bda) && p_scb &&
+ p_scb->svc_conn) {
p_scb->sco_idx = sco_inx;
/* If no other SCO active, allow this one */
@@ -302,18 +303,20 @@
APPL_TRACE_ERROR(
"%s: Nothing to remove,so accept Conn Request(sco_inx 0x%04x)",
__func__, sco_inx);
- bta_ag_cb.sco.p_xfer_scb = NULL;
+ bta_ag_cb.sco.p_xfer_scb = nullptr;
bta_ag_cb.sco.state = BTA_AG_SCO_LISTEN_ST;
bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
}
}
} else {
- /* If error occurred send reject response immediately */
- APPL_TRACE_WARNING(
- "no scb for bta_ag_esco_connreq_cback or no resources");
+ LOG(WARNING) << __func__
+ << ": reject incoming SCO connection, remote_bda="
+ << (remote_bda ? *remote_bda : RawAddress::kEmpty)
+ << ", active_bda=" << active_device_addr << ", current_bda="
+ << (p_scb ? p_scb->peer_addr : RawAddress::kEmpty);
BTM_EScoConnRsp(p_data->conn_evt.sco_inx, HCI_ERR_HOST_REJECT_RESOURCES,
- (enh_esco_params_t*)NULL);
+ (enh_esco_params_t*)nullptr);
}
} else if (event == BTM_ESCO_CHG_EVT) {
/* Received a change in the esco link */
@@ -337,11 +340,9 @@
*
******************************************************************************/
static void bta_ag_cback_sco(tBTA_AG_SCB* p_scb, uint8_t event) {
- tBTA_AG_HDR sco;
-
+ tBTA_AG_HDR sco = {};
sco.handle = bta_ag_scb_to_idx(p_scb);
sco.app_id = p_scb->app_id;
-
/* call close cback */
(*bta_ag_cb.p_cback)(event, (tBTA_AG*)&sco);
}
@@ -360,15 +361,21 @@
static void bta_ag_create_sco(tBTA_AG_SCB* p_scb, bool is_orig) {
APPL_TRACE_DEBUG(
"%s: BEFORE codec_updated=%d, codec_fallback=%d, "
- "sco_codec=%d, peer_codec=%d, msbc_settings=%d",
+ "sco_codec=%d, peer_codec=%d, msbc_settings=%d, device=%s",
__func__, p_scb->codec_updated, p_scb->codec_fallback, p_scb->sco_codec,
- p_scb->peer_codecs, p_scb->codec_msbc_settings);
+ p_scb->peer_codecs, p_scb->codec_msbc_settings,
+ p_scb->peer_addr.ToString().c_str());
tBTA_AG_PEER_CODEC esco_codec = BTA_AG_CODEC_CVSD;
+ if (!bta_ag_sco_is_active_device(p_scb->peer_addr)) {
+ LOG(WARNING) << __func__ << ": device " << p_scb->peer_addr
+ << " is not active, active_device=" << active_device_addr;
+ return;
+ }
/* Make sure this SCO handle is not already in use */
if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) {
- APPL_TRACE_ERROR("%s: Index 0x%04x already in use!", __func__,
- p_scb->sco_idx);
+ APPL_TRACE_ERROR("%s: device %s, index 0x%04x already in use!", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->sco_idx);
return;
}
@@ -423,13 +430,16 @@
/* Send pending commands to create SCO connection to peer */
bta_ag_create_pending_sco(p_scb, bta_ag_cb.sco.is_local);
+ APPL_TRACE_API("%s: orig %d, inx 0x%04x, pkt types 0x%04x", __func__,
+ is_orig, p_scb->sco_idx, params.packet_types);
} else {
/* Not initiating, go to listen mode */
tBTM_STATUS status = BTM_CreateSco(
&p_scb->peer_addr, false, params.packet_types, &p_scb->sco_idx,
bta_ag_sco_conn_cback, bta_ag_sco_disc_cback);
- if (status == BTM_CMD_STARTED)
+ if (status == BTM_CMD_STARTED) {
BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback);
+ }
APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
__func__, is_orig, p_scb->sco_idx, status,
@@ -437,9 +447,10 @@
}
APPL_TRACE_DEBUG(
"%s: AFTER codec_updated=%d, codec_fallback=%d, "
- "sco_codec=%d, peer_codec=%d, msbc_settings=%d",
+ "sco_codec=%d, peer_codec=%d, msbc_settings=%d, device=%s",
__func__, p_scb->codec_updated, p_scb->codec_fallback, p_scb->sco_codec,
- p_scb->peer_codecs, p_scb->codec_msbc_settings);
+ p_scb->peer_codecs, p_scb->codec_msbc_settings,
+ p_scb->peer_addr.ToString().c_str());
}
/*******************************************************************************
@@ -456,7 +467,7 @@
******************************************************************************/
static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local) {
tBTA_AG_PEER_CODEC esco_codec = p_scb->inuse_codec;
- enh_esco_params_t params;
+ enh_esco_params_t params = {};
bta_ag_cb.sco.p_curr_scb = p_scb;
bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
@@ -479,26 +490,20 @@
/* Bypass voice settings if enhanced SCO setup command is supported */
if (!(controller_get_interface()
->supports_enhanced_setup_synchronous_connection())) {
- if (esco_codec == BTA_AG_CODEC_MSBC)
+ if (esco_codec == BTA_AG_CODEC_MSBC) {
BTM_WriteVoiceSettings(BTM_VOICE_SETTING_TRANS);
- else
+ } else {
BTM_WriteVoiceSettings(BTM_VOICE_SETTING_CVSD);
+ }
}
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- /* initialize SCO setup, no voice setting for AG, data rate <==> sample
- * rate */
- BTM_ConfigScoPath(params.input_data_path, bta_ag_sco_read_cback, NULL,
- TRUE);
-#endif
-
- tBTM_STATUS status = BTM_CreateSco(
- &p_scb->peer_addr, true, params.packet_types, &p_scb->sco_idx,
- bta_ag_sco_conn_cback, bta_ag_sco_disc_cback);
- if (status == BTM_CMD_STARTED) {
+ if (BTM_CreateSco(&p_scb->peer_addr, true, params.packet_types,
+ &p_scb->sco_idx, bta_ag_sco_conn_cback,
+ bta_ag_sco_disc_cback) == BTM_CMD_STARTED) {
/* Initiating the connection, set the current sco handle */
bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
}
+ APPL_TRACE_DEBUG("%s: initiated SCO connection", __func__);
} else {
/* Local device accepted SCO connection from peer */
params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
@@ -509,6 +514,7 @@
}
BTM_EScoConnRsp(p_scb->sco_idx, HCI_SUCCESS, ¶ms);
+ APPL_TRACE_DEBUG("%s: listening for SCO connection", __func__);
}
}
@@ -547,13 +553,21 @@
APPL_TRACE_DEBUG("%s", __func__);
bta_ag_cb.sco.p_curr_scb = p_scb;
+ // Workaround for misbehaving HFs such as Sony XAV AX100 car kit and Sony
+ // MW600 Headset, which indicate WBS support in SDP, but no codec
+ // negotiation support in BRSF. In this case, using mSBC codec can result
+ // background noise or no audio. Thus, defaulting to CVSD instead.
+ if (!(p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) {
+ p_scb->sco_codec = UUID_CODEC_CVSD;
+ }
+
if ((p_scb->codec_updated || p_scb->codec_fallback) &&
(p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) {
/* Change the power mode to Active until SCO open is completed. */
bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
/* Send +BCS to the peer */
- bta_ag_send_bcs(p_scb, NULL);
+ bta_ag_send_bcs(p_scb);
/* Start timer to handle timeout */
alarm_set_on_mloop(p_scb->codec_negotiation_timer,
@@ -580,42 +594,12 @@
******************************************************************************/
static void bta_ag_sco_event(tBTA_AG_SCB* p_scb, uint8_t event) {
tBTA_AG_SCO_CB* p_sco = &bta_ag_cb.sco;
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- BT_HDR* p_buf;
-#endif
-
-#if (BTA_AG_SCO_DEBUG == TRUE)
- uint8_t in_state = p_sco->state;
-
- if (event != BTA_AG_SCO_CI_DATA_E) {
- APPL_TRACE_EVENT("%s: SCO Index 0x%04x, State %d (%s), Event %d (%s)",
- __func__, p_scb->sco_idx, p_sco->state,
- bta_ag_sco_state_str(p_sco->state), event,
- bta_ag_sco_evt_str(event));
- }
-#else
- if (event != BTA_AG_SCO_CI_DATA_E) {
- APPL_TRACE_EVENT("%s: SCO Index 0x%04x, State %d, Event %d", __func__,
- p_scb->sco_idx, p_sco->state, event);
- }
-#endif
-
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- if (event == BTA_AG_SCO_CI_DATA_E) {
- while (true) {
- bta_dm_sco_co_out_data(&p_buf);
- if (p_buf) {
- if (p_sco->state == BTA_AG_SCO_OPEN_ST)
- BTM_WriteScoData(p_sco->p_curr_scb->sco_idx, p_buf);
- else
- osi_free(p_buf);
- } else
- break;
- }
-
- return;
- }
-#endif
+ uint8_t previous_state = p_sco->state;
+ APPL_TRACE_EVENT("%s: index=0x%04x, device=%s, state=%s[%d], event=%s[%d]",
+ __func__, p_scb->sco_idx,
+ p_scb->peer_addr.ToString().c_str(),
+ bta_ag_sco_state_str(p_sco->state), p_sco->state,
+ bta_ag_sco_evt_str(event), event);
switch (p_sco->state) {
case BTA_AG_SCO_SHUTDOWN_ST:
@@ -627,8 +611,9 @@
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING(
+ "%s: BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %s[%d]", __func__,
+ bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -653,7 +638,7 @@
/* remove listening connection */
bta_ag_remove_sco(p_scb, false);
- if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = NULL;
+ if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = nullptr;
/* If last SCO instance then finish shutting down */
if (!bta_ag_other_scb_open(p_scb)) {
@@ -665,8 +650,8 @@
/* remove listening connection */
/* Ignore the event. Keep listening SCO for the active SLC
*/
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %s[%d]",
+ __func__, bta_ag_sco_evt_str(event), event);
break;
case BTA_AG_SCO_CONN_CLOSE_E:
@@ -676,8 +661,8 @@
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %s[%d]",
+ __func__, bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -705,7 +690,7 @@
/* remove listening connection */
bta_ag_remove_sco(p_scb, false);
- if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = NULL;
+ if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = nullptr;
/* If last SCO instance then finish shutting down */
if (!bta_ag_other_scb_open(p_scb)) {
@@ -725,8 +710,8 @@
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_CODEC_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING("%s: BTA_AG_SCO_CODEC_ST: Ignoring event %s[%d]",
+ __func__, bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -778,8 +763,8 @@
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPENING_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPENING_ST: Ignoring event %s[%d]",
+ __func__, bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -821,8 +806,8 @@
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_CL_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_CL_ST: Ignoring event %s[%d]",
+ __func__, bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -853,12 +838,13 @@
p_sco->state = BTA_AG_SCO_OPENING_ST;
p_sco->p_curr_scb = p_sco->p_xfer_scb;
p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx;
- p_sco->p_xfer_scb = NULL;
+ p_sco->p_xfer_scb = nullptr;
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING(
+ "%s: BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %s[%d]", __func__,
+ bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -907,8 +893,8 @@
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_ST: Ignoring event %s[%d]",
+ __func__, bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -951,8 +937,8 @@
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSING_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSING_ST: Ignoring event %s[%d]",
+ __func__, bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -981,8 +967,9 @@
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING(
+ "%s: BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %s[%d]", __func__,
+ bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -997,14 +984,14 @@
case BTA_AG_SCO_CLOSE_E:
/* clear xfer scb */
- p_sco->p_xfer_scb = NULL;
+ p_sco->p_xfer_scb = nullptr;
p_sco->state = BTA_AG_SCO_CLOSING_ST;
break;
case BTA_AG_SCO_SHUTDOWN_E:
/* clear xfer scb */
- p_sco->p_xfer_scb = NULL;
+ p_sco->p_xfer_scb = nullptr;
p_sco->state = BTA_AG_SCO_SHUTTING_ST;
break;
@@ -1019,14 +1006,15 @@
/* start codec negotiation */
p_sco->state = BTA_AG_SCO_CODEC_ST;
tBTA_AG_SCB* p_cn_scb = p_sco->p_xfer_scb;
- p_sco->p_xfer_scb = NULL;
+ p_sco->p_xfer_scb = nullptr;
bta_ag_codec_negotiate(p_cn_scb);
break;
}
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING(
+ "%s: BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %s[%d]", __func__,
+ bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -1056,7 +1044,7 @@
if (p_scb == p_sco->p_curr_scb) {
p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
- p_sco->p_curr_scb = NULL;
+ p_sco->p_curr_scb = nullptr;
}
break;
@@ -1077,13 +1065,14 @@
if (p_scb == p_sco->p_curr_scb) {
p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
- p_sco->p_curr_scb = NULL;
+ p_sco->p_curr_scb = nullptr;
}
break;
default:
- APPL_TRACE_WARNING("%s: BTA_AG_SCO_SHUTTING_ST: Ignoring event %d",
- __func__, event);
+ APPL_TRACE_WARNING(
+ "%s: BTA_AG_SCO_SHUTTING_ST: Ignoring event %s[%d]", __func__,
+ bta_ag_sco_evt_str(event), event);
break;
}
break;
@@ -1091,14 +1080,14 @@
default:
break;
}
-#if (BTA_AG_SCO_DEBUG == TRUE)
- if (p_sco->state != in_state) {
- APPL_TRACE_EVENT("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
- bta_ag_sco_state_str(in_state),
- bta_ag_sco_state_str(p_sco->state),
- bta_ag_sco_evt_str(event));
+ if (p_sco->state != previous_state) {
+ APPL_TRACE_EVENT(
+ "%s: SCO_state_change: [%s(0x%02x)]->[%s(0x%02x)] "
+ "after event [%s(0x%02x)]",
+ __func__, bta_ag_sco_state_str(previous_state), previous_state,
+ bta_ag_sco_state_str(p_sco->state), p_sco->state,
+ bta_ag_sco_evt_str(event), event);
}
-#endif
}
/*******************************************************************************
@@ -1142,7 +1131,9 @@
* Returns void
*
******************************************************************************/
-void bta_ag_sco_listen(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
+void bta_ag_sco_listen(tBTA_AG_SCB* p_scb,
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
+ LOG(INFO) << __func__ << ": " << p_scb->peer_addr;
bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
}
@@ -1156,24 +1147,21 @@
* Returns void
*
******************************************************************************/
-void bta_ag_sco_open(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
- uint8_t event;
-
+void bta_ag_sco_open(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
if (!sco_allowed) {
- APPL_TRACE_DEBUG("%s not opening sco, by policy", __func__);
+ LOG(INFO) << __func__ << ": not opening sco, by policy";
return;
}
-
/* if another scb using sco, this is a transfer */
- if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb) {
- event = BTA_AG_SCO_XFER_E;
+ if (bta_ag_cb.sco.p_curr_scb && bta_ag_cb.sco.p_curr_scb != p_scb) {
+ LOG(INFO) << __func__ << ": tranfer " << bta_ag_cb.sco.p_curr_scb->peer_addr
+ << " -> " << p_scb->peer_addr;
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_XFER_E);
+ } else {
+ /* else it is an open */
+ LOG(INFO) << __func__ << ": open " << p_scb->peer_addr;
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_OPEN_E);
}
- /* else it is an open */
- else {
- event = BTA_AG_SCO_OPEN_E;
- }
-
- bta_ag_sco_event(p_scb, event);
}
/*******************************************************************************
@@ -1186,13 +1174,13 @@
* Returns void
*
******************************************************************************/
-void bta_ag_sco_close(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
-/* if scb is in use */
+void bta_ag_sco_close(tBTA_AG_SCB* p_scb,
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
+ /* if scb is in use */
/* sco_idx is not allocated in SCO_CODEC_ST, still need to move to listen
* state. */
if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) ||
- (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST))
- {
+ (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST)) {
APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
}
@@ -1209,15 +1197,16 @@
*
******************************************************************************/
void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result) {
- if (result == true) {
+ if (result) {
/* Subsequent SCO connection will skip codec negotiation */
- APPL_TRACE_DEBUG("%s: Succeeded for index 0x%04x", __func__,
- p_scb->sco_idx);
+ APPL_TRACE_DEBUG("%s: Succeeded for index 0x%04x, device %s", __func__,
+ p_scb->sco_idx, p_scb->peer_addr.ToString().c_str());
p_scb->codec_updated = false;
bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
} else {
/* codec negotiation failed */
- APPL_TRACE_ERROR("%s: Failed for index 0x%04x", __func__, p_scb->sco_idx);
+ APPL_TRACE_ERROR("%s: Failed for index 0x%04x, device %s", __func__,
+ p_scb->sco_idx, p_scb->peer_addr.ToString().c_str());
bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
}
}
@@ -1232,7 +1221,8 @@
* Returns void
*
******************************************************************************/
-void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
+void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb,
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
}
@@ -1247,17 +1237,11 @@
*
******************************************************************************/
void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb,
- UNUSED_ATTR tBTA_AG_DATA* p_data) {
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- /* open SCO codec if SCO is routed through transport */
- bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE,
- BTA_AG_CI_SCO_DATA_EVT);
-#endif
-
/* call app callback */
bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
@@ -1276,9 +1260,9 @@
*
******************************************************************************/
void bta_ag_sco_conn_close(tBTA_AG_SCB* p_scb,
- UNUSED_ATTR tBTA_AG_DATA* p_data) {
+ UNUSED_ATTR const tBTA_AG_DATA& data) {
/* clear current scb */
- bta_ag_cb.sco.p_curr_scb = NULL;
+ bta_ag_cb.sco.p_curr_scb = nullptr;
p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
/* codec_fallback is set when AG is initiator and connection failed for mSBC.
@@ -1333,10 +1317,6 @@
/* tell sys to stop av if any */
bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
/* When HS initiated SCO, it cannot be WBS. */
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- /* Configure the transport being used */
- BTM_ConfigScoPath(resp.input_data_path, bta_ag_sco_read_cback, NULL, TRUE);
-#endif
}
/* If SCO open was initiated from HS, it must be CVSD */
@@ -1345,87 +1325,19 @@
bta_ag_create_pending_sco(p_scb, bta_ag_cb.sco.is_local);
}
-/*******************************************************************************
- *
- * Function bta_ag_ci_sco_data
- *
- * Description Process the SCO data ready callin event
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_ag_ci_sco_data(UNUSED_ATTR tBTA_AG_SCB* p_scb,
- UNUSED_ATTR tBTA_AG_DATA* p_data) {
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E);
-#endif
-}
-
-void bta_ag_set_sco_allowed(tBTA_AG_DATA* p_data) {
- sco_allowed = ((tBTA_AG_API_SET_SCO_ALLOWED*)p_data)->value;
+void bta_ag_set_sco_allowed(bool value) {
+ sco_allowed = value;
APPL_TRACE_DEBUG(sco_allowed ? "sco now allowed" : "sco now not allowed");
}
-/*******************************************************************************
- * Debugging functions
- ******************************************************************************/
+const RawAddress& bta_ag_get_active_device() { return active_device_addr; }
-#if (BTA_AG_SCO_DEBUG == TRUE)
-static char* bta_ag_sco_evt_str(uint8_t event) {
- switch (event) {
- case BTA_AG_SCO_LISTEN_E:
- return "Listen Request";
- case BTA_AG_SCO_OPEN_E:
- return "Open Request";
- case BTA_AG_SCO_XFER_E:
- return "Transfer Request";
- case BTA_AG_SCO_CN_DONE_E:
- return "Codec Negotiation Done";
- case BTA_AG_SCO_REOPEN_E:
- return "Reopen Request";
- case BTA_AG_SCO_CLOSE_E:
- return "Close Request";
- case BTA_AG_SCO_SHUTDOWN_E:
- return "Shutdown Request";
- case BTA_AG_SCO_CONN_OPEN_E:
- return "Opened";
- case BTA_AG_SCO_CONN_CLOSE_E:
- return "Closed";
- case BTA_AG_SCO_CI_DATA_E:
- return "Sco Data";
- default:
- return "Unknown SCO Event";
+void bta_clear_active_device() { active_device_addr = RawAddress::kEmpty; }
+
+void bta_ag_api_set_active_device(const RawAddress& new_active_device) {
+ if (new_active_device.IsEmpty()) {
+ APPL_TRACE_ERROR("%s: empty device", __func__);
+ return;
}
+ active_device_addr = new_active_device;
}
-
-static char* bta_ag_sco_state_str(uint8_t state) {
- switch (state) {
- case BTA_AG_SCO_SHUTDOWN_ST:
- return "Shutdown";
- case BTA_AG_SCO_LISTEN_ST:
- return "Listening";
- case BTA_AG_SCO_CODEC_ST:
- return "Codec Negotiation";
- case BTA_AG_SCO_OPENING_ST:
- return "Opening";
- case BTA_AG_SCO_OPEN_CL_ST:
- return "Open while closing";
- case BTA_AG_SCO_OPEN_XFER_ST:
- return "Opening while Transferring";
- case BTA_AG_SCO_OPEN_ST:
- return "Open";
- case BTA_AG_SCO_CLOSING_ST:
- return "Closing";
- case BTA_AG_SCO_CLOSE_OP_ST:
- return "Close while Opening";
- case BTA_AG_SCO_CLOSE_XFER_ST:
- return "Close while Transferring";
- case BTA_AG_SCO_SHUTTING_ST:
- return "Shutting Down";
- default:
- return "Unknown SCO State";
- }
-}
-
-#endif /* (BTA_AG_SCO_DEBUG) */
diff --git a/bta/ag/bta_ag_sdp.cc b/bta/ag/bta_ag_sdp.cc
index ae3c973..8ff39fd 100644
--- a/bta/ag/bta_ag_sdp.cc
+++ b/bta/ag/bta_ag_sdp.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,18 +23,23 @@
*
******************************************************************************/
-#include <string.h>
+#include <cstring>
+
+#include <base/bind.h>
#include "bt_common.h"
#include "bta_ag_api.h"
#include "bta_ag_int.h"
#include "bta_api.h"
#include "bta_sys.h"
+#include "btif_config.h"
#include "btm_api.h"
#include "osi/include/osi.h"
#include "sdp_api.h"
#include "utl.h"
+using bluetooth::Uuid;
+
/* Number of protocol elements in protocol element list. */
#define BTA_AG_NUM_PROTO_ELEMS 2
@@ -50,11 +55,15 @@
void bta_ag_sdp_cback_1(uint16_t status);
void bta_ag_sdp_cback_2(uint16_t status);
void bta_ag_sdp_cback_3(uint16_t status);
+void bta_ag_sdp_cback_4(uint16_t status);
+void bta_ag_sdp_cback_5(uint16_t status);
+void bta_ag_sdp_cback_6(uint16_t status);
/* SDP callback function table */
typedef tSDP_DISC_CMPL_CB* tBTA_AG_SDP_CBACK;
const tBTA_AG_SDP_CBACK bta_ag_sdp_cback_tbl[] = {
- bta_ag_sdp_cback_1, bta_ag_sdp_cback_2, bta_ag_sdp_cback_3};
+ bta_ag_sdp_cback_1, bta_ag_sdp_cback_2, bta_ag_sdp_cback_3,
+ bta_ag_sdp_cback_4, bta_ag_sdp_cback_5, bta_ag_sdp_cback_6};
/*******************************************************************************
*
@@ -67,32 +76,25 @@
*
******************************************************************************/
static void bta_ag_sdp_cback(uint16_t status, uint8_t idx) {
- uint16_t event;
- tBTA_AG_SCB* p_scb;
-
APPL_TRACE_DEBUG("%s status:0x%x", __func__, status);
-
- p_scb = bta_ag_scb_by_idx(idx);
- if (p_scb != NULL) {
+ tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(idx);
+ if (p_scb) {
+ uint16_t event;
/* set event according to int/acp */
if (p_scb->role == BTA_AG_ACP) {
event = BTA_AG_DISC_ACP_RES_EVT;
} else {
event = BTA_AG_DISC_INT_RES_EVT;
}
-
- tBTA_AG_DISC_RESULT* p_buf =
- (tBTA_AG_DISC_RESULT*)osi_malloc(sizeof(tBTA_AG_DISC_RESULT));
- p_buf->hdr.event = event;
- p_buf->hdr.layer_specific = idx;
- p_buf->status = status;
- bta_sys_sendmsg(p_buf);
+ tBTA_AG_DATA disc_result = {.disc_result.status = status};
+ do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, idx,
+ event, disc_result));
}
}
/*******************************************************************************
*
- * Function bta_ag_sdp_cback_1 to 3
+ * Function bta_ag_sdp_cback_1 to 6
*
* Description SDP callback functions. Since there is no way to
* distinguish scb from the callback we need separate
@@ -105,6 +107,9 @@
void bta_ag_sdp_cback_1(uint16_t status) { bta_ag_sdp_cback(status, 1); }
void bta_ag_sdp_cback_2(uint16_t status) { bta_ag_sdp_cback(status, 2); }
void bta_ag_sdp_cback_3(uint16_t status) { bta_ag_sdp_cback(status, 3); }
+void bta_ag_sdp_cback_4(uint16_t status) { bta_ag_sdp_cback(status, 4); }
+void bta_ag_sdp_cback_5(uint16_t status) { bta_ag_sdp_cback(status, 5); }
+void bta_ag_sdp_cback_6(uint16_t status) { bta_ag_sdp_cback(status, 6); }
/******************************************************************************
*
@@ -119,8 +124,9 @@
* false if function execution failed.
*
*****************************************************************************/
-bool bta_ag_add_record(uint16_t service_uuid, char* p_service_name, uint8_t scn,
- tBTA_AG_FEAT features, uint32_t sdp_handle) {
+bool bta_ag_add_record(uint16_t service_uuid, const char* p_service_name,
+ uint8_t scn, tBTA_AG_FEAT features,
+ uint32_t sdp_handle) {
tSDP_PROTOCOL_ELEM proto_elem_list[BTA_AG_NUM_PROTO_ELEMS];
uint16_t svc_class_id_list[BTA_AG_NUM_SVC_ELEMS];
uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
@@ -133,8 +139,9 @@
APPL_TRACE_DEBUG("%s uuid: %x", __func__, service_uuid);
- memset(proto_elem_list, 0,
- BTA_AG_NUM_PROTO_ELEMS * sizeof(tSDP_PROTOCOL_ELEM));
+ for (auto& proto_element : proto_elem_list) {
+ proto_element = {};
+ }
/* add the protocol element sequence */
proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
@@ -162,7 +169,7 @@
result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);
/* add service name */
- if (p_service_name != NULL && p_service_name[0] != 0) {
+ if (p_service_name != nullptr && p_service_name[0] != 0) {
result &= SDP_AddAttribute(
sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
(uint32_t)(strlen(p_service_name) + 1), (uint8_t*)p_service_name);
@@ -203,7 +210,7 @@
* Returns void
*
******************************************************************************/
-void bta_ag_create_records(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
+void bta_ag_create_records(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
int i;
tBTA_SERVICE_MASK services;
@@ -215,16 +222,13 @@
if (bta_ag_cb.profile[i].sdp_handle == 0) {
bta_ag_cb.profile[i].sdp_handle = SDP_CreateRecord();
bta_ag_cb.profile[i].scn = BTM_AllocateSCN();
- bta_ag_add_record(bta_ag_uuid[i], p_data->api_register.p_name[i],
- bta_ag_cb.profile[i].scn,
- p_data->api_register.features,
+ bta_ag_add_record(bta_ag_uuid[i], data.api_register.p_name[i],
+ bta_ag_cb.profile[i].scn, data.api_register.features,
bta_ag_cb.profile[i].sdp_handle);
bta_sys_add_uuid(bta_ag_uuid[i]);
}
}
}
-
- p_scb->hsp_version = HSP_VERSION_1_2;
}
/*******************************************************************************
@@ -237,7 +241,7 @@
* Returns void
*
******************************************************************************/
-void bta_ag_del_records(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
+void bta_ag_del_records(tBTA_AG_SCB* p_scb) {
tBTA_AG_SCB* p = &bta_ag_cb.scb[0];
tBTA_SERVICE_MASK services;
tBTA_SERVICE_MASK others = 0;
@@ -249,7 +253,7 @@
continue;
}
- if (p->in_use && p->dealloc == false) {
+ if (p->in_use && !p->dealloc) {
others |= p->reg_services;
}
}
@@ -285,7 +289,7 @@
*
******************************************************************************/
bool bta_ag_sdp_find_attr(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) {
- tSDP_DISC_REC* p_rec = NULL;
+ tSDP_DISC_REC* p_rec = nullptr;
tSDP_DISC_ATTR* p_attr;
tSDP_PROTOCOL_ELEM pe;
uint16_t uuid;
@@ -293,25 +297,29 @@
if (service & BTA_HFP_SERVICE_MASK) {
uuid = UUID_SERVCLASS_HF_HANDSFREE;
- p_scb->peer_version = HFP_VERSION_1_1; /* Default version */
+ /* If there is no cached peer version, use default one */
+ if (p_scb->peer_version == HFP_HSP_VERSION_UNKNOWN) {
+ p_scb->peer_version = HFP_VERSION_1_1; /* Default version */
+ }
} else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
uuid = UUID_SERVCLASS_HEADSET_HS;
p_scb->peer_version = HSP_VERSION_1_2; /* Default version */
} else {
- return result;
+ uuid = UUID_SERVCLASS_HEADSET_HS;
+ p_scb->peer_version = HSP_VERSION_1_0;
}
/* loop through all records we found */
while (true) {
/* get next record; if none found, we're done */
p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec);
- if (p_rec == NULL) {
+ if (p_rec == nullptr) {
if (uuid == UUID_SERVCLASS_HEADSET_HS) {
/* Search again in case the peer device uses the old HSP UUID */
uuid = UUID_SERVCLASS_HEADSET;
p_scb->peer_version = HSP_VERSION_1_0;
p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec);
- if (p_rec == NULL) {
+ if (p_rec == nullptr) {
break;
}
} else
@@ -328,26 +336,66 @@
}
/* get profile version (if failure, version parameter is not updated) */
- if (!SDP_FindProfileVersionInRec(p_rec, uuid, &p_scb->peer_version)) {
+ uint16_t peer_version = HFP_HSP_VERSION_UNKNOWN;
+ if (!SDP_FindProfileVersionInRec(p_rec, uuid, &peer_version)) {
APPL_TRACE_WARNING("%s: Get peer_version failed, using default 0x%04x",
__func__, p_scb->peer_version);
+ peer_version = p_scb->peer_version;
}
- /* get features if HFP */
if (service & BTA_HFP_SERVICE_MASK) {
+ /* Update cached peer version if the new one is different */
+ if (peer_version != p_scb->peer_version) {
+ p_scb->peer_version = peer_version;
+ if (btif_config_set_bin(
+ p_scb->peer_addr.ToString(), HFP_VERSION_CONFIG_KEY,
+ (const uint8_t*)&peer_version, sizeof(peer_version))) {
+ btif_config_save();
+ } else {
+ APPL_TRACE_WARNING("%s: Failed to store peer HFP version for %s",
+ __func__, p_scb->peer_addr.ToString().c_str());
+ }
+ }
+ /* get features if HFP */
p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES);
- if (p_attr != NULL) {
+ if (p_attr != nullptr) {
/* Found attribute. Get value. */
/* There might be race condition between SDP and BRSF. */
/* Do not update if we already received BRSF. */
- if (p_scb->peer_features == 0)
- p_scb->peer_features = p_attr->attr_value.v.u16;
+ uint16_t sdp_features = p_attr->attr_value.v.u16;
+ bool sdp_wbs_support = sdp_features & BTA_AG_FEAT_WBS_SUPPORT;
+ if (!p_scb->received_at_bac && sdp_wbs_support) {
+ // Workaround for misbehaving HFs (e.g. some Hyundai car kit) that:
+ // 1. Indicate WBS support in SDP and codec negotiation in BRSF
+ // 2. But do not send required AT+BAC command
+ // Will assume mSBC is enabled and try codec negotiation by default
+ p_scb->codec_updated = true;
+ p_scb->peer_codecs = BTA_AG_CODEC_CVSD & BTA_AG_CODEC_MSBC;
+ p_scb->sco_codec = UUID_CODEC_MSBC;
+ }
+ if (sdp_features != p_scb->peer_sdp_features) {
+ p_scb->peer_sdp_features = sdp_features;
+ if (btif_config_set_bin(
+ p_scb->peer_addr.ToString(), HFP_SDP_FEATURES_CONFIG_KEY,
+ (const uint8_t*)&sdp_features, sizeof(sdp_features))) {
+ btif_config_save();
+ } else {
+ APPL_TRACE_WARNING(
+ "%s: Failed to store peer HFP SDP Features for %s", __func__,
+ p_scb->peer_addr.ToString().c_str());
+ }
+ }
+ if (p_scb->peer_features == 0) {
+ p_scb->peer_features = sdp_features & HFP_SDP_BRSF_FEATURES_MASK;
+ }
}
- } else /* HSP */
- {
+ } else {
+ /* No peer version caching for HSP, use discovered one directly */
+ p_scb->peer_version = peer_version;
+ /* get features if HSP */
p_attr =
SDP_FindAttributeInRec(p_rec, ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL);
- if (p_attr != NULL) {
+ if (p_attr != nullptr) {
/* Remote volume control of HSP */
if (p_attr->attr_value.v.u8)
p_scb->peer_features |= BTA_AG_PEER_FEAT_VOL;
@@ -374,11 +422,10 @@
*
******************************************************************************/
void bta_ag_do_disc(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) {
- tSDP_UUID uuid_list[1];
+ Uuid uuid_list[1];
uint16_t num_uuid = 1;
uint16_t attr_list[4];
uint8_t num_attr;
- bool db_inited = false;
/* HFP initiator; get proto list and features */
if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
@@ -387,7 +434,7 @@
attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
num_attr = 4;
- uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE;
+ uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HF_HANDSFREE);
}
/* HFP acceptor; get features */
else if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_ACP) {
@@ -395,7 +442,7 @@
attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
num_attr = 3;
- uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE;
+ uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HF_HANDSFREE);
}
/* HSP initiator; get proto list */
else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
@@ -409,36 +456,47 @@
// UUID_SERVCLASS_HEADSET (0x1108) to store its service record. However,
// most of such devices are HSP 1.0 devices.
if (p_scb->hsp_version >= HSP_VERSION_1_2) {
- uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HEADSET_HS;
+ uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET_HS);
} else {
- uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HEADSET;
+ uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET);
}
- }
- /* HSP acceptor; no discovery */
- else {
- return;
+ } else {
+ /* HSP acceptor; get features */
+ attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+ attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+ attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
+ attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
+ num_attr = 4;
+
+ if (p_scb->hsp_version >= HSP_VERSION_1_2) {
+ uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET_HS);
+ num_uuid = 2;
+ } else {
+ /* Legacy from HSP v1.0 */
+ uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET);
+ }
}
/* allocate buffer for sdp database */
p_scb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_AG_DISC_BUF_SIZE);
/* set up service discovery database; attr happens to be attr_list len */
- uuid_list[0].len = LEN_UUID_16;
- db_inited = SDP_InitDiscoveryDb(p_scb->p_disc_db, BTA_AG_DISC_BUF_SIZE,
- num_uuid, uuid_list, num_attr, attr_list);
-
- if (db_inited) {
- /*Service discovery not initiated */
- db_inited = SDP_ServiceSearchAttributeRequest(
- p_scb->peer_addr, p_scb->p_disc_db,
- bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
+ if (SDP_InitDiscoveryDb(p_scb->p_disc_db, BTA_AG_DISC_BUF_SIZE, num_uuid,
+ uuid_list, num_attr, attr_list)) {
+ if (SDP_ServiceSearchAttributeRequest(
+ p_scb->peer_addr, p_scb->p_disc_db,
+ bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1])) {
+ return;
+ } else {
+ LOG(ERROR) << __func__ << ": failed to start SDP discovery for "
+ << p_scb->peer_addr;
+ }
+ } else {
+ LOG(ERROR) << __func__ << ": failed to init SDP discovery database for "
+ << p_scb->peer_addr;
}
-
- if (!db_inited) {
- /*free discover db */
- bta_ag_free_db(p_scb, NULL);
- /* sent failed event */
- bta_ag_sm_execute(p_scb, BTA_AG_DISC_FAIL_EVT, NULL);
- }
+ // Failure actions
+ bta_ag_free_db(p_scb, tBTA_AG_DATA::kEmpty);
+ bta_ag_sm_execute(p_scb, BTA_AG_DISC_FAIL_EVT, tBTA_AG_DATA::kEmpty);
}
/*******************************************************************************
@@ -451,6 +509,6 @@
* Returns void
*
******************************************************************************/
-void bta_ag_free_db(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
+void bta_ag_free_db(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
osi_free_and_reset((void**)&p_scb->p_disc_db);
}
diff --git a/bta/ar/bta_ar.cc b/bta/ar/bta_ar.cc
index 3b93e97..bcfa89d 100644
--- a/bta/ar/bta_ar.cc
+++ b/bta/ar/bta_ar.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2012 Broadcom Corporation
+ * Copyright 2008-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,13 +73,14 @@
* Returns void
*
******************************************************************************/
-static void bta_ar_avdt_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
+static void bta_ar_avdt_cback(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index) {
/* route the AVDT registration callback to av or avk */
if (bta_ar_cb.p_av_conn_cback)
- (*bta_ar_cb.p_av_conn_cback)(handle, bd_addr, event, p_data);
+ (*bta_ar_cb.p_av_conn_cback)(handle, bd_addr, event, p_data, scb_index);
if (bta_ar_cb.p_avk_conn_cback)
- (*bta_ar_cb.p_avk_conn_cback)(handle, bd_addr, event, p_data);
+ (*bta_ar_cb.p_avk_conn_cback)(handle, bd_addr, event, p_data, scb_index);
}
/*******************************************************************************
@@ -91,7 +92,7 @@
* Returns void
*
******************************************************************************/
-void bta_ar_reg_avdt(tAVDT_REG* p_reg, tAVDT_CTRL_CBACK* p_cback,
+void bta_ar_reg_avdt(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback,
tBTA_SYS_ID sys_id) {
uint8_t mask = 0;
@@ -153,17 +154,18 @@
* Returns void
*
******************************************************************************/
-void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr) {
+void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr,
+ uint8_t scb_index) {
uint8_t event = BTA_AR_AVDT_CONN_EVT;
tAVDT_CTRL data;
if (sys_id == BTA_ID_AV) {
if (bta_ar_cb.p_avk_conn_cback) {
- (*bta_ar_cb.p_avk_conn_cback)(0, &bd_addr, event, &data);
+ (*bta_ar_cb.p_avk_conn_cback)(0, bd_addr, event, &data, scb_index);
}
} else if (sys_id == BTA_ID_AVK) {
if (bta_ar_cb.p_av_conn_cback) {
- (*bta_ar_cb.p_av_conn_cback)(0, &bd_addr, event, &data);
+ (*bta_ar_cb.p_av_conn_cback)(0, bd_addr, event, &data, scb_index);
}
}
}
diff --git a/bta/ar/bta_ar_int.h b/bta/ar/bta_ar_int.h
index 4661e74..ece8378 100644
--- a/bta/ar/bta_ar_int.h
+++ b/bta/ar/bta_ar_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2012 Broadcom Corporation
+ * Copyright 2008-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/av/bta_av_aact.cc b/bta/av/bta_av_aact.cc
index 12f8b24..297bba4 100644
--- a/bta/av/bta_av_aact.cc
+++ b/bta/av/bta_av_aact.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,27 +24,36 @@
*
******************************************************************************/
+#define LOG_TAG "bt_bta_av"
+
#include "bt_target.h"
#include <base/logging.h>
#include <string.h>
#include <vector>
+#include "a2dp_sbc.h"
#include "avdt_api.h"
+#include "avrcp_service.h"
#include "bt_utils.h"
#include "bta_av_int.h"
#include "btif/include/btif_av_co.h"
+#include "btif/include/btif_config.h"
#include "btif/include/btif_storage.h"
+#include "btm_int.h"
+#include "device/include/controller.h"
#include "device/include/interop.h"
#include "l2c_api.h"
#include "l2cdefs.h"
+#include "osi/include/log.h"
#include "osi/include/osi.h"
#include "osi/include/properties.h"
#include "utl.h"
-
#if (BTA_AR_INCLUDED == TRUE)
#include "bta_ar_api.h"
#endif
+#include "btif/include/btif_av.h"
+#include "btif/include/btif_hf.h"
/*****************************************************************************
* Constants
@@ -70,6 +79,11 @@
/* ACL quota we are letting FW use for A2DP Offload Tx. */
#define BTA_AV_A2DP_OFFLOAD_XMIT_QUOTA 4
+#define MAX_2MBPS_AVDTP_MTU 663
+#define BTIF_A2DP_MAX_BITPOOL_MQ 35
+
+static void bta_av_offload_codec_builder(tBTA_AV_SCB* p_scb,
+ tBT_A2DP_OFFLOAD* p_a2dp_offload);
static void bta_av_st_rc_timer(tBTA_AV_SCB* p_scb,
UNUSED_ATTR tBTA_AV_DATA* p_data);
@@ -84,13 +98,18 @@
};
/* the call out functions for audio stream */
-const tBTA_AV_CO_FUNCTS bta_av_a2dp_cos = {
- bta_av_co_audio_init, bta_av_co_audio_disc_res,
- bta_av_co_audio_getconfig, bta_av_co_audio_setconfig,
- bta_av_co_audio_open, bta_av_co_audio_close,
- bta_av_co_audio_start, bta_av_co_audio_stop,
- bta_av_co_audio_src_data_path, bta_av_co_audio_delay,
- bta_av_co_audio_update_mtu};
+const tBTA_AV_CO_FUNCTS bta_av_a2dp_cos = {bta_av_co_audio_init,
+ bta_av_co_audio_disc_res,
+ bta_av_co_audio_getconfig,
+ bta_av_co_audio_setconfig,
+ bta_av_co_audio_open,
+ bta_av_co_audio_close,
+ bta_av_co_audio_start,
+ bta_av_co_audio_stop,
+ bta_av_co_audio_source_data_path,
+ bta_av_co_audio_delay,
+ bta_av_co_audio_update_mtu,
+ bta_av_co_content_protect_is_active};
/* ssm action functions for audio stream */
const tBTA_AV_SACT bta_av_a2dp_action[] = {
@@ -166,10 +185,8 @@
BTA_AV_STR_WRITE_CFM_EVT, /* AVDT_WRITE_CFM_EVT */
BTA_AV_AVDT_CONNECT_EVT, /* AVDT_CONNECT_IND_EVT */
BTA_AV_AVDT_DISCONNECT_EVT, /* AVDT_DISCONNECT_IND_EVT */
-#if (AVDT_REPORTING == TRUE)
BTA_AV_AVDT_RPT_CONN_EVT, /* AVDT_REPORT_CONN_EVT */
BTA_AV_AVDT_RPT_CONN_EVT, /* AVDT_REPORT_DISCONN_EVT */
-#endif
BTA_AV_AVDT_DELAY_RPT_EVT, /* AVDT_DELAY_REPORT_EVT */
0 /* AVDT_DELAY_REPORT_CFM_EVT */
};
@@ -193,55 +210,12 @@
BTA_AV_STR_WRITE_CFM_EVT, /* AVDT_WRITE_CFM_EVT */
BTA_AV_AVDT_CONNECT_EVT, /* AVDT_CONNECT_IND_EVT */
BTA_AV_AVDT_DISCONNECT_EVT, /* AVDT_DISCONNECT_IND_EVT */
-#if (AVDT_REPORTING == TRUE)
BTA_AV_AVDT_RPT_CONN_EVT, /* AVDT_REPORT_CONN_EVT */
BTA_AV_AVDT_RPT_CONN_EVT, /* AVDT_REPORT_DISCONN_EVT */
-#endif
BTA_AV_AVDT_DELAY_RPT_EVT, /* AVDT_DELAY_REPORT_EVT */
0 /* AVDT_DELAY_REPORT_CFM_EVT */
};
-static void bta_av_stream0_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-static void bta_av_stream1_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#if BTA_AV_NUM_STRS > 2
-static void bta_av_stream2_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#endif
-#if BTA_AV_NUM_STRS > 3
-static void bta_av_stream3_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#endif
-#if BTA_AV_NUM_STRS > 4
-static void bta_av_stream4_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#endif
-#if BTA_AV_NUM_STRS > 5
-static void bta_av_stream5_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#endif
-/* the array of callback functions to receive events from AVDT control channel
- */
-tAVDT_CTRL_CBACK* const bta_av_dt_cback[] = {bta_av_stream0_cback,
- bta_av_stream1_cback
-#if BTA_AV_NUM_STRS > 2
- ,
- bta_av_stream2_cback
-#endif
-#if BTA_AV_NUM_STRS > 3
- ,
- bta_av_stream3_cback
-#endif
-#if BTA_AV_NUM_STRS > 4
- ,
- bta_av_stream4_cback
-#endif
-#if BTA_AV_NUM_STRS > 5
- ,
- bta_av_stream5_cback
-#endif
-};
/***********************************************
*
* Function bta_get_scb_handle
@@ -291,11 +265,14 @@
* Returns void
*
******************************************************************************/
-static void bta_av_save_addr(tBTA_AV_SCB* p_scb, const RawAddress& b) {
- APPL_TRACE_DEBUG("%s: r:%d, s:%d", __func__, p_scb->recfg_sup,
+static void bta_av_save_addr(tBTA_AV_SCB* p_scb, const RawAddress& bd_addr) {
+ APPL_TRACE_DEBUG("%s: peer=%s recfg_sup:%d, suspend_sup:%d", __func__,
+ bd_addr.ToString().c_str(), p_scb->recfg_sup,
p_scb->suspend_sup);
- if (p_scb->peer_addr != b) {
- APPL_TRACE_ERROR("%s: reset flags", __func__);
+ if (p_scb->PeerAddress() != bd_addr) {
+ LOG_INFO(LOG_TAG, "%s: reset flags old_addr=%s new_addr=%s", __func__,
+ p_scb->PeerAddress().ToString().c_str(),
+ bd_addr.ToString().c_str());
/* a new addr, reset the supported flags */
p_scb->recfg_sup = true;
p_scb->suspend_sup = true;
@@ -303,7 +280,7 @@
/* do this copy anyway, just in case the first addr matches
* the control block one by accident */
- p_scb->peer_addr = b;
+ p_scb->OnConnected(bd_addr);
}
/*******************************************************************************
@@ -317,6 +294,9 @@
*
******************************************************************************/
static void notify_start_failed(tBTA_AV_SCB* p_scb) {
+ LOG_ERROR(LOG_TAG, "%s: peer %s role:0x%x channel:%d handle:0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->role, p_scb->chnl,
+ p_scb->hndl);
tBTA_AV_START start;
/* if start failed, clear role */
p_scb->role &= ~BTA_AV_ROLE_START_INT;
@@ -348,7 +328,7 @@
/* for outgoing RC connection as INT/CT */
if ((p_scb->rc_handle == BTA_AV_RC_HANDLE_NONE) &&
/* (bta_av_cb.features & BTA_AV_FEAT_RCCT) && */
- (p_scb->use_rc == true || (p_scb->role & BTA_AV_ROLE_AD_ACP))) {
+ (p_scb->use_rc || (p_scb->role & BTA_AV_ROLE_AD_ACP))) {
if ((p_scb->wait & BTA_AV_WAIT_ROLE_SW_BITS) == 0) {
bta_sys_start_timer(p_scb->avrc_ct_timer, BTA_AV_RC_DISC_TIME_VAL,
BTA_AV_AVRC_TIMER_EVT, p_scb->hndl);
@@ -370,7 +350,6 @@
******************************************************************************/
static bool bta_av_next_getcap(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
int i;
- tAVDT_GETCAP_REQ* p_req;
bool sent_cmd = false;
uint16_t uuid_int = p_scb->uuid_int;
uint8_t sep_requested = 0;
@@ -382,22 +361,16 @@
for (i = p_scb->sep_info_idx; i < p_scb->num_seps; i++) {
/* steam not in use, is a sink, and is the right media type (audio/video) */
- if ((p_scb->sep_info[i].in_use == false) &&
+ if ((!p_scb->sep_info[i].in_use) &&
(p_scb->sep_info[i].tsep == sep_requested) &&
(p_scb->sep_info[i].media_type == p_scb->media_type)) {
p_scb->sep_info_idx = i;
/* we got a stream; get its capabilities */
- if (p_scb->p_cap == NULL)
- p_scb->p_cap = (tAVDT_CFG*)osi_malloc(sizeof(tAVDT_CFG));
- if ((p_scb->avdt_version >= AVDT_VERSION_1_3) &&
- (A2DP_GetAvdtpVersion() >= AVDT_VERSION_1_3)) {
- p_req = AVDT_GetAllCapReq;
- } else {
- p_req = AVDT_GetCapReq;
- }
- (*p_req)(p_scb->peer_addr, p_scb->sep_info[i].seid, p_scb->p_cap,
- bta_av_dt_cback[p_scb->hdi]);
+ bool get_all_cap = (p_scb->AvdtpVersion() >= AVDT_VERSION_1_3) &&
+ (A2DP_GetAvdtpVersion() >= AVDT_VERSION_1_3);
+ AVDT_GetCapReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sep_info[i].seid,
+ &p_scb->peer_cap, &bta_av_proc_stream_evt, get_all_cap);
sent_cmd = true;
break;
}
@@ -406,7 +379,7 @@
/* if no streams available then stream open fails */
if (!sent_cmd) {
APPL_TRACE_ERROR("%s: BTA_AV_STR_GETCAP_FAIL_EVT: peer_addr=%s", __func__,
- p_scb->peer_addr.ToString().c_str());
+ p_scb->PeerAddress().ToString().c_str());
bta_av_ssm_execute(p_scb, BTA_AV_STR_GETCAP_FAIL_EVT, p_data);
}
@@ -422,11 +395,16 @@
* Returns void
*
******************************************************************************/
-static void bta_av_proc_stream_evt(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data,
- int index) {
+void bta_av_proc_stream_evt(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index) {
+ CHECK_LT(scb_index, BTA_AV_NUM_STRS);
+ tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[scb_index];
uint16_t sec_len = 0;
- tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[index];
+
+ APPL_TRACE_EVENT(
+ "%s: peer_address: %s avdt_handle: %d event=0x%x scb_index=%d p_scb=%p",
+ __func__, bd_addr.ToString().c_str(), handle, event, scb_index, p_scb);
if (p_data) {
if (event == AVDT_SECURITY_IND_EVT) {
@@ -447,64 +425,17 @@
/* copy event data, bd addr, and handle to event message buffer */
p_msg->hdr.offset = 0;
- if (bd_addr != NULL) {
- p_msg->bd_addr = *bd_addr;
- VLOG(1) << __func__ << ": bd_addr:" << bd_addr;
- }
+ p_msg->bd_addr = bd_addr;
+ p_msg->scb_index = scb_index;
+ APPL_TRACE_EVENT("%s: stream event bd_addr: %s scb_index: %u", __func__,
+ p_msg->bd_addr.ToString().c_str(), scb_index);
if (p_data != NULL) {
memcpy(&p_msg->msg, p_data, sizeof(tAVDT_CTRL));
/* copy config params to event message buffer */
switch (event) {
- case AVDT_RECONFIG_CFM_EVT:
- if (p_msg->msg.hdr.err_code == 0) {
- APPL_TRACE_DEBUG(
- "%s: reconfig cfm event codec info = 0x%06x-%06x-%06x-%02x",
- __func__,
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[0] << 16) +
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[1] << 8) +
- p_msg->msg.reconfig_cfm.p_cfg->codec_info[2],
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[3] << 16) +
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[4] << 8) +
- p_msg->msg.reconfig_cfm.p_cfg->codec_info[5],
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[6] << 16) +
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[7] << 8) +
- p_msg->msg.reconfig_cfm.p_cfg->codec_info[8],
- p_msg->msg.reconfig_cfm.p_cfg->codec_info[9]);
- }
- break;
-
case AVDT_CONFIG_IND_EVT:
- /* We might have 2 SEP signallings(A2DP + VDP) with one peer device on
- * one L2CAP.
- * If we already have a signalling connection with the bd_addr and the
- * streaming
- * SST is at INIT state, change it to INCOMING state to handle the
- * signalling
- * from the 2nd SEP. */
- if ((bta_av_find_lcb(*bd_addr, BTA_AV_LCB_FIND) != NULL) &&
- (bta_av_is_scb_init(p_scb))) {
- bta_av_set_scb_sst_incoming(p_scb);
-
- /* When ACP_CONNECT_EVT was received, we put first available scb to
- * incoming state.
- * Later when we receive AVDT_CONFIG_IND_EVT, we use a new p_scb and
- * set its state to
- * incoming which we do it above.
- * We also have to set the old p_scb state to init to be used later
- */
- for (int i = 0; i < BTA_AV_NUM_STRS; i++) {
- if ((bta_av_cb.p_scb[i]) && (i != index)) {
- if (bta_av_cb.p_scb[i]->state == BTA_AV_INCOMING_SST) {
- bta_av_cb.p_scb[i]->state = BTA_AV_INIT_SST;
- bta_av_cb.p_scb[i]->coll_mask = 0;
- break;
- }
- }
- }
- }
-
- memcpy(&p_msg->cfg, p_data->config_ind.p_cfg, sizeof(tAVDT_CFG));
+ p_msg->cfg = *p_data->config_ind.p_cfg;
break;
case AVDT_SECURITY_IND_EVT:
@@ -533,8 +464,9 @@
default:
break;
}
- } else
+ } else {
p_msg->msg.hdr.err_code = 0;
+ }
/* look up application event */
if ((p_data == NULL) || (p_data->hdr.err_code == 0)) {
@@ -546,7 +478,7 @@
p_msg->initiator = false;
if (event == AVDT_SUSPEND_CFM_EVT) p_msg->initiator = true;
- APPL_TRACE_VERBOSE("%s: hndl:x%x", __func__, p_scb->hndl);
+ APPL_TRACE_VERBOSE("%s: hndl:0x%x", __func__, p_scb->hndl);
p_msg->hdr.layer_specific = p_scb->hndl;
p_msg->handle = handle;
p_msg->avdt_event = event;
@@ -554,7 +486,7 @@
}
if (p_data) {
- bta_av_conn_cback(handle, bd_addr, event, p_data);
+ bta_av_conn_cback(handle, bd_addr, event, p_data, scb_index);
} else {
APPL_TRACE_ERROR("%s: p_data is null", __func__);
}
@@ -600,104 +532,6 @@
/*******************************************************************************
*
- * Function bta_av_stream0_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_av_stream0_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_VERBOSE("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 0);
-}
-
-/*******************************************************************************
- *
- * Function bta_av_stream1_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_av_stream1_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 1);
-}
-
-#if BTA_AV_NUM_STRS > 2
-/*******************************************************************************
- *
- * Function bta_av_stream2_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_av_stream2_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 2);
-}
-#endif
-
-#if BTA_AV_NUM_STRS > 3
-/*******************************************************************************
- *
- * Function bta_av_stream3_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_av_stream3_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 3);
-}
-#endif
-
-/*******************************************************************************
- *
- * Function bta_av_stream4_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-#if BTA_AV_NUM_STRS > 4
-static void bta_av_stream4_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 4);
-}
-#endif
-
-/*******************************************************************************
- *
- * Function bta_av_stream5_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-#if BTA_AV_NUM_STRS > 5
-static void bta_av_stream5_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 5);
-}
-#endif
-
-/*******************************************************************************
- *
* Function bta_av_a2dp_sdp_cback
*
* Description A2DP service discovery callback.
@@ -705,23 +539,51 @@
* Returns void
*
******************************************************************************/
-static void bta_av_a2dp_sdp_cback(bool found, tA2DP_Service* p_service) {
- tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(bta_av_cb.handle);
+static void bta_av_a2dp_sdp_cback(bool found, tA2DP_Service* p_service,
+ const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer %s : found=%s", __func__,
+ peer_address.ToString().c_str(), (found) ? "true" : "false");
+ tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(bta_av_cb.handle);
if (p_scb == NULL) {
APPL_TRACE_ERROR("%s: no scb found for handle(0x%x)", __func__,
bta_av_cb.handle);
return;
}
+ if (!found) {
+ APPL_TRACE_ERROR("%s: peer %s A2DP service discovery failed", __func__,
+ p_scb->PeerAddress().ToString().c_str());
+ }
+ APPL_TRACE_DEBUG("%s: peer %s found=%s", __func__,
+ p_scb->PeerAddress().ToString().c_str(),
+ (found) ? "true" : "false");
+
tBTA_AV_SDP_RES* p_msg =
(tBTA_AV_SDP_RES*)osi_malloc(sizeof(tBTA_AV_SDP_RES));
- p_msg->hdr.event =
- (found) ? BTA_AV_SDP_DISC_OK_EVT : BTA_AV_SDP_DISC_FAIL_EVT;
- if (found && (p_service != NULL))
- p_scb->avdt_version = p_service->avdt_version;
- else
- p_scb->avdt_version = 0x00;
+ if (found) {
+ p_msg->hdr.event = BTA_AV_SDP_DISC_OK_EVT;
+ } else {
+ p_msg->hdr.event = BTA_AV_SDP_DISC_FAIL_EVT;
+ APPL_TRACE_ERROR("%s: BTA_AV_SDP_DISC_FAIL_EVT: peer_addr=%s", __func__,
+ p_scb->PeerAddress().ToString().c_str());
+ }
+ if (found && (p_service != NULL)) {
+ p_scb->SetAvdtpVersion(p_service->avdt_version);
+ if (p_service->avdt_version != 0) {
+ if (btif_config_set_bin(p_scb->PeerAddress().ToString(),
+ AVDTP_VERSION_CONFIG_KEY,
+ (const uint8_t*)&p_service->avdt_version,
+ sizeof(p_service->avdt_version))) {
+ btif_config_save();
+ } else {
+ APPL_TRACE_WARNING("%s: Failed to store peer AVDTP version for %s",
+ __func__, p_scb->PeerAddress().ToString().c_str());
+ }
+ }
+ } else {
+ p_scb->SetAvdtpVersion(0);
+ }
p_msg->hdr.layer_specific = bta_av_cb.handle;
bta_sys_sendmsg(p_msg);
@@ -767,7 +629,8 @@
tBTA_AV_RS_RES switch_res = BTA_AV_RS_NONE;
tBTA_AV_API_OPEN* p_buf = &p_scb->q_info.open;
- APPL_TRACE_DEBUG("%s: wait:x%x", __func__, p_scb->wait);
+ APPL_TRACE_DEBUG("%s: peer %s wait:0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->wait);
if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_RES_START)
p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RETRY;
@@ -786,6 +649,8 @@
}
} else {
/* report failure on OPEN */
+ APPL_TRACE_ERROR("%s: peer %s role switch failed (wait=0x%x)", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->wait);
switch_res = BTA_AV_RS_FAIL;
}
@@ -813,7 +678,8 @@
void bta_av_role_res(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
bool initiator = false;
- APPL_TRACE_DEBUG("%s: q_tag:%d, wait:x%x, role:x%x", __func__, p_scb->q_tag,
+ APPL_TRACE_DEBUG("%s: peer %s q_tag:%d, wait:0x%x, role:0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->q_tag,
p_scb->wait, p_scb->role);
if (p_scb->role & BTA_AV_ROLE_START_INT) initiator = true;
@@ -822,7 +688,7 @@
p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
if (p_data->role_res.hci_status != HCI_SUCCESS) {
p_scb->role &= ~BTA_AV_ROLE_START_INT;
- bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
/* start failed because of role switch. */
tBTA_AV_START start;
start.chnl = p_scb->chnl;
@@ -845,7 +711,7 @@
if (p_data->role_res.hci_status != HCI_SUCCESS) {
/* Open failed because of role switch. */
tBTA_AV_OPEN av_open;
- av_open.bd_addr = p_scb->peer_addr;
+ av_open.bd_addr = p_scb->PeerAddress();
av_open.chnl = p_scb->chnl;
av_open.hndl = p_scb->hndl;
av_open.status = BTA_AV_FAIL_ROLE;
@@ -864,12 +730,14 @@
}
} else {
APPL_TRACE_WARNING(
- "%s: unexpected role switch event: q_tag = %d wait = %d", __func__,
- p_scb->q_tag, p_scb->wait);
+ "%s: peer %s unexpected role switch event: q_tag = %d wait = 0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->q_tag,
+ p_scb->wait);
}
}
- APPL_TRACE_DEBUG("%s: wait:x%x, role:x%x", __func__, p_scb->wait,
+ APPL_TRACE_DEBUG("%s: peer %s wait:0x%x, role:0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->wait,
p_scb->role);
}
@@ -884,7 +752,11 @@
*
******************************************************************************/
void bta_av_delay_co(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- p_scb->p_cos->delay(p_scb->hndl, p_data->str_msg.msg.delay_rpt_cmd.delay);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d delay:%d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ p_data->str_msg.msg.delay_rpt_cmd.delay);
+ p_scb->p_cos->delay(p_scb->hndl, p_scb->PeerAddress(),
+ p_data->str_msg.msg.delay_rpt_cmd.delay);
}
/*******************************************************************************
@@ -904,7 +776,8 @@
ATTR_ID_BT_PROFILE_DESC_LIST};
uint16_t sdp_uuid = 0; /* UUID for which SDP has to be done */
- APPL_TRACE_DEBUG("%s: use_rc: %d rs:%d, oc:%d", __func__,
+ APPL_TRACE_DEBUG("%s: peer_addr: %s use_rc: %d switch_res:%d, oc:%d",
+ __func__, p_data->api_open.bd_addr.ToString().c_str(),
p_data->api_open.use_rc, p_data->api_open.switch_res,
bta_av_cb.audio_open_cnt);
@@ -928,7 +801,7 @@
/* report a new failure event */
p_scb->open_status = BTA_AV_FAIL_ROLE;
APPL_TRACE_ERROR("%s: BTA_AV_SDP_DISC_FAIL_EVT: peer_addr=%s", __func__,
- p_scb->peer_addr.ToString().c_str());
+ p_scb->PeerAddress().ToString().c_str());
bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_FAIL_EVT, NULL);
break;
@@ -947,7 +820,7 @@
break;
}
- APPL_TRACE_DEBUG("%s: ok_continue: %d wait:x%x, q_tag: %d", __func__,
+ APPL_TRACE_DEBUG("%s: ok_continue: %d wait:0x%x, q_tag: %d", __func__,
ok_continue, p_scb->wait, p_scb->q_tag);
if (!ok_continue) return;
@@ -973,19 +846,7 @@
p_scb->sec_mask = p_data->api_open.sec_mask;
p_scb->use_rc = p_data->api_open.use_rc;
- bta_sys_app_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
-
- if (p_scb->skip_sdp == true) {
- tA2DP_Service a2dp_ser;
- a2dp_ser.avdt_version = AVDT_VERSION;
- p_scb->skip_sdp = false;
- p_scb->uuid_int = p_data->api_open.uuid;
- /* only one A2DP find service is active at a time */
- bta_av_cb.handle = p_scb->hndl;
- APPL_TRACE_WARNING("%s: Skip Sdp for incoming A2dp connection", __func__);
- bta_av_a2dp_sdp_cback(true, &a2dp_ser);
- return;
- }
+ bta_sys_app_open(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
/* only one A2DP find service is active at a time */
bta_av_cb.handle = p_scb->hndl;
@@ -1001,15 +862,21 @@
else if (p_scb->uuid_int == UUID_SERVCLASS_AUDIO_SOURCE)
sdp_uuid = UUID_SERVCLASS_AUDIO_SINK;
- APPL_TRACE_DEBUG("%s: uuid_int 0x%x, Doing SDP For 0x%x", __func__,
- p_scb->uuid_int, sdp_uuid);
- if (A2DP_FindService(sdp_uuid, p_scb->peer_addr, &db_params,
- bta_av_a2dp_sdp_cback) == A2DP_SUCCESS)
- return;
-
- /* when the code reaches here, either the DB is NULL
- * or A2DP_FindService is not successful */
- bta_av_a2dp_sdp_cback(false, NULL);
+ APPL_TRACE_DEBUG(
+ "%s: Initiate SDP discovery for peer %s : uuid_int=0x%x "
+ "sdp_uuid=0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->uuid_int,
+ sdp_uuid);
+ tA2DP_STATUS find_service_status = A2DP_FindService(
+ sdp_uuid, p_scb->PeerAddress(), &db_params, bta_av_a2dp_sdp_cback);
+ if (find_service_status != A2DP_SUCCESS) {
+ APPL_TRACE_ERROR(
+ "%s: A2DP_FindService() failed for peer %s uuid_int=0x%x "
+ "sdp_uuid=0x%x : status=%d",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->uuid_int,
+ sdp_uuid, find_service_status);
+ bta_av_a2dp_sdp_cback(false, nullptr, RawAddress::kEmpty);
+ }
}
/*******************************************************************************
@@ -1025,12 +892,12 @@
tBTA_AV_CONN_CHG msg;
uint8_t role = BTA_AV_ROLE_AD_INT;
- APPL_TRACE_DEBUG("%s", __func__);
+ LOG_INFO(LOG_TAG, "%s peer %s", __func__,
+ p_scb->PeerAddress().ToString().c_str());
/* free any buffers */
- osi_free_and_reset((void**)&p_scb->p_cap);
p_scb->sdp_discovery_started = false;
- p_scb->avdt_version = 0;
+ p_scb->SetAvdtpVersion(0);
/* initialize some control block variables */
p_scb->open_status = BTA_AV_SUCCESS;
@@ -1038,7 +905,8 @@
/* if de-registering shut everything down */
msg.hdr.layer_specific = p_scb->hndl;
p_scb->started = false;
- p_scb->current_codec = nullptr;
+ p_scb->offload_started = false;
+ p_scb->use_rtp_header_marker_bit = false;
p_scb->cong = false;
p_scb->role = role;
p_scb->cur_psc_mask = 0;
@@ -1059,8 +927,7 @@
p_scb->offload_start_pending = false;
- p_scb->skip_sdp = false;
- if (p_scb->deregistring) {
+ if (p_scb->deregistering) {
/* remove stream */
for (int i = 0; i < BTAV_A2DP_CODEC_INDEX_MAX; i++) {
if (p_scb->seps[i].av_handle) AVDT_RemoveStream(p_scb->seps[i].av_handle);
@@ -1071,7 +938,7 @@
} else {
/* report stream closed to main SM */
msg.is_up = false;
- msg.peer_addr = p_scb->peer_addr;
+ msg.peer_addr = p_scb->PeerAddress();
bta_av_conn_chg((tBTA_AV_DATA*)&msg);
}
}
@@ -1101,7 +968,7 @@
void bta_av_config_ind(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
tBTA_AV_CI_SETCONFIG setconfig;
tAVDT_SEP_INFO* p_info;
- tAVDT_CFG* p_evt_cfg = &p_data->str_msg.cfg;
+ const AvdtpSepConfig* p_evt_cfg = &p_data->str_msg.cfg;
uint8_t psc_mask = (p_evt_cfg->psc_mask | p_scb->cfg.psc_mask);
uint8_t
local_sep; /* sep type of local handle on which connection was received */
@@ -1110,8 +977,11 @@
local_sep = bta_av_get_scb_sep_type(p_scb, p_msg->handle);
p_scb->avdt_label = p_data->str_msg.msg.hdr.label;
- APPL_TRACE_DEBUG("%s: local_sep = %d", __func__, local_sep);
- A2DP_DumpCodecInfo(p_evt_cfg->codec_info);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d local_sep:%d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ local_sep);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_evt_cfg->codec_info).c_str());
memcpy(p_scb->cfg.codec_info, p_evt_cfg->codec_info, AVDT_CODEC_SIZE);
bta_av_save_addr(p_scb, p_data->str_msg.bd_addr);
@@ -1155,15 +1025,15 @@
/* in case of A2DP SINK this is the first time peer data is being sent to
* co functions */
if (local_sep == AVDT_TSEP_SNK) {
- p_scb->p_cos->setcfg(p_scb->hndl, p_evt_cfg->codec_info, p_info->seid,
- p_scb->peer_addr, p_evt_cfg->num_protect,
- p_evt_cfg->protect_info, AVDT_TSEP_SNK,
- p_msg->handle);
+ p_scb->p_cos->setcfg(p_scb->hndl, p_scb->PeerAddress(),
+ p_evt_cfg->codec_info, p_info->seid,
+ p_evt_cfg->num_protect, p_evt_cfg->protect_info,
+ AVDT_TSEP_SNK, p_msg->handle);
} else {
- p_scb->p_cos->setcfg(p_scb->hndl, p_evt_cfg->codec_info, p_info->seid,
- p_scb->peer_addr, p_evt_cfg->num_protect,
- p_evt_cfg->protect_info, AVDT_TSEP_SRC,
- p_msg->handle);
+ p_scb->p_cos->setcfg(p_scb->hndl, p_scb->PeerAddress(),
+ p_evt_cfg->codec_info, p_info->seid,
+ p_evt_cfg->num_protect, p_evt_cfg->protect_info,
+ AVDT_TSEP_SRC, p_msg->handle);
}
}
}
@@ -1182,7 +1052,8 @@
tBTA_AV_RCB* p_rcb;
APPL_TRACE_WARNING("%s: conn_lcb: 0x%x peer_addr: %s", __func__,
- bta_av_cb.conn_lcb, p_scb->peer_addr.ToString().c_str());
+ bta_av_cb.conn_lcb,
+ p_scb->PeerAddress().ToString().c_str());
alarm_cancel(bta_av_cb.link_signalling_timer);
alarm_cancel(p_scb->avrc_ct_timer);
@@ -1190,7 +1061,7 @@
if (bta_av_cb.conn_lcb) {
p_rcb = bta_av_get_rcb_by_shdl((uint8_t)(p_scb->hdi + 1));
if (p_rcb) bta_av_del_rc(p_rcb);
- AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DisconnectReq(p_scb->PeerAddress(), &bta_av_proc_stream_evt);
} else {
bta_av_ssm_execute(p_scb, BTA_AV_AVDT_DISCONNECT_EVT, NULL);
}
@@ -1252,14 +1123,15 @@
/* we like this codec_type. find the sep_idx */
local_sep = bta_av_get_scb_sep_type(p_scb, avdt_handle);
bta_av_adjust_seps_idx(p_scb, avdt_handle);
- APPL_TRACE_DEBUG("%s: sep_idx: %d cur_psc_mask:0x%x", __func__,
+ APPL_TRACE_DEBUG("%s: peer %s handle: sep_idx: %d cur_psc_mask:0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(),
p_scb->sep_idx, p_scb->cur_psc_mask);
if ((AVDT_TSEP_SNK == local_sep) &&
(p_data->ci_setconfig.err_code == AVDT_SUCCESS) &&
(p_scb->seps[p_scb->sep_idx].p_app_sink_data_cback != NULL)) {
tBTA_AV_MEDIA av_sink_codec_info;
- av_sink_codec_info.avk_config.bd_addr = p_scb->peer_addr;
+ av_sink_codec_info.avk_config.bd_addr = p_scb->PeerAddress();
av_sink_codec_info.avk_config.codec_info = p_scb->cfg.codec_info;
p_scb->seps[p_scb->sep_idx].p_app_sink_data_cback(BTA_AV_SINK_MEDIA_CFG_EVT,
&av_sink_codec_info);
@@ -1274,14 +1146,14 @@
p_scb->wait = BTA_AV_WAIT_ACP_CAPS_ON;
if (p_data->ci_setconfig.recfg_needed)
p_scb->role |= BTA_AV_ROLE_SUSPEND_OPT;
- APPL_TRACE_DEBUG("%s: recfg_needed:%d role:x%x num:%d", __func__,
+ APPL_TRACE_DEBUG("%s: recfg_needed:%d role:0x%x num:%d", __func__,
p_data->ci_setconfig.recfg_needed, p_scb->role, num);
/* callout module tells BTA the number of "good" SEPs and their SEIDs.
* getcap on these SEID */
p_scb->num_seps = num;
if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT)
- p_scb->avdt_version = AVDT_VERSION_1_3;
+ p_scb->SetAvdtpVersion(AVDT_VERSION_1_3);
if (A2DP_GetCodecType(p_scb->cfg.codec_info) == A2DP_MEDIA_CT_SBC ||
num > 1) {
@@ -1291,7 +1163,7 @@
/* this is called in A2DP SRC path only, In case of SINK we don't need it
*/
if (local_sep == AVDT_TSEP_SRC)
- p_scb->p_cos->disc_res(p_scb->hndl, num, num, 0, p_scb->peer_addr,
+ p_scb->p_cos->disc_res(p_scb->hndl, p_scb->PeerAddress(), num, num, 0,
UUID_SERVCLASS_AUDIO_SOURCE);
} else {
/* we do not know the peer device and it is using non-SBC codec
@@ -1331,11 +1203,13 @@
void bta_av_str_opened(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
tBTA_AV_CONN_CHG msg;
uint8_t* p;
- uint16_t mtu;
+
+ APPL_TRACE_DEBUG("%s: peer %s handle: %d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl);
msg.hdr.layer_specific = p_scb->hndl;
msg.is_up = true;
- msg.peer_addr = p_scb->peer_addr;
+ msg.peer_addr = p_scb->PeerAddress();
p_scb->l2c_cid = AVDT_GetL2CapChannel(p_scb->avdt_handle);
bta_av_conn_chg((tBTA_AV_DATA*)&msg);
/* set the congestion flag, so AV would not send media packets by accident */
@@ -1344,20 +1218,18 @@
p_scb->stream_mtu =
p_data->str_msg.msg.open_ind.peer_mtu - AVDT_MEDIA_HDR_SIZE;
- mtu = bta_av_chk_mtu(p_scb, p_scb->stream_mtu);
- APPL_TRACE_DEBUG("%s: l2c_cid: 0x%x stream_mtu: %d mtu: %d", __func__,
- p_scb->l2c_cid, p_scb->stream_mtu, mtu);
- if (mtu == 0 || mtu > p_scb->stream_mtu) mtu = p_scb->stream_mtu;
+ APPL_TRACE_DEBUG("%s: l2c_cid: 0x%x stream_mtu: %d", __func__, p_scb->l2c_cid,
+ p_scb->stream_mtu);
/* Set the media channel as high priority */
L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_HIGH);
L2CA_SetChnlFlushability(p_scb->l2c_cid, true);
- bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+ bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
memset(&p_scb->q_info, 0, sizeof(tBTA_AV_Q_INFO));
p_scb->l2c_bufs = 0;
- p_scb->p_cos->open(p_scb->hndl, mtu);
+ p_scb->p_cos->open(p_scb->hndl, p_scb->PeerAddress(), p_scb->stream_mtu);
{
/* TODO check if other audio channel is open.
@@ -1371,23 +1243,24 @@
*/
/* check if other audio channel is started. If yes, start */
tBTA_AV_OPEN open;
- open.bd_addr = p_scb->peer_addr;
+ open.bd_addr = p_scb->PeerAddress();
open.chnl = p_scb->chnl;
open.hndl = p_scb->hndl;
open.status = BTA_AV_SUCCESS;
open.starting = bta_av_chk_start(p_scb);
open.edr = 0;
- p = BTM_ReadRemoteFeatures(p_scb->peer_addr);
+ p = BTM_ReadRemoteFeatures(p_scb->PeerAddress());
if (p != NULL) {
if (HCI_EDR_ACL_2MPS_SUPPORTED(p)) open.edr |= BTA_AV_EDR_2MBPS;
if (HCI_EDR_ACL_3MPS_SUPPORTED(p)) {
- if (!interop_match_addr(INTEROP_2MBPS_LINK_ONLY, &p_scb->peer_addr)) {
+ if (!interop_match_addr(INTEROP_2MBPS_LINK_ONLY,
+ &p_scb->PeerAddress())) {
open.edr |= BTA_AV_EDR_3MBPS;
}
}
}
#if (BTA_AR_INCLUDED == TRUE)
- bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr);
+ bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr, p_scb->hdi);
#endif
if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC) {
open.sep = AVDT_TSEP_SNK;
@@ -1486,7 +1359,7 @@
/* close stream */
p_scb->started = false;
- p_scb->current_codec = nullptr;
+ p_scb->use_rtp_header_marker_bit = false;
/* drop the buffers queued in L2CAP */
L2CA_FlushChannel(p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
@@ -1511,6 +1384,8 @@
*
******************************************************************************/
void bta_av_connect_req(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
+ APPL_TRACE_DEBUG("%s: peer %s coll_mask:0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->coll_mask);
p_scb->sdp_discovery_started = false;
if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) {
/* SNK initiated L2C connection while SRC was doing SDP. */
@@ -1522,8 +1397,8 @@
return;
}
- AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask,
- bta_av_dt_cback[p_scb->hdi]);
+ AVDT_ConnectReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sec_mask,
+ &bta_av_proc_stream_evt);
}
/*******************************************************************************
@@ -1537,7 +1412,7 @@
******************************************************************************/
void bta_av_sdp_failed(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
APPL_TRACE_ERROR("%s: peer_addr=%s open_status=%d", __func__,
- p_scb->peer_addr.ToString().c_str(), p_scb->open_status);
+ p_scb->PeerAddress().ToString().c_str(), p_scb->open_status);
if (p_scb->open_status == BTA_AV_SUCCESS) {
p_scb->open_status = BTA_AV_FAIL_SDP;
@@ -1563,13 +1438,16 @@
/* our uuid in case we initiate connection */
uint16_t uuid_int = p_scb->uuid_int;
- APPL_TRACE_DEBUG("%s: initiator UUID 0x%x", __func__, uuid_int);
+ APPL_TRACE_DEBUG("%s: peer %s handle: %d initiator UUID 0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ uuid_int);
+
/* store number of stream endpoints returned */
p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
for (i = 0; i < p_scb->num_seps; i++) {
/* steam not in use, is a sink, and is audio */
- if ((p_scb->sep_info[i].in_use == false) &&
+ if ((!p_scb->sep_info[i].in_use) &&
(p_scb->sep_info[i].media_type == p_scb->media_type)) {
if ((p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
(uuid_int == UUID_SERVCLASS_AUDIO_SOURCE))
@@ -1581,8 +1459,8 @@
}
}
- p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, num_srcs,
- p_scb->peer_addr, uuid_int);
+ p_scb->p_cos->disc_res(p_scb->hndl, p_scb->PeerAddress(), p_scb->num_seps,
+ num_snks, num_srcs, uuid_int);
p_scb->num_disc_snks = num_snks;
p_scb->num_disc_srcs = num_srcs;
@@ -1597,7 +1475,7 @@
/* else we got discover response but with no streams; we're done */
else {
APPL_TRACE_ERROR("%s: BTA_AV_STR_DISC_FAIL_EVT: peer_addr=%s", __func__,
- p_scb->peer_addr.ToString().c_str());
+ p_scb->PeerAddress().ToString().c_str());
bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, p_data);
}
}
@@ -1616,6 +1494,9 @@
void bta_av_disc_res_as_acp(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
uint8_t num_snks = 0, i;
+ APPL_TRACE_DEBUG("%s: peer %s handle: %d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl);
+
/* store number of stream endpoints returned */
p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
@@ -1627,8 +1508,8 @@
num_snks++;
}
}
- p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, 0,
- p_scb->peer_addr, UUID_SERVCLASS_AUDIO_SOURCE);
+ p_scb->p_cos->disc_res(p_scb->hndl, p_scb->PeerAddress(), p_scb->num_seps,
+ num_snks, 0, UUID_SERVCLASS_AUDIO_SOURCE);
p_scb->num_disc_snks = num_snks;
p_scb->num_disc_srcs = 0;
@@ -1643,7 +1524,7 @@
/* else we got discover response but with no streams; we're done */
else {
APPL_TRACE_ERROR("%s: BTA_AV_STR_DISC_FAIL_EVT: peer_addr=%s", __func__,
- p_scb->peer_addr.ToString().c_str());
+ p_scb->PeerAddress().ToString().c_str());
bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, p_data);
}
}
@@ -1658,36 +1539,47 @@
*
******************************************************************************/
void bta_av_save_caps(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- tAVDT_CFG cfg;
+ AvdtpSepConfig cfg;
tAVDT_SEP_INFO* p_info = &p_scb->sep_info[p_scb->sep_info_idx];
uint8_t old_wait = p_scb->wait;
bool getcap_done = false;
- APPL_TRACE_DEBUG("%s: num_seps:%d sep_info_idx:%d wait:x%x", __func__,
- p_scb->num_seps, p_scb->sep_info_idx, p_scb->wait);
- A2DP_DumpCodecInfo(p_scb->p_cap->codec_info);
+ APPL_TRACE_DEBUG(
+ "%s: peer %s handle:%d num_seps:%d sep_info_idx:%d wait:0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl, p_scb->num_seps,
+ p_scb->sep_info_idx, p_scb->wait);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_scb->peer_cap.codec_info).c_str());
- memcpy(&cfg, p_scb->p_cap, sizeof(tAVDT_CFG));
+ cfg = p_scb->peer_cap;
/* let application know the capability of the SNK */
- p_scb->p_cos->getcfg(p_scb->hndl, cfg.codec_info, &p_scb->sep_info_idx,
- p_info->seid, &cfg.num_protect, cfg.protect_info);
+ if (p_scb->p_cos->getcfg(p_scb->hndl, p_scb->PeerAddress(), cfg.codec_info,
+ &p_scb->sep_info_idx, p_info->seid, &cfg.num_protect,
+ cfg.protect_info) != A2DP_SUCCESS) {
+ p_scb->sep_info_idx++;
+ APPL_TRACE_DEBUG("%s: result: next sep_info_idx:%d", __func__,
+ p_scb->sep_info_idx);
+ } else {
+ // All capabilities found
+ getcap_done = true;
+ APPL_TRACE_DEBUG("%s: result: done sep_info_idx:%d", __func__,
+ p_scb->sep_info_idx);
+ }
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(cfg.codec_info).c_str());
- p_scb->sep_info_idx++;
- APPL_TRACE_DEBUG("%s: result: sep_info_idx:%d", __func__,
- p_scb->sep_info_idx);
- A2DP_DumpCodecInfo(cfg.codec_info);
-
- if (p_scb->num_seps > p_scb->sep_info_idx) {
+ if (p_scb->num_seps > p_scb->sep_info_idx && !getcap_done) {
/* Some devices have seps at the end of the discover list, which is not */
/* matching media type(video not audio). */
/* In this case, we are done with getcap without sending another */
/* request to AVDT. */
if (!bta_av_next_getcap(p_scb, p_data)) getcap_done = true;
- } else
+ } else {
getcap_done = true;
+ }
if (getcap_done) {
- APPL_TRACE_DEBUG("%s: getcap_done: num_seps:%d sep_info_idx:%d wait:x%x",
+ APPL_TRACE_DEBUG("%s: getcap_done: num_seps:%d sep_info_idx:%d wait:0x%x",
__func__, p_scb->num_seps, p_scb->sep_info_idx,
p_scb->wait);
p_scb->wait &= ~(BTA_AV_WAIT_ACP_CAPS_ON | BTA_AV_WAIT_ACP_CAPS_STARTED);
@@ -1720,11 +1612,9 @@
*
******************************************************************************/
void bta_av_cco_close(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
- uint16_t mtu;
-
- mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU);
-
- p_scb->p_cos->close(p_scb->hndl);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl);
+ p_scb->p_cos->close(p_scb->hndl, p_scb->PeerAddress());
}
/*******************************************************************************
@@ -1742,25 +1632,25 @@
uint8_t idx;
APPL_TRACE_ERROR("%s: peer_addr=%s", __func__,
- p_scb->peer_addr.ToString().c_str());
+ p_scb->PeerAddress().ToString().c_str());
p_scb->open_status = BTA_AV_FAIL_STREAM;
bta_av_cco_close(p_scb, p_data);
/* check whether there is already an opened audio or video connection with the
* same device */
- for (idx = 0; (idx < BTA_AV_NUM_STRS) && (is_av_opened == false); idx++) {
+ for (idx = 0; (idx < BTA_AV_NUM_STRS) && (!is_av_opened); idx++) {
p_opened_scb = bta_av_cb.p_scb[idx];
if (p_opened_scb && (p_opened_scb->state == BTA_AV_OPEN_SST) &&
- (p_opened_scb->peer_addr == p_scb->peer_addr))
+ (p_opened_scb->PeerAddress() == p_scb->PeerAddress()))
is_av_opened = true;
}
/* if there is already an active AV connnection with the same bd_addr,
don't send disconnect req, just report the open event with
BTA_AV_FAIL_GET_CAP status */
- if (is_av_opened == true) {
+ if (is_av_opened) {
tBTA_AV_OPEN open;
- open.bd_addr = p_scb->peer_addr;
+ open.bd_addr = p_scb->PeerAddress();
open.chnl = p_scb->chnl;
open.hndl = p_scb->hndl;
open.status = BTA_AV_FAIL_GET_CAP;
@@ -1785,7 +1675,7 @@
bta_av_data.open = open;
(*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, &bta_av_data);
} else {
- AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DisconnectReq(p_scb->PeerAddress(), &bta_av_proc_stream_evt);
}
}
@@ -1801,36 +1691,40 @@
*
******************************************************************************/
void bta_av_getcap_results(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- tAVDT_CFG cfg;
- uint8_t media_type;
+ AvdtpSepConfig cfg = p_scb->cfg;
+ uint8_t media_type = A2DP_GetMediaType(p_scb->peer_cap.codec_info);
tAVDT_SEP_INFO* p_info = &p_scb->sep_info[p_scb->sep_info_idx];
- uint16_t uuid_int; /* UUID for which connection was initiatied */
- memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
cfg.num_codec = 1;
- cfg.num_protect = p_scb->p_cap->num_protect;
- memcpy(cfg.codec_info, p_scb->p_cap->codec_info, AVDT_CODEC_SIZE);
- memcpy(cfg.protect_info, p_scb->p_cap->protect_info, AVDT_PROTECT_SIZE);
- media_type = A2DP_GetMediaType(p_scb->p_cap->codec_info);
+ cfg.num_protect = p_scb->peer_cap.num_protect;
+ memcpy(cfg.codec_info, p_scb->peer_cap.codec_info, AVDT_CODEC_SIZE);
+ memcpy(cfg.protect_info, p_scb->peer_cap.protect_info, AVDT_PROTECT_SIZE);
- APPL_TRACE_DEBUG("%s: num_codec %d", __func__, p_scb->p_cap->num_codec);
- APPL_TRACE_DEBUG("%s: media type x%x, x%x", __func__, media_type,
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d num_codec:%d psc_mask=0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ p_scb->peer_cap.num_codec, p_scb->cfg.psc_mask);
+ APPL_TRACE_DEBUG("%s: media type 0x%x, 0x%x", __func__, media_type,
p_scb->media_type);
- A2DP_DumpCodecInfo(p_scb->cfg.codec_info);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_scb->cfg.codec_info).c_str());
/* if codec present and we get a codec configuration */
- if ((p_scb->p_cap->num_codec != 0) && (media_type == p_scb->media_type) &&
- (p_scb->p_cos->getcfg(p_scb->hndl, cfg.codec_info, &p_scb->sep_info_idx,
- p_info->seid, &cfg.num_protect,
+ if ((p_scb->peer_cap.num_codec != 0) && (media_type == p_scb->media_type) &&
+ (p_scb->p_cos->getcfg(p_scb->hndl, p_scb->PeerAddress(), cfg.codec_info,
+ &p_scb->sep_info_idx, p_info->seid,
+ &cfg.num_protect,
cfg.protect_info) == A2DP_SUCCESS)) {
+ /* UUID for which connection was initiatied */
+ uint16_t uuid_int = p_scb->uuid_int;
+
/* save copy of codec configuration */
- memcpy(&p_scb->cfg, &cfg, sizeof(tAVDT_CFG));
+ p_scb->cfg = cfg;
APPL_TRACE_DEBUG("%s: result: sep_info_idx=%d", __func__,
p_scb->sep_info_idx);
- A2DP_DumpCodecInfo(p_scb->cfg.codec_info);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_scb->cfg.codec_info).c_str());
- uuid_int = p_scb->uuid_int;
APPL_TRACE_DEBUG("%s: initiator UUID = 0x%x", __func__, uuid_int);
if (uuid_int == UUID_SERVCLASS_AUDIO_SOURCE)
bta_av_adjust_seps_idx(p_scb,
@@ -1840,14 +1734,19 @@
bta_av_get_scb_handle(p_scb, AVDT_TSEP_SNK));
/* use only the services peer supports */
- cfg.psc_mask &= p_scb->p_cap->psc_mask;
+ cfg.psc_mask &= p_scb->peer_cap.psc_mask;
p_scb->cur_psc_mask = cfg.psc_mask;
+ APPL_TRACE_DEBUG(
+ "%s: peer %s handle:%d sep_idx:%d sep_info_idx:%d "
+ "cur_psc_mask:0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ p_scb->sep_idx, p_scb->sep_info_idx, p_scb->cur_psc_mask);
if ((uuid_int == UUID_SERVCLASS_AUDIO_SINK) &&
(p_scb->seps[p_scb->sep_idx].p_app_sink_data_cback != NULL)) {
APPL_TRACE_DEBUG("%s: configure decoder for Sink connection", __func__);
tBTA_AV_MEDIA av_sink_codec_info;
- av_sink_codec_info.avk_config.bd_addr = p_scb->peer_addr;
+ av_sink_codec_info.avk_config.bd_addr = p_scb->PeerAddress();
av_sink_codec_info.avk_config.codec_info = p_scb->cfg.codec_info;
p_scb->seps[p_scb->sep_idx].p_app_sink_data_cback(
BTA_AV_SINK_MEDIA_CFG_EVT, &av_sink_codec_info);
@@ -1858,13 +1757,8 @@
}
/* open the stream */
- AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
- p_scb->sep_info[p_scb->sep_info_idx].seid, &cfg);
-
- if (!bta_av_is_rcfg_sst(p_scb)) {
- /* free capabilities buffer */
- osi_free_and_reset((void**)&p_scb->p_cap);
- }
+ AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->PeerAddress(),
+ p_scb->hdi, p_scb->sep_info[p_scb->sep_info_idx].seid, &cfg);
} else {
/* try the next stream, if any */
p_scb->sep_info_idx++;
@@ -1909,8 +1803,8 @@
void bta_av_discover_req(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
/* send avdtp discover request */
- AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS,
- bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DiscoverReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sep_info,
+ BTA_AV_NUM_SEPS, &bta_av_proc_stream_evt);
}
/*******************************************************************************
@@ -1924,7 +1818,7 @@
******************************************************************************/
void bta_av_conn_failed(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
APPL_TRACE_ERROR("%s: peer_addr=%s open_status=%d", __func__,
- p_scb->peer_addr.ToString().c_str(), p_scb->open_status);
+ p_scb->PeerAddress().ToString().c_str(), p_scb->open_status);
p_scb->open_status = BTA_AV_FAIL_STREAM;
bta_av_str_closed(p_scb, p_data);
@@ -1940,11 +1834,14 @@
*
******************************************************************************/
void bta_av_do_start(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- uint8_t policy = HCI_ENABLE_SNIFF_MODE;
+ uint8_t clear_policy = 0;
uint8_t cur_role;
- APPL_TRACE_DEBUG("%s: sco_occupied:%d, role:x%x, started:%d", __func__,
- bta_av_cb.sco_occupied, p_scb->role, p_scb->started);
+ LOG_INFO(LOG_TAG,
+ "%s: peer %s sco_occupied:%s role:0x%x started:%s wait:0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(),
+ logbool(bta_av_cb.sco_occupied).c_str(), p_scb->role,
+ logbool(p_scb->started).c_str(), p_scb->wait);
if (bta_av_cb.sco_occupied) {
bta_av_start_failed(p_scb, p_data);
return;
@@ -1953,31 +1850,57 @@
/* disallow role switch during streaming, only if we are the master role
* i.e. allow role switch, if we are slave.
* It would not hurt us, if the peer device wants us to be master */
- if ((BTM_GetRole(p_scb->peer_addr, &cur_role) == BTM_SUCCESS) &&
+ if ((BTM_GetRole(p_scb->PeerAddress(), &cur_role) == BTM_SUCCESS) &&
(cur_role == BTM_ROLE_MASTER)) {
- policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ clear_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
}
- bta_sys_clear_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+ bta_sys_clear_policy(BTA_ID_AV, clear_policy, p_scb->PeerAddress());
- if ((p_scb->started == false) &&
- ((p_scb->role & BTA_AV_ROLE_START_INT) == 0)) {
+ if (p_scb->started) {
p_scb->role |= BTA_AV_ROLE_START_INT;
- bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
-
- AVDT_StartReq(&p_scb->avdt_handle, 1);
- } else if (p_scb->started) {
- p_scb->role |= BTA_AV_ROLE_START_INT;
- if (p_scb->wait == 0) {
- if (p_scb->role & BTA_AV_ROLE_SUSPEND) {
- notify_start_failed(p_scb);
- } else {
- bta_av_start_ok(p_scb, NULL);
- }
+ if (p_scb->wait != 0) {
+ LOG_WARN(
+ LOG_TAG,
+ "%s: peer %s start stream request ignored: "
+ "already waiting: sco_occupied:%s role:0x%x started:%s wait:0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(),
+ logbool(bta_av_cb.sco_occupied).c_str(), p_scb->role,
+ logbool(p_scb->started).c_str(), p_scb->wait);
+ return;
}
+ if (p_scb->role & BTA_AV_ROLE_SUSPEND) {
+ notify_start_failed(p_scb);
+ } else {
+ bta_av_start_ok(p_scb, NULL);
+ }
+ return;
}
- APPL_TRACE_DEBUG("%s: started %d role:x%x", __func__, p_scb->started,
- p_scb->role);
+
+ if ((p_scb->role & BTA_AV_ROLE_START_INT) != 0) {
+ LOG_WARN(
+ LOG_TAG,
+ "%s: peer %s start stream request ignored: "
+ "already initiated: sco_occupied:%s role:0x%x started:%s wait:0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(),
+ logbool(bta_av_cb.sco_occupied).c_str(), p_scb->role,
+ logbool(p_scb->started).c_str(), p_scb->wait);
+ return;
+ }
+
+ p_scb->role |= BTA_AV_ROLE_START_INT;
+ bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
+ uint16_t result = AVDT_StartReq(&p_scb->avdt_handle, 1);
+ if (result != AVDT_SUCCESS) {
+ LOG_ERROR(LOG_TAG, "%s: AVDT_StartReq failed for peer %s result:%d",
+ __func__, p_scb->PeerAddress().ToString().c_str(), result);
+ }
+ LOG_INFO(LOG_TAG,
+ "%s: peer %s start requested: sco_occupied:%s role:0x%x "
+ "started:%s wait:0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(),
+ logbool(bta_av_cb.sco_occupied).c_str(), p_scb->role,
+ logbool(p_scb->started).c_str(), p_scb->wait);
}
/*******************************************************************************
@@ -1994,35 +1917,31 @@
uint8_t start = p_scb->started;
bool sus_evt = true;
BT_HDR* p_buf;
- uint8_t policy = HCI_ENABLE_SNIFF_MODE;
+ uint8_t set_policy = HCI_ENABLE_SNIFF_MODE;
- APPL_TRACE_ERROR("%s: audio_open_cnt=%d, p_data %p", __func__,
- bta_av_cb.audio_open_cnt, p_data);
+ APPL_TRACE_ERROR(
+ "%s: peer %s handle:%d audio_open_cnt:%d, p_data %p start:%d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ bta_av_cb.audio_open_cnt, p_data, start);
- bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 ||
- bta_av_cb.audio_open_cnt == 1)
- policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
- bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+ bta_av_cb.audio_open_cnt == 1) {
+ set_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ }
+ bta_sys_set_policy(BTA_ID_AV, set_policy, p_scb->PeerAddress());
if (p_scb->co_started) {
- /* TODO(eisenbach): RE-IMPLEMENT USING VSC OR HAL EXTENSION
- vendor_get_interface()->send_command(
- (vendor_opcode_t)BT_VND_OP_A2DP_OFFLOAD_STOP, (void*)&p_scb->l2c_cid);
- if (p_scb->offload_start_pending) {
- tBTA_AV_STATUS status = BTA_AV_FAIL_STREAM;
- tBTA_AV bta_av_data;
- bta_av_data.status = status;
- (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, &bta_av_data);
+ if (p_scb->offload_started) {
+ bta_av_vendor_offload_stop();
+ p_scb->offload_started = false;
}
- p_scb->offload_start_pending = false;
- */
bta_av_stream_chg(p_scb, false);
p_scb->co_started = false;
- p_scb->p_cos->stop(p_scb->hndl);
- L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->PeerAddress());
+ L2CA_SetFlushTimeout(p_scb->PeerAddress(), L2CAP_DEFAULT_FLUSH_TO);
}
/* if q_info.a2dp_list is not empty, drop it now */
@@ -2042,7 +1961,8 @@
suspend_rsp.hndl = p_scb->hndl;
if (p_data && p_data->api_stop.suspend) {
- APPL_TRACE_DEBUG("%s: suspending: %d, sup:%d", __func__, start,
+ APPL_TRACE_DEBUG("%s: peer %s suspending: %d, sup:%d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), start,
p_scb->suspend_sup);
if ((start) && (p_scb->suspend_sup)) {
sus_evt = false;
@@ -2088,7 +2008,7 @@
*
******************************************************************************/
void bta_av_reconfig(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- tAVDT_CFG* p_cfg;
+ AvdtpSepConfig* p_cfg;
tBTA_AV_API_STOP stop;
tBTA_AV_API_RCFG* p_rcfg = &p_data->api_reconfig;
@@ -2097,8 +2017,6 @@
p_scb->num_recfg = 0;
/* store the new configuration in control block */
- if (p_scb->p_cap == NULL)
- p_scb->p_cap = (tAVDT_CFG*)osi_malloc(sizeof(tAVDT_CFG));
p_cfg = &p_scb->cfg;
alarm_cancel(p_scb->avrc_ct_timer);
@@ -2106,9 +2024,12 @@
APPL_TRACE_DEBUG(
"%s: p_scb->sep_info_idx=%d p_scb->rcfg_idx=%d p_rcfg->sep_info_idx=%d",
__func__, p_scb->sep_info_idx, p_scb->rcfg_idx, p_rcfg->sep_info_idx);
- A2DP_DumpCodecInfo(p_scb->p_cap->codec_info);
- A2DP_DumpCodecInfo(p_scb->cfg.codec_info);
- A2DP_DumpCodecInfo(p_rcfg->codec_info);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_scb->peer_cap.codec_info).c_str());
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_scb->cfg.codec_info).c_str());
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_rcfg->codec_info).c_str());
p_cfg->num_protect = p_rcfg->num_protect;
memcpy(p_cfg->codec_info, p_rcfg->codec_info, AVDT_CODEC_SIZE);
@@ -2131,7 +2052,8 @@
} else {
// Reconfigure
APPL_TRACE_DEBUG("%s: reconfig", __func__);
- A2DP_DumpCodecInfo(p_scb->cfg.codec_info);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_scb->cfg.codec_info).c_str());
AVDT_ReconfigReq(p_scb->avdt_handle, &p_scb->cfg);
p_scb->cfg.psc_mask = p_scb->cur_psc_mask;
}
@@ -2181,7 +2103,7 @@
if (p_scb->cong) return;
- if (p_scb->current_codec->useRtpHeaderMarkerBit()) {
+ if (p_scb->use_rtp_header_marker_bit) {
m_pt |= AVDT_MARKER_SET;
}
@@ -2197,7 +2119,7 @@
} else {
new_buf = true;
/* A2DP_list empty, call co_data, dup data to other channels */
- p_buf = (BT_HDR*)p_scb->p_cos->data(p_scb->cfg.codec_info, ×tamp);
+ p_buf = p_scb->p_cos->data(p_scb->cfg.codec_info, ×tamp);
if (p_buf) {
/* use the offset area for the time stamp */
@@ -2217,7 +2139,7 @@
/* opt is a bit mask, it could have several options set */
opt = AVDT_DATA_OPT_NONE;
- if (p_scb->no_rtp_hdr) {
+ if (p_scb->no_rtp_header) {
opt |= AVDT_DATA_OPT_NO_RTP;
}
@@ -2279,7 +2201,7 @@
list_prepend(p_scb->a2dp_list, p_buf);
} else {
/* too many buffers in a2dp_list, drop it. */
- bta_av_co_audio_drop(p_scb->hndl);
+ bta_av_co_audio_drop(p_scb->hndl, p_scb->PeerAddress());
osi_free(p_buf);
}
}
@@ -2302,14 +2224,23 @@
uint16_t flush_to;
uint8_t new_role = p_scb->role;
BT_HDR hdr;
- uint8_t policy = HCI_ENABLE_SNIFF_MODE;
+ uint8_t clear_policy = 0;
uint8_t cur_role;
+ uint8_t local_tsep = p_scb->seps[p_scb->sep_idx].tsep;
- APPL_TRACE_DEBUG("%s: wait:x%x, role:x%x", __func__, p_scb->wait,
- p_scb->role);
+ LOG_INFO(LOG_TAG, "%s: peer %s handle:%d wait:0x%x role:0x%x local_tsep:%d",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ p_scb->wait, p_scb->role, local_tsep);
p_scb->started = true;
- p_scb->current_codec = bta_av_get_a2dp_current_codec();
+
+ if (local_tsep == AVDT_TSEP_SRC) {
+ // The RTP Header marker bit for the A2DP Source encoder
+ A2dpCodecConfig* codec_config =
+ bta_av_get_a2dp_peer_current_codec(p_scb->PeerAddress());
+ CHECK(codec_config != nullptr);
+ p_scb->use_rtp_header_marker_bit = codec_config->useRtpHeaderMarkerBit();
+ }
if (p_scb->sco_suspend) {
p_scb->sco_suspend = false;
@@ -2319,23 +2250,30 @@
/* for A2DP SINK we do not send get_caps */
if ((p_scb->avdt_handle == p_scb->seps[p_scb->sep_idx].av_handle) &&
- (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK)) {
+ (local_tsep == AVDT_TSEP_SNK)) {
p_scb->wait &= ~(BTA_AV_WAIT_ACP_CAPS_ON);
APPL_TRACE_DEBUG("%s: local SEP type is SNK new wait is 0x%x", __func__,
p_scb->wait);
}
if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_FAILED) {
/* role switch has failed */
+ APPL_TRACE_ERROR(
+ "%s: peer %s role switch failed: handle:%d wait:0x%x, role:0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ p_scb->wait, p_scb->role);
p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_FAILED;
p_data = (tBTA_AV_DATA*)&hdr;
hdr.offset = BTA_AV_RS_FAIL;
}
- APPL_TRACE_DEBUG("%s: wait:x%x", __func__, p_scb->wait);
+ APPL_TRACE_DEBUG("%s: peer %s wait:0x%x use_rtp_header_marker_bit:%s",
+ __func__, p_scb->PeerAddress().ToString().c_str(),
+ p_scb->wait,
+ (p_scb->use_rtp_header_marker_bit) ? "true" : "false");
if (p_data && (p_data->hdr.offset != BTA_AV_RS_NONE)) {
p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
if (p_data->hdr.offset == BTA_AV_RS_FAIL) {
- bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
tBTA_AV_START start;
start.chnl = p_scb->chnl;
start.status = BTA_AV_FAIL_ROLE;
@@ -2367,8 +2305,9 @@
}
if (p_scb->wait) {
- APPL_TRACE_ERROR("%s: wait:x%x q_tag:%d- not started", __func__,
- p_scb->wait, p_scb->q_tag);
+ APPL_TRACE_ERROR("%s: peer %s wait:0x%x q_tag:%d not started", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->wait,
+ p_scb->q_tag);
/* Clear first bit of p_scb->wait and not to return from this point else
* HAL layer gets blocked. And if there is delay in Get Capability response
* as
@@ -2380,9 +2319,9 @@
}
/* tell role manager to check M/S role */
- bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+ bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
- bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
if (p_scb->media_type == AVDT_MEDIA_TYPE_AUDIO) {
/* in normal logic, conns should be bta_av_cb.audio_count - 1,
@@ -2394,9 +2333,9 @@
p_scb->co_started = bta_av_cb.audio_open_cnt;
flush_to = p_bta_av_cfg->p_audio_flush_to[p_scb->co_started - 1];
} else {
- flush_to = p_bta_av_cfg->video_flush_to;
+ flush_to = 0;
}
- L2CA_SetFlushTimeout(p_scb->peer_addr, flush_to);
+ L2CA_SetFlushTimeout(p_scb->PeerAddress(), flush_to);
/* clear the congestion flag */
p_scb->cong = false;
@@ -2420,23 +2359,25 @@
* Otherwise allow role switch, if source is slave.
* Because it would not hurt source, if the peer device wants source to be
* master */
- if ((BTM_GetRole(p_scb->peer_addr, &cur_role) == BTM_SUCCESS) &&
+ if ((BTM_GetRole(p_scb->PeerAddress(), &cur_role) == BTM_SUCCESS) &&
(cur_role == BTM_ROLE_MASTER)) {
- policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ clear_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
}
- bta_sys_clear_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+ bta_sys_clear_policy(BTA_ID_AV, clear_policy, p_scb->PeerAddress());
}
p_scb->role = new_role;
p_scb->role &= ~BTA_AV_ROLE_AD_ACP;
p_scb->role &= ~BTA_AV_ROLE_SUSPEND_OPT;
- p_scb->no_rtp_hdr = false;
- p_scb->p_cos->start(p_scb->hndl, p_scb->cfg.codec_info, &p_scb->no_rtp_hdr);
+ p_scb->no_rtp_header = false;
+ p_scb->p_cos->start(p_scb->hndl, p_scb->PeerAddress(),
+ p_scb->cfg.codec_info, &p_scb->no_rtp_header);
p_scb->co_started = true;
- APPL_TRACE_DEBUG("%s: suspending: %d, role:x%x, init %d", __func__, suspend,
+ APPL_TRACE_DEBUG("%s: peer %s suspending: %d, role:0x%x, init %d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), suspend,
p_scb->role, initiator);
tBTA_AV_START start;
@@ -2454,7 +2395,7 @@
p_scb->role |= BTA_AV_ROLE_SUSPEND;
p_scb->cong = true; /* do not allow the media data to go through */
/* do not duplicate the media packets to this channel */
- p_scb->p_cos->stop(p_scb->hndl);
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->PeerAddress());
p_scb->co_started = false;
stop.flush = false;
stop.suspend = true;
@@ -2474,14 +2415,20 @@
*
******************************************************************************/
void bta_av_start_failed(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
- if (p_scb->started == false && p_scb->co_started == false) {
- bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ uint8_t set_policy = (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_MASTER_SLAVE_SWITCH);
+
+ APPL_TRACE_ERROR(
+ "%s: peer %s handle:%d audio_open_cnt:%d started:%s co_started:%d",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ bta_av_cb.audio_open_cnt, logbool(p_scb->started).c_str(),
+ p_scb->co_started);
+
+ if (!p_scb->started && !p_scb->co_started) {
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
notify_start_failed(p_scb);
}
- bta_sys_set_policy(BTA_ID_AV,
- (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_MASTER_SLAVE_SWITCH),
- p_scb->peer_addr);
+ bta_sys_set_policy(BTA_ID_AV, set_policy, p_scb->PeerAddress());
p_scb->sco_suspend = false;
}
@@ -2497,17 +2444,18 @@
void bta_av_str_closed(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
tBTA_AV data;
tBTA_AV_EVT event;
- uint8_t policy = HCI_ENABLE_SNIFF_MODE;
+ uint8_t set_policy = HCI_ENABLE_SNIFF_MODE;
APPL_TRACE_WARNING(
- "%s: peer_addr=%s open_status=%d chnl=%d hndl=%d co_started=%d", __func__,
- p_scb->peer_addr.ToString().c_str(), p_scb->open_status, p_scb->chnl,
- p_scb->hndl, p_scb->co_started);
+ "%s: peer %s handle:%d open_status:%d chnl:%d co_started:%d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl, p_scb->open_status,
+ p_scb->chnl, p_scb->co_started);
if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 ||
- bta_av_cb.audio_open_cnt == 1)
- policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
- bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+ bta_av_cb.audio_open_cnt == 1) {
+ set_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ }
+ bta_sys_set_policy(BTA_ID_AV, set_policy, p_scb->PeerAddress());
if (bta_av_cb.audio_open_cnt <= 1) {
/* last connection - restore the allow switch flag */
L2CA_SetDesireRole(L2CAP_ROLE_ALLOW_SWITCH);
@@ -2515,7 +2463,7 @@
if (p_scb->open_status != BTA_AV_SUCCESS) {
/* must be failure when opening the stream */
- data.open.bd_addr = p_scb->peer_addr;
+ data.open.bd_addr = p_scb->PeerAddress();
data.open.status = p_scb->open_status;
data.open.chnl = p_scb->chnl;
data.open.hndl = p_scb->hndl;
@@ -2528,7 +2476,7 @@
event = BTA_AV_OPEN_EVT;
p_scb->open_status = BTA_AV_SUCCESS;
- bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+ bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
bta_av_cleanup(p_scb, p_data);
(*bta_av_cb.p_cback)(event, &data);
} else {
@@ -2538,12 +2486,12 @@
}
{
- p_scb->p_cos->close(p_scb->hndl);
+ p_scb->p_cos->close(p_scb->hndl, p_scb->PeerAddress());
data.close.chnl = p_scb->chnl;
data.close.hndl = p_scb->hndl;
event = BTA_AV_CLOSE_EVT;
- bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+ bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
bta_av_cleanup(p_scb, p_data);
(*bta_av_cb.p_cback)(event, &data);
}
@@ -2560,7 +2508,10 @@
*
******************************************************************************/
void bta_av_clr_cong(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
- if (p_scb->co_started) p_scb->cong = false;
+ APPL_TRACE_DEBUG("%s", __func__);
+ if (p_scb->co_started) {
+ p_scb->cong = false;
+ }
}
/*******************************************************************************
@@ -2575,12 +2526,13 @@
void bta_av_suspend_cfm(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
tBTA_AV_SUSPEND suspend_rsp;
uint8_t err_code = p_data->str_msg.msg.hdr.err_code;
- uint8_t policy = HCI_ENABLE_SNIFF_MODE;
+ uint8_t set_policy = HCI_ENABLE_SNIFF_MODE;
- APPL_TRACE_DEBUG("%s: audio_open_cnt = %d, err_code = %d", __func__,
- bta_av_cb.audio_open_cnt, err_code);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d audio_open_cnt:%d err_code:%d",
+ __func__, p_scb->PeerAddress().ToString().c_str(),
+ p_scb->hndl, bta_av_cb.audio_open_cnt, err_code);
- if (p_scb->started == false) {
+ if (!p_scb->started) {
/* handle the condition where there is a collision of SUSPEND req from
*either side
** Second SUSPEND req could be rejected. Do not treat this as a failure
@@ -2612,33 +2564,26 @@
p_scb->cong = false;
}
- bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 ||
- bta_av_cb.audio_open_cnt == 1)
- policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
- bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+ bta_av_cb.audio_open_cnt == 1) {
+ set_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ }
+ bta_sys_set_policy(BTA_ID_AV, set_policy, p_scb->PeerAddress());
/* in case that we received suspend_ind, we may need to call co_stop here */
if (p_scb->co_started) {
- /* TODO(eisenbach): RE-IMPLEMENT USING VSC OR HAL EXTENSION
- vendor_get_interface()->send_command(
- (vendor_opcode_t)BT_VND_OP_A2DP_OFFLOAD_STOP, (void*)&p_scb->l2c_cid);
- if (p_scb->offload_start_pending) {
- tBTA_AV_STATUS status = BTA_AV_FAIL_STREAM;
- tBTA_AV bta_av_data;
- bta_av_data.status = status;
- (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, &bta_av_data);
+ if (p_scb->offload_started) {
+ bta_av_vendor_offload_stop();
+ p_scb->offload_started = false;
}
- p_scb->offload_start_pending = false;
- */
-
bta_av_stream_chg(p_scb, false);
{
p_scb->co_started = false;
- p_scb->p_cos->stop(p_scb->hndl);
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->PeerAddress());
}
- L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
+ L2CA_SetFlushTimeout(p_scb->PeerAddress(), L2CAP_DEFAULT_FLUSH_TO);
}
{
@@ -2662,22 +2607,22 @@
******************************************************************************/
void bta_av_rcfg_str_ok(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
p_scb->l2c_cid = AVDT_GetL2CapChannel(p_scb->avdt_handle);
- APPL_TRACE_DEBUG("%s: l2c_cid: %d", __func__, p_scb->l2c_cid);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d l2c_cid:%d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ p_scb->l2c_cid);
if (p_data != NULL) {
// p_data could be NULL if the reconfig was triggered by the local device
p_scb->stream_mtu =
p_data->str_msg.msg.open_ind.peer_mtu - AVDT_MEDIA_HDR_SIZE;
- uint16_t mtu = bta_av_chk_mtu(p_scb, p_scb->stream_mtu);
- APPL_TRACE_DEBUG("%s: l2c_cid: 0x%x stream_mtu: %d mtu: %d", __func__,
- p_scb->l2c_cid, p_scb->stream_mtu, mtu);
- if (mtu == 0 || mtu > p_scb->stream_mtu) mtu = p_scb->stream_mtu;
- p_scb->p_cos->update_mtu(p_scb->hndl, mtu);
+ APPL_TRACE_DEBUG("%s: l2c_cid: 0x%x stream_mtu: %d", __func__,
+ p_scb->l2c_cid, p_scb->stream_mtu);
+ p_scb->p_cos->update_mtu(p_scb->hndl, p_scb->PeerAddress(),
+ p_scb->stream_mtu);
}
/* rc listen */
bta_av_st_rc_timer(p_scb, NULL);
- osi_free_and_reset((void**)&p_scb->p_cap);
/* No need to keep the role bits once reconfig is done. */
p_scb->role &= ~BTA_AV_ROLE_AD_ACP;
@@ -2708,7 +2653,7 @@
void bta_av_rcfg_failed(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
APPL_TRACE_ERROR("%s: num_recfg=%d conn_lcb=0x%x peer_addr=%s", __func__,
p_scb->num_recfg, bta_av_cb.conn_lcb,
- p_scb->peer_addr.ToString().c_str());
+ p_scb->PeerAddress().ToString().c_str());
if (p_scb->num_recfg > BTA_AV_RECONFIG_RETRY) {
bta_av_cco_close(p_scb, p_data);
@@ -2726,7 +2671,7 @@
/* open failed. try again */
p_scb->num_recfg++;
if (bta_av_cb.conn_lcb) {
- AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DisconnectReq(p_scb->PeerAddress(), &bta_av_proc_stream_evt);
} else {
bta_av_connect_req(p_scb, NULL);
}
@@ -2743,15 +2688,18 @@
*
******************************************************************************/
void bta_av_rcfg_connect(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
+ APPL_TRACE_DEBUG("%s", __func__);
+
p_scb->cong = false;
p_scb->num_recfg++;
APPL_TRACE_DEBUG("%s: num_recfg: %d", __func__, p_scb->num_recfg);
if (p_scb->num_recfg > BTA_AV_RECONFIG_RETRY) {
/* let bta_av_rcfg_failed report fail */
bta_av_rcfg_failed(p_scb, NULL);
- } else
- AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask,
- bta_av_dt_cback[p_scb->hdi]);
+ } else {
+ AVDT_ConnectReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sec_mask,
+ &bta_av_proc_stream_evt);
+ }
}
/*******************************************************************************
@@ -2766,7 +2714,7 @@
void bta_av_rcfg_discntd(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
APPL_TRACE_ERROR("%s: num_recfg=%d conn_lcb=0x%x peer_addr=%s", __func__,
p_scb->num_recfg, bta_av_cb.conn_lcb,
- p_scb->peer_addr.ToString().c_str());
+ p_scb->PeerAddress().ToString().c_str());
p_scb->num_recfg++;
if (p_scb->num_recfg > BTA_AV_RECONFIG_RETRY) {
@@ -2780,9 +2728,10 @@
(*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, &bta_av_data);
/* report close event & go to init state */
bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
- } else
- AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask,
- bta_av_dt_cback[p_scb->hdi]);
+ } else {
+ AVDT_ConnectReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sec_mask,
+ &bta_av_proc_stream_evt);
+ }
}
/*******************************************************************************
@@ -2798,6 +2747,8 @@
void bta_av_suspend_cont(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
uint8_t err_code = p_data->str_msg.msg.hdr.err_code;
+ APPL_TRACE_DEBUG("%s: err_code=%d", __func__, err_code);
+
p_scb->started = false;
p_scb->cong = false;
if (err_code) {
@@ -2809,7 +2760,7 @@
bta_av_data.reconfig = reconfig;
(*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, &bta_av_data);
APPL_TRACE_ERROR("%s: BTA_AV_STR_DISC_FAIL_EVT: peer_addr=%s", __func__,
- p_scb->peer_addr.ToString().c_str());
+ p_scb->PeerAddress().ToString().c_str());
bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
} else {
APPL_TRACE_ERROR("%s: suspend rejected, try close", __func__);
@@ -2827,7 +2778,8 @@
APPL_TRACE_DEBUG("%s: calling AVDT_ReconfigReq", __func__);
/* reconfig the stream */
- A2DP_DumpCodecInfo(p_scb->cfg.codec_info);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_scb->cfg.codec_info).c_str());
AVDT_ReconfigReq(p_scb->avdt_handle, &p_scb->cfg);
p_scb->cfg.psc_mask = p_scb->cur_psc_mask;
}
@@ -2852,13 +2804,16 @@
bool disable_avdtp_reconfigure = false;
{
char remote_name[BTM_MAX_REM_BD_NAME_LEN] = "";
- if (btif_storage_get_stored_remote_name(p_scb->peer_addr, remote_name)) {
+ if (btif_storage_get_stored_remote_name(p_scb->PeerAddress(),
+ remote_name)) {
if (interop_match_name(INTEROP_DISABLE_AVDTP_RECONFIGURE, remote_name) ||
interop_match_addr(INTEROP_DISABLE_AVDTP_RECONFIGURE,
- (const RawAddress*)&p_scb->peer_addr)) {
- VLOG(1) << __func__ << ": disable AVDTP RECONFIGURE: interop matched "
- "name "
- << remote_name << " address " << p_scb->peer_addr;
+ (const RawAddress*)&p_scb->PeerAddress())) {
+ LOG_INFO(LOG_TAG,
+ "%s: disable AVDTP RECONFIGURE: interop matched "
+ "name %s address %s",
+ __func__, remote_name,
+ p_scb->PeerAddress().ToString().c_str());
disable_avdtp_reconfigure = true;
}
}
@@ -2899,18 +2854,21 @@
*
******************************************************************************/
void bta_av_rcfg_open(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
- APPL_TRACE_DEBUG("%s: num_disc_snks = %d", __func__, p_scb->num_disc_snks);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d num_disc_snks:%d", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ p_scb->num_disc_snks);
if (p_scb->num_disc_snks == 0) {
/* Need to update call-out module so that it will be ready for discover */
- p_scb->p_cos->stop(p_scb->hndl);
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->PeerAddress());
/* send avdtp discover request */
- AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS,
- bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DiscoverReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sep_info,
+ BTA_AV_NUM_SEPS, &bta_av_proc_stream_evt);
} else {
APPL_TRACE_DEBUG("%s: calling AVDT_OpenReq()", __func__);
- A2DP_DumpCodecInfo(p_scb->cfg.codec_info);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_scb->cfg.codec_info).c_str());
/* we may choose to use a different SEP at reconfig.
* adjust the sep_idx now */
@@ -2918,7 +2876,7 @@
/* open the stream with the new config */
p_scb->sep_info_idx = p_scb->rcfg_idx;
- AVDT_OpenReq(p_scb->avdt_handle, p_scb->peer_addr,
+ AVDT_OpenReq(p_scb->avdt_handle, p_scb->PeerAddress(), p_scb->hdi,
p_scb->sep_info[p_scb->sep_info_idx].seid, &p_scb->cfg);
}
}
@@ -2950,29 +2908,41 @@
******************************************************************************/
void bta_av_chk_2nd_start(tBTA_AV_SCB* p_scb,
UNUSED_ATTR tBTA_AV_DATA* p_data) {
- tBTA_AV_SCB* p_scbi;
- int i;
- bool new_started = false;
+ LOG_INFO(LOG_TAG,
+ "%s: peer %s channel:%d bta_av_cb.audio_open_cnt:%d role:0x%x "
+ "features:0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->chnl,
+ bta_av_cb.audio_open_cnt, p_scb->role, bta_av_cb.features);
- if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2)) {
- /* more than one audio channel is connected */
+ if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2) &&
+ (((p_scb->role & BTA_AV_ROLE_AD_ACP) == 0) || // Outgoing connection or
+ (bta_av_cb.features & BTA_AV_FEAT_ACP_START))) { // Auto-starting option
+ // More than one audio channel is connected.
if (!(p_scb->role & BTA_AV_ROLE_SUSPEND_OPT)) {
- /* this channel does not need to be reconfigured.
- * if there is other channel streaming, start the stream now */
- for (i = 0; i < BTA_AV_NUM_STRS; i++) {
- p_scbi = bta_av_cb.p_scb[i];
+ // This channel does not need to be reconfigured.
+ // If there is other channel streaming, start the stream now.
+ bool new_started = false;
+ for (int i = 0; i < BTA_AV_NUM_STRS; i++) {
+ tBTA_AV_SCB* p_scbi = bta_av_cb.p_scb[i];
+ if (p_scb == p_scbi) {
+ continue;
+ }
if (p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started) {
if (!new_started) {
- /* start the new stream */
+ // Start the new stream
new_started = true;
+ LOG_INFO(LOG_TAG,
+ "%s: starting new stream for peer %s because peer %s "
+ "already started",
+ __func__, p_scb->PeerAddress().ToString().c_str(),
+ p_scbi->PeerAddress().ToString().c_str());
bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
}
- /* may need to update the flush timeout of this already started stream
- */
+ // May need to update the flush timeout of this already started stream
if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
p_scbi->co_started = bta_av_cb.audio_open_cnt;
L2CA_SetFlushTimeout(
- p_scbi->peer_addr,
+ p_scbi->PeerAddress(),
p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1]);
}
}
@@ -2991,7 +2961,7 @@
*
******************************************************************************/
void bta_av_open_rc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- APPL_TRACE_DEBUG("%s: use_rc: %d, wait: x%x role:x%x", __func__,
+ APPL_TRACE_DEBUG("%s: use_rc: %d, wait: 0x%x role: 0x%x", __func__,
p_scb->use_rc, p_scb->wait, p_scb->role);
if ((p_scb->wait & BTA_AV_WAIT_ROLE_SW_BITS) &&
(p_scb->q_tag == BTA_AV_Q_TAG_START)) {
@@ -3021,7 +2991,7 @@
return;
}
- if (p_scb->use_rc == true || (p_scb->role & BTA_AV_ROLE_AD_ACP)) {
+ if (p_scb->use_rc || (p_scb->role & BTA_AV_ROLE_AD_ACP)) {
if (bta_av_cb.disc) {
/* AVRC discover db is in use */
if (p_scb->rc_handle == BTA_AV_RC_HANDLE_NONE) {
@@ -3035,7 +3005,13 @@
}
} else {
/* use main SM for AVRC SDP activities */
- bta_av_rc_disc((uint8_t)(p_scb->hdi + 1));
+ if (is_new_avrcp_enabled()) {
+ APPL_TRACE_WARNING("%s: Using the new AVRCP Profile", __func__);
+ bluetooth::avrcp::AvrcpService::Get()->ConnectDevice(
+ p_scb->PeerAddress());
+ } else {
+ bta_av_rc_disc((uint8_t)(p_scb->hdi + 1));
+ }
}
} else {
if (BTA_AV_RC_HANDLE_NONE != p_scb->rc_handle) {
@@ -3059,6 +3035,9 @@
void bta_av_open_at_inc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
memcpy(&(p_scb->open_api), &(p_data->api_open), sizeof(tBTA_AV_API_OPEN));
+ APPL_TRACE_DEBUG("%s: peer %s coll_mask:0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->coll_mask);
+
if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) {
p_scb->coll_mask |= BTA_AV_COLL_API_CALLED;
@@ -3073,11 +3052,71 @@
tBTA_AV_API_OPEN* p_buf =
(tBTA_AV_API_OPEN*)osi_malloc(sizeof(tBTA_AV_API_OPEN));
memcpy(p_buf, &(p_scb->open_api), sizeof(tBTA_AV_API_OPEN));
- p_scb->skip_sdp = true;
bta_sys_sendmsg(p_buf);
}
}
+void offload_vendor_callback(tBTM_VSC_CMPL* param) {
+ uint8_t status = 0;
+ uint8_t sub_opcode = 0;
+ if (param->param_len) {
+ APPL_TRACE_DEBUG("%s: param_len = %d status = %d", __func__,
+ param->param_len, param->p_param_buf[0]);
+ status = param->p_param_buf[0];
+ }
+ if (status == 0) {
+ sub_opcode = param->p_param_buf[1];
+ APPL_TRACE_DEBUG("%s: subopcode = %d", __func__, sub_opcode);
+ switch (sub_opcode) {
+ case VS_HCI_A2DP_OFFLOAD_STOP:
+ APPL_TRACE_DEBUG("%s: VS_HCI_STOP_A2DP_MEDIA successful", __func__);
+ break;
+ case VS_HCI_A2DP_OFFLOAD_START:
+ (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV*)&status);
+ break;
+ default:
+ break;
+ }
+ } else {
+ APPL_TRACE_DEBUG("%s: Offload failed for subopcode= %d", __func__,
+ sub_opcode);
+ if (param->opcode != VS_HCI_A2DP_OFFLOAD_STOP)
+ (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV*)&status);
+ }
+}
+
+void bta_av_vendor_offload_start(tBTA_AV_SCB* p_scb,
+ tBT_A2DP_OFFLOAD* offload_start) {
+ uint8_t param[sizeof(tBT_A2DP_OFFLOAD)];
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ uint8_t* p_param = param;
+ *p_param++ = VS_HCI_A2DP_OFFLOAD_START;
+
+ UINT32_TO_STREAM(p_param, offload_start->codec_type);
+ UINT16_TO_STREAM(p_param, offload_start->max_latency);
+ UINT16_TO_STREAM(p_param, offload_start->scms_t_enable);
+ UINT32_TO_STREAM(p_param, offload_start->sample_rate);
+ UINT8_TO_STREAM(p_param, offload_start->bits_per_sample);
+ UINT8_TO_STREAM(p_param, offload_start->ch_mode);
+ UINT32_TO_STREAM(p_param, offload_start->encoded_audio_bitrate);
+ UINT16_TO_STREAM(p_param, offload_start->acl_hdl);
+ UINT16_TO_STREAM(p_param, offload_start->l2c_rcid);
+ UINT16_TO_STREAM(p_param, offload_start->mtu);
+ ARRAY_TO_STREAM(p_param, offload_start->codec_info,
+ (int8_t)sizeof(offload_start->codec_info));
+ p_scb->offload_started = true;
+ BTM_VendorSpecificCommand(HCI_CONTROLLER_A2DP_OPCODE_OCF, p_param - param,
+ param, offload_vendor_callback);
+}
+
+void bta_av_vendor_offload_stop() {
+ uint8_t param[sizeof(tBT_A2DP_OFFLOAD)];
+ APPL_TRACE_DEBUG("%s", __func__);
+ param[0] = VS_HCI_A2DP_OFFLOAD_STOP;
+ BTM_VendorSpecificCommand(HCI_CONTROLLER_A2DP_OPCODE_OCF, 1, param,
+ offload_vendor_callback);
+}
/*******************************************************************************
*
* Function bta_av_offload_req
@@ -3091,58 +3130,59 @@
void bta_av_offload_req(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
tBTA_AV_STATUS status = BTA_AV_FAIL_RESOURCES;
+ tBT_A2DP_OFFLOAD offload_start;
APPL_TRACE_DEBUG("%s: stream %s, audio channels open %d", __func__,
p_scb->started ? "STARTED" : "STOPPED",
bta_av_cb.audio_open_cnt);
-
/* Check if stream has already been started. */
/* Support offload if only one audio source stream is open. */
if (p_scb->started != true) {
status = BTA_AV_FAIL_STREAM;
+ } else {
+ bta_av_offload_codec_builder(p_scb, &offload_start);
+ bta_av_vendor_offload_start(p_scb, &offload_start);
+ return;
}
-
- /* TODO(eisenbach): RE-IMPLEMENT USING VSC OR HAL EXTENSION
- uint16_t mtu = bta_av_chk_mtu(p_scb, p_scb->stream_mtu);
- else if (bta_av_cb.audio_open_cnt == 1 &&
- p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC &&
- p_scb->chnl == BTA_AV_CHNL_AUDIO) {
- bt_vendor_op_a2dp_offload_t a2dp_offload_start;
-
- if (L2CA_GetConnectionConfig(
- p_scb->l2c_cid, &a2dp_offload_start.acl_data_size,
- &a2dp_offload_start.remote_cid, &a2dp_offload_start.lm_handle)) {
- APPL_TRACE_DEBUG("%s: l2cmtu %d lcid 0x%02X rcid 0x%02X lm_handle
- 0x%02X",
- __func__, a2dp_offload_start.acl_data_size,
- p_scb->l2c_cid, a2dp_offload_start.remote_cid,
- a2dp_offload_start.lm_handle);
-
- a2dp_offload_start.bta_av_handle = p_scb->hndl;
- a2dp_offload_start.xmit_quota = BTA_AV_A2DP_OFFLOAD_XMIT_QUOTA;
- a2dp_offload_start.stream_mtu =
- (mtu < p_scb->stream_mtu) ? mtu : p_scb->stream_mtu;
- a2dp_offload_start.local_cid = p_scb->l2c_cid;
- a2dp_offload_start.is_flushable = true;
- a2dp_offload_start.stream_source =
- ((uint32_t)(p_scb->cfg.codec_info[1] | p_scb->cfg.codec_info[2]));
-
- memcpy(a2dp_offload_start.codec_info, p_scb->cfg.codec_info,
- sizeof(a2dp_offload_start.codec_info));
-
- if (!vendor_get_interface()->send_command(
- (vendor_opcode_t)BT_VND_OP_A2DP_OFFLOAD_START,
- &a2dp_offload_start)) {
- status = BTA_AV_SUCCESS;
- p_scb->offload_start_pending = true;
- }
- }
- }
- */
if (status != BTA_AV_SUCCESS) {
tBTA_AV bta_av_data;
bta_av_data.status = status;
(*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, &bta_av_data);
}
+ /* TODO(eisenbach): RE-IMPLEMENT USING VSC OR HAL EXTENSION
+ else if (bta_av_cb.audio_open_cnt == 1 &&
+ p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC &&
+ p_scb->chnl == BTA_AV_CHNL_AUDIO) {
+ bt_vendor_op_a2dp_offload_t a2dp_offload_start;
+
+ if (L2CA_GetConnectionConfig(
+ p_scb->l2c_cid, &a2dp_offload_start.acl_data_size,
+ &a2dp_offload_start.remote_cid, &a2dp_offload_start.lm_handle)) {
+ APPL_TRACE_DEBUG("%s: l2cmtu %d lcid 0x%02X rcid 0x%02X lm_handle
+ 0x%02X",
+ __func__, a2dp_offload_start.acl_data_size,
+ p_scb->l2c_cid, a2dp_offload_start.remote_cid,
+ a2dp_offload_start.lm_handle);
+
+ a2dp_offload_start.bta_av_handle = p_scb->hndl;
+ a2dp_offload_start.xmit_quota = BTA_AV_A2DP_OFFLOAD_XMIT_QUOTA;
+ a2dp_offload_start.stream_mtu = p_scb->stream_mtu;
+ a2dp_offload_start.local_cid = p_scb->l2c_cid;
+ a2dp_offload_start.is_flushable = true;
+ a2dp_offload_start.stream_source =
+ ((uint32_t)(p_scb->cfg.codec_info[1] | p_scb->cfg.codec_info[2]));
+
+ memcpy(a2dp_offload_start.codec_info, p_scb->cfg.codec_info,
+ sizeof(a2dp_offload_start.codec_info));
+
+ if (!vendor_get_interface()->send_command(
+ (vendor_opcode_t)BT_VND_OP_A2DP_OFFLOAD_START,
+ &a2dp_offload_start)) {
+ status = BTA_AV_SUCCESS;
+ p_scb->offload_start_pending = true;
+ }
+ }
+ }
+ */
}
/*******************************************************************************
@@ -3172,3 +3212,85 @@
bta_av_data.status = status;
(*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, &bta_av_data);
}
+
+static void bta_av_offload_codec_builder(tBTA_AV_SCB* p_scb,
+ tBT_A2DP_OFFLOAD* p_a2dp_offload) {
+ A2dpCodecConfig* CodecConfig = bta_av_get_a2dp_current_codec();
+ btav_a2dp_codec_index_t codec_index =
+ A2DP_SourceCodecIndex(p_scb->cfg.codec_info);
+ uint32_t codec_type = 0;
+ uint16_t mtu = p_scb->stream_mtu;
+ APPL_TRACE_DEBUG("%s:codec_index = %d", __func__, codec_index);
+ switch (codec_index) {
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
+ codec_type = BTA_AV_CODEC_TYPE_SBC;
+ if (A2DP_GetMaxBitpoolSbc(p_scb->cfg.codec_info) <=
+ BTIF_A2DP_MAX_BITPOOL_MQ) {
+ APPL_TRACE_WARNING("%s: Restricting streaming MTU size for MQ Bitpool",
+ __func__);
+ mtu = MAX_2MBPS_AVDTP_MTU;
+ }
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
+ codec_type = BTA_AV_CODEC_TYPE_AAC;
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
+ codec_type = BTA_AV_CODEC_TYPE_APTX;
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
+ codec_type = BTA_AV_CODEC_TYPE_APTXHD;
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
+ codec_type = BTA_AV_CODEC_TYPE_LDAC;
+ break;
+ default:
+ APPL_TRACE_ERROR("%s: Unknown Codec type ", __func__);
+ return;
+ }
+ if (mtu > BTA_AV_MAX_A2DP_MTU) mtu = BTA_AV_MAX_A2DP_MTU;
+ p_a2dp_offload->codec_type = codec_type;
+ p_a2dp_offload->max_latency = 0;
+ p_a2dp_offload->mtu = mtu;
+ p_a2dp_offload->acl_hdl =
+ BTM_GetHCIConnHandle(p_scb->PeerAddress(), BT_TRANSPORT_BR_EDR);
+ p_a2dp_offload->scms_t_enable =
+ p_scb->p_cos->cp_is_active(p_scb->PeerAddress());
+ APPL_TRACE_DEBUG("%s: scms_t_enable =%d", __func__,
+ p_a2dp_offload->scms_t_enable);
+
+ switch (A2DP_GetTrackSampleRate(p_scb->cfg.codec_info)) {
+ case 44100:
+ p_a2dp_offload->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+ break;
+ case 48000:
+ p_a2dp_offload->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+ break;
+ case 88200:
+ p_a2dp_offload->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
+ break;
+ case 96000:
+ p_a2dp_offload->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
+ break;
+ }
+ if (L2CA_GetIdentifiers(p_scb->l2c_cid, &p_a2dp_offload->l2c_rcid, NULL) ==
+ false) {
+ APPL_TRACE_ERROR("%s: Failed to fetch l2c rcid", __func__);
+ return;
+ }
+ switch (CodecConfig->getAudioBitsPerSample()) {
+ case 16:
+ p_a2dp_offload->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
+ break;
+ case 24:
+ p_a2dp_offload->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24;
+ break;
+ case 32:
+ p_a2dp_offload->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32;
+ break;
+ }
+ p_a2dp_offload->ch_mode = A2DP_GetTrackChannelCount(p_scb->cfg.codec_info);
+ p_a2dp_offload->encoded_audio_bitrate = CodecConfig->getTrackBitRate();
+ if (!CodecConfig->getCodecSpecificConfig(p_a2dp_offload)) {
+ APPL_TRACE_ERROR("%s: not a valid codec info", __func__);
+ }
+}
diff --git a/bta/av/bta_av_act.cc b/bta/av/bta_av_act.cc
index 4125b6c..ad3bf3d 100644
--- a/bta/av/bta_av_act.cc
+++ b/bta/av/bta_av_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2016 Broadcom Corporation
+ * Copyright 2004-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
#include <string.h>
#include "avdt_api.h"
+#include "avrcp_service.h"
#include "bta_av_api.h"
#include "bta_av_int.h"
#include "l2c_api.h"
@@ -109,7 +110,7 @@
p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
}
if (p_scb) {
- APPL_TRACE_DEBUG("bta_av_del_rc shdl:%d, srch:%d rc_handle:%d",
+ APPL_TRACE_DEBUG("%s: shdl:%d, srch:%d rc_handle:%d", __func__,
p_rcb->shdl, p_scb->rc_handle, p_rcb->handle);
if (p_scb->rc_handle == p_rcb->handle)
p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;
@@ -120,10 +121,9 @@
}
}
- APPL_TRACE_EVENT(
- "bta_av_del_rc handle: %d status=0x%x, rc_acp_handle:%d, idx:%d",
- p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle,
- bta_av_cb.rc_acp_idx);
+ APPL_TRACE_EVENT("%s: handle: %d status=0x%x, rc_acp_handle:%d, idx:%d",
+ __func__, p_rcb->handle, p_rcb->status,
+ bta_av_cb.rc_acp_handle, bta_av_cb.rc_acp_idx);
rc_handle = p_rcb->handle;
if (!(p_rcb->status & BTA_AV_RC_CONN_MASK) ||
((p_rcb->status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT)) {
@@ -137,8 +137,9 @@
if (rc_handle == bta_av_cb.rc_acp_handle)
bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE;
APPL_TRACE_EVENT(
- "end del_rc handle: %d status=0x%x, rc_acp_handle:%d, lidx:%d",
- p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle, p_rcb->lidx);
+ "%s: end del_rc handle: %d status=0x%x, rc_acp_handle:%d, lidx:%d",
+ __func__, p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle,
+ p_rcb->lidx);
}
}
@@ -155,7 +156,7 @@
int i;
for (i = 0; i < BTA_AV_NUM_RCB; i++) {
- if ((p_cb->disabling == true) || (bta_av_cb.rcb[i].shdl != 0))
+ if ((p_cb->disabling) || (bta_av_cb.rcb[i].shdl != 0))
bta_av_del_rc(&bta_av_cb.rcb[i]);
}
}
@@ -207,7 +208,7 @@
const RawAddress* peer_addr) {
uint16_t msg_event = 0;
- APPL_TRACE_EVENT("%s handle: %d event=0x%x", __func__, handle, event);
+ APPL_TRACE_EVENT("%s: handle: %d event=0x%x", __func__, handle, event);
if (event == AVRC_OPEN_IND_EVT) {
/* save handle of opened connection
bta_av_cb.rc_handle = handle;*/
@@ -245,7 +246,7 @@
uint8_t* p_data_src = NULL;
uint16_t data_len = 0;
- APPL_TRACE_DEBUG("%s handle: %u opcode=0x%x", __func__, handle, opcode);
+ APPL_TRACE_DEBUG("%s: handle: %u opcode=0x%x", __func__, handle, opcode);
/* Copy avrc packet into BTA message buffer (for sending to BTA state machine)
*/
@@ -303,6 +304,12 @@
******************************************************************************/
uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl,
uint8_t lidx) {
+ if (is_new_avrcp_enabled()) {
+ APPL_TRACE_WARNING("%s: Skipping RC creation for the old AVRCP profile",
+ __func__);
+ return BTA_AV_RC_HANDLE_NONE;
+ }
+
tAVRC_CONN_CB ccb;
RawAddress bda = RawAddress::kAny;
uint8_t status = BTA_AV_RC_ROLE_ACP;
@@ -312,18 +319,18 @@
tBTA_AV_RCB* p_rcb;
if (role == AVCT_INT) {
- bda = p_scb->peer_addr;
+ bda = p_scb->PeerAddress();
status = BTA_AV_RC_ROLE_INT;
} else {
p_rcb = bta_av_get_rcb_by_shdl(shdl);
if (p_rcb != NULL) {
- APPL_TRACE_ERROR("bta_av_rc_create ACP handle exist for shdl:%d", shdl);
+ APPL_TRACE_ERROR("%s: ACP handle exist for shdl:%d", __func__, shdl);
return p_rcb->handle;
}
}
- ccb.p_ctrl_cback = bta_av_rc_ctrl_cback;
- ccb.p_msg_cback = bta_av_rc_msg_cback;
+ ccb.ctrl_cback = base::Bind(bta_av_rc_ctrl_cback);
+ ccb.msg_cback = base::Bind(bta_av_rc_msg_cback);
ccb.company_id = p_bta_av_cfg->company_id;
ccb.conn = role;
/* note: BTA_AV_FEAT_RCTG = AVRC_CT_TARGET, BTA_AV_FEAT_RCCT = AVRC_CT_CONTROL
@@ -338,7 +345,7 @@
p_rcb = &p_cb->rcb[i];
if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE) {
- APPL_TRACE_ERROR("bta_av_rc_create found duplicated handle:%d", rc_handle);
+ APPL_TRACE_ERROR("%s: found duplicated handle:%d", __func__, rc_handle);
}
p_rcb->handle = rc_handle;
@@ -350,12 +357,12 @@
/* this LIDX is reserved for the AVRCP ACP connection */
p_cb->rc_acp_handle = p_rcb->handle;
p_cb->rc_acp_idx = (i + 1);
- APPL_TRACE_DEBUG("rc_acp_handle:%d idx:%d", p_cb->rc_acp_handle,
- p_cb->rc_acp_idx);
+ APPL_TRACE_DEBUG("%s: rc_acp_handle:%d idx:%d", __func__,
+ p_cb->rc_acp_handle, p_cb->rc_acp_idx);
}
APPL_TRACE_DEBUG(
- "create %d, role: %d, shdl:%d, rc_handle:%d, lidx:%d, status:0x%x", i,
- role, shdl, p_rcb->handle, lidx, p_rcb->status);
+ "%s: create %d, role: %d, shdl:%d, rc_handle:%d, lidx:%d, status:0x%x",
+ __func__, i, role, shdl, p_rcb->handle, lidx, p_rcb->status);
return rc_handle;
}
@@ -366,12 +373,12 @@
*
* Description Check if it is Group Navigation Msg for Metadata
*
- * Returns BTA_AV_RSP_ACCEPT or BTA_AV_RSP_NOT_IMPL.
+ * Returns AVRC_RSP_ACCEPT or AVRC_RSP_NOT_IMPL
*
******************************************************************************/
static tBTA_AV_CODE bta_av_group_navi_supported(uint8_t len, uint8_t* p_data,
bool is_inquiry) {
- tBTA_AV_CODE ret = BTA_AV_RSP_NOT_IMPL;
+ tBTA_AV_CODE ret = AVRC_RSP_NOT_IMPL;
uint8_t* p_ptr = p_data;
uint16_t u16;
uint32_t u32;
@@ -382,12 +389,12 @@
if (u32 == AVRC_CO_METADATA) {
if (is_inquiry) {
- if (u16 <= AVRC_PDU_PREV_GROUP) ret = BTA_AV_RSP_IMPL_STBL;
+ if (u16 <= AVRC_PDU_PREV_GROUP) ret = AVRC_RSP_IMPL_STBL;
} else {
if (u16 <= AVRC_PDU_PREV_GROUP)
- ret = BTA_AV_RSP_ACCEPT;
+ ret = AVRC_RSP_ACCEPT;
else
- ret = BTA_AV_RSP_REJ;
+ ret = AVRC_RSP_REJ;
}
}
}
@@ -401,24 +408,24 @@
*
* Description Check if remote control operation is supported.
*
- * Returns BTA_AV_RSP_ACCEPT of supported, BTA_AV_RSP_NOT_IMPL if not.
+ * Returns AVRC_RSP_ACCEPT of supported, AVRC_RSP_NOT_IMPL if not.
*
******************************************************************************/
static tBTA_AV_CODE bta_av_op_supported(tBTA_AV_RC rc_id, bool is_inquiry) {
- tBTA_AV_CODE ret_code = BTA_AV_RSP_NOT_IMPL;
+ tBTA_AV_CODE ret_code = AVRC_RSP_NOT_IMPL;
if (p_bta_av_rc_id) {
if (is_inquiry) {
if (p_bta_av_rc_id[rc_id >> 4] & (1 << (rc_id & 0x0F))) {
- ret_code = BTA_AV_RSP_IMPL_STBL;
+ ret_code = AVRC_RSP_IMPL_STBL;
}
} else {
if (p_bta_av_rc_id[rc_id >> 4] & (1 << (rc_id & 0x0F))) {
- ret_code = BTA_AV_RSP_ACCEPT;
- } else if ((p_bta_av_cfg->rc_pass_rsp == BTA_AV_RSP_INTERIM) &&
+ ret_code = AVRC_RSP_ACCEPT;
+ } else if ((p_bta_av_cfg->rc_pass_rsp == AVRC_RSP_INTERIM) &&
p_bta_av_rc_id_ac) {
if (p_bta_av_rc_id_ac[rc_id >> 4] & (1 << (rc_id & 0x0F))) {
- ret_code = BTA_AV_RSP_INTERIM;
+ ret_code = AVRC_RSP_INTERIM;
}
}
}
@@ -441,13 +448,15 @@
uint8_t mask;
tBTA_AV_LCB* p_lcb = NULL;
+ APPL_TRACE_DEBUG("%s: address: %s op:%d", __func__, addr.ToString().c_str(),
+ op);
for (xx = 0; xx < BTA_AV_NUM_LINKS; xx++) {
mask = 1 << xx; /* the used mask for this lcb */
if ((mask & p_cb->conn_lcb) && p_cb->lcb[xx].addr == addr) {
p_lcb = &p_cb->lcb[xx];
if (op == BTA_AV_LCB_FREE) {
p_cb->conn_lcb &= ~mask; /* clear the connect mask */
- APPL_TRACE_DEBUG("conn_lcb: 0x%x", p_cb->conn_lcb);
+ APPL_TRACE_DEBUG("%s: conn_lcb: 0x%x", __func__, p_cb->conn_lcb);
}
break;
}
@@ -477,12 +486,12 @@
/* find the SCB & stop the timer */
for (i = 0; i < BTA_AV_NUM_STRS; i++) {
p_scb = p_cb->p_scb[i];
- if (p_scb && p_scb->peer_addr == p_data->rc_conn_chg.peer_addr) {
+ if (p_scb && p_scb->PeerAddress() == p_data->rc_conn_chg.peer_addr) {
p_scb->rc_handle = p_data->rc_conn_chg.handle;
- APPL_TRACE_DEBUG("bta_av_rc_opened shdl:%d, srch %d", i + 1,
+ APPL_TRACE_DEBUG("%s: shdl:%d, srch %d", __func__, i + 1,
p_scb->rc_handle);
shdl = i + 1;
- LOG_INFO(LOG_TAG, "%s allow incoming AVRCP connections:%d", __func__,
+ LOG_INFO(LOG_TAG, "%s: allow incoming AVRCP connections:%d", __func__,
p_scb->use_rc);
alarm_cancel(p_scb->avrc_ct_timer);
disc = p_scb->hndl;
@@ -492,11 +501,11 @@
i = p_data->rc_conn_chg.handle;
if (p_cb->rcb[i].handle == BTA_AV_RC_HANDLE_NONE) {
- APPL_TRACE_ERROR("not a valid handle:%d any more", i);
+ APPL_TRACE_ERROR("%s: not a valid handle:%d any more", __func__, i);
return;
}
- APPL_TRACE_DEBUG("%s local features %d peer features %d", __func__,
+ APPL_TRACE_DEBUG("%s: local features %d peer features %d", __func__,
p_cb->features, p_cb->rcb[i].peer_features);
/* listen to browsing channel when the connection is open,
@@ -515,14 +524,14 @@
p_cb->rcb[i].lidx = tmp;
p_cb->rc_acp_handle = p_rcb->handle;
p_cb->rc_acp_idx = (p_rcb - p_cb->rcb) + 1;
- APPL_TRACE_DEBUG("switching RCB rc_acp_handle:%d idx:%d",
+ APPL_TRACE_DEBUG("%s: switching RCB rc_acp_handle:%d idx:%d", __func__,
p_cb->rc_acp_handle, p_cb->rc_acp_idx);
}
}
p_cb->rcb[i].shdl = shdl;
rc_open.rc_handle = i;
- APPL_TRACE_ERROR("bta_av_rc_opened rcb[%d] shdl:%d lidx:%d/%d", i, shdl,
+ APPL_TRACE_ERROR("%s: rcb[%d] shdl:%d lidx:%d/%d", __func__, i, shdl,
p_cb->rcb[i].lidx, p_cb->lcb[BTA_AV_NUM_LINKS].lidx);
p_cb->rcb[i].status |= BTA_AV_RC_CONN_MASK;
@@ -531,19 +540,19 @@
* update the index to the extra LCB */
p_lcb = &p_cb->lcb[BTA_AV_NUM_LINKS];
p_lcb->addr = p_data->rc_conn_chg.peer_addr;
- VLOG(1) << "rc_only bd_addr:" << p_lcb->addr;
p_lcb->lidx = BTA_AV_NUM_LINKS + 1;
p_cb->rcb[i].lidx = p_lcb->lidx;
p_lcb->conn_msk = 1;
- APPL_TRACE_ERROR("rcb[%d].lidx=%d, lcb.conn_msk=x%x", i, p_cb->rcb[i].lidx,
- p_lcb->conn_msk);
+ APPL_TRACE_ERROR("%s: bd_addr: %s rcb[%d].lidx=%d, lcb.conn_msk=x%x",
+ __func__, p_lcb->addr.ToString().c_str(), i,
+ p_cb->rcb[i].lidx, p_lcb->conn_msk);
disc = p_data->rc_conn_chg.handle | BTA_AV_CHNL_MSK;
}
rc_open.peer_addr = p_data->rc_conn_chg.peer_addr;
rc_open.peer_features = p_cb->rcb[i].peer_features;
rc_open.status = BTA_AV_SUCCESS;
- APPL_TRACE_DEBUG("%s local features:x%x peer_features:x%x", __func__,
+ APPL_TRACE_DEBUG("%s: local features:x%x peer_features:x%x", __func__,
p_cb->features, rc_open.peer_features);
if (rc_open.peer_features == 0) {
/* we have not done SDP on peer RC capabilities.
@@ -566,7 +575,7 @@
if ((p_cb->features & BTA_AV_FEAT_BROWSE) &&
(rc_open.peer_features & BTA_AV_FEAT_BROWSE) &&
((p_cb->rcb[i].status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT)) {
- APPL_TRACE_DEBUG("%s opening AVRC Browse channel", __func__);
+ APPL_TRACE_DEBUG("%s: opening AVRC Browse channel", __func__);
AVRC_OpenBrowse(p_data->rc_conn_chg.handle, AVCT_INT);
}
}
@@ -743,7 +752,6 @@
uint16_t u16;
tAVRC_MSG_VENDOR* p_vendor = &p_msg->msg.vendor;
-#if (AVRC_METADATA_INCLUDED == TRUE)
pdu = *(p_vendor->p_vendor_data);
p_rc_rsp->pdu = pdu;
*p_ctype = AVRC_RSP_REJ;
@@ -752,21 +760,22 @@
if ((AVRC_MIN_META_CMD_LEN + p_vendor->vendor_len) > AVRC_META_CMD_BUF_SIZE) {
/* reject it */
p_rc_rsp->rsp.status = AVRC_STS_BAD_PARAM;
- APPL_TRACE_ERROR("%s Invalid meta-command length: %d", __func__,
+ APPL_TRACE_ERROR("%s: Invalid meta-command length: %d", __func__,
p_vendor->vendor_len);
return 0;
}
/* Metadata messages only use PANEL sub-unit type */
if (p_vendor->hdr.subunit_type != AVRC_SUB_PANEL) {
- APPL_TRACE_DEBUG("SUBUNIT must be PANEL");
+ APPL_TRACE_DEBUG("%s: SUBUNIT must be PANEL", __func__);
/* reject it */
evt = 0;
- p_vendor->hdr.ctype = BTA_AV_RSP_NOT_IMPL;
+ p_vendor->hdr.ctype = AVRC_RSP_NOT_IMPL;
p_vendor->vendor_len = 0;
p_rc_rsp->rsp.status = AVRC_STS_BAD_PARAM;
} else if (!AVRC_IsValidAvcType(pdu, p_vendor->hdr.ctype)) {
- APPL_TRACE_DEBUG("Invalid pdu/ctype: 0x%x, %d", pdu, p_vendor->hdr.ctype);
+ APPL_TRACE_DEBUG("%s: Invalid pdu/ctype: 0x%x, %d", __func__, pdu,
+ p_vendor->hdr.ctype);
/* reject invalid message without reporting to app */
evt = 0;
p_rc_rsp->rsp.status = AVRC_STS_BAD_CMD;
@@ -795,7 +804,7 @@
memcpy(p_rc_rsp->get_caps.param.event_id,
p_bta_av_cfg->p_meta_evt_ids, p_bta_av_cfg->num_evt_ids);
} else {
- APPL_TRACE_DEBUG("Invalid capability ID: 0x%x", u8);
+ APPL_TRACE_DEBUG("%s: Invalid capability ID: 0x%x", __func__, u8);
/* reject - unknown capability ID */
p_rc_rsp->get_caps.status = AVRC_STS_BAD_PARAM;
}
@@ -809,12 +818,6 @@
break;
}
}
-#else
- APPL_TRACE_DEBUG("AVRCP 1.3 Metadata not supporteed. Reject command.");
- /* reject invalid message without reporting to app */
- evt = 0;
- p_rc_rsp->rsp.status = AVRC_STS_BAD_CMD;
-#endif
return evt;
}
@@ -835,15 +838,13 @@
tAVRC_MSG_VENDOR* p_vendor = &p_data->rc_msg.msg.vendor;
bool is_inquiry = ((p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_SPEC_INQ) ||
p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_GEN_INQ);
-#if (AVRC_METADATA_INCLUDED == TRUE)
uint8_t ctype = 0;
tAVRC_RESPONSE rc_rsp;
rc_rsp.rsp.status = BTA_AV_STS_NO_RSP;
-#endif
if (NULL == p_data) {
- APPL_TRACE_ERROR("Message from peer with no data in %s", __func__);
+ APPL_TRACE_ERROR("%s: Message from peer with no data", __func__);
return;
}
@@ -860,32 +861,30 @@
osi_property_get("bluetooth.pts.avrcp_ct.support", avrcp_ct_support,
"false");
if (p_data->rc_msg.msg.pass.op_id == AVRC_ID_VENDOR) {
- p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_NOT_IMPL;
-#if (AVRC_METADATA_INCLUDED == TRUE)
+ p_data->rc_msg.msg.hdr.ctype = AVRC_RSP_NOT_IMPL;
if (p_cb->features & BTA_AV_FEAT_METADATA)
p_data->rc_msg.msg.hdr.ctype = bta_av_group_navi_supported(
p_data->rc_msg.msg.pass.pass_len,
p_data->rc_msg.msg.pass.p_pass_data, is_inquiry);
-#endif
} else if (((p_data->rc_msg.msg.pass.op_id == AVRC_ID_VOL_UP) ||
(p_data->rc_msg.msg.pass.op_id == AVRC_ID_VOL_DOWN)) &&
!strcmp(avrcp_ct_support, "true")) {
- p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_ACCEPT;
+ p_data->rc_msg.msg.hdr.ctype = AVRC_RSP_ACCEPT;
} else {
p_data->rc_msg.msg.hdr.ctype =
bta_av_op_supported(p_data->rc_msg.msg.pass.op_id, is_inquiry);
}
- APPL_TRACE_DEBUG("ctype %d", p_data->rc_msg.msg.hdr.ctype)
+ APPL_TRACE_DEBUG("%s: ctype %d", __func__, p_data->rc_msg.msg.hdr.ctype)
/* send response */
- if (p_data->rc_msg.msg.hdr.ctype != BTA_AV_RSP_INTERIM)
+ if (p_data->rc_msg.msg.hdr.ctype != AVRC_RSP_INTERIM)
AVRC_PassRsp(p_data->rc_msg.handle, p_data->rc_msg.label,
&p_data->rc_msg.msg.pass);
/* set up for callback if supported */
- if (p_data->rc_msg.msg.hdr.ctype == BTA_AV_RSP_ACCEPT ||
- p_data->rc_msg.msg.hdr.ctype == BTA_AV_RSP_INTERIM) {
+ if (p_data->rc_msg.msg.hdr.ctype == AVRC_RSP_ACCEPT ||
+ p_data->rc_msg.msg.hdr.ctype == AVRC_RSP_INTERIM) {
evt = BTA_AV_REMOTE_CMD_EVT;
av.remote_cmd.rc_id = p_data->rc_msg.msg.pass.op_id;
av.remote_cmd.key_state = p_data->rc_msg.msg.pass.state;
@@ -910,7 +909,7 @@
(p_data->rc_msg.msg.pass.pass_len > 0)) {
av.remote_rsp.p_data =
(uint8_t*)osi_malloc(p_data->rc_msg.msg.pass.pass_len);
- APPL_TRACE_DEBUG("Vendor Unique data len = %d",
+ APPL_TRACE_DEBUG("%s: Vendor Unique data len = %d", __func__,
p_data->rc_msg.msg.pass.pass_len);
memcpy(av.remote_rsp.p_data, p_data->rc_msg.msg.pass.p_pass_data,
p_data->rc_msg.msg.pass.pass_len);
@@ -918,7 +917,7 @@
}
/* must be a bad ctype -> reject*/
else {
- p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_REJ;
+ p_data->rc_msg.msg.hdr.ctype = AVRC_RSP_REJ;
AVRC_PassRsp(p_data->rc_msg.handle, p_data->rc_msg.label,
&p_data->rc_msg.msg.pass);
}
@@ -935,38 +934,34 @@
/* if configured to support vendor specific and it's a command */
if ((p_cb->features & BTA_AV_FEAT_VENDOR) &&
p_data->rc_msg.msg.hdr.ctype <= AVRC_CMD_GEN_INQ) {
-#if (AVRC_METADATA_INCLUDED == TRUE)
if ((p_cb->features & BTA_AV_FEAT_METADATA) &&
(p_vendor->company_id == AVRC_CO_METADATA)) {
av.meta_msg.p_msg = &p_data->rc_msg.msg;
rc_rsp.rsp.status = BTA_AV_STS_NO_RSP;
evt = bta_av_proc_meta_cmd(&rc_rsp, &p_data->rc_msg, &ctype);
- } else
-#endif
+ } else {
evt = BTA_AV_VENDOR_CMD_EVT;
- }
- /* else if configured to support vendor specific and it's a response */
- else if ((p_cb->features & BTA_AV_FEAT_VENDOR) &&
- p_data->rc_msg.msg.hdr.ctype >= AVRC_RSP_NOT_IMPL) {
-#if (AVRC_METADATA_INCLUDED == TRUE)
+ }
+ } else if ((p_cb->features & BTA_AV_FEAT_VENDOR) &&
+ p_data->rc_msg.msg.hdr.ctype >= AVRC_RSP_NOT_IMPL) {
+ /* else if configured to support vendor specific and it's a response */
if ((p_cb->features & BTA_AV_FEAT_METADATA) &&
(p_vendor->company_id == AVRC_CO_METADATA)) {
av.meta_msg.p_msg = &p_data->rc_msg.msg;
evt = BTA_AV_META_MSG_EVT;
- } else
-#endif
+ } else {
evt = BTA_AV_VENDOR_RSP_EVT;
-
- }
- /* else if not configured to support vendor specific and it's a command */
- else if (!(p_cb->features & BTA_AV_FEAT_VENDOR) &&
- p_data->rc_msg.msg.hdr.ctype <= AVRC_CMD_GEN_INQ) {
+ }
+ } else if (!(p_cb->features & BTA_AV_FEAT_VENDOR) &&
+ p_data->rc_msg.msg.hdr.ctype <= AVRC_CMD_GEN_INQ) {
+ /* else if not configured to support vendor specific and it's a command */
if (p_data->rc_msg.msg.vendor.p_vendor_data[0] == AVRC_PDU_INVALID) {
/* reject it */
- p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_REJ;
+ p_data->rc_msg.msg.hdr.ctype = AVRC_RSP_REJ;
p_data->rc_msg.msg.vendor.p_vendor_data[4] = AVRC_STS_BAD_CMD;
- } else
- p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_NOT_IMPL;
+ } else {
+ p_data->rc_msg.msg.hdr.ctype = AVRC_RSP_NOT_IMPL;
+ }
AVRC_VendorRsp(p_data->rc_msg.handle, p_data->rc_msg.label,
&p_data->rc_msg.msg.vendor);
}
@@ -982,7 +977,6 @@
evt = BTA_AV_META_MSG_EVT;
}
-#if (AVRC_METADATA_INCLUDED == TRUE)
if (evt == 0 && rc_rsp.rsp.status != BTA_AV_STS_NO_RSP) {
if (!p_pkt) {
rc_rsp.rsp.opcode = p_data->rc_msg.opcode;
@@ -991,7 +985,6 @@
if (p_pkt)
AVRC_MsgReq(p_data->rc_msg.handle, p_data->rc_msg.label, ctype, p_pkt);
}
-#endif
/* call callback */
if (evt != 0) {
@@ -1019,7 +1012,7 @@
if (handle < BTA_AV_NUM_RCB) {
p_rcb = &p_cb->rcb[handle];
- APPL_TRACE_DEBUG("%s handle: %d, status=0x%x", __func__, p_rcb->handle,
+ APPL_TRACE_DEBUG("%s: handle: %d, status=0x%x", __func__, p_rcb->handle,
p_rcb->status);
if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE) {
if (p_rcb->shdl) {
@@ -1047,7 +1040,7 @@
*
******************************************************************************/
void bta_av_rc_browse_close(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) {
- APPL_TRACE_WARNING("%s empty placeholder does nothing!", __func__);
+ APPL_TRACE_WARNING("%s: empty placeholder does nothing!", __func__);
}
/*******************************************************************************
@@ -1080,54 +1073,20 @@
*
******************************************************************************/
void bta_av_stream_chg(tBTA_AV_SCB* p_scb, bool started) {
- uint8_t started_msk;
- int i;
- uint8_t* p_streams;
- bool no_streams = false;
- tBTA_AV_SCB* p_scbi;
+ uint8_t started_msk = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- started_msk = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- APPL_TRACE_DEBUG("bta_av_stream_chg started:%d started_msk:x%x chnl:x%x",
- started, started_msk, p_scb->chnl);
- if (BTA_AV_CHNL_AUDIO == p_scb->chnl)
- p_streams = &bta_av_cb.audio_streams;
- else
- p_streams = &bta_av_cb.video_streams;
+ APPL_TRACE_DEBUG("%s: peer %s started:%s started_msk:0x%x", __func__,
+ p_scb->PeerAddress().ToString().c_str(),
+ logbool(started).c_str(), started_msk);
if (started) {
+ bta_av_cb.audio_streams |= started_msk;
/* Let L2CAP know this channel is processed with high priority */
- L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_HIGH);
- (*p_streams) |= started_msk;
+ L2CA_SetAclPriority(p_scb->PeerAddress(), L2CAP_PRIORITY_HIGH);
} else {
- (*p_streams) &= ~started_msk;
- }
-
- if (!started) {
- i = 0;
- if (BTA_AV_CHNL_AUDIO == p_scb->chnl) {
- if (bta_av_cb.video_streams == 0) no_streams = true;
- } else {
- no_streams = true;
- if (bta_av_cb.audio_streams) {
- for (; i < BTA_AV_NUM_STRS; i++) {
- p_scbi = bta_av_cb.p_scb[i];
- /* scb is used and started */
- if (p_scbi && (bta_av_cb.audio_streams & BTA_AV_HNDL_TO_MSK(i)) &&
- p_scbi->peer_addr == p_scb->peer_addr) {
- no_streams = false;
- break;
- }
- }
- }
- }
-
- APPL_TRACE_DEBUG("no_streams:%d i:%d, audio_streams:x%x, video_streams:x%x",
- no_streams, i, bta_av_cb.audio_streams,
- bta_av_cb.video_streams);
- if (no_streams) {
- /* Let L2CAP know this channel is processed with low priority */
- L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_NORMAL);
- }
+ bta_av_cb.audio_streams &= ~started_msk;
+ /* Let L2CAP know this channel is processed with low priority */
+ L2CA_SetAclPriority(p_scb->PeerAddress(), L2CAP_PRIORITY_NORMAL);
}
}
@@ -1171,39 +1130,35 @@
if (bta_av_cb.rcb[i].lidx == p_lcb->lidx) {
bta_av_cb.rcb[i].shdl = index + 1;
APPL_TRACE_DEBUG(
- "conn_chg up[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i,
- bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
+ "%s: conn_chg up[%d]: %d, status=0x%x, shdl:%d, lidx:%d",
+ __func__, i, bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx);
break;
}
}
}
- if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
- old_msk = p_cb->conn_audio;
- p_cb->conn_audio |= mask;
- } else {
- old_msk = p_cb->conn_video;
- p_cb->conn_video |= mask;
- }
+ old_msk = p_cb->conn_audio;
+ p_cb->conn_audio |= mask;
if ((old_msk & mask) == 0) {
/* increase the audio open count, if not set yet */
bta_av_cb.audio_open_cnt++;
}
- APPL_TRACE_DEBUG("rc_acp_handle:%d rc_acp_idx:%d", p_cb->rc_acp_handle,
- p_cb->rc_acp_idx);
+ APPL_TRACE_DEBUG("%s: rc_acp_handle:%d rc_acp_idx:%d", __func__,
+ p_cb->rc_acp_handle, p_cb->rc_acp_idx);
/* check if the AVRCP ACP channel is already connected */
if (p_lcb && p_cb->rc_acp_handle != BTA_AV_RC_HANDLE_NONE &&
p_cb->rc_acp_idx) {
p_lcb_rc = &p_cb->lcb[BTA_AV_NUM_LINKS];
APPL_TRACE_DEBUG(
- "rc_acp is connected && conn_chg on same addr "
+ "%s: rc_acp is connected && conn_chg on same addr "
"p_lcb_rc->conn_msk:x%x",
- p_lcb_rc->conn_msk);
+ __func__, p_lcb_rc->conn_msk);
/* check if the RC is connected to the scb addr */
- VLOG(1) << "p_lcb_rc->addr: " << p_lcb_rc->addr
- << " conn_chg.peer_addr:" << p_data->conn_chg.peer_addr;
+ LOG_INFO(LOG_TAG, "%s: p_lcb_rc->addr: %s conn_chg.peer_addr: %s",
+ __func__, p_lcb_rc->addr.ToString().c_str(),
+ p_data->conn_chg.peer_addr.ToString().c_str());
if (p_lcb_rc->conn_msk &&
p_lcb_rc->addr == p_data->conn_chg.peer_addr) {
@@ -1214,23 +1169,25 @@
p_scb->rc_handle = p_cb->rc_acp_handle;
p_rcb = &p_cb->rcb[p_cb->rc_acp_idx - 1];
p_rcb->shdl = bta_av_get_shdl(p_scb);
- APPL_TRACE_DEBUG("update rc_acp shdl:%d/%d srch:%d", index + 1,
- p_rcb->shdl, p_scb->rc_handle);
+ APPL_TRACE_DEBUG("%s: update rc_acp shdl:%d/%d srch:%d", __func__,
+ index + 1, p_rcb->shdl, p_scb->rc_handle);
p_rcb2 = bta_av_get_rcb_by_shdl(p_rcb->shdl);
if (p_rcb2) {
/* found the RCB that was created to associated with this SCB */
p_cb->rc_acp_handle = p_rcb2->handle;
p_cb->rc_acp_idx = (p_rcb2 - p_cb->rcb) + 1;
- APPL_TRACE_DEBUG("new rc_acp_handle:%d, idx:%d",
+ APPL_TRACE_DEBUG("%s: new rc_acp_handle:%d, idx:%d", __func__,
p_cb->rc_acp_handle, p_cb->rc_acp_idx);
p_rcb2->lidx = (BTA_AV_NUM_LINKS + 1);
- APPL_TRACE_DEBUG("rc2 handle:%d lidx:%d/%d", p_rcb2->handle,
- p_rcb2->lidx, p_cb->lcb[p_rcb2->lidx - 1].lidx);
+ APPL_TRACE_DEBUG("%s: rc2 handle:%d lidx:%d/%d", __func__,
+ p_rcb2->handle, p_rcb2->lidx,
+ p_cb->lcb[p_rcb2->lidx - 1].lidx);
}
p_rcb->lidx = p_lcb->lidx;
- APPL_TRACE_DEBUG("rc handle:%d lidx:%d/%d", p_rcb->handle,
- p_rcb->lidx, p_cb->lcb[p_rcb->lidx - 1].lidx);
+ APPL_TRACE_DEBUG("%s: rc handle:%d lidx:%d/%d", __func__,
+ p_rcb->handle, p_rcb->lidx,
+ p_cb->lcb[p_rcb->lidx - 1].lidx);
}
}
}
@@ -1242,12 +1199,9 @@
/* clear the conned mask for this channel */
p_cb->conn_audio &= ~mask;
- p_cb->conn_video &= ~mask;
if (p_scb) {
- /* the stream is closed.
- * clear the peer address, so it would not mess up the AVRCP for the next
- * round of operation */
- p_scb->peer_addr = RawAddress::kEmpty;
+ // The stream is closed. Clear the state.
+ p_scb->OnDisconnected();
if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
if (p_lcb) {
p_lcb->conn_msk &= ~conn_msk;
@@ -1262,11 +1216,12 @@
}
}
- APPL_TRACE_DEBUG("bta_av_conn_chg shdl:%d", index + 1);
+ APPL_TRACE_DEBUG("%s: shdl:%d", __func__, index + 1);
for (i = 0; i < BTA_AV_NUM_RCB; i++) {
- APPL_TRACE_DEBUG("conn_chg dn[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i,
- bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
- bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx);
+ APPL_TRACE_DEBUG("%s: conn_chg dn[%d]: %d, status=0x%x, shdl:%d, lidx:%d",
+ __func__, i, bta_av_cb.rcb[i].handle,
+ bta_av_cb.rcb[i].status, bta_av_cb.rcb[i].shdl,
+ bta_av_cb.rcb[i].lidx);
if (bta_av_cb.rcb[i].shdl == index + 1) {
bta_av_del_rc(&bta_av_cb.rcb[i]);
/* since the connection is already down and info was removed, clean
@@ -1276,7 +1231,7 @@
}
}
- if (p_cb->conn_audio == 0 && p_cb->conn_video == 0) {
+ if (p_cb->conn_audio == 0) {
/* if both channels are not connected,
* close all RC channels */
bta_av_close_all_rc(p_cb);
@@ -1289,10 +1244,10 @@
}
APPL_TRACE_DEBUG(
- "bta_av_conn_chg audio:%x video:%x up:%d conn_msk:0x%x chk_restore:%d "
+ "%s: audio:%x up:%d conn_msk:0x%x chk_restore:%d "
"audio_open_cnt:%d",
- p_cb->conn_audio, p_cb->conn_video, p_data->conn_chg.is_up, conn_msk,
- chk_restore, p_cb->audio_open_cnt);
+ __func__, p_cb->conn_audio, p_data->conn_chg.is_up, conn_msk, chk_restore,
+ p_cb->audio_open_cnt);
if (chk_restore) {
if (p_cb->audio_open_cnt == 1) {
@@ -1312,7 +1267,7 @@
if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
p_scbi->co_started = bta_av_cb.audio_open_cnt;
L2CA_SetFlushTimeout(
- p_scbi->peer_addr,
+ p_scbi->PeerAddress(),
p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1]);
}
}
@@ -1369,6 +1324,56 @@
alarm_cancel(bta_av_cb.link_signalling_timer);
}
+/**
+ * Find the index for the free LCB entry to use.
+ *
+ * The selection order is:
+ * (1) Find the index if there is already SCB entry for the peer address
+ * (2) If there is no SCB entry for the peer address, find the first
+ * SCB entry that is not assigned.
+ *
+ * @param peer_address the peer address to use
+ * @return the index for the free LCB entry to use or BTA_AV_NUM_LINKS
+ * if no entry is found
+ */
+static uint8_t bta_av_find_lcb_index_by_scb_and_address(
+ const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer_address: %s conn_lcb: 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_cb.conn_lcb);
+
+ // Find the index if there is already SCB entry for the peer address
+ for (uint8_t index = 0; index < BTA_AV_NUM_LINKS; index++) {
+ uint8_t mask = 1 << index;
+ if (mask & bta_av_cb.conn_lcb) {
+ continue;
+ }
+ tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[index];
+ if (p_scb == nullptr) {
+ continue;
+ }
+ if (p_scb->PeerAddress() == peer_address) {
+ return index;
+ }
+ }
+
+ // Find the first SCB entry that is not assigned.
+ for (uint8_t index = 0; index < BTA_AV_NUM_LINKS; index++) {
+ uint8_t mask = 1 << index;
+ if (mask & bta_av_cb.conn_lcb) {
+ continue;
+ }
+ tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[index];
+ if (p_scb == nullptr) {
+ continue;
+ }
+ if (!p_scb->IsAssigned()) {
+ return index;
+ }
+ }
+
+ return BTA_AV_NUM_LINKS;
+}
+
/*******************************************************************************
*
* Function bta_av_sig_chg
@@ -1385,67 +1390,67 @@
uint8_t mask;
tBTA_AV_LCB* p_lcb = NULL;
- APPL_TRACE_DEBUG("bta_av_sig_chg event: %d", event);
+ APPL_TRACE_DEBUG("%s: event: %d", __func__, event);
if (event == AVDT_CONNECT_IND_EVT) {
+ APPL_TRACE_DEBUG("%s: AVDT_CONNECT_IND_EVT: peer %s", __func__,
+ p_data->str_msg.bd_addr.ToString().c_str());
+
p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FIND);
if (!p_lcb) {
/* if the address does not have an LCB yet, alloc one */
- for (xx = 0; xx < BTA_AV_NUM_LINKS; xx++) {
- mask = 1 << xx;
- APPL_TRACE_DEBUG("conn_lcb: 0x%x", p_cb->conn_lcb);
- /* look for a p_lcb with its p_scb registered */
- if ((!(mask & p_cb->conn_lcb)) && (p_cb->p_scb[xx] != NULL)) {
- p_lcb = &p_cb->lcb[xx];
- p_lcb->lidx = xx + 1;
- p_lcb->addr = p_data->str_msg.bd_addr;
- p_lcb->conn_msk = 0; /* clear the connect mask */
- /* start listening when the signal channel is open */
- if (p_cb->features & BTA_AV_FEAT_RCTG) {
- bta_av_rc_create(p_cb, AVCT_ACP, 0, p_lcb->lidx);
- }
- /* this entry is not used yet. */
- p_cb->conn_lcb |= mask; /* mark it as used */
- APPL_TRACE_DEBUG("start sig timer %d", p_data->hdr.offset);
- if (p_data->hdr.offset == AVDT_ACP) {
- APPL_TRACE_DEBUG("Incoming L2CAP acquired, set state as incoming",
- NULL);
- p_cb->p_scb[xx]->peer_addr = p_data->str_msg.bd_addr;
- p_cb->p_scb[xx]->use_rc =
- true; /* allowing RC for incoming connection */
- bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_ACP_CONNECT_EVT, p_data);
-
- /* The Pending Event should be sent as soon as the L2CAP signalling
- * channel
- * is set up, which is NOW. Earlier this was done only after
- * BTA_AV_SIGNALLING_TIMEOUT_MS.
- * The following function shall send the event and start the
- * recurring timer
- */
- bta_av_signalling_timer(NULL);
-
- APPL_TRACE_DEBUG("%s: Re-start timer for AVDTP service", __func__);
- bta_sys_conn_open(BTA_ID_AV, p_cb->p_scb[xx]->app_id,
- p_cb->p_scb[xx]->peer_addr);
- /* Possible collision : need to avoid outgoing processing while the
- * timer is running */
- p_cb->p_scb[xx]->coll_mask = BTA_AV_COLL_INC_TMR;
- alarm_set_on_mloop(p_cb->accept_signalling_timer,
- BTA_AV_ACCEPT_SIGNALLING_TIMEOUT_MS,
- bta_av_accept_signalling_timer_cback,
- UINT_TO_PTR(xx));
- }
- break;
- }
- }
+ xx = bta_av_find_lcb_index_by_scb_and_address(p_data->str_msg.bd_addr);
/* check if we found something */
- if (xx == BTA_AV_NUM_LINKS) {
+ if (xx >= BTA_AV_NUM_LINKS) {
/* We do not have scb for this avdt connection. */
/* Silently close the connection. */
- APPL_TRACE_ERROR("av scb not available for avdt connection");
+ APPL_TRACE_ERROR("%s: av scb not available for avdt connection for %s",
+ __func__, p_data->str_msg.bd_addr.ToString().c_str());
AVDT_DisconnectReq(p_data->str_msg.bd_addr, NULL);
return;
}
+ LOG_INFO(LOG_TAG,
+ "%s: AVDT_CONNECT_IND_EVT: peer %s selected lcb_index %d",
+ __func__, p_data->str_msg.bd_addr.ToString().c_str(), xx);
+
+ tBTA_AV_SCB* p_scb = p_cb->p_scb[xx];
+ mask = 1 << xx;
+ p_lcb = &p_cb->lcb[xx];
+ p_lcb->lidx = xx + 1;
+ p_lcb->addr = p_data->str_msg.bd_addr;
+ p_lcb->conn_msk = 0; /* clear the connect mask */
+ /* start listening when the signal channel is open */
+ if (p_cb->features & BTA_AV_FEAT_RCTG) {
+ bta_av_rc_create(p_cb, AVCT_ACP, 0, p_lcb->lidx);
+ }
+ /* this entry is not used yet. */
+ p_cb->conn_lcb |= mask; /* mark it as used */
+ APPL_TRACE_DEBUG("%s: start sig timer %d", __func__, p_data->hdr.offset);
+ if (p_data->hdr.offset == AVDT_ACP) {
+ APPL_TRACE_DEBUG("%s: Incoming L2CAP acquired, set state as incoming",
+ __func__);
+ p_scb->OnConnected(p_data->str_msg.bd_addr);
+ p_scb->use_rc = true; /* allowing RC for incoming connection */
+ bta_av_ssm_execute(p_scb, BTA_AV_ACP_CONNECT_EVT, p_data);
+
+ /* The Pending Event should be sent as soon as the L2CAP signalling
+ * channel
+ * is set up, which is NOW. Earlier this was done only after
+ * BTA_AV_SIGNALLING_TIMEOUT_MS.
+ * The following function shall send the event and start the
+ * recurring timer
+ */
+ bta_av_signalling_timer(NULL);
+
+ APPL_TRACE_DEBUG("%s: Re-start timer for AVDTP service", __func__);
+ bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
+ /* Possible collision : need to avoid outgoing processing while the
+ * timer is running */
+ p_scb->coll_mask = BTA_AV_COLL_INC_TMR;
+ alarm_set_on_mloop(
+ p_cb->accept_signalling_timer, BTA_AV_ACCEPT_SIGNALLING_TIMEOUT_MS,
+ bta_av_accept_signalling_timer_cback, UINT_TO_PTR(xx));
+ }
}
}
#if (BTA_AR_INCLUDED == TRUE)
@@ -1460,22 +1465,22 @@
p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FREE);
if (p_lcb && (p_lcb->conn_msk || bta_av_cb.conn_lcb)) {
- APPL_TRACE_DEBUG("conn_msk: 0x%x", p_lcb->conn_msk);
+ APPL_TRACE_DEBUG("%s: conn_msk: 0x%x", __func__, p_lcb->conn_msk);
/* clean up ssm */
for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
if (p_cb->p_scb[xx] &&
- p_cb->p_scb[xx]->peer_addr == p_data->str_msg.bd_addr) {
+ p_cb->p_scb[xx]->PeerAddress() == p_data->str_msg.bd_addr) {
APPL_TRACE_DEBUG("%s: Closing timer for AVDTP service", __func__);
bta_sys_conn_close(BTA_ID_AV, p_cb->p_scb[xx]->app_id,
- p_cb->p_scb[xx]->peer_addr);
+ p_cb->p_scb[xx]->PeerAddress());
}
mask = 1 << (xx + 1);
if (((mask & p_lcb->conn_msk) || bta_av_cb.conn_lcb) &&
p_cb->p_scb[xx] &&
- p_cb->p_scb[xx]->peer_addr == p_data->str_msg.bd_addr) {
+ p_cb->p_scb[xx]->PeerAddress() == p_data->str_msg.bd_addr) {
APPL_TRACE_WARNING("%s: Sending AVDT_DISCONNECT_EVT peer_addr=%s",
__func__,
- p_cb->p_scb[xx]->peer_addr.ToString().c_str());
+ p_cb->p_scb[xx]->PeerAddress().ToString().c_str());
bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_AVDT_DISCONNECT_EVT, NULL);
}
}
@@ -1502,12 +1507,16 @@
uint8_t mask;
tBTA_AV_LCB* p_lcb = NULL;
- APPL_TRACE_DEBUG("%s", __func__);
+ APPL_TRACE_DEBUG("%s: conn_lcb=0x%x", __func__, p_cb->conn_lcb);
for (xx = 0; xx < BTA_AV_NUM_LINKS; xx++) {
+ p_lcb = &p_cb->lcb[xx];
mask = 1 << xx;
+ APPL_TRACE_DEBUG(
+ "%s: index=%d conn_lcb=0x%x peer=%s conn_mask=0x%x lidx=%d", __func__,
+ xx, p_cb->conn_lcb, p_lcb->addr.ToString().c_str(), p_lcb->conn_msk,
+ p_lcb->lidx);
if (mask & p_cb->conn_lcb) {
/* this entry is used. check if it is connected */
- p_lcb = &p_cb->lcb[xx];
if (!p_lcb->conn_msk) {
bta_sys_start_timer(p_cb->link_signalling_timer,
BTA_AV_SIGNALLING_TIMEOUT_MS,
@@ -1516,6 +1525,10 @@
pend.bd_addr = p_lcb->addr;
tBTA_AV bta_av_data;
bta_av_data.pend = pend;
+ APPL_TRACE_DEBUG(
+ "%s: BTA_AV_PENDING_EVT for %s index=%d conn_mask=0x%x lidx=%d",
+ __func__, pend.bd_addr.ToString().c_str(), xx, p_lcb->conn_msk,
+ p_lcb->lidx);
(*p_cb->p_cback)(BTA_AV_PENDING_EVT, &bta_av_data);
}
}
@@ -1540,7 +1553,7 @@
p_scb = p_cb->p_scb[inx];
}
if (p_scb) {
- APPL_TRACE_DEBUG("%s coll_mask = 0x%02X", __func__, p_scb->coll_mask);
+ APPL_TRACE_DEBUG("%s: coll_mask = 0x%02X", __func__, p_scb->coll_mask);
if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) {
p_scb->coll_mask &= ~BTA_AV_COLL_INC_TMR;
@@ -1597,7 +1610,7 @@
uint16_t peer_rc_version = 0;
uint16_t categories = 0;
- APPL_TRACE_DEBUG("bta_av_check_peer_features service_uuid:x%x", service_uuid);
+ APPL_TRACE_DEBUG("%s: service_uuid:x%x", __func__, service_uuid);
/* loop through all records we found */
while (true) {
/* get next record; if none found, we're done */
@@ -1623,7 +1636,7 @@
/* get profile version (if failure, version parameter is not updated) */
SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL,
&peer_rc_version);
- APPL_TRACE_DEBUG("peer_rc_version 0x%x", peer_rc_version);
+ APPL_TRACE_DEBUG("%s: peer_rc_version 0x%x", __func__, peer_rc_version);
if (peer_rc_version >= AVRC_REV_1_3)
peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
@@ -1641,7 +1654,7 @@
}
}
}
- APPL_TRACE_DEBUG("peer_features:x%x", peer_features);
+ APPL_TRACE_DEBUG("%s: peer_features:x%x", __func__, peer_features);
return peer_features;
}
@@ -1659,13 +1672,14 @@
tBTA_AV_FEAT peer_features = 0;
tBTA_AV_CB* p_cb = &bta_av_cb;
- APPL_TRACE_DEBUG("%s service_uuid:x%x", __func__, service_uuid);
+ APPL_TRACE_DEBUG("%s: service_uuid:x%x", __func__, service_uuid);
/* loop through all records we found */
tSDP_DISC_REC* p_rec =
SDP_FindServiceInDb(p_cb->p_disc_db, service_uuid, NULL);
while (p_rec) {
- APPL_TRACE_DEBUG("%s found Service record for x%x", __func__, service_uuid);
+ APPL_TRACE_DEBUG("%s: found Service record for x%x", __func__,
+ service_uuid);
if ((SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_CLASS_ID_LIST)) !=
NULL) {
@@ -1685,7 +1699,7 @@
uint16_t peer_rc_version = 0;
bool val = SDP_FindProfileVersionInRec(
p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_rc_version);
- APPL_TRACE_DEBUG("%s peer_rc_version for TG 0x%x, profile_found %d",
+ APPL_TRACE_DEBUG("%s: peer_rc_version for TG 0x%x, profile_found %d",
__func__, peer_rc_version, val);
if (peer_rc_version >= AVRC_REV_1_3)
@@ -1716,7 +1730,7 @@
/* get next record; if none found, we're done */
p_rec = SDP_FindServiceInDb(p_cb->p_disc_db, service_uuid, p_rec);
}
- APPL_TRACE_DEBUG("%s peer_features:x%x", __func__, peer_features);
+ APPL_TRACE_DEBUG("%s: peer_features:x%x", __func__, peer_features);
return peer_features;
}
@@ -1737,7 +1751,7 @@
uint8_t rc_handle;
tBTA_AV_FEAT peer_features = 0; /* peer features mask */
- APPL_TRACE_DEBUG("%s bta_av_rc_disc_done disc:x%x", __func__, p_cb->disc);
+ APPL_TRACE_DEBUG("%s: bta_av_rc_disc_done disc:x%x", __func__, p_cb->disc);
if (!p_cb->disc) {
return;
}
@@ -1758,13 +1772,13 @@
}
}
- APPL_TRACE_DEBUG("%s rc_handle %d", __func__, rc_handle);
+ APPL_TRACE_DEBUG("%s: rc_handle %d", __func__, rc_handle);
#if (BTA_AV_SINK_INCLUDED == TRUE)
if (p_cb->sdp_a2dp_snk_handle) {
/* This is Sink + CT + TG(Abs Vol) */
peer_features =
bta_avk_check_peer_features(UUID_SERVCLASS_AV_REM_CTRL_TARGET);
- APPL_TRACE_DEBUG("%s populating rem ctrl target features %d", __func__,
+ APPL_TRACE_DEBUG("%s: populating rem ctrl target features %d", __func__,
peer_features);
if (BTA_AV_FEAT_ADV_CTRL &
bta_avk_check_peer_features(UUID_SERVCLASS_AV_REMOTE_CONTROL))
@@ -1795,9 +1809,9 @@
SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL,
&peer_rc_version);
if (peer_rc_version <= AVRC_REV_1_3) {
- APPL_TRACE_DEBUG("%s Using AVRCP 1.3 Capabilities with remote device",
+ APPL_TRACE_DEBUG("%s: Using AVRCP 1.3 Capabilities with remote device",
__func__);
- p_bta_av_cfg = (tBTA_AV_CFG*)&bta_av_cfg_compatibility;
+ p_bta_av_cfg = &bta_av_cfg_compatibility;
}
}
}
@@ -1805,8 +1819,8 @@
p_cb->disc = 0;
osi_free_and_reset((void**)&p_cb->p_disc_db);
- APPL_TRACE_DEBUG("peer_features 0x%x, features 0x%x", peer_features,
- p_cb->features);
+ APPL_TRACE_DEBUG("%s: peer_features 0x%x, features 0x%x", __func__,
+ peer_features, p_cb->features);
/* if we have no rc connection */
if (rc_handle == BTA_AV_RC_HANDLE_NONE) {
@@ -1816,19 +1830,19 @@
(peer_features & BTA_AV_FEAT_RCTG)) ||
((p_cb->features & BTA_AV_FEAT_RCTG) &&
(peer_features & BTA_AV_FEAT_RCCT)))) {
- p_lcb = bta_av_find_lcb(p_scb->peer_addr, BTA_AV_LCB_FIND);
+ p_lcb = bta_av_find_lcb(p_scb->PeerAddress(), BTA_AV_LCB_FIND);
if (p_lcb) {
rc_handle = bta_av_rc_create(p_cb, AVCT_INT,
(uint8_t)(p_scb->hdi + 1), p_lcb->lidx);
p_cb->rcb[rc_handle].peer_features = peer_features;
} else {
- APPL_TRACE_ERROR("can not find LCB!!");
+ APPL_TRACE_ERROR("%s: can not find LCB!!", __func__);
}
} else if (p_scb->use_rc) {
/* can not find AVRC on peer device. report failure */
p_scb->use_rc = false;
tBTA_AV_RC_OPEN rc_open;
- rc_open.peer_addr = p_scb->peer_addr;
+ rc_open.peer_addr = p_scb->PeerAddress();
rc_open.peer_features = 0;
rc_open.status = BTA_AV_FAIL_SDP;
tBTA_AV bta_av_data;
@@ -1849,7 +1863,7 @@
*/
rc_feat.peer_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx].addr;
} else {
- rc_feat.peer_addr = p_scb->peer_addr;
+ rc_feat.peer_addr = p_scb->PeerAddress();
}
tBTA_AV bta_av_data;
bta_av_data.rc_feat = rc_feat;
@@ -1878,32 +1892,35 @@
rc_close.rc_handle = BTA_AV_RC_HANDLE_NONE;
p_scb = NULL;
- APPL_TRACE_DEBUG("bta_av_rc_closed rc_handle:%d", p_msg->handle);
+ APPL_TRACE_DEBUG("%s: rc_handle:%d", __func__, p_msg->handle);
for (i = 0; i < BTA_AV_NUM_RCB; i++) {
p_rcb = &p_cb->rcb[i];
- APPL_TRACE_DEBUG("bta_av_rc_closed rcb[%d] rc_handle:%d, status=0x%x", i,
+ APPL_TRACE_DEBUG("%s: rcb[%d] rc_handle:%d, status=0x%x", __func__, i,
p_rcb->handle, p_rcb->status);
if (p_rcb->handle == p_msg->handle) {
rc_close.rc_handle = i;
p_rcb->status &= ~BTA_AV_RC_CONN_MASK;
p_rcb->peer_features = 0;
- APPL_TRACE_DEBUG(" shdl:%d, lidx:%d", p_rcb->shdl, p_rcb->lidx);
+ APPL_TRACE_DEBUG("%s: shdl:%d, lidx:%d", __func__, p_rcb->shdl,
+ p_rcb->lidx);
if (p_rcb->shdl) {
if ((p_rcb->shdl - 1) < BTA_AV_NUM_STRS) {
p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
}
if (p_scb) {
- rc_close.peer_addr = p_scb->peer_addr;
+ rc_close.peer_addr = p_scb->PeerAddress();
if (p_scb->rc_handle == p_rcb->handle)
p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;
- APPL_TRACE_DEBUG("shdl:%d, srch:%d", p_rcb->shdl, p_scb->rc_handle);
+ APPL_TRACE_DEBUG("%s: shdl:%d, srch:%d", __func__, p_rcb->shdl,
+ p_scb->rc_handle);
}
p_rcb->shdl = 0;
} else if (p_rcb->lidx == (BTA_AV_NUM_LINKS + 1)) {
/* if the RCB uses the extra LCB, use the addr for event and clean it */
p_lcb = &p_cb->lcb[BTA_AV_NUM_LINKS];
rc_close.peer_addr = p_msg->peer_addr;
- VLOG(1) << "rc_only closed bd_addr:" << p_msg->peer_addr;
+ LOG_INFO(LOG_TAG, "%s: rc_only closed bd_addr: %s", __func__,
+ p_msg->peer_addr.ToString().c_str());
p_lcb->conn_msk = 0;
p_lcb->lidx = 0;
}
@@ -1957,8 +1974,8 @@
tBTA_AV_RC_CONN_CHG* p_msg = (tBTA_AV_RC_CONN_CHG*)p_data;
tBTA_AV_RC_BROWSE_OPEN rc_browse_open;
- VLOG(1) << "bta_av_rc_browse_opened bd_addr:" << p_msg->peer_addr;
- APPL_TRACE_DEBUG("bta_av_rc_browse_opened rc_handle:%d", p_msg->handle);
+ LOG_INFO(LOG_TAG, "%s: peer_addr: %s rc_handle:%d", __func__,
+ p_msg->peer_addr.ToString().c_str(), p_msg->handle);
rc_browse_open.status = BTA_AV_SUCCESS;
rc_browse_open.rc_handle = p_msg->handle;
@@ -1983,8 +2000,8 @@
tBTA_AV_RC_CONN_CHG* p_msg = (tBTA_AV_RC_CONN_CHG*)p_data;
tBTA_AV_RC_BROWSE_CLOSE rc_browse_close;
- VLOG(1) << "bta_av_rc_browse_closed bd_addr:" << p_msg->peer_addr;
- APPL_TRACE_DEBUG("bta_av_rc_browse_closed rc_handle:%d", p_msg->handle);
+ LOG_INFO(LOG_TAG, "%s: peer_addr: %s rc_handle:%d", __func__,
+ p_msg->peer_addr.ToString().c_str(), p_msg->handle);
rc_browse_close.rc_handle = p_msg->handle;
rc_browse_close.peer_addr = p_msg->peer_addr;
@@ -2011,29 +2028,30 @@
ATTR_ID_SUPPORTED_FEATURES};
uint8_t hdi;
tBTA_AV_SCB* p_scb;
- RawAddress* p_addr = NULL;
+ RawAddress peer_addr = RawAddress::kEmpty;
uint8_t rc_handle;
- APPL_TRACE_DEBUG("bta_av_rc_disc 0x%x, %d", disc, bta_av_cb.disc);
+ APPL_TRACE_DEBUG("%s: disc: 0x%x, bta_av_cb.disc: 0x%x", __func__, disc,
+ bta_av_cb.disc);
if ((bta_av_cb.disc != 0) || (disc == 0)) return;
if ((disc & BTA_AV_CHNL_MSK) == BTA_AV_CHNL_MSK) {
/* this is the rc handle/index to tBTA_AV_RCB */
rc_handle = disc & (~BTA_AV_CHNL_MSK);
if (p_cb->rcb[rc_handle].lidx) {
- p_addr = &p_cb->lcb[p_cb->rcb[rc_handle].lidx - 1].addr;
+ peer_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx - 1].addr;
}
} else {
hdi = (disc & BTA_AV_HNDL_MSK) - 1;
p_scb = p_cb->p_scb[hdi];
if (p_scb) {
- APPL_TRACE_DEBUG("rc_handle %d", p_scb->rc_handle);
- p_addr = &p_scb->peer_addr;
+ APPL_TRACE_DEBUG("%s: rc_handle %d", __func__, p_scb->rc_handle);
+ peer_addr = p_scb->PeerAddress();
}
}
- if (p_addr) {
+ if (!peer_addr.IsEmpty()) {
/* allocate discovery database */
if (p_cb->p_disc_db == NULL)
p_cb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_AV_DISC_BUF_SIZE);
@@ -2045,10 +2063,11 @@
db_params.p_attrs = attr_list;
/* searching for UUID_SERVCLASS_AV_REMOTE_CONTROL gets both TG and CT */
- if (AVRC_FindService(UUID_SERVCLASS_AV_REMOTE_CONTROL, *p_addr, &db_params,
- bta_av_avrc_sdp_cback) == AVRC_SUCCESS) {
+ if (AVRC_FindService(UUID_SERVCLASS_AV_REMOTE_CONTROL, peer_addr,
+ &db_params,
+ base::Bind(bta_av_avrc_sdp_cback)) == AVRC_SUCCESS) {
p_cb->disc = disc;
- APPL_TRACE_DEBUG("disc %d", p_cb->disc);
+ APPL_TRACE_DEBUG("%s: disc 0x%x", __func__, p_cb->disc);
}
}
}
@@ -2073,62 +2092,52 @@
p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
if (p_scb) {
- APPL_TRACE_DEBUG("deregistered %d(h%d)", p_scb->chnl, p_scb->hndl);
+ APPL_TRACE_DEBUG("%s: deregistered %d(h%d)", __func__, p_scb->chnl,
+ p_scb->hndl);
mask = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
- p_cb->reg_audio &= ~mask;
- if ((p_cb->conn_audio & mask) && bta_av_cb.audio_open_cnt) {
- /* this channel is still marked as open. decrease the count */
- bta_av_cb.audio_open_cnt--;
- }
- p_cb->conn_audio &= ~mask;
+ p_cb->reg_audio &= ~mask;
+ if ((p_cb->conn_audio & mask) && bta_av_cb.audio_open_cnt) {
+ /* this channel is still marked as open. decrease the count */
+ bta_av_cb.audio_open_cnt--;
+ }
+ p_cb->conn_audio &= ~mask;
- if (p_scb->q_tag == BTA_AV_Q_TAG_STREAM && p_scb->a2dp_list) {
- /* make sure no buffers are in a2dp_list */
- while (!list_is_empty(p_scb->a2dp_list)) {
- p_buf = (BT_HDR*)list_front(p_scb->a2dp_list);
- list_remove(p_scb->a2dp_list, p_buf);
- osi_free(p_buf);
- }
+ if (p_scb->q_tag == BTA_AV_Q_TAG_STREAM && p_scb->a2dp_list) {
+ /* make sure no buffers are in a2dp_list */
+ while (!list_is_empty(p_scb->a2dp_list)) {
+ p_buf = (BT_HDR*)list_front(p_scb->a2dp_list);
+ list_remove(p_scb->a2dp_list, p_buf);
+ osi_free(p_buf);
}
-
- /* remove the A2DP SDP record, if no more audio stream is left */
- if (!p_cb->reg_audio) {
-#if (BTA_AR_INCLUDED == TRUE)
- bta_ar_dereg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, BTA_ID_AV);
-#endif
- if (p_cb->sdp_a2dp_handle) {
- bta_av_del_sdp_rec(&p_cb->sdp_a2dp_handle);
- p_cb->sdp_a2dp_handle = 0;
- bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
- }
-
-#if (BTA_AV_SINK_INCLUDED == TRUE)
- if (p_cb->sdp_a2dp_snk_handle) {
- bta_av_del_sdp_rec(&p_cb->sdp_a2dp_snk_handle);
- p_cb->sdp_a2dp_snk_handle = 0;
- bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SINK);
- }
-#endif
- }
- } else {
- p_cb->reg_video &= ~mask;
- /* make sure that this channel is not connected */
- p_cb->conn_video &= ~mask;
- /* remove the VDP SDP record, (only one video stream at most) */
- bta_av_del_sdp_rec(&p_cb->sdp_vdp_handle);
- bta_sys_remove_uuid(UUID_SERVCLASS_VIDEO_SOURCE);
}
- /* make sure that the timer is not active */
- alarm_cancel(p_scb->avrc_ct_timer);
- osi_free_and_reset((void**)&p_cb->p_scb[p_scb->hdi]);
+ /* remove the A2DP SDP record, if no more audio stream is left */
+ if (!p_cb->reg_audio) {
+#if (BTA_AR_INCLUDED == TRUE)
+ bta_ar_dereg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, BTA_ID_AV);
+#endif
+ if (p_cb->sdp_a2dp_handle) {
+ bta_av_del_sdp_rec(&p_cb->sdp_a2dp_handle);
+ p_cb->sdp_a2dp_handle = 0;
+ bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+ }
+
+#if (BTA_AV_SINK_INCLUDED == TRUE)
+ if (p_cb->sdp_a2dp_snk_handle) {
+ bta_av_del_sdp_rec(&p_cb->sdp_a2dp_snk_handle);
+ p_cb->sdp_a2dp_snk_handle = 0;
+ bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SINK);
+ }
+#endif
+ }
+
+ bta_av_free_scb(p_scb);
}
- APPL_TRACE_DEBUG("audio 0x%x, video: 0x%x, disable:%d", p_cb->reg_audio,
- p_cb->reg_video, p_cb->disabling);
+ APPL_TRACE_DEBUG("%s: audio 0x%x, disable:%d", __func__, p_cb->reg_audio,
+ p_cb->disabling);
/* if no stream control block is active */
- if ((p_cb->reg_audio + p_cb->reg_video) == 0) {
+ if (p_cb->reg_audio == 0) {
#if (BTA_AR_INCLUDED == TRUE)
/* deregister from AVDT */
bta_ar_dereg_avdt(BTA_ID_AV);
diff --git a/bta/av/bta_av_api.cc b/bta/av/bta_av_api.cc
index 82ed10c..bb5cca4 100644
--- a/bta/av/bta_av_api.cc
+++ b/bta/av/bta_av_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2011-2012 Broadcom Corporation
+ * Copyright 2011-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,8 @@
*
******************************************************************************/
+#define LOG_TAG "bt_bta_av"
+
#include <base/logging.h>
#include "bt_target.h"
@@ -36,6 +38,7 @@
#include "bta_sys.h"
#include "osi/include/allocator.h"
+#include "osi/include/log.h"
/*****************************************************************************
* Constants
@@ -153,6 +156,10 @@
******************************************************************************/
void BTA_AvOpen(const RawAddress& bd_addr, tBTA_AV_HNDL handle, bool use_rc,
tBTA_SEC sec_mask, uint16_t uuid) {
+ LOG_INFO(LOG_TAG, "%s: peer %s handle:0x%x use_rc=%s sec_mask=0x%x uuid=0x%x",
+ __func__, bd_addr.ToString().c_str(), handle,
+ (use_rc) ? "true" : "false", sec_mask, uuid);
+
tBTA_AV_API_OPEN* p_buf =
(tBTA_AV_API_OPEN*)osi_malloc(sizeof(tBTA_AV_API_OPEN));
@@ -177,6 +184,8 @@
*
******************************************************************************/
void BTA_AvClose(tBTA_AV_HNDL handle) {
+ LOG_INFO(LOG_TAG, "%s: handle:0x%x", __func__, handle);
+
BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
p_buf->event = BTA_AV_API_CLOSE_EVT;
@@ -195,6 +204,8 @@
*
******************************************************************************/
void BTA_AvDisconnect(const RawAddress& bd_addr) {
+ LOG_INFO(LOG_TAG, "%s: peer %s", __func__, bd_addr.ToString().c_str());
+
tBTA_AV_API_DISCNT* p_buf =
(tBTA_AV_API_DISCNT*)osi_malloc(sizeof(tBTA_AV_API_DISCNT));
@@ -213,10 +224,13 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStart(void) {
+void BTA_AvStart(tBTA_AV_HNDL handle) {
+ LOG_INFO(LOG_TAG, "%s: handle=%d", __func__, handle);
+
BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
p_buf->event = BTA_AV_API_START_EVT;
+ p_buf->layer_specific = handle;
bta_sys_sendmsg(p_buf);
}
@@ -231,6 +245,8 @@
*
******************************************************************************/
void BTA_AvOffloadStart(tBTA_AV_HNDL hndl) {
+ LOG_INFO(LOG_TAG, "%s: handle=%d", __func__, hndl);
+
BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
p_buf->event = BTA_AV_API_OFFLOAD_START_EVT;
@@ -270,11 +286,15 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStop(bool suspend) {
+void BTA_AvStop(tBTA_AV_HNDL handle, bool suspend) {
+ LOG_INFO(LOG_TAG, "%s: handle=%d suspend=%s", __func__, handle,
+ logbool(suspend).c_str());
+
tBTA_AV_API_STOP* p_buf =
(tBTA_AV_API_STOP*)osi_malloc(sizeof(tBTA_AV_API_STOP));
p_buf->hdr.event = BTA_AV_API_STOP_EVT;
+ p_buf->hdr.layer_specific = handle;
p_buf->flush = true;
p_buf->suspend = suspend;
p_buf->reconfig_stop = false;
@@ -298,6 +318,9 @@
void BTA_AvReconfig(tBTA_AV_HNDL hndl, bool suspend, uint8_t sep_info_idx,
uint8_t* p_codec_info, uint8_t num_protect,
const uint8_t* p_protect_info) {
+ LOG_INFO(LOG_TAG, "%s: handle=%d suspend=%s sep_info_idx=%d", __func__, hndl,
+ logbool(suspend).c_str(), sep_info_idx);
+
tBTA_AV_API_RCFG* p_buf =
(tBTA_AV_API_RCFG*)osi_malloc(sizeof(tBTA_AV_API_RCFG) + num_protect);
diff --git a/bta/av/bta_av_cfg.cc b/bta/av/bta_av_cfg.cc
index 688af45..76c9454 100644
--- a/bta/av/bta_av_cfg.cc
+++ b/bta/av/bta_av_cfg.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2016 Broadcom Corporation
+ * Copyright 2005-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
#endif
#ifndef BTA_AV_RC_PASS_RSP_CODE
-#define BTA_AV_RC_PASS_RSP_CODE BTA_AV_RSP_NOT_IMPL
+#define BTA_AV_RC_PASS_RSP_CODE AVRC_RSP_NOT_IMPL
#endif
const uint32_t bta_av_meta_caps_co_ids[] = {AVRC_CO_METADATA, AVRC_CO_BROADCOM};
@@ -74,13 +74,9 @@
/* Note: if AVRC_SUPF_TG_GROUP_NAVI is set, bta_av_cfg.avrc_group should be true
*/
#ifndef BTA_AV_RC_SUPF_TG
-#if (AVRC_METADATA_INCLUDED == TRUE)
#define BTA_AV_RC_SUPF_TG \
(AVRC_SUPF_TG_CAT1 | AVRC_SUPF_TG_MULTI_PLAYER | \
AVRC_SUPF_TG_BROWSE) /* TODO: | AVRC_SUPF_TG_APP_SETTINGS) */
-#else
-#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1)
-#endif
#endif
/*
@@ -132,24 +128,16 @@
/* This configuration to be used when we are Src + TG + CT( only for abs vol) */
const tBTA_AV_CFG bta_av_cfg = {
- BTA_AV_RC_COMP_ID, /* AVRCP Company ID */
-#if (AVRC_METADATA_INCLUDED == TRUE)
- 512, /* AVRCP MTU at L2CAP for control channel */
- BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
-#else
- 48, /* AVRCP MTU at L2CAP for control channel */
- BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
-#endif
+ BTA_AV_RC_COMP_ID, /* AVRCP Company ID */
+ 512, /* AVRCP MTU at L2CAP for control channel */
+ BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
BTA_AV_RC_SUPF_CT, /* AVRCP controller categories */
BTA_AV_RC_SUPF_TG, /* AVRCP target categories */
672, /* AVDTP signaling channel MTU at L2CAP */
- BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP
- */
+ BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP */
bta_av_audio_flush_to, /* AVDTP audio transport channel flush
timeout */
6, /* AVDTP audio channel max data queue size */
- BTA_AV_MAX_VDP_MTU, /* AVDTP video transport channel MTU at L2CAP */
- 600, /* AVDTP video transport channel flush timeout */
false, /* true, to accept AVRC 1.3 group nevigation command */
2, /* company id count in p_meta_co_ids */
BTA_AV_NUM_RC_EVT_IDS, /* event id count in p_meta_evt_ids */
@@ -159,8 +147,7 @@
for company id */
bta_av_meta_caps_evt_ids, /* the the metadata Get Capabilities
response for event id */
- NULL, /* the action function table for VDP stream */
- NULL, /* action function to register VDP */
+ NULL, /* the action function table for audio stream */
BTA_AV_RC_CT_NAME, /* Default AVRCP controller name */
BTA_AV_RC_TG_NAME /* Default AVRCP target name */
};
@@ -168,23 +155,15 @@
/* This configuration to be used when we are Sink + CT + TG( only for abs vol)
*/
const tBTA_AV_CFG bta_avk_cfg = {
- AVRC_CO_METADATA, /* AVRCP Company ID */
-#if (AVRC_METADATA_INCLUDED == TRUE)
- 512, /* AVRCP MTU at L2CAP for control channel */
-#else
- 48, /* AVRCP MTU at L2CAP for control channel */
-#endif
+ AVRC_CO_METADATA, /* AVRCP Company ID */
+ 512, /* AVRCP MTU at L2CAP for control channel */
BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
BTA_AVK_RC_SUPF_CT, /* AVRCP controller categories */
BTA_AVK_RC_SUPF_TG, /* AVRCP target categories */
672, /* AVDTP signaling channel MTU at L2CAP */
- BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP
- */
- bta_av_audio_flush_to, /* AVDTP audio transport channel flush
- timeout */
+ BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP */
+ bta_av_audio_flush_to, /* AVDTP audio transport channel flush timeout */
6, /* AVDTP audio channel max data queue size */
- BTA_AV_MAX_VDP_MTU, /* AVDTP video transport channel MTU at L2CAP */
- 600, /* AVDTP video transport channel flush timeout */
false, /* true, to accept AVRC 1.3 group nevigation command */
2, /* company id count in p_meta_co_ids */
BTA_AVK_NUM_RC_EVT_IDS, /* event id count in p_meta_evt_ids */
@@ -194,49 +173,38 @@
for company id */
bta_avk_meta_caps_evt_ids, /* the the metadata Get Capabilities
response for event id */
- NULL, /* the action function table for VDP stream */
- NULL, /* action function to register VDP */
+ NULL, /* the action function table for audio stream */
{0}, /* Default AVRCP controller name */
{0}, /* Default AVRCP target name */
};
/* This configuration to be used when we are using AVRCP1.3 */
const tBTA_AV_CFG bta_av_cfg_compatibility = {
- BTA_AV_RC_COMP_ID, /* AVRCP Company ID */
-#if (AVRC_METADATA_INCLUDED == TRUE)
- 512, /* AVRCP MTU at L2CAP for control channel */
- BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
-#else
- 48, /* AVRCP MTU at L2CAP for control channel */
- BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
-#endif
- BTA_AV_RC_SUPF_CT, /* AVRCP controller categories */
- AVRC_SUPF_TG_CAT1, /* Only support CAT1 for AVRCP1.3 */
- 672, /* AVDTP signaling channel MTU at L2CAP */
- BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP
- */
- bta_av_audio_flush_to, /* AVDTP audio transport channel flush
- timeout */
- 6, /* AVDTP audio channel max data queue size */
- BTA_AV_MAX_VDP_MTU, /* AVDTP video transport channel MTU at L2CAP */
- 600, /* AVDTP video transport channel flush timeout */
- false, /* true, to accept AVRC 1.3 group nevigation command */
- 2, /* company id count in p_meta_co_ids */
- BTA_AV_NUM_RC_EVT_IDS_AVRCP13, /* event id count for AVRCP1.3*/
+ BTA_AV_RC_COMP_ID, /* AVRCP Company ID */
+ 512, /* AVRCP MTU at L2CAP for control channel */
+ BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
+ BTA_AV_RC_SUPF_CT, /* AVRCP controller categories */
+ AVRC_SUPF_TG_CAT1, /* Only support CAT1 for AVRCP1.3 */
+ 672, /* AVDTP signaling channel MTU at L2CAP */
+ BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP */
+ bta_av_audio_flush_to, /* AVDTP audio transport channel flush timeout */
+ 6, /* AVDTP audio channel max data queue size */
+ false, /* true, to accept AVRC 1.3 group nevigation command */
+ 2, /* company id count in p_meta_co_ids */
+ BTA_AV_NUM_RC_EVT_IDS_AVRCP13, /* event id count for AVRCP1.3 */
BTA_AV_RC_PASS_RSP_CODE, /* the default response code for pass
through commands */
bta_av_meta_caps_co_ids, /* the metadata Get Capabilities response
for company id */
bta_av_meta_caps_evt_ids_avrcp13, /* the the metadata Get Capabilities
response for event id, compatible
- with AVRCP1.3*/
- NULL, /* the action function table for VDP stream */
- NULL, /* action function to register VDP */
+ with AVRCP1.3 */
+ NULL, /* the action function table for audio stream */
BTA_AV_RC_CT_NAME, /* Default AVRCP controller name */
BTA_AV_RC_TG_NAME /* Default AVRCP target name */
};
-tBTA_AV_CFG* p_bta_av_cfg = NULL;
+const tBTA_AV_CFG* p_bta_av_cfg = NULL;
const uint16_t bta_av_rc_id[] = {
0x0000, /* bit mask: 0=SELECT, 1=UP, 2=DOWN, 3=LEFT,
@@ -264,15 +232,11 @@
* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE, 4=PLAY, 5=STOP,
6=PAUSE, 7=RECORD, 8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
12=BACKWARD */
-#if (BTA_AV_RC_PASS_RSP_CODE == BTA_AV_RSP_INTERIM)
+#if (BTA_AV_RC_PASS_RSP_CODE == AVRC_RSP_INTERIM)
0x0070, /* PLAY | STOP | PAUSE */
-#else /* BTA_AV_RC_PASS_RSP_CODE != BTA_AV_RSP_INTERIM */
-#if (BTA_AVRCP_FF_RW_SUPPORT == TRUE)
+#else /* BTA_AV_RC_PASS_RSP_CODE != AVRC_RSP_INTERIM */
0x1b7E, /* PLAY | STOP | PAUSE | FF | RW | VOL_UP | VOL_DOWN | MUTE | FW |
BACK */
-#else /* BTA_AVRCP_FF_RW_SUPPORT == FALSE */
- 0x187E, /* PLAY | STOP | PAUSE | VOL_UP | VOL_DOWN | MUTE | FW | BACK */
-#endif /* BTA_AVRCP_FF_RW_SUPPORT */
#endif /* BTA_AV_RC_PASS_RSP_CODE */
0x0000, /* bit mask: 0=ANGLE, 1=SUBPICT */
@@ -283,7 +247,7 @@
4=F4, 5=F5 */
};
-#if (BTA_AV_RC_PASS_RSP_CODE == BTA_AV_RSP_INTERIM)
+#if (BTA_AV_RC_PASS_RSP_CODE == AVRC_RSP_INTERIM)
const uint16_t bta_av_rc_id_ac[] = {
0x0000, /* bit mask: 0=SELECT, 1=UP, 2=DOWN, 3=LEFT,
4=RIGHT, 5=RIGHT_UP, 6=RIGHT_DOWN,
diff --git a/bta/av/bta_av_ci.cc b/bta/av/bta_av_ci.cc
index a215046..a3d552d 100644
--- a/bta/av/bta_av_ci.cc
+++ b/bta/av/bta_av_ci.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,10 @@
*
******************************************************************************/
+#define LOG_TAG "bt_bta_av"
+
+#include "osi/include/log.h"
+
#include "bta_av_ci.h"
#include "bta_api.h"
#include "bta_av_int.h"
@@ -36,7 +40,7 @@
*
* Description This function sends an event to the AV indicating that
* the phone has audio stream data ready to send and AV
- * should call bta_av_co_audio_src_data_path().
+ * should call bta_av_co_audio_source_data_path().
*
* Returns void
*
@@ -63,13 +67,19 @@
* Returns void
*
******************************************************************************/
-void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, uint8_t err_code, uint8_t category,
- uint8_t num_seid, uint8_t* p_seid, bool recfg_needed,
- uint8_t avdt_handle) {
+void bta_av_ci_setconfig(tBTA_AV_HNDL bta_av_handle, uint8_t err_code,
+ uint8_t category, uint8_t num_seid, uint8_t* p_seid,
+ bool recfg_needed, uint8_t avdt_handle) {
+ LOG_DEBUG(LOG_TAG,
+ "%s: bta_av_handle=%d err_code=%d category=%d "
+ "num_seid=%d recfg_needed=%s avdt_handle=%d",
+ __func__, bta_av_handle, err_code, category, num_seid,
+ recfg_needed ? "true" : "false", avdt_handle);
+
tBTA_AV_CI_SETCONFIG* p_buf =
(tBTA_AV_CI_SETCONFIG*)osi_malloc(sizeof(tBTA_AV_CI_SETCONFIG));
- p_buf->hdr.layer_specific = hndl;
+ p_buf->hdr.layer_specific = bta_av_handle;
p_buf->hdr.event = (err_code == A2DP_SUCCESS) ? BTA_AV_CI_SETCONFIG_OK_EVT
: BTA_AV_CI_SETCONFIG_FAIL_EVT;
p_buf->err_code = err_code;
diff --git a/bta/av/bta_av_int.h b/bta/av/bta_av_int.h
index 963a84a..17c4bf3 100644
--- a/bta/av/bta_av_int.h
+++ b/bta/av/bta_av_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -101,9 +101,7 @@
BTA_AV_AVRC_BROWSE_CLOSE_EVT,
BTA_AV_CONN_CHG_EVT,
BTA_AV_DEREG_COMP_EVT,
-#if (AVDT_REPORTING == TRUE)
BTA_AV_AVDT_RPT_CONN_EVT,
-#endif
BTA_AV_API_START_EVT, /* the following 2 events must be in the same order as
the *AP_*EVT */
BTA_AV_API_STOP_EVT
@@ -133,7 +131,7 @@
#define BTA_AV_RC_HANDLE_NONE 0xFF
/* size of database for service discovery */
-#define BTA_AV_DISC_BUF_SIZE 1000
+#define BTA_AV_DISC_BUF_SIZE 2000
/* maximum length of AVDTP security data */
#define BTA_AV_SECURITY_MAX_LEN 400
@@ -158,30 +156,43 @@
/* function types for call-out functions */
typedef bool (*tBTA_AV_CO_INIT)(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg);
-typedef void (*tBTA_AV_CO_DISC_RES)(tBTA_AV_HNDL hndl, uint8_t num_seps,
- uint8_t num_snk, uint8_t num_src,
- const RawAddress& addr,
- uint16_t uuid_local);
-typedef tA2DP_STATUS (*tBTA_AV_CO_GETCFG)(tBTA_AV_HNDL hndl,
+ AvdtpSepConfig* p_cfg);
+typedef void (*tBTA_AV_CO_DISC_RES)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
+ uint8_t num_seps, uint8_t num_snk,
+ uint8_t num_src, uint16_t uuid_local);
+typedef tA2DP_STATUS (*tBTA_AV_CO_GETCFG)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
uint8_t* p_codec_info,
uint8_t* p_sep_info_idx, uint8_t seid,
uint8_t* p_num_protect,
uint8_t* p_protect_info);
-typedef void (*tBTA_AV_CO_SETCFG)(tBTA_AV_HNDL hndl,
+typedef void (*tBTA_AV_CO_SETCFG)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
const uint8_t* p_codec_info, uint8_t seid,
- const RawAddress& addr, uint8_t num_protect,
+ uint8_t num_protect,
const uint8_t* p_protect_info,
uint8_t t_local_sep, uint8_t avdt_handle);
-typedef void (*tBTA_AV_CO_OPEN)(tBTA_AV_HNDL hndl, uint16_t mtu);
-typedef void (*tBTA_AV_CO_CLOSE)(tBTA_AV_HNDL hndl);
-typedef void (*tBTA_AV_CO_START)(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
- bool* p_no_rtp_hdr);
-typedef void (*tBTA_AV_CO_STOP)(tBTA_AV_HNDL hndl);
-typedef void* (*tBTA_AV_CO_DATAPATH)(const uint8_t* p_codec_info,
- uint32_t* p_timestamp);
-typedef void (*tBTA_AV_CO_DELAY)(tBTA_AV_HNDL hndl, uint16_t delay);
-typedef void (*tBTA_AV_CO_UPDATE_MTU)(tBTA_AV_HNDL hndl, uint16_t mtu);
+typedef void (*tBTA_AV_CO_OPEN)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr, uint16_t mtu);
+typedef void (*tBTA_AV_CO_CLOSE)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr);
+typedef void (*tBTA_AV_CO_START)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
+ const uint8_t* p_codec_info,
+ bool* p_no_rtp_header);
+typedef void (*tBTA_AV_CO_STOP)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr);
+typedef BT_HDR* (*tBTA_AV_CO_DATAPATH)(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp);
+typedef void (*tBTA_AV_CO_DELAY)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr, uint16_t delay);
+typedef void (*tBTA_AV_CO_UPDATE_MTU)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
+ uint16_t mtu);
+
+typedef bool (*tBTA_AV_CO_CONTENT_PROTECT_IS_ACTIVE)(
+ const RawAddress& peer_addr);
/* the call-out functions for one stream */
typedef struct {
@@ -196,6 +207,7 @@
tBTA_AV_CO_DATAPATH data;
tBTA_AV_CO_DELAY delay;
tBTA_AV_CO_UPDATE_MTU update_mtu;
+ tBTA_AV_CO_CONTENT_PROTECT_IS_ACTIVE cp_is_active;
} tBTA_AV_CO_FUNCTS;
/* data type for BTA_AV_API_ENABLE_EVT */
@@ -315,9 +327,10 @@
/* data type for all stream events from AVDTP */
typedef struct {
BT_HDR hdr;
- tAVDT_CFG cfg; /* configuration/capabilities parameters */
+ AvdtpSepConfig cfg; /* configuration/capabilities parameters */
tAVDT_CTRL msg; /* AVDTP callback message parameters */
RawAddress bd_addr; /* bd address */
+ uint8_t scb_index;
uint8_t handle;
uint8_t avdt_event;
bool initiator; /* true, if local device initiates the SUSPEND */
@@ -356,7 +369,6 @@
/* data type for BTA_AV_SDP_DISC_OK_EVT */
typedef struct {
BT_HDR hdr;
- uint16_t avdt_version; /* AVDTP protocol version */
} tBTA_AV_SDP_RES;
/* data type for BTA_AV_API_OFFLOAD_RSP_EVT */
@@ -386,7 +398,7 @@
#define BTA_AV_ROLE_SUSPEND_OPT 0x40 /* Suspend on Start option is set */
/* union of all event datatypes */
-typedef union {
+union tBTA_AV_DATA {
BT_HDR hdr;
tBTA_AV_API_ENABLE api_enable;
tBTA_AV_API_REG api_reg;
@@ -407,7 +419,7 @@
tBTA_AV_SDP_RES sdp_res;
tBTA_AV_API_META_RSP api_meta_rsp;
tBTA_AV_API_STATUS_RSP api_status_rsp;
-} tBTA_AV_DATA;
+};
typedef union {
tBTA_AV_API_OPEN open; /* used only before open and role switch
@@ -443,21 +455,21 @@
0x02 /* API open was called while incoming timer is running */
/* type for AV stream control block */
-typedef struct {
+// TODO: This should be renamed and changed to a proper class
+struct tBTA_AV_SCB final {
+ public:
const tBTA_AV_ACT* p_act_tbl; /* the action table for stream state machine */
const tBTA_AV_CO_FUNCTS* p_cos; /* the associated callout functions */
bool sdp_discovery_started; /* variable to determine whether SDP is started */
tBTA_AV_SEP seps[BTAV_A2DP_CODEC_INDEX_MAX];
- tAVDT_CFG* p_cap; /* buffer used for get capabilities */
+ AvdtpSepConfig peer_cap; /* buffer used for get capabilities */
list_t* a2dp_list; /* used for audio channels only */
tBTA_AV_Q_INFO q_info;
tAVDT_SEP_INFO sep_info[BTA_AV_NUM_SEPS]; /* stream discovery results */
- tAVDT_CFG cfg; /* local SEP configuration */
+ AvdtpSepConfig cfg; /* local SEP configuration */
alarm_t* avrc_ct_timer; /* delay timer for AVRC CT */
- RawAddress peer_addr; /* peer BD address */
uint16_t l2c_cid; /* L2CAP channel ID */
uint16_t stream_mtu; /* MTU of stream */
- uint16_t avdt_version; /* the avdt version of peer device */
tBTA_SEC sec_mask; /* security mask */
uint8_t media_type; /* Media type: AVDT_MEDIA_TYPE_* */
bool cong; /* true if AVDTP congested */
@@ -483,24 +495,67 @@
uint8_t rc_handle; /* connected AVRCP handle */
bool use_rc; /* true if AVRCP is allowed */
bool started; /* true if stream started */
- A2dpCodecConfig* current_codec; /* The current A2DP codec */
+ bool use_rtp_header_marker_bit; /* true if the encoded data packets have RTP
+ * headers, and the Marker bit in the header
+ * is set according to RFC 6416 */
uint8_t
co_started; /* non-zero, if stream started from call-out perspective */
bool recfg_sup; /* true if the first attempt to reconfigure the stream was
successfull, else False if command fails */
bool suspend_sup; /* true if Suspend stream is supported, else false if
suspend command fails */
- bool deregistring; /* true if deregistering */
+ bool deregistering; /* true if deregistering */
bool sco_suspend; /* true if SUSPEND is issued automatically for SCO */
uint8_t coll_mask; /* Mask to check incoming and outgoing collision */
tBTA_AV_API_OPEN open_api; /* Saved OPEN api message */
uint8_t wait; /* set 0x1, when getting Caps as ACP, set 0x2, when started */
uint8_t q_tag; /* identify the associated q_info union member */
- bool no_rtp_hdr; /* true if add no RTP header*/
+ bool no_rtp_header; /* true if add no RTP header */
uint16_t uuid_int; /*intended UUID of Initiator to connect to */
bool offload_start_pending;
- bool skip_sdp; /* Decides if sdp to be done prior to profile connection */
-} tBTA_AV_SCB;
+ bool offload_started;
+
+ /**
+ * Called to setup the state when connected to a peer.
+ *
+ * @param peer_address the peer address
+ */
+ void OnConnected(const RawAddress& peer_address);
+
+ /**
+ * Called to clear the state when disconnected from a peer.
+ *
+ */
+ void OnDisconnected();
+
+ /**
+ * Get the peer address.
+ */
+ const RawAddress& PeerAddress() const { return peer_address_; }
+
+ /**
+ * Get the AVDTP version of the peer device.
+ */
+ uint16_t AvdtpVersion() const { return avdtp_version_; }
+
+ /**
+ * Set the AVDTP version of the peer device.
+ *
+ * @param avdtp_version the AVDTP version to use
+ */
+ void SetAvdtpVersion(uint16_t avdtp_version);
+
+ /**
+ * Check whether the entry is assigned and currenty used.
+ *
+ * @return true if the entry is assigned and currently used
+ */
+ bool IsAssigned() const { return !peer_address_.IsEmpty(); }
+
+ private:
+ RawAddress peer_address_; // Peer address
+ uint16_t avdtp_version_; // The AVDTP version of the peer device
+};
#define BTA_AV_RC_ROLE_MASK 0x10
#define BTA_AV_RC_ROLE_INT 0x00
@@ -543,7 +598,6 @@
accept_signalling_timer; /* timer to monitor signalling when accepting */
uint32_t sdp_a2dp_handle; /* SDP record handle for audio src */
uint32_t sdp_a2dp_snk_handle; /* SDP record handle for audio snk */
- uint32_t sdp_vdp_handle; /* SDP record handle for video src */
tBTA_AV_FEAT features; /* features mask */
tBTA_SEC sec_mask; /* security mask */
tBTA_AV_HNDL handle; /* the handle for SDP activity */
@@ -551,21 +605,38 @@
uint8_t
disc; /* (hdi+1) or (rc_handle|BTA_AV_CHNL_MSK) if p_disc_db is in use */
uint8_t state; /* state machine state */
- uint8_t conn_rc; /* handle mask of connected RCP channels */
uint8_t conn_audio; /* handle mask of connected audio channels */
- uint8_t conn_video; /* handle mask of connected video channels */
uint8_t conn_lcb; /* index mask of used LCBs */
uint8_t audio_open_cnt; /* number of connected audio channels */
uint8_t reg_audio; /* handle mask of registered audio channels */
- uint8_t reg_video; /* handle mask of registered video channels */
uint8_t rc_acp_handle;
uint8_t rc_acp_idx; /* (index + 1) to RCB */
uint8_t rs_idx; /* (index + 1) to SCB for the one waiting for RS on open */
bool sco_occupied; /* true if SCO is being used or call is in progress */
uint8_t audio_streams; /* handle mask of streaming audio channels */
- uint8_t video_streams; /* handle mask of streaming video channels */
} tBTA_AV_CB;
+// A2DP offload VSC parameters
+class tBT_A2DP_OFFLOAD {
+ public:
+ uint32_t codec_type; /* codec types ex: SBC/AAC/LDAC/APTx */
+ uint16_t max_latency; /* maximum latency */
+ uint16_t scms_t_enable; /* content protection enable */
+ uint32_t sample_rate; /* Sample rates ex: 44.1/48/88.2/96 Khz */
+ uint8_t bits_per_sample; /* bits per sample ex: 16/24/32 */
+ uint8_t ch_mode; /* None:0 Left:1 Right:2 */
+ uint32_t encoded_audio_bitrate; /* encoder audio bitrates */
+ uint16_t acl_hdl; /* connection handle */
+ uint16_t l2c_rcid; /* l2cap channel id */
+ uint16_t mtu; /* MTU size */
+ uint8_t codec_info[32]; /* Codec specific information */
+};
+
+/* Vendor OFFLOAD VSC */
+#define HCI_VSQC_CONTROLLER_A2DP_OPCODE 0x000A
+
+#define VS_HCI_A2DP_OFFLOAD_START 0x01
+#define VS_HCI_A2DP_OFFLOAD_STOP 0x02
/*****************************************************************************
* Global data
****************************************************************************/
@@ -574,7 +645,7 @@
extern tBTA_AV_CB bta_av_cb;
/* config struct */
-extern tBTA_AV_CFG* p_bta_av_cfg;
+extern const tBTA_AV_CFG* p_bta_av_cfg;
extern const tBTA_AV_CFG bta_avk_cfg;
extern const tBTA_AV_CFG bta_av_cfg;
extern const tBTA_AV_CFG bta_av_cfg_compatibility;
@@ -585,7 +656,6 @@
extern const tBTA_AV_SACT bta_av_a2dp_action[];
extern const tBTA_AV_CO_FUNCTS bta_av_a2dp_cos;
-extern tAVDT_CTRL_CBACK* const bta_av_dt_cback[];
extern void bta_av_sink_data_cback(uint8_t handle, BT_HDR* p_pkt,
uint32_t time_stamp, uint8_t m_pt);
@@ -596,9 +666,9 @@
extern tBTA_AV_SCB* bta_av_hndl_to_scb(uint16_t handle);
extern bool bta_av_chk_start(tBTA_AV_SCB* p_scb);
extern void bta_av_restore_switch(void);
-extern uint16_t bta_av_chk_mtu(tBTA_AV_SCB* p_scb, uint16_t mtu);
-extern void bta_av_conn_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
+extern void bta_av_conn_cback(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index);
extern uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl,
uint8_t lidx);
extern void bta_av_stream_chg(tBTA_AV_SCB* p_scb, bool started);
@@ -608,6 +678,8 @@
extern bool bta_av_is_scb_init(tBTA_AV_SCB* p_scb);
extern void bta_av_set_scb_sst_incoming(tBTA_AV_SCB* p_scb);
extern tBTA_AV_LCB* bta_av_find_lcb(const RawAddress& addr, uint8_t op);
+extern const char* bta_av_sst_code(uint8_t state);
+extern void bta_av_free_scb(tBTA_AV_SCB* p_scb);
/* main functions */
extern void bta_av_api_deregister(tBTA_AV_DATA* p_data);
@@ -620,7 +692,6 @@
extern const char* bta_av_evt_code(uint16_t evt_code);
extern bool bta_av_switch_if_needed(tBTA_AV_SCB* p_scb);
extern bool bta_av_link_role_ok(tBTA_AV_SCB* p_scb, uint8_t bits);
-extern bool bta_av_is_rcfg_sst(tBTA_AV_SCB* p_scb);
/* nsm action functions */
extern void bta_av_api_disconnect(tBTA_AV_DATA* p_data);
@@ -649,6 +720,10 @@
extern tBTA_AV_RCB* bta_av_get_rcb_by_shdl(uint8_t shdl);
extern void bta_av_del_rc(tBTA_AV_RCB* p_rcb);
+extern void bta_av_proc_stream_evt(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index);
+
/* ssm action functions */
extern void bta_av_do_disc_a2dp(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
extern void bta_av_cleanup(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
@@ -701,5 +776,6 @@
extern void bta_av_open_at_inc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
extern void bta_av_offload_req(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
extern void bta_av_offload_rsp(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
+extern void bta_av_vendor_offload_stop(void);
#endif /* BTA_AV_INT_H */
diff --git a/bta/av/bta_av_main.cc b/bta/av/bta_av_main.cc
index 0d7c360..3679469 100644
--- a/bta/av/bta_av_main.cc
+++ b/bta/av/bta_av_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
#include "bta_av_co.h"
#include "bta_av_int.h"
#include "btif/include/btif_av_co.h"
+#include "btif/include/btif_config.h"
#include "l2c_api.h"
#include "l2cdefs.h"
#include "utl.h"
@@ -84,6 +85,10 @@
#define AVRCP_1_3_STRING "avrcp13"
#endif
+#ifndef AVRCP_DEFAULT_VERSION
+#define AVRCP_DEFAULT_VERSION AVRCP_1_4_STRING
+#endif
+
/* state machine states */
enum { BTA_AV_INIT_ST, BTA_AV_OPEN_ST };
@@ -165,15 +170,13 @@
static void bta_av_api_enable(tBTA_AV_DATA* p_data);
static void bta_av_api_register(tBTA_AV_DATA* p_data);
static void bta_av_ci_data(tBTA_AV_DATA* p_data);
-#if (AVDT_REPORTING == TRUE)
static void bta_av_rpc_conn(tBTA_AV_DATA* p_data);
-#endif
static void bta_av_api_to_ssm(tBTA_AV_DATA* p_data);
static void bta_av_sco_chg_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
- uint8_t app_id, const RawAddress* peer_addr);
+ uint8_t app_id, const RawAddress& peer_addr);
static void bta_av_sys_rs_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
- uint8_t app_id, const RawAddress* peer_addr);
+ uint8_t app_id, const RawAddress& peer_addr);
/* action functions */
const tBTA_AV_NSM_ACT bta_av_nsm_act[] = {
@@ -190,9 +193,7 @@
bta_av_rc_browse_closed, /* BTA_AV_AVRC_BROWSE_CLOSE_EVT */
bta_av_conn_chg, /* BTA_AV_CONN_CHG_EVT */
bta_av_dereg_comp, /* BTA_AV_DEREG_COMP_EVT */
-#if (AVDT_REPORTING == TRUE)
bta_av_rpc_conn, /* BTA_AV_AVDT_RPT_CONN_EVT */
-#endif
bta_av_api_to_ssm, /* BTA_AV_API_START_EVT */
bta_av_api_to_ssm, /* BTA_AV_API_STOP_EVT */
};
@@ -267,7 +268,7 @@
for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
if (bta_av_cb.p_scb[xx]) {
- if (bd_addr == bta_av_cb.p_scb[xx]->peer_addr) {
+ if (bd_addr == bta_av_cb.p_scb[xx]->PeerAddress()) {
p_scb = bta_av_cb.p_scb[xx];
break;
}
@@ -276,6 +277,27 @@
return p_scb;
}
+int BTA_AvObtainPeerChannelIndex(const RawAddress& peer_address) {
+ // Find the entry for the peer (if exists)
+ tBTA_AV_SCB* p_scb = bta_av_addr_to_scb(peer_address);
+ if (p_scb != nullptr) {
+ return p_scb->hdi;
+ }
+
+ // Find the index for an entry that is not used
+ for (int index = 0; index < BTA_AV_NUM_STRS; index++) {
+ tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[index];
+ if (p_scb == nullptr) {
+ continue;
+ }
+ if (p_scb->PeerAddress().IsEmpty()) {
+ return p_scb->hdi;
+ }
+ }
+
+ return -1;
+}
+
/*******************************************************************************
*
* Function bta_av_hndl_to_scb
@@ -308,49 +330,79 @@
*
******************************************************************************/
static tBTA_AV_SCB* bta_av_alloc_scb(tBTA_AV_CHNL chnl) {
- tBTA_AV_SCB* p_ret = NULL;
- int xx;
- tBTA_AV_STATUS sts = BTA_AV_SUCCESS;
-
- if (chnl == BTA_AV_CHNL_VIDEO) {
- if (p_bta_av_cfg->p_act_tbl == NULL || p_bta_av_cfg->p_reg == NULL) {
- APPL_TRACE_ERROR("Video streaming not supported");
- sts = BTA_AV_FAIL;
- } else {
- /* allow only one Video channel */
- if (bta_av_cb.reg_video) {
- APPL_TRACE_ERROR("Already registered");
- sts = BTA_AV_FAIL;
- }
- }
- } else if (chnl != BTA_AV_CHNL_AUDIO) {
- APPL_TRACE_ERROR("bad channel: %d", chnl);
- sts = BTA_AV_FAIL;
+ if (chnl != BTA_AV_CHNL_AUDIO) {
+ APPL_TRACE_ERROR("%s: bad channel: %d", __func__, chnl);
+ return nullptr;
}
- if (sts == BTA_AV_SUCCESS) {
- for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
- if (bta_av_cb.p_scb[xx] == NULL) {
- /* found an empty spot */
- p_ret = (tBTA_AV_SCB*)osi_calloc(sizeof(tBTA_AV_SCB));
- p_ret->rc_handle = BTA_AV_RC_HANDLE_NONE;
- p_ret->chnl = chnl;
- p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl);
- p_ret->hdi = xx;
- p_ret->a2dp_list = list_new(NULL);
- p_ret->avrc_ct_timer = alarm_new("bta_av.avrc_ct_timer");
- bta_av_cb.p_scb[xx] = p_ret;
- break;
- }
- }
+ for (int xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
+ if (bta_av_cb.p_scb[xx] != nullptr) continue;
+ // Found an empty spot
+ // TODO: After tBTA_AV_SCB is changed to a proper class, the entry
+ // here should be allocated by C++ 'new' statement.
+ tBTA_AV_SCB* p_ret = (tBTA_AV_SCB*)osi_calloc(sizeof(tBTA_AV_SCB));
+ p_ret->rc_handle = BTA_AV_RC_HANDLE_NONE;
+ p_ret->chnl = chnl;
+ p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl);
+ p_ret->hdi = xx;
+ p_ret->a2dp_list = list_new(nullptr);
+ p_ret->avrc_ct_timer = alarm_new("bta_av.avrc_ct_timer");
+ bta_av_cb.p_scb[xx] = p_ret;
+ return p_ret;
}
- return p_ret;
+
+ return nullptr;
+}
+
+void bta_av_free_scb(tBTA_AV_SCB* p_scb) {
+ if (p_scb == nullptr) return;
+ uint8_t scb_index = p_scb->hdi;
+ CHECK(scb_index < BTA_AV_NUM_STRS);
+
+ CHECK(p_scb == bta_av_cb.p_scb[scb_index]);
+ bta_av_cb.p_scb[scb_index] = nullptr;
+ alarm_free(p_scb->avrc_ct_timer);
+ // TODO: After tBTA_AV_SCB is changed to a proper class, the entry
+ // here should be de-allocated by C++ 'delete' statement.
+ osi_free(p_scb);
+}
+
+void tBTA_AV_SCB::OnConnected(const RawAddress& peer_address) {
+ peer_address_ = peer_address;
+
+ if (peer_address.IsEmpty()) {
+ LOG_ERROR(LOG_TAG, "%s: Invalid peer address: %s", __func__,
+ peer_address.ToString().c_str());
+ return;
+ }
+
+ // Read and restore the AVDTP version from local storage
+ uint16_t avdtp_version = 0;
+ size_t version_value_size = sizeof(avdtp_version);
+ if (!btif_config_get_bin(peer_address_.ToString(), AVDTP_VERSION_CONFIG_KEY,
+ (uint8_t*)&avdtp_version, &version_value_size)) {
+ LOG_WARN(LOG_TAG, "%s: Failed to read cached peer AVDTP version for %s",
+ __func__, peer_address_.ToString().c_str());
+ } else {
+ SetAvdtpVersion(avdtp_version);
+ }
+}
+
+void tBTA_AV_SCB::OnDisconnected() {
+ peer_address_ = RawAddress::kEmpty;
+ SetAvdtpVersion(0);
+}
+
+void tBTA_AV_SCB::SetAvdtpVersion(uint16_t avdtp_version) {
+ avdtp_version_ = avdtp_version;
+ LOG_DEBUG(LOG_TAG, "%s: AVDTP version for %s set to 0x%x", __func__,
+ peer_address_.ToString().c_str(), avdtp_version_);
}
/*******************************************************************************
******************************************************************************/
-void bta_av_conn_cback(UNUSED_ATTR uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
+void bta_av_conn_cback(UNUSED_ATTR uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data, uint8_t scb_index) {
uint16_t evt = 0;
tBTA_AV_SCB* p_scb = NULL;
@@ -363,7 +415,7 @@
{
evt = BTA_AV_SIG_CHG_EVT;
if (event == AVDT_DISCONNECT_IND_EVT) {
- p_scb = bta_av_addr_to_scb(*bd_addr);
+ p_scb = bta_av_addr_to_scb(bd_addr);
} else if (event == AVDT_CONNECT_IND_EVT) {
APPL_TRACE_DEBUG("%s: CONN_IND is ACP:%d", __func__,
p_data->hdr.err_param);
@@ -374,16 +426,18 @@
p_msg->hdr.event = evt;
p_msg->hdr.layer_specific = event;
p_msg->hdr.offset = p_data->hdr.err_param;
- p_msg->bd_addr = *bd_addr;
+ p_msg->bd_addr = bd_addr;
+ p_msg->scb_index = scb_index;
if (p_scb) {
- APPL_TRACE_DEBUG("scb hndl x%x, role x%x", p_scb->hndl, p_scb->role);
+ APPL_TRACE_DEBUG("%s: scb hndl x%x, role x%x", __func__, p_scb->hndl,
+ p_scb->role);
}
- VLOG(1) << "conn_cback bd_addr:" << bd_addr;
+ LOG_INFO(LOG_TAG, "%s: conn_cback bd_addr: %s", __func__,
+ bd_addr.ToString().c_str());
bta_sys_sendmsg(p_msg);
}
}
-#if (AVDT_REPORTING == TRUE)
/*******************************************************************************
*
* Function bta_av_a2dp_report_cback
@@ -399,7 +453,6 @@
/* Do not need to handle report data for now.
* This empty function is here for conformance reasons. */
}
-#endif
/*******************************************************************************
*
@@ -415,43 +468,45 @@
static void bta_av_api_register(tBTA_AV_DATA* p_data) {
tBTA_AV_REGISTER registr;
tBTA_AV_SCB* p_scb; /* stream control block */
- tAVDT_REG reg;
- tAVDT_CS cs;
+ AvdtpRcb reg;
+ AvdtpStreamConfig avdtp_stream_config;
char* p_service_name;
tBTA_UTL_COD cod;
- memset(&cs, 0, sizeof(tAVDT_CS));
+ avdtp_stream_config.Reset();
registr.status = BTA_AV_FAIL_RESOURCES;
registr.app_id = p_data->api_reg.app_id;
registr.chnl = (tBTA_AV_CHNL)p_data->hdr.layer_specific;
char avrcp_version[PROPERTY_VALUE_MAX] = {0};
- osi_property_get(AVRCP_VERSION_PROPERTY, avrcp_version, AVRCP_1_4_STRING);
- LOG_INFO(LOG_TAG, "AVRCP version used for sdp: \"%s\"", avrcp_version);
+ osi_property_get(AVRCP_VERSION_PROPERTY, avrcp_version,
+ AVRCP_DEFAULT_VERSION);
+ LOG_INFO(LOG_TAG, "%s: AVRCP version used for sdp: \"%s\"", __func__,
+ avrcp_version);
uint16_t profile_initialized = p_data->api_reg.service_uuid;
if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
- p_bta_av_cfg = (tBTA_AV_CFG*)&bta_avk_cfg;
+ p_bta_av_cfg = &bta_avk_cfg;
} else if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
- p_bta_av_cfg = (tBTA_AV_CFG*)&bta_av_cfg;
+ p_bta_av_cfg = &bta_av_cfg;
if (!strncmp(AVRCP_1_3_STRING, avrcp_version, sizeof(AVRCP_1_3_STRING))) {
- LOG_INFO(LOG_TAG, "AVRCP 1.3 capabilites used");
- p_bta_av_cfg = (tBTA_AV_CFG*)&bta_av_cfg_compatibility;
+ LOG_INFO(LOG_TAG, "%s: AVRCP 1.3 capabilites used", __func__);
+ p_bta_av_cfg = &bta_av_cfg_compatibility;
}
}
APPL_TRACE_DEBUG("%s: profile: 0x%x", __func__, profile_initialized);
if (p_bta_av_cfg == NULL) {
- APPL_TRACE_ERROR("AV configuration is null!");
+ APPL_TRACE_ERROR("%s: AV configuration is null!", __func__);
return;
}
do {
p_scb = bta_av_alloc_scb(registr.chnl);
if (p_scb == NULL) {
- APPL_TRACE_ERROR("failed to alloc SCB");
+ APPL_TRACE_ERROR("%s: failed to alloc SCB", __func__);
break;
}
@@ -461,13 +516,14 @@
/* initialize the stream control block */
registr.status = BTA_AV_SUCCESS;
- if ((bta_av_cb.reg_audio + bta_av_cb.reg_video) == 0) {
+ if (bta_av_cb.reg_audio == 0) {
/* the first channel registered. register to AVDTP */
reg.ctrl_mtu = p_bta_av_cfg->sig_mtu;
reg.ret_tout = BTA_AV_RET_TOUT;
reg.sig_tout = BTA_AV_SIG_TOUT;
reg.idle_tout = BTA_AV_IDLE_TOUT;
reg.sec_mask = bta_av_cb.sec_mask;
+ reg.scb_index = p_scb->hdi;
#if (BTA_AR_INCLUDED == TRUE)
bta_ar_reg_avdt(®, bta_av_conn_cback, BTA_ID_AV);
#endif
@@ -486,26 +542,21 @@
BTA_ID_AV);
#endif
- /* For the Audio Sink role we support additional TG 1.3 to support
+ /* For the Audio Sink role we support additional TG to support
* absolute volume.
*/
uint16_t profile_version = AVRC_REV_1_0;
- if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
- if (!strncmp(AVRCP_1_6_STRING, avrcp_version,
- sizeof(AVRCP_1_6_STRING))) {
- profile_version = AVRC_REV_1_6;
- } else if (!strncmp(AVRCP_1_5_STRING, avrcp_version,
- sizeof(AVRCP_1_5_STRING))) {
- profile_version = AVRC_REV_1_5;
- } else if (!strncmp(AVRCP_1_3_STRING, avrcp_version,
- sizeof(AVRCP_1_3_STRING))) {
- profile_version = AVRC_REV_1_3;
- } else {
- profile_version = AVRC_REV_1_4;
- }
- } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
- // Initialize AVRCP1.4 to provide Absolute Volume control.
+ if (!strncmp(AVRCP_1_6_STRING, avrcp_version,
+ sizeof(AVRCP_1_6_STRING))) {
+ profile_version = AVRC_REV_1_6;
+ } else if (!strncmp(AVRCP_1_5_STRING, avrcp_version,
+ sizeof(AVRCP_1_5_STRING))) {
+ profile_version = AVRC_REV_1_5;
+ } else if (!strncmp(AVRCP_1_3_STRING, avrcp_version,
+ sizeof(AVRCP_1_3_STRING))) {
+ profile_version = AVRC_REV_1_3;
+ } else {
profile_version = AVRC_REV_1_4;
}
@@ -525,11 +576,13 @@
} /* if 1st channel */
/* get stream configuration and create stream */
- cs.cfg.num_codec = 1;
- cs.nsc_mask =
- AVDT_NSC_RECONFIG |
- ((bta_av_cb.features & BTA_AV_FEAT_PROTECT) ? 0 : AVDT_NSC_SECURITY);
- APPL_TRACE_DEBUG("nsc_mask: 0x%x", cs.nsc_mask);
+ avdtp_stream_config.cfg.num_codec = 1;
+ avdtp_stream_config.nsc_mask = AvdtpStreamConfig::AVDT_NSC_RECONFIG;
+ if (!(bta_av_cb.features & BTA_AV_FEAT_PROTECT)) {
+ avdtp_stream_config.nsc_mask |= AvdtpStreamConfig::AVDT_NSC_SECURITY;
+ }
+ APPL_TRACE_DEBUG("%s: nsc_mask: 0x%x", __func__,
+ avdtp_stream_config.nsc_mask);
if (p_data->api_reg.p_service_name[0] == 0) {
p_service_name = NULL;
@@ -539,144 +592,132 @@
p_scb->suspend_sup = true;
p_scb->recfg_sup = true;
- p_scb->skip_sdp = false;
- cs.p_ctrl_cback = bta_av_dt_cback[p_scb->hdi];
- if (registr.chnl == BTA_AV_CHNL_AUDIO) {
- /* set up the audio stream control block */
- p_scb->p_act_tbl = (const tBTA_AV_ACT*)bta_av_a2dp_action;
- p_scb->p_cos = &bta_av_a2dp_cos;
- p_scb->media_type = AVDT_MEDIA_TYPE_AUDIO;
- cs.cfg.psc_mask = AVDT_PSC_TRANS;
- cs.media_type = AVDT_MEDIA_TYPE_AUDIO;
- cs.mtu = p_bta_av_cfg->audio_mtu;
- cs.flush_to = L2CAP_DEFAULT_FLUSH_TO;
- btav_a2dp_codec_index_t codec_index_min =
- BTAV_A2DP_CODEC_INDEX_SOURCE_MIN;
- btav_a2dp_codec_index_t codec_index_max =
- BTAV_A2DP_CODEC_INDEX_SOURCE_MAX;
+ avdtp_stream_config.scb_index = p_scb->hdi;
+ avdtp_stream_config.p_avdt_ctrl_cback = &bta_av_proc_stream_evt;
-#if (AVDT_REPORTING == TRUE)
- if (bta_av_cb.features & BTA_AV_FEAT_REPORT) {
- cs.cfg.psc_mask |= AVDT_PSC_REPORT;
- cs.p_report_cback = bta_av_a2dp_report_cback;
+ /* set up the audio stream control block */
+ p_scb->p_act_tbl = (const tBTA_AV_ACT*)bta_av_a2dp_action;
+ p_scb->p_cos = &bta_av_a2dp_cos;
+ p_scb->media_type = AVDT_MEDIA_TYPE_AUDIO;
+ avdtp_stream_config.cfg.psc_mask = AVDT_PSC_TRANS;
+ avdtp_stream_config.media_type = AVDT_MEDIA_TYPE_AUDIO;
+ avdtp_stream_config.mtu = p_bta_av_cfg->audio_mtu;
+ avdtp_stream_config.flush_to = L2CAP_DEFAULT_FLUSH_TO;
+ btav_a2dp_codec_index_t codec_index_min = BTAV_A2DP_CODEC_INDEX_SOURCE_MIN;
+ btav_a2dp_codec_index_t codec_index_max = BTAV_A2DP_CODEC_INDEX_SOURCE_MAX;
+
+ if (bta_av_cb.features & BTA_AV_FEAT_REPORT) {
+ avdtp_stream_config.cfg.psc_mask |= AVDT_PSC_REPORT;
+ avdtp_stream_config.p_report_cback = bta_av_a2dp_report_cback;
+ }
+ if (bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT)
+ avdtp_stream_config.cfg.psc_mask |= AVDT_PSC_DELAY_RPT;
+
+ if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
+ avdtp_stream_config.tsep = AVDT_TSEP_SRC;
+ codec_index_min = BTAV_A2DP_CODEC_INDEX_SOURCE_MIN;
+ codec_index_max = BTAV_A2DP_CODEC_INDEX_SOURCE_MAX;
+ } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
+ avdtp_stream_config.tsep = AVDT_TSEP_SNK;
+ avdtp_stream_config.p_sink_data_cback = bta_av_sink_data_cback;
+ codec_index_min = BTAV_A2DP_CODEC_INDEX_SINK_MIN;
+ codec_index_max = BTAV_A2DP_CODEC_INDEX_SINK_MAX;
+ }
+
+ /* Initialize handles to zero */
+ for (int xx = 0; xx < BTAV_A2DP_CODEC_INDEX_MAX; xx++) {
+ p_scb->seps[xx].av_handle = 0;
+ }
+
+ /* keep the configuration in the stream control block */
+ p_scb->cfg = avdtp_stream_config.cfg;
+ for (int i = codec_index_min; i < codec_index_max; i++) {
+ btav_a2dp_codec_index_t codec_index =
+ static_cast<btav_a2dp_codec_index_t>(i);
+ if (!(*bta_av_a2dp_cos.init)(codec_index, &avdtp_stream_config.cfg)) {
+ continue;
}
-#endif
- if (bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT)
- cs.cfg.psc_mask |= AVDT_PSC_DELAY_RPT;
-
- if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
- cs.tsep = AVDT_TSEP_SRC;
- codec_index_min = BTAV_A2DP_CODEC_INDEX_SOURCE_MIN;
- codec_index_max = BTAV_A2DP_CODEC_INDEX_SOURCE_MAX;
- } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
- cs.tsep = AVDT_TSEP_SNK;
- cs.p_sink_data_cback = bta_av_sink_data_cback;
- codec_index_min = BTAV_A2DP_CODEC_INDEX_SINK_MIN;
- codec_index_max = BTAV_A2DP_CODEC_INDEX_SINK_MAX;
+ if (AVDT_CreateStream(p_scb->app_id, &p_scb->seps[codec_index].av_handle,
+ avdtp_stream_config) != AVDT_SUCCESS) {
+ continue;
}
-
- /* Initialize handles to zero */
- for (int xx = 0; xx < BTAV_A2DP_CODEC_INDEX_MAX; xx++) {
- p_scb->seps[xx].av_handle = 0;
- }
-
- /* keep the configuration in the stream control block */
- memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
- for (int i = codec_index_min; i < codec_index_max; i++) {
- btav_a2dp_codec_index_t codec_index =
- static_cast<btav_a2dp_codec_index_t>(i);
- if (!(*bta_av_a2dp_cos.init)(codec_index, &cs.cfg)) {
- continue;
- }
- if (AVDT_CreateStream(&p_scb->seps[codec_index].av_handle, &cs) !=
- AVDT_SUCCESS) {
- continue;
- }
- /* Save a copy of the codec */
- memcpy(p_scb->seps[codec_index].codec_info, cs.cfg.codec_info,
- AVDT_CODEC_SIZE);
- p_scb->seps[codec_index].tsep = cs.tsep;
- if (cs.tsep == AVDT_TSEP_SNK) {
- p_scb->seps[codec_index].p_app_sink_data_cback =
- p_data->api_reg.p_app_sink_data_cback;
- } else {
- /* In case of A2DP SOURCE we don't need a callback to
- * handle media packets.
- */
- p_scb->seps[codec_index].p_app_sink_data_cback = NULL;
- }
- }
-
- if (!bta_av_cb.reg_audio) {
- bta_av_cb.sdp_a2dp_handle = 0;
- bta_av_cb.sdp_a2dp_snk_handle = 0;
- if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
- /* create the SDP records on the 1st audio channel */
- bta_av_cb.sdp_a2dp_handle = SDP_CreateRecord();
- A2DP_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL,
- A2DP_SUPF_PLAYER, bta_av_cb.sdp_a2dp_handle);
- bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
- } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
-#if (BTA_AV_SINK_INCLUDED == TRUE)
- bta_av_cb.sdp_a2dp_snk_handle = SDP_CreateRecord();
- A2DP_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_service_name, NULL,
- A2DP_SUPF_PLAYER, bta_av_cb.sdp_a2dp_snk_handle);
- bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);
-#endif
- }
- /* start listening when A2DP is registered */
- if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
- bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
-
- /* if the AV and AVK are both supported, it cannot support the CT role
+ /* Save a copy of the codec */
+ memcpy(p_scb->seps[codec_index].codec_info,
+ avdtp_stream_config.cfg.codec_info, AVDT_CODEC_SIZE);
+ p_scb->seps[codec_index].tsep = avdtp_stream_config.tsep;
+ if (avdtp_stream_config.tsep == AVDT_TSEP_SNK) {
+ p_scb->seps[codec_index].p_app_sink_data_cback =
+ p_data->api_reg.p_app_sink_data_cback;
+ } else {
+ /* In case of A2DP SOURCE we don't need a callback to
+ * handle media packets.
*/
- if (bta_av_cb.features & (BTA_AV_FEAT_RCCT)) {
- /* if TG is not supported, we need to register to AVCT now */
- if ((bta_av_cb.features & (BTA_AV_FEAT_RCTG)) == 0) {
+ p_scb->seps[codec_index].p_app_sink_data_cback = NULL;
+ }
+ }
+
+ if (!bta_av_cb.reg_audio) {
+ bta_av_cb.sdp_a2dp_handle = 0;
+ bta_av_cb.sdp_a2dp_snk_handle = 0;
+ if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
+ /* create the SDP records on the 1st audio channel */
+ bta_av_cb.sdp_a2dp_handle = SDP_CreateRecord();
+ A2DP_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL,
+ A2DP_SUPF_PLAYER, bta_av_cb.sdp_a2dp_handle);
+ bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+ } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
+#if (BTA_AV_SINK_INCLUDED == TRUE)
+ bta_av_cb.sdp_a2dp_snk_handle = SDP_CreateRecord();
+ A2DP_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_service_name, NULL,
+ A2DP_SUPF_PLAYER, bta_av_cb.sdp_a2dp_snk_handle);
+ bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);
+#endif
+ }
+ /* start listening when A2DP is registered */
+ if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
+ bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+
+ /* if the AV and AVK are both supported, it cannot support the CT role
+ */
+ if (bta_av_cb.features & (BTA_AV_FEAT_RCCT)) {
+ /* if TG is not supported, we need to register to AVCT now */
+ if ((bta_av_cb.features & (BTA_AV_FEAT_RCTG)) == 0) {
#if (BTA_AR_INCLUDED == TRUE)
#if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE)
- bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
- bta_av_cb.sec_mask, BTA_ID_AV);
+ bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+ bta_av_cb.sec_mask, BTA_ID_AV);
#else
- bta_ar_reg_avct(
- p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
- (uint8_t)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)),
- BTA_ID_AV);
+ bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+ (uint8_t)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)),
+ BTA_ID_AV);
#endif
#endif
- bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
- }
-#if (BTA_AR_INCLUDED == TRUE)
- /* create an SDP record as AVRC CT. We create 1.3 for SOURCE
- * because we rely on feature bits being scanned by external
- * devices more than the profile version itself.
- *
- * We create 1.4 for SINK since we support browsing.
- */
- if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
- bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
- p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
- (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
- AVRC_REV_1_3);
- } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
- bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
- p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
- (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
- AVRC_REV_1_6);
- }
-#endif
+ bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
}
+#if (BTA_AR_INCLUDED == TRUE)
+ /* create an SDP record as AVRC CT. We create 1.3 for SOURCE
+ * because we rely on feature bits being scanned by external
+ * devices more than the profile version itself.
+ *
+ * We create 1.4 for SINK since we support browsing.
+ */
+ if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
+ bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
+ p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
+ (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
+ AVRC_REV_1_3);
+ } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
+ bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
+ p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
+ (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
+ AVRC_REV_1_6);
+ }
+#endif
}
- bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- APPL_TRACE_DEBUG("reg_audio: 0x%x", bta_av_cb.reg_audio);
- } else {
- bta_av_cb.reg_video = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- bta_av_cb.sdp_vdp_handle = SDP_CreateRecord();
- /* register the video channel */
- /* no need to verify the function pointer here. it's verified prior */
- (*p_bta_av_cfg->p_reg)(&cs, p_service_name, p_scb);
}
+ bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+ APPL_TRACE_DEBUG("%s: reg_audio: 0x%x", __func__, bta_av_cb.reg_audio);
} while (0);
/* call callback with register event */
@@ -699,7 +740,7 @@
tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
if (p_scb) {
- p_scb->deregistring = true;
+ p_scb->deregistering = true;
bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, p_data);
} else {
bta_av_dereg_comp(p_data);
@@ -740,9 +781,7 @@
* Returns void
*
******************************************************************************/
-#if (AVDT_REPORTING == TRUE)
static void bta_av_rpc_conn(UNUSED_ATTR tBTA_AV_DATA* p_data) {}
-#endif
/*******************************************************************************
*
@@ -755,12 +794,13 @@
*
******************************************************************************/
static void bta_av_api_to_ssm(tBTA_AV_DATA* p_data) {
- int xx;
uint16_t event =
p_data->hdr.event - BTA_AV_FIRST_A2S_API_EVT + BTA_AV_FIRST_A2S_SSM_EVT;
+ tBTA_AV_HNDL handle = p_data->hdr.layer_specific;
+ tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(handle);
- for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
- bta_av_ssm_execute(bta_av_cb.p_scb[xx], event, p_data);
+ if (p_scb != nullptr) {
+ bta_av_ssm_execute(p_scb, event, p_data);
}
}
@@ -770,41 +810,42 @@
*
* Description if this is audio channel, check if more than one audio
* channel is connected & already started.
+ * This function needs to be kept very similar to
+ * bta_av_chk_2nd_start
*
* Returns true, if need api_start
*
******************************************************************************/
bool bta_av_chk_start(tBTA_AV_SCB* p_scb) {
bool start = false;
- tBTA_AV_SCB* p_scbi;
- int i;
- if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
- if ((bta_av_cb.audio_open_cnt >= 2) &&
- ((0 ==
- (p_scb->role & BTA_AV_ROLE_AD_ACP)) || /* Outgoing connection or */
- (bta_av_cb.features &
- BTA_AV_FEAT_ACP_START))) /* auto-starting option */
- {
- /* more than one audio channel is connected */
- /* if this is the 2nd stream as ACP, give INT a chance to issue the START
- * command */
- for (i = 0; i < BTA_AV_NUM_STRS; i++) {
- p_scbi = bta_av_cb.p_scb[i];
- if (p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started) {
- start = true;
- /* may need to update the flush timeout of this already started stream
- */
- if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
- p_scbi->co_started = bta_av_cb.audio_open_cnt;
- L2CA_SetFlushTimeout(
- p_scbi->peer_addr,
- p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1]);
- }
+ if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2) &&
+ (((p_scb->role & BTA_AV_ROLE_AD_ACP) == 0) || // Outgoing connection or
+ (bta_av_cb.features & BTA_AV_FEAT_ACP_START))) { // Auto-starting option
+ // More than one audio channel is connected.
+ // If this is the 2nd stream as ACP, give INT a chance to issue the START
+ // command.
+ for (int i = 0; i < BTA_AV_NUM_STRS; i++) {
+ tBTA_AV_SCB* p_scbi = bta_av_cb.p_scb[i];
+ if (p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started) {
+ start = true;
+ // May need to update the flush timeout of this already started stream
+ if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
+ p_scbi->co_started = bta_av_cb.audio_open_cnt;
+ L2CA_SetFlushTimeout(
+ p_scbi->PeerAddress(),
+ p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1]);
}
}
}
}
+
+ LOG_INFO(LOG_TAG,
+ "%s: peer %s channel:%d bta_av_cb.audio_open_cnt:%d role:0x%x "
+ "features:0x%x start:%s",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->chnl,
+ bta_av_cb.audio_open_cnt, p_scb->role, bta_av_cb.features,
+ logbool(start).c_str());
return start;
}
@@ -822,14 +863,15 @@
tBTA_AV_CB* p_cb = &bta_av_cb;
int i;
uint8_t mask;
+ uint8_t set_policy = (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_MASTER_SLAVE_SWITCH);
- APPL_TRACE_DEBUG("reg_audio: 0x%x", bta_av_cb.reg_audio);
+ APPL_TRACE_DEBUG("%s: reg_audio: 0x%x", __func__, bta_av_cb.reg_audio);
for (i = 0; i < BTA_AV_NUM_STRS; i++) {
mask = BTA_AV_HNDL_TO_MSK(i);
if (p_cb->conn_audio == mask) {
if (p_cb->p_scb[i]) {
- bta_sys_set_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH,
- p_cb->p_scb[i]->peer_addr);
+ bta_sys_set_policy(BTA_ID_AV, set_policy,
+ p_cb->p_scb[i]->PeerAddress());
}
break;
}
@@ -847,28 +889,32 @@
******************************************************************************/
static void bta_av_sys_rs_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status,
uint8_t id, uint8_t app_id,
- const RawAddress* peer_addr) {
+ const RawAddress& peer_addr) {
int i;
tBTA_AV_SCB* p_scb = NULL;
uint8_t cur_role;
uint8_t peer_idx = 0;
+ uint8_t set_policy = (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_MASTER_SLAVE_SWITCH);
- APPL_TRACE_DEBUG("bta_av_sys_rs_cback: %d", bta_av_cb.rs_idx);
+ APPL_TRACE_DEBUG(
+ "%s: peer %s new_role:%d hci_status:0x%x bta_av_cb.rs_idx:%d", __func__,
+ peer_addr.ToString().c_str(), id, app_id, bta_av_cb.rs_idx);
+
for (i = 0; i < BTA_AV_NUM_STRS; i++) {
/* loop through all the SCBs to find matching peer addresses and report the
* role change event */
/* note that more than one SCB (a2dp & vdp) maybe waiting for this event */
p_scb = bta_av_cb.p_scb[i];
- if (p_scb && p_scb->peer_addr == *peer_addr) {
+ if (p_scb && p_scb->PeerAddress() == peer_addr) {
tBTA_AV_ROLE_RES* p_buf =
(tBTA_AV_ROLE_RES*)osi_malloc(sizeof(tBTA_AV_ROLE_RES));
- APPL_TRACE_DEBUG("new_role:%d, hci_status:x%x hndl: x%x", id, app_id,
- p_scb->hndl);
+ APPL_TRACE_DEBUG(
+ "%s: peer %s found: new_role:%d, hci_status:0x%x hndl:0x%x", __func__,
+ peer_addr.ToString().c_str(), id, app_id, p_scb->hndl);
/*
if ((id != BTM_ROLE_MASTER) && (app_id != HCI_SUCCESS))
{
- bta_sys_set_policy(BTA_ID_AV,
- (HCI_ENABLE_MASTER_SLAVE_SWITCH|HCI_ENABLE_SNIFF_MODE), p_scb->peer_addr);
+ bta_sys_set_policy(BTA_ID_AV, set_policy, p_scb->PeerAddress());
}
*/
p_buf->hdr.event = BTA_AV_ROLE_CHANGE_EVT;
@@ -883,9 +929,9 @@
/* restore role switch policy, if role switch failed */
if ((HCI_SUCCESS != app_id) &&
- (BTM_GetRole(*peer_addr, &cur_role) == BTM_SUCCESS) &&
+ (BTM_GetRole(peer_addr, &cur_role) == BTM_SUCCESS) &&
(cur_role == BTM_ROLE_SLAVE)) {
- bta_sys_set_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, *peer_addr);
+ bta_sys_set_policy(BTA_ID_AV, set_policy, peer_addr);
}
/* if BTA_AvOpen() was called for other device, which caused the role switch
@@ -896,13 +942,20 @@
p_scb = bta_av_cb.p_scb[bta_av_cb.rs_idx - 1];
}
if (p_scb && p_scb->q_tag == BTA_AV_Q_TAG_OPEN) {
- APPL_TRACE_DEBUG("bta_av_sys_rs_cback: rs_idx(%d), hndl:x%x q_tag: %d",
+ APPL_TRACE_DEBUG("%s: peer %s rs_idx:%d, hndl:0x%x q_tag:%d", __func__,
+ p_scb->PeerAddress().ToString().c_str(),
bta_av_cb.rs_idx, p_scb->hndl, p_scb->q_tag);
- if (HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id)
+ if (HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id) {
p_scb->q_info.open.switch_res = BTA_AV_RS_OK;
- else
+ } else {
+ APPL_TRACE_ERROR(
+ "%s: peer %s (p_scb peer %s) role switch failed: new_role:%d "
+ "hci_status:0x%x",
+ __func__, peer_addr.ToString().c_str(),
+ p_scb->PeerAddress().ToString().c_str(), id, app_id);
p_scb->q_info.open.switch_res = BTA_AV_RS_FAIL;
+ }
/* Continue av open process */
bta_av_do_disc_a2dp(p_scb, (tBTA_AV_DATA*)&(p_scb->q_info.open));
@@ -925,12 +978,12 @@
******************************************************************************/
static void bta_av_sco_chg_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
UNUSED_ATTR uint8_t app_id,
- UNUSED_ATTR const RawAddress* peer_addr) {
+ UNUSED_ATTR const RawAddress& peer_addr) {
tBTA_AV_SCB* p_scb;
int i;
tBTA_AV_API_STOP stop;
- APPL_TRACE_DEBUG("bta_av_sco_chg_cback:%d status:%d", id, status);
+ APPL_TRACE_DEBUG("%s: id:%d status:%d", __func__, id, status);
if (id) {
bta_av_cb.sco_occupied = true;
@@ -938,8 +991,8 @@
for (i = 0; i < BTA_AV_NUM_STRS; i++) {
p_scb = bta_av_cb.p_scb[i];
- if (p_scb && p_scb->co_started && (p_scb->sco_suspend == false)) {
- APPL_TRACE_DEBUG("suspending scb:%d", i);
+ if (p_scb && p_scb->co_started && (!p_scb->sco_suspend)) {
+ APPL_TRACE_DEBUG("%s: suspending scb:%d", __func__, i);
/* scb is used and started, not suspended automatically */
p_scb->sco_suspend = true;
stop.flush = false;
@@ -956,7 +1009,7 @@
if (p_scb && p_scb->sco_suspend) /* scb is used and suspended for SCO */
{
- APPL_TRACE_DEBUG("starting scb:%d", i);
+ APPL_TRACE_DEBUG("%s: starting scb:%d", __func__, i);
bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
}
}
@@ -975,6 +1028,10 @@
*
******************************************************************************/
bool bta_av_switch_if_needed(tBTA_AV_SCB* p_scb) {
+ // TODO: A workaround for devices that are connected first, become
+ // Master, and block follow-up role changes - b/72122792 .
+ return false;
+#if 0
uint8_t role;
bool needed = false;
tBTA_AV_SCB* p_scbi;
@@ -984,19 +1041,18 @@
for (i = 0; i < BTA_AV_NUM_STRS; i++) {
mask = BTA_AV_HNDL_TO_MSK(i);
p_scbi = bta_av_cb.p_scb[i];
- if (p_scbi && (p_scb->hdi != i) && /* not the original channel */
- ((bta_av_cb.conn_audio & mask) || /* connected audio */
- (bta_av_cb.conn_video & mask))) /* connected video */
+ if (p_scbi && (p_scb->hdi != i) && /* not the original channel */
+ ((bta_av_cb.conn_audio & mask))) /* connected audio */
{
- BTM_GetRole(p_scbi->peer_addr, &role);
+ BTM_GetRole(p_scbi->PeerAddress(), &role);
/* this channel is open - clear the role switch link policy for this link
*/
if (BTM_ROLE_MASTER != role) {
if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH,
- p_scbi->peer_addr);
+ p_scbi->PeerAddress());
if (BTM_CMD_STARTED !=
- BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL)) {
+ BTM_SwitchRole(p_scbi->PeerAddress(), BTM_ROLE_MASTER, NULL)) {
/* can not switch role on SCBI
* start the timer on SCB - because this function is ONLY called when
* SCB gets API_OPEN */
@@ -1011,6 +1067,7 @@
}
}
return needed;
+#endif
}
/*******************************************************************************
@@ -1027,20 +1084,26 @@
uint8_t role;
bool is_ok = true;
- if (BTM_GetRole(p_scb->peer_addr, &role) == BTM_SUCCESS) {
- LOG_INFO(LOG_TAG, "%s hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x",
- __func__, p_scb->hndl, role, bta_av_cb.conn_audio, bits,
- bta_av_cb.features);
+ if (BTM_GetRole(p_scb->PeerAddress(), &role) == BTM_SUCCESS) {
+ LOG_INFO(
+ LOG_TAG,
+ "%s: peer %s hndl:0x%x role:%d conn_audio:0x%x bits:%d features:0x%x",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->hndl, role,
+ bta_av_cb.conn_audio, bits, bta_av_cb.features);
if (BTM_ROLE_MASTER != role &&
(A2DP_BitsSet(bta_av_cb.conn_audio) > bits ||
(bta_av_cb.features & BTA_AV_FEAT_MASTER))) {
if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH,
- p_scb->peer_addr);
+ p_scb->PeerAddress());
- if (BTM_CMD_STARTED !=
- BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL)) {
+ tBTM_STATUS status =
+ BTM_SwitchRole(p_scb->PeerAddress(), BTM_ROLE_MASTER, NULL);
+ if (status != BTM_CMD_STARTED) {
/* can not switch role on SCB - start the timer on SCB */
+ LOG_ERROR(LOG_TAG,
+ "%s: peer %s BTM_SwitchRole(BTM_ROLE_MASTER) error: %d",
+ __func__, p_scb->PeerAddress().ToString().c_str(), status);
}
is_ok = false;
p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_START;
@@ -1052,46 +1115,6 @@
/*******************************************************************************
*
- * Function bta_av_chk_mtu
- *
- * Description if this is audio channel, check if more than one audio
- * channel is connected.
- *
- * Returns The smallest mtu of the connected audio channels
- *
- ******************************************************************************/
-uint16_t bta_av_chk_mtu(tBTA_AV_SCB* p_scb, UNUSED_ATTR uint16_t mtu) {
- uint16_t ret_mtu = BTA_AV_MAX_A2DP_MTU;
- tBTA_AV_SCB* p_scbi;
- int i;
- uint8_t mask;
-
- /* TODO_MV mess with the mtu according to the number of EDR/non-EDR headsets
- */
- if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
- if (bta_av_cb.audio_open_cnt >= 2) {
- /* more than one audio channel is connected */
- for (i = 0; i < BTA_AV_NUM_STRS; i++) {
- p_scbi = bta_av_cb.p_scb[i];
- if ((p_scb != p_scbi) && p_scbi &&
- (p_scbi->chnl == BTA_AV_CHNL_AUDIO)) {
- mask = BTA_AV_HNDL_TO_MSK(i);
- APPL_TRACE_DEBUG("[%d] mtu: %d, mask:0x%x", i, p_scbi->stream_mtu,
- mask);
- if (bta_av_cb.conn_audio & mask) {
- if (ret_mtu > p_scbi->stream_mtu) ret_mtu = p_scbi->stream_mtu;
- }
- }
- }
- }
- APPL_TRACE_DEBUG("bta_av_chk_mtu audio count:%d, conn_audio:0x%x, ret:%d",
- bta_av_cb.audio_open_cnt, bta_av_cb.conn_audio, ret_mtu);
- }
- return ret_mtu;
-}
-
-/*******************************************************************************
- *
* Function bta_av_dup_audio_buf
*
* Description dup the audio data to the q_info.a2dp of other audio
@@ -1121,7 +1144,7 @@
if (list_length(p_scbi->a2dp_list) > p_bta_av_cfg->audio_mqs) {
// Drop the oldest packet
- bta_av_co_audio_drop(p_scbi->hndl);
+ bta_av_co_audio_drop(p_scbi->hndl, p_scbi->PeerAddress());
BT_HDR* p_buf_drop = static_cast<BT_HDR*>(list_front(p_scbi->a2dp_list));
list_remove(p_scbi->a2dp_list, p_buf_drop);
osi_free(p_buf_drop);
@@ -1154,12 +1177,13 @@
/* set next state */
p_cb->state = state_table[event][BTA_AV_NEXT_STATE];
- APPL_TRACE_EVENT("next state=%d event offset:%d", p_cb->state, event);
+ APPL_TRACE_EVENT("%s: next state=%d event offset:%d", __func__, p_cb->state,
+ event);
/* execute action functions */
action = state_table[event][BTA_AV_ACTION_COL];
if (action != BTA_AV_IGNORE) {
- APPL_TRACE_EVENT("%s action executed %d", __func__, action);
+ APPL_TRACE_EVENT("%s: action executed %d", __func__, action);
(*bta_av_action[action])(p_cb, p_data);
}
}
@@ -1191,7 +1215,7 @@
/* state machine events */
bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA*)p_msg);
} else {
- APPL_TRACE_VERBOSE("handle=0x%x", p_msg->layer_specific);
+ APPL_TRACE_VERBOSE("%s: handle=0x%x", __func__, p_msg->layer_specific);
/* stream state machine events */
bta_av_ssm_execute(bta_av_hndl_to_scb(p_msg->layer_specific), p_msg->event,
(tBTA_AV_DATA*)p_msg);
@@ -1346,10 +1370,8 @@
return "CONN_CHG";
case BTA_AV_DEREG_COMP_EVT:
return "DEREG_COMP";
-#if (AVDT_REPORTING == TRUE)
case BTA_AV_AVDT_RPT_CONN_EVT:
return "RPT_CONN";
-#endif
case BTA_AV_API_START_EVT:
return "API_START";
case BTA_AV_API_STOP_EVT:
@@ -1358,3 +1380,109 @@
return "unknown";
}
}
+
+void bta_debug_av_dump(int fd) {
+ dprintf(fd, "\nBTA AV State:\n");
+ dprintf(fd, " State Machine State: %s\n", bta_av_st_code(bta_av_cb.state));
+ dprintf(fd, " Link signalling timer: %s\n",
+ alarm_is_scheduled(bta_av_cb.link_signalling_timer)
+ ? "Scheduled"
+ : "Not scheduled");
+ dprintf(fd, " Accept signalling timer: %s\n",
+ alarm_is_scheduled(bta_av_cb.accept_signalling_timer)
+ ? "Scheduled"
+ : "Not scheduled");
+ dprintf(fd, " SDP A2DP source handle: %d\n", bta_av_cb.sdp_a2dp_handle);
+ dprintf(fd, " SDP A2DP sink handle: %d\n", bta_av_cb.sdp_a2dp_snk_handle);
+ dprintf(fd, " Features: 0x%x\n", bta_av_cb.features);
+ dprintf(fd, " Security mask: 0x%x\n", bta_av_cb.sec_mask);
+ dprintf(fd, " SDP handle: %d\n", bta_av_cb.handle);
+ dprintf(fd, " Disabling: %s\n", bta_av_cb.disabling ? "true" : "false");
+ dprintf(fd, " SCO occupied: %s\n",
+ bta_av_cb.sco_occupied ? "true" : "false");
+ dprintf(fd, " Connected audio channels: %d\n", bta_av_cb.audio_open_cnt);
+ dprintf(fd, " Connected audio channels mask: 0x%x\n", bta_av_cb.conn_audio);
+ dprintf(fd, " Streaming audio channels mask: 0x%x\n",
+ bta_av_cb.audio_streams);
+ dprintf(fd, " Registered audio channels mask: 0x%x\n", bta_av_cb.reg_audio);
+ dprintf(fd, " Connected LCBs mask: 0x%x\n", bta_av_cb.conn_lcb);
+
+ for (size_t i = 0; i < sizeof(bta_av_cb.lcb) / sizeof(bta_av_cb.lcb[0]);
+ i++) {
+ const tBTA_AV_LCB& lcb = bta_av_cb.lcb[i];
+ dprintf(fd, "\n Link control block: %zu peer: %s\n", i,
+ lcb.addr.ToString().c_str());
+ dprintf(fd, " Connected stream handle mask: 0x%x\n", lcb.conn_msk);
+ dprintf(fd, " Index(+1) to LCB: %d\n", lcb.lidx);
+ }
+ for (size_t i = 0; i < BTA_AV_NUM_STRS; i++) {
+ const tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[i];
+ if (p_scb == nullptr) {
+ continue;
+ }
+ dprintf(fd, "\n BTA ID: %zu peer: %s\n", i,
+ p_scb->PeerAddress().ToString().c_str());
+ dprintf(fd, " SDP discovery started: %s\n",
+ p_scb->sdp_discovery_started ? "true" : "false");
+ for (size_t j = 0; j < BTAV_A2DP_CODEC_INDEX_MAX; j++) {
+ const tBTA_AV_SEP& sep = p_scb->seps[j];
+ dprintf(fd, " SEP ID: %zu\n", j);
+ dprintf(fd, " SEP AVDTP handle: %d\n", sep.av_handle);
+ dprintf(fd, " Local SEP type: %d\n", sep.tsep);
+ dprintf(fd, " Codec: %s\n", A2DP_CodecName(sep.codec_info));
+ }
+ dprintf(fd, " BTA info tag: %d\n", p_scb->q_tag);
+ dprintf(fd, " API Open peer: %s\n",
+ p_scb->q_info.open.bd_addr.ToString().c_str());
+ dprintf(fd, " Use AVRCP: %s\n",
+ p_scb->q_info.open.use_rc ? "true" : "false");
+ dprintf(fd, " Security mask: 0x%x\n", p_scb->q_info.open.sec_mask);
+ dprintf(fd, " Switch result: %d\n", p_scb->q_info.open.switch_res);
+ dprintf(fd, " Initiator UUID: 0x%x\n", p_scb->q_info.open.uuid);
+ dprintf(fd, " Saved API Open peer: %s\n",
+ p_scb->open_api.bd_addr.ToString().c_str());
+ dprintf(fd, " Use AVRCP: %s\n",
+ p_scb->open_api.use_rc ? "true" : "false");
+ dprintf(fd, " Security mask: 0x%x\n", p_scb->open_api.sec_mask);
+ dprintf(fd, " Switch result: %d\n", p_scb->open_api.switch_res);
+ dprintf(fd, " Initiator UUID: 0x%x\n", p_scb->open_api.uuid);
+ // TODO: Print p_scb->sep_info[], cfg, avrc_ct_timer, current_codec ?
+ dprintf(fd, " L2CAP Channel ID: %d\n", p_scb->l2c_cid);
+ dprintf(fd, " Stream MTU: %d\n", p_scb->stream_mtu);
+ dprintf(fd, " AVDTP version: 0x%x\n", p_scb->AvdtpVersion());
+ dprintf(fd, " Security mask: 0x%x\n", p_scb->sec_mask);
+ dprintf(fd, " Media type: %d\n", p_scb->media_type);
+ dprintf(fd, " Congested: %s\n", p_scb->cong ? "true" : "false");
+ dprintf(fd, " Open status: %d\n", p_scb->open_status);
+ dprintf(fd, " Channel: %d\n", p_scb->chnl);
+ dprintf(fd, " BTA handle: 0x%x\n", p_scb->hndl);
+ dprintf(fd, " Protocol service capabilities mask: 0x%x\n",
+ p_scb->cur_psc_mask);
+ dprintf(fd, " AVDTP handle: %d\n", p_scb->avdt_handle);
+ dprintf(fd, " Stream control block index: %d\n", p_scb->hdi);
+ dprintf(fd, " State machine state: %s(%d)\n",
+ bta_av_sst_code(p_scb->state), p_scb->state);
+ dprintf(fd, " AVDTP label: 0x%x\n", p_scb->avdt_label);
+ dprintf(fd, " Application ID: %d\n", p_scb->app_id);
+ dprintf(fd, " Role: 0x%x\n", p_scb->role);
+ dprintf(fd, " Queued L2CAP buffers: %d\n", p_scb->l2c_bufs);
+ dprintf(fd, " AVRCP allowed: %s\n", p_scb->use_rc ? "true" : "false");
+ dprintf(fd, " Stream started: %s\n", p_scb->started ? "true" : "false");
+ dprintf(fd, " Stream call-out started: %d\n", p_scb->co_started);
+ dprintf(fd, " AVDTP Reconfig supported: %s\n",
+ p_scb->recfg_sup ? "true" : "false");
+ dprintf(fd, " AVDTP Suspend supported: %s\n",
+ p_scb->suspend_sup ? "true" : "false");
+ dprintf(fd, " Deregistering: %s\n",
+ p_scb->deregistering ? "true" : "false");
+ dprintf(fd, " SCO automatic Suspend: %s\n",
+ p_scb->sco_suspend ? "true" : "false");
+ dprintf(fd, " Incoming/outgoing connection collusion mask: 0x%x\n",
+ p_scb->coll_mask);
+ dprintf(fd, " Wait mask: 0x%x\n", p_scb->wait);
+ dprintf(fd, " Don't use RTP header: %s\n",
+ p_scb->no_rtp_header ? "true" : "false");
+ dprintf(fd, " Intended UUID of Initiator to connect to: 0x%x\n",
+ p_scb->uuid_int);
+ }
+}
diff --git a/bta/av/bta_av_ssm.cc b/bta/av/bta_av_ssm.cc
index 3036e712..6c384e0 100644
--- a/bta/av/bta_av_ssm.cc
+++ b/bta/av/bta_av_ssm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -107,8 +107,8 @@
/* state table for init state */
static const uint8_t bta_av_sst_init[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_DO_DISC, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_CLEANUP, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* API_OPEN_EVT */ {BTA_AV_DO_DISC, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* API_CLOSE_EVT */ {BTA_AV_CLEANUP, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
@@ -117,8 +117,8 @@
/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_DISC_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
@@ -130,179 +130,180 @@
/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_CLOSE_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AVDT_DISCONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AVDT_DELAY_RPT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_INIT_SST}};
/* state table for incoming state */
static const uint8_t bta_av_sst_incoming[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_OPEN_AT_INC, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_CCO_CLOSE, BTA_AV_DISCONNECT_REQ,
- BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_OPEN_AT_INC, BTA_AV_SIGNORE,
+ BTA_AV_INCOMING_SST},
+ /* API_CLOSE_EVT */
+ {BTA_AV_CCO_CLOSE, BTA_AV_DISCONNECT_REQ, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* API_PROTECT_REQ_EVT */ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* API_PROTECT_RSP_EVT */ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* CI_SETCONFIG_OK_EVT */ {BTA_AV_SETCONFIG_RSP, BTA_AV_ST_RC_TIMER,
- BTA_AV_INCOMING_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_CLEANUP,
- BTA_AV_INIT_SST},
- /* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_DISC_OK_EVT */ {BTA_AV_DISC_RES_AS_ACP, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_DISC_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_GETCAP_OK_EVT */ {BTA_AV_SAVE_CAPS, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_GETCAP_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
+ /* API_RECONFIG_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* API_PROTECT_REQ_EVT */
+ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* API_PROTECT_RSP_EVT */
+ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* API_RC_OPEN_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* SRC_DATA_READY_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* CI_SETCONFIG_OK_EVT */
+ {BTA_AV_SETCONFIG_RSP, BTA_AV_ST_RC_TIMER, BTA_AV_INCOMING_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_CLEANUP, BTA_AV_INIT_SST},
+ /* SDP_DISC_OK_EVT */
+ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* SDP_DISC_FAIL_EVT */
+ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_DISC_OK_EVT */
+ {BTA_AV_DISC_RES_AS_ACP, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_DISC_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_GETCAP_OK_EVT */
+ {BTA_AV_SAVE_CAPS, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_GETCAP_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* STR_OPEN_OK_EVT */ {BTA_AV_STR_OPENED, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* STR_OPEN_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
+ /* STR_OPEN_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_START_OK_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_START_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* STR_CLOSE_EVT */ {BTA_AV_CCO_CLOSE, BTA_AV_CLEANUP, BTA_AV_INIT_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_WRITE_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_CCO_CLOSE, BTA_AV_DISCONNECT_REQ,
- BTA_AV_CLOSING_SST},
+ /* AVDT_CONNECT_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_CCO_CLOSE, BTA_AV_DISCONNECT_REQ, BTA_AV_CLOSING_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
+ /* AVDT_DELAY_RPT_EVT */
+ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST}};
/* state table for opening state */
static const uint8_t bta_av_sst_opening[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* API_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* API_PROTECT_REQ_EVT */ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* API_PROTECT_RSP_EVT */ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
+ /* API_PROTECT_REQ_EVT */
+ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* API_PROTECT_RSP_EVT */
+ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* SDP_DISC_OK_EVT */ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* SDP_DISC_FAIL_EVT */ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_DISC_OK_EVT */ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_DISC_FAIL_EVT */ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_GETCAP_OK_EVT */ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_GETCAP_FAIL_EVT */ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_OPEN_OK_EVT */ {BTA_AV_ST_RC_TIMER, BTA_AV_STR_OPENED,
- BTA_AV_OPEN_SST},
- /* STR_OPEN_FAIL_EVT */ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* SRC_DATA_READY_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* CI_SETCONFIG_OK_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* SDP_DISC_OK_EVT */
+ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* SDP_DISC_FAIL_EVT */
+ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_DISC_OK_EVT */
+ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_DISC_FAIL_EVT */
+ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_GETCAP_OK_EVT */
+ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_GETCAP_FAIL_EVT */
+ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_OPEN_OK_EVT */
+ {BTA_AV_ST_RC_TIMER, BTA_AV_STR_OPENED, BTA_AV_OPEN_SST},
+ /* STR_OPEN_FAIL_EVT */
+ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
+ /* STR_START_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* STR_CLOSE_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* AVRC_TIMER_EVT */ {BTA_AV_SWITCH_ROLE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* AVDT_CONNECT_EVT */ {BTA_AV_DISCOVER_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_CONN_FAILED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_WRITE_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* AVRC_TIMER_EVT */
+ {BTA_AV_SWITCH_ROLE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* AVDT_CONNECT_EVT */
+ {BTA_AV_DISCOVER_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_CONN_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_ROLE_RES, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
+ /* AVDT_DELAY_RPT_EVT */
+ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_OPENING_SST}};
/* state table for open state */
static const uint8_t bta_av_sst_open[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* API_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_DO_START, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* AP_STOP_EVT */ {BTA_AV_STR_STOPPED, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* API_RECONFIG_EVT */ {BTA_AV_RECONFIG, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* API_PROTECT_REQ_EVT */ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* API_PROTECT_RSP_EVT */ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
+ /* API_PROTECT_REQ_EVT */
+ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* API_PROTECT_RSP_EVT */
+ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* API_RC_OPEN_EVT */ {BTA_AV_SET_USE_RC, BTA_AV_OPEN_RC, BTA_AV_OPEN_SST},
- /* SRC_DATA_READY_EVT */ {BTA_AV_DATA_PATH, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
+ /* SRC_DATA_READY_EVT */
+ {BTA_AV_DATA_PATH, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* STR_DISC_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
@@ -312,40 +313,40 @@
/* STR_OPEN_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* STR_OPEN_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* STR_START_OK_EVT */ {BTA_AV_START_OK, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* STR_START_FAIL_EVT */ {BTA_AV_START_FAILED, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
+ /* STR_START_FAIL_EVT */
+ {BTA_AV_START_FAILED, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* STR_CLOSE_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* STR_WRITE_CFM_EVT */ {BTA_AV_CLR_CONG, BTA_AV_DATA_PATH,
- BTA_AV_OPEN_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SUSPEND_CFM, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* AVRC_TIMER_EVT */ {BTA_AV_OPEN_RC, BTA_AV_CHK_2ND_START,
- BTA_AV_OPEN_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* STR_WRITE_CFM_EVT */
+ {BTA_AV_CLR_CONG, BTA_AV_DATA_PATH, BTA_AV_OPEN_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SUSPEND_CFM, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* AVRC_TIMER_EVT */
+ {BTA_AV_OPEN_RC, BTA_AV_CHK_2ND_START, BTA_AV_OPEN_SST},
/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_ROLE_RES, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_OPEN_SST}};
/* state table for reconfig state */
static const uint8_t bta_av_sst_rcfg[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* API_CLOSE_EVT */
+ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* API_RECONFIG_EVT */ {BTA_AV_RECONFIG, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
@@ -354,109 +355,109 @@
/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* STR_DISC_OK_EVT */ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* STR_DISC_FAIL_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
- /* STR_GETCAP_OK_EVT */ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* STR_GETCAP_FAIL_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* STR_DISC_OK_EVT */
+ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* STR_DISC_FAIL_EVT */
+ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* STR_GETCAP_OK_EVT */
+ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* STR_GETCAP_FAIL_EVT */
+ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_OPEN_OK_EVT */ {BTA_AV_RCFG_STR_OK, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* STR_OPEN_FAIL_EVT */ {BTA_AV_RCFG_FAILED, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* STR_OPEN_FAIL_EVT */
+ {BTA_AV_RCFG_FAILED, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* STR_CLOSE_EVT */ {BTA_AV_RCFG_CONNECT, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SUSPEND_CFM, BTA_AV_SUSPEND_CONT,
- BTA_AV_RCFG_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_RCFG_CFM, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SUSPEND_CFM, BTA_AV_SUSPEND_CONT, BTA_AV_RCFG_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_RCFG_CFM, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* AVDT_CONNECT_EVT */ {BTA_AV_RCFG_OPEN, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_RCFG_DISCNTD, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_RCFG_DISCNTD, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_RCFG_SST}};
/* state table for closing state */
static const uint8_t bta_av_sst_closing[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_CLOSE_EVT */
+ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* API_PROTECT_REQ_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* API_PROTECT_RSP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* API_PROTECT_REQ_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_PROTECT_RSP_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* SRC_DATA_READY_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* CI_SETCONFIG_OK_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* SDP_DISC_OK_EVT */ {BTA_AV_SDP_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* SDP_DISC_FAIL_EVT */ {BTA_AV_SDP_FAILED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* SDP_DISC_FAIL_EVT */
+ {BTA_AV_SDP_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_DISC_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* STR_DISC_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_GETCAP_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_GETCAP_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* STR_DISC_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_GETCAP_OK_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_GETCAP_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* STR_OPEN_OK_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* STR_OPEN_FAIL_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* STR_OPEN_FAIL_EVT */
+ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_CLOSE_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_REJ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* STR_START_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_CLOSE_EVT */
+ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SECURITY_REJ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_WRITE_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* AVDT_DELAY_RPT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* AVDT_DELAY_RPT_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST}};
/* type for state table */
typedef const uint8_t (*tBTA_AV_SST_TBL)[BTA_AV_NUM_COLS];
@@ -466,27 +467,6 @@
bta_av_sst_init, bta_av_sst_incoming, bta_av_sst_opening,
bta_av_sst_open, bta_av_sst_rcfg, bta_av_sst_closing};
-static const char* bta_av_sst_code(uint8_t state);
-
-/*******************************************************************************
- *
- * Function bta_av_is_rcfg_sst
- *
- * Description Check if stream state machine is in reconfig state.
- *
- *
- * Returns true if stream state machine is in reconfig state.
- *
- ******************************************************************************/
-bool bta_av_is_rcfg_sst(tBTA_AV_SCB* p_scb) {
- bool is_rcfg_sst = false;
-
- if (p_scb != NULL) {
- if (p_scb->state == BTA_AV_RCFG_SST) is_rcfg_sst = true;
- }
-
- return is_rcfg_sst;
-}
/*******************************************************************************
*
@@ -500,49 +480,32 @@
******************************************************************************/
void bta_av_ssm_execute(tBTA_AV_SCB* p_scb, uint16_t event,
tBTA_AV_DATA* p_data) {
- tBTA_AV_SST_TBL state_table;
- uint8_t action;
- int i, xx;
-
if (p_scb == NULL) {
/* this stream is not registered */
- APPL_TRACE_EVENT("AV channel not registered");
+ APPL_TRACE_EVENT("%s: AV channel not registered", __func__);
return;
}
- /* In case incoming connection is for VDP, we need to swap scb. */
- /* When ACP_CONNECT_EVT was received, we put first available scb to */
- /* to Incoming state. Later, when STR_CONFIG_IND_EVT is coming, we */
- /* know if it is A2DP or VDP. */
- if ((p_scb->state == BTA_AV_INIT_SST) &&
- (event == BTA_AV_STR_CONFIG_IND_EVT)) {
- for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
- if (bta_av_cb.p_scb[xx]) {
- if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST) {
- bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST;
- bta_av_cb.p_scb[xx]->coll_mask = 0;
- p_scb->state = BTA_AV_INCOMING_SST;
- break;
- }
- }
- }
- }
-
- APPL_TRACE_VERBOSE("%s: AV Sevent(0x%x)=0x%x(%s) state=%d(%s)", __func__,
- p_scb->hndl, event, bta_av_evt_code(event), p_scb->state,
- bta_av_sst_code(p_scb->state));
+ APPL_TRACE_VERBOSE(
+ "%s: peer %s AV event(0x%x)=0x%x(%s) state=%d(%s) p_scb=%p", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->hndl, event,
+ bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state),
+ p_scb);
/* look up the state table for the current state */
- state_table = bta_av_sst_tbl[p_scb->state];
-
- event -= BTA_AV_FIRST_SSM_EVT;
+ tBTA_AV_SST_TBL state_table = bta_av_sst_tbl[p_scb->state];
/* set next state */
+ event -= BTA_AV_FIRST_SSM_EVT;
p_scb->state = state_table[event][BTA_AV_SNEXT_STATE];
+ APPL_TRACE_VERBOSE("%s: peer %s AV next state=%d(%s) p_scb=%p", __func__,
+ p_scb->PeerAddress().ToString().c_str(), p_scb->state,
+ bta_av_sst_code(p_scb->state), p_scb);
+
/* execute action functions */
- for (i = 0; i < BTA_AV_SACTIONS; i++) {
- action = state_table[event][i];
+ for (int i = 0; i < BTA_AV_SACTIONS; i++) {
+ uint8_t action = state_table[event][i];
if (action != BTA_AV_SIGNORE) {
(*p_scb->p_act_tbl[action])(p_scb, p_data);
} else
@@ -601,9 +564,19 @@
*
******************************************************************************/
void bta_av_set_scb_sst_init(tBTA_AV_SCB* p_scb) {
- if (p_scb) {
- p_scb->state = BTA_AV_INIT_SST;
+ if (p_scb == nullptr) {
+ return;
}
+
+ uint8_t next_state = BTA_AV_INIT_SST;
+
+ APPL_TRACE_VERBOSE(
+ "%s: peer %s AV (hndl=0x%x) state=%d(%s) next state=%d(%s) p_scb=%p",
+ __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+ p_scb->state, bta_av_sst_code(p_scb->state), next_state,
+ bta_av_sst_code(next_state), p_scb);
+
+ p_scb->state = next_state;
}
/*******************************************************************************
@@ -654,7 +627,7 @@
* Returns char *
*
******************************************************************************/
-static const char* bta_av_sst_code(uint8_t state) {
+const char* bta_av_sst_code(uint8_t state) {
switch (state) {
case BTA_AV_INIT_SST:
return "INIT";
diff --git a/bta/dm/bta_dm_act.cc b/bta/dm/bta_dm_act.cc
index eaa61ab..5abda87 100644
--- a/bta/dm/bta_dm_act.cc
+++ b/bta/dm/bta_dm_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2014 Broadcom Corporation
+ * Copyright 2003-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@
#include <base/bind.h>
#include <base/callback.h>
#include <base/logging.h>
-#include <cutils/log.h>
#include <string.h>
#include "bt_common.h"
@@ -53,12 +52,14 @@
#include "gap_api.h"
#endif
+using bluetooth::Uuid;
+
static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, uint8_t* p_eir,
uint16_t eir_len);
static void bta_dm_inq_cmpl_cb(void* p_result);
static void bta_dm_service_search_remname_cback(const RawAddress& bd_addr,
DEV_CLASS dc, BD_NAME bd_name);
-static void bta_dm_remname_cback(tBTM_REMOTE_DEV_NAME* p_remote_name);
+static void bta_dm_remname_cback(void* p);
static void bta_dm_find_services(const RawAddress& bd_addr);
static void bta_dm_discover_next_device(void);
static void bta_dm_sdp_callback(uint16_t sdp_status);
@@ -75,17 +76,15 @@
DEV_CLASS dev_class,
BD_NAME bd_name,
int result);
-static void bta_dm_local_name_cback(const RawAddress& bd_addr);
+static void bta_dm_local_name_cback(void* p_name);
static bool bta_dm_check_av(uint16_t event);
static void bta_dm_bl_change_cback(tBTM_BL_EVENT_DATA* p_data);
static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
- uint8_t app_id, const RawAddress* peer_addr);
+ uint8_t app_id, const RawAddress& peer_addr);
/* Extended Inquiry Response */
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
static uint8_t bta_dm_sp_cback(tBTM_SP_EVT event, tBTM_SP_EVT_DATA* p_data);
-#endif
static void bta_dm_set_eir(char* local_name);
@@ -96,7 +95,7 @@
static void bta_dm_search_timer_cback(void* data);
static void bta_dm_disable_conn_down_timer_cback(void* data);
static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
- uint8_t app_id, const RawAddress* peer_addr);
+ uint8_t app_id, const RawAddress& peer_addr);
static void bta_dm_adjust_roles(bool delay_role_switch);
static char* bta_dm_get_remname(void);
static void bta_dm_bond_cancel_complete_cback(tBTM_STATUS result);
@@ -147,8 +146,6 @@
#define BTA_DM_SWITCH_DELAY_TIMER_MS 500
#endif
-#define BTA_MAX_SERVICES 32
-
static void bta_dm_reset_sec_dev_pending(const RawAddress& remote_bd_addr);
static void bta_dm_remove_sec_dev_entry(const RawAddress& remote_bd_addr);
static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, uint8_t* p_eir,
@@ -239,11 +236,7 @@
&bta_dm_new_link_key_cback,
&bta_dm_authentication_complete_cback,
&bta_dm_bond_cancel_complete_cback,
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
&bta_dm_sp_cback,
-#else
- NULL,
-#endif
&bta_dm_ble_smp_cback,
&bta_dm_ble_id_key_cback};
@@ -252,28 +245,16 @@
extern DEV_CLASS local_device_default_class;
-/*******************************************************************************
- *
- * Function bta_dm_enable
- *
- * Description Initialises the BT device manager
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_enable(tBTA_DM_MSG* p_data) {
- tBTA_DM_ENABLE enable_event;
-
+/** Initialises the BT device manager */
+void bta_dm_enable(tBTA_DM_SEC_CBACK* p_sec_cback) {
/* if already in use, return an error */
- if (bta_dm_cb.is_bta_dm_active == true) {
+ if (bta_dm_cb.is_bta_dm_active) {
+ tBTA_DM_SEC enable_event;
APPL_TRACE_WARNING("%s Device already started by another application",
__func__);
- memset(&enable_event, 0, sizeof(tBTA_DM_ENABLE));
- enable_event.status = BTA_FAILURE;
- if (p_data->enable.p_sec_cback != NULL)
- p_data->enable.p_sec_cback(BTA_DM_ENABLE_EVT,
- (tBTA_DM_SEC*)&enable_event);
+ memset(&enable_event, 0, sizeof(tBTA_DM_SEC));
+ enable_event.enable.status = BTA_FAILURE;
+ if (p_sec_cback != NULL) p_sec_cback(BTA_DM_ENABLE_EVT, &enable_event);
return;
}
@@ -283,8 +264,7 @@
/* make sure security callback is saved - if no callback, do not erase the
previous one,
it could be an error recovery mechanism */
- if (p_data->enable.p_sec_cback != NULL)
- bta_dm_cb.p_sec_cback = p_data->enable.p_sec_cback;
+ if (p_sec_cback != NULL) bta_dm_cb.p_sec_cback = p_sec_cback;
/* notify BTA DM is now active */
bta_dm_cb.is_bta_dm_active = true;
@@ -430,9 +410,9 @@
BTM_BleLoadLocalKeys(BTA_BLE_LOCAL_KEY_TYPE_ID,
(tBTM_BLE_LOCAL_KEYS*)&id_key);
}
- bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
+ bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID;
- BTM_SecRegister((tBTM_APPL_INFO*)&bta_security);
+ BTM_SecRegister(&bta_security);
BTM_SetDefaultLinkSuperTout(p_bta_dm_cfg->link_timeout);
BTM_WritePageTimeout(p_bta_dm_cfg->page_timeout);
bta_dm_cb.cur_policy = p_bta_dm_cfg->policy_settings;
@@ -459,15 +439,14 @@
which forces
the DM_ENABLE_EVT to be sent only after all the init steps are complete
*/
- BTM_ReadLocalDeviceNameFromController(
- (tBTM_CMPL_CB*)bta_dm_local_name_cback);
+ BTM_ReadLocalDeviceNameFromController(bta_dm_local_name_cback);
- bta_sys_rm_register((tBTA_SYS_CONN_CBACK*)bta_dm_rm_cback);
+ bta_sys_rm_register(bta_dm_rm_cback);
/* initialize bluetooth low power manager */
bta_dm_init_pm();
- bta_sys_policy_register((tBTA_SYS_CONN_CBACK*)bta_dm_policy_cback);
+ bta_sys_policy_register(bta_dm_policy_cback);
bta_dm_gattc_register();
@@ -475,17 +454,8 @@
APPL_TRACE_DEBUG(" --- ignored event");
}
-/*******************************************************************************
- *
- * Function bta_dm_disable
- *
- * Description Disables the BT device manager
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_disable(UNUSED_ATTR tBTA_DM_MSG* p_data) {
+/** Disables the BT device manager */
+void bta_dm_disable() {
/* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after
* last channel is closed) */
L2CA_SetIdleTimeoutByBdAddr(RawAddress::kAny, 0, BT_TRANSPORT_BR_EDR);
@@ -566,32 +536,16 @@
}
}
-/*******************************************************************************
- *
- * Function bta_dm_set_dev_name
- *
- * Description Sets local device name
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_set_dev_name(tBTA_DM_MSG* p_data) {
- BTM_SetLocalDeviceName((char*)p_data->set_name.name);
- bta_dm_set_eir((char*)p_data->set_name.name);
+/** Sets local device name */
+void bta_dm_set_dev_name(const std::vector<uint8_t>& name) {
+ BTM_SetLocalDeviceName((char*)name.data());
+ bta_dm_set_eir((char*)name.data());
}
-/*******************************************************************************
- *
- * Function bta_dm_set_visibility
- *
- * Description Sets discoverability, connectability and pairability
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_set_visibility(tBTA_DM_MSG* p_data) {
+/** Sets discoverability, connectability and pairability */
+void bta_dm_set_visibility(tBTA_DM_DISC disc_mode_param,
+ tBTA_DM_CONN conn_mode_param, uint8_t pairable_mode,
+ uint8_t conn_paired_only) {
uint16_t window, interval;
uint16_t le_disc_mode = BTM_BleReadDiscoverability();
uint16_t le_conn_mode = BTM_BleReadConnectability();
@@ -599,55 +553,44 @@
uint16_t conn_mode = BTM_ReadConnectability(&window, &interval);
/* set modes for Discoverability and connectability if not ignore */
- if (p_data->set_visibility.disc_mode != (BTA_DM_IGNORE | BTA_DM_LE_IGNORE)) {
- if ((p_data->set_visibility.disc_mode & BTA_DM_LE_IGNORE) ==
- BTA_DM_LE_IGNORE)
- p_data->set_visibility.disc_mode =
- ((p_data->set_visibility.disc_mode & ~BTA_DM_LE_IGNORE) |
- le_disc_mode);
- if ((p_data->set_visibility.disc_mode & BTA_DM_IGNORE) == BTA_DM_IGNORE)
- p_data->set_visibility.disc_mode =
- ((p_data->set_visibility.disc_mode & ~BTA_DM_IGNORE) | disc_mode);
+ if (disc_mode_param != (BTA_DM_IGNORE | BTA_DM_LE_IGNORE)) {
+ if ((disc_mode_param & BTA_DM_LE_IGNORE) == BTA_DM_LE_IGNORE)
+ disc_mode_param = ((disc_mode_param & ~BTA_DM_LE_IGNORE) | le_disc_mode);
+ if ((disc_mode_param & BTA_DM_IGNORE) == BTA_DM_IGNORE)
+ disc_mode_param = ((disc_mode_param & ~BTA_DM_IGNORE) | disc_mode);
- BTM_SetDiscoverability(p_data->set_visibility.disc_mode,
- bta_dm_cb.inquiry_scan_window,
+ BTM_SetDiscoverability(disc_mode_param, bta_dm_cb.inquiry_scan_window,
bta_dm_cb.inquiry_scan_interval);
}
- if (p_data->set_visibility.conn_mode != (BTA_DM_IGNORE | BTA_DM_LE_IGNORE)) {
- if ((p_data->set_visibility.conn_mode & BTA_DM_LE_IGNORE) ==
- BTA_DM_LE_IGNORE)
- p_data->set_visibility.conn_mode =
- ((p_data->set_visibility.conn_mode & ~BTA_DM_LE_IGNORE) |
- le_conn_mode);
- if ((p_data->set_visibility.conn_mode & BTA_DM_IGNORE) == BTA_DM_IGNORE)
- p_data->set_visibility.conn_mode =
- ((p_data->set_visibility.conn_mode & ~BTA_DM_IGNORE) | conn_mode);
+ if (conn_mode_param != (BTA_DM_IGNORE | BTA_DM_LE_IGNORE)) {
+ if ((conn_mode_param & BTA_DM_LE_IGNORE) == BTA_DM_LE_IGNORE)
+ conn_mode_param = ((conn_mode_param & ~BTA_DM_LE_IGNORE) | le_conn_mode);
+ if ((conn_mode_param & BTA_DM_IGNORE) == BTA_DM_IGNORE)
+ conn_mode_param = ((conn_mode_param & ~BTA_DM_IGNORE) | conn_mode);
- BTM_SetConnectability(p_data->set_visibility.conn_mode,
- bta_dm_cb.page_scan_window,
+ BTM_SetConnectability(conn_mode_param, bta_dm_cb.page_scan_window,
bta_dm_cb.page_scan_interval);
}
/* Send False or True if not ignore */
- if (p_data->set_visibility.pair_mode != BTA_DM_IGNORE) {
- if (p_data->set_visibility.pair_mode == BTA_DM_NON_PAIRABLE)
+ if (pairable_mode != BTA_DM_IGNORE) {
+ if (pairable_mode == BTA_DM_NON_PAIRABLE)
bta_dm_cb.disable_pair_mode = true;
else
bta_dm_cb.disable_pair_mode = false;
}
/* Send False or True if not ignore */
- if (p_data->set_visibility.conn_paired_only != BTA_DM_IGNORE) {
- if (p_data->set_visibility.conn_paired_only == BTA_DM_CONN_ALL)
+ if (conn_paired_only != BTA_DM_IGNORE) {
+ if (conn_paired_only == BTA_DM_CONN_ALL)
bta_dm_cb.conn_paired_only = false;
else
bta_dm_cb.conn_paired_only = true;
}
/* Change mode if either mode is not ignore */
- if (p_data->set_visibility.pair_mode != BTA_DM_IGNORE ||
- p_data->set_visibility.conn_paired_only != BTA_DM_IGNORE)
+ if (pairable_mode != BTA_DM_IGNORE || conn_paired_only != BTA_DM_IGNORE)
BTM_SetPairableMode((bool)(!(bta_dm_cb.disable_pair_mode)),
bta_dm_cb.conn_paired_only);
}
@@ -678,45 +621,30 @@
}
}
-/*******************************************************************************
- *
- * Function bta_dm_remove_device
- *
- * Description Removes device, disconnects ACL link if required.
- ***
- ******************************************************************************/
-void bta_dm_remove_device(tBTA_DM_MSG* p_data) {
- tBTA_DM_API_REMOVE_DEVICE* p_dev = &p_data->remove_dev;
- bool continue_delete_other_dev = false;
- if (p_dev == NULL) return;
-
- RawAddress other_address = p_dev->bd_addr;
-
+/** Removes device, disconnects ACL link if required */
+void bta_dm_remove_device(const RawAddress& bd_addr) {
/* If ACL exists for the device in the remove_bond message*/
- bool continue_delete_dev = false;
- uint8_t other_transport = BT_TRANSPORT_INVALID;
+ bool is_bd_addr_connected =
+ BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE) ||
+ BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_BR_EDR);
- if (BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_LE) ||
- BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_BR_EDR)) {
- APPL_TRACE_DEBUG("%s: ACL Up count %d", __func__,
+ uint8_t other_transport = BT_TRANSPORT_INVALID;
+ if (is_bd_addr_connected) {
+ APPL_TRACE_DEBUG("%s: ACL Up count: %d", __func__,
bta_dm_cb.device_list.count);
- continue_delete_dev = false;
/* Take the link down first, and mark the device for removal when
* disconnected */
for (int i = 0; i < bta_dm_cb.device_list.count; i++) {
- if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == p_dev->bd_addr) {
- uint8_t transport = BT_TRANSPORT_BR_EDR;
-
- transport = bta_dm_cb.device_list.peer_device[i].transport;
- bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;
- btm_remove_acl(p_dev->bd_addr, transport);
- APPL_TRACE_DEBUG("%s:transport = %d", __func__,
- bta_dm_cb.device_list.peer_device[i].transport);
+ auto& peer_device = bta_dm_cb.device_list.peer_device[i];
+ if (peer_device.peer_bdaddr == bd_addr) {
+ peer_device.conn_state = BTA_DM_UNPAIRING;
+ btm_remove_acl(bd_addr, peer_device.transport);
+ APPL_TRACE_DEBUG("%s: transport: %d", __func__, peer_device.transport);
/* save the other transport to check if device is connected on
* other_transport */
- if (bta_dm_cb.device_list.peer_device[i].transport == BT_TRANSPORT_LE)
+ if (peer_device.transport == BT_TRANSPORT_LE)
other_transport = BT_TRANSPORT_BR_EDR;
else
other_transport = BT_TRANSPORT_LE;
@@ -724,39 +652,44 @@
break;
}
}
- } else {
- continue_delete_dev = true;
}
+
+ RawAddress other_address = bd_addr;
+ RawAddress other_address2 = bd_addr;
+
// If it is DUMO device and device is paired as different address, unpair that
// device
- // if different address
- if ((other_transport &&
- (BTM_ReadConnectedTransportAddress(&other_address, other_transport))) ||
- (!other_transport &&
- (BTM_ReadConnectedTransportAddress(&other_address,
- BT_TRANSPORT_BR_EDR) ||
- BTM_ReadConnectedTransportAddress(&other_address, BT_TRANSPORT_LE)))) {
- continue_delete_other_dev = false;
+ bool other_address_connected =
+ (other_transport)
+ ? BTM_ReadConnectedTransportAddress(&other_address, other_transport)
+ : (BTM_ReadConnectedTransportAddress(&other_address,
+ BT_TRANSPORT_BR_EDR) ||
+ BTM_ReadConnectedTransportAddress(&other_address2,
+ BT_TRANSPORT_LE));
+ if (other_address == bd_addr) other_address = other_address2;
+
+ if (other_address_connected) {
/* Take the link down first, and mark the device for removal when
* disconnected */
for (int i = 0; i < bta_dm_cb.device_list.count; i++) {
- if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == other_address) {
- bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;
- btm_remove_acl(other_address,
- bta_dm_cb.device_list.peer_device[i].transport);
+ auto& peer_device = bta_dm_cb.device_list.peer_device[i];
+ if (peer_device.peer_bdaddr == other_address) {
+ peer_device.conn_state = BTA_DM_UNPAIRING;
+ btm_remove_acl(other_address, peer_device.transport);
break;
}
}
- } else {
- APPL_TRACE_DEBUG("%s: continue to delete the other dev ", __func__);
- continue_delete_other_dev = true;
}
+
/* Delete the device mentioned in the msg */
- if (continue_delete_dev) bta_dm_process_remove_device(p_dev->bd_addr);
+ if (!is_bd_addr_connected) {
+ bta_dm_process_remove_device(bd_addr);
+ }
/* Delete the other paired device too */
- if (continue_delete_other_dev && !other_address.IsEmpty())
+ if (!other_address_connected && !other_address.IsEmpty()) {
bta_dm_process_remove_device(other_address);
+ }
}
/*******************************************************************************
@@ -768,8 +701,7 @@
* required information stored in the NVRAM.
***
******************************************************************************/
-void bta_dm_add_device(tBTA_DM_MSG* p_data) {
- tBTA_DM_API_ADD_DEVICE* p_dev = &p_data->add_dev;
+void bta_dm_add_device(std::unique_ptr<tBTA_DM_API_ADD_DEVICE> msg) {
uint8_t* p_dc = NULL;
uint8_t* p_lc = NULL;
uint32_t trusted_services_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
@@ -779,86 +711,71 @@
memset(trusted_services_mask, 0, sizeof(trusted_services_mask));
/* If not all zeros, the device class has been specified */
- if (p_dev->dc_known) p_dc = (uint8_t*)p_dev->dc;
+ if (msg->dc_known) p_dc = (uint8_t*)msg->dc;
- if (p_dev->link_key_known) p_lc = (uint8_t*)p_dev->link_key;
+ if (msg->link_key_known) p_lc = (uint8_t*)msg->link_key;
- if (p_dev->is_trusted) {
+ if (msg->is_trusted) {
/* covert BTA service mask to BTM mask */
- while (p_dev->tm && (index < BTA_MAX_SERVICE_ID)) {
- if (p_dev->tm & (uint32_t)(1 << index)) {
+ while (msg->tm && (index < BTA_MAX_SERVICE_ID)) {
+ if (msg->tm & (uint32_t)(1 << index)) {
btm_mask_index =
bta_service_id_to_btm_srv_id_lkup_tbl[index] / BTM_SEC_ARRAY_BITS;
trusted_services_mask[btm_mask_index] |=
(uint32_t)(1 << (bta_service_id_to_btm_srv_id_lkup_tbl[index] -
(uint32_t)(btm_mask_index * 32)));
- p_dev->tm &= (uint32_t)(~(1 << index));
+ msg->tm &= (uint32_t)(~(1 << index));
}
index++;
}
}
- if (!BTM_SecAddDevice(p_dev->bd_addr, p_dc, p_dev->bd_name, p_dev->features,
- trusted_services_mask, p_lc, p_dev->key_type,
- p_dev->io_cap, p_dev->pin_length)) {
- LOG(ERROR) << "BTA_DM: Error adding device " << p_dev->bd_addr;
+ if (!BTM_SecAddDevice(msg->bd_addr, p_dc, msg->bd_name, msg->features,
+ trusted_services_mask, p_lc, msg->key_type, msg->io_cap,
+ msg->pin_length)) {
+ LOG(ERROR) << "BTA_DM: Error adding device " << msg->bd_addr;
}
}
-/*******************************************************************************
- *
- * Function bta_dm_close_acl
- *
- * Description This function forces to close the connection to a remote
- * device and optionaly remove the device from security
- * database if required.
- ***
- ******************************************************************************/
-void bta_dm_close_acl(tBTA_DM_MSG* p_data) {
- tBTA_DM_API_REMOVE_ACL* p_remove_acl = &p_data->remove_acl;
+/** This function forces to close the connection to a remote device and
+ * optionaly remove the device from security database if required. */
+void bta_dm_close_acl(const RawAddress& bd_addr, bool remove_dev,
+ tBTA_TRANSPORT transport) {
uint8_t index;
APPL_TRACE_DEBUG("bta_dm_close_acl");
- if (BTM_IsAclConnectionUp(p_remove_acl->bd_addr, p_remove_acl->transport)) {
+ if (BTM_IsAclConnectionUp(bd_addr, transport)) {
for (index = 0; index < bta_dm_cb.device_list.count; index++) {
- if (bta_dm_cb.device_list.peer_device[index].peer_bdaddr ==
- p_remove_acl->bd_addr)
+ if (bta_dm_cb.device_list.peer_device[index].peer_bdaddr == bd_addr)
break;
}
if (index != bta_dm_cb.device_list.count) {
- if (p_remove_acl->remove_dev)
+ if (remove_dev)
bta_dm_cb.device_list.peer_device[index].remove_dev_pending = true;
} else {
APPL_TRACE_ERROR("unknown device, remove ACL failed");
}
/* Disconnect the ACL link */
- btm_remove_acl(p_remove_acl->bd_addr, p_remove_acl->transport);
+ btm_remove_acl(bd_addr, transport);
}
/* if to remove the device from security database ? do it now */
- else if (p_remove_acl->remove_dev) {
- if (!BTM_SecDeleteDevice(p_remove_acl->bd_addr)) {
+ else if (remove_dev) {
+ if (!BTM_SecDeleteDevice(bd_addr)) {
APPL_TRACE_ERROR("delete device from security database failed.");
}
/* need to remove all pending background connection if any */
- BTA_GATTC_CancelOpen(0, p_remove_acl->bd_addr, false);
+ BTA_GATTC_CancelOpen(0, bd_addr, false);
/* remove all cached GATT information */
- BTA_GATTC_Refresh(p_remove_acl->bd_addr);
+ BTA_GATTC_Refresh(bd_addr);
}
/* otherwise, no action needed */
}
-/*******************************************************************************
- *
- * Function bta_dm_remove_all_acl
- *
- * Description This function forces to close all the ACL links specified by
- * link type
- ***
- ******************************************************************************/
-void bta_dm_remove_all_acl(tBTA_DM_MSG* p_data) {
- const tBTA_DM_LINK_TYPE link_type = p_data->remove_all_acl.link_type;
+// TODO: this is unused. remove?
+/** This function forces to close all the ACL links specified by link type */
+void bta_dm_remove_all_acl(const tBTA_DM_LINK_TYPE link_type) {
tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
APPL_TRACE_DEBUG("%s link type = %d", __func__, link_type);
@@ -877,31 +794,21 @@
}
}
-/*******************************************************************************
- *
- * Function bta_dm_bond
- *
- * Description Bonds with peer device
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_bond(tBTA_DM_MSG* p_data) {
+/** Bonds with peer device */
+void bta_dm_bond(const RawAddress& bd_addr, tBTA_TRANSPORT transport) {
tBTM_STATUS status;
tBTA_DM_SEC sec_event;
char* p_name;
- if (p_data->bond.transport == BTA_TRANSPORT_UNKNOWN)
- status = BTM_SecBond(p_data->bond.bd_addr, 0, NULL, 0);
+ if (transport == BTA_TRANSPORT_UNKNOWN)
+ status = BTM_SecBond(bd_addr, 0, NULL, 0);
else
- status = BTM_SecBondByTransport(p_data->bond.bd_addr,
- p_data->bond.transport, 0, NULL, 0);
+ status = BTM_SecBondByTransport(bd_addr, transport, 0, NULL, 0);
if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED)) {
memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
- sec_event.auth_cmpl.bd_addr = p_data->bond.bd_addr;
- p_name = BTM_SecReadDevName(p_data->bond.bd_addr);
+ sec_event.auth_cmpl.bd_addr = bd_addr;
+ p_name = BTM_SecReadDevName(bd_addr);
if (p_name != NULL) {
memcpy(sec_event.auth_cmpl.bd_name, p_name, (BD_NAME_LEN - 1));
sec_event.auth_cmpl.bd_name[BD_NAME_LEN - 1] = 0;
@@ -916,28 +823,19 @@
sec_event.auth_cmpl.success = true;
} else {
/* delete this device entry from Sec Dev DB */
- bta_dm_remove_sec_dev_entry(p_data->bond.bd_addr);
+ bta_dm_remove_sec_dev_entry(bd_addr);
}
bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
}
}
-/*******************************************************************************
- *
- * Function bta_dm_bond_cancel
- *
- * Description Cancels bonding with a peer device
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_bond_cancel(tBTA_DM_MSG* p_data) {
+/** Cancels bonding with a peer device */
+void bta_dm_bond_cancel(const RawAddress& bd_addr) {
tBTM_STATUS status;
tBTA_DM_SEC sec_event;
APPL_TRACE_EVENT(" bta_dm_bond_cancel ");
- status = BTM_SecBondCancel(p_data->bond_cancel.bd_addr);
+ status = BTM_SecBondCancel(bd_addr);
if (bta_dm_cb.p_sec_cback &&
(status != BTM_CMD_STARTED && status != BTM_SUCCESS)) {
@@ -947,35 +845,22 @@
}
}
-/*******************************************************************************
- *
- * Function bta_dm_pin_reply
- *
- * Description Send the pin_reply to a request from BTM
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_pin_reply(tBTA_DM_MSG* p_data) {
+/** Send the pin_reply to a request from BTM */
+void bta_dm_pin_reply(std::unique_ptr<tBTA_DM_API_PIN_REPLY> msg) {
uint32_t trusted_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
- uint32_t* current_trusted_mask;
- current_trusted_mask = BTM_ReadTrustedMask(p_data->pin_reply.bd_addr);
-
+ uint32_t* current_trusted_mask = BTM_ReadTrustedMask(msg->bd_addr);
if (current_trusted_mask) {
memcpy(trusted_mask, current_trusted_mask, sizeof(trusted_mask));
} else {
memset(trusted_mask, 0, sizeof(trusted_mask));
}
- if (p_data->pin_reply.accept) {
- BTM_PINCodeReply(p_data->pin_reply.bd_addr, BTM_SUCCESS,
- p_data->pin_reply.pin_len, p_data->pin_reply.p_pin,
+ if (msg->accept) {
+ BTM_PINCodeReply(msg->bd_addr, BTM_SUCCESS, msg->pin_len, msg->p_pin,
trusted_mask);
} else {
- BTM_PINCodeReply(p_data->pin_reply.bd_addr, BTM_NOT_AUTHORIZED, 0, NULL,
- trusted_mask);
+ BTM_PINCodeReply(msg->bd_addr, BTM_NOT_AUTHORIZED, 0, NULL, trusted_mask);
}
}
@@ -989,12 +874,14 @@
*
******************************************************************************/
static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
- uint8_t app_id, const RawAddress* peer_addr) {
+ uint8_t app_id, const RawAddress& peer_addr) {
tBTA_DM_PEER_DEVICE* p_dev = NULL;
uint16_t policy = app_id;
uint32_t mask = (uint32_t)(1 << id);
- if (peer_addr) p_dev = bta_dm_find_peer_device(*peer_addr);
+ if (peer_addr != RawAddress::kEmpty) {
+ p_dev = bta_dm_find_peer_device(peer_addr);
+ }
APPL_TRACE_DEBUG(" bta_dm_policy_cback cmd:%d, policy:0x%x", status, policy);
switch (status) {
@@ -1036,67 +923,22 @@
}
}
-/*******************************************************************************
- *
- * Function bta_dm_confirm
- *
- * Description Send the user confirm request reply in response to a
- * request from BTM
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_confirm(tBTA_DM_MSG* p_data) {
- tBTM_STATUS res = BTM_NOT_AUTHORIZED;
-
- if (p_data->confirm.accept == true) res = BTM_SUCCESS;
- BTM_ConfirmReqReply(res, p_data->confirm.bd_addr);
+/** Send the user confirm request reply in response to a request from BTM */
+void bta_dm_confirm(const RawAddress& bd_addr, bool accept) {
+ BTM_ConfirmReqReply(accept ? BTM_SUCCESS : BTM_NOT_AUTHORIZED, bd_addr);
}
-/*******************************************************************************
- *
- * Function bta_dm_loc_oob
- *
- * Description Retrieve the OOB data from the local LM
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_loc_oob(UNUSED_ATTR tBTA_DM_MSG* p_data) { BTM_ReadLocalOobData(); }
-
-/*******************************************************************************
- *
- * Function bta_dm_ci_io_req_act
- *
- * Description respond to the IO capabilities request from BTM
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_ci_io_req_act(tBTA_DM_MSG* p_data) {
- tBTM_AUTH_REQ auth_req = BTM_AUTH_AP_NO;
- if (p_data->ci_io_req.auth_req) auth_req = BTM_AUTH_AP_YES;
- BTM_IoCapRsp(p_data->ci_io_req.bd_addr, p_data->ci_io_req.io_cap,
- p_data->ci_io_req.oob_data, auth_req);
+/** respond to the IO capabilities request from BTM */
+void bta_dm_ci_io_req_act(const RawAddress& bd_addr, tBTA_IO_CAP io_cap,
+ tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req) {
+ BTM_IoCapRsp(bd_addr, io_cap, oob_data,
+ auth_req ? BTM_AUTH_AP_YES : BTM_AUTH_AP_NO);
}
-/*******************************************************************************
- *
- * Function bta_dm_ci_rmt_oob_act
- *
- * Description respond to the OOB data request for the remote device from
- * BTM
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG* p_data) {
- tBTM_STATUS res = BTM_NOT_AUTHORIZED;
-
- if (p_data->ci_rmt_oob.accept == true) res = BTM_SUCCESS;
- BTM_RemoteOobDataReply(res, p_data->ci_rmt_oob.bd_addr, p_data->ci_rmt_oob.c,
- p_data->ci_rmt_oob.r);
+/** respond to the OOB data request for the remote device from BTM */
+void bta_dm_ci_rmt_oob_act(std::unique_ptr<tBTA_DM_CI_RMT_OOB> msg) {
+ BTM_RemoteOobDataReply(msg->accept ? BTM_SUCCESS : BTM_NOT_AUTHORIZED,
+ msg->bd_addr, msg->c, msg->r);
}
/*******************************************************************************
@@ -1110,9 +952,9 @@
*
******************************************************************************/
void bta_dm_search_start(tBTA_DM_MSG* p_data) {
- tBTM_INQUIRY_CMPL result;
+ tBTM_INQUIRY_CMPL result = {};
- size_t len = sizeof(tBT_UUID) * p_data->search.num_uuid;
+ size_t len = sizeof(Uuid) * p_data->search.num_uuid;
bta_dm_gattc_register();
APPL_TRACE_DEBUG("%s avoid_scatter=%d", __func__,
@@ -1121,11 +963,12 @@
if (p_bta_dm_cfg->avoid_scatter &&
(p_data->search.rs_res == BTA_DM_RS_NONE) &&
bta_dm_check_av(BTA_DM_API_SEARCH_EVT)) {
+ LOG(INFO) << __func__ << ": delay search to avoid scatter";
memcpy(&bta_dm_cb.search_msg, &p_data->search, sizeof(tBTA_DM_API_SEARCH));
return;
}
- BTM_ClearInqDb(NULL);
+ BTM_ClearInqDb(nullptr);
/* save search params */
bta_dm_search_cb.p_search_cback = p_data->search.p_cback;
bta_dm_search_cb.services = p_data->search.services;
@@ -1133,16 +976,17 @@
osi_free_and_reset((void**)&bta_dm_search_cb.p_srvc_uuid);
if ((bta_dm_search_cb.num_uuid = p_data->search.num_uuid) != 0 &&
- p_data->search.p_uuid != NULL) {
- bta_dm_search_cb.p_srvc_uuid = (tBT_UUID*)osi_malloc(len);
- memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->search.p_uuid, len);
+ p_data->search.p_uuid != nullptr) {
+ bta_dm_search_cb.p_srvc_uuid = (Uuid*)osi_malloc(len);
+ *bta_dm_search_cb.p_srvc_uuid = *p_data->search.p_uuid;
}
result.status = BTM_StartInquiry((tBTM_INQ_PARMS*)&p_data->search.inq_params,
- bta_dm_inq_results_cb,
- (tBTM_CMPL_CB*)bta_dm_inq_cmpl_cb);
+ bta_dm_inq_results_cb, bta_dm_inq_cmpl_cb);
APPL_TRACE_EVENT("%s status=%d", __func__, result.status);
if (result.status != BTM_CMD_STARTED) {
+ LOG(ERROR) << __func__ << ": BTM_StartInquiry returned "
+ << std::to_string(result.status);
result.num_resp = 0;
bta_dm_inq_cmpl_cb((void*)&result);
}
@@ -1205,7 +1049,7 @@
*
******************************************************************************/
void bta_dm_discover(tBTA_DM_MSG* p_data) {
- size_t len = sizeof(tBT_UUID) * p_data->discover.num_uuid;
+ size_t len = sizeof(Uuid) * p_data->discover.num_uuid;
APPL_TRACE_EVENT("%s services_to_search=0x%04X, sdp_search=%d", __func__,
p_data->discover.services, p_data->discover.sdp_search);
@@ -1216,8 +1060,8 @@
osi_free_and_reset((void**)&bta_dm_search_cb.p_srvc_uuid);
if ((bta_dm_search_cb.num_uuid = p_data->discover.num_uuid) != 0 &&
p_data->discover.p_uuid != NULL) {
- bta_dm_search_cb.p_srvc_uuid = (tBT_UUID*)osi_malloc(len);
- memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->discover.p_uuid, len);
+ bta_dm_search_cb.p_srvc_uuid = (Uuid*)osi_malloc(len);
+ *bta_dm_search_cb.p_srvc_uuid = *p_data->discover.p_uuid;
}
bta_dm_search_cb.uuid_to_search = bta_dm_search_cb.num_uuid;
@@ -1232,7 +1076,7 @@
bta_dm_search_cb.transport = p_data->discover.transport;
bta_dm_search_cb.name_discover_done = false;
- memcpy(&bta_dm_search_cb.uuid, &p_data->discover.uuid, sizeof(tSDP_UUID));
+ bta_dm_search_cb.uuid = p_data->discover.uuid;
bta_dm_discover_device(p_data->discover.bd_addr);
}
@@ -1361,9 +1205,8 @@
bta_dm_search_cb.peer_bdaddr = bd_addr;
bta_dm_search_cb.peer_name[0] = 0;
- btm_status =
- BTM_ReadRemoteDeviceName(bta_dm_search_cb.peer_bdaddr,
- (tBTM_CMPL_CB*)bta_dm_remname_cback, transport);
+ btm_status = BTM_ReadRemoteDeviceName(bta_dm_search_cb.peer_bdaddr,
+ bta_dm_remname_cback, transport);
if (btm_status == BTM_CMD_STARTED) {
APPL_TRACE_DEBUG("%s: BTM_ReadRemoteDeviceName is started", __func__);
@@ -1484,12 +1327,10 @@
uint16_t service = 0xFFFF;
tSDP_PROTOCOL_ELEM pe;
- tBT_UUID* p_uuid = bta_dm_search_cb.p_srvc_uuid;
+ Uuid* p_uuid = bta_dm_search_cb.p_srvc_uuid;
tBTA_DM_SEARCH result;
- tBT_UUID service_uuid;
- uint32_t num_uuids = 0;
- uint8_t uuid_list[BTA_MAX_SERVICES][MAX_UUID_SIZE]; // assuming a max of 32 services
+ std::vector<Uuid> uuid_list;
if ((p_data->sdp_event.sdp_result == SDP_SUCCESS) ||
(p_data->sdp_event.sdp_result == SDP_NO_RECS_MATCH) ||
@@ -1499,7 +1340,7 @@
p_sdp_rec = NULL;
if (bta_dm_search_cb.service_index == (BTA_USER_SERVICE_ID + 1)) {
p_sdp_rec = SDP_FindServiceUUIDInDb(bta_dm_search_cb.p_sdp_db,
- &bta_dm_search_cb.uuid, p_sdp_rec);
+ bta_dm_search_cb.uuid, p_sdp_rec);
if (p_sdp_rec && SDP_FindProtocolListElemInRec(
p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
@@ -1519,7 +1360,7 @@
p_uuid +=
(bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search);
/* only support 16 bits UUID for now */
- service = p_uuid->uu.uuid16;
+ service = p_uuid->As16Bit();
}
/* all GATT based services */
do {
@@ -1527,14 +1368,14 @@
p_sdp_rec =
SDP_FindServiceInDb(bta_dm_search_cb.p_sdp_db, 0, p_sdp_rec);
if (p_sdp_rec) {
+ Uuid service_uuid;
if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
/* send result back to app now, one by one */
result.disc_ble_res.bd_addr = bta_dm_search_cb.peer_bdaddr;
strlcpy((char*)result.disc_ble_res.bd_name, bta_dm_get_remname(),
BD_NAME_LEN);
- result.disc_ble_res.service.len = service_uuid.len;
- result.disc_ble_res.service.uu.uuid16 = service_uuid.uu.uuid16;
+ result.disc_ble_res.service = service_uuid;
bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
}
}
@@ -1549,20 +1390,14 @@
bta_dm_search_cb.services != BTA_ALL_SERVICE_MASK) ||
(p_sdp_rec != NULL)) {
if (service != UUID_SERVCLASS_PNP_INFORMATION) {
- uint16_t tmp_svc = 0xFFFF;
bta_dm_search_cb.services_found |=
(tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(
bta_dm_search_cb.service_index - 1));
- tmp_svc =
+ uint16_t tmp_svc =
bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index -
1];
/* Add to the list of UUIDs */
- if (num_uuids < BTA_MAX_SERVICES) {
- sdpu_uuid16_to_uuid128(tmp_svc, uuid_list[num_uuids]);
- num_uuids++;
- } else {
- android_errorWriteLog(0x534e4554, "74016921");
- }
+ uuid_list.push_back(Uuid::From16Bit(tmp_svc));
}
}
}
@@ -1588,18 +1423,14 @@
if (bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK) {
p_sdp_rec = NULL;
do {
- tBT_UUID temp_uuid;
/* find a service record, report it */
p_sdp_rec =
SDP_FindServiceInDb_128bit(bta_dm_search_cb.p_sdp_db, p_sdp_rec);
if (p_sdp_rec) {
+ // SDP_FindServiceUUIDInRec_128bit is used only once, refactor?
+ Uuid temp_uuid;
if (SDP_FindServiceUUIDInRec_128bit(p_sdp_rec, &temp_uuid)) {
- if (num_uuids < BTA_MAX_SERVICES) {
- memcpy(uuid_list[num_uuids], temp_uuid.uu.uuid128, MAX_UUID_SIZE);
- num_uuids++;
- } else {
- android_errorWriteLog(0x534e4554, "74016921");
- }
+ uuid_list.push_back(temp_uuid);
}
}
} while (p_sdp_rec);
@@ -1620,13 +1451,15 @@
p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;
p_msg->disc_result.result.disc_res.p_raw_data = NULL;
p_msg->disc_result.result.disc_res.raw_data_size = 0;
- p_msg->disc_result.result.disc_res.num_uuids = num_uuids;
+ p_msg->disc_result.result.disc_res.num_uuids = uuid_list.size();
p_msg->disc_result.result.disc_res.p_uuid_list = NULL;
- if (num_uuids > 0) {
+ if (uuid_list.size() > 0) {
+ // TODO(jpawlowski): make p_uuid_list into vector, and just copy
+ // vectors, but first get rid of bta_sys_sendmsg below.
p_msg->disc_result.result.disc_res.p_uuid_list =
- (uint8_t*)osi_malloc(num_uuids * MAX_UUID_SIZE);
- memcpy(p_msg->disc_result.result.disc_res.p_uuid_list, uuid_list,
- num_uuids * MAX_UUID_SIZE);
+ (Uuid*)osi_malloc(uuid_list.size() * sizeof(Uuid));
+ memcpy(p_msg->disc_result.result.disc_res.p_uuid_list, uuid_list.data(),
+ uuid_list.size() * sizeof(Uuid));
}
// Copy the raw_data to the discovery result structure
if (bta_dm_search_cb.p_sdp_db != NULL &&
@@ -1921,11 +1754,9 @@
*
******************************************************************************/
static void bta_dm_find_services(const RawAddress& bd_addr) {
- tSDP_UUID uuid;
-
- memset(&uuid, 0, sizeof(tSDP_UUID));
while (bta_dm_search_cb.service_index < BTA_MAX_SERVICE_ID) {
+ Uuid uuid = Uuid::kEmpty;
if (bta_dm_search_cb.services_to_search &
(tBTA_SERVICE_MASK)(
BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index))) {
@@ -1938,10 +1769,10 @@
LOG_INFO(LOG_TAG, "%s services_to_search=%08x", __func__,
bta_dm_search_cb.services_to_search);
if (bta_dm_search_cb.services_to_search & BTA_RES_SERVICE_MASK) {
- uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[0];
+ uuid = Uuid::From16Bit(bta_service_id_to_uuid_lkup_tbl[0]);
bta_dm_search_cb.services_to_search &= ~BTA_RES_SERVICE_MASK;
} else {
- uuid.uu.uuid16 = UUID_PROTOCOL_L2CAP;
+ uuid = Uuid::From16Bit(UUID_PROTOCOL_L2CAP);
bta_dm_search_cb.services_to_search = 0;
}
} else {
@@ -1949,15 +1780,14 @@
if (bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID) {
if (bta_dm_search_cb.uuid_to_search > 0 &&
bta_dm_search_cb.p_srvc_uuid) {
- memcpy(&uuid, (const void*)(bta_dm_search_cb.p_srvc_uuid +
- bta_dm_search_cb.num_uuid -
- bta_dm_search_cb.uuid_to_search),
- sizeof(tBT_UUID));
+ uuid = *(bta_dm_search_cb.p_srvc_uuid + bta_dm_search_cb.num_uuid -
+ bta_dm_search_cb.uuid_to_search);
bta_dm_search_cb.uuid_to_search--;
} else {
- uuid.uu.uuid16 =
- bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index];
+ uuid = Uuid::From16Bit(
+ bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb
+ .service_index]);
}
/* last one? clear the BLE service bit if all discovery has been done
@@ -1971,18 +1801,17 @@
/* remove the service from services to be searched */
bta_dm_search_cb.services_to_search &= (tBTA_SERVICE_MASK)(~(
BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)));
- uuid.uu.uuid16 =
- bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index];
+ uuid = Uuid::From16Bit(
+ bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index]);
}
}
- if (uuid.len == 0) uuid.len = LEN_UUID_16;
-
if (bta_dm_search_cb.service_index == BTA_USER_SERVICE_ID) {
- memcpy(&uuid, &bta_dm_search_cb.uuid, sizeof(tSDP_UUID));
+ uuid = bta_dm_search_cb.uuid;
}
- LOG_INFO(LOG_TAG, "%s search UUID = %04x", __func__, uuid.uu.uuid16);
+ LOG_INFO(LOG_TAG, "%s search UUID = %s", __func__,
+ uuid.ToString().c_str());
SDP_InitDiscoveryDb(bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1,
&uuid, 0, NULL);
@@ -2111,8 +1940,7 @@
((bta_dm_search_cb.p_btm_inq_info == NULL) ||
(bta_dm_search_cb.p_btm_inq_info &&
(!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name)))) {
- if (bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr,
- transport) == true)
+ if (bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr, transport))
return;
/* starting name discovery failed */
@@ -2128,7 +1956,7 @@
bta_dm_search_cb.uuid_to_search = bta_dm_search_cb.num_uuid;
if ((bta_dm_search_cb.p_btm_inq_info != NULL) &&
bta_dm_search_cb.services != BTA_USER_SERVICE_MASK &&
- (bta_dm_search_cb.sdp_search == false)) {
+ (!bta_dm_search_cb.sdp_search)) {
/* check if EIR provides the information of supported services */
bta_dm_eir_search_services(&bta_dm_search_cb.p_btm_inq_info->results,
&bta_dm_search_cb.services_to_search,
@@ -2272,7 +2100,7 @@
APPL_TRACE_DEBUG("%s", __func__);
- if (bta_dm_search_cb.cancel_pending == false) {
+ if (!bta_dm_search_cb.cancel_pending) {
p_msg->inq_cmpl.hdr.event = BTA_DM_INQUIRY_CMPL_EVT;
p_msg->inq_cmpl.num = ((tBTM_INQUIRY_CMPL*)p_result)->num_resp;
} else {
@@ -2315,9 +2143,9 @@
bta_dm_remname_cback(&rem_name);
} else {
/* get name of device */
- btm_status = BTM_ReadRemoteDeviceName(bta_dm_search_cb.peer_bdaddr,
- (tBTM_CMPL_CB*)bta_dm_remname_cback,
- BT_TRANSPORT_BR_EDR);
+ btm_status =
+ BTM_ReadRemoteDeviceName(bta_dm_search_cb.peer_bdaddr,
+ bta_dm_remname_cback, BT_TRANSPORT_BR_EDR);
if (btm_status == BTM_BUSY) {
/* wait for next chance(notification of remote name discovery done) */
APPL_TRACE_DEBUG("%s: BTM_ReadRemoteDeviceName is busy", __func__);
@@ -2343,7 +2171,8 @@
* Returns void
*
******************************************************************************/
-static void bta_dm_remname_cback(tBTM_REMOTE_DEV_NAME* p_remote_name) {
+static void bta_dm_remname_cback(void* p) {
+ tBTM_REMOTE_DEV_NAME* p_remote_name = (tBTM_REMOTE_DEV_NAME*)p;
APPL_TRACE_DEBUG("bta_dm_remname_cback len = %d name=<%s>",
p_remote_name->length, p_remote_name->remote_bd_name);
@@ -2452,6 +2281,12 @@
/* 1 additional event data fields for this event */
sec_event.cfm_req.just_works = bta_dm_cb.just_works;
+ /* retrieve the loc and rmt caps */
+ sec_event.cfm_req.loc_io_caps = bta_dm_cb.loc_io_caps;
+ sec_event.cfm_req.rmt_io_caps = bta_dm_cb.rmt_io_caps;
+ sec_event.cfm_req.loc_auth_req = bta_dm_cb.loc_auth_req;
+ sec_event.cfm_req.rmt_auth_req = bta_dm_cb.rmt_auth_req;
+
} else {
/* Retrieved saved device class and bd_addr */
sec_event.pin_req.bd_addr = bta_dm_cb.pin_bd_addr;
@@ -2608,7 +2443,6 @@
return BTM_SUCCESS;
}
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
/*******************************************************************************
*
* Function bta_dm_sp_cback
@@ -2629,16 +2463,20 @@
/* TODO_SP */
switch (event) {
case BTM_SP_IO_REQ_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
/* translate auth_req */
bta_dm_co_io_req(p_data->io_req.bd_addr, &p_data->io_req.io_cap,
&p_data->io_req.oob_data, &p_data->io_req.auth_req,
p_data->io_req.is_orig);
+#endif
APPL_TRACE_EVENT("io mitm: %d oob_data:%d", p_data->io_req.auth_req,
p_data->io_req.oob_data);
break;
case BTM_SP_IO_RSP_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
bta_dm_co_io_rsp(p_data->io_rsp.bd_addr, p_data->io_rsp.io_cap,
p_data->io_rsp.oob_data, p_data->io_rsp.auth_req);
+#endif
break;
case BTM_SP_CFM_REQ_EVT:
@@ -2651,10 +2489,12 @@
sec_event.cfm_req.rmt_io_caps = p_data->cfm_req.rmt_io_caps;
/* continue to next case */
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
/* Passkey entry mode, mobile device with output capability is very
unlikely to receive key request, so skip this event */
/*case BTM_SP_KEY_REQ_EVT: */
case BTM_SP_KEY_NOTIF_EVT:
+#endif
bta_dm_cb.num_val = sec_event.key_notif.passkey =
p_data->key_notif.passkey;
@@ -2664,6 +2504,11 @@
if (p_data->cfm_req.bd_name[0] == 0) {
bta_dm_cb.pin_evt = pin_evt;
bta_dm_cb.pin_bd_addr = p_data->cfm_req.bd_addr;
+ bta_dm_cb.rmt_io_caps = sec_event.cfm_req.rmt_io_caps;
+ bta_dm_cb.loc_io_caps = sec_event.cfm_req.loc_io_caps;
+ bta_dm_cb.rmt_auth_req = sec_event.cfm_req.rmt_auth_req;
+ bta_dm_cb.loc_auth_req = sec_event.cfm_req.loc_auth_req;
+
BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class,
p_data->cfm_req.dev_class);
if ((BTM_ReadRemoteDeviceName(
@@ -2766,7 +2611,6 @@
APPL_TRACE_EVENT("dm status: %d", status);
return status;
}
-#endif
/*******************************************************************************
*
@@ -2778,7 +2622,7 @@
* Returns void
*
******************************************************************************/
-static void bta_dm_local_name_cback(UNUSED_ATTR const RawAddress& p_name) {
+static void bta_dm_local_name_cback(UNUSED_ATTR void* p_name) {
tBTA_DM_SEC sec_event;
sec_event.enable.status = BTA_SUCCESS;
@@ -2787,51 +2631,226 @@
bta_dm_cb.p_sec_cback(BTA_DM_ENABLE_EVT, &sec_event);
}
-/*******************************************************************************
- *
- * Function bta_dm_bl_change_cback
- *
- * Description Callback from btm when acl connection goes up or down
- *
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_dm_bl_change_cback(tBTM_BL_EVENT_DATA* p_data) {
- tBTA_DM_ACL_CHANGE* p_msg =
- (tBTA_DM_ACL_CHANGE*)osi_malloc(sizeof(tBTA_DM_ACL_CHANGE));
+static void send_busy_level_update(uint8_t busy_level,
+ uint8_t busy_level_flags) {
+ if (!bta_dm_cb.p_sec_cback) return;
- p_msg->event = p_data->event;
- p_msg->is_new = false;
+ tBTA_DM_SEC conn;
+ memset(&conn, 0, sizeof(tBTA_DM_SEC));
+ conn.busy_level.level = busy_level;
+ conn.busy_level.level_flags = busy_level_flags;
+ bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn);
+}
- switch (p_msg->event) {
- case BTM_BL_CONN_EVT:
- p_msg->is_new = true;
- p_msg->bd_addr = *p_data->conn.p_bda;
- p_msg->transport = p_data->conn.transport;
- p_msg->handle = p_data->conn.handle;
+static void handle_role_change(const RawAddress& bd_addr, uint8_t new_role,
+ uint8_t hci_status) {
+ tBTA_DM_SEC conn;
+ memset(&conn, 0, sizeof(tBTA_DM_SEC));
+
+ tBTA_DM_PEER_DEVICE* p_dev = bta_dm_find_peer_device(bd_addr);
+ if (!p_dev) return;
+ LOG_INFO(LOG_TAG,
+ "%s: peer %s info:0x%x new_role:0x%x dev count:%d hci_status=%d",
+ __func__, bd_addr.ToString().c_str(), p_dev->info, new_role,
+ bta_dm_cb.device_list.count, hci_status);
+ if (p_dev->info & BTA_DM_DI_AV_ACTIVE) {
+ bool need_policy_change = false;
+
+ /* there's AV activity on this link */
+ if (new_role == HCI_ROLE_SLAVE && bta_dm_cb.device_list.count > 1 &&
+ hci_status == HCI_SUCCESS) {
+ /* more than one connections and the AV connection is role switched
+ * to slave
+ * switch it back to master and remove the switch policy */
+ BTM_SwitchRole(bd_addr, BTM_ROLE_MASTER, NULL);
+ need_policy_change = true;
+ } else if (p_bta_dm_cfg->avoid_scatter && (new_role == HCI_ROLE_MASTER)) {
+ /* if the link updated to be master include AV activities, remove
+ * the switch policy */
+ need_policy_change = true;
+ }
+
+ if (need_policy_change) {
+ bta_dm_policy_cback(BTA_SYS_PLCY_CLR, 0, HCI_ENABLE_MASTER_SLAVE_SWITCH,
+ p_dev->peer_bdaddr);
+ }
+ } else {
+ /* there's AV no activity on this link and role switch happened
+ * check if AV is active
+ * if so, make sure the AV link is master */
+ bta_dm_check_av(0);
+ }
+ bta_sys_notify_role_chg(bd_addr, new_role, hci_status);
+ conn.role_chg.bd_addr = bd_addr;
+ conn.role_chg.new_role = (uint8_t)new_role;
+ if (bta_dm_cb.p_sec_cback) bta_dm_cb.p_sec_cback(BTA_DM_ROLE_CHG_EVT, &conn);
+}
+
+static void bta_dm_acl_change(bool is_new, const RawAddress& bd_addr,
+ tBT_TRANSPORT transport, uint16_t handle) {
+ bool issue_unpair_cb = false;
+
+ tBTA_DM_SEC conn;
+ memset(&conn, 0, sizeof(tBTA_DM_SEC));
+
+ if (is_new) {
+ uint8_t i;
+ for (i = 0; i < bta_dm_cb.device_list.count; i++) {
+ if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == bd_addr &&
+ bta_dm_cb.device_list.peer_device[i].conn_handle == handle)
+ break;
+ }
+
+ if (i == bta_dm_cb.device_list.count) {
+ if (bta_dm_cb.device_list.count < BTA_DM_NUM_PEER_DEVICE) {
+ bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count]
+ .peer_bdaddr = bd_addr;
+ bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count]
+ .link_policy = bta_dm_cb.cur_policy;
+ bta_dm_cb.device_list.count++;
+ bta_dm_cb.device_list.peer_device[i].conn_handle = handle;
+ if (transport == BT_TRANSPORT_LE) bta_dm_cb.device_list.le_count++;
+ } else {
+ APPL_TRACE_ERROR("%s max active connection reached, no resources",
+ __func__);
+ return;
+ }
+ }
+
+ bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_CONNECTED;
+ bta_dm_cb.device_list.peer_device[i].pref_role = BTA_ANY_ROLE;
+ conn.link_up.bd_addr = bd_addr;
+ bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_NONE;
+ conn.link_up.link_type = transport;
+ bta_dm_cb.device_list.peer_device[i].transport = transport;
+
+ uint8_t* p;
+ if (((NULL != (p = BTM_ReadLocalFeatures())) &&
+ HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
+ ((NULL != (p = BTM_ReadRemoteFeatures(bd_addr))) &&
+ HCI_SNIFF_SUB_RATE_SUPPORTED(p))) {
+ /* both local and remote devices support SSR */
+ bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_USE_SSR;
+ }
+ APPL_TRACE_WARNING("%s info: 0x%x", __func__,
+ bta_dm_cb.device_list.peer_device[i].info);
+
+ if (bta_dm_cb.p_sec_cback) bta_dm_cb.p_sec_cback(BTA_DM_LINK_UP_EVT, &conn);
+ } else {
+ for (uint8_t i = 0; i < bta_dm_cb.device_list.count; i++) {
+ if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr != bd_addr ||
+ bta_dm_cb.device_list.peer_device[i].transport != transport)
+ continue;
+
+ if (bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_UNPAIRING) {
+ if (BTM_SecDeleteDevice(
+ bta_dm_cb.device_list.peer_device[i].peer_bdaddr))
+ issue_unpair_cb = true;
+
+ APPL_TRACE_DEBUG("%s: Unpairing: issue unpair CB = %d ", __func__,
+ issue_unpair_cb);
+ }
+
+ conn.link_down.is_removed =
+ bta_dm_cb.device_list.peer_device[i].remove_dev_pending;
+
+ // Iterate to the one before the last when shrinking the list,
+ // otherwise we memcpy garbage data into the record.
+ // Then clear out the last item in the list since we are shrinking.
+ for (; i < bta_dm_cb.device_list.count - 1; i++) {
+ memcpy(&bta_dm_cb.device_list.peer_device[i],
+ &bta_dm_cb.device_list.peer_device[i + 1],
+ sizeof(bta_dm_cb.device_list.peer_device[i]));
+ }
+ if (bta_dm_cb.device_list.count > 0) {
+ int clear_index = bta_dm_cb.device_list.count - 1;
+ memset(&bta_dm_cb.device_list.peer_device[clear_index], 0,
+ sizeof(bta_dm_cb.device_list.peer_device[clear_index]));
+ }
break;
- case BTM_BL_DISCN_EVT:
- p_msg->bd_addr = *p_data->discn.p_bda;
- p_msg->transport = p_data->discn.transport;
- p_msg->handle = p_data->discn.handle;
- break;
- case BTM_BL_UPDATE_EVT:
- p_msg->busy_level = p_data->update.busy_level;
- p_msg->busy_level_flags = p_data->update.busy_level_flags;
- break;
- case BTM_BL_ROLE_CHG_EVT:
- p_msg->new_role = p_data->role_chg.new_role;
- p_msg->hci_status = p_data->role_chg.hci_status;
- p_msg->bd_addr = *p_data->role_chg.p_bda;
- break;
- case BTM_BL_COLLISION_EVT:
- p_msg->bd_addr = *p_data->conn.p_bda;
- break;
+ }
+ if (bta_dm_cb.device_list.count) bta_dm_cb.device_list.count--;
+ if ((transport == BT_TRANSPORT_LE) && (bta_dm_cb.device_list.le_count))
+ bta_dm_cb.device_list.le_count--;
+ conn.link_down.link_type = transport;
+
+ if (bta_dm_search_cb.wait_disc && bta_dm_search_cb.peer_bdaddr == bd_addr) {
+ bta_dm_search_cb.wait_disc = false;
+
+ if (bta_dm_search_cb.sdp_results) {
+ APPL_TRACE_EVENT(" timer stopped ");
+ alarm_cancel(bta_dm_search_cb.search_timer);
+ bta_dm_discover_next_device();
+ }
+ }
+
+ if (bta_dm_cb.disabling) {
+ if (!BTM_GetNumAclLinks()) {
+ /*
+ * Start a timer to make sure that the profiles
+ * get the disconnect event.
+ */
+ alarm_set_on_mloop(bta_dm_cb.disable_timer,
+ BTA_DM_DISABLE_CONN_DOWN_TIMER_MS,
+ bta_dm_disable_conn_down_timer_cback, NULL);
+ }
+ }
+ if (conn.link_down.is_removed) {
+ BTM_SecDeleteDevice(bd_addr);
+ /* need to remove all pending background connection */
+ BTA_GATTC_CancelOpen(0, bd_addr, false);
+ /* remove all cached GATT information */
+ BTA_GATTC_Refresh(bd_addr);
+ }
+
+ conn.link_down.bd_addr = bd_addr;
+ conn.link_down.status = (uint8_t)btm_get_acl_disc_reason_code();
+ if (bta_dm_cb.p_sec_cback) {
+ bta_dm_cb.p_sec_cback(BTA_DM_LINK_DOWN_EVT, &conn);
+ if (issue_unpair_cb)
+ bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &conn);
+ }
}
- p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
- bta_sys_sendmsg(p_msg);
+ bta_dm_adjust_roles(true);
+}
+
+/** Callback from btm when acl connection goes up or down */
+static void bta_dm_bl_change_cback(tBTM_BL_EVENT_DATA* p_data) {
+ switch (p_data->event) {
+ case BTM_BL_CONN_EVT:
+ /* connection up */
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_acl_change, true, *p_data->conn.p_bda,
+ p_data->conn.transport, p_data->conn.handle));
+ break;
+ case BTM_BL_DISCN_EVT:
+ /* connection down */
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(bta_dm_acl_change, false, *p_data->discn.p_bda,
+ p_data->discn.transport, p_data->discn.handle));
+ break;
+
+ case BTM_BL_UPDATE_EVT: {
+ /* busy level update */
+ do_in_bta_thread(FROM_HERE, base::Bind(send_busy_level_update,
+ p_data->update.busy_level,
+ p_data->update.busy_level_flags));
+ return;
+ }
+ case BTM_BL_ROLE_CHG_EVT: {
+ const auto& tmp = p_data->role_chg;
+ do_in_bta_thread(FROM_HERE, base::Bind(handle_role_change, *tmp.p_bda,
+ tmp.new_role, tmp.hci_status));
+ return;
+ }
+
+ case BTM_BL_COLLISION_EVT:
+ /* Collision report from Stack: Notify profiles */
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(bta_sys_notify_collision, *p_data->conn.p_bda));
+ return;
+ }
}
/*******************************************************************************
@@ -2843,7 +2862,7 @@
* Returns
*
******************************************************************************/
-static void bta_dm_rs_cback(UNUSED_ATTR tBTM_ROLE_SWITCH_CMPL* p1) {
+static void bta_dm_rs_cback(UNUSED_ATTR void* p1) {
APPL_TRACE_WARNING("bta_dm_rs_cback:%d", bta_dm_cb.rs_event);
if (bta_dm_cb.rs_event == BTA_DM_API_SEARCH_EVT) {
bta_dm_cb.search_msg.rs_res =
@@ -2885,18 +2904,18 @@
APPL_TRACE_WARNING("[%d]: state:%d, info:x%x, avoid_rs %d", i,
p_dev->conn_state, p_dev->info, avoid_roleswitch);
if ((p_dev->conn_state == BTA_DM_CONNECTED) &&
- (p_dev->info & BTA_DM_DI_AV_ACTIVE) && (avoid_roleswitch == false)) {
+ (p_dev->info & BTA_DM_DI_AV_ACTIVE) && (!avoid_roleswitch)) {
/* make master and take away the role switch policy */
if (BTM_CMD_STARTED == BTM_SwitchRole(p_dev->peer_bdaddr,
HCI_ROLE_MASTER,
- (tBTM_CMPL_CB*)bta_dm_rs_cback)) {
+ bta_dm_rs_cback)) {
/* the role switch command is actually sent */
bta_dm_cb.rs_event = event;
switching = true;
}
/* else either already master or can not switch for some reasons */
bta_dm_policy_cback(BTA_SYS_PLCY_CLR, 0, HCI_ENABLE_MASTER_SLAVE_SWITCH,
- &p_dev->peer_bdaddr);
+ p_dev->peer_bdaddr);
break;
}
}
@@ -2906,216 +2925,6 @@
/*******************************************************************************
*
- * Function bta_dm_acl_change
- *
- * Description Process BTA_DM_ACL_CHANGE_EVT
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_acl_change(tBTA_DM_MSG* p_data) {
- uint8_t i;
- uint8_t* p;
- tBTA_DM_SEC conn;
- bool is_new = p_data->acl_change.is_new;
- const RawAddress& p_bda = p_data->acl_change.bd_addr;
- bool need_policy_change = false;
- bool issue_unpair_cb = false;
-
- tBTA_DM_PEER_DEVICE* p_dev;
- memset(&conn, 0, sizeof(tBTA_DM_SEC));
-
- switch (p_data->acl_change.event) {
- case BTM_BL_UPDATE_EVT: /* busy level update */
- if (bta_dm_cb.p_sec_cback) {
- conn.busy_level.level = p_data->acl_change.busy_level;
- conn.busy_level.level_flags = p_data->acl_change.busy_level_flags;
- bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn);
- }
- return;
-
- case BTM_BL_ROLE_CHG_EVT: /* role change event */
- p_dev = bta_dm_find_peer_device(p_bda);
- if (p_dev) {
- APPL_TRACE_DEBUG(
- "bta_dm_acl_change role chg info:x%x new_role:%d dev count:%d",
- p_dev->info, p_data->acl_change.new_role,
- bta_dm_cb.device_list.count);
- if (p_dev->info & BTA_DM_DI_AV_ACTIVE) {
- /* there's AV activity on this link */
- if (p_data->acl_change.new_role == HCI_ROLE_SLAVE &&
- bta_dm_cb.device_list.count > 1 &&
- p_data->acl_change.hci_status == HCI_SUCCESS) {
- /* more than one connections and the AV connection is role switched
- * to slave
- * switch it back to master and remove the switch policy */
- BTM_SwitchRole(p_bda, BTM_ROLE_MASTER, NULL);
- need_policy_change = true;
- } else if (p_bta_dm_cfg->avoid_scatter &&
- (p_data->acl_change.new_role == HCI_ROLE_MASTER)) {
- /* if the link updated to be master include AV activities, remove
- * the switch policy */
- need_policy_change = true;
- }
-
- if (need_policy_change) {
- bta_dm_policy_cback(BTA_SYS_PLCY_CLR, 0,
- HCI_ENABLE_MASTER_SLAVE_SWITCH,
- &p_dev->peer_bdaddr);
- }
- } else {
- /* there's AV no activity on this link and role switch happened
- * check if AV is active
- * if so, make sure the AV link is master */
- bta_dm_check_av(0);
- }
- bta_sys_notify_role_chg(p_data->acl_change.bd_addr,
- p_data->acl_change.new_role,
- p_data->acl_change.hci_status);
- conn.role_chg.bd_addr = p_bda;
- conn.role_chg.new_role = (uint8_t)p_data->acl_change.new_role;
- if (bta_dm_cb.p_sec_cback)
- bta_dm_cb.p_sec_cback(BTA_DM_ROLE_CHG_EVT, (tBTA_DM_SEC*)&conn);
- }
- return;
- }
-
- /* Collision report from Stack: Notify profiles */
- if (p_data->acl_change.event == BTM_BL_COLLISION_EVT) {
- bta_sys_notify_collision(p_bda);
- return;
- }
-
- if (is_new) {
- for (i = 0; i < bta_dm_cb.device_list.count; i++) {
- if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == p_bda &&
- bta_dm_cb.device_list.peer_device[i].conn_handle ==
- p_data->acl_change.handle)
- break;
- }
-
- if (i == bta_dm_cb.device_list.count) {
- if (bta_dm_cb.device_list.count < BTA_DM_NUM_PEER_DEVICE) {
- bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count]
- .peer_bdaddr = p_bda;
- bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count]
- .link_policy = bta_dm_cb.cur_policy;
- bta_dm_cb.device_list.count++;
- bta_dm_cb.device_list.peer_device[i].conn_handle =
- p_data->acl_change.handle;
- if (p_data->acl_change.transport == BT_TRANSPORT_LE)
- bta_dm_cb.device_list.le_count++;
- } else {
- APPL_TRACE_ERROR("%s max active connection reached, no resources",
- __func__);
- return;
- }
- }
-
- bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_CONNECTED;
- bta_dm_cb.device_list.peer_device[i].pref_role = BTA_ANY_ROLE;
- conn.link_up.bd_addr = p_bda;
- bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_NONE;
- conn.link_up.link_type = p_data->acl_change.transport;
- bta_dm_cb.device_list.peer_device[i].transport =
- p_data->acl_change.transport;
-
- if (((NULL != (p = BTM_ReadLocalFeatures())) &&
- HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
- ((NULL != (p = BTM_ReadRemoteFeatures(p_bda))) &&
- HCI_SNIFF_SUB_RATE_SUPPORTED(p))) {
- /* both local and remote devices support SSR */
- bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_USE_SSR;
- }
- APPL_TRACE_WARNING("%s info: 0x%x", __func__,
- bta_dm_cb.device_list.peer_device[i].info);
-
- if (bta_dm_cb.p_sec_cback)
- bta_dm_cb.p_sec_cback(BTA_DM_LINK_UP_EVT, (tBTA_DM_SEC*)&conn);
- } else {
- for (i = 0; i < bta_dm_cb.device_list.count; i++) {
- if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr != p_bda ||
- bta_dm_cb.device_list.peer_device[i].transport !=
- p_data->acl_change.transport)
- continue;
-
- if (bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_UNPAIRING) {
- if (BTM_SecDeleteDevice(
- bta_dm_cb.device_list.peer_device[i].peer_bdaddr))
- issue_unpair_cb = true;
-
- APPL_TRACE_DEBUG("%s: Unpairing: issue unpair CB = %d ", __func__,
- issue_unpair_cb);
- }
-
- conn.link_down.is_removed =
- bta_dm_cb.device_list.peer_device[i].remove_dev_pending;
-
- // Iterate to the one before the last when shrinking the list,
- // otherwise we memcpy garbage data into the record.
- // Then clear out the last item in the list since we are shrinking.
- for (; i < bta_dm_cb.device_list.count - 1; i++) {
- memcpy(&bta_dm_cb.device_list.peer_device[i],
- &bta_dm_cb.device_list.peer_device[i + 1],
- sizeof(bta_dm_cb.device_list.peer_device[i]));
- }
- if (bta_dm_cb.device_list.count > 0) {
- int clear_index = bta_dm_cb.device_list.count - 1;
- memset(&bta_dm_cb.device_list.peer_device[clear_index], 0,
- sizeof(bta_dm_cb.device_list.peer_device[clear_index]));
- }
- break;
- }
- if (bta_dm_cb.device_list.count) bta_dm_cb.device_list.count--;
- if ((p_data->acl_change.transport == BT_TRANSPORT_LE) &&
- (bta_dm_cb.device_list.le_count))
- bta_dm_cb.device_list.le_count--;
- conn.link_down.link_type = p_data->acl_change.transport;
-
- if (bta_dm_search_cb.wait_disc && bta_dm_search_cb.peer_bdaddr == p_bda) {
- bta_dm_search_cb.wait_disc = false;
-
- if (bta_dm_search_cb.sdp_results) {
- APPL_TRACE_EVENT(" timer stopped ");
- alarm_cancel(bta_dm_search_cb.search_timer);
- bta_dm_discover_next_device();
- }
- }
-
- if (bta_dm_cb.disabling) {
- if (!BTM_GetNumAclLinks()) {
- /*
- * Start a timer to make sure that the profiles
- * get the disconnect event.
- */
- alarm_set_on_mloop(bta_dm_cb.disable_timer,
- BTA_DM_DISABLE_CONN_DOWN_TIMER_MS,
- bta_dm_disable_conn_down_timer_cback, NULL);
- }
- }
- if (conn.link_down.is_removed) {
- BTM_SecDeleteDevice(p_bda);
- /* need to remove all pending background connection */
- BTA_GATTC_CancelOpen(0, p_bda, false);
- /* remove all cached GATT information */
- BTA_GATTC_Refresh(p_bda);
- }
-
- conn.link_down.bd_addr = p_bda;
- conn.link_down.status = (uint8_t)btm_get_acl_disc_reason_code();
- if (bta_dm_cb.p_sec_cback) {
- bta_dm_cb.p_sec_cback(BTA_DM_LINK_DOWN_EVT, &conn);
- if (issue_unpair_cb)
- bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &conn);
- }
- }
-
- bta_dm_adjust_roles(true);
-}
-
-/*******************************************************************************
- *
* Function bta_dm_disable_conn_down_timer_cback
*
* Description Sends disable event to application
@@ -3153,12 +2962,12 @@
*
******************************************************************************/
static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
- uint8_t app_id, const RawAddress* peer_addr) {
+ uint8_t app_id, const RawAddress& peer_addr) {
uint8_t j;
tBTA_PREF_ROLES role;
tBTA_DM_PEER_DEVICE* p_dev;
- p_dev = bta_dm_find_peer_device(*peer_addr);
+ p_dev = bta_dm_find_peer_device(peer_addr);
if (status == BTA_SYS_CONN_OPEN) {
if (p_dev) {
/* Do not set to connected if we are in the middle of unpairing. When AV
@@ -3326,7 +3135,7 @@
if (bta_dm_cb.device_list.peer_device[i].pref_role !=
BTA_SLAVE_ROLE_ONLY &&
- delay_role_switch == false) {
+ !delay_role_switch) {
BTM_SwitchRole(bta_dm_cb.device_list.peer_device[i].peer_bdaddr,
HCI_ROLE_MASTER, NULL);
} else {
@@ -3477,16 +3286,16 @@
if (local_name_len > p_bta_dm_eir_cfg->bta_dm_eir_min_name_len) {
/* get number of UUID 16-bit list */
#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
- num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len / LEN_UUID_16;
+ num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len / Uuid::kNumBytes16;
#else // BTA_EIR_CANNED_UUID_LIST
- max_num_uuid = (free_eir_length - 2) / LEN_UUID_16;
+ max_num_uuid = (free_eir_length - 2) / Uuid::kNumBytes16;
data_type = BTM_GetEirSupportedServices(bta_dm_cb.eir_uuid, &p,
max_num_uuid, &num_uuid);
p = (uint8_t*)p_buf + BTM_HCI_EIR_OFFSET; /* reset p */
#endif // BTA_EIR_CANNED_UUID_LIST
/* if UUID doesn't fit remaing space, shorten local name */
- if (local_name_len > (free_eir_length - 4 - num_uuid * LEN_UUID_16)) {
+ if (local_name_len > (free_eir_length - 4 - num_uuid * Uuid::kNumBytes16)) {
local_name_len = find_utf8_char_boundary(
local_name, p_bta_dm_eir_cfg->bta_dm_eir_min_name_len);
APPL_TRACE_WARNING("%s local name is shortened (%d)", __func__,
@@ -3510,23 +3319,24 @@
/* if UUID list is provided as static data in configuration */
if ((p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len > 0) &&
(p_bta_dm_eir_cfg->bta_dm_eir_uuid16)) {
- if (free_eir_length > LEN_UUID_16 + 2) {
+ if (free_eir_length > Uuid::kNumBytes16 + 2) {
free_eir_length -= 2;
if (free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len) {
- num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len / LEN_UUID_16;
+ num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len / Uuid::kNumBytes16;
data_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
} else /* not enough room for all UUIDs */
{
APPL_TRACE_WARNING("BTA EIR: UUID 16-bit list is truncated");
- num_uuid = free_eir_length / LEN_UUID_16;
+ num_uuid = free_eir_length / Uuid::kNumBytes16;
data_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
}
- UINT8_TO_STREAM(p, num_uuid * LEN_UUID_16 + 1);
+ UINT8_TO_STREAM(p, num_uuid * Uuid::kNumBytes16 + 1);
UINT8_TO_STREAM(p, data_type);
- memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_uuid16, num_uuid * LEN_UUID_16);
- p += num_uuid * LEN_UUID_16;
- free_eir_length -= num_uuid * LEN_UUID_16;
+ memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_uuid16,
+ num_uuid * Uuid::kNumBytes16);
+ p += num_uuid * Uuid::kNumBytes16;
+ free_eir_length -= num_uuid * Uuid::kNumBytes16;
}
}
#else /* (BTA_EIR_CANNED_UUID_LIST == TRUE) */
@@ -3536,7 +3346,7 @@
p_type = p++;
num_uuid = 0;
- max_num_uuid = (free_eir_length - 2) / LEN_UUID_16;
+ max_num_uuid = (free_eir_length - 2) / Uuid::kNumBytes16;
data_type = BTM_GetEirSupportedServices(bta_dm_cb.eir_uuid, &p,
max_num_uuid, &num_uuid);
@@ -3548,10 +3358,10 @@
for (custom_uuid_idx = 0;
custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID;
custom_uuid_idx++) {
- if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_16) {
+ const Uuid& curr = bta_dm_cb.custom_uuid[custom_uuid_idx];
+ if (curr.GetShortestRepresentationSize() == Uuid::kNumBytes16) {
if (num_uuid < max_num_uuid) {
- UINT16_TO_STREAM(p,
- bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid16);
+ UINT16_TO_STREAM(p, curr.As16Bit());
num_uuid++;
} else {
data_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
@@ -3563,9 +3373,9 @@
}
#endif /* (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0) */
- UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_16 + 1);
+ UINT8_TO_STREAM(p_length, num_uuid * Uuid::kNumBytes16 + 1);
UINT8_TO_STREAM(p_type, data_type);
- free_eir_length -= num_uuid * LEN_UUID_16 + 2;
+ free_eir_length -= num_uuid * Uuid::kNumBytes16 + 2;
}
#endif /* (BTA_EIR_CANNED_UUID_LIST == TRUE) */
@@ -3577,13 +3387,14 @@
num_uuid = 0;
data_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
- max_num_uuid = (free_eir_length - 2) / LEN_UUID_32;
+ max_num_uuid = (free_eir_length - 2) / Uuid::kNumBytes32;
for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID;
custom_uuid_idx++) {
- if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_32) {
+ const Uuid& curr = bta_dm_cb.custom_uuid[custom_uuid_idx];
+ if (curr.GetShortestRepresentationSize() == Uuid::kNumBytes32) {
if (num_uuid < max_num_uuid) {
- UINT32_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid32);
+ UINT32_TO_STREAM(p, curr.As32Bit());
num_uuid++;
} else {
data_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
@@ -3593,9 +3404,9 @@
}
}
- UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_32 + 1);
+ UINT8_TO_STREAM(p_length, num_uuid * Uuid::kNumBytes32 + 1);
UINT8_TO_STREAM(p_type, data_type);
- free_eir_length -= num_uuid * LEN_UUID_32 + 2;
+ free_eir_length -= num_uuid * Uuid::kNumBytes32 + 2;
}
/* Adding 128-bit UUID list */
@@ -3605,14 +3416,14 @@
num_uuid = 0;
data_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
- max_num_uuid = (free_eir_length - 2) / LEN_UUID_128;
+ max_num_uuid = (free_eir_length - 2) / Uuid::kNumBytes128;
for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID;
custom_uuid_idx++) {
- if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_128) {
+ const Uuid& curr = bta_dm_cb.custom_uuid[custom_uuid_idx];
+ if (curr.GetShortestRepresentationSize() == Uuid::kNumBytes128) {
if (num_uuid < max_num_uuid) {
- ARRAY16_TO_STREAM(p,
- bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid128);
+ ARRAY16_TO_STREAM(p, curr.To128BitBE().data());
num_uuid++;
} else {
data_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
@@ -3622,9 +3433,9 @@
}
}
- UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_128 + 1);
+ UINT8_TO_STREAM(p_length, num_uuid * Uuid::kNumBytes128 + 1);
UINT8_TO_STREAM(p_type, data_type);
- free_eir_length -= num_uuid * LEN_UUID_128 + 2;
+ free_eir_length -= num_uuid * Uuid::kNumBytes128 + 2;
}
#endif /* ( BTA_EIR_CANNED_UUID_LIST != TRUE \
)&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0) */
@@ -3767,54 +3578,6 @@
/*******************************************************************************
*
- * Function bta_dm_enable_test_mode
- *
- * Description enable test mode
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_enable_test_mode(UNUSED_ATTR tBTA_DM_MSG* p_data) {
- BTM_EnableTestMode();
-}
-
-/*******************************************************************************
- *
- * Function bta_dm_disable_test_mode
- *
- * Description disable test mode
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_disable_test_mode(UNUSED_ATTR tBTA_DM_MSG* p_data) {
- BTM_DeviceReset(NULL);
-}
-
-/*******************************************************************************
- *
- * Function bta_dm_execute_callback
- *
- * Description Just execute a generic call back in the context of the
- * BTU/BTA tack
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_execute_callback(tBTA_DM_MSG* p_data) {
- /* sanity check */
- if (p_data->exec_cback.p_exec_cback == NULL) {
- return;
- }
-
- p_data->exec_cback.p_exec_cback(p_data->exec_cback.p_param);
-}
-
-/*******************************************************************************
- *
* Function bta_dm_encrypt_cback
*
* Description link encryption complete callback.
@@ -3864,44 +3627,32 @@
}
}
-/*******************************************************************************
- *
- * Function bta_dm_set_encryption
- *
- * Description This function to encrypt the link
- *
- * Returns None
- *
- ******************************************************************************/
-void bta_dm_set_encryption(tBTA_DM_MSG* p_data) {
+/**This function to encrypt the link */
+void bta_dm_set_encryption(const RawAddress& bd_addr, tBTA_TRANSPORT transport,
+ tBTA_DM_ENCRYPT_CBACK* p_callback,
+ tBTA_DM_BLE_SEC_ACT sec_act) {
uint8_t i;
APPL_TRACE_DEBUG("bta_dm_set_encryption"); // todo
- if (!p_data->set_encryption.p_callback) {
+ if (!p_callback) {
APPL_TRACE_ERROR("bta_dm_set_encryption callback is not provided");
return;
}
for (i = 0; i < bta_dm_cb.device_list.count; i++) {
- if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr ==
- p_data->set_encryption.bd_addr &&
+ if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == bd_addr &&
bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED)
break;
}
if (i < bta_dm_cb.device_list.count) {
if (bta_dm_cb.device_list.peer_device[i].p_encrypt_cback) {
APPL_TRACE_ERROR("earlier enc was not done for same device");
- (*p_data->set_encryption.p_callback)(p_data->set_encryption.bd_addr,
- p_data->set_encryption.transport,
- BTA_BUSY);
+ (*p_callback)(bd_addr, transport, BTA_BUSY);
return;
}
- if (BTM_SetEncryption(p_data->set_encryption.bd_addr,
- p_data->set_encryption.transport,
- bta_dm_encrypt_cback, NULL,
- p_data->set_encryption.sec_act) == BTM_CMD_STARTED) {
- bta_dm_cb.device_list.peer_device[i].p_encrypt_cback =
- p_data->set_encryption.p_callback;
+ if (BTM_SetEncryption(bd_addr, transport, bta_dm_encrypt_cback, NULL,
+ sec_act) == BTM_CMD_STARTED) {
+ bta_dm_cb.device_list.peer_device[i].p_encrypt_cback = p_callback;
}
}
}
@@ -4157,12 +3908,10 @@
* Parameters:
*
******************************************************************************/
-void bta_dm_add_blekey(tBTA_DM_MSG* p_data) {
- if (!BTM_SecAddBleKey(p_data->add_ble_key.bd_addr,
- (tBTM_LE_KEY_VALUE*)&p_data->add_ble_key.blekey,
- p_data->add_ble_key.key_type)) {
- LOG(ERROR) << "BTA_DM: Error adding BLE Key for device "
- << p_data->add_ble_key.bd_addr;
+void bta_dm_add_blekey(const RawAddress& bd_addr, tBTA_LE_KEY_VALUE blekey,
+ tBTA_LE_KEY_TYPE key_type) {
+ if (!BTM_SecAddBleKey(bd_addr, (tBTM_LE_KEY_VALUE*)&blekey, key_type)) {
+ LOG(ERROR) << "BTA_DM: Error adding BLE Key for device " << bd_addr;
}
}
@@ -4178,12 +3927,10 @@
* Parameters:
*
******************************************************************************/
-void bta_dm_add_ble_device(tBTA_DM_MSG* p_data) {
- if (!BTM_SecAddBleDevice(p_data->add_ble_device.bd_addr, NULL,
- p_data->add_ble_device.dev_type,
- p_data->add_ble_device.addr_type)) {
- LOG(ERROR) << "BTA_DM: Error adding BLE Device for device "
- << p_data->add_ble_device.bd_addr;
+void bta_dm_add_ble_device(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
+ tBT_DEVICE_TYPE dev_type) {
+ if (!BTM_SecAddBleDevice(bd_addr, NULL, dev_type, addr_type)) {
+ LOG(ERROR) << "BTA_DM: Error adding BLE Device for device " << bd_addr;
}
}
@@ -4199,152 +3946,76 @@
* Parameters:
*
******************************************************************************/
-void bta_dm_ble_passkey_reply(tBTA_DM_MSG* p_data) {
- if (p_data->pin_reply.accept) {
- BTM_BlePasskeyReply(p_data->ble_passkey_reply.bd_addr, BTM_SUCCESS,
- p_data->ble_passkey_reply.passkey);
- } else {
- BTM_BlePasskeyReply(p_data->ble_passkey_reply.bd_addr, BTM_NOT_AUTHORIZED,
- p_data->ble_passkey_reply.passkey);
- }
+void bta_dm_ble_passkey_reply(const RawAddress& bd_addr, bool accept,
+ uint32_t passkey) {
+ BTM_BlePasskeyReply(bd_addr, accept ? BTM_SUCCESS : BTM_NOT_AUTHORIZED,
+ passkey);
}
-/*******************************************************************************
- *
- * Function bta_dm_ble_confirm_reply
- *
- * Description This is response to SM numeric comparison request submitted
- * to application.
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_ble_confirm_reply(tBTA_DM_MSG* p_data) {
- if (p_data->confirm.accept) {
- BTM_BleConfirmReply(p_data->confirm.bd_addr, BTM_SUCCESS);
- } else {
- BTM_BleConfirmReply(p_data->ble_passkey_reply.bd_addr, BTM_NOT_AUTHORIZED);
- }
+/** This is response to SM numeric comparison request submitted to application.
+ */
+void bta_dm_ble_confirm_reply(const RawAddress& bd_addr, bool accept) {
+ BTM_BleConfirmReply(bd_addr, accept ? BTM_SUCCESS : BTM_NOT_AUTHORIZED);
}
-/*******************************************************************************
- *
- * Function bta_dm_security_grant
- *
- * Description This function grant SMP security request access.
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_security_grant(tBTA_DM_MSG* p_data) {
- BTM_SecurityGrant(p_data->ble_sec_grant.bd_addr, p_data->ble_sec_grant.res);
+/** This function set the preferred connection parameters */
+void bta_dm_ble_set_conn_params(const RawAddress& bd_addr,
+ uint16_t conn_int_min, uint16_t conn_int_max,
+ uint16_t slave_latency,
+ uint16_t supervision_tout) {
+ L2CA_AdjustConnectionIntervals(&conn_int_min, &conn_int_max,
+ BTM_BLE_CONN_INT_MIN);
+
+ BTM_BleSetPrefConnParams(bd_addr, conn_int_min, conn_int_max, slave_latency,
+ supervision_tout);
}
-/*******************************************************************************
- *
- * Function bta_dm_ble_set_bg_conn_type
- *
- * Description This function set the BLE background connection type
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_ble_set_bg_conn_type(tBTA_DM_MSG* p_data) {
- BTM_BleStartAutoConn();
+/** This function set the preferred connection scan parameters */
+void bta_dm_ble_set_conn_scan_params(uint32_t scan_interval,
+ uint32_t scan_window) {
+ BTM_BleSetConnScanParams(scan_interval, scan_window);
}
-/*******************************************************************************
- *
- * Function bta_dm_ble_set_conn_params
- *
- * Description This function set the preferred connection parameters.
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_ble_set_conn_params(tBTA_DM_MSG* p_data) {
- BTM_BleSetPrefConnParams(p_data->ble_set_conn_params.peer_bda,
- p_data->ble_set_conn_params.conn_int_min,
- p_data->ble_set_conn_params.conn_int_max,
- p_data->ble_set_conn_params.slave_latency,
- p_data->ble_set_conn_params.supervision_tout);
-}
+/** This function update LE connection parameters */
+void bta_dm_ble_update_conn_params(const RawAddress& bd_addr, uint16_t min_int,
+ uint16_t max_int, uint16_t latency,
+ uint16_t timeout, uint16_t min_ce_len,
+ uint16_t max_ce_len) {
+ L2CA_AdjustConnectionIntervals(&min_int, &max_int, BTM_BLE_CONN_INT_MIN);
-/*******************************************************************************
- *
- * Function bta_dm_ble_set_conn_scan_params
- *
- * Description This function set the preferred connection scan parameters.
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_ble_set_conn_scan_params(tBTA_DM_MSG* p_data) {
- BTM_BleSetConnScanParams(p_data->ble_set_conn_scan_params.scan_int,
- p_data->ble_set_conn_scan_params.scan_window);
-}
-/*******************************************************************************
- *
- * Function bta_dm_ble_update_conn_params
- *
- * Description This function update LE connection parameters.
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_ble_update_conn_params(tBTA_DM_MSG* p_data) {
- if (!L2CA_UpdateBleConnParams(p_data->ble_update_conn_params.bd_addr,
- p_data->ble_update_conn_params.min_int,
- p_data->ble_update_conn_params.max_int,
- p_data->ble_update_conn_params.latency,
- p_data->ble_update_conn_params.timeout)) {
+ if (!L2CA_UpdateBleConnParams(bd_addr, min_int, max_int, latency, timeout,
+ min_ce_len, max_ce_len)) {
APPL_TRACE_ERROR("Update connection parameters failed!");
}
}
#if (BLE_PRIVACY_SPT == TRUE)
-/*******************************************************************************
- *
- * Function bta_dm_ble_config_local_privacy
- *
- * Description This function set the local device LE privacy settings.
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_ble_config_local_privacy(tBTA_DM_MSG* p_data) {
- BTM_BleConfigPrivacy(p_data->ble_local_privacy.privacy_enable);
+/** This function set the local device LE privacy settings. */
+void bta_dm_ble_config_local_privacy(bool privacy_enable) {
+ BTM_BleConfigPrivacy(privacy_enable);
}
#endif
-/*******************************************************************************
- *
- * Function bta_dm_ble_observe
- *
- * Description This function set the preferred connection scan parameters.
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_ble_observe(tBTA_DM_MSG* p_data) {
- tBTM_STATUS status;
- if (p_data->ble_observe.start) {
- /*Save the callback to be called when a scan results are available */
- bta_dm_search_cb.p_scan_cback = p_data->ble_observe.p_cback;
- status = BTM_BleObserve(true, p_data->ble_observe.duration,
- bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb);
- if (status != BTM_CMD_STARTED) {
- tBTA_DM_SEARCH data;
- APPL_TRACE_WARNING(" %s BTM_BleObserve failed. status %d", __func__,
- status);
- data.inq_cmpl.num_resps = 0;
- if (bta_dm_search_cb.p_scan_cback) {
- bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
- }
- }
- } else {
+void bta_dm_ble_observe(bool start, uint8_t duration,
+ tBTA_DM_SEARCH_CBACK* p_cback) {
+ if (!start) {
bta_dm_search_cb.p_scan_cback = NULL;
BTM_BleObserve(false, 0, NULL, NULL);
+ return;
+ }
+
+ /*Save the callback to be called when a scan results are available */
+ bta_dm_search_cb.p_scan_cback = p_cback;
+ tBTM_STATUS status = BTM_BleObserve(true, duration, bta_dm_observe_results_cb,
+ bta_dm_observe_cmpl_cb);
+ if (status != BTM_CMD_STARTED) {
+ tBTA_DM_SEARCH data;
+ APPL_TRACE_WARNING(" %s BTM_BleObserve failed. status %d", __func__,
+ status);
+ data.inq_cmpl.num_resps = 0;
+ if (bta_dm_search_cb.p_scan_cback) {
+ bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
+ }
}
}
/*******************************************************************************
@@ -4362,19 +4033,10 @@
BTA_DM_BLE_ADV_CHNL_MAP);
}
-/*******************************************************************************
- *
- * Function bta_dm_ble_set_data_length
- *
- * Description This function set the maximum transmission packet size
- *
- * Parameters
- *
- ******************************************************************************/
-void bta_dm_ble_set_data_length(tBTA_DM_MSG* p_data) {
- if (BTM_SetBleDataLength(p_data->ble_set_data_length.remote_bda,
- p_data->ble_set_data_length.tx_data_length) !=
- BTM_SUCCESS) {
+/** This function set the maximum transmission packet size */
+void bta_dm_ble_set_data_length(const RawAddress& bd_addr,
+ uint16_t tx_data_length) {
+ if (BTM_SetBleDataLength(bd_addr, tx_data_length) != BTM_SUCCESS) {
APPL_TRACE_ERROR("%s failed", __func__);
}
}
@@ -4404,20 +4066,11 @@
ctrl_state, st);
}
-/*******************************************************************************
- *
- * Function bta_dm_ble_get_energy_info
- *
- * Description This function obtains the energy info
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_ble_get_energy_info(tBTA_DM_MSG* p_data) {
- tBTM_STATUS btm_status = 0;
-
- bta_dm_cb.p_energy_info_cback = p_data->ble_energy_info.p_energy_info_cback;
- btm_status = BTM_BleGetEnergyInfo(bta_ble_energy_info_cmpl);
+/** This function obtains the energy info */
+void bta_dm_ble_get_energy_info(
+ tBTA_BLE_ENERGY_INFO_CBACK* p_energy_info_cback) {
+ bta_dm_cb.p_energy_info_cback = p_energy_info_cback;
+ tBTM_STATUS btm_status = BTM_BleGetEnergyInfo(bta_ble_energy_info_cmpl);
if (BTM_CMD_STARTED != btm_status)
bta_ble_energy_info_cmpl(0, 0, 0, 0, btm_status);
}
@@ -4440,7 +4093,7 @@
if (bta_dm_search_cb.client_if == BTA_GATTS_INVALID_IF) {
BTA_GATTC_AppRegister(bta_dm_gattc_callback,
base::Bind([](uint8_t client_id, uint8_t status) {
- if (status == BTA_GATT_OK)
+ if (status == GATT_SUCCESS)
bta_dm_search_cb.client_if = client_id;
else
bta_dm_search_cb.client_if = BTA_GATTS_INVALID_IF;
@@ -4459,11 +4112,8 @@
*
******************************************************************************/
static void btm_dm_start_disc_gatt_services(uint16_t conn_id) {
- tBT_UUID* p_uuid = bta_dm_search_cb.p_srvc_uuid + bta_dm_search_cb.num_uuid -
- bta_dm_search_cb.uuid_to_search;
-
- p_uuid = bta_dm_search_cb.p_srvc_uuid + bta_dm_search_cb.num_uuid -
- bta_dm_search_cb.uuid_to_search;
+ Uuid* p_uuid = bta_dm_search_cb.p_srvc_uuid + bta_dm_search_cb.num_uuid -
+ bta_dm_search_cb.uuid_to_search;
/* always search for all services */
BTA_GATTC_ServiceSearchRequest(conn_id, p_uuid);
@@ -4490,11 +4140,14 @@
if (bta_dm_search_cb.ble_raw_used + sizeof(tBTA_GATT_ID) <
bta_dm_search_cb.ble_raw_size) {
APPL_TRACE_DEBUG(
- "ADDING BLE SERVICE uuid=0x%x, ble_ptr = 0x%x, ble_raw_used = 0x%x",
- service_id.uuid.uu.uuid16, bta_dm_search_cb.p_ble_rawdata,
+ "ADDING BLE SERVICE uuid=%s, ble_ptr = 0x%x, ble_raw_used = 0x%x",
+ service_id.uuid.ToString().c_str(), bta_dm_search_cb.p_ble_rawdata,
bta_dm_search_cb.ble_raw_used);
if (bta_dm_search_cb.p_ble_rawdata) {
+ // TODO(jpawlowski): the p_ble_raw data is only sent to btif_dm.cc, but is
+ // never used there. Get rid of this code completly, or implement the
+ // TODOs from btif_dm.cc
memcpy((bta_dm_search_cb.p_ble_rawdata + bta_dm_search_cb.ble_raw_used),
&service_id, sizeof(service_id));
@@ -4510,14 +4163,14 @@
__func__, bta_dm_search_cb.ble_raw_size, bta_dm_search_cb.ble_raw_used);
}
- LOG_INFO(LOG_TAG, "%s service_id_uuid_len=%d ", __func__,
- service_id.uuid.len);
+ LOG_INFO(LOG_TAG, "%s service_id_uuid_len=%zu", __func__,
+ service_id.uuid.GetShortestRepresentationSize());
if (bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE) {
/* send result back to app now, one by one */
result.disc_ble_res.bd_addr = bta_dm_search_cb.peer_bdaddr;
strlcpy((char*)result.disc_ble_res.bd_name, bta_dm_get_remname(),
BD_NAME_LEN);
- memcpy(&result.disc_ble_res.service, &service_id.uuid, sizeof(tBT_UUID));
+ result.disc_ble_res.service = service_id.uuid;
bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
}
@@ -4532,13 +4185,12 @@
* Parameters:
*
******************************************************************************/
-static void bta_dm_gatt_disc_complete(uint16_t conn_id,
- tBTA_GATT_STATUS status) {
+static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status) {
APPL_TRACE_DEBUG("%s conn_id = %d", __func__, conn_id);
if (bta_dm_search_cb.uuid_to_search > 0) bta_dm_search_cb.uuid_to_search--;
- if (status == BTA_GATT_OK && bta_dm_search_cb.uuid_to_search > 0) {
+ if (status == GATT_SUCCESS && bta_dm_search_cb.uuid_to_search > 0) {
btm_dm_start_disc_gatt_services(conn_id);
} else {
tBTA_DM_MSG* p_msg = (tBTA_DM_MSG*)osi_malloc(sizeof(tBTA_DM_MSG));
@@ -4548,7 +4200,7 @@
/* no more services to be discovered */
p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
p_msg->disc_result.result.disc_res.result =
- (status == BTA_GATT_OK) ? BTA_SUCCESS : BTA_FAILURE;
+ (status == GATT_SUCCESS) ? BTA_SUCCESS : BTA_FAILURE;
APPL_TRACE_DEBUG("%s service found: 0x%08x", __func__,
bta_dm_search_cb.services_found);
p_msg->disc_result.result.disc_res.services =
@@ -4576,7 +4228,7 @@
bta_sys_sendmsg(p_msg);
- if (conn_id != BTA_GATT_INVALID_CONN_ID) {
+ if (conn_id != GATT_INVALID_CONN_ID) {
/* start a GATT channel close delay timer */
bta_sys_start_timer(bta_dm_search_cb.gatt_close_timer,
BTA_DM_GATT_CLOSE_DELAY_TOUT,
@@ -4598,11 +4250,11 @@
*
******************************************************************************/
void bta_dm_close_gatt_conn(UNUSED_ATTR tBTA_DM_MSG* p_data) {
- if (bta_dm_search_cb.conn_id != BTA_GATT_INVALID_CONN_ID)
+ if (bta_dm_search_cb.conn_id != GATT_INVALID_CONN_ID)
BTA_GATTC_Close(bta_dm_search_cb.conn_id);
bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty;
- bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
+ bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID;
}
/*******************************************************************************
*
@@ -4619,17 +4271,17 @@
/* connection is already open */
if (bta_dm_search_cb.pending_close_bda == bd_addr &&
- bta_dm_search_cb.conn_id != BTA_GATT_INVALID_CONN_ID) {
+ bta_dm_search_cb.conn_id != GATT_INVALID_CONN_ID) {
bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty;
alarm_cancel(bta_dm_search_cb.gatt_close_timer);
btm_dm_start_disc_gatt_services(bta_dm_search_cb.conn_id);
} else {
if (BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE)) {
BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, true,
- BTA_GATT_TRANSPORT_LE, true);
+ GATT_TRANSPORT_LE, true);
} else {
BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, true,
- BTA_GATT_TRANSPORT_LE, false);
+ GATT_TRANSPORT_LE, false);
}
}
}
@@ -4644,12 +4296,11 @@
*
******************************************************************************/
static void bta_dm_cancel_gatt_discovery(const RawAddress& bd_addr) {
- if (bta_dm_search_cb.conn_id == BTA_GATT_INVALID_CONN_ID) {
+ if (bta_dm_search_cb.conn_id == GATT_INVALID_CONN_ID) {
BTA_GATTC_CancelOpen(bta_dm_search_cb.client_if, bd_addr, true);
}
- bta_dm_gatt_disc_complete(bta_dm_search_cb.conn_id,
- (tBTA_GATT_STATUS)BTA_GATT_ERROR);
+ bta_dm_gatt_disc_complete(bta_dm_search_cb.conn_id, (tGATT_STATUS)GATT_ERROR);
}
/*******************************************************************************
@@ -4671,10 +4322,10 @@
bta_dm_search_cb.conn_id = p_data->conn_id;
- if (p_data->status == BTA_GATT_OK) {
+ if (p_data->status == GATT_SUCCESS) {
btm_dm_start_disc_gatt_services(p_data->conn_id);
} else {
- bta_dm_gatt_disc_complete(BTA_GATT_INVALID_CONN_ID, p_data->status);
+ bta_dm_gatt_disc_complete(GATT_INVALID_CONN_ID, p_data->status);
}
}
@@ -4711,8 +4362,8 @@
if ((bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE) &&
(bta_dm_search_cb.state != BTA_DM_SEARCH_ACTIVE) &&
p_data->close.remote_bda == bta_dm_search_cb.peer_bdaddr) {
- bta_dm_gatt_disc_complete((uint16_t)BTA_GATT_INVALID_CONN_ID,
- (tBTA_GATT_STATUS)BTA_GATT_ERROR);
+ bta_dm_gatt_disc_complete((uint16_t)GATT_INVALID_CONN_ID,
+ (tGATT_STATUS)GATT_ERROR);
}
break;
diff --git a/bta/dm/bta_dm_api.cc b/bta/dm/bta_dm_api.cc
index c06de60..e968bd1 100644
--- a/bta/dm/bta_dm_api.cc
+++ b/bta/dm/bta_dm_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2014 Broadcom Corporation
+ * Copyright 2003-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,12 +35,12 @@
#include "osi/include/osi.h"
#include "utl.h"
+using bluetooth::Uuid;
+
/*****************************************************************************
* Constants
****************************************************************************/
-static const tBTA_SYS_REG bta_dm_reg = {bta_dm_sm_execute, bta_dm_sm_disable};
-
static const tBTA_SYS_REG bta_dm_search_reg = {bta_dm_search_sm_execute,
bta_dm_search_sm_disable};
@@ -59,19 +59,12 @@
/* Bluetooth disabling is in progress */
if (bta_dm_cb.disabling) return BTA_FAILURE;
- bta_sys_register(BTA_ID_DM, &bta_dm_reg);
bta_sys_register(BTA_ID_DM_SEARCH, &bta_dm_search_reg);
/* if UUID list is not provided as static data */
bta_sys_eir_register(bta_dm_eir_update_uuid);
- tBTA_DM_API_ENABLE* p_msg =
- (tBTA_DM_API_ENABLE*)osi_malloc(sizeof(tBTA_DM_API_ENABLE));
- p_msg->hdr.event = BTA_DM_API_ENABLE_EVT;
- p_msg->p_sec_cback = p_cback;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_enable, p_cback));
return BTA_SUCCESS;
}
@@ -86,99 +79,37 @@
*
******************************************************************************/
tBTA_STATUS BTA_DisableBluetooth(void) {
- BT_HDR* p_msg = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_msg->event = BTA_DM_API_DISABLE_EVT;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_disable));
return BTA_SUCCESS;
}
-/*******************************************************************************
- *
- * Function BTA_EnableTestMode
- *
- * Description Enables bluetooth device under test mode
- *
- *
- * Returns tBTA_STATUS
- *
- ******************************************************************************/
-tBTA_STATUS BTA_EnableTestMode(void) {
- BT_HDR* p_msg = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- APPL_TRACE_API("%s", __func__);
-
- p_msg->event = BTA_DM_API_ENABLE_TEST_MODE_EVT;
- bta_sys_sendmsg(p_msg);
-
- return BTA_SUCCESS;
+/** Enables bluetooth device under test mode */
+void BTA_EnableTestMode(void) {
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(base::IgnoreResult(BTM_EnableTestMode)));
}
-/*******************************************************************************
- *
- * Function BTA_DisableTestMode
- *
- * Description Disable bluetooth device under test mode
- *
- *
- * Returns None
- *
- ******************************************************************************/
+/** Disable bluetooth device under test mode */
void BTA_DisableTestMode(void) {
- BT_HDR* p_msg = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- APPL_TRACE_API("%s", __func__);
-
- p_msg->event = BTA_DM_API_DISABLE_TEST_MODE_EVT;
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(BTM_DeviceReset, nullptr));
}
-/*******************************************************************************
- *
- * Function BTA_DmSetDeviceName
- *
- * Description This function sets the Bluetooth name of local device
- *
- *
- * Returns void
- *
- ******************************************************************************/
+/** This function sets the Bluetooth name of local device */
void BTA_DmSetDeviceName(char* p_name) {
- tBTA_DM_API_SET_NAME* p_msg =
- (tBTA_DM_API_SET_NAME*)osi_malloc(sizeof(tBTA_DM_API_SET_NAME));
+ std::vector<uint8_t> name(BD_NAME_LEN);
+ strlcpy((char*)name.data(), p_name, BD_NAME_LEN);
- p_msg->hdr.event = BTA_DM_API_SET_NAME_EVT;
- strlcpy((char*)p_msg->name, p_name, BD_NAME_LEN);
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_set_dev_name, name));
}
-/*******************************************************************************
- *
- * Function BTA_DmSetVisibility
- *
- * Description This function sets the Bluetooth connectable,
- * discoverable, pairable and conn paired only modes of local
- * device
- *
- *
- * Returns void
- *
- ******************************************************************************/
+/** This function sets the Bluetooth connectable, discoverable, pairable and
+ * conn paired only modes of local device
+ */
void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode,
- uint8_t pairable_mode, uint8_t conn_filter) {
- tBTA_DM_API_SET_VISIBILITY* p_msg =
- (tBTA_DM_API_SET_VISIBILITY*)osi_malloc(sizeof(tBTA_DM_MSG));
-
- p_msg->hdr.event = BTA_DM_API_SET_VISIBILITY_EVT;
- p_msg->disc_mode = disc_mode;
- p_msg->conn_mode = conn_mode;
- p_msg->pair_mode = pairable_mode;
- p_msg->conn_paired_only = conn_filter;
-
- bta_sys_sendmsg(p_msg);
+ uint8_t pairable_mode, uint8_t conn_paired_only) {
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_set_visibility, disc_mode, conn_mode,
+ pairable_mode, conn_paired_only));
}
/*******************************************************************************
@@ -260,7 +191,7 @@
* Returns void
*
******************************************************************************/
-void BTA_DmDiscoverUUID(const RawAddress& bd_addr, tSDP_UUID* uuid,
+void BTA_DmDiscoverUUID(const RawAddress& bd_addr, const Uuid& uuid,
tBTA_DM_SEARCH_CBACK* p_cback, bool sdp_search) {
tBTA_DM_API_DISCOVER* p_msg =
(tBTA_DM_API_DISCOVER*)osi_malloc(sizeof(tBTA_DM_API_DISCOVER));
@@ -273,76 +204,27 @@
p_msg->num_uuid = 0;
p_msg->p_uuid = NULL;
-
- memcpy(&p_msg->uuid, uuid, sizeof(tSDP_UUID));
+ p_msg->uuid = uuid;
bta_sys_sendmsg(p_msg);
}
-/*******************************************************************************
- *
- * Function BTA_DmBond
- *
- * Description This function initiates a bonding procedure with a peer
- * device
- *
- *
- * Returns void
- *
- ******************************************************************************/
+/** This function initiates a bonding procedure with a peer device */
void BTA_DmBond(const RawAddress& bd_addr) {
- tBTA_DM_API_BOND* p_msg =
- (tBTA_DM_API_BOND*)osi_malloc(sizeof(tBTA_DM_API_BOND));
-
- p_msg->hdr.event = BTA_DM_API_BOND_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->transport = BTA_TRANSPORT_UNKNOWN;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_bond, bd_addr, BTA_TRANSPORT_UNKNOWN));
}
-/*******************************************************************************
- *
- * Function BTA_DmBondByTransports
- *
- * Description This function initiates a bonding procedure with a peer
- * device
- *
- *
- * Returns void
- *
- ******************************************************************************/
+/** This function initiates a bonding procedure with a peer device */
void BTA_DmBondByTransport(const RawAddress& bd_addr,
tBTA_TRANSPORT transport) {
- tBTA_DM_API_BOND* p_msg =
- (tBTA_DM_API_BOND*)osi_malloc(sizeof(tBTA_DM_API_BOND));
-
- p_msg->hdr.event = BTA_DM_API_BOND_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->transport = transport;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_bond, bd_addr, transport));
}
-/*******************************************************************************
- *
- * Function BTA_DmBondCancel
- *
- * Description This function cancels the bonding procedure with a peer
- * device
- *
- *
- * Returns void
- *
- ******************************************************************************/
+/** This function cancels the bonding procedure with a peer device
+ */
void BTA_DmBondCancel(const RawAddress& bd_addr) {
- tBTA_DM_API_BOND_CANCEL* p_msg =
- (tBTA_DM_API_BOND_CANCEL*)osi_malloc(sizeof(tBTA_DM_API_BOND_CANCEL));
-
- p_msg->hdr.event = BTA_DM_API_BOND_CANCEL_EVT;
- p_msg->bd_addr = bd_addr;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_bond_cancel, bd_addr));
}
/*******************************************************************************
@@ -357,21 +239,18 @@
*
******************************************************************************/
void BTA_DmPinReply(const RawAddress& bd_addr, bool accept, uint8_t pin_len,
- uint8_t* p_pin)
+ uint8_t* p_pin) {
+ std::unique_ptr<tBTA_DM_API_PIN_REPLY> msg =
+ std::make_unique<tBTA_DM_API_PIN_REPLY>();
-{
- tBTA_DM_API_PIN_REPLY* p_msg =
- (tBTA_DM_API_PIN_REPLY*)osi_malloc(sizeof(tBTA_DM_API_PIN_REPLY));
-
- p_msg->hdr.event = BTA_DM_API_PIN_REPLY_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->accept = accept;
+ msg->bd_addr = bd_addr;
+ msg->accept = accept;
if (accept) {
- p_msg->pin_len = pin_len;
- memcpy(p_msg->p_pin, p_pin, pin_len);
+ msg->pin_len = pin_len;
+ memcpy(msg->p_pin, p_pin, pin_len);
}
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_pin_reply, base::Passed(&msg)));
}
/*******************************************************************************
@@ -388,11 +267,7 @@
*
******************************************************************************/
void BTA_DmLocalOob(void) {
- tBTA_DM_API_LOC_OOB* p_msg =
- (tBTA_DM_API_LOC_OOB*)osi_malloc(sizeof(tBTA_DM_API_LOC_OOB));
-
- p_msg->hdr.event = BTA_DM_API_LOC_OOB_EVT;
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(BTM_ReadLocalOobData));
}
/*******************************************************************************
@@ -406,14 +281,7 @@
*
******************************************************************************/
void BTA_DmConfirm(const RawAddress& bd_addr, bool accept) {
- tBTA_DM_API_CONFIRM* p_msg =
- (tBTA_DM_API_CONFIRM*)osi_malloc(sizeof(tBTA_DM_API_CONFIRM));
-
- p_msg->hdr.event = BTA_DM_API_CONFIRM_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->accept = accept;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_confirm, bd_addr, accept));
}
/*******************************************************************************
@@ -431,55 +299,38 @@
LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
bool is_trusted, uint8_t key_type, tBTA_IO_CAP io_cap,
uint8_t pin_length) {
- tBTA_DM_API_ADD_DEVICE* p_msg =
- (tBTA_DM_API_ADD_DEVICE*)osi_calloc(sizeof(tBTA_DM_API_ADD_DEVICE));
+ std::unique_ptr<tBTA_DM_API_ADD_DEVICE> msg =
+ std::make_unique<tBTA_DM_API_ADD_DEVICE>();
- p_msg->hdr.event = BTA_DM_API_ADD_DEVICE_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->tm = trusted_mask;
- p_msg->is_trusted = is_trusted;
- p_msg->io_cap = io_cap;
+ msg->bd_addr = bd_addr;
+ msg->tm = trusted_mask;
+ msg->is_trusted = is_trusted;
+ msg->io_cap = io_cap;
if (link_key) {
- p_msg->link_key_known = true;
- p_msg->key_type = key_type;
- memcpy(p_msg->link_key, link_key, LINK_KEY_LEN);
+ msg->link_key_known = true;
+ msg->key_type = key_type;
+ memcpy(msg->link_key, link_key, LINK_KEY_LEN);
}
/* Load device class if specified */
if (dev_class) {
- p_msg->dc_known = true;
- memcpy(p_msg->dc, dev_class, DEV_CLASS_LEN);
+ msg->dc_known = true;
+ memcpy(msg->dc, dev_class, DEV_CLASS_LEN);
}
- memset(p_msg->bd_name, 0, BD_NAME_LEN + 1);
- memset(p_msg->features, 0, sizeof(p_msg->features));
- p_msg->pin_length = pin_length;
+ memset(msg->bd_name, 0, BD_NAME_LEN + 1);
+ memset(msg->features, 0, sizeof(msg->features));
+ msg->pin_length = pin_length;
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_add_device, base::Passed(&msg)));
}
-/*******************************************************************************
- *
- * Function BTA_DmRemoveDevice
- *
- * Description This function removes a device fromthe security database
- * list of peer device. It manages unpairing even while
- * connected.
- *
- *
- * Returns void
- *
- ******************************************************************************/
+/** This function removes a device fromthe security database list of peer
+ * device. It manages unpairing even while connected */
tBTA_STATUS BTA_DmRemoveDevice(const RawAddress& bd_addr) {
- tBTA_DM_API_REMOVE_DEVICE* p_msg =
- (tBTA_DM_API_REMOVE_DEVICE*)osi_calloc(sizeof(tBTA_DM_API_REMOVE_DEVICE));
-
- p_msg->hdr.event = BTA_DM_API_REMOVE_DEVICE_EVT;
- p_msg->bd_addr = bd_addr;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_remove_device, bd_addr));
return BTA_SUCCESS;
}
@@ -500,11 +351,11 @@
tBTA_SERVICE_MASK* p_services) {
uint8_t xx, yy;
uint8_t num_uuid, max_num_uuid = 32;
- uint8_t uuid_list[32 * LEN_UUID_16];
+ uint8_t uuid_list[32 * Uuid::kNumBytes16];
uint16_t* p_uuid16 = (uint16_t*)uuid_list;
tBTA_SERVICE_MASK mask;
- BTM_GetEirUuidList(p_eir, eir_len, LEN_UUID_16, &num_uuid, uuid_list,
+ BTM_GetEirUuidList(p_eir, eir_len, Uuid::kNumBytes16, &num_uuid, uuid_list,
max_num_uuid);
for (xx = 0; xx < num_uuid; xx++) {
mask = 1;
@@ -576,29 +427,6 @@
/*******************************************************************************
*
- * Function bta_dmexecutecallback
- *
- * Description This function will request BTA to execute a call back in the
- * context of BTU task.
- * This API was named in lower case because it is only intended
- * for the internal customers(like BTIF).
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dmexecutecallback(tBTA_DM_EXEC_CBACK* p_callback, void* p_param) {
- tBTA_DM_API_EXECUTE_CBACK* p_msg =
- (tBTA_DM_API_EXECUTE_CBACK*)osi_malloc(sizeof(tBTA_DM_MSG));
-
- p_msg->hdr.event = BTA_DM_API_EXECUTE_CBACK_EVT;
- p_msg->p_param = p_param;
- p_msg->p_exec_cback = p_callback;
-
- bta_sys_sendmsg(p_msg);
-}
-
-/*******************************************************************************
- *
* Function BTA_DmAddBleKey
*
* Description Add/modify LE device information. This function will be
@@ -615,15 +443,8 @@
******************************************************************************/
void BTA_DmAddBleKey(const RawAddress& bd_addr, tBTA_LE_KEY_VALUE* p_le_key,
tBTA_LE_KEY_TYPE key_type) {
- tBTA_DM_API_ADD_BLEKEY* p_msg =
- (tBTA_DM_API_ADD_BLEKEY*)osi_calloc(sizeof(tBTA_DM_API_ADD_BLEKEY));
-
- p_msg->hdr.event = BTA_DM_API_ADD_BLEKEY_EVT;
- p_msg->key_type = key_type;
- p_msg->bd_addr = bd_addr;
- memcpy(&p_msg->blekey, p_le_key, sizeof(tBTA_LE_KEY_VALUE));
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_add_blekey, bd_addr, *p_le_key, key_type));
}
/*******************************************************************************
@@ -643,15 +464,8 @@
******************************************************************************/
void BTA_DmAddBleDevice(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
tBT_DEVICE_TYPE dev_type) {
- tBTA_DM_API_ADD_BLE_DEVICE* p_msg = (tBTA_DM_API_ADD_BLE_DEVICE*)osi_calloc(
- sizeof(tBTA_DM_API_ADD_BLE_DEVICE));
-
- p_msg->hdr.event = BTA_DM_API_ADD_BLEDEVICE_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->addr_type = addr_type;
- p_msg->dev_type = dev_type;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_add_ble_device, bd_addr,
+ addr_type, dev_type));
}
/*******************************************************************************
@@ -670,16 +484,8 @@
******************************************************************************/
void BTA_DmBlePasskeyReply(const RawAddress& bd_addr, bool accept,
uint32_t passkey) {
- tBTA_DM_API_PASSKEY_REPLY* p_msg =
- (tBTA_DM_API_PASSKEY_REPLY*)osi_calloc(sizeof(tBTA_DM_API_PASSKEY_REPLY));
-
- p_msg->hdr.event = BTA_DM_API_BLE_PASSKEY_REPLY_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->accept = accept;
-
- if (accept) p_msg->passkey = passkey;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_ble_passkey_reply, bd_addr,
+ accept, accept ? passkey : 0));
}
/*******************************************************************************
@@ -696,14 +502,8 @@
*
******************************************************************************/
void BTA_DmBleConfirmReply(const RawAddress& bd_addr, bool accept) {
- tBTA_DM_API_CONFIRM* p_msg =
- (tBTA_DM_API_CONFIRM*)osi_calloc(sizeof(tBTA_DM_API_CONFIRM));
-
- p_msg->hdr.event = BTA_DM_API_BLE_CONFIRM_REPLY_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->accept = accept;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_ble_confirm_reply, bd_addr, accept));
}
/*******************************************************************************
@@ -720,14 +520,7 @@
******************************************************************************/
void BTA_DmBleSecurityGrant(const RawAddress& bd_addr,
tBTA_DM_BLE_SEC_GRANT res) {
- tBTA_DM_API_BLE_SEC_GRANT* p_msg =
- (tBTA_DM_API_BLE_SEC_GRANT*)osi_calloc(sizeof(tBTA_DM_API_BLE_SEC_GRANT));
-
- p_msg->hdr.event = BTA_DM_API_BLE_SEC_GRANT_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->res = res;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(BTM_SecurityGrant, bd_addr, res));
}
/*******************************************************************************
@@ -753,17 +546,9 @@
uint16_t min_conn_int, uint16_t max_conn_int,
uint16_t slave_latency,
uint16_t supervision_tout) {
- tBTA_DM_API_BLE_CONN_PARAMS* p_msg = (tBTA_DM_API_BLE_CONN_PARAMS*)osi_calloc(
- sizeof(tBTA_DM_API_BLE_CONN_PARAMS));
-
- p_msg->hdr.event = BTA_DM_API_BLE_CONN_PARAM_EVT;
- p_msg->peer_bda = bd_addr;
- p_msg->conn_int_max = max_conn_int;
- p_msg->conn_int_min = min_conn_int;
- p_msg->slave_latency = slave_latency;
- p_msg->supervision_tout = supervision_tout;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_ble_set_conn_params, bd_addr, min_conn_int,
+ max_conn_int, slave_latency, supervision_tout));
}
/*******************************************************************************
@@ -780,25 +565,13 @@
*
******************************************************************************/
void BTA_DmSetBleConnScanParams(uint32_t scan_interval, uint32_t scan_window) {
- tBTA_DM_API_BLE_SCAN_PARAMS* p_msg = (tBTA_DM_API_BLE_SCAN_PARAMS*)osi_calloc(
- sizeof(tBTA_DM_API_BLE_SCAN_PARAMS));
-
- p_msg->hdr.event = BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT;
- p_msg->scan_int = scan_interval;
- p_msg->scan_window = scan_window;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_ble_set_conn_scan_params,
+ scan_interval, scan_window));
}
-/**
- * Set BLE connectable mode to auto connect
- */
+/** Set BLE connectable mode to auto connect */
void BTA_DmBleStartAutoConn() {
- tBTA_DM_API_SET_NAME* p_msg =
- (tBTA_DM_API_SET_NAME*)osi_calloc(sizeof(tBTA_DM_API_SET_NAME));
-
- p_msg->hdr.event = BTA_DM_API_BLE_SET_BG_CONN_TYPE;
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(BTM_BleStartAutoConn));
}
/*******************************************************************************
@@ -815,9 +588,10 @@
tBTA_DM_SEARCH_CBACK* p_cback,
bool sdp_search,
tBTA_TRANSPORT transport) {
- const size_t len = p_services ? (sizeof(tBTA_DM_API_DISCOVER) +
- sizeof(tBT_UUID) * p_services->num_uuid)
- : sizeof(tBTA_DM_API_DISCOVER);
+ const size_t len =
+ p_services
+ ? (sizeof(tBTA_DM_API_DISCOVER) + sizeof(Uuid) * p_services->num_uuid)
+ : sizeof(tBTA_DM_API_DISCOVER);
tBTA_DM_API_DISCOVER* p_msg = (tBTA_DM_API_DISCOVER*)osi_calloc(len);
p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
@@ -830,9 +604,9 @@
p_msg->services = p_services->srvc_mask;
p_msg->num_uuid = p_services->num_uuid;
if (p_services->num_uuid != 0) {
- p_msg->p_uuid = (tBT_UUID*)(p_msg + 1);
+ p_msg->p_uuid = (Uuid*)(p_msg + 1);
memcpy(p_msg->p_uuid, p_services->p_uuid,
- sizeof(tBT_UUID) * p_services->num_uuid);
+ sizeof(Uuid) * p_services->num_uuid);
}
}
@@ -906,9 +680,10 @@
******************************************************************************/
void BTA_DmSearchExt(tBTA_DM_INQ* p_dm_inq, tBTA_SERVICE_MASK_EXT* p_services,
tBTA_DM_SEARCH_CBACK* p_cback) {
- const size_t len = p_services ? (sizeof(tBTA_DM_API_SEARCH) +
- sizeof(tBT_UUID) * p_services->num_uuid)
- : sizeof(tBTA_DM_API_SEARCH);
+ const size_t len =
+ p_services
+ ? (sizeof(tBTA_DM_API_SEARCH) + sizeof(Uuid) * p_services->num_uuid)
+ : sizeof(tBTA_DM_API_SEARCH);
tBTA_DM_API_SEARCH* p_msg = (tBTA_DM_API_SEARCH*)osi_calloc(len);
p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
@@ -921,9 +696,9 @@
p_msg->num_uuid = p_services->num_uuid;
if (p_services->num_uuid != 0) {
- p_msg->p_uuid = (tBT_UUID*)(p_msg + 1);
+ p_msg->p_uuid = (Uuid*)(p_msg + 1);
memcpy(p_msg->p_uuid, p_services->p_uuid,
- sizeof(tBT_UUID) * p_services->num_uuid);
+ sizeof(Uuid) * p_services->num_uuid);
} else {
p_msg->p_uuid = NULL;
}
@@ -950,21 +725,13 @@
* Returns void
*
******************************************************************************/
-void BTA_DmBleUpdateConnectionParam(const RawAddress& bd_addr, uint16_t min_int,
- uint16_t max_int, uint16_t latency,
- uint16_t timeout) {
- tBTA_DM_API_UPDATE_CONN_PARAM* p_msg =
- (tBTA_DM_API_UPDATE_CONN_PARAM*)osi_calloc(
- sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
-
- p_msg->hdr.event = BTA_DM_API_UPDATE_CONN_PARAM_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->min_int = min_int;
- p_msg->max_int = max_int;
- p_msg->latency = latency;
- p_msg->timeout = timeout;
-
- bta_sys_sendmsg(p_msg);
+void BTA_DmBleUpdateConnectionParams(const RawAddress& bd_addr,
+ uint16_t min_int, uint16_t max_int,
+ uint16_t latency, uint16_t timeout,
+ uint16_t min_ce_len, uint16_t max_ce_len) {
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(bta_dm_ble_update_conn_params, bd_addr, min_int,
+ max_int, latency, timeout, min_ce_len, max_ce_len));
}
/*******************************************************************************
@@ -980,13 +747,8 @@
******************************************************************************/
void BTA_DmBleConfigLocalPrivacy(bool privacy_enable) {
#if (BLE_PRIVACY_SPT == TRUE)
- tBTA_DM_API_LOCAL_PRIVACY* p_msg = (tBTA_DM_API_LOCAL_PRIVACY*)osi_calloc(
- sizeof(tBTA_DM_API_ENABLE_PRIVACY));
-
- p_msg->hdr.event = BTA_DM_API_LOCAL_PRIVACY_EVT;
- p_msg->privacy_enable = privacy_enable;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_ble_config_local_privacy, privacy_enable));
#else
UNUSED(privacy_enable);
#endif
@@ -1004,73 +766,15 @@
*
******************************************************************************/
void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK* p_cmpl_cback) {
- const size_t len = sizeof(tBTA_DM_API_ENERGY_INFO) + sizeof(tBLE_BD_ADDR);
- tBTA_DM_API_ENERGY_INFO* p_msg = (tBTA_DM_API_ENERGY_INFO*)osi_calloc(len);
-
- APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_DM_API_BLE_ENERGY_INFO_EVT;
- p_msg->p_energy_info_cback = p_cmpl_cback;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_ble_get_energy_info, p_cmpl_cback));
}
-/*******************************************************************************
- *
- * Function BTA_DmBleUpdateConnectionParams
- *
- * Description Update connection parameters, can only be used when
- * connection is up.
- *
- * Parameters: bd_addr - BD address of the peer
- * min_int - minimum connection interval,
- * [0x0004 ~ 0x4000]
- * max_int - maximum connection interval,
- * [0x0004 ~ 0x4000]
- * latency - slave latency [0 ~ 500]
- * timeout - supervision timeout [0x000a ~ 0xc80]
- *
- * Returns void
- *
- ******************************************************************************/
-void BTA_DmBleUpdateConnectionParams(const RawAddress& bd_addr,
- uint16_t min_int, uint16_t max_int,
- uint16_t latency, uint16_t timeout) {
- tBTA_DM_API_UPDATE_CONN_PARAM* p_msg =
- (tBTA_DM_API_UPDATE_CONN_PARAM*)osi_calloc(
- sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
-
- p_msg->hdr.event = BTA_DM_API_UPDATE_CONN_PARAM_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->min_int = min_int;
- p_msg->max_int = max_int;
- p_msg->latency = latency;
- p_msg->timeout = timeout;
-
- bta_sys_sendmsg(p_msg);
-}
-
-/*******************************************************************************
- *
- * Function BTA_DmBleSetDataLength
- *
- * Description This function is to set maximum LE data packet size
- *
- * Returns void
- *
- *
- ******************************************************************************/
+/** This function is to set maximum LE data packet size */
void BTA_DmBleSetDataLength(const RawAddress& remote_device,
uint16_t tx_data_length) {
- tBTA_DM_API_BLE_SET_DATA_LENGTH* p_msg =
- (tBTA_DM_API_BLE_SET_DATA_LENGTH*)osi_malloc(
- sizeof(tBTA_DM_API_BLE_SET_DATA_LENGTH));
-
- p_msg->remote_bda = remote_device;
- p_msg->hdr.event = BTA_DM_API_SET_DATA_LENGTH_EVT;
- p_msg->tx_data_length = tx_data_length;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_ble_set_data_length,
+ remote_device, tx_data_length));
}
/*******************************************************************************
@@ -1098,18 +802,9 @@
void BTA_DmSetEncryption(const RawAddress& bd_addr, tBTA_TRANSPORT transport,
tBTA_DM_ENCRYPT_CBACK* p_callback,
tBTA_DM_BLE_SEC_ACT sec_act) {
- tBTA_DM_API_SET_ENCRYPTION* p_msg = (tBTA_DM_API_SET_ENCRYPTION*)osi_calloc(
- sizeof(tBTA_DM_API_SET_ENCRYPTION));
-
APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_DM_API_SET_ENCRYPTION_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->transport = transport;
- p_msg->p_callback = p_callback;
- p_msg->sec_act = sec_act;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_set_encryption, bd_addr,
+ transport, p_callback, sec_act));
}
/*******************************************************************************
@@ -1127,17 +822,8 @@
******************************************************************************/
void BTA_DmCloseACL(const RawAddress& bd_addr, bool remove_dev,
tBTA_TRANSPORT transport) {
- tBTA_DM_API_REMOVE_ACL* p_msg =
- (tBTA_DM_API_REMOVE_ACL*)osi_calloc(sizeof(tBTA_DM_API_REMOVE_ACL));
-
- APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_DM_API_REMOVE_ACL_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->remove_dev = remove_dev;
- p_msg->transport = transport;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(bta_dm_close_acl, bd_addr, remove_dev, transport));
}
/*******************************************************************************
@@ -1157,17 +843,9 @@
******************************************************************************/
extern void BTA_DmBleObserve(bool start, uint8_t duration,
tBTA_DM_SEARCH_CBACK* p_results_cb) {
- tBTA_DM_API_BLE_OBSERVE* p_msg =
- (tBTA_DM_API_BLE_OBSERVE*)osi_calloc(sizeof(tBTA_DM_API_BLE_OBSERVE));
-
APPL_TRACE_API("%s:start = %d ", __func__, start);
-
- p_msg->hdr.event = BTA_DM_API_BLE_OBSERVE_EVT;
- p_msg->start = start;
- p_msg->duration = duration;
- p_msg->p_cback = p_results_cb;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(bta_dm_ble_observe, start, duration, p_results_cb));
}
/*******************************************************************************
diff --git a/bta/dm/bta_dm_cfg.cc b/bta/dm/bta_dm_cfg.cc
index 4202975..91053a1 100644
--- a/bta/dm/bta_dm_cfg.cc
+++ b/bta/dm/bta_dm_cfg.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -111,9 +111,9 @@
{BTA_ID_HH, BTA_ALL_APP_ID, BTA_HH_ROLE},
{BTA_ID_AV, BTA_ALL_APP_ID, BTA_AV_ROLE}};
-tBTA_DM_CFG* p_bta_dm_cfg = (tBTA_DM_CFG*)&bta_dm_cfg;
+const tBTA_DM_CFG* p_bta_dm_cfg = &bta_dm_cfg;
-tBTA_DM_RM* p_bta_dm_rm_cfg = (tBTA_DM_RM*)&bta_dm_rm_cfg;
+const tBTA_DM_RM* p_bta_dm_rm_cfg = &bta_dm_rm_cfg[0];
#define BTA_DM_NUM_PM_ENTRY \
23 /* number of entries in bta_dm_pm_cfg except the first */
@@ -236,7 +236,7 @@
/* AV : 4 */
{(BTA_DM_PM_SNIFF), /* allow sniff */
#if (BTM_SSR_INCLUDED == TRUE)
- (BTA_DM_PM_SSR2), /* the SSR entry */
+ (BTA_DM_PM_SSR0), /* the SSR entry */
#endif
{
{{BTA_DM_PM_SNIFF_A2DP_IDX, 7000},
@@ -288,7 +288,7 @@
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
- {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000},
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_FTC_IDLE_TO_SNIFF_DELAY_MS},
{BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0},
@@ -559,12 +559,12 @@
{360, 160, 1600} /* BTA_DM_PM_SSR3 - HD */
};
-tBTA_DM_SSR_SPEC* p_bta_dm_ssr_spec = (tBTA_DM_SSR_SPEC*)&bta_dm_ssr_spec;
+tBTA_DM_SSR_SPEC* p_bta_dm_ssr_spec = &bta_dm_ssr_spec[0];
#endif
-tBTA_DM_PM_CFG* p_bta_dm_pm_cfg = (tBTA_DM_PM_CFG*)&bta_dm_pm_cfg;
-tBTA_DM_PM_SPEC* p_bta_dm_pm_spec = (tBTA_DM_PM_SPEC*)&bta_dm_pm_spec;
-tBTM_PM_PWR_MD* p_bta_dm_pm_md = (tBTM_PM_PWR_MD*)&bta_dm_pm_md;
+const tBTA_DM_PM_CFG* p_bta_dm_pm_cfg = &bta_dm_pm_cfg[0];
+const tBTA_DM_PM_SPEC* p_bta_dm_pm_spec = &bta_dm_pm_spec[0];
+const tBTM_PM_PWR_MD* p_bta_dm_pm_md = &bta_dm_pm_md[0];
/* The performance impact of EIR packet size
*
@@ -620,4 +620,4 @@
0, /* length of additional data in bytes */
NULL /* additional data */
};
-tBTA_DM_EIR_CONF* p_bta_dm_eir_cfg = (tBTA_DM_EIR_CONF*)&bta_dm_eir_cfg;
+const tBTA_DM_EIR_CONF* p_bta_dm_eir_cfg = &bta_dm_eir_cfg;
diff --git a/bta/dm/bta_dm_ci.cc b/bta/dm/bta_dm_ci.cc
index 7ff9da2..3d40480 100644
--- a/bta/dm/bta_dm_ci.cc
+++ b/bta/dm/bta_dm_ci.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,14 +21,15 @@
* This is the API implementation file for the BTA device manager.
*
******************************************************************************/
-#include <string.h>
-
#include "bt_common.h"
#include "bta_api.h"
#include "bta_dm_ci.h"
#include "bta_dm_int.h"
#include "bta_sys.h"
+#include <base/bind.h>
+#include <memory>
+
/*******************************************************************************
*
* Function bta_dm_ci_io_req
@@ -44,16 +45,8 @@
tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req)
{
- tBTA_DM_CI_IO_REQ* p_msg =
- (tBTA_DM_CI_IO_REQ*)osi_malloc(sizeof(tBTA_DM_CI_IO_REQ));
-
- p_msg->hdr.event = BTA_DM_CI_IO_REQ_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->io_cap = io_cap;
- p_msg->oob_data = oob_data;
- p_msg->auth_req = auth_req;
-
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_ci_io_req_act, bd_addr, io_cap,
+ oob_data, auth_req));
}
/*******************************************************************************
@@ -69,40 +62,15 @@
******************************************************************************/
void bta_dm_ci_rmt_oob(bool accept, const RawAddress& bd_addr, BT_OCTET16 c,
BT_OCTET16 r) {
- tBTA_DM_CI_RMT_OOB* p_msg =
- (tBTA_DM_CI_RMT_OOB*)osi_malloc(sizeof(tBTA_DM_CI_RMT_OOB));
+ std::unique_ptr<tBTA_DM_CI_RMT_OOB> msg =
+ std::make_unique<tBTA_DM_CI_RMT_OOB>();
- p_msg->hdr.event = BTA_DM_CI_RMT_OOB_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->accept = accept;
- memcpy(p_msg->c, c, BT_OCTET16_LEN);
- memcpy(p_msg->r, r, BT_OCTET16_LEN);
+ msg->bd_addr = bd_addr;
+ msg->accept = accept;
+ memcpy(msg->c, c, BT_OCTET16_LEN);
+ memcpy(msg->r, r, BT_OCTET16_LEN);
- bta_sys_sendmsg(p_msg);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(bta_dm_ci_rmt_oob_act, base::Passed(&msg)));
}
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
-/*******************************************************************************
- *
- * Function bta_dm_sco_ci_data_ready
- *
- * Description This function sends an event to indicating that the phone
- * has SCO data ready.
- *
- * Parameters event: is obtained from bta_dm_sco_co_open() function, which
- * is the BTA event we want to send back to BTA module
- * when there is encoded data ready.
- * sco_handle: is the BTA sco handle which indicate a specific
- * SCO connection.
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_sco_ci_data_ready(uint16_t event, uint16_t sco_handle) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = event;
- p_buf->layer_specific = sco_handle;
-
- bta_sys_sendmsg(p_buf);
-}
-#endif
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index 12a4074..6aafd7d 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,60 +45,6 @@
#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id))
-/* DM events */
-enum {
- /* device manager local device API events */
- BTA_DM_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_DM),
- BTA_DM_API_DISABLE_EVT,
- BTA_DM_API_SET_NAME_EVT,
- BTA_DM_API_SET_VISIBILITY_EVT,
-
- BTA_DM_ACL_CHANGE_EVT,
- BTA_DM_API_ADD_DEVICE_EVT,
- BTA_DM_API_REMOVE_ACL_EVT,
-
- /* security API events */
- BTA_DM_API_BOND_EVT,
- BTA_DM_API_BOND_CANCEL_EVT,
- BTA_DM_API_PIN_REPLY_EVT,
-
- /* power manger events */
- BTA_DM_PM_BTM_STATUS_EVT,
- BTA_DM_PM_TIMER_EVT,
-
- /* simple pairing events */
- BTA_DM_API_CONFIRM_EVT,
-
- BTA_DM_API_SET_ENCRYPTION_EVT,
-
- BTA_DM_API_LOC_OOB_EVT,
- BTA_DM_CI_IO_REQ_EVT,
- BTA_DM_CI_RMT_OOB_EVT,
-
- BTA_DM_API_ADD_BLEKEY_EVT,
- BTA_DM_API_ADD_BLEDEVICE_EVT,
- BTA_DM_API_BLE_PASSKEY_REPLY_EVT,
- BTA_DM_API_BLE_CONFIRM_REPLY_EVT,
- BTA_DM_API_BLE_SEC_GRANT_EVT,
- BTA_DM_API_BLE_SET_BG_CONN_TYPE,
- BTA_DM_API_BLE_CONN_PARAM_EVT,
- BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT,
- BTA_DM_API_BLE_OBSERVE_EVT,
- BTA_DM_API_UPDATE_CONN_PARAM_EVT,
-#if (BLE_PRIVACY_SPT == TRUE)
- BTA_DM_API_LOCAL_PRIVACY_EVT,
-#endif
- BTA_DM_API_SET_DATA_LENGTH_EVT,
- BTA_DM_API_BLE_ENERGY_INFO_EVT,
-
- BTA_DM_API_ENABLE_TEST_MODE_EVT,
- BTA_DM_API_DISABLE_TEST_MODE_EVT,
- BTA_DM_API_EXECUTE_CBACK_EVT,
- BTA_DM_API_REMOVE_ALL_ACL_EVT,
- BTA_DM_API_REMOVE_DEVICE_EVT,
- BTA_DM_MAX_EVT
-};
-
/* DM search events */
enum {
/* DM search API events */
@@ -115,27 +61,6 @@
};
-/* data type for BTA_DM_API_ENABLE_EVT */
-typedef struct {
- BT_HDR hdr;
- tBTA_DM_SEC_CBACK* p_sec_cback;
-} tBTA_DM_API_ENABLE;
-
-/* data type for BTA_DM_API_SET_NAME_EVT */
-typedef struct {
- BT_HDR hdr;
- BD_NAME name; /* max 248 bytes name, plus must be Null terminated */
-} tBTA_DM_API_SET_NAME;
-
-/* data type for BTA_DM_API_SET_VISIBILITY_EVT */
-typedef struct {
- BT_HDR hdr;
- tBTA_DM_DISC disc_mode;
- tBTA_DM_CONN conn_mode;
- uint8_t pair_mode;
- uint8_t conn_paired_only;
-} tBTA_DM_API_SET_VISIBILITY;
-
enum {
BTA_DM_RS_NONE, /* straight API call */
BTA_DM_RS_OK, /* the role switch result - successful */
@@ -151,7 +76,7 @@
tBTA_DM_SEARCH_CBACK* p_cback;
tBTA_DM_RS_RES rs_res;
uint8_t num_uuid;
- tBT_UUID* p_uuid;
+ bluetooth::Uuid* p_uuid;
} tBTA_DM_API_SEARCH;
/* data type for BTA_DM_API_DISCOVER_EVT */
@@ -163,8 +88,8 @@
bool sdp_search;
tBTA_TRANSPORT transport;
uint8_t num_uuid;
- tBT_UUID* p_uuid;
- tSDP_UUID uuid;
+ bluetooth::Uuid* p_uuid;
+ bluetooth::Uuid uuid;
} tBTA_DM_API_DISCOVER;
/* data type for BTA_DM_API_DI_DISC_EVT */
@@ -176,40 +101,13 @@
tBTA_DM_SEARCH_CBACK* p_cback;
} tBTA_DM_API_DI_DISC;
-/* data type for BTA_DM_API_BOND_EVT */
typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- tBTA_TRANSPORT transport;
-} tBTA_DM_API_BOND;
-
-/* data type for BTA_DM_API_BOND_CANCEL_EVT */
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- tBTA_TRANSPORT transport;
-} tBTA_DM_API_BOND_CANCEL;
-
-/* data type for BTA_DM_API_PIN_REPLY_EVT */
-typedef struct {
- BT_HDR hdr;
RawAddress bd_addr;
bool accept;
uint8_t pin_len;
uint8_t p_pin[PIN_CODE_LEN];
} tBTA_DM_API_PIN_REPLY;
-/* data type for BTA_DM_API_LOC_OOB_EVT */
-typedef struct { BT_HDR hdr; } tBTA_DM_API_LOC_OOB;
-
-/* data type for BTA_DM_API_CONFIRM_EVT */
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- bool accept;
-} tBTA_DM_API_CONFIRM;
-
-/* data type for BTA_DM_CI_IO_REQ_EVT */
typedef struct {
BT_HDR hdr;
RawAddress bd_addr;
@@ -218,9 +116,7 @@
tBTA_AUTH_REQ auth_req;
} tBTA_DM_CI_IO_REQ;
-/* data type for BTA_DM_CI_RMT_OOB_EVT */
typedef struct {
- BT_HDR hdr;
RawAddress bd_addr;
BT_OCTET16 c;
BT_OCTET16 r;
@@ -251,40 +147,7 @@
uint16_t sdp_result;
} tBTA_DM_SDP_RESULT;
-/* data type for BTA_DM_ACL_CHANGE_EVT */
typedef struct {
- BT_HDR hdr;
- tBTM_BL_EVENT event;
- uint8_t busy_level;
- uint8_t busy_level_flags;
- bool is_new;
- uint8_t new_role;
- RawAddress bd_addr;
- uint8_t hci_status;
- uint16_t handle;
- tBT_TRANSPORT transport;
-} tBTA_DM_ACL_CHANGE;
-
-/* data type for BTA_DM_PM_BTM_STATUS_EVT */
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- tBTM_PM_STATUS status;
- uint16_t value;
- uint8_t hci_status;
-
-} tBTA_DM_PM_BTM_STATUS;
-
-/* data type for BTA_DM_PM_TIMER_EVT */
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- tBTA_DM_PM_ACTION pm_request;
-} tBTA_DM_PM_TIMER;
-
-/* data type for BTA_DM_API_ADD_DEVICE_EVT */
-typedef struct {
- BT_HDR hdr;
RawAddress bd_addr;
DEV_CLASS dc;
LINK_KEY link_key;
@@ -300,176 +163,20 @@
uint8_t pin_length;
} tBTA_DM_API_ADD_DEVICE;
-/* data type for BTA_DM_API_REMOVE_ACL_EVT */
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
-} tBTA_DM_API_REMOVE_DEVICE;
-
-/* data type for BTA_DM_API_EXECUTE_CBACK_EVT */
-typedef struct {
- BT_HDR hdr;
- void* p_param;
- tBTA_DM_EXEC_CBACK* p_exec_cback;
-} tBTA_DM_API_EXECUTE_CBACK;
-
-/* data type for tBTA_DM_API_SET_ENCRYPTION */
-typedef struct {
- BT_HDR hdr;
- tBTA_TRANSPORT transport;
- tBTA_DM_ENCRYPT_CBACK* p_callback;
- tBTA_DM_BLE_SEC_ACT sec_act;
- RawAddress bd_addr;
-} tBTA_DM_API_SET_ENCRYPTION;
-
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- tBTA_LE_KEY_VALUE blekey;
- tBTA_LE_KEY_TYPE key_type;
-
-} tBTA_DM_API_ADD_BLEKEY;
-
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- tBT_DEVICE_TYPE dev_type;
- tBLE_ADDR_TYPE addr_type;
-
-} tBTA_DM_API_ADD_BLE_DEVICE;
-
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- bool accept;
- uint32_t passkey;
-} tBTA_DM_API_PASSKEY_REPLY;
-
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- tBTA_DM_BLE_SEC_GRANT res;
-} tBTA_DM_API_BLE_SEC_GRANT;
-
-/* set prefered BLE connection parameters for a device */
-typedef struct {
- BT_HDR hdr;
- RawAddress peer_bda;
- uint16_t conn_int_min;
- uint16_t conn_int_max;
- uint16_t supervision_tout;
- uint16_t slave_latency;
-
-} tBTA_DM_API_BLE_CONN_PARAMS;
-
-typedef struct {
- BT_HDR hdr;
- RawAddress peer_bda;
- bool privacy_enable;
-
-} tBTA_DM_API_ENABLE_PRIVACY;
-
-typedef struct {
- BT_HDR hdr;
- bool privacy_enable;
-} tBTA_DM_API_LOCAL_PRIVACY;
-
-/* set scan parameter for BLE connections */
-typedef struct {
- BT_HDR hdr;
- tBTA_GATTC_IF client_if;
- uint32_t scan_int;
- uint32_t scan_window;
- tBLE_SCAN_MODE scan_mode;
- tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback;
-} tBTA_DM_API_BLE_SCAN_PARAMS;
-
-/* set scan parameter for BLE connections */
-typedef struct {
- BT_HDR hdr;
- uint16_t scan_int;
- uint16_t scan_window;
-} tBTA_DM_API_BLE_CONN_SCAN_PARAMS;
-
-/* Data type for start/stop observe */
-typedef struct {
- BT_HDR hdr;
- bool start;
- uint16_t duration;
- tBTA_DM_SEARCH_CBACK* p_cback;
-} tBTA_DM_API_BLE_OBSERVE;
-
-typedef struct {
- BT_HDR hdr;
- RawAddress remote_bda;
- uint16_t tx_data_length;
-} tBTA_DM_API_BLE_SET_DATA_LENGTH;
-
-/* set adv parameter for BLE advertising */
-
typedef struct {
BT_HDR hdr;
bool enable;
-
} tBTA_DM_API_BLE_FEATURE;
-typedef struct {
- BT_HDR hdr;
- tBTA_BLE_ENERGY_INFO_CBACK* p_energy_info_cback;
-} tBTA_DM_API_ENERGY_INFO;
-
-/* data type for BTA_DM_API_REMOVE_ACL_EVT */
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- bool remove_dev;
- tBTA_TRANSPORT transport;
-} tBTA_DM_API_REMOVE_ACL;
-
-/* data type for BTA_DM_API_REMOVE_ALL_ACL_EVT */
-typedef struct {
- BT_HDR hdr;
- tBTA_DM_LINK_TYPE link_type;
-
-} tBTA_DM_API_REMOVE_ALL_ACL;
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- uint16_t min_int;
- uint16_t max_int;
- uint16_t latency;
- uint16_t timeout;
-} tBTA_DM_API_UPDATE_CONN_PARAM;
-
/* union of all data types */
typedef union {
/* GKI event buffer header */
BT_HDR hdr;
- tBTA_DM_API_ENABLE enable;
-
- tBTA_DM_API_SET_NAME set_name;
-
- tBTA_DM_API_SET_VISIBILITY set_visibility;
-
- tBTA_DM_API_ADD_DEVICE add_dev;
-
- tBTA_DM_API_REMOVE_DEVICE remove_dev;
tBTA_DM_API_SEARCH search;
tBTA_DM_API_DISCOVER discover;
- tBTA_DM_API_BOND bond;
-
- tBTA_DM_API_BOND_CANCEL bond_cancel;
-
- tBTA_DM_API_PIN_REPLY pin_reply;
-
- tBTA_DM_API_LOC_OOB loc_oob;
- tBTA_DM_API_CONFIRM confirm;
- tBTA_DM_CI_IO_REQ ci_io_req;
- tBTA_DM_CI_RMT_OOB ci_rmt_oob;
-
tBTA_DM_REM_NAME rem_name;
tBTA_DM_DISC_RESULT disc_result;
@@ -478,35 +185,8 @@
tBTA_DM_SDP_RESULT sdp_event;
- tBTA_DM_ACL_CHANGE acl_change;
-
- tBTA_DM_PM_BTM_STATUS pm_status;
-
- tBTA_DM_PM_TIMER pm_timer;
-
tBTA_DM_API_DI_DISC di_disc;
- tBTA_DM_API_EXECUTE_CBACK exec_cback;
-
- tBTA_DM_API_SET_ENCRYPTION set_encryption;
-
- tBTA_DM_API_ADD_BLEKEY add_ble_key;
- tBTA_DM_API_ADD_BLE_DEVICE add_ble_device;
- tBTA_DM_API_PASSKEY_REPLY ble_passkey_reply;
- tBTA_DM_API_BLE_SEC_GRANT ble_sec_grant;
- tBTA_DM_API_BLE_CONN_PARAMS ble_set_conn_params;
- tBTA_DM_API_BLE_CONN_SCAN_PARAMS ble_set_conn_scan_params;
- tBTA_DM_API_BLE_OBSERVE ble_observe;
- tBTA_DM_API_ENABLE_PRIVACY ble_remote_privacy;
- tBTA_DM_API_LOCAL_PRIVACY ble_local_privacy;
- tBTA_DM_API_UPDATE_CONN_PARAM ble_update_conn_params;
- tBTA_DM_API_BLE_SET_DATA_LENGTH ble_set_data_length;
-
- tBTA_DM_API_ENERGY_INFO ble_energy_info;
-
- tBTA_DM_API_REMOVE_ACL remove_acl;
- tBTA_DM_API_REMOVE_ALL_ACL remove_all_acl;
-
} tBTA_DM_MSG;
#define BTA_DM_NUM_PEER_DEVICE 7
@@ -634,6 +314,10 @@
RawAddress pin_bd_addr;
DEV_CLASS pin_dev_class;
tBTA_DM_SEC_EVT pin_evt;
+ tBTA_IO_CAP loc_io_caps; /* IO Capabilities of local device */
+ tBTA_IO_CAP rmt_io_caps; /* IO Capabilities of remote device */
+ tBTA_AUTH_REQ loc_auth_req; /* Authentication required for local device */
+ tBTA_AUTH_REQ rmt_auth_req;
uint32_t num_val; /* the numeric value for comparison. If just_works, do not
show this number to UI */
bool just_works; /* true, if "Just Works" association model */
@@ -641,7 +325,7 @@
/* store UUID list for EIR */
uint32_t eir_uuid[BTM_EIR_SERVICE_ARRAY_SIZE];
#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
- tBT_UUID custom_uuid[BTA_EIR_SERVER_NUM_CUSTOM_UUID];
+ bluetooth::Uuid custom_uuid[BTA_EIR_SERVER_NUM_CUSTOM_UUID];
#endif
#endif
@@ -669,15 +353,15 @@
cancel stored here */
bool wait_disc;
bool sdp_results;
- tSDP_UUID uuid;
+ bluetooth::Uuid uuid;
uint8_t peer_scn;
bool sdp_search;
bool cancel_pending; /* inquiry cancel is pending */
tBTA_TRANSPORT transport;
tBTA_DM_SEARCH_CBACK* p_scan_cback;
- tBTA_GATTC_IF client_if;
+ tGATT_IF client_if;
uint8_t num_uuid;
- tBT_UUID* p_srvc_uuid;
+ bluetooth::Uuid* p_srvc_uuid;
uint8_t uuid_to_search;
bool gatt_disc_active;
uint16_t conn_id;
@@ -727,8 +411,8 @@
} tBTA_DM_RM;
-extern tBTA_DM_CFG* p_bta_dm_cfg;
-extern tBTA_DM_RM* p_bta_dm_rm_cfg;
+extern const tBTA_DM_CFG* p_bta_dm_cfg;
+extern const tBTA_DM_RM* p_bta_dm_rm_cfg;
typedef struct {
uint8_t id;
@@ -766,16 +450,16 @@
extern const uint16_t bta_service_id_to_uuid_lkup_tbl[];
-extern tBTA_DM_PM_CFG* p_bta_dm_pm_cfg;
-extern tBTA_DM_PM_SPEC* p_bta_dm_pm_spec;
-extern tBTM_PM_PWR_MD* p_bta_dm_pm_md;
+extern const tBTA_DM_PM_CFG* p_bta_dm_pm_cfg;
+extern const tBTA_DM_PM_SPEC* p_bta_dm_pm_spec;
+extern const tBTM_PM_PWR_MD* p_bta_dm_pm_md;
#if (BTM_SSR_INCLUDED == TRUE)
extern tBTA_DM_SSR_SPEC* p_bta_dm_ssr_spec;
#endif
/* update dynamic BRCM Aware EIR data */
extern const tBTA_DM_EIR_CONF bta_dm_eir_cfg;
-extern tBTA_DM_EIR_CONF* p_bta_dm_eir_cfg;
+extern const tBTA_DM_EIR_CONF* p_bta_dm_eir_cfg;
/* DM control block */
extern tBTA_DM_CB bta_dm_cb;
@@ -786,56 +470,61 @@
/* DI control block */
extern tBTA_DM_DI_CB bta_dm_di_cb;
-extern bool bta_dm_sm_execute(BT_HDR* p_msg);
-extern void bta_dm_sm_disable(void);
extern bool bta_dm_search_sm_execute(BT_HDR* p_msg);
extern void bta_dm_search_sm_disable(void);
-extern void bta_dm_enable(tBTA_DM_MSG* p_data);
-extern void bta_dm_disable(tBTA_DM_MSG* p_data);
+extern void bta_dm_enable(tBTA_DM_SEC_CBACK*);
+extern void bta_dm_disable();
extern void bta_dm_init_cb(void);
-extern void bta_dm_set_dev_name(tBTA_DM_MSG* p_data);
-extern void bta_dm_set_visibility(tBTA_DM_MSG* p_data);
-
+extern void bta_dm_set_dev_name(const std::vector<uint8_t>&);
+extern void bta_dm_set_visibility(tBTA_DM_DISC, tBTA_DM_CONN, uint8_t, uint8_t);
extern void bta_dm_set_scan_config(tBTA_DM_MSG* p_data);
extern void bta_dm_vendor_spec_command(tBTA_DM_MSG* p_data);
-extern void bta_dm_bond(tBTA_DM_MSG* p_data);
-extern void bta_dm_bond_cancel(tBTA_DM_MSG* p_data);
-extern void bta_dm_pin_reply(tBTA_DM_MSG* p_data);
-extern void bta_dm_acl_change(tBTA_DM_MSG* p_data);
-extern void bta_dm_add_device(tBTA_DM_MSG* p_data);
-extern void bta_dm_remove_device(tBTA_DM_MSG* p_data);
-extern void bta_dm_close_acl(tBTA_DM_MSG* p_data);
+extern void bta_dm_bond(const RawAddress&, tBTA_TRANSPORT);
+extern void bta_dm_bond_cancel(const RawAddress&);
+extern void bta_dm_pin_reply(std::unique_ptr<tBTA_DM_API_PIN_REPLY> msg);
+extern void bta_dm_add_device(std::unique_ptr<tBTA_DM_API_ADD_DEVICE> msg);
+extern void bta_dm_remove_device(const RawAddress& bd_addr);
+extern void bta_dm_close_acl(const RawAddress&, bool, tBTA_TRANSPORT);
-extern void bta_dm_pm_btm_status(tBTA_DM_MSG* p_data);
-extern void bta_dm_pm_timer(tBTA_DM_MSG* p_data);
+extern void bta_dm_pm_btm_status(const RawAddress&, tBTM_PM_STATUS, uint16_t,
+ uint8_t);
+extern void bta_dm_pm_timer(const RawAddress&, tBTA_DM_PM_ACTION);
extern void bta_dm_add_ampkey(tBTA_DM_MSG* p_data);
-extern void bta_dm_add_blekey(tBTA_DM_MSG* p_data);
-extern void bta_dm_add_ble_device(tBTA_DM_MSG* p_data);
-extern void bta_dm_ble_passkey_reply(tBTA_DM_MSG* p_data);
-extern void bta_dm_ble_confirm_reply(tBTA_DM_MSG* p_data);
-extern void bta_dm_security_grant(tBTA_DM_MSG* p_data);
-extern void bta_dm_ble_set_bg_conn_type(tBTA_DM_MSG* p_data);
-extern void bta_dm_ble_set_conn_params(tBTA_DM_MSG* p_data);
-extern void bta_dm_ble_set_conn_scan_params(tBTA_DM_MSG* p_data);
+extern void bta_dm_add_blekey(const RawAddress& bd_addr,
+ tBTA_LE_KEY_VALUE blekey,
+ tBTA_LE_KEY_TYPE key_type);
+extern void bta_dm_add_ble_device(const RawAddress& bd_addr,
+ tBLE_ADDR_TYPE addr_type,
+ tBT_DEVICE_TYPE dev_type);
+extern void bta_dm_ble_passkey_reply(const RawAddress& bd_addr, bool accept,
+ uint32_t passkey);
+extern void bta_dm_ble_confirm_reply(const RawAddress&, bool);
+extern void bta_dm_ble_set_conn_params(const RawAddress&, uint16_t, uint16_t,
+ uint16_t, uint16_t);
+extern void bta_dm_ble_set_conn_scan_params(uint32_t, uint32_t);
extern void bta_dm_close_gatt_conn(tBTA_DM_MSG* p_data);
-extern void bta_dm_ble_observe(tBTA_DM_MSG* p_data);
-extern void bta_dm_ble_update_conn_params(tBTA_DM_MSG* p_data);
-extern void bta_dm_ble_config_local_privacy(tBTA_DM_MSG* p_data);
+extern void bta_dm_ble_observe(bool, uint8_t, tBTA_DM_SEARCH_CBACK*);
+extern void bta_dm_ble_update_conn_params(const RawAddress&, uint16_t, uint16_t,
+ uint16_t, uint16_t, uint16_t,
+ uint16_t);
+extern void bta_dm_ble_config_local_privacy(bool);
extern void bta_dm_ble_set_adv_params(uint16_t adv_int_min,
uint16_t adv_int_max,
tBLE_BD_ADDR* p_dir_bda);
-extern void bta_dm_ble_set_data_length(tBTA_DM_MSG* p_data);
+extern void bta_dm_ble_set_data_length(const RawAddress&, uint16_t);
-extern void bta_dm_ble_get_energy_info(tBTA_DM_MSG* p_data);
+extern void bta_dm_ble_get_energy_info(tBTA_BLE_ENERGY_INFO_CBACK*);
-extern void bta_dm_set_encryption(tBTA_DM_MSG* p_data);
-extern void bta_dm_confirm(tBTA_DM_MSG* p_data);
-extern void bta_dm_loc_oob(tBTA_DM_MSG* p_data);
-extern void bta_dm_ci_io_req_act(tBTA_DM_MSG* p_data);
-extern void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG* p_data);
+extern void bta_dm_set_encryption(const RawAddress&, tBTA_TRANSPORT,
+ tBTA_DM_ENCRYPT_CBACK*, tBTA_DM_BLE_SEC_ACT);
+extern void bta_dm_confirm(const RawAddress&, bool);
+extern void bta_dm_ci_io_req_act(const RawAddress& bd_addr, tBTA_IO_CAP io_cap,
+ tBTA_OOB_DATA oob_data,
+ tBTA_AUTH_REQ auth_req);
+extern void bta_dm_ci_rmt_oob_act(std::unique_ptr<tBTA_DM_CI_RMT_OOB> msg);
extern void bta_dm_init_pm(void);
extern void bta_dm_disable_pm(void);
@@ -865,9 +554,5 @@
void bta_dm_eir_update_uuid(uint16_t uuid16, bool adding);
-extern void bta_dm_enable_test_mode(tBTA_DM_MSG* p_data);
-extern void bta_dm_disable_test_mode(tBTA_DM_MSG* p_data);
-extern void bta_dm_execute_callback(tBTA_DM_MSG* p_data);
-
-extern void bta_dm_remove_all_acl(tBTA_DM_MSG* p_data);
+extern void bta_dm_remove_all_acl(const tBTA_DM_LINK_TYPE);
#endif /* BTA_DM_INT_H */
diff --git a/bta/dm/bta_dm_main.cc b/bta/dm/bta_dm_main.cc
index d91eaba..f9bffe6 100644
--- a/bta/dm/bta_dm_main.cc
+++ b/bta/dm/bta_dm_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,60 +39,6 @@
/* type for action functions */
typedef void (*tBTA_DM_ACTION)(tBTA_DM_MSG* p_data);
-/* action function list */
-const tBTA_DM_ACTION bta_dm_action[] = {
-
- /* device manager local device API events */
- bta_dm_enable, /* 0 BTA_DM_API_ENABLE_EVT */
- bta_dm_disable, /* 1 BTA_DM_API_DISABLE_EVT */
- bta_dm_set_dev_name, /* 2 BTA_DM_API_SET_NAME_EVT */
- bta_dm_set_visibility, /* 3 BTA_DM_API_SET_VISIBILITY_EVT */
- bta_dm_acl_change, /* 8 BTA_DM_ACL_CHANGE_EVT */
- bta_dm_add_device, /* 9 BTA_DM_API_ADD_DEVICE_EVT */
- bta_dm_close_acl, /* 10 BTA_DM_API_ADD_DEVICE_EVT */
-
- /* security API events */
- bta_dm_bond, /* 11 BTA_DM_API_BOND_EVT */
- bta_dm_bond_cancel, /* 12 BTA_DM_API_BOND_CANCEL_EVT */
- bta_dm_pin_reply, /* 13 BTA_DM_API_PIN_REPLY_EVT */
-
- /* power manger events */
- bta_dm_pm_btm_status, /* 16 BTA_DM_PM_BTM_STATUS_EVT */
- bta_dm_pm_timer, /* 17 BTA_DM_PM_TIMER_EVT*/
-
- /* simple pairing events */
- bta_dm_confirm, /* 18 BTA_DM_API_CONFIRM_EVT */
-
- bta_dm_set_encryption, /* BTA_DM_API_SET_ENCRYPTION_EVT */
-
- /* out of band pairing events */
- bta_dm_loc_oob, /* 20 BTA_DM_API_LOC_OOB_EVT */
- bta_dm_ci_io_req_act, /* 21 BTA_DM_CI_IO_REQ_EVT */
- bta_dm_ci_rmt_oob_act, /* 22 BTA_DM_CI_RMT_OOB_EVT */
-
- bta_dm_add_blekey, /* BTA_DM_API_ADD_BLEKEY_EVT */
- bta_dm_add_ble_device, /* BTA_DM_API_ADD_BLEDEVICE_EVT */
- bta_dm_ble_passkey_reply, /* BTA_DM_API_BLE_PASSKEY_REPLY_EVT */
- bta_dm_ble_confirm_reply, /* BTA_DM_API_BLE_CONFIRM_REPLY_EVT */
- bta_dm_security_grant, bta_dm_ble_set_bg_conn_type,
- bta_dm_ble_set_conn_params, /* BTA_DM_API_BLE_CONN_PARAM_EVT */
- bta_dm_ble_set_conn_scan_params, /* BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT */
- bta_dm_ble_observe,
- bta_dm_ble_update_conn_params, /* BTA_DM_API_UPDATE_CONN_PARAM_EVT */
-#if (BLE_PRIVACY_SPT == TRUE)
- bta_dm_ble_config_local_privacy, /* BTA_DM_API_LOCAL_PRIVACY_EVT */
-#endif
- bta_dm_ble_set_data_length, /* BTA_DM_API_SET_DATA_LENGTH_EVT */
- bta_dm_ble_get_energy_info, /* BTA_DM_API_BLE_ENERGY_INFO_EVT */
-
- bta_dm_enable_test_mode, /* BTA_DM_API_ENABLE_TEST_MODE_EVT */
- bta_dm_disable_test_mode, /* BTA_DM_API_DISABLE_TEST_MODE_EVT */
- bta_dm_execute_callback, /* BTA_DM_API_EXECUTE_CBACK_EVT */
-
- bta_dm_remove_all_acl, /* BTA_DM_API_REMOVE_ALL_ACL_EVT */
- bta_dm_remove_device, /* BTA_DM_API_REMOVE_DEVICE_EVT */
-};
-
/* state machine action enumeration list */
enum {
BTA_DM_API_SEARCH, /* 0 bta_dm_search_start */
@@ -261,41 +207,6 @@
/*******************************************************************************
*
- * Function bta_dm_sm_disable
- *
- * Description unregister BTA DM
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_sm_disable() { bta_sys_deregister(BTA_ID_DM); }
-
-/*******************************************************************************
- *
- * Function bta_dm_sm_execute
- *
- * Description State machine event handling function for DM
- *
- *
- * Returns void
- *
- ******************************************************************************/
-bool bta_dm_sm_execute(BT_HDR* p_msg) {
- uint16_t event = p_msg->event & 0x00ff;
-
- APPL_TRACE_EVENT("bta_dm_sm_execute event:0x%x", event);
-
- /* execute action functions */
- if (event < BTA_DM_NUM_ACTIONS) {
- (*bta_dm_action[event])((tBTA_DM_MSG*)p_msg);
- }
-
- return true;
-}
-
-/*******************************************************************************
- *
* Function bta_dm_sm_search_disable
*
* Description unregister BTA SEARCH DM
diff --git a/bta/dm/bta_dm_pm.cc b/bta/dm/bta_dm_pm.cc
index 23716c1..731d253 100644
--- a/bta/dm/bta_dm_pm.cc
+++ b/bta/dm/bta_dm_pm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
*
******************************************************************************/
+#include <base/bind.h>
#include <base/logging.h>
#include <string.h>
@@ -47,7 +48,9 @@
static bool bta_dm_pm_park(const RawAddress& peer_addr);
static bool bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE* p_peer_dev, uint8_t index);
static bool bta_dm_pm_is_sco_active();
+#if (BTM_SSR_INCLUDED == TRUE)
static int bta_dm_get_sco_index();
+#endif
static void bta_dm_pm_hid_check(bool bScoActive);
static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE* p_dev,
bool bDisable);
@@ -83,7 +86,7 @@
/* if there are no power manger entries, so not register */
if (p_bta_dm_pm_cfg[0].app_id != 0) {
- bta_sys_pm_register((tBTA_SYS_CONN_CBACK*)bta_dm_pm_cback);
+ bta_sys_pm_register(bta_dm_pm_cback);
BTM_PmRegister((BTM_PM_REG_SET | BTM_PM_REG_NOTIF), &bta_dm_cb.pm_id,
bta_dm_pm_btm_cback);
@@ -113,7 +116,7 @@
* Deregister the PM callback from the system handling to prevent
* re-enabling the PM timers after this call if the callback is invoked.
*/
- bta_sys_pm_register((tBTA_SYS_CONN_CBACK*)NULL);
+ bta_sys_pm_register(NULL);
/* Need to stop all active timers. */
for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
@@ -331,14 +334,9 @@
static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
uint8_t app_id, const RawAddress& peer_addr) {
uint8_t i, j;
- uint8_t* p = NULL;
tBTA_DM_PEER_DEVICE* p_dev;
tBTA_DM_PM_REQ pm_req = BTA_DM_PM_NEW_REQ;
-#if (BTM_SSR_INCLUDED == TRUE)
- int index = BTA_DM_PM_SSR0;
-#endif
-
APPL_TRACE_DEBUG("bta_dm_pm_cback: st(%d), id(%d), app(%d)", status, id,
app_id);
@@ -360,6 +358,7 @@
#if (BTM_SSR_INCLUDED == TRUE)
/* set SSR parameters on SYS CONN OPEN */
+ int index = BTA_DM_PM_SSR0;
if ((BTA_SYS_CONN_OPEN == status) && p_dev &&
(p_dev->info & BTA_DM_DI_USE_SSR)) {
index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
@@ -448,6 +447,7 @@
) {
bta_dm_pm_ssr(peer_addr);
} else {
+ uint8_t* p = NULL;
if (((NULL != (p = BTM_ReadLocalFeatures())) &&
HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
((NULL != (p = BTM_ReadRemoteFeatures(peer_addr))) &&
@@ -506,9 +506,10 @@
tBTA_DM_PEER_DEVICE* p_peer_device = NULL;
tBTA_DM_PM_ACTION allowed_modes = 0;
tBTA_DM_PM_ACTION pref_modes = 0;
- tBTA_DM_PM_CFG* p_pm_cfg;
- tBTA_DM_PM_SPEC* p_pm_spec;
- tBTA_DM_PM_ACTN *p_act0, *p_act1;
+ const tBTA_DM_PM_CFG* p_pm_cfg;
+ const tBTA_DM_PM_SPEC* p_pm_spec;
+ const tBTA_DM_PM_ACTN* p_act0;
+ const tBTA_DM_PM_ACTN* p_act1;
tBTA_DM_SRVCS* p_srvcs = NULL;
bool timer_started = false;
uint8_t timer_idx, available_timer = BTA_DM_PM_MODE_TIMER_MAX;
@@ -691,25 +692,16 @@
tBTM_PM_MODE mode = BTM_PM_STS_ACTIVE;
tBTM_PM_PWR_MD pwr_md;
tBTM_STATUS status;
-#if (BTM_SSR_INCLUDED == TRUE)
- uint8_t* p_rem_feat = NULL;
-#endif
BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode);
- p_rem_feat = BTM_ReadRemoteFeatures(p_peer_dev->peer_bdaddr);
#if (BTM_SSR_INCLUDED == TRUE)
+ uint8_t* p_rem_feat = BTM_ReadRemoteFeatures(p_peer_dev->peer_bdaddr);
APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index,
p_peer_dev->info);
if (mode != BTM_PM_MD_SNIFF ||
(HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadLocalFeatures()) && p_rem_feat &&
HCI_SNIFF_SUB_RATE_SUPPORTED(p_rem_feat) &&
- !(p_peer_dev->info & BTA_DM_DI_USE_SSR)))
-#else
- APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d", mode, index);
- if (mode != BTM_PM_MD_SNIFF)
-#endif
- {
-#if (BTM_SSR_INCLUDED == TRUE)
+ !(p_peer_dev->info & BTA_DM_DI_USE_SSR))) {
/* Dont initiate Sniff if controller has alreay accepted
* remote sniff params. This avoid sniff loop issue with
* some agrresive headsets who use sniff latencies more than
@@ -718,6 +710,9 @@
APPL_TRACE_DEBUG("%s: already in remote initiate sniff", __func__);
return true;
}
+#else
+ APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d", mode, index);
+ if (mode != BTM_PM_MD_SNIFF) {
#endif
/* if the current mode is not sniff, issue the sniff command.
* If sniff, but SSR is not used in this link, still issue the command */
@@ -756,53 +751,48 @@
******************************************************************************/
#if (BTM_SSR_INCLUDED == TRUE)
static void bta_dm_pm_ssr(const RawAddress& peer_addr) {
- tBTA_DM_SSR_SPEC *p_spec, *p_spec_cur;
- uint8_t i, j;
- int ssr = BTA_DM_PM_SSR0;
+ int current_ssr_index;
+ int ssr_index = BTA_DM_PM_SSR0;
+ tBTA_DM_SSR_SPEC* p_spec = &p_bta_dm_ssr_spec[ssr_index];
/* go through the connected services */
- for (i = 0; i < bta_dm_conn_srvcs.count; i++) {
- if (bta_dm_conn_srvcs.conn_srvc[i].peer_bdaddr == peer_addr) {
- /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
- for (j = 1; j <= p_bta_dm_pm_cfg[0].app_id; j++) {
- /* find the associated p_bta_dm_pm_cfg */
- if ((p_bta_dm_pm_cfg[j].id == bta_dm_conn_srvcs.conn_srvc[i].id) &&
- ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID) ||
- (p_bta_dm_pm_cfg[j].app_id ==
- bta_dm_conn_srvcs.conn_srvc[i].app_id))) {
- APPL_TRACE_WARNING("bta_dm_pm_ssr conn_srvc id:%d, app_id:%d",
- bta_dm_conn_srvcs.conn_srvc[i].id,
- bta_dm_conn_srvcs.conn_srvc[i].app_id);
- break;
- }
+ for (int i = 0; i < bta_dm_conn_srvcs.count; i++) {
+ const tBTA_DM_SRVCS& service = bta_dm_conn_srvcs.conn_srvc[i];
+ if (service.peer_bdaddr != peer_addr) {
+ continue;
+ }
+ /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
+ for (int j = 1; j <= p_bta_dm_pm_cfg[0].app_id; j++) {
+ /* find the associated p_bta_dm_pm_cfg */
+ const tBTA_DM_PM_CFG& config = p_bta_dm_pm_cfg[j];
+ current_ssr_index = p_bta_dm_pm_spec[config.spec_idx].ssr;
+ if ((config.id == service.id) && ((config.app_id == BTA_ALL_APP_ID) ||
+ (config.app_id == service.app_id))) {
+ APPL_TRACE_WARNING("%s: conn_srvc id:%d, app_id:%d", __func__,
+ service.id, service.app_id);
+ break;
}
-
- /* find the ssr index with the smallest max latency. */
- p_spec_cur =
- &p_bta_dm_ssr_spec[p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr];
- p_spec = &p_bta_dm_ssr_spec[ssr];
-
+ }
+ /* find the ssr index with the smallest max latency. */
+ tBTA_DM_SSR_SPEC* p_spec_cur = &p_bta_dm_ssr_spec[current_ssr_index];
#if (BTA_HH_INCLUDED == TRUE)
- /* HH has the per connection SSR preference, already read the SSR params
- * from BTA HH */
- if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr ==
- BTA_DM_PM_SSR_HH) {
- if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat,
- &p_spec_cur->min_rmt_to) == BTA_HH_ERR)
- continue;
+ /* HH has the per connection SSR preference, already read the SSR params
+ * from BTA HH */
+ if (current_ssr_index == BTA_DM_PM_SSR_HH) {
+ if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat,
+ &p_spec_cur->min_rmt_to) == BTA_HH_ERR) {
+ continue;
}
+ }
#endif
- if (p_spec_cur->max_lat < p_spec->max_lat ||
- (ssr == BTA_DM_PM_SSR0 &&
- p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr !=
- BTA_DM_PM_SSR0)) {
- ssr = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr;
- }
+ if (p_spec_cur->max_lat < p_spec->max_lat ||
+ (ssr_index == BTA_DM_PM_SSR0 && current_ssr_index != BTA_DM_PM_SSR0)) {
+ ssr_index = current_ssr_index;
+ p_spec = &p_bta_dm_ssr_spec[ssr_index];
}
}
- p_spec = &p_bta_dm_ssr_spec[ssr];
- APPL_TRACE_WARNING("%s ssr:%d, lat:%d", __func__, ssr, p_spec->max_lat);
+ APPL_TRACE_WARNING("%s ssr:%d, lat:%d", __func__, ssr_index, p_spec->max_lat);
if (p_spec->max_lat) {
/* Avoid SSR reset on device which has SCO connected */
@@ -843,29 +833,12 @@
BTM_SetPowerMode(bta_dm_cb.pm_id, peer_addr, &pm);
}
-/*******************************************************************************
- *
- * Function bta_dm_pm_btm_cback
- *
- * Description BTM power manager callback.
- *
- *
- * Returns void
- *
- ******************************************************************************/
+/** BTM power manager callback */
static void bta_dm_pm_btm_cback(const RawAddress& bd_addr,
tBTM_PM_STATUS status, uint16_t value,
uint8_t hci_status) {
- tBTA_DM_PM_BTM_STATUS* p_buf =
- (tBTA_DM_PM_BTM_STATUS*)osi_malloc(sizeof(tBTA_DM_PM_BTM_STATUS));
-
- p_buf->hdr.event = BTA_DM_PM_BTM_STATUS_EVT;
- p_buf->status = status;
- p_buf->value = value;
- p_buf->hci_status = hci_status;
- p_buf->bd_addr = bd_addr;
-
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_pm_btm_status, bd_addr, status,
+ value, hci_status));
}
/*******************************************************************************
@@ -905,51 +878,35 @@
/* no more timers */
if (i == BTA_DM_NUM_PM_TIMER) return;
- tBTA_DM_PM_TIMER* p_buf =
- (tBTA_DM_PM_TIMER*)osi_malloc(sizeof(tBTA_DM_PM_TIMER));
- p_buf->hdr.event = BTA_DM_PM_TIMER_EVT;
- p_buf->pm_request = bta_dm_cb.pm_timer[i].pm_action[j];
- p_buf->bd_addr = bta_dm_cb.pm_timer[i].peer_bdaddr;
-
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(
+ FROM_HERE, base::Bind(bta_dm_pm_timer, bta_dm_cb.pm_timer[i].peer_bdaddr,
+ bta_dm_cb.pm_timer[i].pm_action[j]));
}
-/*******************************************************************************
- *
- * Function bta_dm_pm_btm_status
- *
- * Description Process pm status event from btm
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_pm_btm_status(tBTA_DM_MSG* p_data) {
- APPL_TRACE_DEBUG("%s status: %d", __func__, p_data->pm_status.status);
+/** Process pm status event from btm */
+void bta_dm_pm_btm_status(const RawAddress& bd_addr, tBTM_PM_STATUS status,
+ uint16_t value, uint8_t hci_status) {
+ APPL_TRACE_DEBUG("%s status: %d", __func__, status);
- tBTA_DM_PEER_DEVICE* p_dev =
- bta_dm_find_peer_device(p_data->pm_status.bd_addr);
+ tBTA_DM_PEER_DEVICE* p_dev = bta_dm_find_peer_device(bd_addr);
if (NULL == p_dev) return;
tBTA_DM_DEV_INFO info = p_dev->info;
/* check new mode */
- switch (p_data->pm_status.status) {
+ switch (status) {
case BTM_PM_STS_ACTIVE:
/* if our sniff or park attempt failed
we should not try it again*/
- if (p_data->pm_status.hci_status != 0) {
- APPL_TRACE_ERROR("%s hci_status=%d", __func__,
- p_data->pm_status.hci_status);
+ if (hci_status != 0) {
+ APPL_TRACE_ERROR("%s hci_status=%d", __func__, hci_status);
p_dev->info &=
~(BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF | BTA_DM_DI_SET_SNIFF);
if (p_dev->pm_mode_attempted & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF)) {
p_dev->pm_mode_failed |=
((BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & p_dev->pm_mode_attempted);
- bta_dm_pm_stop_timer_by_mode(p_data->pm_status.bd_addr,
- p_dev->pm_mode_attempted);
- bta_dm_pm_set_mode(p_data->pm_status.bd_addr, BTA_DM_PM_NO_ACTION,
- BTA_DM_PM_RESTART);
+ bta_dm_pm_stop_timer_by_mode(bd_addr, p_dev->pm_mode_attempted);
+ bta_dm_pm_set_mode(bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART);
}
} else {
#if (BTM_SSR_INCLUDED == TRUE)
@@ -961,9 +918,8 @@
#endif
/* link to active mode, need to restart the timer for next low power
* mode if needed */
- bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
- bta_dm_pm_set_mode(p_data->pm_status.bd_addr, BTA_DM_PM_NO_ACTION,
- BTA_DM_PM_RESTART);
+ bta_dm_pm_stop_timer(bd_addr);
+ bta_dm_pm_set_mode(bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART);
}
break;
@@ -973,26 +929,25 @@
/* save the previous low power mode - for SSR.
* SSR parameters are sent to controller on "conn open".
* the numbers stay good until park/hold/detach */
- if (p_dev->info & BTA_DM_DI_USE_SSR)
- p_dev->prev_low = p_data->pm_status.status;
+ if (p_dev->info & BTA_DM_DI_USE_SSR) p_dev->prev_low = status;
break;
case BTM_PM_STS_SSR:
- if (p_data->pm_status.value)
+ if (value)
p_dev->info |= BTA_DM_DI_USE_SSR;
else
p_dev->info &= ~BTA_DM_DI_USE_SSR;
break;
#endif
case BTM_PM_STS_SNIFF:
- if (p_data->pm_status.hci_status == 0) {
+ if (hci_status == 0) {
/* Stop PM timer now if already active for
* particular device since link is already
* put in sniff mode by remote device, and
* PM timer sole purpose is to put the link
* in sniff mode from host side.
*/
- bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
+ bta_dm_pm_stop_timer(bd_addr);
} else {
p_dev->info &=
~(BTA_DM_DI_SET_SNIFF | BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF);
@@ -1012,20 +967,10 @@
}
}
-/*******************************************************************************
- *
- * Function bta_dm_pm_timer
- *
- * Description Process pm timer event from btm
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_pm_timer(tBTA_DM_MSG* p_data) {
+/** Process pm timer event from btm */
+void bta_dm_pm_timer(const RawAddress& bd_addr, tBTA_DM_PM_ACTION pm_request) {
APPL_TRACE_EVENT("%s", __func__);
- bta_dm_pm_set_mode(p_data->pm_timer.bd_addr, p_data->pm_timer.pm_request,
- BTA_DM_PM_EXECUTE);
+ bta_dm_pm_set_mode(bd_addr, pm_request, BTA_DM_PM_EXECUTE);
}
/*******************************************************************************
@@ -1075,6 +1020,7 @@
return bScoActive;
}
+#if (BTM_SSR_INCLUDED == TRUE)
/*******************************************************************************
*
* Function bta_dm_get_sco_index
@@ -1094,6 +1040,7 @@
}
return -1;
}
+#endif
/*******************************************************************************
*
diff --git a/bta/dm/bta_dm_sco.cc b/bta/dm/bta_dm_sco.cc
deleted file mode 100644
index 4757a53..0000000
--- a/bta/dm/bta_dm_sco.cc
+++ /dev/null
@@ -1,667 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2003-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * This file contains the down sampling utility to convert PCM samples in
- * 16k/32k/48k/44.1k/22050/11025 sampling rate into 8K/16bits samples
- * required for SCO channel format. One API function isprovided and only
- * possible to be used when transmitting SCO data is sent via HCI
- * interface.
- *
- ******************************************************************************/
-#include <string.h>
-
-#include "bta_api.h"
-#include "bta_sys.h"
-
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
-
-#ifndef BTA_DM_SCO_DEBUG
-#define BTA_DM_SCO_DEBUG false
-#endif
-/*****************************************************************************
- * Constants
- ****************************************************************************/
-
-#define BTA_DM_PCM_OVERLAP_SIZE 48
-
-#define BTA_DM_PCM_SMPL_RATE_44100 44100
-#define BTA_DM_PCM_SMPL_RATE_22050 22050
-#define BTA_DM_PCM_SMPL_RATE_11025 11025
-
-/*****************************************************************************
- * Data types for PCM Resampling utility
- ****************************************************************************/
-
-typedef int32_t (*PCONVERT_TO_BT_FILTERED)(uint8_t* pSrc, void* pDst,
- uint32_t dwSrcSamples,
- uint32_t dwSrcSps,
- int32_t* pLastCurPos,
- uint8_t* pOverlapArea);
-typedef int32_t (*PCONVERT_TO_BT_NOFILTER)(void* pSrc, void* pDst,
- uint32_t dwSrcSamples,
- uint32_t dwSrcSps);
-typedef struct {
- uint8_t overlap_area[BTA_DM_PCM_OVERLAP_SIZE * 4];
- uint32_t cur_pos; /* current position */
- uint32_t src_sps; /* samples per second (source audio data) */
- PCONVERT_TO_BT_FILTERED filter; /* the action function to do the
- conversion 44100, 22050, 11025*/
- PCONVERT_TO_BT_NOFILTER nofilter; /* the action function to do
- the conversion 48000, 32000, 16000*/
- uint32_t bits; /* number of bits per pcm sample */
- uint32_t n_channels; /* number of channels (i.e. mono(1), stereo(2)...) */
- uint32_t sample_size;
- uint32_t can_be_filtered;
- uint32_t divisor;
-} tBTA_DM_PCM_RESAMPLE_CB;
-
-tBTA_DM_PCM_RESAMPLE_CB bta_dm_pcm_cb;
-
-/*****************************************************************************
- * Macro Definition
- ****************************************************************************/
-
-#define CHECK_SATURATION16(x) \
- do { \
- if ((x) > 32767) \
- (x) = 32767; \
- else if ((x) < -32768) \
- (x) = -32768; \
- } while (0)
-
-////////////////////////////////////////////////////////////////////////////////
-//
-#define CONVERT_44100_TO_BLUETOOTH(pStart, pEnd) \
- do { \
- int32_t out1, out2, out3, out4, out5; \
- SRC_TYPE* pS = (SRC_TYPE*)(pStart); \
- SRC_TYPE* pSEnd = (SRC_TYPE*)(pEnd); \
- \
- while (pS < pSEnd) { \
- CurrentPos -= 8000; \
- \
- if (CurrentPos >= 0) { \
- pS += SRC_CHANNELS; \
- continue; \
- } \
- CurrentPos += dwSrcSps; \
- \
- out1 = (SRC_SAMPLE(0) * 1587) + \
- ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 1522) + \
- ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1337) + \
- ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 1058); \
- \
- out1 = out1 / 30000; \
- \
- out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 725) + \
- ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 384) + \
- ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 79); \
- \
- out2 = out2 / 30000; \
- \
- out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 156) + \
- ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 298) + \
- ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 345); \
- \
- out3 = out3 / 30000; \
- \
- out4 = ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 306) + \
- ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 207) + \
- ((SRC_SAMPLE(12) + SRC_SAMPLE(-12)) * 78); \
- \
- out4 = out4 / 30000; \
- \
- out5 = out1 + out2 - out3 - out4; \
- \
- CHECK_SATURATION16(out5); \
- *psBtOut++ = (int16_t)out5; \
- \
- pS += SRC_CHANNELS; \
- } \
- } while (0)
-
-////////////////////////////////////////////////////////////////////////////////
-//
-#define CONVERT_22050_TO_BLUETOOTH(pStart, pEnd) \
- do { \
- int32_t out1, out2, out3, out4, out5; \
- SRC_TYPE* pS = (SRC_TYPE*)(pStart); \
- SRC_TYPE* pSEnd = (SRC_TYPE*)(pEnd); \
- \
- while (pS < pSEnd) { \
- CurrentPos -= 8000; \
- \
- if (CurrentPos >= 0) { \
- pS += SRC_CHANNELS; \
- continue; \
- } \
- CurrentPos += dwSrcSps; \
- \
- out1 = (SRC_SAMPLE(0) * 2993) + \
- ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2568) + \
- ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1509) + \
- ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 331); \
- \
- out1 = out1 / 30000; \
- \
- out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 454) + \
- ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 620) + \
- ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 305); \
- \
- out2 = out2 / 30000; \
- \
- out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 127) + \
- ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 350) + \
- ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 265) + \
- ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 6); \
- \
- out3 = out3 / 30000; \
- \
- out4 = ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 201); \
- \
- out4 = out4 / 30000; \
- \
- out5 = out1 - out2 + out3 - out4; \
- \
- CHECK_SATURATION16(out5); \
- *psBtOut++ = (int16_t)out5; \
- \
- pS += SRC_CHANNELS; \
- } \
- } while (0)
-
-////////////////////////////////////////////////////////////////////////////////
-//
-#define CONVERT_11025_TO_BLUETOOTH(pStart, pEnd) \
- do { \
- int32_t out1; \
- SRC_TYPE* pS = (SRC_TYPE*)(pStart); \
- SRC_TYPE* pSEnd = (SRC_TYPE*)(pEnd); \
- \
- while (pS < pSEnd) { \
- CurrentPos -= 8000; \
- \
- if (CurrentPos >= 0) { \
- pS += SRC_CHANNELS; \
- continue; \
- } \
- CurrentPos += dwSrcSps; \
- \
- out1 = (SRC_SAMPLE(0) * 6349) + \
- ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2874) - \
- ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1148) - \
- ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 287) + \
- ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 675) - \
- ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 258) - \
- ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 206) + \
- ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 266); \
- \
- out1 = out1 / 30000; \
- \
- CHECK_SATURATION16(out1); \
- *psBtOut++ = (int16_t)out1; \
- \
- pS += SRC_CHANNELS; \
- } \
- } while (0)
-
-////////////////////////////////////////////////////////////////////////////////
-//
-#undef SRC_CHANNELS
-#undef SRC_SAMPLE
-#undef SRC_TYPE
-
-#define SRC_TYPE uint8_t
-#define SRC_CHANNELS 1
-#define SRC_SAMPLE(x) ((pS[x] - 0x80) << 8)
-
-/*****************************************************************************
- * Local Function
- ****************************************************************************/
-int32_t Convert_8M_ToBT_Filtered(uint8_t* pSrc, void* pDst,
- uint32_t dwSrcSamples, uint32_t dwSrcSps,
- int32_t* pLastCurPos, uint8_t* pOverlapArea) {
- int32_t CurrentPos = *pLastCurPos;
- SRC_TYPE *pIn, *pInEnd;
- SRC_TYPE *pOv, *pOvEnd;
- int16_t* psBtOut = (int16_t*)pDst;
-#if (BTA_DM_SCO_DEBUG == TRUE)
- APPL_TRACE_DEBUG("Convert_8M_ToBT_Filtered, CurrentPos %d\n", CurrentPos);
-#endif
- memcpy(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc,
- BTA_DM_PCM_OVERLAP_SIZE * 2);
-
- pOv = (SRC_TYPE*)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
- pOvEnd = (SRC_TYPE*)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
-
- pIn = (SRC_TYPE*)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
- pInEnd = (SRC_TYPE*)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof(SRC_TYPE)) -
- BTA_DM_PCM_OVERLAP_SIZE);
-
- if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100) {
- CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
- } else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050) {
- CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
- } else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025) {
- CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
- }
-
- memcpy(pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof(SRC_TYPE)) -
- (BTA_DM_PCM_OVERLAP_SIZE * 2),
- BTA_DM_PCM_OVERLAP_SIZE * 2);
-
- *pLastCurPos = CurrentPos;
-
- return (psBtOut - (int16_t*)pDst);
-}
-
-int32_t Convert_8M_ToBT_NoFilter(void* pSrc, void* pDst, uint32_t dwSrcSamples,
- uint32_t dwSrcSps) {
- int32_t CurrentPos;
- uint8_t* pbSrc = (uint8_t*)pSrc;
- int16_t* psDst = (int16_t*)pDst;
- int16_t sWorker;
-
- // start at dwSpsSrc / 2, decrement by 8000
- //
- CurrentPos = (dwSrcSps >> 1);
-
- while (dwSrcSamples--) {
- CurrentPos -= 8000;
-
- if (CurrentPos >= 0)
- pbSrc++;
- else {
- sWorker = *pbSrc++;
- sWorker -= 0x80;
- sWorker <<= 8;
-
- *psDst++ = sWorker;
-
- CurrentPos += dwSrcSps;
- }
- }
-
- return (psDst - (int16_t*)pDst);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-#undef SRC_CHANNELS
-#undef SRC_SAMPLE
-#undef SRC_TYPE
-
-#define SRC_TYPE int16_t
-#define SRC_CHANNELS 1
-#define SRC_SAMPLE(x) pS[x]
-
-int32_t Convert_16M_ToBT_Filtered(uint8_t* pSrc, void* pDst,
- uint32_t dwSrcSamples, uint32_t dwSrcSps,
- int32_t* pLastCurPos, uint8_t* pOverlapArea) {
- int32_t CurrentPos = *pLastCurPos;
- SRC_TYPE *pIn, *pInEnd;
- SRC_TYPE *pOv, *pOvEnd;
- int16_t* psBtOut = (int16_t*)pDst;
-
- memcpy(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc,
- BTA_DM_PCM_OVERLAP_SIZE * 2);
-
- pOv = (SRC_TYPE*)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
- pOvEnd = (SRC_TYPE*)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
-
- pIn = (SRC_TYPE*)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
- pInEnd = (SRC_TYPE*)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof(SRC_TYPE)) -
- BTA_DM_PCM_OVERLAP_SIZE);
-
- if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100) {
- CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
- } else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050) {
- CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
- } else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025) {
- CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
- }
-
- memcpy(pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof(SRC_TYPE)) -
- (BTA_DM_PCM_OVERLAP_SIZE * 2),
- BTA_DM_PCM_OVERLAP_SIZE * 2);
-
- *pLastCurPos = CurrentPos;
-
- return (psBtOut - (int16_t*)pDst);
-}
-
-int32_t Convert_16M_ToBT_NoFilter(void* pSrc, void* pDst, uint32_t dwSrcSamples,
- uint32_t dwSrcSps) {
- int32_t CurrentPos;
- int16_t* psSrc = (int16_t*)pSrc;
- int16_t* psDst = (int16_t*)pDst;
-
- // start at dwSpsSrc / 2, decrement by 8000
- //
- CurrentPos = (dwSrcSps >> 1);
-
- while (dwSrcSamples--) {
- CurrentPos -= 8000;
-
- if (CurrentPos >= 0)
- psSrc++;
- else {
- *psDst++ = *psSrc++;
-
- CurrentPos += dwSrcSps;
- }
- }
-
- return (psDst - (int16_t*)pDst);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-#undef SRC_CHANNELS
-#undef SRC_SAMPLE
-#undef SRC_TYPE
-
-#define SRC_TYPE uint8_t
-#define SRC_CHANNELS 2
-#define SRC_SAMPLE(x) \
- ((((pS[x * 2] - 0x80) << 8) + ((pS[(x * 2) + 1] - 0x80) << 8)) >> 1)
-
-int32_t Convert_8S_ToBT_Filtered(uint8_t* pSrc, void* pDst,
- uint32_t dwSrcSamples, uint32_t dwSrcSps,
- int32_t* pLastCurPos, uint8_t* pOverlapArea) {
- int32_t CurrentPos = *pLastCurPos;
- SRC_TYPE *pIn, *pInEnd;
- SRC_TYPE *pOv, *pOvEnd;
- int16_t* psBtOut = (int16_t*)pDst;
-
-#if (BTA_DM_SCO_DEBUG == TRUE)
- APPL_TRACE_DEBUG(
- "Convert_8S_ToBT_Filtered CurrentPos %d, SRC_TYPE %d, SRC_CHANNELS %d, \
- dwSrcSamples %d, dwSrcSps %d",
- CurrentPos, sizeof(SRC_TYPE), SRC_CHANNELS, dwSrcSamples, dwSrcSps);
-#endif
- memcpy(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc,
- BTA_DM_PCM_OVERLAP_SIZE * 2);
-
- pOv = (SRC_TYPE*)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
- pOvEnd = (SRC_TYPE*)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
-
- pIn = (SRC_TYPE*)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
- pInEnd = (SRC_TYPE*)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof(SRC_TYPE)) -
- BTA_DM_PCM_OVERLAP_SIZE);
-
- if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100) {
- CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
- } else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050) {
- CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
- } else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025) {
- CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
- }
-
- memcpy(pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof(SRC_TYPE)) -
- (BTA_DM_PCM_OVERLAP_SIZE * 2),
- BTA_DM_PCM_OVERLAP_SIZE * 2);
-
- *pLastCurPos = CurrentPos;
-
- return (psBtOut - (int16_t*)pDst);
-}
-
-int32_t Convert_8S_ToBT_NoFilter(void* pSrc, void* pDst, uint32_t dwSrcSamples,
- uint32_t dwSrcSps) {
- int32_t CurrentPos;
- uint8_t* pbSrc = (uint8_t*)pSrc;
- int16_t* psDst = (int16_t*)pDst;
- int16_t sWorker, sWorker2;
-
- // start at dwSpsSrc / 2, decrement by 8000
- //
- CurrentPos = (dwSrcSps >> 1);
-
- while (dwSrcSamples--) {
- CurrentPos -= 8000;
-
- if (CurrentPos >= 0)
- pbSrc += 2;
- else {
- sWorker = *(unsigned char*)pbSrc;
- sWorker -= 0x80;
- sWorker <<= 8;
- pbSrc++;
-
- sWorker2 = *(unsigned char*)pbSrc;
- sWorker2 -= 0x80;
- sWorker2 <<= 8;
- pbSrc++;
-
- sWorker += sWorker2;
- sWorker >>= 1;
-
- *psDst++ = sWorker;
-
- CurrentPos += dwSrcSps;
- }
- }
-
- return (psDst - (int16_t*)pDst);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-#undef SRC_CHANNELS
-#undef SRC_SAMPLE
-#undef SRC_TYPE
-
-#define SRC_TYPE int16_t
-#define SRC_CHANNELS 2
-#define SRC_SAMPLE(x) ((pS[x * 2] + pS[(x * 2) + 1]) >> 1)
-
-int32_t Convert_16S_ToBT_Filtered(uint8_t* pSrc, void* pDst,
- uint32_t dwSrcSamples, uint32_t dwSrcSps,
- int32_t* pLastCurPos, uint8_t* pOverlapArea) {
- int32_t CurrentPos = *pLastCurPos;
- SRC_TYPE *pIn, *pInEnd;
- SRC_TYPE *pOv, *pOvEnd;
- int16_t* psBtOut = (int16_t*)pDst;
-
- memcpy(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc,
- BTA_DM_PCM_OVERLAP_SIZE * 2);
-
- pOv = (SRC_TYPE*)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
- pOvEnd = (SRC_TYPE*)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
-
- pIn = (SRC_TYPE*)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
- pInEnd = (SRC_TYPE*)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof(SRC_TYPE)) -
- BTA_DM_PCM_OVERLAP_SIZE);
-
- if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100) {
- CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
- } else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050) {
- CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
- } else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025) {
- CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
- CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
- }
-
- memcpy(pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof(SRC_TYPE)) -
- (BTA_DM_PCM_OVERLAP_SIZE * 2),
- BTA_DM_PCM_OVERLAP_SIZE * 2);
-
- *pLastCurPos = CurrentPos;
-
- return (psBtOut - (int16_t*)pDst);
-}
-
-int32_t Convert_16S_ToBT_NoFilter(void* pSrc, void* pDst, uint32_t dwSrcSamples,
- uint32_t dwSrcSps) {
- int32_t CurrentPos;
- int16_t* psSrc = (int16_t*)pSrc;
- int16_t* psDst = (int16_t*)pDst;
- int16_t sWorker;
-
- // start at dwSpsSrc / 2, decrement by 8000
- //
- CurrentPos = (dwSrcSps >> 1);
-
- while (dwSrcSamples--) {
- CurrentPos -= 8000;
-
- if (CurrentPos >= 0)
- psSrc += 2;
- else {
- /* CR 82894, to avoid overflow, divide before add */
- sWorker = ((*psSrc) >> 1);
- psSrc++;
- sWorker += ((*psSrc) >> 1);
- psSrc++;
-
- *psDst++ = sWorker;
-
- CurrentPos += dwSrcSps;
- }
- }
-
- return (psDst - (int16_t*)pDst);
-}
-
-/*******************************************************************************
- *
- * Function BTA_DmPcmInitSamples
- *
- * Description initialize the down sample converter.
- *
- * src_sps: original samples per second (source audio data)
- * (ex. 44100, 48000)
- * bits: number of bits per pcm sample (16)
- * n_channels: number of channels (i.e. mono(1), stereo(2)...)
- *
- * Returns none
- *
- ******************************************************************************/
-void BTA_DmPcmInitSamples(uint32_t src_sps, uint32_t bits,
- uint32_t n_channels) {
- tBTA_DM_PCM_RESAMPLE_CB* p_cb = &bta_dm_pcm_cb;
-
- p_cb->cur_pos = src_sps / 2;
- p_cb->src_sps = src_sps;
- p_cb->bits = bits;
- p_cb->n_channels = n_channels;
- p_cb->sample_size = 2;
- p_cb->divisor = 2;
-
- memset(p_cb->overlap_area, 0, sizeof(p_cb->overlap_area));
-
- if ((src_sps == BTA_DM_PCM_SMPL_RATE_44100) ||
- (src_sps == BTA_DM_PCM_SMPL_RATE_22050) ||
- (src_sps == BTA_DM_PCM_SMPL_RATE_11025))
- p_cb->can_be_filtered = 1;
- else
- p_cb->can_be_filtered = 0;
-
-#if (BTA_DM_SCO_DEBUG == TRUE)
- APPL_TRACE_DEBUG("bta_dm_pcm_init_samples: n_channels = %d bits = %d",
- n_channels, bits);
-#endif
- if (n_channels == 1) {
- /* mono */
- if (bits == 8) {
- p_cb->filter = (PCONVERT_TO_BT_FILTERED)Convert_8M_ToBT_Filtered;
- p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER)Convert_8M_ToBT_NoFilter;
- p_cb->divisor = 1;
- } else {
- p_cb->filter = (PCONVERT_TO_BT_FILTERED)Convert_16M_ToBT_Filtered;
- p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER)Convert_16M_ToBT_NoFilter;
- }
- } else {
- /* stereo */
- if (bits == 8) {
- p_cb->filter = (PCONVERT_TO_BT_FILTERED)Convert_8S_ToBT_Filtered;
- p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER)Convert_8S_ToBT_NoFilter;
- } else {
- p_cb->filter = (PCONVERT_TO_BT_FILTERED)Convert_16S_ToBT_Filtered;
- p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER)Convert_16S_ToBT_NoFilter;
- p_cb->divisor = 4;
- }
- }
-
-#if (BTA_DM_SCO_DEBUG == TRUE)
- APPL_TRACE_DEBUG("bta_pcm_init_dwn_sample: cur_pos %d, src_sps %d",
- p_cb->cur_pos, p_cb->src_sps);
- APPL_TRACE_DEBUG(
- "bta_pcm_init_dwn_sample: bits %d, n_channels %d, sample_size %d, ",
- p_cb->bits, p_cb->n_channels, p_cb->sample_size);
- APPL_TRACE_DEBUG(
- "bta_pcm_init_dwn_sample: can_be_filtered %d, n_channels: %d, \
- divisor %d",
- p_cb->can_be_filtered, p_cb->n_channels, p_cb->divisor);
-#endif
-}
-
-/*******************************************************************************
- * Function BTA_DmPcmResample
- *
- * Description Down sampling utility to convert higher sampling rate into
- * 8K/16bits PCM samples.
- *
- * Parameters p_src: pointer to the buffer where the original sampling PCM
- * are stored.
- * in_bytes: Length of the input PCM sample buffer in byte.
- * p_dst: pointer to the buffer which is to be used to
- * store the converted PCM samples.
- *
- *
- * Returns int32_t: number of samples converted.
- *
- ******************************************************************************/
-int32_t BTA_DmPcmResample(void* p_src, uint32_t in_bytes, void* p_dst) {
- uint32_t out_sample;
-
-#if (BTA_DM_SCO_DEBUG == TRUE)
- APPL_TRACE_DEBUG("bta_pcm_resample : insamples %d",
- (in_bytes / bta_dm_pcm_cb.divisor));
-#endif
- if (bta_dm_pcm_cb.can_be_filtered) {
- out_sample = (*bta_dm_pcm_cb.filter)(
- p_src, p_dst, (in_bytes / bta_dm_pcm_cb.divisor), bta_dm_pcm_cb.src_sps,
- (int32_t*)&bta_dm_pcm_cb.cur_pos, bta_dm_pcm_cb.overlap_area);
- } else {
- out_sample = (*bta_dm_pcm_cb.nofilter)(p_src, p_dst,
- (in_bytes / bta_dm_pcm_cb.divisor),
- bta_dm_pcm_cb.src_sps);
- }
-
-#if (BTA_DM_SCO_DEBUG == TRUE)
- APPL_TRACE_DEBUG("bta_pcm_resample : outsamples %d", out_sample);
-#endif
-
- return (out_sample * bta_dm_pcm_cb.sample_size);
-}
-#endif
diff --git a/bta/gatt/bta_gattc_act.cc b/bta/gatt/bta_gattc_act.cc
index 8b482b8..8a137dc 100644
--- a/bta/gatt/bta_gattc_act.cc
+++ b/bta/gatt/bta_gattc_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,6 +44,9 @@
#include "bta_hh_int.h"
#endif
+using base::StringPrintf;
+using bluetooth::Uuid;
+
/*****************************************************************************
* Constants
****************************************************************************/
@@ -56,7 +59,7 @@
tGATT_STATUS status,
tGATT_CL_COMPLETE* p_data);
static void bta_gattc_cmpl_sendmsg(uint16_t conn_id, tGATTC_OPTYPE op,
- tBTA_GATT_STATUS status,
+ tGATT_STATUS status,
tGATT_CL_COMPLETE* p_data);
static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB* p_clreg);
@@ -81,79 +84,74 @@
/* opcode(tGATTC_OPTYPE) order has to be comply with internal event order */
static uint16_t bta_gattc_opcode_to_int_evt[] = {
- BTA_GATTC_API_READ_EVT, BTA_GATTC_API_WRITE_EVT, BTA_GATTC_API_EXEC_EVT,
- BTA_GATTC_API_CFG_MTU_EVT};
+ /* Skip: GATTC_OPTYPE_NONE */
+ /* Skip: GATTC_OPTYPE_DISCOVERY */
+ BTA_GATTC_API_READ_EVT, /* GATTC_OPTYPE_READ */
+ BTA_GATTC_API_WRITE_EVT, /* GATTC_OPTYPE_WRITE */
+ BTA_GATTC_API_EXEC_EVT, /* GATTC_OPTYPE_EXE_WRITE */
+ BTA_GATTC_API_CFG_MTU_EVT /* GATTC_OPTYPE_CONFIG */
+};
static const char* bta_gattc_op_code_name[] = {
- "Unknown", "Discovery", "Read", "Write",
- "Exec", "Config", "Notification", "Indication"};
+ "Unknown", /* GATTC_OPTYPE_NONE */
+ "Discovery", /* GATTC_OPTYPE_DISCOVERY */
+ "Read", /* GATTC_OPTYPE_READ */
+ "Write", /* GATTC_OPTYPE_WRITE */
+ "Exec", /* GATTC_OPTYPE_EXE_WRITE */
+ "Config", /* GATTC_OPTYPE_CONFIG */
+ "Notification", /* GATTC_OPTYPE_NOTIFICATION */
+ "Indication" /* GATTC_OPTYPE_INDICATION */
+};
+
/*****************************************************************************
* Action Functions
****************************************************************************/
-void bta_gattc_reset_discover_st(tBTA_GATTC_SERV* p_srcb,
- tBTA_GATT_STATUS status);
+void bta_gattc_reset_discover_st(tBTA_GATTC_SERV* p_srcb, tGATT_STATUS status);
-/*******************************************************************************
- *
- * Function bta_gattc_enable
- *
- * Description Enables GATTC module
- *
- *
- * Returns void
- *
- ******************************************************************************/
+/** Enables GATTC module */
static void bta_gattc_enable() {
- APPL_TRACE_DEBUG("%s", __func__);
+ VLOG(1) << __func__;
if (bta_gattc_cb.state == BTA_GATTC_STATE_DISABLED) {
/* initialize control block */
- memset(&bta_gattc_cb, 0, sizeof(tBTA_GATTC_CB));
+ bta_gattc_cb = tBTA_GATTC_CB();
bta_gattc_cb.state = BTA_GATTC_STATE_ENABLED;
} else {
- APPL_TRACE_DEBUG("GATTC is already enabled");
+ VLOG(1) << "GATTC is already enabled";
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_disable
- *
- * Description Disable GATTC module by cleaning up all active connections
- * and deregister all application.
- *
- * Returns void
- *
- ******************************************************************************/
+/** Disable GATTC module by cleaning up all active connections and deregister
+ * all application */
void bta_gattc_disable() {
uint8_t i;
- APPL_TRACE_DEBUG("%s", __func__);
+ VLOG(1) << __func__;
if (bta_gattc_cb.state != BTA_GATTC_STATE_ENABLED) {
- APPL_TRACE_ERROR("not enabled, or disabled in progress");
+ LOG(ERROR) << "not enabled, or disabled in progress";
return;
}
for (i = 0; i < BTA_GATTC_CL_MAX; i++) {
- if (bta_gattc_cb.cl_rcb[i].in_use) {
- bta_gattc_cb.state = BTA_GATTC_STATE_DISABLING;
+ if (!bta_gattc_cb.cl_rcb[i].in_use) continue;
+
+ bta_gattc_cb.state = BTA_GATTC_STATE_DISABLING;
/* don't deregister HH GATT IF */
/* HH GATT IF will be deregistered by bta_hh_le_deregister when disable HH */
#if (BTA_HH_LE_INCLUDED == TRUE)
- if (!bta_hh_le_is_hh_gatt_if(bta_gattc_cb.cl_rcb[i].client_if)) {
+ if (!bta_hh_le_is_hh_gatt_if(bta_gattc_cb.cl_rcb[i].client_if)) {
#endif
- bta_gattc_deregister(&bta_gattc_cb.cl_rcb[i]);
+ bta_gattc_deregister(&bta_gattc_cb.cl_rcb[i]);
#if (BTA_HH_LE_INCLUDED == TRUE)
- }
-#endif
}
+#endif
}
/* no registered apps, indicate disable completed */
if (bta_gattc_cb.state != BTA_GATTC_STATE_DISABLING) {
- memset(&bta_gattc_cb, 0, sizeof(tBTA_GATTC_CB));
+ bta_gattc_cb = tBTA_GATTC_CB();
bta_gattc_cb.state = BTA_GATTC_STATE_DISABLED;
}
}
@@ -161,7 +159,7 @@
/** start an application interface */
void bta_gattc_start_if(uint8_t client_if) {
if (!bta_gattc_cl_get_regcb(client_if)) {
- APPL_TRACE_ERROR("Unable to start app.: Unknown interface =%d", client_if);
+ LOG(ERROR) << "Unable to start app.: Unknown client_if=" << +client_if;
return;
}
@@ -169,11 +167,11 @@
}
/** Register a GATT client application with BTA */
-void bta_gattc_register(tBT_UUID* p_app_uuid, tBTA_GATTC_CBACK* p_cback,
+void bta_gattc_register(const Uuid& app_uuid, tBTA_GATTC_CBACK* p_cback,
BtaAppRegisterCallback cb) {
- tBTA_GATT_STATUS status = BTA_GATT_NO_RESOURCES;
+ tGATT_STATUS status = GATT_NO_RESOURCES;
uint8_t client_if = 0;
- APPL_TRACE_DEBUG("%s: state %d", __func__, bta_gattc_cb.state);
+ VLOG(1) << __func__ << ": state:" << +bta_gattc_cb.state;
/* check if GATTC module is already enabled . Else enable */
if (bta_gattc_cb.state == BTA_GATTC_STATE_DISABLED) {
@@ -182,22 +180,21 @@
/* todo need to check duplicate uuid */
for (uint8_t i = 0; i < BTA_GATTC_CL_MAX; i++) {
if (!bta_gattc_cb.cl_rcb[i].in_use) {
- if ((p_app_uuid == NULL) ||
- (bta_gattc_cb.cl_rcb[i].client_if =
- GATT_Register(p_app_uuid, &bta_gattc_cl_cback)) == 0) {
- APPL_TRACE_ERROR("Register with GATT stack failed.");
- status = BTA_GATT_ERROR;
+ if ((bta_gattc_cb.cl_rcb[i].client_if =
+ GATT_Register(app_uuid, &bta_gattc_cl_cback)) == 0) {
+ LOG(ERROR) << "Register with GATT stack failed.";
+ status = GATT_ERROR;
} else {
bta_gattc_cb.cl_rcb[i].in_use = true;
bta_gattc_cb.cl_rcb[i].p_cback = p_cback;
- memcpy(&bta_gattc_cb.cl_rcb[i].app_uuid, p_app_uuid, sizeof(tBT_UUID));
+ bta_gattc_cb.cl_rcb[i].app_uuid = app_uuid;
/* BTA use the same client interface as BTE GATT statck */
client_if = bta_gattc_cb.cl_rcb[i].client_if;
do_in_bta_thread(FROM_HERE, base::Bind(&bta_gattc_start_if, client_if));
- status = BTA_GATT_OK;
+ status = GATT_SUCCESS;
break;
}
}
@@ -206,202 +203,150 @@
if (!cb.is_null()) cb.Run(client_if, status);
}
-/*******************************************************************************
- *
- * Function bta_gattc_deregister
- *
- * Description De-Register a GATT client application with BTA.
- *
- * Returns void
- *
- ******************************************************************************/
+/** De-Register a GATT client application with BTA */
void bta_gattc_deregister(tBTA_GATTC_RCB* p_clreg) {
- uint8_t i;
- BT_HDR buf;
-
- if (p_clreg != NULL) {
- /* remove bg connection associated with this rcb */
- for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i++) {
- if (bta_gattc_cb.bg_track[i].in_use) {
- if (bta_gattc_cb.bg_track[i].cif_mask &
- (1 << (p_clreg->client_if - 1))) {
- bta_gattc_mark_bg_conn(p_clreg->client_if,
- bta_gattc_cb.bg_track[i].remote_bda, false);
- GATT_CancelConnect(p_clreg->client_if,
- bta_gattc_cb.bg_track[i].remote_bda, false);
- }
- }
- }
-
- if (p_clreg->num_clcb > 0) {
- /* close all CLCB related to this app */
- for (i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
- if (bta_gattc_cb.clcb[i].in_use &&
- (bta_gattc_cb.clcb[i].p_rcb == p_clreg)) {
- p_clreg->dereg_pending = true;
-
- buf.event = BTA_GATTC_API_CLOSE_EVT;
- buf.layer_specific = bta_gattc_cb.clcb[i].bta_conn_id;
- bta_gattc_close(&bta_gattc_cb.clcb[i], (tBTA_GATTC_DATA*)&buf);
- }
- }
- } else
- bta_gattc_deregister_cmpl(p_clreg);
- } else {
- APPL_TRACE_ERROR("%s: Deregister Failed unknown client cif", __func__);
+ if (!p_clreg) {
+ LOG(ERROR) << __func__ << ": Deregister Failed unknown client cif";
bta_hh_cleanup_disable(BTA_HH_OK);
+ return;
+ }
+
+ /* remove bg connection associated with this rcb */
+ for (uint8_t i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i++) {
+ if (!bta_gattc_cb.bg_track[i].in_use) continue;
+
+ if (bta_gattc_cb.bg_track[i].cif_mask & (1 << (p_clreg->client_if - 1))) {
+ bta_gattc_mark_bg_conn(p_clreg->client_if,
+ bta_gattc_cb.bg_track[i].remote_bda, false);
+ GATT_CancelConnect(p_clreg->client_if,
+ bta_gattc_cb.bg_track[i].remote_bda, false);
+ }
+ }
+
+ if (p_clreg->num_clcb == 0) {
+ bta_gattc_deregister_cmpl(p_clreg);
+ return;
+ }
+
+ /* close all CLCB related to this app */
+ for (uint8_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
+ if (!bta_gattc_cb.clcb[i].in_use || (bta_gattc_cb.clcb[i].p_rcb != p_clreg))
+ continue;
+
+ p_clreg->dereg_pending = true;
+
+ BT_HDR buf;
+ buf.event = BTA_GATTC_API_CLOSE_EVT;
+ buf.layer_specific = bta_gattc_cb.clcb[i].bta_conn_id;
+ bta_gattc_close(&bta_gattc_cb.clcb[i], (tBTA_GATTC_DATA*)&buf);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_process_api_open
- *
- * Description process connect API request.
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** process connect API request */
void bta_gattc_process_api_open(tBTA_GATTC_DATA* p_msg) {
uint16_t event = ((BT_HDR*)p_msg)->event;
- tBTA_GATTC_CLCB* p_clcb = NULL;
+
tBTA_GATTC_RCB* p_clreg = bta_gattc_cl_get_regcb(p_msg->api_conn.client_if);
+ if (!p_clreg) {
+ LOG(ERROR) << __func__
+ << ": Failed, unknown client_if=" << +p_msg->api_conn.client_if;
+ return;
+ }
- if (p_clreg != NULL) {
- if (p_msg->api_conn.is_direct) {
- p_clcb = bta_gattc_find_alloc_clcb(p_msg->api_conn.client_if,
- p_msg->api_conn.remote_bda,
- p_msg->api_conn.transport);
- if (p_clcb != NULL) {
- bta_gattc_sm_execute(p_clcb, event, p_msg);
- } else {
- APPL_TRACE_ERROR("No resources to open a new connection.");
+ if (!p_msg->api_conn.is_direct) {
+ bta_gattc_init_bk_conn(&p_msg->api_conn, p_clreg);
+ return;
+ }
- bta_gattc_send_open_cback(
- p_clreg, BTA_GATT_NO_RESOURCES, p_msg->api_conn.remote_bda,
- BTA_GATT_INVALID_CONN_ID, p_msg->api_conn.transport, 0);
- }
- } else {
- bta_gattc_init_bk_conn(&p_msg->api_conn, p_clreg);
- }
+ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_alloc_clcb(
+ p_msg->api_conn.client_if, p_msg->api_conn.remote_bda,
+ p_msg->api_conn.transport);
+ if (p_clcb != NULL) {
+ bta_gattc_sm_execute(p_clcb, event, p_msg);
} else {
- APPL_TRACE_ERROR("%s: Failed, unknown client_if: %d", __func__,
- p_msg->api_conn.client_if);
+ LOG(ERROR) << "No resources to open a new connection.";
+
+ bta_gattc_send_open_cback(p_clreg, GATT_NO_RESOURCES,
+ p_msg->api_conn.remote_bda, GATT_INVALID_CONN_ID,
+ p_msg->api_conn.transport, 0);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_process_api_open_cancel
- *
- * Description process connect API request.
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** process connect API request */
void bta_gattc_process_api_open_cancel(tBTA_GATTC_DATA* p_msg) {
uint16_t event = ((BT_HDR*)p_msg)->event;
- tBTA_GATTC_CLCB* p_clcb = NULL;
- tBTA_GATTC_RCB* p_clreg;
- tBTA_GATTC cb_data;
- if (p_msg->api_cancel_conn.is_direct) {
- p_clcb = bta_gattc_find_clcb_by_cif(p_msg->api_cancel_conn.client_if,
- p_msg->api_cancel_conn.remote_bda,
- BTA_GATT_TRANSPORT_LE);
- if (p_clcb != NULL) {
- bta_gattc_sm_execute(p_clcb, event, p_msg);
- } else {
- APPL_TRACE_ERROR("No such connection need to be cancelled");
-
- p_clreg = bta_gattc_cl_get_regcb(p_msg->api_cancel_conn.client_if);
-
- if (p_clreg && p_clreg->p_cback) {
- cb_data.status = BTA_GATT_ERROR;
- (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
- }
- }
- } else {
+ if (!p_msg->api_cancel_conn.is_direct) {
bta_gattc_cancel_bk_conn(&p_msg->api_cancel_conn);
+ return;
+ }
+
+ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_cif(
+ p_msg->api_cancel_conn.client_if, p_msg->api_cancel_conn.remote_bda,
+ GATT_TRANSPORT_LE);
+ if (p_clcb != NULL) {
+ bta_gattc_sm_execute(p_clcb, event, p_msg);
+ return;
+ }
+
+ LOG(ERROR) << "No such connection need to be cancelled";
+
+ tBTA_GATTC_RCB* p_clreg =
+ bta_gattc_cl_get_regcb(p_msg->api_cancel_conn.client_if);
+
+ if (p_clreg && p_clreg->p_cback) {
+ tBTA_GATTC cb_data;
+ cb_data.status = GATT_ERROR;
+ (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
}
/** process encryption complete message */
void bta_gattc_process_enc_cmpl(tGATT_IF client_if, const RawAddress& bda) {
- tBTA_GATTC_RCB* p_clreg;
+ tBTA_GATTC_RCB* p_clreg = bta_gattc_cl_get_regcb(client_if);
+
+ if (!p_clreg || !p_clreg->p_cback) return;
+
tBTA_GATTC cb_data;
+ memset(&cb_data, 0, sizeof(tBTA_GATTC));
- p_clreg = bta_gattc_cl_get_regcb(client_if);
+ cb_data.enc_cmpl.client_if = client_if;
+ cb_data.enc_cmpl.remote_bda = bda;
- if (p_clreg && p_clreg->p_cback) {
- memset(&cb_data, 0, sizeof(tBTA_GATTC));
-
- cb_data.enc_cmpl.client_if = client_if;
- cb_data.enc_cmpl.remote_bda = bda;
-
- (*p_clreg->p_cback)(BTA_GATTC_ENC_CMPL_CB_EVT, &cb_data);
- }
+ (*p_clreg->p_cback)(BTA_GATTC_ENC_CMPL_CB_EVT, &cb_data);
}
-/*******************************************************************************
- *
- * Function bta_gattc_cancel_open_error
- *
- * Description
- *
- * Returns void
- *
- ******************************************************************************/
void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB* p_clcb,
UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
tBTA_GATTC cb_data;
- cb_data.status = BTA_GATT_ERROR;
+ cb_data.status = GATT_ERROR;
if (p_clcb && p_clcb->p_rcb && p_clcb->p_rcb->p_cback)
(*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
-/*******************************************************************************
- *
- * Function bta_gattc_open_error
- *
- * Description
- *
- * Returns void
- *
- ******************************************************************************/
void bta_gattc_open_error(tBTA_GATTC_CLCB* p_clcb,
UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
- APPL_TRACE_ERROR("Connection already opened. wrong state");
+ LOG(ERROR) << "Connection already opened. wrong state";
- bta_gattc_send_open_cback(p_clcb->p_rcb, BTA_GATT_OK, p_clcb->bda,
+ bta_gattc_send_open_cback(p_clcb->p_rcb, GATT_SUCCESS, p_clcb->bda,
p_clcb->bta_conn_id, p_clcb->transport, 0);
}
-/*******************************************************************************
- *
- * Function bta_gattc_open_fail
- *
- * Description
- *
- * Returns void
- *
- ******************************************************************************/
+
void bta_gattc_open_fail(tBTA_GATTC_CLCB* p_clcb,
UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
- bta_gattc_send_open_cback(p_clcb->p_rcb, BTA_GATT_ERROR, p_clcb->bda,
+ LOG(WARNING) << __func__ << ": Cannot establish Connection. conn_id="
+ << +p_clcb->bta_conn_id << ". Return GATT_ERROR(" << +GATT_ERROR
+ << ")";
+
+ bta_gattc_send_open_cback(p_clcb->p_rcb, GATT_ERROR, p_clcb->bda,
p_clcb->bta_conn_id, p_clcb->transport, 0);
/* open failure, remove clcb */
bta_gattc_clcb_dealloc(p_clcb);
}
-/*******************************************************************************
- *
- * Function bta_gattc_open
- *
- * Description Process API connection function.
- *
- * Returns void
- *
- ******************************************************************************/
+/** Process API connection function */
void bta_gattc_open(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
tBTA_GATTC_DATA gattc_data;
@@ -409,91 +354,72 @@
if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda, true,
p_data->api_conn.transport, p_data->api_conn.opportunistic,
p_data->api_conn.initiating_phys)) {
- APPL_TRACE_ERROR("Connection open failure");
+ LOG(ERROR) << "Connection open failure";
bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_OPEN_FAIL_EVT, p_data);
- } else {
- /* a connected remote device */
- if (GATT_GetConnIdIfConnected(
- p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda,
- &p_clcb->bta_conn_id, p_data->api_conn.transport)) {
- gattc_data.int_conn.hdr.layer_specific = p_clcb->bta_conn_id;
-
- bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
- }
- /* else wait for the callback event */
+ return;
}
+
+ /* a connected remote device */
+ if (GATT_GetConnIdIfConnected(
+ p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda,
+ &p_clcb->bta_conn_id, p_data->api_conn.transport)) {
+ gattc_data.int_conn.hdr.layer_specific = p_clcb->bta_conn_id;
+
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
+ }
+ /* else wait for the callback event */
}
-/*******************************************************************************
- *
- * Function bta_gattc_init_bk_conn
- *
- * Description Process API Open for a background connection
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** Process API Open for a background connection */
void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN* p_data,
tBTA_GATTC_RCB* p_clreg) {
- tBTA_GATT_STATUS status = BTA_GATT_NO_RESOURCES;
+ if (!bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, true)) {
+ bta_gattc_send_open_cback(p_clreg, GATT_NO_RESOURCES, p_data->remote_bda,
+ GATT_INVALID_CONN_ID, GATT_TRANSPORT_LE, 0);
+ return;
+ }
+
+ /* always call open to hold a connection */
+ if (!GATT_Connect(p_data->client_if, p_data->remote_bda, false,
+ p_data->transport, false)) {
+ LOG(ERROR) << __func__
+ << " unable to connect to remote bd_addr=" << p_data->remote_bda;
+ bta_gattc_send_open_cback(p_clreg, GATT_ERROR, p_data->remote_bda,
+ GATT_INVALID_CONN_ID, GATT_TRANSPORT_LE, 0);
+ return;
+ }
+
uint16_t conn_id;
- tBTA_GATTC_CLCB* p_clcb;
+ /* if is not a connected remote device */
+ if (!GATT_GetConnIdIfConnected(p_data->client_if, p_data->remote_bda,
+ &conn_id, p_data->transport)) {
+ return;
+ }
+
+ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_alloc_clcb(
+ p_data->client_if, p_data->remote_bda, GATT_TRANSPORT_LE);
+ if (!p_clcb) return;
+
tBTA_GATTC_DATA gattc_data;
+ gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
- if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, true)) {
- /* always call open to hold a connection */
- if (!GATT_Connect(p_data->client_if, p_data->remote_bda, false,
- p_data->transport, false)) {
- status = BTA_GATT_ERROR;
- LOG(ERROR) << __func__ << " unable to connect to remote bd_addr:"
- << p_data->remote_bda;
-
- } else {
- status = BTA_GATT_OK;
-
- /* if is a connected remote device */
- if (GATT_GetConnIdIfConnected(p_data->client_if, p_data->remote_bda,
- &conn_id, p_data->transport)) {
- p_clcb = bta_gattc_find_alloc_clcb(
- p_data->client_if, p_data->remote_bda, BTA_GATT_TRANSPORT_LE);
- if (p_clcb != NULL) {
- gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
-
- /* open connection */
- bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
- status = BTA_GATT_OK;
- }
- }
- }
- }
-
- /* open failure, report OPEN_EVT */
- if (status != BTA_GATT_OK) {
- bta_gattc_send_open_cback(p_clreg, status, p_data->remote_bda,
- BTA_GATT_INVALID_CONN_ID, BTA_GATT_TRANSPORT_LE,
- 0);
- }
+ /* open connection */
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
}
-/*******************************************************************************
- *
- * Function bta_gattc_cancel_bk_conn
- *
- * Description Process API Cancel Open for a background connection
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** Process API Cancel Open for a background connection */
void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN* p_data) {
tBTA_GATTC_RCB* p_clreg;
tBTA_GATTC cb_data;
- cb_data.status = BTA_GATT_ERROR;
+ cb_data.status = GATT_ERROR;
/* remove the device from the bg connection mask */
if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, false)) {
if (GATT_CancelConnect(p_data->client_if, p_data->remote_bda, false)) {
- cb_data.status = BTA_GATT_OK;
+ cb_data.status = GATT_SUCCESS;
} else {
- APPL_TRACE_ERROR("%s: failed", __func__);
+ LOG(ERROR) << __func__ << ": failed";
}
}
p_clreg = bta_gattc_cl_get_regcb(p_data->client_if);
@@ -502,35 +428,19 @@
(*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_int_cancel_open_ok
- *
- * Description
- *
- * Returns void
- *
- ******************************************************************************/
+
void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB* p_clcb,
UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
tBTA_GATTC cb_data;
if (p_clcb->p_rcb->p_cback) {
- cb_data.status = BTA_GATT_OK;
+ cb_data.status = GATT_SUCCESS;
(*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
bta_gattc_clcb_dealloc(p_clcb);
}
-/*******************************************************************************
- *
- * Function bta_gattc_cancel_open
- *
- * Description
- *
- * Returns void
- *
- ******************************************************************************/
+
void bta_gattc_cancel_open(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
tBTA_GATTC cb_data;
@@ -539,27 +449,19 @@
bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CANCEL_OPEN_OK_EVT, p_data);
} else {
if (p_clcb->p_rcb->p_cback) {
- cb_data.status = BTA_GATT_ERROR;
+ cb_data.status = GATT_ERROR;
(*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_conn
- *
- * Description receive connection callback from stack
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** receive connection callback from stack */
void bta_gattc_conn(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
- tBTA_GATTC_IF gatt_if;
- APPL_TRACE_DEBUG("%s: server cache state=%d", __func__,
- p_clcb->p_srcb->state);
+ tGATT_IF gatt_if;
+ VLOG(1) << __func__ << ": server cache state=" << +p_clcb->p_srcb->state;
if (p_data != NULL) {
- APPL_TRACE_DEBUG("%s: conn_id=%d", __func__, p_data->hdr.layer_specific);
+ VLOG(1) << __func__ << ": conn_id=" << +p_data->hdr.layer_specific;
p_clcb->bta_conn_id = p_data->int_conn.hdr.layer_specific;
GATT_GetConnectionInfor(p_data->hdr.layer_specific, &gatt_if, p_clcb->bda,
@@ -571,13 +473,13 @@
if (p_clcb->p_srcb->mtu == 0) p_clcb->p_srcb->mtu = GATT_DEF_BLE_MTU_SIZE;
/* start database cache if needed */
- if (p_clcb->p_srcb->p_srvc_cache == NULL ||
+ if (p_clcb->p_srcb->srvc_cache.empty() ||
p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE) {
if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) {
p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
if (bta_gattc_cache_load(p_clcb)) {
p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
- bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
+ bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
} else {
p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
/* cache load failure, start discovery */
@@ -601,20 +503,13 @@
if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
bta_sys_conn_open(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
- bta_gattc_send_open_cback(p_clcb->p_rcb, BTA_GATT_OK, p_clcb->bda,
+ bta_gattc_send_open_cback(p_clcb->p_rcb, GATT_SUCCESS, p_clcb->bda,
p_clcb->bta_conn_id, p_clcb->transport,
p_clcb->p_srcb->mtu);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_close_fail
- *
- * Description close a connection.
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** close a connection */
void bta_gattc_close_fail(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
tBTA_GATTC cb_data;
@@ -623,27 +518,23 @@
cb_data.close.client_if = p_clcb->p_rcb->client_if;
cb_data.close.conn_id = p_data->hdr.layer_specific;
cb_data.close.remote_bda = p_clcb->bda;
- cb_data.close.status = BTA_GATT_ERROR;
+ cb_data.close.status = GATT_ERROR;
cb_data.close.reason = BTA_GATT_CONN_NONE;
+ LOG(WARNING) << __func__ << ": conn_id=" << loghex(cb_data.close.conn_id)
+ << ". Returns GATT_ERROR(" << +GATT_ERROR << ").";
+
(*p_clcb->p_rcb->p_cback)(BTA_GATTC_CLOSE_EVT, &cb_data);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_api_close
- *
- * Description close a GATTC connection.
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** close a GATTC connection */
void bta_gattc_close(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
tBTA_GATTC_CBACK* p_cback = p_clcb->p_rcb->p_cback;
tBTA_GATTC_RCB* p_clreg = p_clcb->p_rcb;
tBTA_GATTC cb_data;
- APPL_TRACE_DEBUG("%s: conn_id=%d", __func__, p_clcb->bta_conn_id);
+ VLOG(1) << __func__ << ": conn_id=" << +p_clcb->bta_conn_id;
cb_data.close.client_if = p_clcb->p_rcb->client_if;
cb_data.close.conn_id = p_clcb->bta_conn_id;
@@ -669,20 +560,10 @@
bta_gattc_deregister_cmpl(p_clreg);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_reset_discover_st
- *
- * Description when a SRCB finished discovery, tell all related clcb.
- *
- * Returns None.
- *
- ******************************************************************************/
-void bta_gattc_reset_discover_st(tBTA_GATTC_SERV* p_srcb,
- tBTA_GATT_STATUS status) {
- uint8_t i;
- for (i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
+/** when a SRCB finished discovery, tell all related clcb */
+void bta_gattc_reset_discover_st(tBTA_GATTC_SERV* p_srcb, tGATT_STATUS status) {
+ for (uint8_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
if (bta_gattc_cb.clcb[i].p_srcb == p_srcb) {
bta_gattc_cb.clcb[i].status = status;
bta_gattc_sm_execute(&bta_gattc_cb.clcb[i], BTA_GATTC_DISCOVER_CMPL_EVT,
@@ -690,21 +571,13 @@
}
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_disc_close
- *
- * Description close a GATTC connection while in discovery state.
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** close a GATTC connection while in discovery state */
void bta_gattc_disc_close(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
- APPL_TRACE_DEBUG("%s: Discovery cancel conn_id=%d", __func__,
- p_clcb->bta_conn_id);
+ VLOG(1) << __func__ << ": Discovery cancel conn_id=" << +p_clcb->bta_conn_id;
if (p_clcb->disc_active)
- bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_ERROR);
+ bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR);
else
p_clcb->state = BTA_GATTC_CONN_ST;
@@ -712,88 +585,55 @@
// while in the BTA_GATTC_DISCOVER_ST state. Once the state changes, the
// connection itself still needs to be closed to resolve the original event.
if (p_clcb->state == BTA_GATTC_CONN_ST) {
- APPL_TRACE_DEBUG(
- "State is back to BTA_GATTC_CONN_ST. "
- "Trigger connection close");
+ VLOG(1) << "State is back to BTA_GATTC_CONN_ST. Trigger connection close";
bta_gattc_close(p_clcb, p_data);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_set_discover_st
- *
- * Description when a SRCB start discovery, tell all related clcb and set
- * the state.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** when a SRCB start discovery, tell all related clcb and set the state */
void bta_gattc_set_discover_st(tBTA_GATTC_SERV* p_srcb) {
uint8_t i;
L2CA_EnableUpdateBleConnParams(p_srcb->server_bda, false);
for (i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
if (bta_gattc_cb.clcb[i].p_srcb == p_srcb) {
- bta_gattc_cb.clcb[i].status = BTA_GATT_OK;
+ bta_gattc_cb.clcb[i].status = GATT_SUCCESS;
bta_gattc_cb.clcb[i].state = BTA_GATTC_DISCOVER_ST;
}
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_restart_discover
- *
- * Description process service change in discovery state, mark up the auto
- * update flag and set status to be discovery cancel for
- * current discovery.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** process service change in discovery state, mark up the auto update flag and
+ * set status to be discovery cancel for current discovery.
+ */
void bta_gattc_restart_discover(tBTA_GATTC_CLCB* p_clcb,
UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
- p_clcb->status = BTA_GATT_CANCEL;
+ p_clcb->status = GATT_CANCEL;
p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
}
-/*******************************************************************************
- *
- * Function bta_gattc_cfg_mtu
- *
- * Description Configure MTU size on the GATT connection.
- *
- * Returns None.
- *
- ******************************************************************************/
+/** Configure MTU size on the GATT connection */
void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
- tBTA_GATT_STATUS status;
+ if (!bta_gattc_enqueue(p_clcb, p_data)) return;
- if (bta_gattc_enqueue(p_clcb, p_data)) {
- status = GATTC_ConfigureMTU(p_clcb->bta_conn_id, p_data->api_mtu.mtu);
+ tGATT_STATUS status =
+ GATTC_ConfigureMTU(p_clcb->bta_conn_id, p_data->api_mtu.mtu);
- /* if failed, return callback here */
- if (status != GATT_SUCCESS && status != GATT_CMD_STARTED) {
- /* Dequeue the data, if it was enqueued */
- if (p_clcb->p_q_cmd == p_data) p_clcb->p_q_cmd = NULL;
+ /* if failed, return callback here */
+ if (status != GATT_SUCCESS && status != GATT_CMD_STARTED) {
+ /* Dequeue the data, if it was enqueued */
+ if (p_clcb->p_q_cmd == p_data) p_clcb->p_q_cmd = NULL;
- bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_CONFIG, status,
- NULL);
- }
+ bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_CONFIG, status,
+ NULL);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_start_discover
- *
- * Description Start a discovery on server.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** Start a discovery on server */
void bta_gattc_start_discover(tBTA_GATTC_CLCB* p_clcb,
UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
- APPL_TRACE_DEBUG("%s: conn_id=%d p_clcb->p_srcb->state = %d ", __func__,
- p_clcb->bta_conn_id, p_clcb->p_srcb->state);
+ VLOG(1) << __func__ << ": conn_id:" << +p_clcb->bta_conn_id
+ << " p_clcb->p_srcb->state:" << +p_clcb->p_srcb->state;
if (((p_clcb->p_q_cmd == NULL ||
p_clcb->auto_update == BTA_GATTC_REQ_WAITING) &&
@@ -816,17 +656,17 @@
bta_gattc_set_discover_st(p_clcb->p_srcb);
p_clcb->status = bta_gattc_init_cache(p_clcb->p_srcb);
- if (p_clcb->status == BTA_GATT_OK) {
+ if (p_clcb->status == GATT_SUCCESS) {
p_clcb->status = bta_gattc_discover_pri_service(
p_clcb->bta_conn_id, p_clcb->p_srcb, GATT_DISC_SRVC_ALL);
}
- if (p_clcb->status != BTA_GATT_OK) {
- APPL_TRACE_ERROR("discovery on server failed");
+ if (p_clcb->status != GATT_SUCCESS) {
+ LOG(ERROR) << "discovery on server failed";
bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
} else
p_clcb->disc_active = true;
} else {
- APPL_TRACE_ERROR("unknown device, can not start discovery");
+ LOG(ERROR) << "unknown device, can not start discovery";
}
}
/* pending operation, wait until it finishes */
@@ -837,20 +677,13 @@
p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_disc_cmpl
- *
- * Description discovery on server is finished
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** discovery on server is finished */
void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB* p_clcb,
UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
tBTA_GATTC_DATA* p_q_cmd = p_clcb->p_q_cmd;
- APPL_TRACE_DEBUG("%s: conn_id=%d", __func__, p_clcb->bta_conn_id);
+ VLOG(1) << __func__ << ": conn_id=" << +p_clcb->bta_conn_id;
if (p_clcb->transport == BTA_TRANSPORT_LE)
L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, true);
@@ -859,17 +692,17 @@
if (p_clcb->status != GATT_SUCCESS) {
/* clean up cache */
- if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache) {
- list_free(p_clcb->p_srcb->p_srvc_cache);
- p_clcb->p_srcb->p_srvc_cache = NULL;
+ if (p_clcb->p_srcb) {
+ // clear reallocating
+ std::vector<tBTA_GATTC_SERVICE>().swap(p_clcb->p_srcb->srvc_cache);
}
/* used to reset cache in application */
bta_gattc_cache_reset(p_clcb->p_srcb->server_bda);
}
- if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_list) {
+ if (p_clcb->p_srcb) {
/* release pending attribute list buffer */
- osi_free_and_reset((void**)&p_clcb->p_srcb->p_srvc_list);
+ p_clcb->p_srcb->pending_discovery.clear();
}
if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING) {
@@ -881,7 +714,8 @@
else if (p_q_cmd != NULL) {
p_clcb->p_q_cmd = NULL;
/* execute pending operation of link block still present */
- if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda, BT_TRANSPORT_LE)) {
+ if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda,
+ p_clcb->transport)) {
bta_gattc_sm_execute(p_clcb, p_q_cmd->hdr.event, p_q_cmd);
}
/* if the command executed requeued the cmd, we don't
@@ -891,19 +725,12 @@
if (p_q_cmd != p_clcb->p_q_cmd) osi_free_and_reset((void**)&p_q_cmd);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_read
- *
- * Description Read an attribute
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** Read an attribute */
void bta_gattc_read(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
if (!bta_gattc_enqueue(p_clcb, p_data)) return;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
if (p_data->api_read.handle != 0) {
tGATT_READ_PARAM read_param;
memset(&read_param, 0, sizeof(tGATT_READ_PARAM));
@@ -922,7 +749,7 @@
}
/* read fail */
- if (status != BTA_GATT_OK) {
+ if (status != GATT_SUCCESS) {
/* Dequeue the data, if it was enqueued */
if (p_clcb->p_q_cmd == p_data) p_clcb->p_q_cmd = NULL;
@@ -930,53 +757,36 @@
NULL);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_read_multi
- *
- * Description read multiple
- *
- * Returns None.
- ******************************************************************************/
+
+/** read multiple */
void bta_gattc_read_multi(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
- tBTA_GATT_STATUS status = BTA_GATT_OK;
+ if (!bta_gattc_enqueue(p_clcb, p_data)) return;
+
tGATT_READ_PARAM read_param;
+ memset(&read_param, 0, sizeof(tGATT_READ_PARAM));
- if (bta_gattc_enqueue(p_clcb, p_data)) {
- memset(&read_param, 0, sizeof(tGATT_READ_PARAM));
+ read_param.read_multiple.num_handles = p_data->api_read_multi.num_attr;
+ read_param.read_multiple.auth_req = p_data->api_read_multi.auth_req;
+ memcpy(&read_param.read_multiple.handles, p_data->api_read_multi.handles,
+ sizeof(uint16_t) * p_data->api_read_multi.num_attr);
- if (status == BTA_GATT_OK) {
- read_param.read_multiple.num_handles = p_data->api_read_multi.num_attr;
- read_param.read_multiple.auth_req = p_data->api_read_multi.auth_req;
- memcpy(&read_param.read_multiple.handles, p_data->api_read_multi.handles,
- sizeof(uint16_t) * p_data->api_read_multi.num_attr);
+ tGATT_STATUS status =
+ GATTC_Read(p_clcb->bta_conn_id, GATT_READ_MULTIPLE, &read_param);
+ /* read fail */
+ if (status != GATT_SUCCESS) {
+ /* Dequeue the data, if it was enqueued */
+ if (p_clcb->p_q_cmd == p_data) p_clcb->p_q_cmd = NULL;
- status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_MULTIPLE, &read_param);
- }
-
- /* read fail */
- if (status != BTA_GATT_OK) {
- /* Dequeue the data, if it was enqueued */
- if (p_clcb->p_q_cmd == p_data) p_clcb->p_q_cmd = NULL;
-
- bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status,
- NULL);
- }
+ bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status,
+ NULL);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_write
- *
- * Description Write an attribute
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** Write an attribute */
void bta_gattc_write(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
if (!bta_gattc_enqueue(p_clcb, p_data)) return;
- tBTA_GATT_STATUS status = BTA_GATT_OK;
+ tGATT_STATUS status = GATT_SUCCESS;
tGATT_VALUE attr;
attr.conn_id = p_clcb->bta_conn_id;
@@ -992,7 +802,7 @@
GATTC_Write(p_clcb->bta_conn_id, p_data->api_write.write_type, &attr);
/* write fail */
- if (status != BTA_GATT_OK) {
+ if (status != GATT_SUCCESS) {
/* Dequeue the data, if it was enqueued */
if (p_clcb->p_q_cmd == p_data) p_clcb->p_q_cmd = NULL;
@@ -1000,45 +810,29 @@
NULL);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_execute
- *
- * Description send execute write
- *
- * Returns None.
- ******************************************************************************/
+
+/** send execute write */
void bta_gattc_execute(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
- tBTA_GATT_STATUS status;
+ if (!bta_gattc_enqueue(p_clcb, p_data)) return;
- if (bta_gattc_enqueue(p_clcb, p_data)) {
- status =
- GATTC_ExecuteWrite(p_clcb->bta_conn_id, p_data->api_exec.is_execute);
+ tGATT_STATUS status =
+ GATTC_ExecuteWrite(p_clcb->bta_conn_id, p_data->api_exec.is_execute);
+ if (status != GATT_SUCCESS) {
+ /* Dequeue the data, if it was enqueued */
+ if (p_clcb->p_q_cmd == p_data) p_clcb->p_q_cmd = NULL;
- if (status != BTA_GATT_OK) {
- /* Dequeue the data, if it was enqueued */
- if (p_clcb->p_q_cmd == p_data) p_clcb->p_q_cmd = NULL;
-
- bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_EXE_WRITE,
- status, NULL);
- }
+ bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_EXE_WRITE, status,
+ NULL);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_confirm
- *
- * Description send handle value confirmation
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** send handle value confirmation */
void bta_gattc_confirm(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
uint16_t handle = p_data->api_confirm.handle;
if (GATTC_SendHandleValueConfirm(p_data->api_confirm.hdr.layer_specific,
handle) != GATT_SUCCESS) {
- APPL_TRACE_ERROR("%s: to handle [0x%04x] failed", __func__, handle);
+ LOG(ERROR) << __func__ << ": to handle=" << loghex(handle) << " failed";
} else {
/* if over BR_EDR, inform PM for mode change */
if (p_clcb->transport == BTA_TRANSPORT_BR_EDR) {
@@ -1047,15 +841,8 @@
}
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_read_cmpl
- *
- * Description read complete
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** read complete */
void bta_gattc_read_cmpl(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_OP_CMPL* p_data) {
GATT_READ_OP_CB cb = p_clcb->p_q_cmd->api_read.read_cb;
void* my_cb_data = p_clcb->p_q_cmd->api_read.read_cb_data;
@@ -1074,15 +861,8 @@
my_cb_data);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_write_cmpl
- *
- * Description write complete
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** write complete */
void bta_gattc_write_cmpl(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_OP_CMPL* p_data) {
GATT_WRITE_OP_CB cb = p_clcb->p_q_cmd->api_write.write_cb;
void* my_cb_data = p_clcb->p_q_cmd->api_write.write_cb_data;
@@ -1094,20 +874,13 @@
my_cb_data);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_exec_cmpl
- *
- * Description execute write complete
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** execute write complete */
void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_OP_CMPL* p_data) {
tBTA_GATTC cb_data;
osi_free_and_reset((void**)&p_clcb->p_q_cmd);
- p_clcb->status = BTA_GATT_OK;
+ p_clcb->status = GATT_SUCCESS;
/* execute complete, callback */
cb_data.exec_cmpl.conn_id = p_clcb->bta_conn_id;
@@ -1116,22 +889,14 @@
(*p_clcb->p_rcb->p_cback)(BTA_GATTC_EXEC_EVT, &cb_data);
}
-/*******************************************************************************
- *
- * Function bta_gattc_cfg_mtu_cmpl
- *
- * Description configure MTU operation complete
- *
- * Returns None.
- *
- ******************************************************************************/
+/** configure MTU operation complete */
void bta_gattc_cfg_mtu_cmpl(tBTA_GATTC_CLCB* p_clcb,
tBTA_GATTC_OP_CMPL* p_data) {
tBTA_GATTC cb_data;
osi_free_and_reset((void**)&p_clcb->p_q_cmd);
- if (p_data->p_cmpl && p_data->status == BTA_GATT_OK)
+ if (p_data->p_cmpl && p_data->status == GATT_SUCCESS)
p_clcb->p_srcb->mtu = p_data->p_cmpl->mtu;
/* configure MTU complete, callback */
@@ -1142,100 +907,83 @@
(*p_clcb->p_rcb->p_cback)(BTA_GATTC_CFG_MTU_EVT, &cb_data);
}
-/*******************************************************************************
- *
- * Function bta_gattc_op_cmpl
- *
- * Description operation completed.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** operation completed */
void bta_gattc_op_cmpl(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
uint8_t op = (uint8_t)p_data->op_cmpl.op_code;
uint8_t mapped_op = 0;
- APPL_TRACE_DEBUG("%s: op = %d", __func__, op);
+ VLOG(1) << __func__ << ": op:" << +op;
if (op == GATTC_OPTYPE_INDICATION || op == GATTC_OPTYPE_NOTIFICATION) {
- APPL_TRACE_ERROR("unexpected operation, ignored");
- } else if (op >= GATTC_OPTYPE_READ) {
- if (p_clcb->p_q_cmd == NULL) {
- APPL_TRACE_ERROR("No pending command");
- return;
- }
- if (p_clcb->p_q_cmd->hdr.event !=
- bta_gattc_opcode_to_int_evt[op - GATTC_OPTYPE_READ]) {
- mapped_op = p_clcb->p_q_cmd->hdr.event - BTA_GATTC_API_READ_EVT +
- GATTC_OPTYPE_READ;
- if (mapped_op > GATTC_OPTYPE_INDICATION) mapped_op = 0;
+ LOG(ERROR) << "unexpected operation, ignored";
+ return;
+ }
- APPL_TRACE_ERROR(
- "expect op:(%s :0x%04x), receive unexpected operation (%s).",
- bta_gattc_op_code_name[mapped_op], p_clcb->p_q_cmd->hdr.event,
- bta_gattc_op_code_name[op]);
- return;
- }
+ if (op < GATTC_OPTYPE_READ) return;
- /* Except for MTU configuration, discard responses if service change
- * indication is received before operation completed
- */
- if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING &&
- p_clcb->p_srcb->srvc_hdl_chg && op != GATTC_OPTYPE_CONFIG) {
- APPL_TRACE_DEBUG(
- "Discard all responses when service change indication is received.");
- p_data->op_cmpl.status = GATT_ERROR;
- }
+ if (p_clcb->p_q_cmd == NULL) {
+ LOG(ERROR) << "No pending command";
+ return;
+ }
- /* service handle change void the response, discard it */
- if (op == GATTC_OPTYPE_READ)
- bta_gattc_read_cmpl(p_clcb, &p_data->op_cmpl);
+ if (p_clcb->p_q_cmd->hdr.event !=
+ bta_gattc_opcode_to_int_evt[op - GATTC_OPTYPE_READ]) {
+ mapped_op =
+ p_clcb->p_q_cmd->hdr.event - BTA_GATTC_API_READ_EVT + GATTC_OPTYPE_READ;
+ if (mapped_op > GATTC_OPTYPE_INDICATION) mapped_op = 0;
- else if (op == GATTC_OPTYPE_WRITE)
- bta_gattc_write_cmpl(p_clcb, &p_data->op_cmpl);
+ LOG(ERROR) << StringPrintf(
+ "expect op:(%s :0x%04x), receive unexpected operation (%s).",
+ bta_gattc_op_code_name[mapped_op], p_clcb->p_q_cmd->hdr.event,
+ bta_gattc_op_code_name[op]);
+ return;
+ }
- else if (op == GATTC_OPTYPE_EXE_WRITE)
- bta_gattc_exec_cmpl(p_clcb, &p_data->op_cmpl);
+ /* Except for MTU configuration, discard responses if service change
+ * indication is received before operation completed
+ */
+ if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING &&
+ p_clcb->p_srcb->srvc_hdl_chg && op != GATTC_OPTYPE_CONFIG) {
+ VLOG(1) << "Discard all responses when service change indication is "
+ "received.";
+ p_data->op_cmpl.status = GATT_ERROR;
+ }
- else if (op == GATTC_OPTYPE_CONFIG)
- bta_gattc_cfg_mtu_cmpl(p_clcb, &p_data->op_cmpl);
+ /* service handle change void the response, discard it */
+ if (op == GATTC_OPTYPE_READ)
+ bta_gattc_read_cmpl(p_clcb, &p_data->op_cmpl);
- if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING) {
- p_clcb->auto_update = BTA_GATTC_REQ_WAITING;
- bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
- }
+ else if (op == GATTC_OPTYPE_WRITE)
+ bta_gattc_write_cmpl(p_clcb, &p_data->op_cmpl);
+
+ else if (op == GATTC_OPTYPE_EXE_WRITE)
+ bta_gattc_exec_cmpl(p_clcb, &p_data->op_cmpl);
+
+ else if (op == GATTC_OPTYPE_CONFIG)
+ bta_gattc_cfg_mtu_cmpl(p_clcb, &p_data->op_cmpl);
+
+ if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING) {
+ p_clcb->auto_update = BTA_GATTC_REQ_WAITING;
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_op_cmpl
- *
- * Description operation completed.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** operation completed */
void bta_gattc_ignore_op_cmpl(UNUSED_ATTR tBTA_GATTC_CLCB* p_clcb,
tBTA_GATTC_DATA* p_data) {
/* receive op complete when discovery is started, ignore the response,
and wait for discovery finish and resent */
- APPL_TRACE_DEBUG("%s: op = %d", __func__, p_data->hdr.layer_specific);
+ VLOG(1) << __func__ << ": op = " << +p_data->hdr.layer_specific;
}
-/*******************************************************************************
- *
- * Function bta_gattc_search
- *
- * Description start a search in the local server cache
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** start a search in the local server cache */
void bta_gattc_search(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
- tBTA_GATT_STATUS status = GATT_INTERNAL_ERROR;
+ tGATT_STATUS status = GATT_INTERNAL_ERROR;
tBTA_GATTC cb_data;
- APPL_TRACE_DEBUG("%s: conn_id=%d", __func__, p_clcb->bta_conn_id);
- if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache) {
- status = BTA_GATT_OK;
+ VLOG(1) << __func__ << ": conn_id=" << +p_clcb->bta_conn_id;
+ if (p_clcb->p_srcb && !p_clcb->p_srcb->srvc_cache.empty()) {
+ status = GATT_SUCCESS;
/* search the local cache of a server device */
bta_gattc_search_service(p_clcb, p_data->api_search.p_srvc_uuid);
}
@@ -1245,48 +993,24 @@
/* end of search or no server cache available */
(*p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_CMPL_EVT, &cb_data);
}
-/*******************************************************************************
- *
- * Function bta_gattc_q_cmd
- *
- * Description enqueue a command into control block, usually because
- * discovery operation is busy.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** enqueue a command into control block, usually because discovery operation is
+ * busy */
void bta_gattc_q_cmd(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
bta_gattc_enqueue(p_clcb, p_data);
}
-/*******************************************************************************
- *
- * Function bta_gattc_fail
- *
- * Description report API call failure back to apps
- *
- * Returns None.
- *
- ******************************************************************************/
+/** report API call failure back to apps */
void bta_gattc_fail(tBTA_GATTC_CLCB* p_clcb,
UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
- if (p_clcb->status == BTA_GATT_OK) {
- APPL_TRACE_ERROR("operation not supported at current state [%d]",
- p_clcb->state);
+ if (p_clcb->status == GATT_SUCCESS) {
+ LOG(ERROR) << "operation not supported at current state " << +p_clcb->state;
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_deregister_cmpl
- *
- * Description De-Register a GATT client application with BTA completed.
- *
- * Returns void
- *
- ******************************************************************************/
+/* De-Register a GATT client application with BTA completed */
static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB* p_clreg) {
- tBTA_GATTC_IF client_if = p_clreg->client_if;
+ tGATT_IF client_if = p_clreg->client_if;
tBTA_GATTC cb_data;
tBTA_GATTC_CBACK* p_cback = p_clreg->p_cback;
@@ -1296,7 +1020,7 @@
memset(p_clreg, 0, sizeof(tBTA_GATTC_RCB));
cb_data.reg_oper.client_if = client_if;
- cb_data.reg_oper.status = BTA_GATT_OK;
+ cb_data.reg_oper.status = GATT_SUCCESS;
if (p_cback) /* callback with de-register event */
(*p_cback)(BTA_GATTC_DEREG_EVT, &cb_data);
@@ -1306,22 +1030,16 @@
bta_gattc_cb.state = BTA_GATTC_STATE_DISABLED;
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_conn_cback
- *
- * Description callback functions to GATT client stack.
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** callback functions to GATT client stack */
static void bta_gattc_conn_cback(tGATT_IF gattc_if, const RawAddress& bdaddr,
uint16_t conn_id, bool connected,
tGATT_DISCONN_REASON reason,
tBT_TRANSPORT transport) {
if (reason != 0) {
- APPL_TRACE_WARNING("%s() - cif=%d connected=%d conn_id=%d reason=0x%04x",
- __func__, gattc_if, connected, conn_id, reason);
+ LOG(WARNING) << __func__ << ": cif=" << +gattc_if
+ << " connected=" << connected << " conn_id=" << loghex(conn_id)
+ << " reason=" << loghex(reason);
}
if (connected)
@@ -1343,18 +1061,10 @@
bta_sys_sendmsg(p_buf);
}
-/*******************************************************************************
- *
- * Function bta_gattc_enc_cmpl_cback
- *
- * Description encryption complete callback function to GATT client stack.
- *
- * Returns void
- *
- ******************************************************************************/
+/** encryption complete callback function to GATT client stack */
static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, const RawAddress& bda) {
tBTA_GATTC_CLCB* p_clcb =
- bta_gattc_find_clcb_by_cif(gattc_if, bda, BTA_GATT_TRANSPORT_LE);
+ bta_gattc_find_clcb_by_cif(gattc_if, bda, GATT_TRANSPORT_LE);
if (p_clcb == NULL) return;
@@ -1368,32 +1078,22 @@
}
#endif
- APPL_TRACE_DEBUG("%s: cif = %d", __func__, gattc_if);
+ VLOG(1) << __func__ << ": cif:" << +gattc_if;
do_in_bta_thread(FROM_HERE,
base::Bind(&bta_gattc_process_enc_cmpl, gattc_if, bda));
}
-/*******************************************************************************
- *
- * Function bta_gattc_process_api_refresh
- *
- * Description process refresh API to delete cache and start a new
- * discovery if currently connected.
- *
- * Returns None.
- *
- ******************************************************************************/
+/** process refresh API to delete cache and start a new discovery if currently
+ * connected */
void bta_gattc_process_api_refresh(const RawAddress& remote_bda) {
tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_srvr_cache(remote_bda);
- tBTA_GATTC_CLCB* p_clcb = &bta_gattc_cb.clcb[0];
- bool found = false;
- uint8_t i;
-
- if (p_srvc_cb != NULL) {
+ if (p_srvc_cb) {
/* try to find a CLCB */
if (p_srvc_cb->connected && p_srvc_cb->num_clcb != 0) {
- for (i = 0; i < BTA_GATTC_CLCB_MAX; i++, p_clcb++) {
+ bool found = false;
+ tBTA_GATTC_CLCB* p_clcb = &bta_gattc_cb.clcb[0];
+ for (uint8_t i = 0; i < BTA_GATTC_CLCB_MAX; i++, p_clcb++) {
if (p_clcb->in_use && p_clcb->p_srcb == p_srvc_cb) {
found = true;
break;
@@ -1405,108 +1105,91 @@
}
}
/* in all other cases, mark it and delete the cache */
- if (p_srvc_cb->p_srvc_cache != NULL) {
- list_free(p_srvc_cb->p_srvc_cache);
- p_srvc_cb->p_srvc_cache = NULL;
- }
+
+ // clear reallocating
+ std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->srvc_cache);
}
+
/* used to reset cache in application */
bta_gattc_cache_reset(remote_bda);
}
-/*******************************************************************************
- *
- * Function bta_gattc_process_srvc_chg_ind
- *
- * Description process service change indication.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** process service change indication */
bool bta_gattc_process_srvc_chg_ind(uint16_t conn_id, tBTA_GATTC_RCB* p_clrcb,
tBTA_GATTC_SERV* p_srcb,
tBTA_GATTC_CLCB* p_clcb,
tBTA_GATTC_NOTIFY* p_notify,
tGATT_VALUE* att_value) {
- tBT_UUID gattp_uuid, srvc_chg_uuid;
- bool processed = false;
- uint8_t i;
- gattp_uuid.len = 2;
- gattp_uuid.uu.uuid16 = UUID_SERVCLASS_GATT_SERVER;
-
- srvc_chg_uuid.len = 2;
- srvc_chg_uuid.uu.uuid16 = GATT_UUID_GATT_SRV_CHGD;
+ Uuid gattp_uuid = Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER);
+ Uuid srvc_chg_uuid = Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD);
const tBTA_GATTC_CHARACTERISTIC* p_char =
bta_gattc_get_characteristic_srcb(p_srcb, p_notify->handle);
- if (p_char &&
- bta_gattc_uuid_compare(&p_char->service->uuid, &gattp_uuid, true) &&
- bta_gattc_uuid_compare(&p_char->uuid, &srvc_chg_uuid, true)) {
- if (att_value->len != BTA_GATTC_SERVICE_CHANGED_LEN) {
- APPL_TRACE_ERROR(
- "%s: received malformed service changed indication, skipping",
- __func__);
- return false;
- }
-
- uint8_t* p = att_value->value;
- uint16_t s_handle = ((uint16_t)(*(p)) + (((uint16_t)(*(p + 1))) << 8));
- uint16_t e_handle = ((uint16_t)(*(p + 2)) + (((uint16_t)(*(p + 3))) << 8));
-
- APPL_TRACE_ERROR("%s: service changed s_handle:0x%04x e_handle:0x%04x",
- __func__, s_handle, e_handle);
-
- processed = true;
- /* mark service handle change pending */
- p_srcb->srvc_hdl_chg = true;
- /* clear up all notification/indication registration */
- bta_gattc_clear_notif_registration(p_srcb, conn_id, s_handle, e_handle);
- /* service change indication all received, do discovery update */
- if (++p_srcb->update_count == bta_gattc_num_reg_app()) {
- /* not an opened connection; or connection busy */
- /* search for first available clcb and start discovery */
- if (p_clcb == NULL || (p_clcb && p_clcb->p_q_cmd != NULL)) {
- for (i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
- if (bta_gattc_cb.clcb[i].in_use &&
- bta_gattc_cb.clcb[i].p_srcb == p_srcb &&
- bta_gattc_cb.clcb[i].p_q_cmd == NULL) {
- p_clcb = &bta_gattc_cb.clcb[i];
- break;
- }
- }
- }
- /* send confirmation here if this is an indication, it should always be */
- GATTC_SendHandleValueConfirm(conn_id, att_value->handle);
-
- /* if connection available, refresh cache by doing discovery now */
- if (p_clcb != NULL)
- bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
- }
- /* notify applicationf or service change */
- if (p_clrcb->p_cback != NULL) {
- tBTA_GATTC bta_gattc;
- bta_gattc.remote_bda = p_srcb->server_bda;
- (*p_clrcb->p_cback)(BTA_GATTC_SRVC_CHG_EVT, &bta_gattc);
- }
+ if (!p_char) return false;
+ const tBTA_GATTC_SERVICE* p_svc =
+ bta_gattc_get_service_for_handle_srcb(p_srcb, p_char->value_handle);
+ if (!p_svc || p_svc->uuid != gattp_uuid || p_char->uuid != srvc_chg_uuid) {
+ return false;
}
- return processed;
+ if (att_value->len != BTA_GATTC_SERVICE_CHANGED_LEN) {
+ LOG(ERROR) << __func__
+ << ": received malformed service changed indication, skipping";
+ return false;
+ }
+
+ uint8_t* p = att_value->value;
+ uint16_t s_handle = ((uint16_t)(*(p)) + (((uint16_t)(*(p + 1))) << 8));
+ uint16_t e_handle = ((uint16_t)(*(p + 2)) + (((uint16_t)(*(p + 3))) << 8));
+
+ LOG(ERROR) << __func__ << ": service changed s_handle=" << loghex(s_handle)
+ << ", e_handle=" << loghex(e_handle);
+
+ /* mark service handle change pending */
+ p_srcb->srvc_hdl_chg = true;
+ /* clear up all notification/indication registration */
+ bta_gattc_clear_notif_registration(p_srcb, conn_id, s_handle, e_handle);
+ /* service change indication all received, do discovery update */
+ if (++p_srcb->update_count == bta_gattc_num_reg_app()) {
+ /* not an opened connection; or connection busy */
+ /* search for first available clcb and start discovery */
+ if (p_clcb == NULL || (p_clcb && p_clcb->p_q_cmd != NULL)) {
+ for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
+ if (bta_gattc_cb.clcb[i].in_use &&
+ bta_gattc_cb.clcb[i].p_srcb == p_srcb &&
+ bta_gattc_cb.clcb[i].p_q_cmd == NULL) {
+ p_clcb = &bta_gattc_cb.clcb[i];
+ break;
+ }
+ }
+ }
+ /* send confirmation here if this is an indication, it should always be */
+ GATTC_SendHandleValueConfirm(conn_id, att_value->handle);
+
+ /* if connection available, refresh cache by doing discovery now */
+ if (p_clcb) bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+ }
+
+ /* notify applicationf or service change */
+ if (p_clrcb->p_cback) {
+ tBTA_GATTC bta_gattc;
+ bta_gattc.remote_bda = p_srcb->server_bda;
+ (*p_clrcb->p_cback)(BTA_GATTC_SRVC_CHG_EVT, &bta_gattc);
+ }
+
+ return true;
}
-/*******************************************************************************
- *
- * Function bta_gattc_proc_other_indication
- *
- * Description process all non-service change indication/notification.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** process all non-service change indication/notification */
void bta_gattc_proc_other_indication(tBTA_GATTC_CLCB* p_clcb, uint8_t op,
tGATT_CL_COMPLETE* p_data,
tBTA_GATTC_NOTIFY* p_notify) {
- APPL_TRACE_DEBUG("%s: check p_data->att_value.handle=%d p_data->handle=%d",
- __func__, p_data->att_value.handle, p_data->handle);
- APPL_TRACE_DEBUG("is_notify", p_notify->is_notify);
+ VLOG(1) << __func__
+ << StringPrintf(
+ ": check p_data->att_value.handle=%d p_data->handle=%d",
+ p_data->att_value.handle, p_data->handle);
+ VLOG(1) << "is_notify", p_notify->is_notify;
p_notify->is_notify = (op == GATTC_OPTYPE_INDICATION) ? false : true;
p_notify->len = p_data->att_value.len;
@@ -1520,98 +1203,81 @@
(*p_clcb->p_rcb->p_cback)(BTA_GATTC_NOTIF_EVT, &bta_gattc);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_process_indicate
- *
- * Description process indication/notification.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** process indication/notification */
void bta_gattc_process_indicate(uint16_t conn_id, tGATTC_OPTYPE op,
tGATT_CL_COMPLETE* p_data) {
uint16_t handle = p_data->att_value.handle;
- tBTA_GATTC_CLCB* p_clcb;
- tBTA_GATTC_RCB* p_clrcb = NULL;
- tBTA_GATTC_SERV* p_srcb = NULL;
tBTA_GATTC_NOTIFY notify;
RawAddress remote_bda;
- tBTA_GATTC_IF gatt_if;
+ tGATT_IF gatt_if;
tBTA_TRANSPORT transport;
if (!GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport)) {
- APPL_TRACE_ERROR("%s indication/notif for unknown app", __func__);
+ LOG(ERROR) << __func__ << ": indication/notif for unknown app";
if (op == GATTC_OPTYPE_INDICATION)
GATTC_SendHandleValueConfirm(conn_id, handle);
return;
}
- p_clrcb = bta_gattc_cl_get_regcb(gatt_if);
+ tBTA_GATTC_RCB* p_clrcb = bta_gattc_cl_get_regcb(gatt_if);
if (p_clrcb == NULL) {
- APPL_TRACE_ERROR("%s indication/notif for unregistered app", __func__);
+ LOG(ERROR) << __func__ << ": indication/notif for unregistered app";
if (op == GATTC_OPTYPE_INDICATION)
GATTC_SendHandleValueConfirm(conn_id, handle);
return;
}
- p_srcb = bta_gattc_find_srcb(remote_bda);
+ tBTA_GATTC_SERV* p_srcb = bta_gattc_find_srcb(remote_bda);
if (p_srcb == NULL) {
- APPL_TRACE_ERROR("%s indication/notif for unknown device, ignore",
- __func__);
+ LOG(ERROR) << __func__ << ": indication/notif for unknown device, ignore";
if (op == GATTC_OPTYPE_INDICATION)
GATTC_SendHandleValueConfirm(conn_id, handle);
return;
}
- p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
notify.handle = handle;
- /* if non-service change indication/notification, forward to application */
- if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, ¬ify,
- &p_data->att_value)) {
- /* if app registered for the notification */
- if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, ¬ify)) {
- /* connection not open yet */
+
+ /* if service change indication/notification, don't forward to application */
+ if (bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, ¬ify,
+ &p_data->att_value))
+ return;
+
+ /* if app registered for the notification */
+ if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, ¬ify)) {
+ /* connection not open yet */
+ if (p_clcb == NULL) {
+ p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda, transport);
+
if (p_clcb == NULL) {
- p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda, transport);
-
- if (p_clcb == NULL) {
- APPL_TRACE_ERROR("No resources");
- return;
- }
-
- p_clcb->bta_conn_id = conn_id;
- p_clcb->transport = transport;
-
- bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, NULL);
+ LOG(ERROR) << "No resources";
+ return;
}
- if (p_clcb != NULL)
- bta_gattc_proc_other_indication(p_clcb, op, p_data, ¬ify);
+ p_clcb->bta_conn_id = conn_id;
+ p_clcb->transport = transport;
+
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, NULL);
}
- /* no one intersted and need ack? */
- else if (op == GATTC_OPTYPE_INDICATION) {
- APPL_TRACE_DEBUG("%s no one interested, ack now", __func__);
- GATTC_SendHandleValueConfirm(conn_id, handle);
- }
+
+ if (p_clcb != NULL)
+ bta_gattc_proc_other_indication(p_clcb, op, p_data, ¬ify);
+ }
+ /* no one intersted and need ack? */
+ else if (op == GATTC_OPTYPE_INDICATION) {
+ VLOG(1) << __func__ << " no one interested, ack now";
+ GATTC_SendHandleValueConfirm(conn_id, handle);
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_cmpl_cback
- *
- * Description client operation complete callback register with BTE GATT.
- *
- * Returns None.
- *
- ******************************************************************************/
+
+/** client operation complete callback register with BTE GATT */
static void bta_gattc_cmpl_cback(uint16_t conn_id, tGATTC_OPTYPE op,
tGATT_STATUS status,
tGATT_CL_COMPLETE* p_data) {
- tBTA_GATTC_CLCB* p_clcb;
- APPL_TRACE_DEBUG("bta_gattc_cmpl_cback: conn_id = %d op = %d status = %d",
- conn_id, op, status);
+ VLOG(1) << __func__ << ": conn_id:" << +conn_id << " op:" << +op
+ << " status:" << +status;
/* notification and indication processed right away */
if (op == GATTC_OPTYPE_NOTIFICATION || op == GATTC_OPTYPE_INDICATION) {
@@ -1619,13 +1285,11 @@
return;
}
/* for all other operation, not expected if w/o connection */
- else {
- p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
- if (p_clcb == NULL) {
- APPL_TRACE_ERROR("%s: unknown conn_id = %d, ignore data", __func__,
- conn_id);
- return;
- }
+ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ if (!p_clcb) {
+ LOG(ERROR) << __func__ << ": unknown conn_id=" << loghex(conn_id)
+ << " ignore data";
+ return;
}
/* if over BR_EDR, inform PM for mode change */
@@ -1637,17 +1301,9 @@
bta_gattc_cmpl_sendmsg(conn_id, op, status, p_data);
}
-/*******************************************************************************
- *
- * Function bta_gattc_cmpl_sendmsg
- *
- * Description client operation complete send message
- *
- * Returns None.
- *
- ******************************************************************************/
+/** client operation complete send message */
static void bta_gattc_cmpl_sendmsg(uint16_t conn_id, tGATTC_OPTYPE op,
- tBTA_GATT_STATUS status,
+ tGATT_STATUS status,
tGATT_CL_COMPLETE* p_data) {
const size_t len = sizeof(tBTA_GATTC_OP_CMPL) + sizeof(tGATT_CL_COMPLETE);
tBTA_GATTC_OP_CMPL* p_buf = (tBTA_GATTC_OP_CMPL*)osi_calloc(len);
@@ -1657,7 +1313,7 @@
p_buf->status = status;
p_buf->op_code = op;
- if (p_data != NULL) {
+ if (p_data) {
p_buf->p_cmpl = (tGATT_CL_COMPLETE*)(p_buf + 1);
memcpy(p_buf->p_cmpl, p_data, sizeof(tGATT_CL_COMPLETE));
}
@@ -1665,28 +1321,16 @@
bta_sys_sendmsg(p_buf);
}
-/*******************************************************************************
- *
- * Function bta_gattc_cong_cback
- *
- * Description congestion callback for BTA GATT client.
- *
- * Returns void
- *
- ******************************************************************************/
+/** congestion callback for BTA GATT client */
static void bta_gattc_cong_cback(uint16_t conn_id, bool congested) {
- tBTA_GATTC_CLCB* p_clcb;
+ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ if (!p_clcb || !p_clcb->p_rcb->p_cback) return;
+
tBTA_GATTC cb_data;
+ cb_data.congest.conn_id = conn_id;
+ cb_data.congest.congested = congested;
- p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
- if (p_clcb != NULL) {
- if (p_clcb->p_rcb->p_cback) {
- cb_data.congest.conn_id = conn_id;
- cb_data.congest.congested = congested;
-
- (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CONGEST_EVT, &cb_data);
- }
- }
+ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CONGEST_EVT, &cb_data);
}
static void bta_gattc_phy_update_cback(tGATT_IF gatt_if, uint16_t conn_id,
@@ -1695,7 +1339,7 @@
tBTA_GATTC_RCB* p_clreg = bta_gattc_cl_get_regcb(gatt_if);
if (!p_clreg || !p_clreg->p_cback) {
- APPL_TRACE_ERROR("%s: client_if=%d not found", __func__, gatt_if);
+ LOG(ERROR) << __func__ << ": client_if=" << +gatt_if << " not found";
return;
}
@@ -1714,7 +1358,7 @@
tBTA_GATTC_RCB* p_clreg = bta_gattc_cl_get_regcb(gatt_if);
if (!p_clreg || !p_clreg->p_cback) {
- APPL_TRACE_ERROR("%s: client_if=%d not found", __func__, gatt_if);
+ LOG(ERROR) << __func__ << ": client_if=" << gatt_if << " not found";
return;
}
diff --git a/bta/gatt/bta_gattc_api.cc b/bta/gatt/bta_gattc_api.cc
index 4815f24..bec0081 100644
--- a/bta/gatt/bta_gattc_api.cc
+++ b/bta/gatt/bta_gattc_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2010-2012 Broadcom Corporation
+ * Copyright 2010-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,8 @@
#include "bta_sys.h"
#include "device/include/controller.h"
+using bluetooth::Uuid;
+
/*****************************************************************************
* Constants
****************************************************************************/
@@ -55,8 +57,8 @@
*
******************************************************************************/
void BTA_GATTC_Disable(void) {
- if (bta_sys_is_register(BTA_ID_GATTC) == false) {
- APPL_TRACE_WARNING("GATTC Module not enabled/already disabled");
+ if (!bta_sys_is_register(BTA_ID_GATTC)) {
+ LOG(WARNING) << "GATTC Module not enabled/already disabled";
return;
}
@@ -64,14 +66,6 @@
bta_sys_deregister(BTA_ID_GATTC);
}
-static void create_random_uuid(tBT_UUID* uuid) {
- uuid->len = LEN_UUID_128;
-
- for (int i = 0; i < 16; ++i) {
- uuid->uu.uuid128[i] = (uint8_t)(rand() % 256);
- }
-}
-
/**
* This function is called to register application callbacks with BTA GATTC
* module. |client_cb| pointer to the application callback function.
@@ -79,17 +73,14 @@
*/
void BTA_GATTC_AppRegister(tBTA_GATTC_CBACK* p_client_cb,
BtaAppRegisterCallback cb) {
- if (bta_sys_is_register(BTA_ID_GATTC) == false)
+ if (!bta_sys_is_register(BTA_ID_GATTC))
bta_sys_register(BTA_ID_GATTC, &bta_gattc_reg);
- // base::Owned will own and free app_uuid
- tBT_UUID* uuid = new tBT_UUID;
- create_random_uuid(uuid);
- do_in_bta_thread(FROM_HERE, base::Bind(&bta_gattc_register, base::Owned(uuid),
+ do_in_bta_thread(FROM_HERE, base::Bind(&bta_gattc_register, Uuid::GetRandom(),
p_client_cb, std::move(cb)));
}
-static void app_deregister_impl(tBTA_GATTC_IF client_if) {
+static void app_deregister_impl(tGATT_IF client_if) {
bta_gattc_deregister(bta_gattc_cl_get_regcb(client_if));
}
/*******************************************************************************
@@ -104,7 +95,7 @@
* Returns None
*
******************************************************************************/
-void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if) {
+void BTA_GATTC_AppDeregister(tGATT_IF client_if) {
do_in_bta_thread(FROM_HERE, base::Bind(&app_deregister_impl, client_if));
}
@@ -125,16 +116,16 @@
* and don't impact the disconnection timer
*
******************************************************************************/
-void BTA_GATTC_Open(tBTA_GATTC_IF client_if, const RawAddress& remote_bda,
- bool is_direct, tBTA_GATT_TRANSPORT transport,
+void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda,
+ bool is_direct, tGATT_TRANSPORT transport,
bool opportunistic) {
uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
BTA_GATTC_Open(client_if, remote_bda, is_direct, transport, opportunistic,
phy);
}
-void BTA_GATTC_Open(tBTA_GATTC_IF client_if, const RawAddress& remote_bda,
- bool is_direct, tBTA_GATT_TRANSPORT transport,
+void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda,
+ bool is_direct, tGATT_TRANSPORT transport,
bool opportunistic, uint8_t initiating_phys) {
tBTA_GATTC_API_OPEN* p_buf =
(tBTA_GATTC_API_OPEN*)osi_malloc(sizeof(tBTA_GATTC_API_OPEN));
@@ -165,7 +156,7 @@
* Returns void
*
******************************************************************************/
-void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, const RawAddress& remote_bda,
+void BTA_GATTC_CancelOpen(tGATT_IF client_if, const RawAddress& remote_bda,
bool is_direct) {
tBTA_GATTC_API_CANCEL_OPEN* p_buf = (tBTA_GATTC_API_CANCEL_OPEN*)osi_malloc(
sizeof(tBTA_GATTC_API_CANCEL_OPEN));
@@ -239,15 +230,15 @@
* Returns None
*
******************************************************************************/
-void BTA_GATTC_ServiceSearchRequest(uint16_t conn_id, tBT_UUID* p_srvc_uuid) {
- const size_t len = sizeof(tBTA_GATTC_API_SEARCH) + sizeof(tBT_UUID);
+void BTA_GATTC_ServiceSearchRequest(uint16_t conn_id, Uuid* p_srvc_uuid) {
+ const size_t len = sizeof(tBTA_GATTC_API_SEARCH) + sizeof(Uuid);
tBTA_GATTC_API_SEARCH* p_buf = (tBTA_GATTC_API_SEARCH*)osi_calloc(len);
p_buf->hdr.event = BTA_GATTC_API_SEARCH_EVT;
p_buf->hdr.layer_specific = conn_id;
if (p_srvc_uuid) {
- p_buf->p_srvc_uuid = (tBT_UUID*)(p_buf + 1);
- memcpy(p_buf->p_srvc_uuid, p_srvc_uuid, sizeof(tBT_UUID));
+ p_buf->p_srvc_uuid = (Uuid*)(p_buf + 1);
+ *p_buf->p_srvc_uuid = *p_srvc_uuid;
} else {
p_buf->p_srvc_uuid = NULL;
}
@@ -255,11 +246,12 @@
bta_sys_sendmsg(p_buf);
}
-void BTA_GATTC_DiscoverServiceByUuid(uint16_t conn_id, tBT_UUID* p_srvc_uuid) {
+void BTA_GATTC_DiscoverServiceByUuid(uint16_t conn_id,
+ const Uuid& p_srvc_uuid) {
tGATT_DISC_PARAM* param = new tGATT_DISC_PARAM;
param->s_handle = 0x0001;
param->e_handle = 0xFFFF;
- param->service = *p_srvc_uuid;
+ param->service = p_srvc_uuid;
do_in_bta_thread(FROM_HERE,
base::Bind(base::IgnoreResult(&GATTC_Discover), conn_id,
GATT_DISC_SRVC_BY_UUID, base::Owned(param)));
@@ -274,10 +266,10 @@
*
* Parameters conn_id: connection ID which identify the server.
*
- * Returns returns list_t of tBTA_GATTC_SERVICE or NULL.
+ * Returns returns list of tBTA_GATTC_SERVICE or NULL.
*
******************************************************************************/
-const list_t* BTA_GATTC_GetServices(uint16_t conn_id) {
+const std::vector<tBTA_GATTC_SERVICE>* BTA_GATTC_GetServices(uint16_t conn_id) {
return bta_gattc_get_services(conn_id);
}
@@ -317,6 +309,20 @@
return bta_gattc_get_descriptor(conn_id, handle);
}
+/* Return characteristic that owns descriptor with handle equal to |handle|, or
+ * NULL */
+const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetOwningCharacteristic(
+ uint16_t conn_id, uint16_t handle) {
+ return bta_gattc_get_owning_characteristic(conn_id, handle);
+}
+
+/* Return service that owns descriptor or characteristic with handle equal to
+ * |handle|, or NULL */
+const tBTA_GATTC_SERVICE* BTA_GATTC_GetOwningService(uint16_t conn_id,
+ uint16_t handle) {
+ return bta_gattc_get_service_for_handle(conn_id, handle);
+}
+
/*******************************************************************************
*
* Function BTA_GATTC_GetGattDb
@@ -348,7 +354,7 @@
*
******************************************************************************/
void BTA_GATTC_ReadCharacteristic(uint16_t conn_id, uint16_t handle,
- tBTA_GATT_AUTH_REQ auth_req,
+ tGATT_AUTH_REQ auth_req,
GATT_READ_OP_CB callback, void* cb_data) {
tBTA_GATTC_API_READ* p_buf =
(tBTA_GATTC_API_READ*)osi_calloc(sizeof(tBTA_GATTC_API_READ));
@@ -367,9 +373,9 @@
* This function is called to read a value of characteristic with uuid equal to
* |uuid|
*/
-void BTA_GATTC_ReadUsingCharUuid(uint16_t conn_id, tBT_UUID uuid,
+void BTA_GATTC_ReadUsingCharUuid(uint16_t conn_id, const Uuid& uuid,
uint16_t s_handle, uint16_t e_handle,
- tBTA_GATT_AUTH_REQ auth_req,
+ tGATT_AUTH_REQ auth_req,
GATT_READ_OP_CB callback, void* cb_data) {
tBTA_GATTC_API_READ* p_buf =
(tBTA_GATTC_API_READ*)osi_calloc(sizeof(tBTA_GATTC_API_READ));
@@ -400,8 +406,8 @@
*
******************************************************************************/
void BTA_GATTC_ReadCharDescr(uint16_t conn_id, uint16_t handle,
- tBTA_GATT_AUTH_REQ auth_req,
- GATT_READ_OP_CB callback, void* cb_data) {
+ tGATT_AUTH_REQ auth_req, GATT_READ_OP_CB callback,
+ void* cb_data) {
tBTA_GATTC_API_READ* p_buf =
(tBTA_GATTC_API_READ*)osi_calloc(sizeof(tBTA_GATTC_API_READ));
@@ -429,7 +435,7 @@
*
******************************************************************************/
void BTA_GATTC_ReadMultiple(uint16_t conn_id, tBTA_GATTC_MULTI* p_read_multi,
- tBTA_GATT_AUTH_REQ auth_req) {
+ tGATT_AUTH_REQ auth_req) {
tBTA_GATTC_API_READ_MULTI* p_buf =
(tBTA_GATTC_API_READ_MULTI*)osi_calloc(sizeof(tBTA_GATTC_API_READ_MULTI));
@@ -460,9 +466,9 @@
*
******************************************************************************/
void BTA_GATTC_WriteCharValue(uint16_t conn_id, uint16_t handle,
- tBTA_GATTC_WRITE_TYPE write_type,
+ tGATT_WRITE_TYPE write_type,
std::vector<uint8_t> value,
- tBTA_GATT_AUTH_REQ auth_req,
+ tGATT_AUTH_REQ auth_req,
GATT_WRITE_OP_CB callback, void* cb_data) {
tBTA_GATTC_API_WRITE* p_buf = (tBTA_GATTC_API_WRITE*)osi_calloc(
sizeof(tBTA_GATTC_API_WRITE) + value.size());
@@ -499,7 +505,7 @@
******************************************************************************/
void BTA_GATTC_WriteCharDescr(uint16_t conn_id, uint16_t handle,
std::vector<uint8_t> value,
- tBTA_GATT_AUTH_REQ auth_req,
+ tGATT_AUTH_REQ auth_req,
GATT_WRITE_OP_CB callback, void* cb_data) {
tBTA_GATTC_API_WRITE* p_buf = (tBTA_GATTC_API_WRITE*)osi_calloc(
sizeof(tBTA_GATTC_API_WRITE) + value.size());
@@ -508,7 +514,7 @@
p_buf->hdr.layer_specific = conn_id;
p_buf->auth_req = auth_req;
p_buf->handle = handle;
- p_buf->write_type = BTA_GATTC_TYPE_WRITE;
+ p_buf->write_type = GATT_WRITE;
p_buf->write_cb = callback;
p_buf->write_cb_data = cb_data;
@@ -537,8 +543,7 @@
*
******************************************************************************/
void BTA_GATTC_PrepareWrite(uint16_t conn_id, uint16_t handle, uint16_t offset,
- std::vector<uint8_t> value,
- tBTA_GATT_AUTH_REQ auth_req,
+ std::vector<uint8_t> value, tGATT_AUTH_REQ auth_req,
GATT_WRITE_OP_CB callback, void* cb_data) {
tBTA_GATTC_API_WRITE* p_buf = (tBTA_GATTC_API_WRITE*)osi_calloc(
sizeof(tBTA_GATTC_API_WRITE) + value.size());
@@ -602,7 +607,8 @@
tBTA_GATTC_API_CONFIRM* p_buf =
(tBTA_GATTC_API_CONFIRM*)osi_calloc(sizeof(tBTA_GATTC_API_CONFIRM));
- APPL_TRACE_API("%s conn_id=%d handle=0x%04x", __func__, conn_id, handle);
+ VLOG(1) << __func__ << ": conn_id=" << +conn_id << " handle=0x" << std::hex
+ << +handle;
p_buf->hdr.event = BTA_GATTC_API_CONFIRM_EVT;
p_buf->hdr.layer_specific = conn_id;
@@ -625,15 +631,15 @@
* Returns OK if registration succeed, otherwise failed.
*
******************************************************************************/
-tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications(tBTA_GATTC_IF client_if,
- const RawAddress& bda,
- uint16_t handle) {
+tGATT_STATUS BTA_GATTC_RegisterForNotifications(tGATT_IF client_if,
+ const RawAddress& bda,
+ uint16_t handle) {
tBTA_GATTC_RCB* p_clreg;
- tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
+ tGATT_STATUS status = GATT_ILLEGAL_PARAMETER;
uint8_t i;
if (!handle) {
- APPL_TRACE_ERROR("deregistration failed, handle is 0");
+ LOG(ERROR) << "deregistration failed, handle is 0";
return status;
}
@@ -643,12 +649,12 @@
if (p_clreg->notif_reg[i].in_use &&
p_clreg->notif_reg[i].remote_bda == bda &&
p_clreg->notif_reg[i].handle == handle) {
- APPL_TRACE_WARNING("notification already registered");
- status = BTA_GATT_OK;
+ LOG(WARNING) << "notification already registered";
+ status = GATT_SUCCESS;
break;
}
}
- if (status != BTA_GATT_OK) {
+ if (status != GATT_SUCCESS) {
for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i++) {
if (!p_clreg->notif_reg[i].in_use) {
memset((void*)&p_clreg->notif_reg[i], 0,
@@ -658,17 +664,17 @@
p_clreg->notif_reg[i].remote_bda = bda;
p_clreg->notif_reg[i].handle = handle;
- status = BTA_GATT_OK;
+ status = GATT_SUCCESS;
break;
}
}
if (i == BTA_GATTC_NOTIF_REG_MAX) {
- status = BTA_GATT_NO_RESOURCES;
- APPL_TRACE_ERROR("Max Notification Reached, registration failed.");
+ status = GATT_NO_RESOURCES;
+ LOG(ERROR) << "Max Notification Reached, registration failed.";
}
}
} else {
- APPL_TRACE_ERROR("Client_if: %d Not Registered", client_if);
+ LOG(ERROR) << "client_if=" << +client_if << " Not Registered";
}
return status;
@@ -688,33 +694,33 @@
* Returns OK if deregistration succeed, otherwise failed.
*
******************************************************************************/
-tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications(tBTA_GATTC_IF client_if,
- const RawAddress& bda,
- uint16_t handle) {
+tGATT_STATUS BTA_GATTC_DeregisterForNotifications(tGATT_IF client_if,
+ const RawAddress& bda,
+ uint16_t handle) {
if (!handle) {
- APPL_TRACE_ERROR("%s: deregistration failed, handle is 0", __func__);
- return BTA_GATT_ILLEGAL_PARAMETER;
+ LOG(ERROR) << __func__ << ": deregistration failed, handle is 0";
+ return GATT_ILLEGAL_PARAMETER;
}
tBTA_GATTC_RCB* p_clreg = bta_gattc_cl_get_regcb(client_if);
if (p_clreg == NULL) {
- LOG(ERROR) << __func__ << " client_if: " << +client_if
- << " not registered bd_addr:" << bda;
- return BTA_GATT_ILLEGAL_PARAMETER;
+ LOG(ERROR) << __func__ << " client_if=" << +client_if
+ << " not registered bd_addr=" << bda;
+ return GATT_ILLEGAL_PARAMETER;
}
for (int i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i++) {
if (p_clreg->notif_reg[i].in_use &&
p_clreg->notif_reg[i].remote_bda == bda &&
p_clreg->notif_reg[i].handle == handle) {
- VLOG(1) << __func__ << " deregistered bd_addr:" << bda;
+ VLOG(1) << __func__ << " deregistered bd_addr=" << bda;
memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
- return BTA_GATT_OK;
+ return GATT_SUCCESS;
}
}
- LOG(ERROR) << __func__ << " registration not found bd_addr:" << bda;
- return BTA_GATT_ERROR;
+ LOG(ERROR) << __func__ << " registration not found bd_addr=" << bda;
+ return GATT_ERROR;
}
/*******************************************************************************
diff --git a/bta/gatt/bta_gattc_cache.cc b/bta/gatt/bta_gattc_cache.cc
index 110e534..60224a3 100644
--- a/bta/gatt/bta_gattc_cache.cc
+++ b/bta/gatt/bta_gattc_cache.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,24 +44,24 @@
#include "sdpdefs.h"
#include "utl.h"
+using bluetooth::Uuid;
+using base::StringPrintf;
+
static void bta_gattc_cache_write(const RawAddress& server_bda,
uint16_t num_attr, tBTA_GATTC_NV_ATTR* attr);
static void bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,
tBTA_GATTC_SERV* p_srvc_cb);
-static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(
- uint16_t conn_id, tBTA_GATTC_SERV* p_server_cb);
-extern void bta_to_btif_uuid(bt_uuid_t* p_dest, tBT_UUID* p_src);
-tBTA_GATTC_SERVICE* bta_gattc_find_matching_service(const list_t* services,
- uint16_t handle);
-tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV* p_srcb,
- uint16_t handle);
+static tGATT_STATUS bta_gattc_sdp_service_disc(uint16_t conn_id,
+ tBTA_GATTC_SERV* p_server_cb);
+const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(
+ tBTA_GATTC_SERV* p_srcb, uint16_t handle);
tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
tBTA_GATTC_SERV* p_srcb, uint16_t handle);
#define BTA_GATT_SDP_DB_SIZE 4096
#define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
-#define GATT_CACHE_VERSION 2
+#define GATT_CACHE_VERSION 4
static void bta_gattc_generate_cache_file_name(char* buffer, size_t buffer_len,
const RawAddress& bda) {
@@ -80,73 +80,54 @@
} tBTA_GATTC_CB_DATA;
#if (BTA_GATT_DEBUG == TRUE)
-static char* bta_gattc_attr_type[] = {
- "I", /* Included Service */
- "C", /* Characteristic */
- "D" /* Characteristic Descriptor */
-};
/* utility functions */
-bool display_cache_attribute(void* data, void* context) {
- tBTA_GATTC_CACHE_ATTR* p_attr = data;
- APPL_TRACE_ERROR("\t Attr handle[%d] uuid[0x%04x] type[%s] prop[0x%1x]",
- p_attr->handle, p_attr->uuid.uu.uuid16,
- bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
- return true;
-}
+/* debug function to display the server cache */
+static void display_db(const std::vector<tBTA_GATTC_SERVICE>& cache) {
+ for (const tBTA_GATTC_SERVICE& service : cache) {
+ LOG(ERROR) << "Service: s_handle=" << loghex(service.s_handle)
+ << ", e_handle=" << loghex(service.e_handle)
+ << ", inst=" << loghex(service.handle)
+ << ", uuid=" << service.uuid;
-bool display_cache_service(void* data, void* context) {
- tBTA_GATTC_SERVICE* p_cur_srvc = data;
- APPL_TRACE_ERROR("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]",
- p_cur_srvc->s_handle, p_cur_srvc->e_handle,
- ((p_cur_srvc->uuid.len == 2) ? "uuid16" : "uuid128"),
- p_cur_srvc->uuid.uu.uuid16, p_cur_srvc->handle);
+ if (service.characteristics.empty()) {
+ LOG(ERROR) << "\t No characteristics";
+ continue;
+ }
- if (p_cur_srvc->characteristics != NULL) {
- list_foreach(p_cur_srvc->characteristics, display_cache_attribute, NULL);
+ for (const tBTA_GATTC_CHARACTERISTIC& c : service.characteristics) {
+ LOG(ERROR) << "\t Characteristic value_handle=" << loghex(c.value_handle)
+ << ", uuid=" << c.uuid << ", prop=" << loghex(c.properties);
+
+ if (c.descriptors.empty()) {
+ LOG(ERROR) << "\t\t No descriptors";
+ continue;
+ }
+
+ for (const tBTA_GATTC_DESCRIPTOR& d : c.descriptors) {
+ LOG(ERROR) << "\t\t Descriptor handle=" << loghex(d.handle)
+ << ", uuid=" << d.uuid;
+ }
+ }
}
-
- return true;
}
-/*******************************************************************************
- *
- * Function bta_gattc_display_cache_server
- *
- * Description debug function to display the server cache.
- *
- * Returns none.
- *
- ******************************************************************************/
-static void bta_gattc_display_cache_server(list_t* p_cache) {
- APPL_TRACE_ERROR("<================Start Server Cache =============>");
- list_foreach(p_cache, display_cache_service, NULL);
- APPL_TRACE_ERROR("<================End Server Cache =============>");
- APPL_TRACE_ERROR(" ");
+/* debug function to display the server cache */
+static void bta_gattc_display_cache_server(
+ const std::vector<tBTA_GATTC_SERVICE>& cache) {
+ LOG(ERROR) << "<================Start Server Cache =============>";
+ display_db(cache);
+ LOG(ERROR) << "<================End Server Cache =============>";
+ LOG(ERROR) << " ";
}
-/*******************************************************************************
- *
- * Function bta_gattc_display_explore_record
- *
- * Description debug function to display the exploration list
- *
- * Returns none.
- *
- ******************************************************************************/
-static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC* p_rec,
- uint8_t num_rec) {
- uint8_t i;
- tBTA_GATTC_ATTR_REC* pp = p_rec;
-
- APPL_TRACE_ERROR("<================Start Explore Queue =============>");
- for (i = 0; i < num_rec; i++, pp++) {
- APPL_TRACE_ERROR(
- "\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
- i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
- }
- APPL_TRACE_ERROR("<================ End Explore Queue =============>");
- APPL_TRACE_ERROR(" ");
+/** debug function to display the exploration list */
+static void bta_gattc_display_explore_record(
+ const std::vector<tBTA_GATTC_SERVICE>& cache) {
+ LOG(ERROR) << "<================Start Explore Queue =============>";
+ display_db(cache);
+ LOG(ERROR) << "<================ End Explore Queue =============>";
+ LOG(ERROR) << " ";
}
#endif /* BTA_GATT_DEBUG == TRUE */
@@ -160,91 +141,56 @@
* Returns status
*
******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb) {
- if (p_srvc_cb->p_srvc_cache != NULL) {
- list_free(p_srvc_cb->p_srvc_cache);
- p_srvc_cb->p_srvc_cache = NULL;
+tGATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb) {
+ // clear reallocating
+ std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->srvc_cache);
+ std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->pending_discovery);
+ return GATT_SUCCESS;
+}
+
+tBTA_GATTC_SERVICE* bta_gattc_find_matching_service(
+ std::vector<tBTA_GATTC_SERVICE>& services, uint16_t handle) {
+ for (tBTA_GATTC_SERVICE& service : services) {
+ if (handle >= service.s_handle && handle <= service.e_handle)
+ return &service;
}
- osi_free(p_srvc_cb->p_srvc_list);
- p_srvc_cb->p_srvc_list =
- (tBTA_GATTC_ATTR_REC*)osi_malloc(BTA_GATTC_ATTR_LIST_SIZE);
- p_srvc_cb->total_srvc = 0;
- p_srvc_cb->cur_srvc_idx = 0;
- p_srvc_cb->cur_char_idx = 0;
- p_srvc_cb->next_avail_idx = 0;
-
- return BTA_GATT_OK;
+ return nullptr;
}
-static void characteristic_free(void* ptr) {
- tBTA_GATTC_CHARACTERISTIC* p_char = (tBTA_GATTC_CHARACTERISTIC*)ptr;
- list_free(p_char->descriptors);
- osi_free(p_char);
-}
-
-static void service_free(void* ptr) {
- tBTA_GATTC_SERVICE* srvc = (tBTA_GATTC_SERVICE*)ptr;
- list_free(srvc->characteristics);
- list_free(srvc->included_svc);
- osi_free(srvc);
-}
-
-/*******************************************************************************
- *
- * Function bta_gattc_add_srvc_to_cache
- *
- * Description Add a service into database cache.
- *
- * Returns status
- *
- ******************************************************************************/
-static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV* p_srvc_cb,
- uint16_t s_handle,
- uint16_t e_handle,
- tBT_UUID* p_uuid,
- bool is_primary) {
+/** Add a service into GATT database */
+static void add_service_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
+ uint16_t s_handle, uint16_t e_handle,
+ const Uuid& uuid, bool is_primary) {
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("Add a service into Service");
+ VLOG(1) << "Add a service into GATT DB";
#endif
- tBTA_GATTC_SERVICE* p_new_srvc =
- (tBTA_GATTC_SERVICE*)osi_malloc(sizeof(tBTA_GATTC_SERVICE));
-
- /* update service information */
- p_new_srvc->s_handle = s_handle;
- p_new_srvc->e_handle = e_handle;
- p_new_srvc->is_primary = is_primary;
- memcpy(&p_new_srvc->uuid, p_uuid, sizeof(tBT_UUID));
- p_new_srvc->handle = s_handle;
- p_new_srvc->characteristics = list_new(characteristic_free);
- p_new_srvc->included_svc = list_new(osi_free);
-
- if (p_srvc_cb->p_srvc_cache == NULL) {
- p_srvc_cb->p_srvc_cache = list_new(service_free);
- }
-
- list_append(p_srvc_cb->p_srvc_cache, p_new_srvc);
- return BTA_GATT_OK;
+ gatt_db.emplace_back(tBTA_GATTC_SERVICE{
+ .s_handle = s_handle,
+ .e_handle = e_handle,
+ .is_primary = is_primary,
+ .uuid = uuid,
+ .handle = s_handle,
+ });
}
-static tBTA_GATT_STATUS bta_gattc_add_char_to_cache(tBTA_GATTC_SERV* p_srvc_cb,
- uint16_t attr_handle,
- uint16_t value_handle,
- tBT_UUID* p_uuid,
- uint8_t property) {
+/** Add a characteristic into GATT database */
+static void add_characteristic_to_gatt_db(
+ std::vector<tBTA_GATTC_SERVICE>& gatt_db, uint16_t attr_handle,
+ uint16_t value_handle, const Uuid& uuid, uint8_t property) {
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("%s: Add a characteristic into Service", __func__);
- APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x", value_handle,
- p_uuid->uu.uuid16, property);
+ VLOG(1) << __func__
+ << ": Add a characteristic into service. handle:" << +value_handle
+ << " uuid:" << uuid << " property=0x" << std::hex << +property;
#endif
tBTA_GATTC_SERVICE* service =
- bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, attr_handle);
+ bta_gattc_find_matching_service(gatt_db, attr_handle);
if (!service) {
- APPL_TRACE_ERROR(
- "Illegal action to add char/descr/incl srvc for non-existing service!");
- return GATT_WRONG_STATE;
+ LOG(ERROR) << "Illegal action to add char/descr/incl srvc for non-existing "
+ "service!";
+ return;
}
/* TODO(jpawlowski): We should use attribute handle, not value handle to refer
@@ -253,258 +199,148 @@
*/
if (service->e_handle < value_handle) service->e_handle = value_handle;
- tBTA_GATTC_CHARACTERISTIC* characteristic =
- (tBTA_GATTC_CHARACTERISTIC*)osi_malloc(sizeof(tBTA_GATTC_CHARACTERISTIC));
-
- characteristic->handle = value_handle;
- characteristic->properties = property;
- characteristic->descriptors = list_new(osi_free);
- memcpy(&characteristic->uuid, p_uuid, sizeof(tBT_UUID));
-
- characteristic->service = service;
- list_append(service->characteristics, characteristic);
-
- return BTA_GATT_OK;
+ service->characteristics.emplace_back(
+ tBTA_GATTC_CHARACTERISTIC{.declaration_handle = attr_handle,
+ .value_handle = value_handle,
+ .properties = property,
+ .uuid = uuid});
+ return;
}
-/*******************************************************************************
- *
- * Function bta_gattc_add_attr_to_cache
- *
- * Description Add an attribute into database cache buffer.
- *
- * Returns status
- *
- ******************************************************************************/
-static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(
- tBTA_GATTC_SERV* p_srvc_cb, uint16_t handle, tBT_UUID* p_uuid,
- uint8_t property, uint16_t incl_srvc_s_handle, tBTA_GATTC_ATTR_TYPE type) {
+/* Add an descriptor into database cache buffer */
+static void add_descriptor_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
+ uint16_t handle, const Uuid& uuid) {
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("%s: Add a [%s] into Service", __func__,
- bta_gattc_attr_type[type]);
- APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", handle,
- p_uuid->uu.uuid16, property, type);
+ VLOG(1) << __func__ << ": add descriptor, handle=" << loghex(handle)
+ << ", uuid=" << uuid;
#endif
tBTA_GATTC_SERVICE* service =
- bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, handle);
+ bta_gattc_find_matching_service(gatt_db, handle);
if (!service) {
- APPL_TRACE_ERROR(
- "Illegal action to add char/descr/incl srvc for non-existing service!");
- return GATT_WRONG_STATE;
- }
-
- if (type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) {
- tBTA_GATTC_INCLUDED_SVC* isvc =
- (tBTA_GATTC_INCLUDED_SVC*)osi_malloc(sizeof(tBTA_GATTC_INCLUDED_SVC));
-
- isvc->handle = handle;
- memcpy(&isvc->uuid, p_uuid, sizeof(tBT_UUID));
-
- isvc->owning_service = service;
- isvc->included_service = bta_gattc_find_matching_service(
- p_srvc_cb->p_srvc_cache, incl_srvc_s_handle);
- if (!isvc->included_service) {
- APPL_TRACE_ERROR(
- "%s: Illegal action to add non-existing included service!", __func__);
- osi_free(isvc);
- return GATT_WRONG_STATE;
- }
-
- list_append(service->included_svc, isvc);
- } else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
- tBTA_GATTC_DESCRIPTOR* descriptor =
- (tBTA_GATTC_DESCRIPTOR*)osi_malloc(sizeof(tBTA_GATTC_DESCRIPTOR));
-
- descriptor->handle = handle;
- memcpy(&descriptor->uuid, p_uuid, sizeof(tBT_UUID));
-
- if (service->characteristics == NULL ||
- list_is_empty(service->characteristics)) {
- APPL_TRACE_ERROR(
- "%s: Illegal action to add descriptor before adding a "
- "characteristic!",
- __func__);
- osi_free(descriptor);
- return GATT_WRONG_STATE;
- }
-
- tBTA_GATTC_CHARACTERISTIC* char_node =
- (tBTA_GATTC_CHARACTERISTIC*)list_back(service->characteristics);
-
- descriptor->characteristic = char_node;
- list_append(char_node->descriptors, descriptor);
- }
- return BTA_GATT_OK;
-}
-
-/*******************************************************************************
- *
- * Function bta_gattc_get_disc_range
- *
- * Description get discovery stating and ending handle range.
- *
- * Returns None.
- *
- ******************************************************************************/
-void bta_gattc_get_disc_range(tBTA_GATTC_SERV* p_srvc_cb, uint16_t* p_s_hdl,
- uint16_t* p_e_hdl, bool is_srvc) {
- tBTA_GATTC_ATTR_REC* p_rec = NULL;
-
- if (is_srvc) {
- p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
- *p_s_hdl = p_rec->s_handle;
- } else {
- p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
- *p_s_hdl = p_rec->s_handle + 1;
- }
-
- *p_e_hdl = p_rec->e_handle;
-#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("discover range [%d ~ %d]", p_rec->s_handle,
- p_rec->e_handle);
-#endif
- return;
-}
-/*******************************************************************************
- *
- * Function bta_gattc_discover_pri_service
- *
- * Description Start primary service discovery
- *
- * Returns status of the operation.
- *
- ******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
- tBTA_GATTC_SERV* p_server_cb,
- uint8_t disc_type) {
- tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
- tBTA_GATT_STATUS status = BTA_GATT_ERROR;
-
- if (p_clcb) {
- if (p_clcb->transport == BTA_TRANSPORT_LE)
- status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
- else
- status = bta_gattc_sdp_service_disc(conn_id, p_server_cb);
- }
-
- return status;
-}
-/*******************************************************************************
- *
- * Function bta_gattc_discover_procedure
- *
- * Description Start a particular type of discovery procedure on server.
- *
- * Returns status of the operation.
- *
- ******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_discover_procedure(uint16_t conn_id,
- tBTA_GATTC_SERV* p_server_cb,
- uint8_t disc_type) {
- tGATT_DISC_PARAM param;
- bool is_service = true;
-
- memset(¶m, 0, sizeof(tGATT_DISC_PARAM));
-
- if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID) {
- param.s_handle = 1;
- param.e_handle = 0xFFFF;
- } else {
- if (disc_type == GATT_DISC_CHAR_DSCPT) is_service = false;
-
- bta_gattc_get_disc_range(p_server_cb, ¶m.s_handle, ¶m.e_handle,
- is_service);
-
- if (param.s_handle > param.e_handle) {
- return GATT_ERROR;
- }
- }
- return GATTC_Discover(conn_id, disc_type, ¶m);
-}
-/*******************************************************************************
- *
- * Function bta_gattc_start_disc_include_srvc
- *
- * Description Start discovery for included service
- *
- * Returns status of the operation.
- *
- ******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(uint16_t conn_id,
- tBTA_GATTC_SERV* p_srvc_cb) {
- return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
-}
-/*******************************************************************************
- *
- * Function bta_gattc_start_disc_char
- *
- * Description Start discovery for characteristic
- *
- * Returns status of the operation.
- *
- ******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_start_disc_char(uint16_t conn_id,
- tBTA_GATTC_SERV* p_srvc_cb) {
- p_srvc_cb->total_char = 0;
-
- return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
-}
-/*******************************************************************************
- *
- * Function bta_gattc_start_disc_char_dscp
- *
- * Description Start discovery for characteristic descriptor
- *
- * Returns none.
- *
- ******************************************************************************/
-void bta_gattc_start_disc_char_dscp(uint16_t conn_id,
- tBTA_GATTC_SERV* p_srvc_cb) {
- APPL_TRACE_DEBUG("starting discover characteristics descriptor");
-
- if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) !=
- 0)
- bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
-}
-/*******************************************************************************
- *
- * Function bta_gattc_explore_srvc
- *
- * Description process the service discovery complete event
- *
- * Returns status
- *
- ******************************************************************************/
-static void bta_gattc_explore_srvc(uint16_t conn_id,
- tBTA_GATTC_SERV* p_srvc_cb) {
- tBTA_GATTC_ATTR_REC* p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
- tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
-
- APPL_TRACE_DEBUG("Start service discovery: srvc_idx = %d",
- p_srvc_cb->cur_srvc_idx);
-
- p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
-
- if (p_clcb == NULL) {
- APPL_TRACE_ERROR("unknown connection ID");
+ LOG(ERROR) << "Illegal action to add descriptor for non-existing service!";
return;
}
- /* start expore a service if there is service not been explored */
- if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc) {
- /* add the first service into cache */
- if (bta_gattc_add_srvc_to_cache(p_srvc_cb, p_rec->s_handle, p_rec->e_handle,
- &p_rec->uuid, p_rec->is_primary) == 0) {
- /* start discovering included services */
- bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
- return;
- }
+
+ if (service->characteristics.empty()) {
+ LOG(ERROR) << __func__
+ << ": Illegal action to add descriptor before adding a "
+ "characteristic!";
+ return;
}
+
+ tBTA_GATTC_CHARACTERISTIC* char_node = &service->characteristics.front();
+ for (auto it = service->characteristics.begin();
+ it != service->characteristics.end(); it++) {
+ if (it->value_handle > handle) break;
+ char_node = &(*it);
+ }
+
+ char_node->descriptors.emplace_back(
+ tBTA_GATTC_DESCRIPTOR{.handle = handle, .uuid = uuid});
+}
+
+/* Add an attribute into database cache buffer */
+static void add_incl_srvc_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
+ uint16_t handle, const Uuid& uuid,
+ uint16_t incl_srvc_s_handle) {
+#if (BTA_GATT_DEBUG == TRUE)
+ VLOG(1) << __func__ << ": add included service, handle=" << loghex(handle)
+ << ", uuid=" << uuid;
+#endif
+
+ tBTA_GATTC_SERVICE* service =
+ bta_gattc_find_matching_service(gatt_db, handle);
+ if (!service) {
+ LOG(ERROR) << "Illegal action to add incl srvc for non-existing service!";
+ return;
+ }
+
+ tBTA_GATTC_SERVICE* included_service =
+ bta_gattc_find_matching_service(gatt_db, incl_srvc_s_handle);
+ if (!included_service) {
+ LOG(ERROR) << __func__
+ << ": Illegal action to add non-existing included service!";
+ return;
+ }
+
+ service->included_svc.emplace_back(tBTA_GATTC_INCLUDED_SVC{
+ .handle = handle,
+ .uuid = uuid,
+ .owning_service = service,
+ .included_service = included_service,
+ });
+}
+
+/** Start primary service discovery */
+tGATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
+ tBTA_GATTC_SERV* p_server_cb,
+ uint8_t disc_type) {
+ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ if (!p_clcb) return GATT_ERROR;
+
+ if (p_clcb->transport == BTA_TRANSPORT_LE) {
+ tGATT_DISC_PARAM param{.s_handle = 0x0001, .e_handle = 0xFFFF};
+ return GATTC_Discover(conn_id, disc_type, ¶m);
+ }
+
+ return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
+}
+
+/** Start discovery for characteristic descriptor */
+void bta_gattc_start_disc_char_dscp(uint16_t conn_id,
+ tBTA_GATTC_SERV* p_srvc_cb) {
+ VLOG(1) << "starting discover characteristics descriptor";
+ auto& characteristic = p_srvc_cb->pending_char;
+
+ uint16_t end_handle = 0xFFFF;
+ // if there are more characteristics in the service
+ if (std::next(p_srvc_cb->pending_char) !=
+ p_srvc_cb->pending_service->characteristics.end()) {
+ // end at beginning of next characteristic
+ end_handle = std::next(p_srvc_cb->pending_char)->declaration_handle - 1;
+ } else {
+ // end at the end of current service
+ end_handle = p_srvc_cb->pending_service->e_handle;
+ }
+
+ tGATT_DISC_PARAM param{
+ .s_handle = (uint16_t)(characteristic->value_handle + 1),
+ .e_handle = end_handle};
+ if (GATTC_Discover(conn_id, GATT_DISC_CHAR_DSCPT, ¶m) != 0) {
+ bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+ }
+}
+
+/** process the service discovery complete event */
+static void bta_gattc_explore_srvc(uint16_t conn_id,
+ tBTA_GATTC_SERV* p_srvc_cb) {
+ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ if (!p_clcb) {
+ LOG(ERROR) << "unknown conn_id=" << +conn_id;
+ return;
+ }
+
+ /* start expore a service if there is service not been explored */
+ if (p_srvc_cb->pending_service != p_srvc_cb->pending_discovery.end()) {
+ auto& service = *p_srvc_cb->pending_service;
+ VLOG(1) << "Start service discovery";
+
+ /* start discovering included services */
+ tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
+ .e_handle = service.e_handle};
+ GATTC_Discover(conn_id, GATT_DISC_INC_SRVC, ¶m);
+ return;
+ }
+
/* no service found at all, the end of server discovery*/
- LOG_WARN(LOG_TAG, "%s no more services found", __func__);
+ LOG(INFO) << __func__ << ": no more services found";
+
+ p_srvc_cb->srvc_cache.swap(p_srvc_cb->pending_discovery);
+ std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->pending_discovery);
#if (BTA_GATT_DEBUG == TRUE)
- bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
+ bta_gattc_display_cache_server(p_srvc_cb->srvc_cache);
#endif
/* save cache to NV */
p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
@@ -513,191 +349,42 @@
bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id);
}
- bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
+ bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
}
-/*******************************************************************************
- *
- * Function bta_gattc_incl_srvc_disc_cmpl
- *
- * Description process the relationship discovery complete event
- *
- * Returns status
- *
- ******************************************************************************/
-static void bta_gattc_incl_srvc_disc_cmpl(uint16_t conn_id,
- tBTA_GATTC_SERV* p_srvc_cb) {
- p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
- /* start discoverying characteristic */
- bta_gattc_start_disc_char(conn_id, p_srvc_cb);
-}
-/*******************************************************************************
- *
- * Function bta_gattc_char_disc_cmpl
- *
- * Description process the characteristic discovery complete event
- *
- * Returns status
- *
- ******************************************************************************/
-static void bta_gattc_char_disc_cmpl(uint16_t conn_id,
- tBTA_GATTC_SERV* p_srvc_cb) {
- tBTA_GATTC_ATTR_REC* p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
-
- /* if there are characteristic needs to be explored */
- if (p_srvc_cb->total_char > 0) {
- /* add the first characteristic into cache */
- bta_gattc_add_char_to_cache(p_srvc_cb, p_rec->char_decl_handle,
- p_rec->s_handle, &p_rec->uuid, p_rec->property);
-
- /* start discoverying characteristic descriptor , if failed, disc for next
- * char*/
- bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
- } else /* otherwise start with next service */
- {
- p_srvc_cb->cur_srvc_idx++;
-
- bta_gattc_explore_srvc(conn_id, p_srvc_cb);
- }
-}
-/*******************************************************************************
- *
- * Function bta_gattc_char_dscpt_disc_cmpl
- *
- * Description process the char descriptor discovery complete event
- *
- * Returns status
- *
- ******************************************************************************/
+/** process the char descriptor discovery complete event */
static void bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,
tBTA_GATTC_SERV* p_srvc_cb) {
- tBTA_GATTC_ATTR_REC* p_rec = NULL;
-
- if (--p_srvc_cb->total_char > 0) {
- p_rec = p_srvc_cb->p_srvc_list + (++p_srvc_cb->cur_char_idx);
- /* add the next characteristic into cache */
- bta_gattc_add_char_to_cache(p_srvc_cb, p_rec->char_decl_handle,
- p_rec->s_handle, &p_rec->uuid, p_rec->property);
-
+ ++p_srvc_cb->pending_char;
+ if (p_srvc_cb->pending_char !=
+ p_srvc_cb->pending_service->characteristics.end()) {
/* start discoverying next characteristic for char descriptor */
bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
- } else
+ return;
+ }
+
/* all characteristic has been explored, start with next service if any */
- {
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_ERROR("all char has been explored");
+ LOG(ERROR) << "all char has been explored";
#endif
- p_srvc_cb->cur_srvc_idx++;
- bta_gattc_explore_srvc(conn_id, p_srvc_cb);
- }
+ p_srvc_cb->pending_service++;
+ bta_gattc_explore_srvc(conn_id, p_srvc_cb);
}
-static bool bta_gattc_srvc_in_list(tBTA_GATTC_SERV* p_srvc_cb,
- uint16_t s_handle, uint16_t e_handle,
- UNUSED_ATTR tBT_UUID uuid) {
- tBTA_GATTC_ATTR_REC* p_rec = NULL;
- uint8_t i;
- bool exist_srvc = false;
+static bool bta_gattc_srvc_in_list(std::vector<tBTA_GATTC_SERVICE>& services,
+ uint16_t s_handle, uint16_t e_handle, Uuid) {
if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle)) {
- APPL_TRACE_ERROR("invalid included service handle: [0x%04x ~ 0x%04x]",
- s_handle, e_handle);
- exist_srvc = true;
- } else {
- for (i = 0; i < p_srvc_cb->next_avail_idx; i++) {
- p_rec = p_srvc_cb->p_srvc_list + i;
-
- /* a new service should not have any overlap with other service handle
- * range */
- if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle) {
- exist_srvc = true;
- break;
- }
- }
+ LOG(ERROR) << "invalid included service s_handle=" << loghex(s_handle)
+ << ", e_handle=" << loghex(e_handle);
+ return true;
}
- return exist_srvc;
-}
-/*******************************************************************************
- *
- * Function bta_gattc_add_srvc_to_list
- *
- * Description Add a service into explore pending list
- *
- * Returns status
- *
- ******************************************************************************/
-static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV* p_srvc_cb,
- uint16_t s_handle,
- uint16_t e_handle,
- tBT_UUID uuid,
- bool is_primary) {
- tBTA_GATTC_ATTR_REC* p_rec = NULL;
- tBTA_GATT_STATUS status = BTA_GATT_OK;
- if (p_srvc_cb->p_srvc_list &&
- p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) {
- p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
-
- APPL_TRACE_DEBUG("%s handle=%d, service type=0x%04x", __func__, s_handle,
- uuid.uu.uuid16);
-
- p_rec->s_handle = s_handle;
- p_rec->e_handle = e_handle;
- p_rec->is_primary = is_primary;
- memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
-
- p_srvc_cb->total_srvc++;
- p_srvc_cb->next_avail_idx++;
- } else { /* allocate bigger buffer ?? */
- status = GATT_DB_FULL;
-
- APPL_TRACE_ERROR("service not added, no resources or wrong state");
+ for (tBTA_GATTC_SERVICE& service : services) {
+ if (service.s_handle == s_handle || service.e_handle == e_handle)
+ return true;
}
- return status;
-}
-/*******************************************************************************
- *
- * Function bta_gattc_add_char_to_list
- *
- * Description Add a characteristic into explore pending list
- *
- * Returns status
- *
- ******************************************************************************/
-static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV* p_srvc_cb,
- uint16_t decl_handle,
- uint16_t value_handle,
- tBT_UUID uuid,
- uint8_t property) {
- tBTA_GATTC_ATTR_REC* p_rec = NULL;
- tBTA_GATT_STATUS status = BTA_GATT_OK;
- if (p_srvc_cb->p_srvc_list == NULL) {
- APPL_TRACE_ERROR("No service available, unexpected char discovery result");
- status = BTA_GATT_INTERNAL_ERROR;
- } else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) {
- p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
-
- p_srvc_cb->total_char++;
-
- p_rec->s_handle = value_handle;
- p_rec->char_decl_handle = decl_handle;
- p_rec->property = property;
- p_rec->e_handle =
- (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
- memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
-
- /* update the endind handle of pervious characteristic if available */
- if (p_srvc_cb->total_char > 1) {
- p_rec -= 1;
- p_rec->e_handle = decl_handle - 1;
- }
- p_srvc_cb->next_avail_idx++;
- } else {
- APPL_TRACE_ERROR("char not added, no resources");
- /* allocate bigger buffer ?? */
- status = BTA_GATT_DB_FULL;
- }
- return status;
+ return false;
}
/*******************************************************************************
@@ -710,51 +397,56 @@
*
******************************************************************************/
void bta_gattc_sdp_callback(uint16_t sdp_status, void* user_data) {
- tSDP_DISC_REC* p_sdp_rec = NULL;
- tBT_UUID service_uuid;
- tSDP_PROTOCOL_ELEM pe;
- uint16_t start_handle = 0, end_handle = 0;
tBTA_GATTC_CB_DATA* cb_data = (tBTA_GATTC_CB_DATA*)user_data;
tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_scb_by_cid(cb_data->sdp_conn_id);
- if (((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) &&
- p_srvc_cb != NULL) {
- do {
- /* find a service record, report it */
- p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
- if (p_sdp_rec) {
- if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
- if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT,
- &pe)) {
- start_handle = (uint16_t)pe.params[0];
- end_handle = (uint16_t)pe.params[1];
+ if (p_srvc_cb == nullptr) {
+ LOG(ERROR) << "GATT service discovery is done on unknown connection";
+ } else {
+ bool no_pending_disc = p_srvc_cb->pending_discovery.empty();
+
+ if ((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) {
+ tSDP_DISC_REC* p_sdp_rec = NULL;
+ do {
+ /* find a service record, report it */
+ p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
+ if (p_sdp_rec) {
+ Uuid service_uuid;
+ if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
+ tSDP_PROTOCOL_ELEM pe;
+ if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT,
+ &pe)) {
+ uint16_t start_handle = (uint16_t)pe.params[0];
+ uint16_t end_handle = (uint16_t)pe.params[1];
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_EVENT(
- "Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
- service_uuid.uu.uuid16, start_handle, end_handle);
+ VLOG(1) << "Found ATT service uuid=" << service_uuid
+ << ", s_handle=" << loghex(start_handle)
+ << ", e_handle=" << loghex(end_handle);
#endif
- if (GATT_HANDLE_IS_VALID(start_handle) &&
- GATT_HANDLE_IS_VALID(end_handle) && p_srvc_cb != NULL) {
- /* discover services result, add services into a service list */
- bta_gattc_add_srvc_to_list(p_srvc_cb, start_handle, end_handle,
- service_uuid, true);
- } else {
- APPL_TRACE_ERROR("invalid start_handle = %d end_handle = %d",
- start_handle, end_handle);
+ if (GATT_HANDLE_IS_VALID(start_handle) &&
+ GATT_HANDLE_IS_VALID(end_handle) && p_srvc_cb != NULL) {
+ /* discover services result, add services into a service list */
+ add_service_to_gatt_db(p_srvc_cb->pending_discovery,
+ start_handle, end_handle, service_uuid,
+ true);
+ } else {
+ LOG(ERROR) << "invalid start_handle=" << loghex(start_handle)
+ << ", end_handle=" << loghex(end_handle);
+ }
}
}
}
- }
- } while (p_sdp_rec);
- }
+ } while (p_sdp_rec);
+ }
- if (p_srvc_cb != NULL) {
+ if (no_pending_disc) {
+ p_srvc_cb->pending_service = p_srvc_cb->pending_discovery.begin();
+ }
+
/* start discover primary service */
bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb);
- } else {
- APPL_TRACE_ERROR("GATT service discovery is done on unknown connection");
}
/* both were allocated in bta_gattc_sdp_service_disc */
@@ -770,17 +462,11 @@
* Returns void
*
******************************************************************************/
-static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(
- uint16_t conn_id, tBTA_GATTC_SERV* p_server_cb) {
- tSDP_UUID uuid;
+static tGATT_STATUS bta_gattc_sdp_service_disc(uint16_t conn_id,
+ tBTA_GATTC_SERV* p_server_cb) {
uint16_t num_attrs = 2;
uint16_t attr_list[2];
- memset(&uuid, 0, sizeof(tSDP_UUID));
-
- uuid.len = LEN_UUID_16;
- uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
-
/*
* On success, cb_data will be freed inside bta_gattc_sdp_callback,
* otherwise it will be freed within this function.
@@ -792,6 +478,7 @@
attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+ Uuid uuid = Uuid::From16Bit(UUID_PROTOCOL_ATT);
SDP_InitDiscoveryDb(cb_data->p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1, &uuid,
num_attrs, attr_list);
@@ -800,86 +487,67 @@
&bta_gattc_sdp_callback, cb_data)) {
osi_free(cb_data->p_sdp_db);
osi_free(cb_data);
- return BTA_GATT_ERROR;
+ return GATT_ERROR;
}
cb_data->sdp_conn_id = conn_id;
- return BTA_GATT_OK;
+ return GATT_SUCCESS;
}
-/*******************************************************************************
- *
- * Function bta_gattc_disc_res_cback
- * bta_gattc_disc_cmpl_cback
- *
- * Description callback functions to GATT client stack.
- *
- * Returns void
- *
- ******************************************************************************/
+
+/** callback function to GATT client stack */
void bta_gattc_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
tGATT_DISC_RES* p_data) {
- tBTA_GATTC_SERV* p_srvc_cb = NULL;
- bool pri_srvc;
tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
- p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
+ if (!p_srvc_cb || !p_clcb || p_clcb->state != BTA_GATTC_DISCOVER_ST) return;
- if (p_srvc_cb != NULL && p_clcb != NULL &&
- p_clcb->state == BTA_GATTC_DISCOVER_ST) {
- switch (disc_type) {
- case GATT_DISC_SRVC_ALL:
- /* discover services result, add services into a service list */
- bta_gattc_add_srvc_to_list(
- p_srvc_cb, p_data->handle, p_data->value.group_value.e_handle,
- p_data->value.group_value.service_type, true);
+ switch (disc_type) {
+ case GATT_DISC_SRVC_ALL:
+ case GATT_DISC_SRVC_BY_UUID:
+ /* discover services result, add services into a service list */
+ add_service_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
+ p_data->value.group_value.e_handle,
+ p_data->value.group_value.service_type, true);
+ break;
- break;
- case GATT_DISC_SRVC_BY_UUID:
- bta_gattc_add_srvc_to_list(
- p_srvc_cb, p_data->handle, p_data->value.group_value.e_handle,
- p_data->value.group_value.service_type, true);
- break;
+ case GATT_DISC_INC_SRVC:
+ /* add included service into service list if it's secondary or it never
+ showed up in the primary service search */
+ if (!bta_gattc_srvc_in_list(p_srvc_cb->pending_discovery,
+ p_data->value.incl_service.s_handle,
+ p_data->value.incl_service.e_handle,
+ p_data->value.incl_service.service_type)) {
+ add_service_to_gatt_db(p_srvc_cb->pending_discovery,
+ p_data->value.incl_service.s_handle,
+ p_data->value.incl_service.e_handle,
+ p_data->value.incl_service.service_type, false);
+ }
- case GATT_DISC_INC_SRVC:
- /* add included service into service list if it's secondary or it never
- showed up
- in the primary service search */
- pri_srvc = bta_gattc_srvc_in_list(
- p_srvc_cb, p_data->value.incl_service.s_handle,
- p_data->value.incl_service.e_handle,
- p_data->value.incl_service.service_type);
+ /* add into database */
+ add_incl_srvc_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
+ p_data->value.incl_service.service_type,
+ p_data->value.incl_service.s_handle);
+ break;
- if (!pri_srvc)
- bta_gattc_add_srvc_to_list(
- p_srvc_cb, p_data->value.incl_service.s_handle,
- p_data->value.incl_service.e_handle,
- p_data->value.incl_service.service_type, false);
- /* add into database */
- bta_gattc_add_attr_to_cache(
- p_srvc_cb, p_data->handle, &p_data->value.incl_service.service_type,
- pri_srvc, p_data->value.incl_service.s_handle,
- BTA_GATTC_ATTR_TYPE_INCL_SRVC);
- break;
+ case GATT_DISC_CHAR:
+ /* add char value into database */
+ add_characteristic_to_gatt_db(p_srvc_cb->pending_discovery,
+ p_data->handle,
+ p_data->value.dclr_value.val_handle,
+ p_data->value.dclr_value.char_uuid,
+ p_data->value.dclr_value.char_prop);
+ break;
- case GATT_DISC_CHAR:
- /* add char value into database */
- bta_gattc_add_char_to_list(p_srvc_cb, p_data->handle,
- p_data->value.dclr_value.val_handle,
- p_data->value.dclr_value.char_uuid,
- p_data->value.dclr_value.char_prop);
- break;
-
- case GATT_DISC_CHAR_DSCPT:
- bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
- 0 /* incl_srvc_handle */,
- BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
- break;
- }
+ case GATT_DISC_CHAR_DSCPT:
+ add_descriptor_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
+ p_data->type);
+ break;
}
}
+
void bta_gattc_disc_cmpl_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
tGATT_STATUS status) {
- tBTA_GATTC_SERV* p_srvc_cb;
tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
if (p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS)) {
@@ -887,87 +555,85 @@
bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
return;
}
- p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
- if (p_srvc_cb != NULL) {
- switch (disc_type) {
- case GATT_DISC_SRVC_ALL:
- case GATT_DISC_SRVC_BY_UUID:
+ tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
+ if (!p_srvc_cb) return;
+
+ switch (disc_type) {
+ case GATT_DISC_SRVC_ALL:
+ case GATT_DISC_SRVC_BY_UUID:
+// definition of all services are discovered, now it's time to discover
+// their content
#if (BTA_GATT_DEBUG == TRUE)
- bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list,
- p_srvc_cb->next_avail_idx);
+ bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
#endif
- bta_gattc_explore_srvc(conn_id, p_srvc_cb);
- break;
+ p_srvc_cb->pending_service = p_srvc_cb->pending_discovery.begin();
+ bta_gattc_explore_srvc(conn_id, p_srvc_cb);
+ break;
- case GATT_DISC_INC_SRVC:
- bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
+ case GATT_DISC_INC_SRVC: {
+ auto& service = *p_srvc_cb->pending_service;
- break;
+ /* start discoverying characteristic */
- case GATT_DISC_CHAR:
-#if (BTA_GATT_DEBUG == TRUE)
- bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list,
- p_srvc_cb->next_avail_idx);
-#endif
- bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
- break;
-
- case GATT_DISC_CHAR_DSCPT:
- bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
- break;
+ tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
+ .e_handle = service.e_handle};
+ GATTC_Discover(conn_id, GATT_DISC_CHAR, ¶m);
+ break;
}
+
+ case GATT_DISC_CHAR: {
+#if (BTA_GATT_DEBUG == TRUE)
+ bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
+#endif
+ auto& service = *p_srvc_cb->pending_service;
+ if (!service.characteristics.empty()) {
+ /* discover descriptors */
+ p_srvc_cb->pending_char = service.characteristics.begin();
+ bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
+ return;
+ }
+ /* start next service */
+ ++p_srvc_cb->pending_service;
+ bta_gattc_explore_srvc(conn_id, p_srvc_cb);
+ break;
+ }
+
+ case GATT_DISC_CHAR_DSCPT:
+ bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+ break;
}
}
-/*******************************************************************************
- *
- * Function bta_gattc_search_service
- *
- * Description search local cache for matching service record.
- *
- * Returns false if map can not be found.
- *
- ******************************************************************************/
-void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb, tBT_UUID* p_uuid) {
- tBTA_GATTC cb_data;
-
- if (!p_clcb->p_srcb->p_srvc_cache ||
- list_is_empty(p_clcb->p_srcb->p_srvc_cache))
- return;
-
- for (list_node_t* sn = list_begin(p_clcb->p_srcb->p_srvc_cache);
- sn != list_end(p_clcb->p_srcb->p_srvc_cache); sn = list_next(sn)) {
- tBTA_GATTC_SERVICE* p_cache = (tBTA_GATTC_SERVICE*)list_node(sn);
-
- if (!bta_gattc_uuid_compare(p_uuid, &p_cache->uuid, false)) continue;
+/** search local cache for matching service record */
+void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb, Uuid* p_uuid) {
+ for (const tBTA_GATTC_SERVICE& service : p_clcb->p_srcb->srvc_cache) {
+ if (p_uuid && *p_uuid != service.uuid) continue;
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
- p_cache->uuid.uu.uuid16, p_cache->handle,
- p_cache->s_handle);
+ VLOG(1) << __func__ << "found service " << service.uuid
+ << ", inst:" << +service.handle << " handle:" << +service.s_handle;
#endif
if (!p_clcb->p_rcb->p_cback) continue;
+ tBTA_GATTC cb_data;
memset(&cb_data, 0, sizeof(tBTA_GATTC));
-
cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
- cb_data.srvc_res.service_uuid.inst_id = p_cache->handle;
- memcpy(&cb_data.srvc_res.service_uuid.uuid, &p_cache->uuid,
- sizeof(tBTA_GATT_ID));
+ cb_data.srvc_res.service_uuid.inst_id = service.handle;
+ cb_data.srvc_res.service_uuid.uuid = service.uuid;
(*p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
}
}
-list_t* bta_gattc_get_services_srcb(tBTA_GATTC_SERV* p_srcb) {
- if (!p_srcb || !p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
- return NULL;
+std::vector<tBTA_GATTC_SERVICE>* bta_gattc_get_services_srcb(
+ tBTA_GATTC_SERV* p_srcb) {
+ if (!p_srcb || p_srcb->srvc_cache.empty()) return NULL;
- return p_srcb->p_srvc_cache;
+ return &p_srcb->srvc_cache;
}
-const list_t* bta_gattc_get_services(uint16_t conn_id) {
+std::vector<tBTA_GATTC_SERVICE>* bta_gattc_get_services(uint16_t conn_id) {
tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
if (p_clcb == NULL) return NULL;
@@ -977,47 +643,31 @@
return bta_gattc_get_services_srcb(p_srcb);
}
-tBTA_GATTC_SERVICE* bta_gattc_find_matching_service(const list_t* services,
- uint16_t handle) {
- if (!services || list_is_empty(services)) return NULL;
-
- for (list_node_t* sn = list_begin(services); sn != list_end(services);
- sn = list_next(sn)) {
- tBTA_GATTC_SERVICE* service = (tBTA_GATTC_SERVICE*)list_node(sn);
-
- if (handle >= service->s_handle && handle <= service->e_handle)
- return service;
- }
-
- return NULL;
-}
-
-const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle_srcb(
+tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle_srcb(
tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
- const list_t* services = bta_gattc_get_services_srcb(p_srcb);
-
- return bta_gattc_find_matching_service(services, handle);
+ std::vector<tBTA_GATTC_SERVICE>* services =
+ bta_gattc_get_services_srcb(p_srcb);
+ if (services == NULL) return NULL;
+ return bta_gattc_find_matching_service(*services, handle);
}
const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(uint16_t conn_id,
uint16_t handle) {
- const list_t* services = bta_gattc_get_services(conn_id);
+ std::vector<tBTA_GATTC_SERVICE>* services = bta_gattc_get_services(conn_id);
+ if (services == NULL) return NULL;
- return bta_gattc_find_matching_service(services, handle);
+ return bta_gattc_find_matching_service(*services, handle);
}
tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
- const tBTA_GATTC_SERVICE* service =
+ tBTA_GATTC_SERVICE* service =
bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
if (!service) return NULL;
- for (list_node_t* cn = list_begin(service->characteristics);
- cn != list_end(service->characteristics); cn = list_next(cn)) {
- tBTA_GATTC_CHARACTERISTIC* p_char =
- (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
- if (handle == p_char->handle) return p_char;
+ for (tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+ if (handle == charac.value_handle) return &charac;
}
return NULL;
@@ -1033,8 +683,8 @@
return bta_gattc_get_characteristic_srcb(p_srcb, handle);
}
-tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV* p_srcb,
- uint16_t handle) {
+const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(
+ tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
const tBTA_GATTC_SERVICE* service =
bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
@@ -1042,22 +692,17 @@
return NULL;
}
- for (list_node_t* cn = list_begin(service->characteristics);
- cn != list_end(service->characteristics); cn = list_next(cn)) {
- tBTA_GATTC_CHARACTERISTIC* p_char =
- (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
- for (list_node_t* dn = list_begin(p_char->descriptors);
- dn != list_end(p_char->descriptors); dn = list_next(dn)) {
- tBTA_GATTC_DESCRIPTOR* p_desc = (tBTA_GATTC_DESCRIPTOR*)list_node(dn);
- if (handle == p_desc->handle) return p_desc;
+ for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+ for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
+ if (handle == desc.handle) return &desc;
}
}
return NULL;
}
-tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(uint16_t conn_id,
- uint16_t handle) {
+const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(uint16_t conn_id,
+ uint16_t handle) {
tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
if (p_clcb == NULL) return NULL;
@@ -1066,6 +711,30 @@
return bta_gattc_get_descriptor_srcb(p_srcb, handle);
}
+tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_owning_characteristic_srcb(
+ tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
+ tBTA_GATTC_SERVICE* service =
+ bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
+
+ if (!service) return NULL;
+
+ for (tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+ for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
+ if (handle == desc.handle) return &charac;
+ }
+ }
+
+ return NULL;
+}
+
+const tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_owning_characteristic(
+ uint16_t conn_id, uint16_t handle) {
+ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ if (!p_clcb) return NULL;
+
+ return bta_gattc_get_owning_characteristic_srcb(p_clcb->p_srcb, handle);
+}
+
/*******************************************************************************
*
* Function bta_gattc_fill_gatt_db_el
@@ -1078,7 +747,7 @@
void bta_gattc_fill_gatt_db_el(btgatt_db_element_t* p_attr,
bt_gatt_db_attribute_type_t type,
uint16_t att_handle, uint16_t s_handle,
- uint16_t e_handle, uint16_t id, tBT_UUID uuid,
+ uint16_t e_handle, uint16_t id, const Uuid& uuid,
uint8_t prop) {
p_attr->type = type;
p_attr->attribute_handle = att_handle;
@@ -1090,43 +759,33 @@
// Permissions are not discoverable using the attribute protocol.
// Core 5.0, Part F, 3.2.5 Attribute Permissions
p_attr->permissions = 0;
- bta_to_btif_uuid(&p_attr->uuid, &uuid);
+ p_attr->uuid = uuid;
}
/*******************************************************************************
* Returns number of elements inside db from start_handle to end_handle
******************************************************************************/
-static size_t bta_gattc_get_db_size(list_t* services, uint16_t start_handle,
- uint16_t end_handle) {
- if (!services || list_is_empty(services)) return 0;
+static size_t bta_gattc_get_db_size(
+ const std::vector<tBTA_GATTC_SERVICE>& services, uint16_t start_handle,
+ uint16_t end_handle) {
+ if (services.empty()) return 0;
size_t db_size = 0;
- for (list_node_t* sn = list_begin(services); sn != list_end(services);
- sn = list_next(sn)) {
- tBTA_GATTC_SERVICE* p_cur_srvc = (tBTA_GATTC_SERVICE*)list_node(sn);
+ for (const tBTA_GATTC_SERVICE& service : services) {
+ if (service.s_handle < start_handle) continue;
- if (p_cur_srvc->s_handle < start_handle) continue;
-
- if (p_cur_srvc->e_handle > end_handle) break;
+ if (service.e_handle > end_handle) break;
db_size++;
- if (!p_cur_srvc->characteristics ||
- list_is_empty(p_cur_srvc->characteristics))
- continue;
- for (list_node_t* cn = list_begin(p_cur_srvc->characteristics);
- cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
- tBTA_GATTC_CHARACTERISTIC* p_char =
- (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
+ for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
db_size++;
- if (p_char->descriptors) db_size += list_length(p_char->descriptors);
+ db_size += charac.descriptors.size();
}
- if (p_cur_srvc->included_svc) {
- db_size += list_length(p_cur_srvc->included_svc);
- }
+ db_size += service.included_svc.size();
}
return db_size;
@@ -1151,77 +810,55 @@
uint16_t start_handle,
uint16_t end_handle,
btgatt_db_element_t** db, int* count) {
- APPL_TRACE_DEBUG("%s: start_handle 0x%04x, end_handle 0x%04x", __func__,
- start_handle, end_handle);
+ VLOG(1) << __func__
+ << StringPrintf(": start_handle 0x%04x, end_handle 0x%04x",
+ start_handle, end_handle);
- if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) {
+ if (p_srvc_cb->srvc_cache.empty()) {
*count = 0;
*db = NULL;
return;
}
size_t db_size =
- bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, start_handle, end_handle);
+ bta_gattc_get_db_size(p_srvc_cb->srvc_cache, start_handle, end_handle);
void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t));
btgatt_db_element_t* curr_db_attr = (btgatt_db_element_t*)buffer;
- for (list_node_t* sn = list_begin(p_srvc_cb->p_srvc_cache);
- sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
- tBTA_GATTC_SERVICE* p_cur_srvc = (tBTA_GATTC_SERVICE*)list_node(sn);
+ for (const tBTA_GATTC_SERVICE& service : p_srvc_cb->srvc_cache) {
+ if (service.s_handle < start_handle) continue;
- if (p_cur_srvc->s_handle < start_handle) continue;
+ if (service.e_handle > end_handle) break;
- if (p_cur_srvc->e_handle > end_handle) break;
-
- bta_gattc_fill_gatt_db_el(
- curr_db_attr, p_cur_srvc->is_primary ? BTGATT_DB_PRIMARY_SERVICE
- : BTGATT_DB_SECONDARY_SERVICE,
- 0 /* att_handle */, p_cur_srvc->s_handle, p_cur_srvc->e_handle,
- p_cur_srvc->s_handle, p_cur_srvc->uuid, 0 /* prop */);
+ bta_gattc_fill_gatt_db_el(curr_db_attr,
+ service.is_primary ? BTGATT_DB_PRIMARY_SERVICE
+ : BTGATT_DB_SECONDARY_SERVICE,
+ 0 /* att_handle */, service.s_handle,
+ service.e_handle, service.s_handle, service.uuid,
+ 0 /* prop */);
curr_db_attr++;
- if (!p_cur_srvc->characteristics ||
- list_is_empty(p_cur_srvc->characteristics))
- continue;
-
- for (list_node_t* cn = list_begin(p_cur_srvc->characteristics);
- cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
- tBTA_GATTC_CHARACTERISTIC* p_char =
- (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
-
+ for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
bta_gattc_fill_gatt_db_el(curr_db_attr, BTGATT_DB_CHARACTERISTIC,
- p_char->handle, 0 /* s_handle */,
- 0 /* e_handle */, p_char->handle, p_char->uuid,
- p_char->properties);
+ charac.value_handle, 0 /* s_handle */,
+ 0 /* e_handle */, charac.value_handle,
+ charac.uuid, charac.properties);
curr_db_attr++;
- if (!p_char->descriptors || list_is_empty(p_char->descriptors)) continue;
-
- for (list_node_t* dn = list_begin(p_char->descriptors);
- dn != list_end(p_char->descriptors); dn = list_next(dn)) {
- tBTA_GATTC_DESCRIPTOR* p_desc = (tBTA_GATTC_DESCRIPTOR*)list_node(dn);
-
- bta_gattc_fill_gatt_db_el(curr_db_attr, BTGATT_DB_DESCRIPTOR,
- p_desc->handle, 0 /* s_handle */,
- 0 /* e_handle */, p_desc->handle,
- p_desc->uuid, 0 /* property */);
+ for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
+ bta_gattc_fill_gatt_db_el(
+ curr_db_attr, BTGATT_DB_DESCRIPTOR, desc.handle, 0 /* s_handle */,
+ 0 /* e_handle */, desc.handle, desc.uuid, 0 /* property */);
curr_db_attr++;
}
}
- if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
- continue;
-
- for (list_node_t* isn = list_begin(p_cur_srvc->included_svc);
- isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
- tBTA_GATTC_INCLUDED_SVC* p_isvc =
- (tBTA_GATTC_INCLUDED_SVC*)list_node(isn);
-
- bta_gattc_fill_gatt_db_el(curr_db_attr, BTGATT_DB_INCLUDED_SERVICE,
- p_isvc->handle, 0 /* s_handle */,
- 0 /* e_handle */, p_isvc->handle, p_isvc->uuid,
- 0 /* property */);
+ for (const tBTA_GATTC_INCLUDED_SVC& p_isvc : service.included_svc) {
+ bta_gattc_fill_gatt_db_el(
+ curr_db_attr, BTGATT_DB_INCLUDED_SERVICE, p_isvc.handle,
+ p_isvc.included_service ? p_isvc.included_service->s_handle : 0,
+ 0 /* e_handle */, p_isvc.handle, p_isvc.uuid, 0 /* property */);
curr_db_attr++;
}
}
@@ -1251,20 +888,19 @@
LOG_DEBUG(LOG_TAG, "%s", __func__);
if (p_clcb == NULL) {
- APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
+ LOG(ERROR) << "Unknown conn_id=" << loghex(conn_id);
return;
}
if (p_clcb->state != BTA_GATTC_CONN_ST) {
- APPL_TRACE_ERROR("server cache not available, CLCB state = %d",
- p_clcb->state);
+ LOG(ERROR) << "server cache not available, CLCB state=" << +p_clcb->state;
return;
}
if (!p_clcb->p_srcb ||
- p_clcb->p_srcb->p_srvc_list || /* no active discovery */
- !p_clcb->p_srcb->p_srvc_cache) {
- APPL_TRACE_ERROR("No server cache available");
+ !p_clcb->p_srcb->pending_discovery.empty() || /* no active discovery */
+ p_clcb->p_srcb->srvc_cache.empty()) {
+ LOG(ERROR) << "No server cache available";
return;
}
@@ -1272,45 +908,36 @@
count);
}
-/*******************************************************************************
- *
- * Function bta_gattc_rebuild_cache
- *
- * Description rebuild server cache from NV cache.
- *
- * Parameters
- *
- * Returns None.
- *
- ******************************************************************************/
+/* rebuild server cache from NV cache */
void bta_gattc_rebuild_cache(tBTA_GATTC_SERV* p_srvc_cb, uint16_t num_attr,
tBTA_GATTC_NV_ATTR* p_attr) {
/* first attribute loading, initialize buffer */
- APPL_TRACE_ERROR("%s: bta_gattc_rebuild_cache", __func__);
+ LOG(INFO) << __func__ << " " << num_attr;
- list_free(p_srvc_cb->p_srvc_cache);
- p_srvc_cb->p_srvc_cache = NULL;
+ // clear reallocating
+ std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->srvc_cache);
while (num_attr > 0 && p_attr != NULL) {
switch (p_attr->attr_type) {
case BTA_GATTC_ATTR_TYPE_SRVC:
- bta_gattc_add_srvc_to_cache(p_srvc_cb, p_attr->s_handle,
- p_attr->e_handle, &p_attr->uuid,
- p_attr->is_primary);
+ add_service_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
+ p_attr->e_handle, p_attr->uuid,
+ p_attr->is_primary);
break;
case BTA_GATTC_ATTR_TYPE_CHAR:
- // TODO(jpawlowski): store decl_handle properly.
- bta_gattc_add_char_to_cache(p_srvc_cb, p_attr->s_handle,
- p_attr->s_handle, &p_attr->uuid,
- p_attr->prop);
+ add_characteristic_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
+ p_attr->s_handle, p_attr->uuid,
+ p_attr->prop);
break;
case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
+ add_descriptor_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
+ p_attr->uuid);
+ break;
case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
- bta_gattc_add_attr_to_cache(p_srvc_cb, p_attr->s_handle, &p_attr->uuid,
- p_attr->prop, p_attr->incl_srvc_handle,
- p_attr->attr_type);
+ add_incl_srvc_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
+ p_attr->uuid, p_attr->incl_srvc_handle);
break;
}
p_attr++;
@@ -1328,7 +955,7 @@
*
******************************************************************************/
void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR* p_attr, uint8_t type,
- uint16_t s_handle, uint16_t e_handle, tBT_UUID uuid,
+ uint16_t s_handle, uint16_t e_handle, Uuid uuid,
uint8_t prop, uint16_t incl_srvc_handle,
bool is_primary) {
p_attr->s_handle = s_handle;
@@ -1338,8 +965,7 @@
p_attr->id = 0;
p_attr->prop = prop;
p_attr->incl_srvc_handle = incl_srvc_handle;
-
- memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
+ p_attr->uuid = uuid;
}
/*******************************************************************************
@@ -1352,65 +978,37 @@
*
******************************************************************************/
void bta_gattc_cache_save(tBTA_GATTC_SERV* p_srvc_cb, uint16_t conn_id) {
- if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache))
- return;
+ if (p_srvc_cb->srvc_cache.empty()) return;
int i = 0;
- size_t db_size =
- bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, 0x0000, 0xFFFF);
+ size_t db_size = bta_gattc_get_db_size(p_srvc_cb->srvc_cache, 0x0000, 0xFFFF);
tBTA_GATTC_NV_ATTR* nv_attr =
(tBTA_GATTC_NV_ATTR*)osi_malloc(db_size * sizeof(tBTA_GATTC_NV_ATTR));
- for (list_node_t* sn = list_begin(p_srvc_cb->p_srvc_cache);
- sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
- tBTA_GATTC_SERVICE* p_cur_srvc = (tBTA_GATTC_SERVICE*)list_node(sn);
-
+ for (const tBTA_GATTC_SERVICE& service : p_srvc_cb->srvc_cache) {
bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_SRVC,
- p_cur_srvc->s_handle, p_cur_srvc->e_handle,
- p_cur_srvc->uuid, 0 /* properties */,
- 0 /* incl_srvc_handle */, p_cur_srvc->is_primary);
+ service.s_handle, service.e_handle, service.uuid,
+ 0 /* properties */, 0 /* incl_srvc_handle */,
+ service.is_primary);
}
- for (list_node_t* sn = list_begin(p_srvc_cb->p_srvc_cache);
- sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
- tBTA_GATTC_SERVICE* p_cur_srvc = (tBTA_GATTC_SERVICE*)list_node(sn);
-
- if (!p_cur_srvc->characteristics ||
- list_is_empty(p_cur_srvc->characteristics))
- continue;
-
- for (list_node_t* cn = list_begin(p_cur_srvc->characteristics);
- cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
- tBTA_GATTC_CHARACTERISTIC* p_char =
- (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
-
+ for (const tBTA_GATTC_SERVICE& service : p_srvc_cb->srvc_cache) {
+ for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
bta_gattc_fill_nv_attr(
- &nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR, p_char->handle, 0,
- p_char->uuid, p_char->properties, 0 /* incl_srvc_handle */, false);
+ &nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR, charac.value_handle, 0,
+ charac.uuid, charac.properties, 0 /* incl_srvc_handle */, false);
- if (!p_char->descriptors || list_is_empty(p_char->descriptors)) continue;
-
- for (list_node_t* dn = list_begin(p_char->descriptors);
- dn != list_end(p_char->descriptors); dn = list_next(dn)) {
- tBTA_GATTC_DESCRIPTOR* p_desc = (tBTA_GATTC_DESCRIPTOR*)list_node(dn);
-
- bta_gattc_fill_nv_attr(
- &nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR_DESCR, p_desc->handle, 0,
- p_desc->uuid, 0 /* properties */, 0 /* incl_srvc_handle */, false);
+ for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
+ bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+ desc.handle, 0, desc.uuid, 0 /* properties */,
+ 0 /* incl_srvc_handle */, false);
}
}
- if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
- continue;
-
- for (list_node_t* an = list_begin(p_cur_srvc->included_svc);
- an != list_end(p_cur_srvc->included_svc); an = list_next(an)) {
- tBTA_GATTC_INCLUDED_SVC* p_isvc = (tBTA_GATTC_INCLUDED_SVC*)list_node(an);
-
+ for (const tBTA_GATTC_INCLUDED_SVC& p_isvc : service.included_svc) {
bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_INCL_SRVC,
- p_isvc->handle, 0, p_isvc->uuid,
- 0 /* properties */,
- p_isvc->included_service->s_handle, false);
+ p_isvc.handle, 0, p_isvc.uuid, 0 /* properties */,
+ p_isvc.included_service->s_handle, false);
}
}
@@ -1436,8 +1034,8 @@
FILE* fd = fopen(fname, "rb");
if (!fd) {
- APPL_TRACE_ERROR("%s: can't open GATT cache file %s for reading, error: %s",
- __func__, fname, strerror(errno));
+ LOG(ERROR) << __func__ << ": can't open GATT cache file " << fname
+ << " for reading, error: " << strerror(errno);
return false;
}
@@ -1447,31 +1045,25 @@
uint16_t num_attr = 0;
if (fread(&cache_ver, sizeof(uint16_t), 1, fd) != 1) {
- APPL_TRACE_ERROR("%s: can't read GATT cache version from: %s", __func__,
- fname);
+ LOG(ERROR) << __func__ << ": can't read GATT cache version from: " << fname;
goto done;
}
if (cache_ver != GATT_CACHE_VERSION) {
- APPL_TRACE_ERROR("%s: wrong GATT cache version: %s", __func__, fname);
+ LOG(ERROR) << __func__ << ": wrong GATT cache version: " << fname;
goto done;
}
if (fread(&num_attr, sizeof(uint16_t), 1, fd) != 1) {
- APPL_TRACE_ERROR("%s: can't read number of GATT attributes: %s", __func__,
- fname);
- goto done;
- }
-
- if (num_attr > 0xFFFF) {
- APPL_TRACE_ERROR("%s: more than 0xFFFF GATT attributes: %s", __func__, fname);
+ LOG(ERROR) << __func__
+ << ": can't read number of GATT attributes: " << fname;
goto done;
}
attr = (tBTA_GATTC_NV_ATTR*)osi_malloc(sizeof(tBTA_GATTC_NV_ATTR) * num_attr);
if (fread(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
- APPL_TRACE_ERROR("%s: can't read GATT attributes: %s", __func__, fname);
+ LOG(ERROR) << __func__ << "s: can't read GATT attributes: " << fname;
goto done;
}
@@ -1505,28 +1097,27 @@
FILE* fd = fopen(fname, "wb");
if (!fd) {
- APPL_TRACE_ERROR("%s: can't open GATT cache file for writing: %s", __func__,
- fname);
+ LOG(ERROR) << __func__
+ << ": can't open GATT cache file for writing: " << fname;
return;
}
uint16_t cache_ver = GATT_CACHE_VERSION;
if (fwrite(&cache_ver, sizeof(uint16_t), 1, fd) != 1) {
- APPL_TRACE_ERROR("%s: can't write GATT cache version: %s", __func__, fname);
+ LOG(ERROR) << __func__ << ": can't write GATT cache version: " << fname;
fclose(fd);
return;
}
if (fwrite(&num_attr, sizeof(uint16_t), 1, fd) != 1) {
- APPL_TRACE_ERROR("%s: can't write GATT cache attribute count: %s", __func__,
- fname);
+ LOG(ERROR) << __func__
+ << ": can't write GATT cache attribute count: " << fname;
fclose(fd);
return;
}
if (fwrite(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
- APPL_TRACE_ERROR("%s: can't write GATT cache attributes: %s", __func__,
- fname);
+ LOG(ERROR) << __func__ << ": can't write GATT cache attributes: " << fname;
fclose(fd);
return;
}
@@ -1547,7 +1138,7 @@
*
******************************************************************************/
void bta_gattc_cache_reset(const RawAddress& server_bda) {
- BTIF_TRACE_DEBUG("%s", __func__);
+ VLOG(1) << __func__;
char fname[255] = {0};
bta_gattc_generate_cache_file_name(fname, sizeof(fname), server_bda);
unlink(fname);
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index 8055090..5b33eae 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,9 @@
#include "bt_common.h"
+#include <base/logging.h>
+#include <base/strings/stringprintf.h>
+
/*****************************************************************************
* Constants and data types
****************************************************************************/
@@ -84,7 +87,7 @@
typedef struct {
BT_HDR hdr;
RawAddress remote_bda;
- tBTA_GATTC_IF client_if;
+ tGATT_IF client_if;
bool is_direct;
tBTA_TRANSPORT transport;
uint8_t initiating_phys;
@@ -95,13 +98,13 @@
typedef struct {
BT_HDR hdr;
- tBTA_GATT_AUTH_REQ auth_req;
+ tGATT_AUTH_REQ auth_req;
// read by handle data
uint16_t handle;
// read by UUID data
- tBT_UUID uuid;
+ bluetooth::Uuid uuid;
uint16_t s_handle;
uint16_t e_handle;
@@ -112,9 +115,9 @@
typedef struct {
BT_HDR hdr;
- tBTA_GATT_AUTH_REQ auth_req;
+ tGATT_AUTH_REQ auth_req;
uint16_t handle;
- tBTA_GATTC_WRITE_TYPE write_type;
+ tGATT_WRITE_TYPE write_type;
uint16_t offset;
uint16_t len;
uint8_t* p_value;
@@ -143,12 +146,12 @@
typedef struct {
BT_HDR hdr;
- tBT_UUID* p_srvc_uuid;
+ bluetooth::Uuid* p_srvc_uuid;
} tBTA_GATTC_API_SEARCH;
typedef struct {
BT_HDR hdr;
- tBTA_GATT_AUTH_REQ auth_req;
+ tGATT_AUTH_REQ auth_req;
uint8_t num_attr;
uint16_t handles[GATT_MAX_READ_MULTI_HANDLES];
} tBTA_GATTC_API_READ_MULTI;
@@ -161,7 +164,7 @@
typedef struct {
BT_HDR hdr;
RawAddress remote_bda;
- tBTA_GATTC_IF client_if;
+ tGATT_IF client_if;
uint8_t role;
tBT_TRANSPORT transport;
tGATT_DISCONN_REASON reason;
@@ -182,26 +185,6 @@
tBTA_GATTC_INT_CONN int_conn;
} tBTA_GATTC_DATA;
-/* GATT server cache on the client */
-
-typedef struct {
- tBT_UUID uuid;
- uint16_t s_handle;
- uint16_t e_handle;
- // this field is set only for characteristic
- uint16_t char_decl_handle;
- bool is_primary;
- tBTA_GATT_CHAR_PROP property;
-} tBTA_GATTC_ATTR_REC;
-
-#define BTA_GATTC_MAX_CACHE_CHAR 40
-#define BTA_GATTC_ATTR_LIST_SIZE \
- (BTA_GATTC_MAX_CACHE_CHAR * sizeof(tBTA_GATTC_ATTR_REC))
-
-#ifndef BTA_GATTC_CACHE_SRVR_SIZE
-#define BTA_GATTC_CACHE_SRVR_SIZE 600
-#endif
-
enum {
BTA_GATTC_IDLE_ST = 0, /* Idle */
BTA_GATTC_W4_CONN_ST, /* Wait for connection - (optional) */
@@ -223,16 +206,13 @@
uint8_t state;
- list_t* p_srvc_cache; /* list of tBTA_GATTC_SERVICE */
+ std::vector<tBTA_GATTC_SERVICE> srvc_cache;
uint8_t update_count; /* indication received */
uint8_t num_clcb; /* number of associated CLCB */
- tBTA_GATTC_ATTR_REC* p_srvc_list;
- uint8_t cur_srvc_idx;
- uint8_t cur_char_idx;
- uint8_t next_avail_idx;
- uint8_t total_srvc;
- uint8_t total_char;
+ std::vector<tBTA_GATTC_SERVICE> pending_discovery;
+ std::vector<tBTA_GATTC_SERVICE>::iterator pending_service;
+ std::vector<tBTA_GATTC_CHARACTERISTIC>::iterator pending_char;
uint8_t srvc_hdl_chg; /* service handle change indication pending */
uint16_t attr_index; /* cahce NV saving/loading attribute index */
@@ -253,11 +233,10 @@
typedef struct {
tBTA_GATTC_CBACK* p_cback;
bool in_use;
- tBTA_GATTC_IF
- client_if; /* client interface with BTE stack for this application */
+ tGATT_IF client_if; /* client interface with BTE stack for this application */
uint8_t num_clcb; /* number of associated CLCB */
bool dereg_pending;
- tBT_UUID app_uuid;
+ bluetooth::Uuid app_uuid;
tBTA_GATTC_NOTIF_REG notif_reg[BTA_GATTC_NOTIF_REG_MAX];
} tBTA_GATTC_RCB;
@@ -279,7 +258,7 @@
bool disc_active;
bool in_use;
tBTA_GATTC_STATE state;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
uint16_t reason;
} tBTA_GATTC_CLCB;
@@ -338,7 +317,8 @@
/* function processed outside SM */
extern void bta_gattc_disable();
-extern void bta_gattc_register(tBT_UUID* p_app_uuid, tBTA_GATTC_CBACK* p_data,
+extern void bta_gattc_register(const bluetooth::Uuid& app_uuid,
+ tBTA_GATTC_CBACK* p_data,
BtaAppRegisterCallback cb);
extern void bta_gattc_process_api_open(tBTA_GATTC_DATA* p_msg);
extern void bta_gattc_process_api_open_cancel(tBTA_GATTC_DATA* p_msg);
@@ -391,7 +371,7 @@
tBTA_GATTC_RCB* p_clreg);
extern void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN* p_data);
extern void bta_gattc_send_open_cback(tBTA_GATTC_RCB* p_clreg,
- tBTA_GATT_STATUS status,
+ tGATT_STATUS status,
const RawAddress& remote_bda,
uint16_t conn_id,
tBTA_TRANSPORT transport, uint16_t mtu);
@@ -405,11 +385,11 @@
const RawAddress& remote_bda,
tBTA_TRANSPORT transport);
extern tBTA_GATTC_CLCB* bta_gattc_find_clcb_by_conn_id(uint16_t conn_id);
-extern tBTA_GATTC_CLCB* bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if,
+extern tBTA_GATTC_CLCB* bta_gattc_clcb_alloc(tGATT_IF client_if,
const RawAddress& remote_bda,
tBTA_TRANSPORT transport);
extern void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB* p_clcb);
-extern tBTA_GATTC_CLCB* bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if,
+extern tBTA_GATTC_CLCB* bta_gattc_find_alloc_clcb(tGATT_IF client_if,
const RawAddress& remote_bda,
tBTA_TRANSPORT transport);
extern tBTA_GATTC_RCB* bta_gattc_cl_get_regcb(uint8_t client_if);
@@ -421,14 +401,12 @@
extern bool bta_gattc_enqueue(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data);
-extern bool bta_gattc_uuid_compare(const tBT_UUID* p_src, const tBT_UUID* p_tar,
- bool is_precise);
extern bool bta_gattc_check_notif_registry(tBTA_GATTC_RCB* p_clreg,
tBTA_GATTC_SERV* p_srcb,
tBTA_GATTC_NOTIFY* p_notify);
-extern bool bta_gattc_mark_bg_conn(tBTA_GATTC_IF client_if,
+extern bool bta_gattc_mark_bg_conn(tGATT_IF client_if,
const RawAddress& remote_bda, bool add);
-extern bool bta_gattc_check_bg_conn(tBTA_GATTC_IF client_if,
+extern bool bta_gattc_check_bg_conn(tGATT_IF client_if,
const RawAddress& remote_bda, uint8_t role);
extern uint8_t bta_gattc_num_reg_app(void);
extern void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV* p_srcb,
@@ -444,29 +422,34 @@
extern void bta_gattc_disc_cmpl_cback(uint16_t conn_id,
tGATT_DISC_TYPE disc_type,
tGATT_STATUS status);
-extern tBTA_GATT_STATUS bta_gattc_discover_procedure(
- uint16_t conn_id, tBTA_GATTC_SERV* p_server_cb, uint8_t disc_type);
-extern tBTA_GATT_STATUS bta_gattc_discover_pri_service(
- uint16_t conn_id, tBTA_GATTC_SERV* p_server_cb, uint8_t disc_type);
-extern void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb, tBT_UUID* p_uuid);
-extern const list_t* bta_gattc_get_services(uint16_t conn_id);
+extern tGATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
+ tBTA_GATTC_SERV* p_server_cb,
+ uint8_t disc_type);
+extern void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb,
+ bluetooth::Uuid* p_uuid);
+extern std::vector<tBTA_GATTC_SERVICE>* bta_gattc_get_services(
+ uint16_t conn_id);
extern const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(
uint16_t conn_id, uint16_t handle);
tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
tBTA_GATTC_SERV* p_srcb, uint16_t handle);
+extern tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle_srcb(
+ tBTA_GATTC_SERV* p_srcb, uint16_t handle);
extern tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic(uint16_t conn_id,
uint16_t handle);
-extern tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(uint16_t conn_id,
- uint16_t handle);
+extern const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(uint16_t conn_id,
+ uint16_t handle);
+extern const tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_owning_characteristic(
+ uint16_t conn_id, uint16_t handle);
extern void bta_gattc_get_gatt_db(uint16_t conn_id, uint16_t start_handle,
uint16_t end_handle, btgatt_db_element_t** db,
int* count);
-extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb);
+extern tGATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb);
extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV* p_srcv, uint16_t num_attr,
tBTA_GATTC_NV_ATTR* attr);
extern void bta_gattc_cache_save(tBTA_GATTC_SERV* p_srvc_cb, uint16_t conn_id);
extern void bta_gattc_reset_discover_st(tBTA_GATTC_SERV* p_srcb,
- tBTA_GATT_STATUS status);
+ tGATT_STATUS status);
extern tBTA_GATTC_CONN* bta_gattc_conn_alloc(const RawAddress& remote_bda);
extern tBTA_GATTC_CONN* bta_gattc_conn_find(const RawAddress& remote_bda);
diff --git a/bta/gatt/bta_gattc_main.cc b/bta/gatt/bta_gattc_main.cc
index 9a2deb6..afc3e51 100644
--- a/bta/gatt/bta_gattc_main.cc
+++ b/bta/gatt/bta_gattc_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,8 @@
#include "bt_common.h"
#include "bta_gattc_int.h"
+using base::StringPrintf;
+
/*****************************************************************************
* Constants and types
****************************************************************************/
@@ -44,13 +46,11 @@
BTA_GATTC_CONN,
BTA_GATTC_START_DISCOVER,
BTA_GATTC_DISC_CMPL,
-
BTA_GATTC_Q_CMD,
BTA_GATTC_CLOSE,
BTA_GATTC_CLOSE_FAIL,
BTA_GATTC_READ,
BTA_GATTC_WRITE,
-
BTA_GATTC_OP_CMPL,
BTA_GATTC_SEARCH,
BTA_GATTC_FAIL,
@@ -69,32 +69,32 @@
tBTA_GATTC_DATA* p_data);
/* action function list */
-const tBTA_GATTC_ACTION bta_gattc_action[] = {bta_gattc_open,
- bta_gattc_open_fail,
- bta_gattc_open_error,
- bta_gattc_cancel_open,
- bta_gattc_cancel_open_ok,
- bta_gattc_cancel_open_error,
- bta_gattc_conn,
- bta_gattc_start_discover,
- bta_gattc_disc_cmpl,
-
- bta_gattc_q_cmd,
- bta_gattc_close,
- bta_gattc_close_fail,
- bta_gattc_read,
- bta_gattc_write,
-
- bta_gattc_op_cmpl,
- bta_gattc_search,
- bta_gattc_fail,
- bta_gattc_confirm,
- bta_gattc_execute,
- bta_gattc_read_multi,
- bta_gattc_ignore_op_cmpl,
- bta_gattc_disc_close,
- bta_gattc_restart_discover,
- bta_gattc_cfg_mtu};
+const tBTA_GATTC_ACTION bta_gattc_action[] = {
+ bta_gattc_open, /* BTA_GATTC_OPEN */
+ bta_gattc_open_fail, /* BTA_GATTC_OPEN_FAIL */
+ bta_gattc_open_error, /* BTA_GATTC_OPEN_ERROR */
+ bta_gattc_cancel_open, /* BTA_GATTC_CANCEL_OPEN */
+ bta_gattc_cancel_open_ok, /* BTA_GATTC_CANCEL_OPEN_OK */
+ bta_gattc_cancel_open_error, /* BTA_GATTC_CANCEL_OPEN_ERROR */
+ bta_gattc_conn, /* BTA_GATTC_CONN */
+ bta_gattc_start_discover, /* BTA_GATTC_START_DISCOVER */
+ bta_gattc_disc_cmpl, /* BTA_GATTC_DISC_CMPL */
+ bta_gattc_q_cmd, /* BTA_GATTC_Q_CMD */
+ bta_gattc_close, /* BTA_GATTC_CLOSE */
+ bta_gattc_close_fail, /* BTA_GATTC_CLOSE_FAIL */
+ bta_gattc_read, /* BTA_GATTC_READ */
+ bta_gattc_write, /* BTA_GATTC_WRITE */
+ bta_gattc_op_cmpl, /* BTA_GATTC_OP_CMPL */
+ bta_gattc_search, /* BTA_GATTC_SEARCH */
+ bta_gattc_fail, /* BTA_GATTC_FAIL */
+ bta_gattc_confirm, /* BTA_GATTC_CONFIRM */
+ bta_gattc_execute, /* BTA_GATTC_EXEC */
+ bta_gattc_read_multi, /* BTA_GATTC_READ_MULTI */
+ bta_gattc_ignore_op_cmpl, /* BTA_GATTC_IGNORE_OP_CMPL */
+ bta_gattc_disc_close, /* BTA_GATTC_DISC_CLOSE */
+ bta_gattc_restart_discover, /* BTA_GATTC_RESTART_DISCOVER */
+ bta_gattc_cfg_mtu /* BTA_GATTC_CFG_MTU */
+};
/* state table information */
#define BTA_GATTC_ACTIONS 1 /* number of actions */
@@ -267,8 +267,11 @@
/* state table */
const tBTA_GATTC_ST_TBL bta_gattc_st_tbl[] = {
- bta_gattc_st_idle, bta_gattc_st_w4_conn, bta_gattc_st_connected,
- bta_gattc_st_discover};
+ bta_gattc_st_idle, /* BTA_GATTC_IDLE_ST */
+ bta_gattc_st_w4_conn, /* BTA_GATTC_W4_CONN_ST */
+ bta_gattc_st_connected, /* BTA_GATTC_CONN_ST */
+ bta_gattc_st_discover /* BTA_GATTC_DISCOVER_ST */
+};
/*****************************************************************************
* Global data
@@ -278,8 +281,8 @@
tBTA_GATTC_CB bta_gattc_cb;
#if (BTA_GATT_DEBUG == TRUE)
-static char* gattc_evt_code(tBTA_GATTC_INT_EVT evt_code);
-static char* gattc_state_code(tBTA_GATTC_STATE state_code);
+static const char* gattc_evt_code(tBTA_GATTC_INT_EVT evt_code);
+static const char* gattc_state_code(tBTA_GATTC_STATE state_code);
#endif
/*******************************************************************************
@@ -299,12 +302,15 @@
uint8_t action;
int i;
bool rt = true;
-#if (BTA_GATT_DEBUG == TRUE)
tBTA_GATTC_STATE in_state = p_clcb->state;
uint16_t in_event = event;
- APPL_TRACE_DEBUG("bta_gattc_sm_execute: State 0x%02x [%s], Event 0x%x[%s]",
- in_state, gattc_state_code(in_state), in_event,
- gattc_evt_code(in_event));
+#if (BTA_GATT_DEBUG == TRUE)
+ VLOG(1) << StringPrintf("%s: State 0x%02x [%s], Event 0x%x[%s]", __func__,
+ in_state, gattc_state_code(in_state), in_event,
+ gattc_evt_code(in_event));
+#else
+ VLOG(1) << StringPrintf("%s: State 0x%02x, Event 0x%x", __func__, in_state,
+ in_event);
#endif
/* look up the state table for the current state */
@@ -333,10 +339,15 @@
#if (BTA_GATT_DEBUG == TRUE)
if (in_state != p_clcb->state) {
- APPL_TRACE_DEBUG("GATTC State Change: [%s] -> [%s] after Event [%s]",
- gattc_state_code(in_state),
- gattc_state_code(p_clcb->state), gattc_evt_code(in_event));
+ VLOG(1) << StringPrintf("GATTC State Change: [%s] -> [%s] after Event [%s]",
+ gattc_state_code(in_state),
+ gattc_state_code(p_clcb->state),
+ gattc_evt_code(in_event));
}
+#else
+ VLOG(1) << StringPrintf(
+ "%s: GATTC State Change: 0x%02x -> 0x%02x after Event 0x%x", __func__,
+ in_state, p_clcb->state, in_event);
#endif
return rt;
}
@@ -355,8 +366,7 @@
tBTA_GATTC_CLCB* p_clcb = NULL;
bool rt = true;
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("bta_gattc_hdl_event: Event [%s]",
- gattc_evt_code(p_msg->event));
+ VLOG(1) << __func__ << ": Event:" << gattc_evt_code(p_msg->event);
#endif
switch (p_msg->event) {
@@ -380,7 +390,7 @@
rt =
bta_gattc_sm_execute(p_clcb, p_msg->event, (tBTA_GATTC_DATA*)p_msg);
} else {
- APPL_TRACE_DEBUG("Ignore unknown conn ID: %d", p_msg->layer_specific);
+ VLOG(1) << "Ignore unknown conn ID: " << +p_msg->layer_specific;
}
break;
@@ -403,7 +413,7 @@
* Returns void
*
******************************************************************************/
-static char* gattc_evt_code(tBTA_GATTC_INT_EVT evt_code) {
+static const char* gattc_evt_code(tBTA_GATTC_INT_EVT evt_code) {
switch (evt_code) {
case BTA_GATTC_API_OPEN_EVT:
return "BTA_GATTC_API_OPEN_EVT";
@@ -453,7 +463,7 @@
* Returns void
*
******************************************************************************/
-static char* gattc_state_code(tBTA_GATTC_STATE state_code) {
+static const char* gattc_state_code(tBTA_GATTC_STATE state_code) {
switch (state_code) {
case BTA_GATTC_IDLE_ST:
return "GATTC_IDLE_ST";
diff --git a/bta/gatt/bta_gattc_queue.cc b/bta/gatt/bta_gattc_queue.cc
new file mode 100644
index 0000000..c00a885
--- /dev/null
+++ b/bta/gatt/bta_gattc_queue.cc
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bta_gatt_queue.h"
+
+#include <list>
+#include <unordered_map>
+#include <unordered_set>
+
+using gatt_operation = BtaGattQueue::gatt_operation;
+
+constexpr uint8_t GATT_READ_CHAR = 1;
+constexpr uint8_t GATT_READ_DESC = 2;
+constexpr uint8_t GATT_WRITE_CHAR = 3;
+constexpr uint8_t GATT_WRITE_DESC = 4;
+
+struct gatt_read_op_data {
+ GATT_READ_OP_CB cb;
+ void* cb_data;
+};
+
+std::unordered_map<uint16_t, std::list<gatt_operation>>
+ BtaGattQueue::gatt_op_queue;
+std::unordered_set<uint16_t> BtaGattQueue::gatt_op_queue_executing;
+
+void BtaGattQueue::mark_as_not_executing(uint16_t conn_id) {
+ gatt_op_queue_executing.erase(conn_id);
+}
+
+void BtaGattQueue::gatt_read_op_finished(uint16_t conn_id, tGATT_STATUS status,
+ uint16_t handle, uint16_t len,
+ uint8_t* value, void* data) {
+ gatt_read_op_data* tmp = (gatt_read_op_data*)data;
+ GATT_READ_OP_CB tmp_cb = tmp->cb;
+ void* tmp_cb_data = tmp->cb_data;
+
+ osi_free(data);
+
+ mark_as_not_executing(conn_id);
+ gatt_execute_next_op(conn_id);
+
+ if (tmp_cb) {
+ tmp_cb(conn_id, status, handle, len, value, tmp_cb_data);
+ return;
+ }
+}
+
+struct gatt_write_op_data {
+ GATT_WRITE_OP_CB cb;
+ void* cb_data;
+};
+
+void BtaGattQueue::gatt_write_op_finished(uint16_t conn_id, tGATT_STATUS status,
+ uint16_t handle, void* data) {
+ gatt_write_op_data* tmp = (gatt_write_op_data*)data;
+ GATT_WRITE_OP_CB tmp_cb = tmp->cb;
+ void* tmp_cb_data = tmp->cb_data;
+
+ osi_free(data);
+
+ mark_as_not_executing(conn_id);
+ gatt_execute_next_op(conn_id);
+
+ if (tmp_cb) {
+ tmp_cb(conn_id, status, handle, tmp_cb_data);
+ return;
+ }
+}
+
+void BtaGattQueue::gatt_execute_next_op(uint16_t conn_id) {
+ APPL_TRACE_DEBUG("%s:", __func__, conn_id);
+ if (gatt_op_queue.empty()) {
+ APPL_TRACE_DEBUG("%s: op queue is empty", __func__);
+ return;
+ }
+
+ auto map_ptr = gatt_op_queue.find(conn_id);
+ if (map_ptr == gatt_op_queue.end() || map_ptr->second.empty()) {
+ APPL_TRACE_DEBUG("%s: no more operations queued for conn_id %d", __func__,
+ conn_id);
+ return;
+ }
+
+ if (gatt_op_queue_executing.count(conn_id)) {
+ APPL_TRACE_DEBUG("%s: can't enqueue next op, already executing", __func__);
+ return;
+ }
+
+ gatt_op_queue_executing.insert(conn_id);
+
+ std::list<gatt_operation>& gatt_ops = map_ptr->second;
+
+ gatt_operation& op = gatt_ops.front();
+
+ if (op.type == GATT_READ_CHAR) {
+ gatt_read_op_data* data =
+ (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data));
+ data->cb = op.read_cb;
+ data->cb_data = op.read_cb_data;
+ BTA_GATTC_ReadCharacteristic(conn_id, op.handle, GATT_AUTH_REQ_NONE,
+ gatt_read_op_finished, data);
+
+ } else if (op.type == GATT_READ_DESC) {
+ gatt_read_op_data* data =
+ (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data));
+ data->cb = op.read_cb;
+ data->cb_data = op.read_cb_data;
+ BTA_GATTC_ReadCharDescr(conn_id, op.handle, GATT_AUTH_REQ_NONE,
+ gatt_read_op_finished, data);
+
+ } else if (op.type == GATT_WRITE_CHAR) {
+ gatt_write_op_data* data =
+ (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data));
+ data->cb = op.write_cb;
+ data->cb_data = op.write_cb_data;
+ BTA_GATTC_WriteCharValue(conn_id, op.handle, op.write_type,
+ std::move(op.value), GATT_AUTH_REQ_NONE,
+ gatt_write_op_finished, data);
+
+ } else if (op.type == GATT_WRITE_DESC) {
+ gatt_write_op_data* data =
+ (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data));
+ data->cb = op.write_cb;
+ data->cb_data = op.write_cb_data;
+ BTA_GATTC_WriteCharDescr(conn_id, op.handle, std::move(op.value),
+ GATT_AUTH_REQ_NONE, gatt_write_op_finished, data);
+ }
+
+ gatt_ops.pop_front();
+}
+
+void BtaGattQueue::Clean(uint16_t conn_id) {
+ gatt_op_queue.erase(conn_id);
+ gatt_op_queue_executing.erase(conn_id);
+}
+
+void BtaGattQueue::ReadCharacteristic(uint16_t conn_id, uint16_t handle,
+ GATT_READ_OP_CB cb, void* cb_data) {
+ gatt_op_queue[conn_id].push_back({.type = GATT_READ_CHAR,
+ .handle = handle,
+ .read_cb = cb,
+ .read_cb_data = cb_data});
+ gatt_execute_next_op(conn_id);
+}
+
+void BtaGattQueue::ReadDescriptor(uint16_t conn_id, uint16_t handle,
+ GATT_READ_OP_CB cb, void* cb_data) {
+ gatt_op_queue[conn_id].push_back({.type = GATT_READ_DESC,
+ .handle = handle,
+ .read_cb = cb,
+ .read_cb_data = cb_data});
+ gatt_execute_next_op(conn_id);
+}
+
+void BtaGattQueue::WriteCharacteristic(uint16_t conn_id, uint16_t handle,
+ std::vector<uint8_t> value,
+ tGATT_WRITE_TYPE write_type,
+ GATT_WRITE_OP_CB cb, void* cb_data) {
+ gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_CHAR,
+ .handle = handle,
+ .write_type = write_type,
+ .write_cb = cb,
+ .write_cb_data = cb_data,
+ .value = std::move(value)});
+ gatt_execute_next_op(conn_id);
+}
+
+void BtaGattQueue::WriteDescriptor(uint16_t conn_id, uint16_t handle,
+ std::vector<uint8_t> value,
+ tGATT_WRITE_TYPE write_type,
+ GATT_WRITE_OP_CB cb, void* cb_data) {
+ gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_DESC,
+ .handle = handle,
+ .write_type = write_type,
+ .write_cb = cb,
+ .write_cb_data = cb_data,
+ .value = std::move(value)});
+ gatt_execute_next_op(conn_id);
+}
diff --git a/bta/gatt/bta_gattc_utils.cc b/bta/gatt/bta_gattc_utils.cc
index f14f469..21b63c0 100644
--- a/bta/gatt/bta_gattc_utils.cc
+++ b/bta/gatt/bta_gattc_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,76 +35,6 @@
#include "l2c_api.h"
#include "utl.h"
-/*****************************************************************************
- * Constants
- ****************************************************************************/
-
-static const uint8_t base_uuid[LEN_UUID_128] = {
- 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-/*******************************************************************************
- *
- * Function bta_gatt_convert_uuid16_to_uuid128
- *
- * Description Convert a 16 bits UUID to be an standard 128 bits one.
- *
- * Returns true if two uuid match; false otherwise.
- *
- ******************************************************************************/
-void bta_gatt_convert_uuid16_to_uuid128(uint8_t uuid_128[LEN_UUID_128],
- uint16_t uuid_16) {
- uint8_t* p = &uuid_128[LEN_UUID_128 - 4];
-
- memcpy(uuid_128, base_uuid, LEN_UUID_128);
-
- UINT16_TO_STREAM(p, uuid_16);
-}
-/*******************************************************************************
- *
- * Function bta_gattc_uuid_compare
- *
- * Description Compare two UUID to see if they are the same.
- *
- * Returns true if two uuid match; false otherwise.
- *
- ******************************************************************************/
-bool bta_gattc_uuid_compare(const tBT_UUID* p_src, const tBT_UUID* p_tar,
- bool is_precise) {
- uint8_t su[LEN_UUID_128], tu[LEN_UUID_128];
- const uint8_t *ps, *pt;
-
- /* any of the UUID is unspecified */
- if (p_src == 0 || p_tar == 0) {
- if (is_precise)
- return false;
- else
- return true;
- }
-
- /* If both are 16-bit, we can do a simple compare */
- if (p_src->len == 2 && p_tar->len == 2) {
- return p_src->uu.uuid16 == p_tar->uu.uuid16;
- }
-
- /* One or both of the UUIDs is 128-bit */
- if (p_src->len == LEN_UUID_16) {
- /* convert a 16 bits UUID to 128 bits value */
- bta_gatt_convert_uuid16_to_uuid128(su, p_src->uu.uuid16);
- ps = su;
- } else
- ps = p_src->uu.uuid128;
-
- if (p_tar->len == LEN_UUID_16) {
- /* convert a 16 bits UUID to 128 bits value */
- bta_gatt_convert_uuid16_to_uuid128(tu, p_tar->uu.uuid16);
- pt = tu;
- } else
- pt = p_tar->uu.uuid128;
-
- return (memcmp(ps, pt, LEN_UUID_128) == 0);
-}
-
/*******************************************************************************
*
* Function bta_gattc_cl_get_regcb
@@ -190,7 +120,7 @@
* Returns pointer to the clcb
*
******************************************************************************/
-tBTA_GATTC_CLCB* bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if,
+tBTA_GATTC_CLCB* bta_gattc_clcb_alloc(tGATT_IF client_if,
const RawAddress& remote_bda,
tBTA_TRANSPORT transport) {
uint8_t i_clcb = 0;
@@ -199,12 +129,11 @@
for (i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++) {
if (!bta_gattc_cb.clcb[i_clcb].in_use) {
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("bta_gattc_clcb_alloc: found clcb[%d] available",
- i_clcb);
+ VLOG(1) << __func__ << ": found clcb:" << +i_clcb << " available";
#endif
p_clcb = &bta_gattc_cb.clcb[i_clcb];
p_clcb->in_use = true;
- p_clcb->status = BTA_GATT_OK;
+ p_clcb->status = GATT_SUCCESS;
p_clcb->transport = transport;
p_clcb->bda = remote_bda;
@@ -236,7 +165,7 @@
* Returns pointer to the clcb
*
******************************************************************************/
-tBTA_GATTC_CLCB* bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if,
+tBTA_GATTC_CLCB* bta_gattc_find_alloc_clcb(tGATT_IF client_if,
const RawAddress& remote_bda,
tBTA_TRANSPORT transport) {
tBTA_GATTC_CLCB* p_clcb;
@@ -258,32 +187,28 @@
*
******************************************************************************/
void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB* p_clcb) {
- tBTA_GATTC_SERV* p_srcb = NULL;
-
- if (p_clcb) {
- p_srcb = p_clcb->p_srcb;
- if (p_srcb->num_clcb) p_srcb->num_clcb--;
-
- if (p_clcb->p_rcb->num_clcb) p_clcb->p_rcb->num_clcb--;
-
- /* if the srcb is no longer needed, reset the state */
- if (p_srcb->num_clcb == 0) {
- p_srcb->connected = false;
- p_srcb->state = BTA_GATTC_SERV_IDLE;
- p_srcb->mtu = 0;
-
- /* clean up cache */
- if (p_srcb->p_srvc_cache) {
- list_free(p_srcb->p_srvc_cache);
- p_srcb->p_srvc_cache = NULL;
- }
- }
-
- osi_free_and_reset((void**)&p_clcb->p_q_cmd);
- memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
- } else {
- APPL_TRACE_ERROR("bta_gattc_clcb_dealloc p_clcb=NULL");
+ if (!p_clcb) {
+ LOG(ERROR) << __func__ << " p_clcb=NULL";
+ return;
}
+
+ tBTA_GATTC_SERV* p_srcb = p_clcb->p_srcb;
+ if (p_srcb->num_clcb) p_srcb->num_clcb--;
+
+ if (p_clcb->p_rcb->num_clcb) p_clcb->p_rcb->num_clcb--;
+
+ /* if the srcb is no longer needed, reset the state */
+ if (p_srcb->num_clcb == 0) {
+ p_srcb->connected = false;
+ p_srcb->state = BTA_GATTC_SERV_IDLE;
+ p_srcb->mtu = 0;
+
+ // clear reallocating
+ std::vector<tBTA_GATTC_SERVICE>().swap(p_srcb->srvc_cache);
+ }
+
+ osi_free_and_reset((void**)&p_clcb->p_q_cmd);
+ memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
}
/*******************************************************************************
@@ -370,10 +295,10 @@
p_tcb = p_recycle;
if (p_tcb != NULL) {
- if (p_tcb->p_srvc_cache != NULL) list_free(p_tcb->p_srvc_cache);
-
- osi_free_and_reset((void**)&p_tcb->p_srvc_list);
- memset(p_tcb, 0, sizeof(tBTA_GATTC_SERV));
+ // clear reallocating
+ std::vector<tBTA_GATTC_SERVICE>().swap(p_tcb->srvc_cache);
+ std::vector<tBTA_GATTC_SERVICE>().swap(p_tcb->pending_discovery);
+ *p_tcb = tBTA_GATTC_SERV();
p_tcb->in_use = true;
p_tcb->server_bda = bda;
@@ -395,7 +320,7 @@
return true;
}
- APPL_TRACE_ERROR("%s: already has a pending command!!", __func__);
+ LOG(ERROR) << __func__ << ": already has a pending command";
/* skip the callback now. ----- need to send callback ? */
return false;
}
@@ -418,7 +343,7 @@
if (p_clreg->notif_reg[i].in_use &&
p_clreg->notif_reg[i].remote_bda == p_srcb->server_bda &&
p_clreg->notif_reg[i].handle == p_notify->handle) {
- APPL_TRACE_DEBUG("Notification registered!");
+ VLOG(1) << "Notification registered!";
return true;
}
}
@@ -441,7 +366,7 @@
uint16_t conn_id, uint16_t start_handle,
uint16_t end_handle) {
RawAddress remote_bda;
- tBTA_GATTC_IF gatt_if;
+ tGATT_IF gatt_if;
tBTA_GATTC_RCB* p_clrcb;
uint8_t i;
tGATT_TRANSPORT transport;
@@ -463,8 +388,7 @@
}
}
} else {
- APPL_TRACE_ERROR(
- "can not clear indication/notif registration for unknown app");
+ LOG(ERROR) << "can not clear indication/notif registration for unknown app";
}
return;
}
@@ -479,7 +403,7 @@
* Returns true if success; false otherwise.
*
******************************************************************************/
-bool bta_gattc_mark_bg_conn(tBTA_GATTC_IF client_if,
+bool bta_gattc_mark_bg_conn(tGATT_IF client_if,
const RawAddress& remote_bda_ptr, bool add) {
tBTA_GATTC_BG_TCK* p_bg_tck = &bta_gattc_cb.bg_track[0];
uint8_t i = 0;
@@ -506,7 +430,8 @@
}
}
if (!add) {
- LOG(ERROR) << __func__ << " unable to find the bg connection mask for: "
+ LOG(ERROR) << __func__
+ << " unable to find the bg connection mask for bd_addr="
<< remote_bda_ptr;
return false;
} else /* adding a new device mask */
@@ -523,7 +448,7 @@
return true;
}
}
- APPL_TRACE_ERROR("no available space to mark the bg connection status");
+ LOG(ERROR) << "no available space to mark the bg connection status";
return false;
}
}
@@ -537,8 +462,8 @@
* Returns true if success; false otherwise.
*
******************************************************************************/
-bool bta_gattc_check_bg_conn(tBTA_GATTC_IF client_if,
- const RawAddress& remote_bda, uint8_t role) {
+bool bta_gattc_check_bg_conn(tGATT_IF client_if, const RawAddress& remote_bda,
+ uint8_t role) {
tBTA_GATTC_BG_TCK* p_bg_tck = &bta_gattc_cb.bg_track[0];
uint8_t i = 0;
bool is_bg_conn = false;
@@ -562,7 +487,7 @@
* Returns
*
******************************************************************************/
-void bta_gattc_send_open_cback(tBTA_GATTC_RCB* p_clreg, tBTA_GATT_STATUS status,
+void bta_gattc_send_open_cback(tBTA_GATTC_RCB* p_clreg, tGATT_STATUS status,
const RawAddress& remote_bda, uint16_t conn_id,
tBTA_TRANSPORT transport, uint16_t mtu) {
tBTA_GATTC cb_data;
@@ -596,8 +521,7 @@
for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn++) {
if (!p_conn->in_use) {
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("bta_gattc_conn_alloc: found conn_track[%d] available",
- i_conn);
+ VLOG(1) << __func__ << ": found conn_track:" << +i_conn << " available";
#endif
p_conn->in_use = true;
p_conn->remote_bda = remote_bda;
@@ -623,8 +547,7 @@
for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn++) {
if (p_conn->in_use && remote_bda == p_conn->remote_bda) {
#if (BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("bta_gattc_conn_find: found conn_track[%d] matched",
- i_conn);
+ VLOG(1) << __func__ << ": found conn_track:" << +i_conn << " matched";
#endif
return p_conn;
}
@@ -727,8 +650,8 @@
p_msg->int_conn.transport);
}
if (p_clcb == NULL) {
- APPL_TRACE_DEBUG(" disconnection ID: [%d] not used by BTA",
- p_msg->int_conn.hdr.layer_specific);
+ VLOG(1) << " disconnection ID:" << +p_msg->int_conn.hdr.layer_specific
+ << " not used by BTA";
}
return p_clcb;
}
diff --git a/bta/gatt/bta_gatts_act.cc b/bta/gatt/bta_gatts_act.cc
index b328093..8e3d589 100644
--- a/bta/gatt/bta_gatts_act.cc
+++ b/bta/gatt/bta_gatts_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,8 @@
#include "osi/include/osi.h"
#include "utl.h"
+using base::StringPrintf;
+
static void bta_gatts_nv_save_cback(bool is_saved,
tGATTS_HNDL_RANGE* p_hndl_range);
static bool bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd,
@@ -101,9 +103,9 @@
static bool bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd,
tGATTS_SRV_CHG_REQ* p_req,
tGATTS_SRV_CHG_RSP* p_rsp) {
- return bta_gatts_co_srv_chg((tBTA_GATTS_SRV_CHG_CMD)cmd,
- (tBTA_GATTS_SRV_CHG_REQ*)p_req,
- (tBTA_GATTS_SRV_CHG_RSP*)p_rsp);
+ return bta_gatts_co_srv_chg((tGATTS_SRV_CHG_CMD)cmd,
+ (tGATTS_SRV_CHG_REQ*)p_req,
+ (tGATTS_SRV_CHG_RSP*)p_rsp);
}
/*******************************************************************************
@@ -120,7 +122,7 @@
tBTA_GATTS_HNDL_RANGE handle_range;
if (p_cb->enabled) {
- APPL_TRACE_DEBUG("GATTS already enabled.");
+ VLOG(1) << "GATTS already enabled.";
} else {
memset(p_cb, 0, sizeof(tBTA_GATTS_CB));
@@ -132,10 +134,10 @@
index++;
}
- APPL_TRACE_DEBUG("bta_gatts_enable: num of handle range added=%d", index);
+ VLOG(1) << __func__ << ": num of handle range added:" << +index;
if (!GATTS_NVRegister(&bta_gatts_nv_cback)) {
- APPL_TRACE_ERROR("BTA GATTS NV register failed.");
+ LOG(ERROR) << "BTA GATTS NV register failed.";
}
}
}
@@ -160,7 +162,7 @@
}
memset(p_cb, 0, sizeof(tBTA_GATTS_CB));
} else {
- APPL_TRACE_ERROR("GATTS not enabled");
+ LOG(ERROR) << "GATTS not enabled";
}
}
@@ -175,25 +177,24 @@
******************************************************************************/
void bta_gatts_register(tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg) {
tBTA_GATTS cb_data;
- tBTA_GATT_STATUS status = BTA_GATT_OK;
+ tGATT_STATUS status = GATT_SUCCESS;
uint8_t i, first_unuse = 0xff;
- if (p_cb->enabled == false) {
+ if (!p_cb->enabled) {
bta_gatts_enable(p_cb);
}
for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i++) {
if (p_cb->rcb[i].in_use) {
- if (bta_gatts_uuid_compare(p_cb->rcb[i].app_uuid,
- p_msg->api_reg.app_uuid)) {
- APPL_TRACE_ERROR("application already registered.");
- status = BTA_GATT_DUP_REG;
+ if (p_cb->rcb[i].app_uuid == p_msg->api_reg.app_uuid) {
+ LOG(ERROR) << "application already registered.";
+ status = GATT_DUP_REG;
break;
}
}
}
- if (status == BTA_GATT_OK) {
+ if (status == GATT_SUCCESS) {
for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i++) {
if (first_unuse == 0xff && !p_cb->rcb[i].in_use) {
first_unuse = i;
@@ -202,19 +203,17 @@
}
cb_data.reg_oper.server_if = BTA_GATTS_INVALID_IF;
- memcpy(&cb_data.reg_oper.uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
+ cb_data.reg_oper.uuid = p_msg->api_reg.app_uuid;
if (first_unuse != 0xff) {
- APPL_TRACE_ERROR("register application first_unuse rcb_idx = %d",
- first_unuse);
+ LOG(INFO) << "register application first_unuse rcb_idx=" << +first_unuse;
p_cb->rcb[first_unuse].in_use = true;
p_cb->rcb[first_unuse].p_cback = p_msg->api_reg.p_cback;
- memcpy(&p_cb->rcb[first_unuse].app_uuid, &p_msg->api_reg.app_uuid,
- sizeof(tBT_UUID));
+ p_cb->rcb[first_unuse].app_uuid = p_msg->api_reg.app_uuid;
cb_data.reg_oper.server_if = p_cb->rcb[first_unuse].gatt_if =
- GATT_Register(&p_msg->api_reg.app_uuid, &bta_gatts_cback);
+ GATT_Register(p_msg->api_reg.app_uuid, &bta_gatts_cback);
if (!p_cb->rcb[first_unuse].gatt_if) {
- status = BTA_GATT_NO_RESOURCES;
+ status = GATT_NO_RESOURCES;
} else {
tBTA_GATTS_INT_START_IF* p_buf = (tBTA_GATTS_INT_START_IF*)osi_malloc(
sizeof(tBTA_GATTS_INT_START_IF));
@@ -224,7 +223,7 @@
bta_sys_sendmsg(p_buf);
}
} else {
- status = BTA_GATT_NO_RESOURCES;
+ status = GATT_NO_RESOURCES;
}
}
cb_data.reg_oper.status = status;
@@ -246,8 +245,8 @@
if (bta_gatts_find_app_rcb_by_app_if(p_msg->int_start_if.server_if)) {
GATT_StartIf(p_msg->int_start_if.server_if);
} else {
- APPL_TRACE_ERROR("Unable to start app.: Unknown interface =%d",
- p_msg->int_start_if.server_if);
+ LOG(ERROR) << "Unable to start app.: Unknown interface="
+ << +p_msg->int_start_if.server_if;
}
}
/*******************************************************************************
@@ -260,7 +259,7 @@
*
******************************************************************************/
void bta_gatts_deregister(tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg) {
- tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+ tGATT_STATUS status = GATT_ERROR;
tBTA_GATTS_CBACK* p_cback = NULL;
uint8_t i;
tBTA_GATTS cb_data;
@@ -272,7 +271,7 @@
if (p_cb->rcb[i].in_use &&
p_cb->rcb[i].gatt_if == p_msg->api_dereg.server_if) {
p_cback = p_cb->rcb[i].p_cback;
- status = BTA_GATT_OK;
+ status = GATT_SUCCESS;
/* deregister the app */
GATT_Deregister(p_cb->rcb[i].gatt_if);
@@ -287,7 +286,7 @@
if (p_cback) {
(*p_cback)(BTA_GATTS_DEREG_EVT, &cb_data);
} else {
- APPL_TRACE_ERROR("application not registered.");
+ LOG(ERROR) << "application not registered.";
}
}
@@ -310,10 +309,10 @@
if (GATTS_DeleteService(p_rcb->gatt_if, &p_srvc_cb->service_uuid,
p_srvc_cb->service_id)) {
- cb_data.srvc_oper.status = BTA_GATT_OK;
+ cb_data.srvc_oper.status = GATT_SUCCESS;
memset(p_srvc_cb, 0, sizeof(tBTA_GATTS_SRVC_CB));
} else {
- cb_data.srvc_oper.status = BTA_GATT_ERROR;
+ cb_data.srvc_oper.status = GATT_ERROR;
}
if (p_rcb->p_cback) (*p_rcb->p_cback)(BTA_GATTS_DELELTE_EVT, &cb_data);
@@ -336,9 +335,8 @@
GATTS_StopService(p_srvc_cb->service_id);
cb_data.srvc_oper.server_if = p_rcb->gatt_if;
cb_data.srvc_oper.service_id = p_srvc_cb->service_id;
- cb_data.srvc_oper.status = BTA_GATT_OK;
- APPL_TRACE_ERROR("bta_gatts_stop_service service_id= %d",
- p_srvc_cb->service_id);
+ cb_data.srvc_oper.status = GATT_SUCCESS;
+ LOG(ERROR) << __func__ << " service_id=" << +p_srvc_cb->service_id;
if (p_rcb->p_cback) (*p_rcb->p_cback)(BTA_GATTS_STOP_EVT, &cb_data);
}
@@ -356,7 +354,7 @@
if (GATTS_SendRsp(p_msg->api_rsp.hdr.layer_specific, p_msg->api_rsp.trans_id,
p_msg->api_rsp.status,
(tGATTS_RSP*)p_msg->api_rsp.p_rsp) != GATT_SUCCESS) {
- APPL_TRACE_ERROR("Sending response failed");
+ LOG(ERROR) << "Sending response failed";
}
}
/*******************************************************************************
@@ -371,7 +369,7 @@
void bta_gatts_indicate_handle(tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg) {
tBTA_GATTS_SRVC_CB* p_srvc_cb;
tBTA_GATTS_RCB* p_rcb = NULL;
- tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
+ tGATT_STATUS status = GATT_ILLEGAL_PARAMETER;
tGATT_IF gatt_if;
RawAddress remote_bda;
tBTA_TRANSPORT transport;
@@ -401,8 +399,9 @@
bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
}
} else {
- APPL_TRACE_ERROR("Unknown connection ID: %d fail sending notification",
- p_msg->api_indicate.hdr.layer_specific);
+ LOG(ERROR) << "Unknown connection_id="
+ << loghex(p_msg->api_indicate.hdr.layer_specific)
+ << " fail sending notification";
}
if ((status != GATT_SUCCESS || !p_msg->api_indicate.need_confirm) &&
@@ -413,8 +412,8 @@
(*p_rcb->p_cback)(BTA_GATTS_CONF_EVT, &cb_data);
}
} else {
- APPL_TRACE_ERROR("Not an registered servce attribute ID: 0x%04x",
- p_msg->api_indicate.attr_id);
+ LOG(ERROR) << "Not an registered servce attribute ID: "
+ << loghex(p_msg->api_indicate.attr_id);
}
}
@@ -429,7 +428,7 @@
******************************************************************************/
void bta_gatts_open(UNUSED_ATTR tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg) {
tBTA_GATTS_RCB* p_rcb = NULL;
- tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+ tGATT_STATUS status = GATT_ERROR;
uint16_t conn_id;
p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_open.server_if);
@@ -438,19 +437,22 @@
if (GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda,
p_msg->api_open.is_direct, p_msg->api_open.transport,
false)) {
- status = BTA_GATT_OK;
+ status = GATT_SUCCESS;
if (GATT_GetConnIdIfConnected(p_rcb->gatt_if, p_msg->api_open.remote_bda,
&conn_id, p_msg->api_open.transport)) {
- status = BTA_GATT_ALREADY_OPEN;
+ status = GATT_ALREADY_OPEN;
}
}
} else {
- APPL_TRACE_ERROR("Inavlide server_if=%d", p_msg->api_open.server_if);
+ LOG(ERROR) << "Inavlid server_if=" << p_msg->api_open.server_if;
}
- if (p_rcb && p_rcb->p_cback)
- (*p_rcb->p_cback)(BTA_GATTS_OPEN_EVT, (tBTA_GATTS*)&status);
+ if (p_rcb && p_rcb->p_cback) {
+ tBTA_GATTS bta_gatts;
+ bta_gatts.status = status;
+ (*p_rcb->p_cback)(BTA_GATTS_OPEN_EVT, &bta_gatts);
+ }
}
/*******************************************************************************
*
@@ -464,22 +466,25 @@
void bta_gatts_cancel_open(UNUSED_ATTR tBTA_GATTS_CB* p_cb,
tBTA_GATTS_DATA* p_msg) {
tBTA_GATTS_RCB* p_rcb;
- tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+ tGATT_STATUS status = GATT_ERROR;
p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_cancel_open.server_if);
if (p_rcb != NULL) {
if (!GATT_CancelConnect(p_rcb->gatt_if, p_msg->api_cancel_open.remote_bda,
p_msg->api_cancel_open.is_direct)) {
- APPL_TRACE_ERROR("bta_gatts_cancel_open failed for open request");
+ LOG(ERROR) << __func__ << ": failed for open request";
} else {
- status = BTA_GATT_OK;
+ status = GATT_SUCCESS;
}
} else {
- APPL_TRACE_ERROR("Inavlide server_if=%d", p_msg->api_cancel_open.server_if);
+ LOG(ERROR) << "Inavlid server_if=" << +p_msg->api_cancel_open.server_if;
}
- if (p_rcb && p_rcb->p_cback)
- (*p_rcb->p_cback)(BTA_GATTS_CANCEL_OPEN_EVT, (tBTA_GATTS*)&status);
+ if (p_rcb && p_rcb->p_cback) {
+ tBTA_GATTS bta_gatts;
+ bta_gatts.status = status;
+ (*p_rcb->p_cback)(BTA_GATTS_CANCEL_OPEN_EVT, &bta_gatts);
+ }
}
/*******************************************************************************
*
@@ -492,18 +497,18 @@
******************************************************************************/
void bta_gatts_close(UNUSED_ATTR tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg) {
tBTA_GATTS_RCB* p_rcb;
- tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+ tGATT_STATUS status = GATT_ERROR;
tGATT_IF gatt_if;
RawAddress remote_bda;
- tBTA_GATT_TRANSPORT transport;
+ tGATT_TRANSPORT transport;
if (GATT_GetConnectionInfor(p_msg->hdr.layer_specific, &gatt_if, remote_bda,
&transport)) {
if (GATT_Disconnect(p_msg->hdr.layer_specific) != GATT_SUCCESS) {
- APPL_TRACE_ERROR("bta_gatts_close fail conn_id=%d",
- p_msg->hdr.layer_specific);
+ LOG(ERROR) << __func__
+ << ": fail conn_id=" << loghex(p_msg->hdr.layer_specific);
} else {
- status = BTA_GATT_OK;
+ status = GATT_SUCCESS;
}
p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
@@ -512,10 +517,12 @@
if (transport == BTA_TRANSPORT_BR_EDR)
bta_sys_conn_close(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
- (*p_rcb->p_cback)(BTA_GATTS_CLOSE_EVT, (tBTA_GATTS*)&status);
+ tBTA_GATTS bta_gatts;
+ bta_gatts.status = status;
+ (*p_rcb->p_cback)(BTA_GATTS_CLOSE_EVT, &bta_gatts);
}
} else {
- APPL_TRACE_ERROR("Unknown connection ID: %d", p_msg->hdr.layer_specific);
+ LOG(ERROR) << "Unknown connection_id=" << loghex(p_msg->hdr.layer_specific);
}
}
@@ -534,7 +541,7 @@
tBTA_GATTS cb_data;
tBTA_GATTS_RCB* p_rcb;
tGATT_IF gatt_if;
- tBTA_GATT_TRANSPORT transport;
+ tGATT_TRANSPORT transport;
memset(&cb_data, 0, sizeof(tBTA_GATTS));
@@ -542,8 +549,8 @@
&transport)) {
p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
- APPL_TRACE_DEBUG("%s: conn_id=%d trans_id=%d req_type=%d", __func__,
- conn_id, trans_id, req_type);
+ VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
+ << ", trans_id=" << +trans_id << ", req_type=" << +req_type;
if (p_rcb && p_rcb->p_cback) {
/* if over BR_EDR, inform PM for mode change */
@@ -554,15 +561,15 @@
cb_data.req_data.conn_id = conn_id;
cb_data.req_data.trans_id = trans_id;
- cb_data.req_data.p_data = (tBTA_GATTS_REQ_DATA*)p_data;
+ cb_data.req_data.p_data = (tGATTS_DATA*)p_data;
(*p_rcb->p_cback)(req_type, &cb_data);
} else {
- APPL_TRACE_ERROR("connection request on gatt_if[%d] is not interested",
- gatt_if);
+ LOG(ERROR) << "connection request on gatt_if=" << +gatt_if
+ << " is not interested";
}
} else {
- APPL_TRACE_ERROR("request received on unknown connectino ID: %d", conn_id);
+ LOG(ERROR) << "request received on unknown conn_id=" << loghex(conn_id);
}
}
@@ -583,10 +590,9 @@
uint8_t evt = connected ? BTA_GATTS_CONNECT_EVT : BTA_GATTS_DISCONNECT_EVT;
tBTA_GATTS_RCB* p_reg;
- APPL_TRACE_DEBUG(
- "bta_gatts_conn_cback gatt_if=%d conn_id=%d connected=%d reason = 0x%04d",
- gatt_if, conn_id, connected, reason);
- VLOG(1) << __func__ << " bda :" << bdaddr;
+ VLOG(1) << __func__ << " bda=" << bdaddr << " gatt_if= " << gatt_if
+ << ", conn_id=" << loghex(conn_id) << " connected=" << connected
+ << ", reason=" << loghex(reason);
if (connected)
btif_debug_conn_state(bdaddr, BTIF_DEBUG_CONNECTED, GATT_CONN_UNKNOWN);
@@ -611,7 +617,7 @@
cb_data.conn.remote_bda = bdaddr;
(*p_reg->p_cback)(evt, &cb_data);
} else {
- APPL_TRACE_ERROR("bta_gatts_conn_cback server_if=%d not found", gatt_if);
+ LOG(ERROR) << __func__ << " server_if=" << +gatt_if << " not found";
}
}
@@ -620,7 +626,7 @@
uint8_t status) {
tBTA_GATTS_RCB* p_reg = bta_gatts_find_app_rcb_by_app_if(gatt_if);
if (!p_reg || !p_reg->p_cback) {
- APPL_TRACE_ERROR("%s: server_if=%d not found", __func__, gatt_if);
+ LOG(ERROR) << __func__ << ": server_if=" << +gatt_if << " not found";
return;
}
@@ -638,7 +644,7 @@
uint16_t timeout, uint8_t status) {
tBTA_GATTS_RCB* p_reg = bta_gatts_find_app_rcb_by_app_if(gatt_if);
if (!p_reg || !p_reg->p_cback) {
- APPL_TRACE_ERROR("%s: server_if=%d not found", __func__, gatt_if);
+ LOG(ERROR) << __func__ << ": server_if=" << +gatt_if << " not found";
return;
}
@@ -664,7 +670,7 @@
static void bta_gatts_cong_cback(uint16_t conn_id, bool congested) {
tBTA_GATTS_RCB* p_rcb;
tGATT_IF gatt_if;
- tBTA_GATT_TRANSPORT transport;
+ tGATT_TRANSPORT transport;
tBTA_GATTS cb_data;
if (GATT_GetConnectionInfor(conn_id, &gatt_if, cb_data.req_data.remote_bda,
diff --git a/bta/gatt/bta_gatts_api.cc b/bta/gatt/bta_gatts_api.cc
index 7d45043..9d7cda0 100644
--- a/bta/gatt/bta_gatts_api.cc
+++ b/bta/gatt/bta_gatts_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2010-2012 Broadcom Corporation
+ * Copyright 2010-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,15 +24,15 @@
#include "bt_target.h"
+#include <base/bind.h>
#include <string.h>
#include "bt_common.h"
+#include "bta_closure_api.h"
#include "bta_gatt_api.h"
#include "bta_gatts_int.h"
#include "bta_sys.h"
-void btif_to_bta_uuid(tBT_UUID* p_dest, const bt_uuid_t* p_src);
-
/*****************************************************************************
* Constants
****************************************************************************/
@@ -52,8 +52,8 @@
*
******************************************************************************/
void BTA_GATTS_Disable(void) {
- if (bta_sys_is_register(BTA_ID_GATTS) == false) {
- APPL_TRACE_WARNING("GATTS Module not enabled/already disabled");
+ if (!bta_sys_is_register(BTA_ID_GATTS)) {
+ LOG(WARNING) << "GATTS Module not enabled/already disabled";
return;
}
@@ -76,17 +76,17 @@
* Returns None
*
******************************************************************************/
-void BTA_GATTS_AppRegister(tBT_UUID* p_app_uuid, tBTA_GATTS_CBACK* p_cback) {
+void BTA_GATTS_AppRegister(const bluetooth::Uuid& app_uuid,
+ tBTA_GATTS_CBACK* p_cback) {
tBTA_GATTS_API_REG* p_buf =
(tBTA_GATTS_API_REG*)osi_malloc(sizeof(tBTA_GATTS_API_REG));
/* register with BTA system manager */
- if (bta_sys_is_register(BTA_ID_GATTS) == false)
+ if (!bta_sys_is_register(BTA_ID_GATTS))
bta_sys_register(BTA_ID_GATTS, &bta_gatts_reg);
p_buf->hdr.event = BTA_GATTS_API_REG_EVT;
- if (p_app_uuid != NULL)
- memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
+ p_buf->app_uuid = app_uuid;
p_buf->p_cback = p_cback;
bta_sys_sendmsg(p_buf);
@@ -103,7 +103,7 @@
* Returns void
*
******************************************************************************/
-void BTA_GATTS_AppDeregister(tBTA_GATTS_IF server_if) {
+void BTA_GATTS_AppDeregister(tGATT_IF server_if) {
tBTA_GATTS_API_DEREG* p_buf =
(tBTA_GATTS_API_DEREG*)osi_malloc(sizeof(tBTA_GATTS_API_DEREG));
@@ -113,6 +113,43 @@
bta_sys_sendmsg(p_buf);
}
+void bta_gatts_add_service_impl(tGATT_IF server_if,
+ std::vector<btgatt_db_element_t> service,
+ BTA_GATTS_AddServiceCb cb) {
+ uint8_t rcb_idx =
+ bta_gatts_find_app_rcb_idx_by_app_if(&bta_gatts_cb, server_if);
+
+ LOG(INFO) << __func__ << ": rcb_idx=" << +rcb_idx;
+
+ if (rcb_idx == BTA_GATTS_INVALID_APP) {
+ cb.Run(GATT_ERROR, server_if, std::move(service));
+ return;
+ }
+
+ uint8_t srvc_idx = bta_gatts_alloc_srvc_cb(&bta_gatts_cb, rcb_idx);
+ if (srvc_idx == BTA_GATTS_INVALID_APP) {
+ cb.Run(GATT_ERROR, server_if, std::move(service));
+ return;
+ }
+
+ uint16_t status = GATTS_AddService(server_if, service.data(), service.size());
+ if (status != GATT_SERVICE_STARTED) {
+ memset(&bta_gatts_cb.srvc_cb[srvc_idx], 0, sizeof(tBTA_GATTS_SRVC_CB));
+ LOG(ERROR) << __func__ << ": service creation failed.";
+ cb.Run(GATT_ERROR, server_if, std::move(service));
+ return;
+ }
+
+ bta_gatts_cb.srvc_cb[srvc_idx].service_uuid = service[0].uuid;
+
+ // service_id is equal to service start handle
+ bta_gatts_cb.srvc_cb[srvc_idx].service_id = service[0].attribute_handle;
+ bta_gatts_cb.srvc_cb[srvc_idx].idx = srvc_idx;
+
+ cb.Run(GATT_SUCCESS, server_if, std::move(service));
+ return;
+}
+
/*******************************************************************************
*
* Function BTA_GATTS_AddService
@@ -124,38 +161,15 @@
* Parameters server_if: server interface.
* service: pointer vector describing service.
*
- * Returns Returns |BTA_GATT_OK| on success or |BTA_GATT_ERROR| if the
+ * Returns Returns |GATT_SUCCESS| on success or |GATT_ERROR| if the
* service cannot be added.
*
******************************************************************************/
-extern uint16_t BTA_GATTS_AddService(tBTA_GATTS_IF server_if,
- vector<btgatt_db_element_t>& service) {
- uint8_t rcb_idx =
- bta_gatts_find_app_rcb_idx_by_app_if(&bta_gatts_cb, server_if);
-
- APPL_TRACE_ERROR("%s: rcb_idx = %d", __func__, rcb_idx);
-
- if (rcb_idx == BTA_GATTS_INVALID_APP) return BTA_GATT_ERROR;
-
- uint8_t srvc_idx = bta_gatts_alloc_srvc_cb(&bta_gatts_cb, rcb_idx);
- if (srvc_idx == BTA_GATTS_INVALID_APP) return BTA_GATT_ERROR;
-
- uint16_t status = GATTS_AddService(server_if, service.data(), service.size());
-
- if (status == GATT_SERVICE_STARTED) {
- btif_to_bta_uuid(&bta_gatts_cb.srvc_cb[srvc_idx].service_uuid,
- &service[0].uuid);
-
- // service_id is equal to service start handle
- bta_gatts_cb.srvc_cb[srvc_idx].service_id = service[0].attribute_handle;
- bta_gatts_cb.srvc_cb[srvc_idx].idx = srvc_idx;
-
- return BTA_GATT_OK;
- } else {
- memset(&bta_gatts_cb.srvc_cb[srvc_idx], 0, sizeof(tBTA_GATTS_SRVC_CB));
- APPL_TRACE_ERROR("%s: service creation failed.", __func__);
- return BTA_GATT_ERROR;
- }
+extern void BTA_GATTS_AddService(tGATT_IF server_if,
+ std::vector<btgatt_db_element_t> service,
+ BTA_GATTS_AddServiceCb cb) {
+ do_in_bta_thread(FROM_HERE, base::Bind(&bta_gatts_add_service_impl, server_if,
+ std::move(service), std::move(cb)));
}
/*******************************************************************************
@@ -248,9 +262,9 @@
* Returns None
*
******************************************************************************/
-void BTA_GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id,
- tBTA_GATT_STATUS status, tBTA_GATTS_RSP* p_msg) {
- const size_t len = sizeof(tBTA_GATTS_API_RSP) + sizeof(tBTA_GATTS_RSP);
+void BTA_GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id, tGATT_STATUS status,
+ tGATTS_RSP* p_msg) {
+ const size_t len = sizeof(tBTA_GATTS_API_RSP) + sizeof(tGATTS_RSP);
tBTA_GATTS_API_RSP* p_buf = (tBTA_GATTS_API_RSP*)osi_calloc(len);
p_buf->hdr.event = BTA_GATTS_API_RSP_EVT;
@@ -258,8 +272,8 @@
p_buf->trans_id = trans_id;
p_buf->status = status;
if (p_msg != NULL) {
- p_buf->p_rsp = (tBTA_GATTS_RSP*)(p_buf + 1);
- memcpy(p_buf->p_rsp, p_msg, sizeof(tBTA_GATTS_RSP));
+ p_buf->p_rsp = (tGATTS_RSP*)(p_buf + 1);
+ memcpy(p_buf->p_rsp, p_msg, sizeof(tGATTS_RSP));
}
bta_sys_sendmsg(p_buf);
@@ -281,8 +295,8 @@
* Returns void
*
******************************************************************************/
-void BTA_GATTS_Open(tBTA_GATTS_IF server_if, const RawAddress& remote_bda,
- bool is_direct, tBTA_GATT_TRANSPORT transport) {
+void BTA_GATTS_Open(tGATT_IF server_if, const RawAddress& remote_bda,
+ bool is_direct, tGATT_TRANSPORT transport) {
tBTA_GATTS_API_OPEN* p_buf =
(tBTA_GATTS_API_OPEN*)osi_malloc(sizeof(tBTA_GATTS_API_OPEN));
@@ -309,7 +323,7 @@
* Returns void
*
******************************************************************************/
-void BTA_GATTS_CancelOpen(tBTA_GATTS_IF server_if, const RawAddress& remote_bda,
+void BTA_GATTS_CancelOpen(tGATT_IF server_if, const RawAddress& remote_bda,
bool is_direct) {
tBTA_GATTS_API_CANCEL_OPEN* p_buf = (tBTA_GATTS_API_CANCEL_OPEN*)osi_malloc(
sizeof(tBTA_GATTS_API_CANCEL_OPEN));
diff --git a/bta/gatt/bta_gatts_int.h b/bta/gatt/bta_gatts_int.h
index df5d706..adecf30 100644
--- a/bta/gatt/bta_gatts_int.h
+++ b/bta/gatt/bta_gatts_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
#include "bta_sys.h"
#include "gatt_api.h"
+#include <base/strings/stringprintf.h>
#include "bt_common.h"
/*****************************************************************************
@@ -59,20 +60,20 @@
/* internal strucutre for GATTC register API */
typedef struct {
BT_HDR hdr;
- tBT_UUID app_uuid;
+ bluetooth::Uuid app_uuid;
tBTA_GATTS_CBACK* p_cback;
} tBTA_GATTS_API_REG;
typedef struct {
BT_HDR hdr;
- tBTA_GATTS_IF server_if;
+ tGATT_IF server_if;
} tBTA_GATTS_INT_START_IF;
typedef tBTA_GATTS_INT_START_IF tBTA_GATTS_API_DEREG;
typedef struct {
BT_HDR hdr;
- tBTA_GATTS_IF server_if;
+ tGATT_IF server_if;
btgatt_db_element_t* service;
uint16_t count;
} tBTA_GATTS_API_ADD_SERVICE;
@@ -82,27 +83,27 @@
uint16_t attr_id;
uint16_t len;
bool need_confirm;
- uint8_t value[BTA_GATT_MAX_ATTR_LEN];
+ uint8_t value[GATT_MAX_ATTR_LEN];
} tBTA_GATTS_API_INDICATION;
typedef struct {
BT_HDR hdr;
uint32_t trans_id;
- tBTA_GATT_STATUS status;
- tBTA_GATTS_RSP* p_rsp;
+ tGATT_STATUS status;
+ tGATTS_RSP* p_rsp;
} tBTA_GATTS_API_RSP;
typedef struct {
BT_HDR hdr;
- tBTA_GATT_TRANSPORT transport;
+ tGATT_TRANSPORT transport;
} tBTA_GATTS_API_START;
typedef struct {
BT_HDR hdr;
RawAddress remote_bda;
- tBTA_GATTS_IF server_if;
+ tGATT_IF server_if;
bool is_direct;
- tBTA_GATT_TRANSPORT transport;
+ tGATT_TRANSPORT transport;
} tBTA_GATTS_API_OPEN;
@@ -124,14 +125,14 @@
/* application registration control block */
typedef struct {
bool in_use;
- tBT_UUID app_uuid;
+ bluetooth::Uuid app_uuid;
tBTA_GATTS_CBACK* p_cback;
- tBTA_GATTS_IF gatt_if;
+ tGATT_IF gatt_if;
} tBTA_GATTS_RCB;
/* service registration control block */
typedef struct {
- tBT_UUID service_uuid; /* service UUID */
+ bluetooth::Uuid service_uuid; /* service UUID */
uint16_t service_id; /* service start handle */
uint8_t rcb_idx;
uint8_t idx; /* self index of serviec CB */
@@ -175,11 +176,9 @@
extern void bta_gatts_cancel_open(tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg);
extern void bta_gatts_close(tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg);
-extern bool bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src);
-extern tBTA_GATTS_RCB* bta_gatts_find_app_rcb_by_app_if(
- tBTA_GATTS_IF server_if);
+extern tBTA_GATTS_RCB* bta_gatts_find_app_rcb_by_app_if(tGATT_IF server_if);
extern uint8_t bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB* p_cb,
- tBTA_GATTS_IF server_if);
+ tGATT_IF server_if);
extern uint8_t bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB* p_cb, uint8_t rcb_idx);
extern tBTA_GATTS_SRVC_CB* bta_gatts_find_srvc_cb_by_srvc_id(
tBTA_GATTS_CB* p_cb, uint16_t service_id);
diff --git a/bta/gatt/bta_gatts_main.cc b/bta/gatt/bta_gatts_main.cc
index ac82878..1dc0aa2 100644
--- a/bta/gatt/bta_gatts_main.cc
+++ b/bta/gatt/bta_gatts_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -89,8 +89,7 @@
if (p_srvc_cb != NULL)
bta_gatts_delete_service(p_srvc_cb, (tBTA_GATTS_DATA*)p_msg);
else
- APPL_TRACE_ERROR("%s: can't delete service - no srvc_cb found",
- __func__);
+ LOG(ERROR) << __func__ << ": can't delete service - no srvc_cb found";
break;
}
@@ -102,7 +101,7 @@
if (p_srvc_cb != NULL)
bta_gatts_stop_service(p_srvc_cb, (tBTA_GATTS_DATA*)p_msg);
else
- APPL_TRACE_ERROR("%s: can't stop service - no srvc_cb found", __func__);
+ LOG(ERROR) << __func__ << ": can't stop service - no srvc_cb found";
break;
}
diff --git a/bta/gatt/bta_gatts_utils.cc b/bta/gatt/bta_gatts_utils.cc
index 23cc7c7..173d4f3 100644
--- a/bta/gatt/bta_gatts_utils.cc
+++ b/bta/gatt/bta_gatts_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,27 +31,6 @@
#include "bta_sys.h"
#include "utl.h"
-static const uint8_t base_uuid[LEN_UUID_128] = {
- 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-/*******************************************************************************
- *
- * Function bta_gatt_convert_uuid16_to_uuid128
- *
- * Description Convert a 16 bits UUID to be an standard 128 bits one.
- *
- * Returns true if two uuid match; false otherwise.
- *
- ******************************************************************************/
-static void bta_gatt_convert_uuid16_to_uuid128(uint8_t uuid_128[LEN_UUID_128],
- uint16_t uuid_16) {
- uint8_t* p = &uuid_128[LEN_UUID_128 - 4];
-
- memcpy(uuid_128, base_uuid, LEN_UUID_128);
-
- UINT16_TO_STREAM(p, uuid_16);
-}
/*******************************************************************************
*
* Function bta_gatts_alloc_srvc_cb
@@ -83,7 +62,7 @@
* Returns pointer to the control block if success, otherwise NULL
*
******************************************************************************/
-tBTA_GATTS_RCB* bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if) {
+tBTA_GATTS_RCB* bta_gatts_find_app_rcb_by_app_if(tGATT_IF server_if) {
uint8_t i;
tBTA_GATTS_RCB* p_reg;
@@ -106,7 +85,7 @@
******************************************************************************/
uint8_t bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB* p_cb,
- tBTA_GATTS_IF server_if) {
+ tGATT_IF server_if) {
uint8_t i;
for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i++) {
@@ -126,12 +105,10 @@
tBTA_GATTS_SRVC_CB* bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB* p_cb,
uint16_t service_id) {
uint8_t i;
- APPL_TRACE_DEBUG("bta_gatts_find_srvc_cb_by_srvc_id service_id=%d",
- service_id);
+ VLOG(1) << __func__ << ": service_id=" << +service_id;
for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i++) {
if (p_cb->srvc_cb[i].in_use && p_cb->srvc_cb[i].service_id == service_id) {
- APPL_TRACE_DEBUG(
- "bta_gatts_find_srvc_cb_by_srvc_id found service cb index =%d", i);
+ VLOG(1) << __func__ << ": found service cb index=" << +i;
return &p_cb->srvc_cb[i];
}
}
@@ -168,43 +145,3 @@
}
return NULL;
}
-/*******************************************************************************
- *
- * Function bta_gatts_uuid_compare
- *
- * Description Compare two UUID to see if they are the same.
- *
- * Returns true if two uuid match; false otherwise.
- *
- ******************************************************************************/
-bool bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src) {
- uint8_t su[LEN_UUID_128], tu[LEN_UUID_128];
- uint8_t *ps, *pt;
-
- /* any of the UUID is unspecified */
- if (src.len == 0 || tar.len == 0) {
- return true;
- }
-
- /* If both are 16-bit, we can do a simple compare */
- if (src.len == 2 && tar.len == 2) {
- return src.uu.uuid16 == tar.uu.uuid16;
- }
-
- /* One or both of the UUIDs is 128-bit */
- if (src.len == LEN_UUID_16) {
- /* convert a 16 bits UUID to 128 bits value */
- bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
- ps = su;
- } else
- ps = src.uu.uuid128;
-
- if (tar.len == LEN_UUID_16) {
- /* convert a 16 bits UUID to 128 bits value */
- bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
- pt = tu;
- } else
- pt = tar.uu.uuid128;
-
- return (memcmp(ps, pt, LEN_UUID_128) == 0);
-}
diff --git a/bta/hd/bta_hd_act.cc b/bta/hd/bta_hd_act.cc
index b8cdb7d..0d677ee 100644
--- a/bta/hd/bta_hd_act.cc
+++ b/bta/hd/bta_hd_act.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -104,7 +104,9 @@
}
/* signal BTA call back event */
- (*bta_hd_cb.p_cback)(BTA_HD_ENABLE_EVT, (tBTA_HD*)&status);
+ tBTA_HD bta_hd;
+ bta_hd.status = status;
+ (*bta_hd_cb.p_cback)(BTA_HD_ENABLE_EVT, &bta_hd);
}
/*******************************************************************************
@@ -139,7 +141,9 @@
APPL_TRACE_ERROR("%s: Failed to deregister HID device (%s)", __func__, ret);
}
- (*bta_hd_cb.p_cback)(BTA_HD_DISABLE_EVT, (tBTA_HD*)&status);
+ tBTA_HD bta_hd;
+ bta_hd.status = status;
+ (*bta_hd_cb.p_cback)(BTA_HD_DISABLE_EVT, &bta_hd);
memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
}
@@ -232,7 +236,9 @@
bta_hd_cb.sdp_handle = 0;
bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
- (*bta_hd_cb.p_cback)(BTA_HD_UNREGISTER_APP_EVT, (tBTA_HD*)&status);
+ tBTA_HD bta_hd;
+ bta_hd.status = status;
+ (*bta_hd_cb.p_cback)(BTA_HD_UNREGISTER_APP_EVT, &bta_hd);
}
/*******************************************************************************
@@ -520,7 +526,9 @@
ret.len = len;
ret.p_data = p_buf;
- (*bta_hd_cb.p_cback)(BTA_HD_INTR_DATA_EVT, (tBTA_HD*)&ret);
+ tBTA_HD bta_hd;
+ bta_hd.intr_data = ret;
+ (*bta_hd_cb.p_cback)(BTA_HD_INTR_DATA_EVT, &bta_hd);
}
/*******************************************************************************
@@ -569,7 +577,9 @@
ret.buffer_size = *p_buf | (*(p_buf + 1) << 8);
}
- (*bta_hd_cb.p_cback)(BTA_HD_GET_REPORT_EVT, (tBTA_HD*)&ret);
+ tBTA_HD bta_hd;
+ bta_hd.get_report = ret;
+ (*bta_hd_cb.p_cback)(BTA_HD_GET_REPORT_EVT, &bta_hd);
}
/*******************************************************************************
@@ -614,7 +624,9 @@
ret.len = len;
ret.p_data = p_buf;
- (*bta_hd_cb.p_cback)(BTA_HD_SET_REPORT_EVT, (tBTA_HD*)&ret);
+ tBTA_HD bta_hd;
+ bta_hd.set_report = ret;
+ (*bta_hd_cb.p_cback)(BTA_HD_SET_REPORT_EVT, &bta_hd);
}
/*******************************************************************************
diff --git a/bta/hd/bta_hd_api.cc b/bta/hd/bta_hd_api.cc
index 199bc7b..5459747 100644
--- a/bta/hd/bta_hd_api.cc
+++ b/bta/hd/bta_hd_api.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -104,23 +104,20 @@
p_buf->hdr.event = BTA_HD_API_REGISTER_APP_EVT;
if (p_app_info->p_name) {
- strncpy(p_buf->name, p_app_info->p_name, BTA_HD_APP_NAME_LEN);
- p_buf->name[BTA_HD_APP_NAME_LEN] = '\0';
+ strlcpy(p_buf->name, p_app_info->p_name, BTA_HD_APP_NAME_LEN);
} else {
p_buf->name[0] = '\0';
}
if (p_app_info->p_description) {
- strncpy(p_buf->description, p_app_info->p_description,
+ strlcpy(p_buf->description, p_app_info->p_description,
BTA_HD_APP_DESCRIPTION_LEN);
- p_buf->description[BTA_HD_APP_DESCRIPTION_LEN] = '\0';
} else {
p_buf->description[0] = '\0';
}
if (p_app_info->p_provider) {
- strncpy(p_buf->provider, p_app_info->p_provider, BTA_HD_APP_PROVIDER_LEN);
- p_buf->provider[BTA_HD_APP_PROVIDER_LEN] = '\0';
+ strlcpy(p_buf->provider, p_app_info->p_provider, BTA_HD_APP_PROVIDER_LEN);
} else {
p_buf->provider[0] = '\0';
}
diff --git a/bta/hd/bta_hd_int.h b/bta/hd/bta_hd_int.h
index 318e350..4a48254 100644
--- a/bta/hd/bta_hd_int.h
+++ b/bta/hd/bta_hd_int.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -77,9 +77,9 @@
typedef struct {
BT_HDR hdr;
- char name[BTA_HD_APP_NAME_LEN + 1];
- char description[BTA_HD_APP_DESCRIPTION_LEN + 1];
- char provider[BTA_HD_APP_PROVIDER_LEN + 1];
+ char name[BTA_HD_APP_NAME_LEN];
+ char description[BTA_HD_APP_DESCRIPTION_LEN];
+ char provider[BTA_HD_APP_PROVIDER_LEN];
uint8_t subclass;
uint16_t d_len;
uint8_t d_data[BTA_HD_APP_DESCRIPTOR_LEN];
@@ -141,12 +141,7 @@
bool disable_w4_close;
} tBTA_HD_CB;
-#if BTA_DYNAMIC_MEMORY == FALSE
extern tBTA_HD_CB bta_hd_cb;
-#else
-extern tBTA_HD_CB* bta_hd_cb_ptr;
-#define bta_hd_cb (*bta_hd_cb_ptr)
-#endif
/*****************************************************************************
* Function prototypes
diff --git a/bta/hd/bta_hd_main.cc b/bta/hd/bta_hd_main.cc
index dff5d9c..84784b1 100644
--- a/bta/hd/bta_hd_main.cc
+++ b/bta/hd/bta_hd_main.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -219,9 +219,7 @@
/*****************************************************************************
* Global data
****************************************************************************/
-#if BTA_DYNAMIC_MEMORY == FALSE
tBTA_HD_CB bta_hd_cb;
-#endif
static const char* bta_hd_evt_code(tBTA_HD_INT_EVT evt_code);
static const char* bta_hd_state_code(tBTA_HD_STATE state_code);
diff --git a/bta/hearing_aid/hearing_aid.cc b/bta/hearing_aid/hearing_aid.cc
new file mode 100644
index 0000000..8779542
--- /dev/null
+++ b/bta/hearing_aid/hearing_aid.cc
@@ -0,0 +1,1221 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "bta_hearing_aid_api.h"
+
+#include "bta_gatt_api.h"
+#include "bta_gatt_queue.h"
+#include "btm_int.h"
+#include "device/include/controller.h"
+#include "embdrv/g722/g722_enc_dec.h"
+#include "gap_api.h"
+#include "gatt_api.h"
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+#include <hardware/bt_hearing_aid.h>
+#include <vector>
+
+using base::Closure;
+using bluetooth::Uuid;
+using bluetooth::hearing_aid::ConnectionState;
+
+void btif_storage_add_hearing_aid(const RawAddress& address, uint16_t psm,
+ uint8_t capabilities, uint16_t codecs,
+ uint16_t audio_control_point_handle,
+ uint16_t volume_handle, uint64_t hiSyncId,
+ uint16_t render_delay,
+ uint16_t preparation_delay);
+
+constexpr uint8_t CODEC_G722_16KHZ = 0x01;
+constexpr uint8_t CODEC_G722_24KHZ = 0x02;
+
+// Masks for checking capability support
+constexpr uint8_t CAPABILITY_SIDE = 0x01;
+constexpr uint8_t CAPABILITY_BINAURAL = 0x02;
+constexpr uint8_t CAPABILITY_RESERVED = 0xFC;
+
+// audio control point opcodes
+constexpr uint8_t CONTROL_POINT_OP_START = 0x01;
+constexpr uint8_t CONTROL_POINT_OP_STOP = 0x02;
+
+// used to mark current_volume as not yet known, or possibly old
+constexpr int8_t VOLUME_UNKNOWN = 127;
+constexpr int8_t VOLUME_MIN = -127;
+
+namespace {
+
+// clang-format off
+Uuid HEARING_AID_UUID = Uuid::FromString("FDF0");
+Uuid READ_ONLY_PROPERTIES_UUID = Uuid::FromString("6333651e-c481-4a3e-9169-7c902aad37bb");
+Uuid AUDIO_CONTROL_POINT_UUID = Uuid::FromString("f0d4de7e-4a88-476c-9d9f-1937b0996cc0");
+Uuid AUDIO_STATUS_UUID = Uuid::FromString("38663f1a-e711-4cac-b641-326b56404837");
+Uuid VOLUME_UUID = Uuid::FromString("00e4ca9e-ab14-41e4-8823-f9e70c7e91df");
+Uuid LE_PSM_UUID = Uuid::FromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
+// clang-format on
+
+constexpr uint16_t MIN_CE_LEN_1M = 0x0006;
+
+void hearingaid_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
+void encryption_callback(const RawAddress*, tGATT_TRANSPORT, void*,
+ tBTM_STATUS);
+
+inline BT_HDR* malloc_l2cap_buf(uint16_t len) {
+ BT_HDR* msg = (BT_HDR*)osi_malloc(BT_HDR_SIZE + L2CAP_MIN_OFFSET +
+ len /* LE-only, no need for FCS here */);
+ msg->offset = L2CAP_MIN_OFFSET;
+ msg->len = len;
+ return msg;
+}
+
+inline uint8_t* get_l2cap_sdu_start_ptr(BT_HDR* msg) {
+ return (uint8_t*)(msg) + BT_HDR_SIZE + L2CAP_MIN_OFFSET;
+}
+
+struct AudioStats {
+ size_t packet_flush_count;
+ size_t packet_send_count;
+ size_t frame_flush_count;
+ size_t frame_send_count;
+
+ AudioStats() { Reset(); }
+
+ void Reset() {
+ packet_flush_count = 0;
+ packet_send_count = 0;
+ frame_flush_count = 0;
+ frame_send_count = 0;
+ }
+};
+
+class HearingAidImpl;
+HearingAidImpl* instance;
+HearingAidAudioReceiver* audioReceiver;
+
+struct HearingDevice {
+ RawAddress address;
+ /* This is true only during first connection to profile, until we store the
+ * device */
+ bool first_connection;
+
+ /* we are making active attempt to connect to this device, 'direct connect'.
+ * This is true only during initial phase of first connection. */
+ bool connecting_actively;
+
+ /* For two hearing aids, you must update their parameters one after another,
+ * not simulteanously, to ensure start of connection events for both devices
+ * are far from each other. This flag means that this device is waiting for
+ * update of parameters, that should happen after "LE Connection Update
+ * Complete" event
+ */
+ bool connection_update_pending;
+
+ /* if true, we are connected, L2CAP socket is open, we can stream audio*/
+ bool accepting_audio;
+
+ uint16_t conn_id;
+ uint16_t gap_handle;
+ uint16_t audio_control_point_handle;
+ uint16_t volume_handle;
+ uint16_t psm;
+
+ uint8_t capabilities;
+ uint64_t hi_sync_id;
+ uint16_t render_delay;
+ uint16_t preparation_delay;
+ uint16_t codecs;
+
+ AudioStats audio_stats;
+
+ HearingDevice(const RawAddress& address, uint16_t psm, uint8_t capabilities,
+ uint16_t codecs, uint16_t audio_control_point_handle,
+ uint16_t volume_handle, uint64_t hiSyncId,
+ uint16_t render_delay, uint16_t preparation_delay)
+ : address(address),
+ first_connection(false),
+ connecting_actively(false),
+ connection_update_pending(false),
+ accepting_audio(false),
+ conn_id(0),
+ gap_handle(0),
+ audio_control_point_handle(audio_control_point_handle),
+ volume_handle(volume_handle),
+ psm(psm),
+ capabilities(capabilities),
+ hi_sync_id(hiSyncId),
+ render_delay(render_delay),
+ preparation_delay(preparation_delay),
+ codecs(codecs) {}
+
+ HearingDevice(const RawAddress& address, bool first_connection)
+ : address(address),
+ first_connection(first_connection),
+ connecting_actively(first_connection),
+ connection_update_pending(false),
+ accepting_audio(false),
+ conn_id(0),
+ gap_handle(0),
+ psm(0) {}
+
+ HearingDevice() { HearingDevice(RawAddress::kEmpty, false); }
+
+ /* return true if this device represents left Hearing Aid. Returned value is
+ * valid only after capabilities are discovered */
+ bool isLeft() const { return !(capabilities & CAPABILITY_SIDE); }
+};
+
+class HearingDevices {
+ public:
+ void Add(HearingDevice device) {
+ if (FindByAddress(device.address) != nullptr) return;
+
+ devices.push_back(device);
+ }
+
+ void Remove(const RawAddress& address) {
+ for (auto it = devices.begin(); it != devices.end();) {
+ if (it->address != address) {
+ ++it;
+ continue;
+ }
+
+ it = devices.erase(it);
+ return;
+ }
+ }
+
+ HearingDevice* FindByAddress(const RawAddress& address) {
+ auto iter = std::find_if(devices.begin(), devices.end(),
+ [&address](const HearingDevice& device) {
+ return device.address == address;
+ });
+
+ return (iter == devices.end()) ? nullptr : &(*iter);
+ }
+
+ HearingDevice* FindByConnId(uint16_t conn_id) {
+ auto iter = std::find_if(devices.begin(), devices.end(),
+ [&conn_id](const HearingDevice& device) {
+ return device.conn_id == conn_id;
+ });
+
+ return (iter == devices.end()) ? nullptr : &(*iter);
+ }
+
+ HearingDevice* FindByGapHandle(uint16_t gap_handle) {
+ auto iter = std::find_if(devices.begin(), devices.end(),
+ [&gap_handle](const HearingDevice& device) {
+ return device.gap_handle == gap_handle;
+ });
+
+ return (iter == devices.end()) ? nullptr : &(*iter);
+ }
+
+ bool IsAnyConnectionUpdatePending() {
+ for (const auto& d : devices) {
+ if (d.connection_update_pending) return true;
+ }
+
+ return false;
+ }
+
+ size_t size() { return (devices.size()); }
+
+ std::vector<HearingDevice> devices;
+};
+
+g722_encode_state_t* encoder_state_left = nullptr;
+g722_encode_state_t* encoder_state_right = nullptr;
+
+class HearingAidImpl : public HearingAid {
+ public:
+ virtual ~HearingAidImpl() = default;
+
+ HearingAidImpl(bluetooth::hearing_aid::HearingAidCallbacks* callbacks,
+ Closure initCb)
+ : gatt_if(0),
+ seq_counter(0),
+ current_volume(VOLUME_UNKNOWN),
+ callbacks(callbacks) {
+ DVLOG(2) << __func__;
+ BTA_GATTC_AppRegister(
+ hearingaid_gattc_callback,
+ base::Bind(
+ [](Closure initCb, uint8_t client_id, uint8_t status) {
+ if (status != GATT_SUCCESS) {
+ LOG(ERROR) << "Can't start Hearing Aid profile - no gatt "
+ "clients left!";
+ return;
+ }
+ instance->gatt_if = client_id;
+ initCb.Run();
+ },
+ initCb));
+ }
+
+ void Connect(const RawAddress& address) override {
+ DVLOG(2) << __func__ << " " << address;
+ hearingDevices.Add(HearingDevice(address, true));
+ BTA_GATTC_Open(gatt_if, address, true, GATT_TRANSPORT_LE, false);
+ }
+
+ void AddFromStorage(const RawAddress& address, uint16_t psm,
+ uint8_t capabilities, uint16_t codecs,
+ uint16_t audio_control_point_handle,
+ uint16_t volume_handle, uint64_t hiSyncId,
+ uint16_t render_delay, uint16_t preparation_delay,
+ uint16_t is_white_listed) {
+ DVLOG(2) << __func__ << " " << address << ", hiSyncId=" << loghex(hiSyncId)
+ << ", isWhiteListed=" << is_white_listed;
+ if (is_white_listed) {
+ hearingDevices.Add(HearingDevice(
+ address, psm, capabilities, codecs, audio_control_point_handle,
+ volume_handle, hiSyncId, render_delay, preparation_delay));
+
+ // TODO: we should increase the scanning window for few seconds, to get
+ // faster initial connection, same after hearing aid disconnects, i.e.
+ // BTM_BleSetConnScanParams(2048, 1024);
+
+ /* add device into BG connection to accept remote initiated connection */
+ BTA_GATTC_Open(gatt_if, address, false, GATT_TRANSPORT_LE, false);
+ BTA_DmBleStartAutoConn();
+ }
+
+ callbacks->OnDeviceAvailable(capabilities, hiSyncId, address);
+ }
+
+ int GetDeviceCount() { return (hearingDevices.size()); }
+
+ void OnGattConnected(tGATT_STATUS status, uint16_t conn_id,
+ tGATT_IF client_if, RawAddress address,
+ tBTA_TRANSPORT transport, uint16_t mtu) {
+ VLOG(2) << __func__ << " " << address;
+
+ HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
+ if (!hearingDevice) {
+ DVLOG(2) << "Skipping unknown device, address=" << address;
+ return;
+ }
+
+ if (status != GATT_SUCCESS) {
+ if (!hearingDevice->connecting_actively) {
+ // whitelist connection failed, that's ok.
+ return;
+ }
+
+ LOG(INFO) << "Failed to connect to Hearing Aid device";
+ hearingDevices.Remove(address);
+ callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
+ return;
+ }
+
+ hearingDevice->connecting_actively = false;
+ hearingDevice->conn_id = conn_id;
+
+ /* We must update connection parameters one at a time, otherwise anchor
+ * point (start of connection event) for two devices can be too close to
+ * each other. Here, by setting min_ce_len=max_ce_len=X, we force controller
+ * to move anchor point of both connections away from each other, to make
+ * sure we'll be able to fit all the data we want in one connection event.
+ */
+ bool any_update_pending = hearingDevices.IsAnyConnectionUpdatePending();
+ // mark the device as pending connection update. If we don't start the
+ // update now, it'll be started once current device finishes.
+ hearingDevice->connection_update_pending = true;
+ if (!any_update_pending) {
+ L2CA_UpdateBleConnParams(address, 0x0008, 0x0008, 0x000A, 0x0064 /*1s*/,
+ MIN_CE_LEN_1M, MIN_CE_LEN_1M);
+ }
+
+ // Set data length
+ // TODO(jpawlowski: for 16khz only 87 is required, optimize
+ BTM_SetBleDataLength(address, 147);
+
+ tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(address);
+ if (p_dev_rec) {
+ if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
+ p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING) {
+ /* if security collision happened, wait for encryption done
+ * (BTA_GATTC_ENC_CMPL_CB_EVT) */
+ return;
+ }
+ }
+
+ /* verify bond */
+ uint8_t sec_flag = 0;
+ BTM_GetSecurityFlagsByTransport(address, &sec_flag, BT_TRANSPORT_LE);
+
+ if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) {
+ /* if link has been encrypted */
+ OnEncryptionComplete(address, true);
+ return;
+ }
+
+ if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) {
+ /* if bonded and link not encrypted */
+ sec_flag = BTM_BLE_SEC_ENCRYPT;
+ BTM_SetEncryption(address, BTA_TRANSPORT_LE, encryption_callback, nullptr,
+ sec_flag);
+ return;
+ }
+
+ /* otherwise let it go through */
+ OnEncryptionComplete(address, true);
+ }
+
+ void OnConnectionUpdateComplete(uint16_t conn_id) {
+ HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
+ if (!hearingDevice) {
+ DVLOG(2) << "Skipping unknown device, conn_id=" << loghex(conn_id);
+ return;
+ }
+
+ hearingDevice->connection_update_pending = false;
+
+ for (auto& device : hearingDevices.devices) {
+ if (device.conn_id && device.connection_update_pending) {
+ L2CA_UpdateBleConnParams(device.address, 0x0008, 0x0008, 0x000A,
+ 0x0064 /*1s*/, MIN_CE_LEN_1M, MIN_CE_LEN_1M);
+ return;
+ }
+ }
+ }
+
+ void OnEncryptionComplete(const RawAddress& address, bool success) {
+ HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
+ if (!hearingDevice) {
+ DVLOG(2) << "Skipping unknown device" << address;
+ return;
+ }
+
+ if (!success) {
+ LOG(ERROR) << "encryption failed";
+ BTA_GATTC_Close(hearingDevice->conn_id);
+ if (hearingDevice->first_connection) {
+ callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
+ }
+ return;
+ }
+
+ DVLOG(2) << __func__ << " " << address;
+
+ if (!hearingDevice->first_connection) {
+ // Use cached data, jump to connecting socket
+ ConnectSocket(hearingDevice);
+ return;
+ }
+
+ BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, &HEARING_AID_UUID);
+ }
+
+ void OnServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status) {
+ HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
+ if (!hearingDevice) {
+ DVLOG(2) << "Skipping unknown device, conn_id=" << loghex(conn_id);
+ return;
+ }
+
+ // Known device, nothing to do.
+ if (!hearingDevice->first_connection) return;
+
+ if (status != GATT_SUCCESS) {
+ /* close connection and report service discovery complete with error */
+ LOG(ERROR) << "Service discovery failed";
+ if (hearingDevice->first_connection) {
+ callbacks->OnConnectionState(ConnectionState::DISCONNECTED,
+ hearingDevice->address);
+ }
+ return;
+ }
+
+ const std::vector<tBTA_GATTC_SERVICE>* services =
+ BTA_GATTC_GetServices(conn_id);
+
+ const tBTA_GATTC_SERVICE* service = nullptr;
+ for (const tBTA_GATTC_SERVICE& tmp : *services) {
+ if (tmp.uuid != HEARING_AID_UUID) continue;
+ LOG(INFO) << "Found Hearing Aid service, handle=" << loghex(tmp.handle);
+ service = &tmp;
+ break;
+ }
+
+ if (!service) {
+ LOG(ERROR) << "No Hearing Aid service found";
+ callbacks->OnConnectionState(ConnectionState::DISCONNECTED,
+ hearingDevice->address);
+ return;
+ }
+
+ uint16_t psm_handle = 0x0000;
+ for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+ if (charac.uuid == READ_ONLY_PROPERTIES_UUID) {
+ DVLOG(2) << "Reading read only properties "
+ << loghex(charac.value_handle);
+ BtaGattQueue::ReadCharacteristic(
+ conn_id, charac.value_handle,
+ HearingAidImpl::OnReadOnlyPropertiesReadStatic, nullptr);
+ } else if (charac.uuid == AUDIO_CONTROL_POINT_UUID) {
+ hearingDevice->audio_control_point_handle = charac.value_handle;
+ // store audio control point!
+ } else if (charac.uuid == AUDIO_STATUS_UUID) {
+ DVLOG(2) << "Reading Audio status " << loghex(charac.value_handle);
+ BtaGattQueue::ReadCharacteristic(conn_id, charac.value_handle,
+ HearingAidImpl::OnAudioStatusStatic,
+ nullptr);
+ } else if (charac.uuid == VOLUME_UUID) {
+ hearingDevice->volume_handle = charac.value_handle;
+ } else if (charac.uuid == LE_PSM_UUID) {
+ psm_handle = charac.value_handle;
+ } else {
+ LOG(WARNING) << "Unknown characteristic found:" << charac.uuid;
+ }
+ }
+
+ if (psm_handle) {
+ DVLOG(2) << "Reading PSM " << loghex(psm_handle);
+ BtaGattQueue::ReadCharacteristic(
+ conn_id, psm_handle, HearingAidImpl::OnPsmReadStatic, nullptr);
+ }
+ }
+
+ void OnReadOnlyPropertiesRead(uint16_t conn_id, tGATT_STATUS status,
+ uint16_t handle, uint16_t len, uint8_t* value,
+ void* data) {
+ HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
+ if (!hearingDevice) {
+ DVLOG(2) << __func__ << "unknown conn_id=" << loghex(conn_id);
+ return;
+ }
+
+ VLOG(2) << __func__ << " " << base::HexEncode(value, len);
+
+ uint8_t* p = value;
+
+ uint8_t version;
+ STREAM_TO_UINT8(version, p);
+
+ if (version != 0x01) {
+ LOG(WARNING) << "Unknown version: " << loghex(version);
+ return;
+ }
+
+ // version 0x01 of read only properties:
+ if (len < 17) {
+ LOG(WARNING) << "Read only properties too short: " << loghex(len);
+ return;
+ }
+ uint8_t capabilities;
+ STREAM_TO_UINT8(capabilities, p);
+ hearingDevice->capabilities = capabilities;
+ bool side = capabilities & CAPABILITY_SIDE;
+ bool standalone = capabilities & CAPABILITY_BINAURAL;
+ VLOG(2) << __func__ << " capabilities: " << (side ? "right" : "left")
+ << ", " << (standalone ? "binaural" : "monaural");
+
+ if (capabilities & CAPABILITY_RESERVED) {
+ LOG(WARNING) << __func__ << " reserved capabilities are set";
+ }
+
+ STREAM_TO_UINT64(hearingDevice->hi_sync_id, p);
+ VLOG(2) << __func__ << " hiSyncId: " << loghex(hearingDevice->hi_sync_id);
+ uint8_t feature_map;
+ STREAM_TO_UINT8(feature_map, p);
+
+ STREAM_TO_UINT16(hearingDevice->render_delay, p);
+ VLOG(2) << __func__
+ << " render delay: " << loghex(hearingDevice->render_delay);
+
+ STREAM_TO_UINT16(hearingDevice->preparation_delay, p);
+ VLOG(2) << __func__ << " preparation delay: "
+ << loghex(hearingDevice->preparation_delay);
+
+ uint16_t codecs;
+ STREAM_TO_UINT16(codecs, p);
+ hearingDevice->codecs = codecs;
+ VLOG(2) << __func__ << " supported codecs: " << loghex(codecs);
+ if (codecs & (1 << CODEC_G722_16KHZ)) VLOG(2) << "\tG722@16kHz";
+ if (codecs & (1 << CODEC_G722_24KHZ)) VLOG(2) << "\tG722@24kHz";
+
+ if (!(codecs & (1 << CODEC_G722_16KHZ))) {
+ LOG(WARNING) << __func__ << " Mandatory codec, G722@16kHz not supported";
+ }
+ }
+
+ void OnAudioStatus(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
+ uint16_t len, uint8_t* value, void* data) {
+ DVLOG(2) << __func__ << " " << base::HexEncode(value, len);
+ }
+
+ void OnPsmRead(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
+ uint16_t len, uint8_t* value, void* data) {
+ HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
+ if (!hearingDevice) {
+ DVLOG(2) << "Skipping unknown read event, conn_id=" << loghex(conn_id);
+ return;
+ }
+
+ if (status != GATT_SUCCESS) {
+ LOG(ERROR) << "Error reading PSM for device" << hearingDevice->address;
+ return;
+ }
+
+ if (len > 2) {
+ LOG(ERROR) << "Bad PSM length";
+ return;
+ }
+
+ uint16_t psm_val = *((uint16_t*)value);
+ hearingDevice->psm = psm_val;
+ VLOG(2) << "read psm:" << loghex(hearingDevice->psm);
+
+ ConnectSocket(hearingDevice);
+ }
+
+ void ConnectSocket(HearingDevice* hearingDevice) {
+ tL2CAP_CFG_INFO cfg_info = tL2CAP_CFG_INFO{.mtu = 512};
+
+ uint16_t gap_handle = GAP_ConnOpen(
+ "", 0, false, &hearingDevice->address, hearingDevice->psm,
+ 514 /* MPS */, &cfg_info, nullptr,
+ BTM_SEC_NONE /* TODO: request security ? */, L2CAP_FCR_LE_COC_MODE,
+ HearingAidImpl::GapCallbackStatic, BT_TRANSPORT_LE);
+ if (gap_handle == GAP_INVALID_HANDLE) {
+ LOG(ERROR) << "UNABLE TO GET gap_handle";
+ return;
+ }
+
+ hearingDevice->gap_handle = gap_handle;
+ LOG(INFO) << "Successfully sent GAP connect request";
+ }
+
+ static void OnReadOnlyPropertiesReadStatic(uint16_t conn_id,
+ tGATT_STATUS status,
+ uint16_t handle, uint16_t len,
+ uint8_t* value, void* data) {
+ if (instance)
+ instance->OnReadOnlyPropertiesRead(conn_id, status, handle, len, value,
+ data);
+ }
+ static void OnAudioStatusStatic(uint16_t conn_id, tGATT_STATUS status,
+ uint16_t handle, uint16_t len, uint8_t* value,
+ void* data) {
+ if (instance)
+ instance->OnAudioStatus(conn_id, status, handle, len, value, data);
+ }
+
+ static void OnPsmReadStatic(uint16_t conn_id, tGATT_STATUS status,
+ uint16_t handle, uint16_t len, uint8_t* value,
+ void* data) {
+ if (instance)
+ instance->OnPsmRead(conn_id, status, handle, len, value, data);
+ }
+
+ /* CoC Socket is ready */
+ void OnGapConnection(const RawAddress& address) {
+ HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
+ if (!hearingDevice) {
+ LOG(INFO) << "Device not connected to profile" << address;
+ return;
+ }
+
+ if (hearingDevice->first_connection) {
+ /* add device into BG connection to accept remote initiated connection */
+ BTA_GATTC_Open(gatt_if, address, false, GATT_TRANSPORT_LE, false);
+ BTA_DmBleStartAutoConn();
+
+ btif_storage_add_hearing_aid(
+ address, hearingDevice->psm, hearingDevice->capabilities,
+ hearingDevice->codecs, hearingDevice->audio_control_point_handle,
+ hearingDevice->volume_handle, hearingDevice->hi_sync_id,
+ hearingDevice->render_delay, hearingDevice->preparation_delay);
+
+ hearingDevice->first_connection = false;
+ }
+
+ SendStart(*hearingDevice);
+
+ hearingDevice->accepting_audio = true;
+ LOG(INFO) << __func__ << ": address=" << address
+ << ", hi_sync_id=" << loghex(hearingDevice->hi_sync_id);
+ callbacks->OnDeviceAvailable(hearingDevice->capabilities,
+ hearingDevice->hi_sync_id, address);
+ callbacks->OnConnectionState(ConnectionState::CONNECTED, address);
+
+ StartSendingAudio(*hearingDevice);
+ }
+
+ void StartSendingAudio(const HearingDevice& hearingDevice) {
+ VLOG(0) << __func__ << hearingDevice.address;
+
+ if (encoder_state_left == nullptr) {
+ encoder_state_left = g722_encode_init(nullptr, 64000, G722_PACKED);
+ encoder_state_right = g722_encode_init(nullptr, 64000, G722_PACKED);
+ seq_counter = 0;
+
+ // use the best codec avaliable for this pair of devices.
+ uint16_t codecs = hearingDevice.codecs;
+ if (hearingDevice.hi_sync_id != 0) {
+ for (const auto& device : hearingDevices.devices) {
+ if (device.hi_sync_id != hearingDevice.hi_sync_id) continue;
+
+ codecs &= device.codecs;
+ }
+ }
+
+ if ((codecs & (1 << CODEC_G722_24KHZ)) &&
+ controller_get_interface()->supports_ble_2m_phy()) {
+ codec_in_use = CODEC_G722_24KHZ;
+ codec.sample_rate = 24000;
+ codec.bit_rate = 16;
+ codec.data_interval_ms = 10;
+ } else if (codecs & (1 << CODEC_G722_16KHZ)) {
+ codec_in_use = CODEC_G722_16KHZ;
+ codec.sample_rate = 16000;
+ codec.bit_rate = 16;
+ codec.data_interval_ms = 10;
+ }
+
+ // TODO: remove once we implement support for other codecs
+ codec_in_use = CODEC_G722_16KHZ;
+ HearingAidAudioSource::Start(codec, audioReceiver);
+ }
+ }
+
+ void OnAudioSuspend() {
+ DVLOG(2) << __func__;
+
+ std::vector<uint8_t> stop({CONTROL_POINT_OP_STOP});
+ for (const auto& device : hearingDevices.devices) {
+ if (!device.accepting_audio) continue;
+
+ BtaGattQueue::WriteCharacteristic(device.conn_id,
+ device.audio_control_point_handle, stop,
+ GATT_WRITE, nullptr, nullptr);
+ }
+ }
+
+ void OnAudioResume() {
+ DVLOG(2) << __func__;
+
+ // TODO: shall we also reset the encoder ?
+ if (encoder_state_left != nullptr) {
+ g722_encode_release(encoder_state_left);
+ g722_encode_release(encoder_state_right);
+ encoder_state_left = g722_encode_init(nullptr, 64000, G722_PACKED);
+ encoder_state_right = g722_encode_init(nullptr, 64000, G722_PACKED);
+ }
+ seq_counter = 0;
+
+ for (const auto& device : hearingDevices.devices) {
+ if (!device.accepting_audio) continue;
+ SendStart(device);
+ }
+ }
+
+ void SendStart(const HearingDevice& device) {
+ std::vector<uint8_t> start({CONTROL_POINT_OP_START, codec_in_use,
+ 0x02 /* media */, (uint8_t)current_volume});
+
+ if (current_volume == VOLUME_UNKNOWN) start[3] = (uint8_t)VOLUME_MIN;
+
+ BtaGattQueue::WriteCharacteristic(device.conn_id,
+ device.audio_control_point_handle, start,
+ GATT_WRITE, nullptr, nullptr);
+
+ // TODO(jpawlowski): this will be removed, once test devices get volume
+ // from start reqest
+ if (current_volume != VOLUME_UNKNOWN) {
+ std::vector<uint8_t> volume_value(
+ {static_cast<unsigned char>(current_volume)});
+ BtaGattQueue::WriteCharacteristic(device.conn_id, device.volume_handle,
+ volume_value, GATT_WRITE_NO_RSP,
+ nullptr, nullptr);
+ }
+ }
+
+ void OnAudioDataReady(const std::vector<uint8_t>& data) {
+ /* For now we assume data comes in as 16bit per sample 16kHz PCM stereo */
+ DVLOG(2) << __func__;
+
+ int num_samples =
+ data.size() / (2 /*bytes_per_sample*/ * 2 /*number of channels*/);
+
+ // The G.722 codec accept only even number of samples for encoding
+ if (num_samples % 2 != 0)
+ LOG(FATAL) << "num_samples is not even: " << num_samples;
+
+ std::vector<uint16_t> chan_left;
+ std::vector<uint16_t> chan_right;
+ // TODO: encode data into G.722 left/right or mono.
+ for (int i = 0; i < num_samples; i++) {
+ const uint8_t* sample = data.data() + i * 4;
+
+ uint16_t left = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
+ chan_left.push_back(left);
+
+ sample += 2;
+ uint16_t right = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
+ chan_right.push_back(right);
+ }
+
+ // TODO: we should cache left/right and current state, instad of recomputing
+ // it for each packet, 100 times a second.
+ HearingDevice* left = nullptr;
+ HearingDevice* right = nullptr;
+ for (auto& device : hearingDevices.devices) {
+ if (!device.accepting_audio) continue;
+
+ if (device.isLeft())
+ left = &device;
+ else
+ right = &device;
+ }
+
+ if (left == nullptr && right == nullptr) {
+ HearingAidAudioSource::Stop();
+ current_volume = VOLUME_UNKNOWN;
+ return;
+ }
+
+ // TODO: monural, binarual check
+
+ // divide encoded data into packets, add header, send.
+
+ // TODO: make those buffers static and global to prevent constant
+ // reallocations
+ // TODO: this should basically fit the encoded data, tune the size later
+ std::vector<uint8_t> encoded_data_left;
+ if (left) {
+ encoded_data_left.resize(2000);
+ int encoded_size =
+ g722_encode(encoder_state_left, encoded_data_left.data(),
+ (const int16_t*)chan_left.data(), chan_left.size());
+ encoded_data_left.resize(encoded_size);
+
+ uint16_t cid = GAP_ConnGetL2CAPCid(left->gap_handle);
+ uint16_t packets_to_flush = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
+ if (packets_to_flush) {
+ VLOG(2) << left->address << " skipping " << packets_to_flush
+ << " packets";
+ left->audio_stats.packet_flush_count += packets_to_flush;
+ left->audio_stats.frame_flush_count++;
+ }
+ // flush all packets stuck in queue
+ L2CA_FlushChannel(cid, 0xffff);
+ }
+
+ std::vector<uint8_t> encoded_data_right;
+ if (right) {
+ encoded_data_right.resize(2000);
+ int encoded_size =
+ g722_encode(encoder_state_right, encoded_data_right.data(),
+ (const int16_t*)chan_right.data(), chan_right.size());
+ encoded_data_right.resize(encoded_size);
+
+ uint16_t cid = GAP_ConnGetL2CAPCid(right->gap_handle);
+ uint16_t packets_to_flush = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
+ if (packets_to_flush) {
+ VLOG(2) << right->address << " skipping " << packets_to_flush
+ << " packets";
+ right->audio_stats.packet_flush_count += packets_to_flush;
+ right->audio_stats.frame_flush_count++;
+ }
+ // flush all packets stuck in queue
+ L2CA_FlushChannel(cid, 0xffff);
+ }
+
+ size_t encoded_data_size =
+ std::max(encoded_data_left.size(), encoded_data_right.size());
+
+ // TODO: make it also dependent on the interval, when we support intervals
+ // different than 10ms
+ uint16_t packet_size;
+
+ if (codec_in_use == CODEC_G722_24KHZ) {
+ packet_size = 120;
+ } else /* if (codec_in_use == CODEC_G722_16KHZ) */ {
+ packet_size = 80;
+ }
+
+ for (size_t i = 0; i < encoded_data_size; i += packet_size) {
+ if (left) {
+ left->audio_stats.packet_send_count++;
+ SendAudio(encoded_data_left.data() + i, packet_size, left);
+ }
+ if (right) {
+ right->audio_stats.packet_send_count++;
+ SendAudio(encoded_data_right.data() + i, packet_size, right);
+ }
+ seq_counter++;
+ }
+ if (left) left->audio_stats.frame_send_count++;
+ if (right) right->audio_stats.frame_send_count++;
+ }
+
+ void SendAudio(uint8_t* encoded_data, uint16_t packet_size,
+ HearingDevice* hearingAid) {
+ BT_HDR* audio_packet = malloc_l2cap_buf(packet_size + 1);
+ uint8_t* p = get_l2cap_sdu_start_ptr(audio_packet);
+ *p = seq_counter;
+ p++;
+ memcpy(p, encoded_data, packet_size);
+
+ DVLOG(2) << hearingAid->address << " : " << base::HexEncode(p, packet_size);
+
+ uint16_t result = GAP_ConnWriteData(hearingAid->gap_handle, audio_packet);
+
+ if (result != BT_PASS) {
+ LOG(ERROR) << " Error sending data: " << loghex(result);
+ }
+ }
+
+ void GapCallback(uint16_t gap_handle, uint16_t event, tGAP_CB_DATA* data) {
+ HearingDevice* hearingDevice = hearingDevices.FindByGapHandle(gap_handle);
+ if (!hearingDevice) {
+ DVLOG(2) << "Skipping unknown device, gap_handle=" << gap_handle;
+ return;
+ }
+
+ switch (event) {
+ case GAP_EVT_CONN_OPENED: {
+ RawAddress address = *GAP_ConnGetRemoteAddr(gap_handle);
+ uint16_t tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
+
+ LOG(INFO) << "GAP_EVT_CONN_OPENED " << address << ", tx_mtu=" << tx_mtu;
+ OnGapConnection(address);
+ break;
+ }
+
+ // TODO: handle properly!
+ case GAP_EVT_CONN_CLOSED:
+ DVLOG(2) << "GAP_EVT_CONN_CLOSED";
+ hearingDevice->accepting_audio = false;
+ hearingDevice->gap_handle = 0;
+ break;
+ case GAP_EVT_CONN_DATA_AVAIL: {
+ DVLOG(2) << "GAP_EVT_CONN_DATA_AVAIL";
+
+ // only data we receive back from hearing aids are some stats, not
+ // really important, but useful now for debugging.
+ uint32_t bytes_to_read = 0;
+ GAP_GetRxQueueCnt(gap_handle, &bytes_to_read);
+ std::vector<uint8_t> buffer(bytes_to_read);
+
+ uint16_t bytes_read = 0;
+ // TODO:GAP_ConnReadData should accpet uint32_t for length!
+ GAP_ConnReadData(gap_handle, buffer.data(), buffer.size(), &bytes_read);
+
+ if (bytes_read < 4) {
+ LOG(WARNING) << " Wrong data length";
+ return;
+ }
+
+ uint8_t* p = buffer.data();
+
+ DVLOG(1) << "stats from the hearing aid:";
+ for (size_t i = 0; i + 4 <= buffer.size(); i += 4) {
+ uint16_t event_counter, frame_index;
+ STREAM_TO_UINT16(event_counter, p);
+ STREAM_TO_UINT16(frame_index, p);
+ DVLOG(1) << "event_counter=" << event_counter
+ << " frame_index: " << frame_index;
+ }
+ break;
+ }
+
+ case GAP_EVT_TX_EMPTY:
+ DVLOG(2) << "GAP_EVT_TX_EMPTY";
+ break;
+ case GAP_EVT_CONN_CONGESTED:
+ DVLOG(2) << "GAP_EVT_CONN_CONGESTED";
+
+ // TODO: make it into function
+ HearingAidAudioSource::Stop();
+ // TODO: kill the encoder only if all hearing aids are down.
+ // g722_encode_release(encoder_state);
+ // encoder_state_left = nulllptr;
+ // encoder_state_right = nulllptr;
+ break;
+ case GAP_EVT_CONN_UNCONGESTED:
+ DVLOG(2) << "GAP_EVT_CONN_UNCONGESTED";
+ break;
+
+ case GAP_EVT_LE_COC_CREDITS: {
+ auto& tmp = data->coc_credits;
+ DVLOG(2) << "GAP_EVT_LE_COC_CREDITS, for device: "
+ << hearingDevice->address << " added" << tmp.credits_received
+ << " credit_count: " << tmp.credit_count;
+ break;
+ }
+ }
+ }
+
+ static void GapCallbackStatic(uint16_t gap_handle, uint16_t event,
+ tGAP_CB_DATA* data) {
+ if (instance) instance->GapCallback(gap_handle, event, data);
+ }
+
+ void Dump(int fd) {
+ std::stringstream stream;
+ for (const auto& device : hearingDevices.devices) {
+ bool side = device.capabilities & CAPABILITY_SIDE;
+ bool standalone = device.capabilities & CAPABILITY_BINAURAL;
+ stream << " " << device.address.ToString() << " "
+ << (device.accepting_audio ? "" : "not ") << "connected"
+ << "\n " << (standalone ? "binaural" : "monaural") << " "
+ << (side ? "right" : "left") << " " << loghex(device.hi_sync_id)
+ << std::endl;
+ stream
+ << " Packet counts (enqueued/flushed) : "
+ << device.audio_stats.packet_send_count << " / "
+ << device.audio_stats.packet_flush_count
+ << "\n Frame counts (enqueued/flushed) : "
+ << device.audio_stats.frame_send_count << " / "
+ << device.audio_stats.frame_flush_count << std::endl;
+ }
+ dprintf(fd, "%s", stream.str().c_str());
+ }
+
+ void Disconnect(const RawAddress& address) override {
+ DVLOG(2) << __func__;
+ HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
+ if (!hearingDevice) {
+ LOG(INFO) << "Device not connected to profile" << address;
+ return;
+ }
+
+ VLOG(2) << __func__ << ": " << address;
+
+ bool connected = hearingDevice->accepting_audio;
+ hearingDevice->accepting_audio = false;
+
+ if (hearingDevice->connecting_actively) {
+ // cancel pending direct connect
+ BTA_GATTC_CancelOpen(gatt_if, address, true);
+ }
+
+ if (hearingDevice->conn_id) {
+ BTA_GATTC_Close(hearingDevice->conn_id);
+ }
+
+ if (hearingDevice->gap_handle) {
+ GAP_ConnClose(hearingDevice->gap_handle);
+ hearingDevice->gap_handle = 0;
+ }
+
+ // cancel autoconnect
+ BTA_GATTC_CancelOpen(gatt_if, address, false);
+
+ hearingDevices.Remove(address);
+
+ if (connected)
+ callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
+ }
+
+ void OnGattDisconnected(tGATT_STATUS status, uint16_t conn_id,
+ tGATT_IF client_if, RawAddress remote_bda,
+ tBTA_GATT_REASON reason) {
+ HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
+ if (!hearingDevice) {
+ VLOG(2) << "Skipping unknown device disconnect, conn_id=" << conn_id;
+ return;
+ }
+
+ hearingDevice->accepting_audio = false;
+ hearingDevice->conn_id = 0;
+
+ BtaGattQueue::Clean(conn_id);
+
+ callbacks->OnConnectionState(ConnectionState::DISCONNECTED, remote_bda);
+ }
+
+ void SetVolume(int8_t volume) override {
+ VLOG(2) << __func__ << ": " << +volume;
+ current_volume = volume;
+ for (HearingDevice& device : hearingDevices.devices) {
+ if (!device.accepting_audio) continue;
+
+ std::vector<uint8_t> volume_value({static_cast<unsigned char>(volume)});
+ BtaGattQueue::WriteCharacteristic(device.conn_id, device.volume_handle,
+ volume_value, GATT_WRITE_NO_RSP,
+ nullptr, nullptr);
+ }
+ }
+
+ void CleanUp() {
+ BTA_GATTC_AppDeregister(gatt_if);
+ for (HearingDevice& device : hearingDevices.devices) {
+ if (!device.gap_handle) continue;
+
+ GAP_ConnClose(device.gap_handle);
+ device.gap_handle = 0;
+ }
+
+ hearingDevices.devices.clear();
+ HearingAidAudioSource::Stop();
+ }
+
+ private:
+ uint8_t gatt_if;
+ uint8_t seq_counter;
+ /* current volume gain for the hearing aids*/
+ int8_t current_volume;
+ bluetooth::hearing_aid::HearingAidCallbacks* callbacks;
+
+ /* currently used codec */
+ uint8_t codec_in_use;
+ CodecConfiguration codec;
+
+ HearingDevices hearingDevices;
+};
+
+void hearingaid_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
+ VLOG(2) << __func__ << " event = " << +event;
+
+ if (p_data == nullptr) return;
+
+ switch (event) {
+ case BTA_GATTC_DEREG_EVT:
+ break;
+
+ case BTA_GATTC_OPEN_EVT: {
+ if (!instance) return;
+ tBTA_GATTC_OPEN& o = p_data->open;
+ instance->OnGattConnected(o.status, o.conn_id, o.client_if, o.remote_bda,
+ o.transport, o.mtu);
+ break;
+ }
+
+ case BTA_GATTC_CLOSE_EVT: {
+ if (!instance) return;
+ tBTA_GATTC_CLOSE& c = p_data->close;
+ instance->OnGattDisconnected(c.status, c.conn_id, c.client_if,
+ c.remote_bda, c.reason);
+ } break;
+
+ case BTA_GATTC_SEARCH_CMPL_EVT:
+ if (!instance) return;
+ instance->OnServiceSearchComplete(p_data->search_cmpl.conn_id,
+ p_data->search_cmpl.status);
+ break;
+
+ case BTA_GATTC_NOTIF_EVT:
+ break;
+
+ case BTA_GATTC_ENC_CMPL_CB_EVT:
+ if (!instance) return;
+ instance->OnEncryptionComplete(p_data->enc_cmpl.remote_bda, true);
+ break;
+
+ case BTA_GATTC_CONN_UPDATE_EVT:
+ if (!instance) return;
+ instance->OnConnectionUpdateComplete(p_data->conn_update.conn_id);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void encryption_callback(const RawAddress* address, tGATT_TRANSPORT, void*,
+ tBTM_STATUS status) {
+ if (instance) {
+ instance->OnEncryptionComplete(*address,
+ status == BTM_SUCCESS ? true : false);
+ }
+}
+
+class HearingAidAudioReceiverImpl : public HearingAidAudioReceiver {
+ public:
+ void OnAudioDataReady(const std::vector<uint8_t>& data) override {
+ if (instance) instance->OnAudioDataReady(data);
+ }
+ void OnAudioSuspend() override {
+ if (instance) instance->OnAudioSuspend();
+ }
+
+ void OnAudioResume() override {
+ if (instance) instance->OnAudioResume();
+ }
+};
+
+HearingAidAudioReceiverImpl audioReceiverImpl;
+
+} // namespace
+
+void HearingAid::Initialize(
+ bluetooth::hearing_aid::HearingAidCallbacks* callbacks, Closure initCb) {
+ if (instance) {
+ LOG(ERROR) << "Already initialized!";
+ }
+
+ audioReceiver = &audioReceiverImpl;
+ instance = new HearingAidImpl(callbacks, initCb);
+ HearingAidAudioSource::Initialize();
+}
+
+bool HearingAid::IsInitialized() { return instance; }
+
+HearingAid* HearingAid::Get() {
+ CHECK(instance);
+ return instance;
+};
+
+void HearingAid::AddFromStorage(const RawAddress& address, uint16_t psm,
+ uint8_t capabilities, uint16_t codecs,
+ uint16_t audio_control_point_handle,
+ uint16_t volume_handle, uint64_t hiSyncId,
+ uint16_t render_delay,
+ uint16_t preparation_delay,
+ uint16_t is_white_listed) {
+ if (!instance) {
+ LOG(ERROR) << "Not initialized yet";
+ }
+
+ instance->AddFromStorage(address, psm, capabilities, codecs,
+ audio_control_point_handle, volume_handle, hiSyncId,
+ render_delay, preparation_delay, is_white_listed);
+};
+
+int HearingAid::GetDeviceCount() {
+ if (!instance) {
+ LOG(INFO) << __func__ << ": Not initialized yet";
+ return 0;
+ }
+
+ return (instance->GetDeviceCount());
+}
+
+void HearingAid::CleanUp() {
+ // Must stop audio source to make sure it doesn't call any of callbacks on our
+ // soon to be null instance
+ HearingAidAudioSource::Stop();
+ HearingAidAudioSource::CleanUp();
+
+ instance->CleanUp();
+ HearingAidImpl* ptr = instance;
+ instance = nullptr;
+ delete ptr;
+};
+
+void HearingAid::DebugDump(int fd) {
+ dprintf(fd, "\nHearing Aid Manager:\n");
+ if (instance) instance->Dump(fd);
+ HearingAidAudioSource::DebugDump(fd);
+}
\ No newline at end of file
diff --git a/bta/hearing_aid/hearing_aid_audio_source.cc b/bta/hearing_aid/hearing_aid_audio_source.cc
new file mode 100644
index 0000000..947caaf
--- /dev/null
+++ b/bta/hearing_aid/hearing_aid_audio_source.cc
@@ -0,0 +1,304 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h"
+#include "bta_hearing_aid_api.h"
+#include "osi/include/alarm.h"
+#include "uipc.h"
+
+#include <base/files/file_util.h>
+#include <include/hardware/bt_av.h>
+
+using base::FilePath;
+extern const char* audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event);
+
+namespace {
+int bit_rate = 16;
+int sample_rate = 16000;
+int data_interval_ms = 10 /* msec */;
+int num_channels = 2;
+alarm_t* audio_timer = nullptr;
+
+HearingAidAudioReceiver* localAudioReceiver;
+std::unique_ptr<tUIPC_STATE> uipc_hearing_aid;
+
+struct AudioHalStats {
+ size_t media_read_total_underflow_bytes;
+ size_t media_read_total_underflow_count;
+ uint64_t media_read_last_underflow_us;
+
+ AudioHalStats() { Reset(); }
+
+ void Reset() {
+ media_read_total_underflow_bytes = 0;
+ media_read_total_underflow_count = 0;
+ media_read_last_underflow_us = 0;
+ }
+};
+
+AudioHalStats stats;
+
+void send_audio_data(void*) {
+ uint32_t bytes_per_tick =
+ (num_channels * sample_rate * data_interval_ms * (bit_rate / 8)) / 1000;
+
+ uint16_t event;
+ uint8_t p_buf[bytes_per_tick];
+
+ uint32_t bytes_read = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO,
+ &event, p_buf, bytes_per_tick);
+
+ VLOG(2) << "bytes_read: " << bytes_read;
+ if (bytes_read < bytes_per_tick) {
+ stats.media_read_total_underflow_bytes += bytes_per_tick - bytes_read;
+ stats.media_read_total_underflow_count++;
+ stats.media_read_last_underflow_us = time_get_os_boottime_us();
+ }
+
+ std::vector<uint8_t> data(p_buf, p_buf + bytes_read);
+
+ localAudioReceiver->OnAudioDataReady(data);
+}
+
+void hearing_aid_send_ack(tHEARING_AID_CTRL_ACK status) {
+ uint8_t ack = status;
+ DVLOG(2) << "Hearing Aid audio ctrl ack: " << status;
+ UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, &ack, sizeof(ack));
+}
+
+void hearing_aid_data_cb(tUIPC_CH_ID, tUIPC_EVENT event) {
+ DVLOG(2) << "Hearing Aid audio data event: " << event;
+ switch (event) {
+ case UIPC_OPEN_EVT:
+ /*
+ * Read directly from media task from here on (keep callback for
+ * connection events.
+ */
+ UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO,
+ UIPC_REG_REMOVE_ACTIVE_READSET, NULL);
+ UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO,
+ reinterpret_cast<void*>(0));
+
+ audio_timer = alarm_new_periodic("hearing_aid_data_timer");
+ alarm_set_on_mloop(audio_timer, data_interval_ms, send_audio_data,
+ nullptr);
+ break;
+ case UIPC_CLOSE_EVT:
+ hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
+ if (audio_timer) {
+ alarm_cancel(audio_timer);
+ }
+ break;
+ default:
+ LOG(ERROR) << "Hearing Aid audio data event not recognized:" << event;
+ }
+}
+
+void hearing_aid_recv_ctrl_data() {
+ tHEARING_AID_CTRL_CMD cmd = HEARING_AID_CTRL_CMD_NONE;
+ int n;
+
+ uint8_t read_cmd = 0; /* The read command size is one octet */
+ n = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, NULL, &read_cmd, 1);
+ cmd = static_cast<tHEARING_AID_CTRL_CMD>(read_cmd);
+
+ /* detach on ctrl channel means audioflinger process was terminated */
+ if (n == 0) {
+ LOG(WARNING) << __func__ << "CTRL CH DETACHED";
+ UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL);
+ return;
+ }
+
+ VLOG(2) << __func__ << " " << audio_ha_hw_dump_ctrl_event(cmd);
+ // a2dp_cmd_pending = cmd;
+
+ switch (cmd) {
+ case HEARING_AID_CTRL_CMD_CHECK_READY:
+ hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
+ break;
+
+ case HEARING_AID_CTRL_CMD_START:
+ if (localAudioReceiver) localAudioReceiver->OnAudioResume();
+ // timer is restarted in UIPC_Open
+ UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, hearing_aid_data_cb,
+ HEARING_AID_DATA_PATH);
+ hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
+ break;
+
+ case HEARING_AID_CTRL_CMD_STOP:
+ hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
+ break;
+
+ case HEARING_AID_CTRL_CMD_SUSPEND:
+ if (audio_timer) alarm_cancel(audio_timer);
+ if (localAudioReceiver) localAudioReceiver->OnAudioSuspend();
+ hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
+ break;
+
+ case HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG: {
+ btav_a2dp_codec_config_t codec_config;
+ btav_a2dp_codec_config_t codec_capability;
+ if (sample_rate == 16000) {
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_16000;
+ codec_capability.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_16000;
+ } else if (sample_rate == 24000) {
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_24000;
+ codec_capability.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_24000;
+ } else {
+ LOG(FATAL) << "unsupported sample rate: " << sample_rate;
+ }
+
+ codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
+ codec_capability.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
+
+ codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ codec_capability.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+
+ hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
+ // Send the current codec config
+ UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<const uint8_t*>(&codec_config.sample_rate),
+ sizeof(btav_a2dp_codec_sample_rate_t));
+ UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<const uint8_t*>(&codec_config.bits_per_sample),
+ sizeof(btav_a2dp_codec_bits_per_sample_t));
+ UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<const uint8_t*>(&codec_config.channel_mode),
+ sizeof(btav_a2dp_codec_channel_mode_t));
+ // Send the current codec capability
+ UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<const uint8_t*>(&codec_capability.sample_rate),
+ sizeof(btav_a2dp_codec_sample_rate_t));
+ UIPC_Send(
+ *uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<const uint8_t*>(&codec_capability.bits_per_sample),
+ sizeof(btav_a2dp_codec_bits_per_sample_t));
+ UIPC_Send(
+ *uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<const uint8_t*>(&codec_capability.channel_mode),
+ sizeof(btav_a2dp_codec_channel_mode_t));
+ break;
+ }
+
+ case HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG: {
+ // TODO: we only support one config for now!
+ btav_a2dp_codec_config_t codec_config;
+ codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
+ codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE;
+ codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
+
+ hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
+ // Send the current codec config
+ if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<uint8_t*>(&codec_config.sample_rate),
+ sizeof(btav_a2dp_codec_sample_rate_t)) !=
+ sizeof(btav_a2dp_codec_sample_rate_t)) {
+ LOG(ERROR) << __func__ << "Error reading sample rate from audio HAL";
+ break;
+ }
+ if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<uint8_t*>(&codec_config.bits_per_sample),
+ sizeof(btav_a2dp_codec_bits_per_sample_t)) !=
+ sizeof(btav_a2dp_codec_bits_per_sample_t)) {
+ LOG(ERROR) << __func__
+ << "Error reading bits per sample from audio HAL";
+
+ break;
+ }
+ if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<uint8_t*>(&codec_config.channel_mode),
+ sizeof(btav_a2dp_codec_channel_mode_t)) !=
+ sizeof(btav_a2dp_codec_channel_mode_t)) {
+ LOG(ERROR) << __func__ << "Error reading channel mode from audio HAL";
+
+ break;
+ }
+ LOG(INFO) << __func__ << " HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG: "
+ << "sample_rate=" << codec_config.sample_rate
+ << "bits_per_sample=" << codec_config.bits_per_sample
+ << "channel_mode=" << codec_config.channel_mode;
+ break;
+ }
+
+ default:
+ LOG(ERROR) << __func__ << "UNSUPPORTED CMD: " << cmd;
+ hearing_aid_send_ack(HEARING_AID_CTRL_ACK_FAILURE);
+ break;
+ }
+ VLOG(2) << __func__ << " a2dp-ctrl-cmd : " << audio_ha_hw_dump_ctrl_event(cmd)
+ << " DONE";
+}
+
+void hearing_aid_ctrl_cb(tUIPC_CH_ID, tUIPC_EVENT event) {
+ VLOG(2) << "Hearing Aid audio ctrl event: " << event;
+ switch (event) {
+ case UIPC_OPEN_EVT:
+ break;
+ case UIPC_CLOSE_EVT:
+ UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb,
+ HEARING_AID_CTRL_PATH);
+ break;
+ case UIPC_RX_DATA_READY_EVT:
+ hearing_aid_recv_ctrl_data();
+ break;
+ default:
+ LOG(ERROR) << "Hearing Aid audio ctrl unrecognized event: " << event;
+ }
+}
+} // namespace
+
+void HearingAidAudioSource::Start(const CodecConfiguration& codecConfiguration,
+ HearingAidAudioReceiver* audioReceiver) {
+ localAudioReceiver = audioReceiver;
+ VLOG(2) << "Hearing Aid UIPC Open";
+ stats.Reset();
+}
+
+void HearingAidAudioSource::Stop() {
+ if (audio_timer) {
+ alarm_cancel(audio_timer);
+ }
+}
+
+void HearingAidAudioSource::Initialize() {
+ uipc_hearing_aid = UIPC_Init();
+ UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb,
+ HEARING_AID_CTRL_PATH);
+}
+
+void HearingAidAudioSource::CleanUp() {
+ UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_ALL);
+}
+
+void HearingAidAudioSource::DebugDump(int fd) {
+ uint64_t now_us = time_get_os_boottime_us();
+ std::stringstream stream;
+ stream << " Hearing Aid Audio HAL:"
+ << "\n Counts (underflow) : "
+ << stats.media_read_total_underflow_count
+ << "\n Bytes (underflow) : "
+ << stats.media_read_total_underflow_bytes
+ << "\n Last update time ago in ms (underflow) : "
+ << (stats.media_read_last_underflow_us > 0
+ ? (unsigned long long)(now_us -
+ stats.media_read_last_underflow_us) /
+ 1000
+ : 0)
+ << std::endl;
+ dprintf(fd, "%s", stream.str().c_str());
+}
diff --git a/bta/hf_client/bta_hf_client_act.cc b/bta/hf_client/bta_hf_client_act.cc
index b633bd0..3e6c22d 100644
--- a/bta/hf_client/bta_hf_client_act.cc
+++ b/bta/hf_client/bta_hf_client_act.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -108,7 +108,7 @@
/* Let the incoming connection goes through. */
/* Issue collision for now. */
/* We will decide what to do when we find incoming connection later.*/
- bta_hf_client_collision_cback(0, BTA_ID_HS, 0, &client_cb->peer_addr);
+ bta_hf_client_collision_cback(0, BTA_ID_HS, 0, client_cb->peer_addr);
return;
}
@@ -303,7 +303,7 @@
evt.conn.bd_addr = client_cb->peer_addr;
/* if not deregistering reopen server */
- if (bta_hf_client_cb_arr.deregister == false) {
+ if (!bta_hf_client_cb_arr.deregister) {
/* Make sure SCO is shutdown */
bta_hf_client_sco_shutdown(client_cb);
diff --git a/bta/hf_client/bta_hf_client_api.cc b/bta/hf_client/bta_hf_client_api.cc
index d1ec0b7..38c5594 100644
--- a/bta/hf_client/bta_hf_client_api.cc
+++ b/bta/hf_client/bta_hf_client_api.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/hf_client/bta_hf_client_at.cc b/bta/hf_client/bta_hf_client_at.cc
index 5d8493b..5bcc68e 100644
--- a/bta/hf_client/bta_hf_client_at.cc
+++ b/bta/hf_client/bta_hf_client_at.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -170,7 +170,7 @@
uint16_t buf_len) {
APPL_TRACE_DEBUG("%s", __func__);
if ((client_cb->at_cb.current_cmd == BTA_HF_CLIENT_AT_NONE ||
- client_cb->svc_conn == false) &&
+ !client_cb->svc_conn) &&
!alarm_is_scheduled(client_cb->at_cb.hold_timer)) {
uint16_t len;
@@ -257,7 +257,7 @@
client_cb->at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE;
return;
case BTA_HF_CLIENT_AT_CLIP: // last cmd is post slc seq
- if (client_cb->send_at_reply == false) {
+ if (!client_cb->send_at_reply) {
client_cb->send_at_reply = true;
}
break;
@@ -296,7 +296,7 @@
bta_hf_client_cback_sco(client_cb, BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
break;
case BTA_HF_CLIENT_AT_CLIP: // last cmd is post slc seq
- if (client_cb->send_at_reply == false) {
+ if (!client_cb->send_at_reply) {
client_cb->send_at_reply = true;
}
break;
@@ -1587,7 +1587,7 @@
client_cb->at_cb.offset += space_left;
/* find end of last complete command before proceeding */
- while (bta_hf_client_check_at_complete(client_cb) == false) {
+ while (!bta_hf_client_check_at_complete(client_cb)) {
if (client_cb->at_cb.offset == 0) {
APPL_TRACE_ERROR("HFPClient: AT parser buffer overrun, disconnecting");
@@ -1620,7 +1620,7 @@
client_cb->at_cb.offset += len;
/* If last event is complete, parsing can be started */
- if (bta_hf_client_check_at_complete(client_cb) == true) {
+ if (bta_hf_client_check_at_complete(client_cb)) {
bta_hf_client_at_parse_start(client_cb);
bta_hf_client_at_clear_buf(client_cb);
}
@@ -1886,7 +1886,7 @@
APPL_TRACE_DEBUG("%s", __func__);
- if (query == true) {
+ if (query) {
at_len = snprintf(buf, sizeof(buf), "AT+BTRH?\r");
} else {
at_len = snprintf(buf, sizeof(buf), "AT+BTRH=%u\r", val);
diff --git a/bta/hf_client/bta_hf_client_at.h b/bta/hf_client/bta_hf_client_at.h
index 7b52336..1328175 100644
--- a/bta/hf_client/bta_hf_client_at.h
+++ b/bta/hf_client/bta_hf_client_at.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/hf_client/bta_hf_client_int.h b/bta/hf_client/bta_hf_client_int.h
index 9ff7fa1..15ceec2 100644
--- a/bta/hf_client/bta_hf_client_int.h
+++ b/bta/hf_client/bta_hf_client_int.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -218,7 +218,7 @@
extern void bta_hf_client_app_callback(uint16_t event, tBTA_HF_CLIENT* data);
extern void bta_hf_client_collision_cback(tBTA_SYS_CONN_STATUS status,
uint8_t id, uint8_t app_id,
- const RawAddress* peer_addr);
+ const RawAddress& peer_addr);
extern void bta_hf_client_resume_open(tBTA_HF_CLIENT_CB* client_cb);
extern tBTA_STATUS bta_hf_client_api_enable(tBTA_HF_CLIENT_CBACK* p_cback,
tBTA_SEC sec_mask,
diff --git a/bta/hf_client/bta_hf_client_main.cc b/bta/hf_client/bta_hf_client_main.cc
index e52994c..4f717ae 100644
--- a/bta/hf_client/bta_hf_client_main.cc
+++ b/bta/hf_client/bta_hf_client_main.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2016 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -363,8 +363,8 @@
******************************************************************************/
void bta_hf_client_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status,
uint8_t id, UNUSED_ATTR uint8_t app_id,
- const RawAddress* peer_addr) {
- tBTA_HF_CLIENT_CB* client_cb = bta_hf_client_find_cb_by_bda(*peer_addr);
+ const RawAddress& peer_addr) {
+ tBTA_HF_CLIENT_CB* client_cb = bta_hf_client_find_cb_by_bda(peer_addr);
if (client_cb != NULL && client_cb->state == BTA_HF_CLIENT_OPENING_ST) {
if (id == BTA_ID_SYS) /* ACL collision */
{
@@ -381,7 +381,7 @@
/* Cancel SDP if it had been started. */
if (client_cb->p_disc_db) {
(void)SDP_CancelServiceSearch(client_cb->p_disc_db);
- bta_hf_client_free_db(NULL);
+ osi_free_and_reset((void**)&client_cb->p_disc_db);
}
/* reopen registered server */
diff --git a/bta/hf_client/bta_hf_client_rfc.cc b/bta/hf_client/bta_hf_client_rfc.cc
index 3e2aa59..e261c16 100644
--- a/bta/hf_client/bta_hf_client_rfc.cc
+++ b/bta/hf_client/bta_hf_client_rfc.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -284,7 +284,7 @@
/* Cancel SDP if it had been started. */
if (client_cb->p_disc_db) {
(void)SDP_CancelServiceSearch(client_cb->p_disc_db);
- bta_hf_client_free_db(NULL);
+ osi_free_and_reset((void**)&client_cb->p_disc_db);
}
}
}
diff --git a/bta/hf_client/bta_hf_client_sco.cc b/bta/hf_client/bta_hf_client_sco.cc
index 6181ba1..e03de4f 100644
--- a/bta/hf_client/bta_hf_client_sco.cc
+++ b/bta/hf_client/bta_hf_client_sco.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,7 +87,7 @@
evt.bd_addr = client_cb->peer_addr;
/* call app cback */
- bta_hf_client_app_callback(event, (tBTA_HF_CLIENT*)&evt);
+ bta_hf_client_app_callback(event, &evt);
}
/*******************************************************************************
@@ -233,7 +233,7 @@
return;
}
- enh_esco_params_t params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T1);
+ enh_esco_params_t params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
/* if initiating set current scb and peer bd addr */
if (is_orig) {
@@ -602,7 +602,7 @@
/* call app callback */
bta_hf_client_cback_sco(client_cb, BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
- if (client_cb->sco_close_rfc == true) {
+ if (client_cb->sco_close_rfc) {
client_cb->sco_close_rfc = false;
bta_hf_client_rfc_do_close(p_data);
}
diff --git a/bta/hf_client/bta_hf_client_sdp.cc b/bta/hf_client/bta_hf_client_sdp.cc
index 475ce16..d68adcc 100644
--- a/bta/hf_client/bta_hf_client_sdp.cc
+++ b/bta/hf_client/bta_hf_client_sdp.cc
@@ -1,21 +1,21 @@
/******************************************************************************
-*
-* Copyright (c) 2014 The Android Open Source Project
-* Copyright (C) 2003-2012 Broadcom Corporation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at:
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************************/
+ *
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
/******************************************************************************
*
@@ -25,6 +25,7 @@
******************************************************************************/
#include <string.h>
+#include <base/logging.h>
#include "bt_utils.h"
#include "bta_api.h"
@@ -33,6 +34,8 @@
#include "bta_sys.h"
#include "osi/include/osi.h"
+using bluetooth::Uuid;
+
/* Number of protocol elements in protocol element list. */
#define BTA_HF_CLIENT_NUM_PROTO_ELEMS 2
@@ -289,7 +292,7 @@
*
******************************************************************************/
void bta_hf_client_do_disc(tBTA_HF_CLIENT_CB* client_cb) {
- tSDP_UUID uuid_list[2];
+ Uuid uuid_list[1];
uint16_t num_uuid = 1;
uint16_t attr_list[4];
uint8_t num_attr;
@@ -302,7 +305,7 @@
attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
num_attr = 4;
- uuid_list[0].uu.uuid16 = UUID_SERVCLASS_AG_HANDSFREE;
+ uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
}
/* acceptor; get features */
else {
@@ -310,15 +313,13 @@
attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
num_attr = 3;
- uuid_list[0].uu.uuid16 = UUID_SERVCLASS_AG_HANDSFREE;
+ uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
}
/* allocate buffer for sdp database */
client_cb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
/* set up service discovery database; attr happens to be attr_list len */
- uuid_list[0].len = LEN_UUID_16;
- uuid_list[1].len = LEN_UUID_16;
db_inited = SDP_InitDiscoveryDb(client_cb->p_disc_db, BT_DEFAULT_BUFFER_SIZE,
num_uuid, uuid_list, num_attr, attr_list);
@@ -331,7 +332,7 @@
if (!db_inited) {
/*free discover db */
- bta_hf_client_free_db(NULL);
+ osi_free_and_reset((void**)&client_cb->p_disc_db);
/* sent failed event */
tBTA_HF_CLIENT_DATA msg;
msg.hdr.layer_specific = client_cb->handle;
@@ -350,6 +351,7 @@
*
******************************************************************************/
void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA* p_data) {
+ CHECK(p_data != NULL);
tBTA_HF_CLIENT_CB* client_cb =
bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
if (client_cb == NULL) {
diff --git a/bta/hh/bta_hh_act.cc b/bta/hh/bta_hh_act.cc
index 4b11a09..4d85437 100644
--- a/bta/hh/bta_hh_act.cc
+++ b/bta/hh/bta_hh_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -99,8 +99,12 @@
bta_hh_le_enable();
} else
#endif
+ {
/* signal BTA call back event */
- (*bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH*)&status);
+ tBTA_HH bta_hh;
+ bta_hh.status = status;
+ (*bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, &bta_hh);
+ }
}
/*******************************************************************************
*
@@ -224,7 +228,9 @@
osi_free_and_reset((void**)&bta_hh_cb.p_disc_db);
/* send SDP_CMPL_EVT into state machine */
- bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
+ tBTA_HH_DATA bta_hh_data;
+ bta_hh_data.status = status;
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
return;
}
@@ -282,7 +288,9 @@
if (status != BTA_HH_OK) {
osi_free_and_reset((void**)&bta_hh_cb.p_disc_db);
/* send SDP_CMPL_EVT into state machine */
- bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
+ tBTA_HH_DATA bta_hh_data;
+ bta_hh_data.status = status;
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
}
return;
}
@@ -332,7 +340,9 @@
} else
status = BTA_HH_ERR_NO_RES;
}
- bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
+ tBTA_HH_DATA bta_hh_data;
+ bta_hh_data.status = status;
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
return;
}
@@ -366,8 +376,11 @@
return;
}
- if (status != BTA_HH_OK)
- bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
+ if (status != BTA_HH_OK) {
+ tBTA_HH_DATA bta_hh_data;
+ bta_hh_data.status = status;
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
+ }
return;
}
@@ -486,7 +499,11 @@
status = HID_HostCloseDev(disc_dat.handle);
- if (status) (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH*)&disc_dat);
+ if (status) {
+ tBTA_HH bta_hh;
+ bta_hh.dev_status = disc_dat;
+ (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, &bta_hh);
+ }
}
return;
@@ -622,31 +639,28 @@
*
******************************************************************************/
void bta_hh_handsk_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
- tBTA_HH_CBDATA cback_data;
- tBTA_HH_HSDATA hs_data;
- tBTA_HH_CONN conn;
-
#if (BTA_HH_DEBUG == TRUE)
APPL_TRACE_DEBUG("HANDSHAKE received for: event = %s data= %d",
bta_hh_get_w4_event(p_cb->w4_evt), p_data->hid_cback.data);
#endif
- memset(&hs_data, 0, sizeof(tBTA_HH_HSDATA));
- memset(&cback_data, 0, sizeof(tBTA_HH_CBDATA));
+ tBTA_HH bta_hh;
+ memset(&bta_hh, 0, sizeof(tBTA_HH));
switch (p_cb->w4_evt) {
/* GET_ transsaction, handshake indicate unsupported request */
case BTA_HH_GET_PROTO_EVT:
- hs_data.rsp_data.proto_mode = BTA_HH_PROTO_UNKNOWN;
+ bta_hh.hs_data.rsp_data.proto_mode = BTA_HH_PROTO_UNKNOWN;
/* fall through */
case BTA_HH_GET_RPT_EVT:
case BTA_HH_GET_IDLE_EVT:
- hs_data.handle = p_cb->hid_handle;
+ bta_hh.hs_data.handle = p_cb->hid_handle;
/* if handshake gives an OK code for these transaction, fill in UNSUPT */
- hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
- if (hs_data.status == BTA_HH_OK) hs_data.status = BTA_HH_HS_TRANS_NOT_SPT;
+ bta_hh.hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
+ if (bta_hh.hs_data.status == BTA_HH_OK)
+ bta_hh.hs_data.status = BTA_HH_HS_TRANS_NOT_SPT;
- (*bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH*)&hs_data);
+ (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh);
p_cb->w4_evt = 0;
break;
@@ -654,18 +668,20 @@
case BTA_HH_SET_RPT_EVT:
case BTA_HH_SET_PROTO_EVT:
case BTA_HH_SET_IDLE_EVT:
- cback_data.handle = p_cb->hid_handle;
- cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
- (*bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH*)&cback_data);
+ bta_hh.dev_status.handle = p_cb->hid_handle;
+ bta_hh.dev_status.status =
+ bta_hh_get_trans_status(p_data->hid_cback.data);
+ (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh);
p_cb->w4_evt = 0;
break;
/* SET_PROTOCOL when open connection */
case BTA_HH_OPEN_EVT:
- conn.status = p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK;
- conn.handle = p_cb->hid_handle;
- conn.bda = p_cb->addr;
- (*bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH*)&conn);
+ bta_hh.conn.status =
+ p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK;
+ bta_hh.conn.handle = p_cb->hid_handle;
+ bta_hh.conn.bda = p_cb->addr;
+ (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh);
#if (BTA_HH_DEBUG == TRUE)
bta_hh_trace_dev_db();
#endif
@@ -916,7 +932,8 @@
#if (BTA_HH_LE_INCLUDED == TRUE)
if (bta_hh_is_le_device(p_cb, p_data->api_conn.bd_addr)) {
dev_info.handle = bta_hh_le_add_device(p_cb, p_dev_info);
- dev_info.status = BTA_HH_OK;
+ if (dev_info.handle != BTA_HH_INVALID_HANDLE)
+ dev_info.status = BTA_HH_OK;
} else
#endif
diff --git a/bta/hh/bta_hh_api.cc b/bta/hh/bta_hh_api.cc
index 164633c..e9b3f64 100644
--- a/bta/hh/bta_hh_api.cc
+++ b/bta/hh/bta_hh_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/hh/bta_hh_cfg.cc b/bta/hh/bta_hh_cfg.cc
index 9479e8b..debe3e5 100644
--- a/bta/hh/bta_hh_cfg.cc
+++ b/bta/hh/bta_hh_cfg.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,4 +52,4 @@
BTA_HH_DISC_BUF_SIZE /* HH SDP discovery database size */
};
-tBTA_HH_CFG* p_bta_hh_cfg = (tBTA_HH_CFG*)&bta_hh_cfg;
+const tBTA_HH_CFG* p_bta_hh_cfg = &bta_hh_cfg;
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
index 128a078..74bcffc 100644
--- a/bta/hh/bta_hh_int.h
+++ b/bta/hh/bta_hh_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -284,9 +284,9 @@
uint8_t cb_index[BTA_HH_MAX_KNOWN]; /* maintain a CB index
map to dev handle */
#if (BTA_HH_LE_INCLUDED == TRUE)
- uint8_t le_cb_index[BTA_HH_MAX_DEVICE]; /* maintain a CB index map to LE dev
+ uint8_t le_cb_index[BTA_HH_LE_MAX_KNOWN]; /* maintain a CB index map to LE dev
handle */
- tBTA_GATTC_IF gatt_if;
+ tGATT_IF gatt_if;
#endif
tBTA_HH_CBACK* p_cback; /* Application callbacks */
tSDP_DISCOVERY_DB* p_disc_db;
@@ -354,7 +354,7 @@
/* functions for LE HID */
extern void bta_hh_le_enable(void);
-extern bool bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if);
+extern bool bta_hh_le_is_hh_gatt_if(tGATT_IF client_if);
extern void bta_hh_le_deregister(void);
extern bool bta_hh_is_le_device(tBTA_HH_DEV_CB* p_cb,
const RawAddress& remote_bda);
diff --git a/bta/hh/bta_hh_le.cc b/bta/hh/bta_hh_le.cc
index b4827a2..adeb957 100644
--- a/bta/hh/bta_hh_le.cc
+++ b/bta/hh/bta_hh_le.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,12 +28,9 @@
#include <base/bind.h>
#include <base/callback.h>
-#include <list>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
#include "bta_gatt_api.h"
+#include "bta_gatt_queue.h"
#include "bta_hh_co.h"
#include "btm_api.h"
#include "btm_ble_api.h"
@@ -44,6 +41,7 @@
#include "stack/include/l2c_api.h"
#include "utl.h"
+using bluetooth::Uuid;
using std::vector;
#ifndef BTA_HH_LE_RECONN
@@ -73,161 +71,6 @@
// tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
// uint8_t num_rpt);
-#define GATT_READ_CHAR 0
-#define GATT_READ_DESC 1
-#define GATT_WRITE_CHAR 2
-#define GATT_WRITE_DESC 3
-
-/* Holds pending GATT operations */
-struct gatt_operation {
- uint8_t type;
- uint16_t handle;
- GATT_READ_OP_CB read_cb;
- void* read_cb_data;
- GATT_WRITE_OP_CB write_cb;
- void* write_cb_data;
-
- /* write-specific fields */
- tBTA_GATTC_WRITE_TYPE write_type;
- vector<uint8_t> value;
-};
-
-// maps connection id to operations waiting for execution
-static std::unordered_map<uint16_t, std::list<gatt_operation>> gatt_op_queue;
-// contain connection ids that currently execute operations
-static std::unordered_set<uint16_t> gatt_op_queue_executing;
-
-static void mark_as_not_executing(uint16_t conn_id) {
- gatt_op_queue_executing.erase(conn_id);
-}
-
-static void gatt_op_queue_clean(uint16_t conn_id) {
- gatt_op_queue.erase(conn_id);
- gatt_op_queue_executing.erase(conn_id);
-}
-
-static void gatt_execute_next_op(uint16_t conn_id);
-GATT_READ_OP_CB act_read_cb = NULL;
-void* act_read_cb_data = NULL;
-static void gatt_read_op_finished(uint16_t conn_id, tGATT_STATUS status,
- uint16_t handle, uint16_t len, uint8_t* value,
- void* data) {
- GATT_READ_OP_CB tmp_cb = act_read_cb;
- void* tmp_cb_data = act_read_cb_data;
-
- act_read_cb = NULL;
- act_read_cb_data = NULL;
-
- mark_as_not_executing(conn_id);
- gatt_execute_next_op(conn_id);
-
- if (tmp_cb) {
- tmp_cb(conn_id, status, handle, len, value, tmp_cb_data);
- return;
- }
-}
-
-GATT_WRITE_OP_CB act_write_cb = NULL;
-void* act_write_cb_data = NULL;
-static void gatt_write_op_finished(uint16_t conn_id, tGATT_STATUS status,
- uint16_t handle, void* data) {
- GATT_WRITE_OP_CB tmp_cb = act_write_cb;
- void* tmp_cb_data = act_write_cb_data;
- act_write_cb = NULL;
- act_write_cb_data = NULL;
-
- mark_as_not_executing(conn_id);
- gatt_execute_next_op(conn_id);
-
- if (tmp_cb) {
- tmp_cb(conn_id, status, handle, tmp_cb_data);
- return;
- }
-}
-
-static void gatt_execute_next_op(uint16_t conn_id) {
- APPL_TRACE_DEBUG("%s:", __func__, conn_id);
- if (gatt_op_queue.empty()) {
- APPL_TRACE_DEBUG("%s: op queue is empty", __func__);
- return;
- }
-
- auto map_ptr = gatt_op_queue.find(conn_id);
- if (map_ptr == gatt_op_queue.end() || map_ptr->second.empty()) {
- APPL_TRACE_DEBUG("%s: no more operations queued for conn_id %d", __func__,
- conn_id);
- return;
- }
-
- if (gatt_op_queue_executing.count(conn_id)) {
- APPL_TRACE_DEBUG("%s: can't enqueue next op, already executing", __func__);
- return;
- }
-
- gatt_op_queue_executing.insert(conn_id);
-
- std::list<gatt_operation>& gatt_ops = map_ptr->second;
-
- gatt_operation& op = gatt_ops.front();
-
- if (op.type == GATT_READ_CHAR) {
- act_read_cb = op.read_cb;
- act_read_cb_data = op.read_cb_data;
- BTA_GATTC_ReadCharacteristic(conn_id, op.handle, BTA_GATT_AUTH_REQ_NONE,
- gatt_read_op_finished, NULL);
-
- } else if (op.type == GATT_READ_DESC) {
- act_read_cb = op.read_cb;
- act_read_cb_data = op.read_cb_data;
- BTA_GATTC_ReadCharDescr(conn_id, op.handle, BTA_GATT_AUTH_REQ_NONE,
- gatt_read_op_finished, NULL);
-
- } else if (op.type == GATT_WRITE_CHAR) {
- act_write_cb = op.write_cb;
- act_write_cb_data = op.write_cb_data;
- BTA_GATTC_WriteCharValue(conn_id, op.handle, op.write_type,
- std::move(op.value), BTA_GATT_AUTH_REQ_NONE,
- gatt_write_op_finished, NULL);
-
- } else if (op.type == GATT_WRITE_DESC) {
- act_write_cb = op.write_cb;
- act_write_cb_data = op.write_cb_data;
- BTA_GATTC_WriteCharDescr(conn_id, op.handle, std::move(op.value),
- BTA_GATT_AUTH_REQ_NONE, gatt_write_op_finished,
- NULL);
- }
-
- gatt_ops.pop_front();
-}
-
-static void gatt_queue_read_op(uint8_t op_type, uint16_t conn_id,
- uint16_t handle, GATT_READ_OP_CB cb,
- void* cb_data) {
- gatt_operation op;
- op.type = op_type;
- op.handle = handle;
- op.read_cb = cb;
- op.read_cb_data = cb_data;
- gatt_op_queue[conn_id].push_back(op);
- gatt_execute_next_op(conn_id);
-}
-
-static void gatt_queue_write_op(uint8_t op_type, uint16_t conn_id,
- uint16_t handle, vector<uint8_t> value,
- tBTA_GATTC_WRITE_TYPE write_type,
- GATT_WRITE_OP_CB cb, void* cb_data) {
- gatt_operation op;
- op.type = op_type;
- op.handle = handle;
- op.write_type = write_type;
- op.write_cb = cb;
- op.write_cb_data = cb_data;
- op.value = std::move(value);
-
- gatt_op_queue[conn_id].push_back(op);
- gatt_execute_next_op(conn_id);
-}
-
#if (BTA_HH_DEBUG == TRUE)
static const char* bta_hh_le_rpt_name[4] = {"UNKNOWN", "INPUT", "OUTPUT",
"FEATURE"};
@@ -324,22 +167,27 @@
bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
- for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
+ for (xx = 0; xx < ARRAY_SIZE(bta_hh_cb.le_cb_index); xx++)
bta_hh_cb.le_cb_index[xx] = BTA_HH_IDX_INVALID;
BTA_GATTC_AppRegister(bta_hh_gattc_callback,
base::Bind([](uint8_t client_id, uint8_t r_status) {
- tBTA_HH_STATUS status = BTA_HH_ERR;
+ tBTA_HH bta_hh;
+ bta_hh.status = BTA_HH_ERR;
- if (r_status == BTA_GATT_OK) {
+ if (r_status == GATT_SUCCESS) {
bta_hh_cb.gatt_if = client_id;
- status = BTA_HH_OK;
- } else
+ bta_hh.status = BTA_HH_OK;
+ } else {
bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
+ }
- /* signal BTA call back event */
- (*bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT,
- (tBTA_HH*)&status);
+ /* null check is needed in case HID profile is shut
+ * down before BTA_GATTC_AppRegister is done */
+ if (bta_hh_cb.p_cback) {
+ /* signal BTA call back event */
+ (*bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, &bta_hh);
+ }
}));
}
@@ -353,7 +201,7 @@
* Returns whether it is HH GATT IF
*
******************************************************************************/
-bool bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if) {
+bool bta_hh_le_is_hh_gatt_if(tGATT_IF client_if) {
return (bta_hh_cb.gatt_if == client_if);
}
@@ -384,6 +232,28 @@
return p_cb->is_le_device;
}
+/******************************************************************************
+ *
+ * Function bta_hh_le_get_le_cb
+ *
+ * Description Allocate bta_hh_cb.le_cb_index
+ *
+ * Parameters:
+ *
+ ******************************************************************************/
+uint8_t bta_hh_le_get_le_dev_hdl(uint8_t cb_index) {
+ uint8_t i;
+ for (i = 0; i < ARRAY_SIZE(bta_hh_cb.le_cb_index); i++) {
+ if (bta_hh_cb.le_cb_index[i] == cb_index) return BTA_HH_GET_LE_DEV_HDL(i);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bta_hh_cb.le_cb_index); i++) {
+ if (bta_hh_cb.le_cb_index[i] == BTA_HH_IDX_INVALID)
+ return BTA_HH_GET_LE_DEV_HDL(i);
+ }
+ return BTA_HH_IDX_INVALID;
+}
+
/*******************************************************************************
*
* Function bta_hh_le_open_conn
@@ -394,14 +264,20 @@
*
******************************************************************************/
void bta_hh_le_open_conn(tBTA_HH_DEV_CB* p_cb, const RawAddress& remote_bda) {
+ tBTA_HH_STATUS status = BTA_HH_ERR_NO_RES;
+
/* update cb_index[] map */
- p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
+ p_cb->hid_handle = bta_hh_le_get_le_dev_hdl(p_cb->index);
+ if (p_cb->hid_handle == BTA_HH_IDX_INVALID) {
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
+ return;
+ }
+
p_cb->addr = remote_bda;
bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
p_cb->in_use = true;
- BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, true, BTA_GATT_TRANSPORT_LE,
- false);
+ BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, true, GATT_TRANSPORT_LE, false);
}
/*******************************************************************************
@@ -581,7 +457,7 @@
return NULL;
}
-static tBTA_GATTC_DESCRIPTOR* find_descriptor_by_short_uuid(
+static const tBTA_GATTC_DESCRIPTOR* find_descriptor_by_short_uuid(
uint16_t conn_id, uint16_t char_handle, uint16_t short_uuid) {
const tBTA_GATTC_CHARACTERISTIC* p_char =
BTA_GATTC_GetCharacteristic(conn_id, char_handle);
@@ -591,14 +467,8 @@
return NULL;
}
- if (!p_char->descriptors || list_is_empty(p_char->descriptors)) return NULL;
-
- for (list_node_t* dn = list_begin(p_char->descriptors);
- dn != list_end(p_char->descriptors); dn = list_next(dn)) {
- tBTA_GATTC_DESCRIPTOR* p_desc = (tBTA_GATTC_DESCRIPTOR*)list_node(dn);
-
- if (p_char->uuid.len == LEN_UUID_16 && p_desc->uuid.uu.uuid16 == short_uuid)
- return p_desc;
+ for (const tBTA_GATTC_DESCRIPTOR& desc : p_char->descriptors) {
+ if (desc.uuid == Uuid::From16Bit(short_uuid)) return &desc;
}
return NULL;
@@ -620,8 +490,7 @@
find_descriptor_by_short_uuid(p_cb->conn_id, char_handle, short_uuid);
if (!p_desc) return BTA_HH_ERR;
- gatt_queue_read_op(GATT_READ_DESC, p_cb->conn_id, p_desc->handle, cb,
- cb_data);
+ BtaGattQueue::ReadDescriptor(p_cb->conn_id, p_desc->handle, cb, cb_data);
return BTA_HH_OK;
}
@@ -637,7 +506,7 @@
void bta_hh_le_save_report_ref(tBTA_HH_DEV_CB* p_dev_cb, tBTA_HH_LE_RPT* p_rpt,
tGATT_STATUS status, uint8_t* value,
uint16_t len) {
- if (status == BTA_GATT_INSUF_AUTHENTICATION) {
+ if (status == GATT_INSUF_AUTHENTICATION) {
/* close connection right away */
p_dev_cb->status = BTA_HH_ERR_AUTH_FAILED;
/* close the connection and report service discovery complete with error */
@@ -646,7 +515,7 @@
}
/* if the length of the descriptor value is right, parse it */
- if (status == BTA_GATT_OK && len == 2) {
+ if (status == GATT_SUCCESS && len == 2) {
uint8_t* pp = value;
STREAM_TO_UINT8(p_rpt->rpt_id, pp);
@@ -702,7 +571,7 @@
/* boot mode, deregister report input notification */
else if (proto_mode == BTA_HH_PROTO_BOOT_MODE) {
if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
- p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION) {
+ p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
APPL_TRACE_DEBUG("%s ---> Deregister Report ID: %d", __func__,
p_rpt->rpt_id);
BTA_GATTC_DeregisterForNotifications(
@@ -719,14 +588,13 @@
} else if (proto_mode == BTA_HH_PROTO_RPT_MODE) {
if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
- p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION) {
+ p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
APPL_TRACE_DEBUG("%s ---> Deregister Boot Report ID: %d", __func__,
p_rpt->rpt_id);
BTA_GATTC_DeregisterForNotifications(
bta_hh_cb.gatt_if, p_dev_cb->addr, p_rpt->char_inst_id);
} else if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
- p_rpt->client_cfg_value ==
- BTA_GATT_CLT_CONFIG_NOTIFICATION) {
+ p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
APPL_TRACE_DEBUG("%s <--- Register Report ID: %d", __func__,
p_rpt->rpt_id);
BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
@@ -752,14 +620,14 @@
for (uint8_t i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++) {
if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) {
if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
- p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION) {
+ p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
APPL_TRACE_DEBUG("%s ---> Deregister Report ID: %d", __func__,
p_rpt->rpt_id);
BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
p_rpt->char_inst_id);
} else if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
- p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION) {
+ p_rpt->client_cfg_value == GATT_CLT_CONFIG_NOTIFICATION) {
APPL_TRACE_DEBUG("%s ---> Deregister Boot Report ID: %d", __func__,
p_rpt->rpt_id);
BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
@@ -803,7 +671,7 @@
bool bta_hh_le_write_ccc(tBTA_HH_DEV_CB* p_cb, uint8_t char_handle,
uint16_t clt_cfg_value, GATT_WRITE_OP_CB cb,
void* cb_data) {
- tBTA_GATTC_DESCRIPTOR* p_desc = find_descriptor_by_short_uuid(
+ const tBTA_GATTC_DESCRIPTOR* p_desc = find_descriptor_by_short_uuid(
p_cb->conn_id, char_handle, GATT_UUID_CHAR_CLIENT_CONFIG);
if (!p_desc) return false;
@@ -811,8 +679,8 @@
uint8_t* ptr = value.data();
UINT16_TO_STREAM(ptr, clt_cfg_value);
- gatt_queue_write_op(GATT_WRITE_DESC, p_cb->conn_id, p_desc->handle,
- std::move(value), BTA_GATTC_TYPE_WRITE, cb, cb_data);
+ BtaGattQueue::WriteDescriptor(p_cb->conn_id, p_desc->handle, std::move(value),
+ GATT_WRITE, cb, cb_data);
return true;
}
@@ -823,12 +691,11 @@
uint8_t srvc_inst_id, hid_inst_id;
tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
- const tBTA_GATTC_DESCRIPTOR* p_desc =
- BTA_GATTC_GetDescriptor(conn_id, handle);
+ const tBTA_GATTC_CHARACTERISTIC* characteristic =
+ BTA_GATTC_GetOwningCharacteristic(conn_id, handle);
+ uint16_t char_uuid = characteristic->uuid.As16Bit();
- uint16_t char_uuid = p_desc->characteristic->uuid.uu.uuid16;
-
- srvc_inst_id = p_desc->characteristic->service->handle;
+ srvc_inst_id = BTA_GATTC_GetOwningService(conn_id, handle)->handle;
hid_inst_id = srvc_inst_id;
switch (char_uuid) {
case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
@@ -838,9 +705,9 @@
case GATT_UUID_HID_BT_KB_INPUT:
case GATT_UUID_HID_BT_MOUSE_INPUT:
case GATT_UUID_HID_REPORT:
- if (status == BTA_GATT_OK)
+ if (status == GATT_SUCCESS)
p_dev_cb->hid_srvc.report[p_dev_cb->clt_cfg_idx].client_cfg_value =
- BTA_GATT_CLT_CONFIG_NOTIFICATION;
+ GATT_CLT_CONFIG_NOTIFICATION;
p_dev_cb->clt_cfg_idx++;
bta_hh_le_write_rpt_clt_cfg(p_dev_cb);
break;
@@ -866,7 +733,7 @@
/* enable notification for all input report, regardless mode */
if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) {
if (bta_hh_le_write_ccc(p_cb, p_rpt->char_inst_id,
- BTA_GATT_CLT_CONFIG_NOTIFICATION,
+ GATT_CLT_CONFIG_NOTIFICATION,
write_rpt_ctl_cfg_cb, p_cb)) {
p_cb->clt_cfg_idx = i;
return true;
@@ -897,15 +764,15 @@
tBTA_HH_CBDATA cback_data;
cback_data.handle = p_dev_cb->hid_handle;
- cback_data.status = (status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR;
+ cback_data.status = (status == GATT_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR;
- if (status == BTA_GATT_OK)
+ if (status == GATT_SUCCESS)
bta_hh_le_register_input_notif(p_dev_cb, p_dev_cb->mode, false);
p_dev_cb->w4_evt = 0;
(*bta_hh_cb.p_cback)(cb_evt, (tBTA_HH*)&cback_data);
} else if (p_dev_cb->state == BTA_HH_W4_CONN_ST) {
- p_dev_cb->status = (status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
+ p_dev_cb->status = (status == GATT_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) == 0)
bta_hh_le_open_cmpl(p_dev_cb);
@@ -950,9 +817,9 @@
mode = (mode == BTA_HH_PROTO_BOOT_MODE) ? BTA_HH_LE_PROTO_BOOT_MODE
: BTA_HH_LE_PROTO_REPORT_MODE;
- gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id,
- p_cb->hid_srvc.proto_mode_handle, {mode},
- BTA_GATTC_TYPE_WRITE_NO_RSP, write_proto_mode_cb, p_cb);
+ BtaGattQueue::WriteCharacteristic(
+ p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle, {mode},
+ GATT_WRITE_NO_RSP, write_proto_mode_cb, p_cb);
return true;
}
@@ -976,7 +843,7 @@
hs_data.handle = p_dev_cb->hid_handle;
hs_data.rsp_data.proto_mode = p_dev_cb->mode;
- if (status == BTA_GATT_OK && len) {
+ if (status == GATT_SUCCESS && len) {
hs_data.status = BTA_HH_OK;
/* match up BTE/BTA report/boot mode def*/
hs_data.rsp_data.proto_mode = *(value);
@@ -1013,9 +880,9 @@
p_cb->w4_evt = BTA_HH_GET_PROTO_EVT;
if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.proto_mode_handle != 0) {
- gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id,
- p_cb->hid_srvc.proto_mode_handle, get_protocol_mode_cb,
- p_cb);
+ BtaGattQueue::ReadCharacteristic(p_cb->conn_id,
+ p_cb->hid_srvc.proto_mode_handle,
+ get_protocol_mode_cb, p_cb);
return;
}
@@ -1071,8 +938,6 @@
*
******************************************************************************/
void bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB* p_cb) {
- tBT_UUID pri_srvc;
-
bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id);
p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS | BTA_HH_LE_DISC_DIS);
@@ -1085,8 +950,7 @@
/* in parallel */
/* start primary service discovery for HID service */
- pri_srvc.len = LEN_UUID_16;
- pri_srvc.uu.uuid16 = UUID_SERVCLASS_LE_HID;
+ Uuid pri_srvc = Uuid::From16Bit(UUID_SERVCLASS_LE_HID);
BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
return;
}
@@ -1101,7 +965,7 @@
*
******************************************************************************/
void bta_hh_le_encrypt_cback(const RawAddress* bd_addr,
- UNUSED_ATTR tBTA_GATT_TRANSPORT transport,
+ UNUSED_ATTR tGATT_TRANSPORT transport,
UNUSED_ATTR void* p_ref_data, tBTM_STATUS result) {
uint8_t idx = bta_hh_find_cb(*bd_addr);
tBTA_HH_DEV_CB* p_dev_cb;
@@ -1150,7 +1014,7 @@
if (p_cb->app_id != 0 && p_cb->hid_srvc.in_use) {
APPL_TRACE_DEBUG("%s: discovery has been done for HID service", __func__);
/* configure protocol mode */
- if (bta_hh_le_set_protocol_mode(p_cb, p_cb->mode) == false) {
+ if (!bta_hh_le_set_protocol_mode(p_cb, p_cb->mode)) {
bta_hh_le_open_cmpl(p_cb);
}
}
@@ -1177,7 +1041,7 @@
*
******************************************************************************/
void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_buf) {
- if (p_cb == NULL || p_cb->security_pending == false || p_buf == NULL ||
+ if (p_cb == NULL || !p_cb->security_pending || p_buf == NULL ||
p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if) {
return;
}
@@ -1234,6 +1098,7 @@
/* if link has been encrypted */
if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) {
+ p_cb->status = BTA_HH_OK;
bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
}
/* if bonded and link not encrypted */
@@ -1269,7 +1134,6 @@
void bta_hh_gatt_open(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_buf) {
tBTA_GATTC_OPEN* p_data = &p_buf->le_open;
uint8_t* p2;
- tHID_STATUS status = BTA_HH_ERR;
/* if received invalid callback data , ignore it */
if (p_cb == NULL || p_data == NULL) return;
@@ -1281,15 +1145,20 @@
((p2[0]) << 24) + ((p2[1]) << 16) + ((p2[2]) << 8) + (p2[3]),
((p2[4]) << 8) + p2[5], p_data->status);
- if (p_data->status == BTA_GATT_OK) {
+ if (p_data->status == GATT_SUCCESS) {
+ p_cb->hid_handle = bta_hh_le_get_le_dev_hdl(p_cb->index);
+ if (p_cb->hid_handle == BTA_HH_IDX_INVALID) {
+ p_cb->conn_id = p_data->conn_id;
+ bta_hh_le_api_disc_act(p_cb);
+ return;
+ }
p_cb->is_le_device = true;
p_cb->in_use = true;
p_cb->conn_id = p_data->conn_id;
- p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
- gatt_op_queue_clean(p_cb->conn_id);
+ BtaGattQueue::Clean(p_cb->conn_id);
#if (BTA_HH_DEBUG == TRUE)
APPL_TRACE_DEBUG("hid_handle = %2x conn_id = %04x cb_index = %d",
@@ -1298,9 +1167,11 @@
bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL);
- } else /* open failure */
- {
- bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
+ } else {
+ /* open failure */
+ tBTA_HH_DATA bta_hh_data;
+ bta_hh_data.status = BTA_HH_ERR;
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
}
}
@@ -1326,7 +1197,7 @@
p_buf->conn_id = p_data->conn_id;
p_buf->reason = p_data->reason;
- p_dev_cb->conn_id = BTA_GATT_INVALID_CONN_ID;
+ p_dev_cb->conn_id = GATT_INVALID_CONN_ID;
p_dev_cb->security_pending = false;
bta_sys_sendmsg(p_buf);
}
@@ -1363,7 +1234,7 @@
static void read_hid_info_cb(uint16_t conn_id, tGATT_STATUS status,
uint16_t handle, uint16_t len, uint8_t* value,
void* data) {
- if (status != BTA_GATT_OK) {
+ if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s: error: %d", __func__, status);
return;
}
@@ -1384,7 +1255,7 @@
static void read_hid_report_map_cb(uint16_t conn_id, tGATT_STATUS status,
uint16_t handle, uint16_t len,
uint8_t* value, void* data) {
- if (status != BTA_GATT_OK) {
+ if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s: error reading characteristic: %d", __func__, status);
return;
}
@@ -1407,14 +1278,14 @@
static void read_ext_rpt_ref_desc_cb(uint16_t conn_id, tGATT_STATUS status,
uint16_t handle, uint16_t len,
uint8_t* value, void* data) {
- if (status != BTA_GATT_OK) {
+ if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s: error: %d", __func__, status);
return;
}
/* if the length of the descriptor value is right, parse it assume it's a 16
* bits UUID */
- if (len != LEN_UUID_16) {
+ if (len != Uuid::kNumBytes16) {
APPL_TRACE_ERROR("%s: we support only 16bit UUID: %d", __func__, len);
return;
}
@@ -1433,7 +1304,7 @@
static void read_report_ref_desc_cb(uint16_t conn_id, tGATT_STATUS status,
uint16_t handle, uint16_t len,
uint8_t* value, void* data) {
- if (status != BTA_GATT_OK) {
+ if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s: error: %d", __func__, status);
return;
}
@@ -1447,17 +1318,22 @@
return;
}
+ const tBTA_GATTC_CHARACTERISTIC* characteristic =
+ BTA_GATTC_GetOwningCharacteristic(conn_id, handle);
+ const tBTA_GATTC_SERVICE* service =
+ BTA_GATTC_GetOwningService(conn_id, characteristic->value_handle);
+
tBTA_HH_LE_RPT* p_rpt;
- p_rpt = bta_hh_le_find_report_entry(
- p_dev_cb, p_desc->characteristic->service->handle, GATT_UUID_HID_REPORT,
- p_desc->characteristic->handle);
+ p_rpt = bta_hh_le_find_report_entry(p_dev_cb, service->handle,
+ GATT_UUID_HID_REPORT,
+ characteristic->value_handle);
if (p_rpt) bta_hh_le_save_report_ref(p_dev_cb, p_rpt, status, value, len);
}
void read_pref_conn_params_cb(uint16_t conn_id, tGATT_STATUS status,
uint16_t handle, uint16_t len, uint8_t* value,
void* data) {
- if (status != BTA_GATT_OK) {
+ if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s: error: %d", __func__, status);
return;
}
@@ -1470,30 +1346,45 @@
// TODO(jpawlowski): this should be done by GAP profile, remove when GAP is
// fixed.
uint8_t* pp = value;
- uint16_t min, max, latency, tout;
- STREAM_TO_UINT16(min, pp);
- STREAM_TO_UINT16(max, pp);
+ uint16_t min_interval, max_interval, latency, timeout;
+ STREAM_TO_UINT16(min_interval, pp);
+ STREAM_TO_UINT16(max_interval, pp);
STREAM_TO_UINT16(latency, pp);
- STREAM_TO_UINT16(tout, pp);
+ STREAM_TO_UINT16(timeout, pp);
// Make sure both min, and max are bigger than 11.25ms, lower values can
- // introduce
- // audio issues if A2DP is also active.
- if (min < BTM_BLE_CONN_INT_MIN_LIMIT) min = BTM_BLE_CONN_INT_MIN_LIMIT;
- if (max < BTM_BLE_CONN_INT_MIN_LIMIT) max = BTM_BLE_CONN_INT_MIN_LIMIT;
+ // introduce audio issues if A2DP is also active.
+ L2CA_AdjustConnectionIntervals(&min_interval, &max_interval,
+ BTM_BLE_CONN_INT_MIN_LIMIT);
// If the device has no preferred connection timeout, use the default.
- if (tout == BTM_BLE_CONN_PARAM_UNDEF) tout = BTM_BLE_CONN_TIMEOUT_DEF;
+ if (timeout == BTM_BLE_CONN_PARAM_UNDEF) timeout = BTM_BLE_CONN_TIMEOUT_DEF;
+
+ if (min_interval < BTM_BLE_CONN_INT_MIN ||
+ min_interval > BTM_BLE_CONN_INT_MAX ||
+ max_interval < BTM_BLE_CONN_INT_MIN ||
+ max_interval > BTM_BLE_CONN_INT_MAX ||
+ latency > BTM_BLE_CONN_LATENCY_MAX ||
+ timeout < BTM_BLE_CONN_SUP_TOUT_MIN ||
+ timeout > BTM_BLE_CONN_SUP_TOUT_MAX || max_interval < min_interval) {
+ APPL_TRACE_ERROR(
+ "%s: Invalid connection parameters. min=%d, max=%d, latency=%d, "
+ "timeout=%d",
+ __func__, min_interval, max_interval, latency, timeout);
+ return;
+ }
tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
if (interop_match_addr(INTEROP_HID_PREF_CONN_SUP_TIMEOUT_3S,
- (RawAddress*)&p_dev_cb->addr) == true) {
- if (tout < 300) tout = 300;
+ (RawAddress*)&p_dev_cb->addr)) {
+ if (timeout < 300) timeout = 300;
}
- BTM_BleSetPrefConnParams(p_dev_cb->addr, min, max, latency, tout);
- L2CA_UpdateBleConnParams(p_dev_cb->addr, min, max, latency, tout);
+ BTM_BleSetPrefConnParams(p_dev_cb->addr, min_interval, max_interval, latency,
+ timeout);
+ L2CA_UpdateBleConnParams(p_dev_cb->addr, min_interval, max_interval, latency,
+ timeout);
}
/*******************************************************************************
@@ -1507,35 +1398,31 @@
*
******************************************************************************/
static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB* p_dev_cb,
- tBTA_GATTC_SERVICE* service) {
+ const tBTA_GATTC_SERVICE* service) {
tBTA_HH_LE_RPT* p_rpt;
- for (list_node_t* cn = list_begin(service->characteristics);
- cn != list_end(service->characteristics); cn = list_next(cn)) {
- tBTA_GATTC_CHARACTERISTIC* p_char =
- (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
+ for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+ if (!charac.uuid.Is16Bit()) continue;
- if (p_char->uuid.len != LEN_UUID_16) continue;
+ uint16_t uuid16 = charac.uuid.As16Bit();
+ LOG_DEBUG(LOG_TAG, "%s: %s %s", __func__, bta_hh_uuid_to_str(uuid16),
+ charac.uuid.ToString().c_str());
- LOG_DEBUG(LOG_TAG, "%s: %s 0x%04d", __func__,
- bta_hh_uuid_to_str(p_char->uuid.uu.uuid16),
- p_char->uuid.uu.uuid16);
-
- switch (p_char->uuid.uu.uuid16) {
+ switch (uuid16) {
case GATT_UUID_HID_CONTROL_POINT:
- p_dev_cb->hid_srvc.control_point_handle = p_char->handle;
+ p_dev_cb->hid_srvc.control_point_handle = charac.value_handle;
break;
case GATT_UUID_HID_INFORMATION:
/* only one instance per HID service */
- gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle,
- read_hid_info_cb, p_dev_cb);
+ BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id, charac.value_handle,
+ read_hid_info_cb, p_dev_cb);
break;
case GATT_UUID_HID_REPORT_MAP:
/* only one instance per HID service */
- gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle,
- read_hid_report_map_cb, p_dev_cb);
+ BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id, charac.value_handle,
+ read_hid_report_map_cb, p_dev_cb);
/* descriptor is optional */
- bta_hh_le_read_char_descriptor(p_dev_cb, p_char->handle,
+ bta_hh_le_read_char_descriptor(p_dev_cb, charac.value_handle,
GATT_UUID_EXT_RPT_REF_DESCR,
read_ext_rpt_ref_desc_cb, p_dev_cb);
break;
@@ -1543,7 +1430,7 @@
case GATT_UUID_HID_REPORT:
p_rpt = bta_hh_le_find_alloc_report_entry(
p_dev_cb, p_dev_cb->hid_srvc.srvc_inst_id, GATT_UUID_HID_REPORT,
- p_char->handle);
+ charac.value_handle);
if (p_rpt == NULL) {
APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
break;
@@ -1551,7 +1438,7 @@
if (p_rpt->rpt_type != BTA_HH_RPTT_INPUT) break;
- bta_hh_le_read_char_descriptor(p_dev_cb, p_char->handle,
+ bta_hh_le_read_char_descriptor(p_dev_cb, charac.value_handle,
GATT_UUID_RPT_REF_DESCR,
read_report_ref_desc_cb, p_dev_cb);
break;
@@ -1560,29 +1447,22 @@
case GATT_UUID_HID_BT_KB_OUTPUT:
case GATT_UUID_HID_BT_MOUSE_INPUT:
case GATT_UUID_HID_BT_KB_INPUT:
- if (bta_hh_le_find_alloc_report_entry(p_dev_cb, service->handle,
- p_char->uuid.uu.uuid16,
- p_char->handle) == NULL)
+ if (bta_hh_le_find_alloc_report_entry(p_dev_cb, service->handle, uuid16,
+ charac.value_handle) == NULL)
APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
break;
default:
APPL_TRACE_DEBUG("%s: not processing %s 0x%04d", __func__,
- bta_hh_uuid_to_str(p_char->uuid.uu.uuid16),
- p_char->uuid.uu.uuid16);
+ bta_hh_uuid_to_str(uuid16), uuid16);
}
}
/* Make sure PROTO_MODE is processed as last */
- for (list_node_t* cn = list_begin(service->characteristics);
- cn != list_end(service->characteristics); cn = list_next(cn)) {
- tBTA_GATTC_CHARACTERISTIC* p_char =
- (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
-
- if (p_char->uuid.len == LEN_UUID_16 &&
- p_char->uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE) {
- p_dev_cb->hid_srvc.proto_mode_handle = p_char->handle;
+ for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+ if (charac.uuid == Uuid::From16Bit(GATT_UUID_HID_PROTO_MODE)) {
+ p_dev_cb->hid_srvc.proto_mode_handle = charac.value_handle;
bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
break;
}
@@ -1604,46 +1484,40 @@
/* service search exception or no HID service is supported on remote */
if (p_dev_cb == NULL) return;
- if (p_data->status != BTA_GATT_OK) {
+ if (p_data->status != GATT_SUCCESS) {
p_dev_cb->status = BTA_HH_ERR_SDP;
/* close the connection and report service discovery complete with error */
bta_hh_le_api_disc_act(p_dev_cb);
return;
}
- const list_t* services = BTA_GATTC_GetServices(p_data->conn_id);
+ const std::vector<tBTA_GATTC_SERVICE>* services =
+ BTA_GATTC_GetServices(p_data->conn_id);
bool have_hid = false;
- for (list_node_t* sn = list_begin(services); sn != list_end(services);
- sn = list_next(sn)) {
- tBTA_GATTC_SERVICE* service = (tBTA_GATTC_SERVICE*)list_node(sn);
-
- if (service->uuid.uu.uuid16 == UUID_SERVCLASS_LE_HID &&
- service->is_primary && !have_hid) {
+ for (const tBTA_GATTC_SERVICE& service : *services) {
+ if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_LE_HID) &&
+ service.is_primary && !have_hid) {
have_hid = true;
/* found HID primamry service */
p_dev_cb->hid_srvc.in_use = true;
- p_dev_cb->hid_srvc.srvc_inst_id = service->handle;
+ p_dev_cb->hid_srvc.srvc_inst_id = service.handle;
p_dev_cb->hid_srvc.proto_mode_handle = 0;
p_dev_cb->hid_srvc.control_point_handle = 0;
- bta_hh_le_search_hid_chars(p_dev_cb, service);
+ bta_hh_le_search_hid_chars(p_dev_cb, &service);
APPL_TRACE_DEBUG("%s: have HID service inst_id= %d", __func__,
p_dev_cb->hid_srvc.srvc_inst_id);
- } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_SCAN_PARAM) {
+ } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_SCAN_PARAM)) {
p_dev_cb->scan_refresh_char_handle = 0;
- for (list_node_t* cn = list_begin(service->characteristics);
- cn != list_end(service->characteristics); cn = list_next(cn)) {
- tBTA_GATTC_CHARACTERISTIC* p_char =
- (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
- if (p_char->uuid.len == LEN_UUID_16 &&
- p_char->uuid.uu.uuid16 == GATT_UUID_SCAN_REFRESH) {
- p_dev_cb->scan_refresh_char_handle = p_char->handle;
+ for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
+ if (charac.uuid == Uuid::From16Bit(GATT_UUID_SCAN_REFRESH)) {
+ p_dev_cb->scan_refresh_char_handle = charac.value_handle;
- if (p_char->properties & BTA_GATT_CHAR_PROP_BIT_NOTIFY)
+ if (charac.properties & GATT_CHAR_PROP_BIT_NOTIFY)
p_dev_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT;
else
p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
@@ -1651,19 +1525,15 @@
break;
}
}
- } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_GAP_SERVER) {
+ } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) {
// TODO(jpawlowski): this should be done by GAP profile, remove when GAP
// is fixed.
- for (list_node_t* cn = list_begin(service->characteristics);
- cn != list_end(service->characteristics); cn = list_next(cn)) {
- tBTA_GATTC_CHARACTERISTIC* p_char =
- (tBTA_GATTC_CHARACTERISTIC*)list_node(cn);
- if (p_char->uuid.len == LEN_UUID_16 &&
- p_char->uuid.uu.uuid16 == GATT_UUID_GAP_PREF_CONN_PARAM) {
+ for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
+ if (charac.uuid == Uuid::From16Bit(GATT_UUID_GAP_PREF_CONN_PARAM)) {
/* read the char value */
- gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle,
- read_pref_conn_params_cb, p_dev_cb);
-
+ BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id,
+ charac.value_handle,
+ read_pref_conn_params_cb, p_dev_cb);
break;
}
}
@@ -1707,19 +1577,20 @@
app_id = p_dev_cb->app_id;
- p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_dev_cb->hid_srvc.srvc_inst_id,
- p_char->uuid.uu.uuid16, p_char->handle);
+ p_rpt =
+ bta_hh_le_find_report_entry(p_dev_cb, p_dev_cb->hid_srvc.srvc_inst_id,
+ p_char->uuid.As16Bit(), p_char->value_handle);
if (p_rpt == NULL) {
APPL_TRACE_ERROR(
- "%s: notification received for Unknown Report, uuid: 0x%04x, handle: "
+ "%s: notification received for Unknown Report, uuid: %s, handle: "
"0x%04x",
- __func__, p_char->uuid.uu.uuid16, p_char->handle);
+ __func__, p_char->uuid.ToString().c_str(), p_char->value_handle);
return;
}
- if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_BT_MOUSE_INPUT)
+ if (p_char->uuid == Uuid::From16Bit(GATT_UUID_HID_BT_MOUSE_INPUT))
app_id = BTA_HH_APP_ID_MI;
- else if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT)
+ else if (p_char->uuid == Uuid::From16Bit(GATT_UUID_HID_BT_KB_INPUT))
app_id = BTA_HH_APP_ID_KB;
APPL_TRACE_DEBUG("Notification received on report ID: %d", p_rpt->rpt_id);
@@ -1767,7 +1638,7 @@
conn_dat.scps_supported = p_cb->scps_supported;
if (p_cb->status == BTA_HH_OK)
- conn_dat.status = (p_data->le_close.reason == BTA_GATT_CONN_UNKNOWN)
+ conn_dat.status = (p_data->le_close.reason == GATT_CONN_UNKNOWN)
? p_cb->status
: BTA_HH_ERR;
else
@@ -1807,7 +1678,7 @@
bta_hh_disc_cmpl();
} else {
#if (BTA_HH_LE_RECONN == TRUE)
- if (p_data->le_close.reason == BTA_GATT_CONN_TIMEOUT) {
+ if (p_data->le_close.reason == GATT_CONN_TIMEOUT) {
bta_hh_le_add_dev_bg_conn(p_cb, false);
}
#endif
@@ -1826,8 +1697,8 @@
*
******************************************************************************/
void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB* p_cb) {
- if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID) {
- gatt_op_queue_clean(p_cb->conn_id);
+ if (p_cb->conn_id != GATT_INVALID_CONN_ID) {
+ BtaGattQueue::Clean(p_cb->conn_id);
BTA_GATTC_Close(p_cb->conn_id);
/* remove device from background connection if intended to disconnect,
do not allow reconnection */
@@ -1853,7 +1724,7 @@
if (p_char == NULL) return;
- uint16_t char_uuid = p_char->uuid.uu.uuid16;
+ uint16_t char_uuid = p_char->uuid.As16Bit();
if (char_uuid != GATT_UUID_HID_REPORT &&
char_uuid != GATT_UUID_HID_BT_KB_INPUT &&
@@ -1880,9 +1751,12 @@
hs_data.status = BTA_HH_ERR;
hs_data.handle = p_dev_cb->hid_handle;
- if (status == BTA_GATT_OK) {
- p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_char->service->handle,
- p_char->uuid.uu.uuid16, p_char->handle);
+ if (status == GATT_SUCCESS) {
+ const tBTA_GATTC_SERVICE* p_svc =
+ BTA_GATTC_GetOwningService(conn_id, p_char->value_handle);
+
+ p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle, char_uuid,
+ p_char->value_handle);
if (p_rpt != NULL && len) {
p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + len + 1);
@@ -1928,8 +1802,8 @@
}
p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
- gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_rpt->char_inst_id,
- read_report_cb, p_cb);
+ BtaGattQueue::ReadCharacteristic(p_cb->conn_id, p_rpt->char_inst_id,
+ read_report_cb, p_cb);
}
static void write_report_cb(uint16_t conn_id, tGATT_STATUS status,
@@ -1946,7 +1820,7 @@
const tBTA_GATTC_CHARACTERISTIC* p_char =
BTA_GATTC_GetCharacteristic(conn_id, handle);
- uint16_t uuid = p_char->uuid.uu.uuid16;
+ uint16_t uuid = p_char->uuid.As16Bit();
if (uuid != GATT_UUID_HID_REPORT && uuid != GATT_UUID_HID_BT_KB_INPUT &&
uuid != GATT_UUID_HID_BT_MOUSE_INPUT &&
uuid != GATT_UUID_HID_BT_KB_OUTPUT) {
@@ -1955,7 +1829,7 @@
/* Set Report finished */
cback_data.handle = p_dev_cb->hid_handle;
- cback_data.status = (status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR;
+ cback_data.status = (status == GATT_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR;
p_dev_cb->w4_evt = 0;
(*bta_hh_cb.p_cback)(cb_evt, (tBTA_HH*)&cback_data);
}
@@ -1996,12 +1870,13 @@
const tBTA_GATTC_CHARACTERISTIC* p_char =
BTA_GATTC_GetCharacteristic(p_cb->conn_id, p_rpt->char_inst_id);
- tBTA_GATTC_WRITE_TYPE write_type = BTA_GATTC_TYPE_WRITE;
- if (p_char && (p_char->properties & BTA_GATT_CHAR_PROP_BIT_WRITE_NR))
- write_type = BTA_GATTC_TYPE_WRITE_NO_RSP;
+ tGATT_WRITE_TYPE write_type = GATT_WRITE;
+ if (p_char && (p_char->properties & GATT_CHAR_PROP_BIT_WRITE_NR))
+ write_type = GATT_WRITE_NO_RSP;
- gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_rpt->char_inst_id,
- std::move(value), write_type, write_report_cb, p_cb);
+ BtaGattQueue::WriteCharacteristic(p_cb->conn_id, p_rpt->char_inst_id,
+ std::move(value), write_type,
+ write_report_cb, p_cb);
}
/*******************************************************************************
@@ -2018,9 +1893,9 @@
ctrl_type -= BTA_HH_CTRL_SUSPEND;
// We don't care about response
- gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id,
- p_cb->hid_srvc.control_point_handle, {(uint8_t)ctrl_type},
- BTA_GATTC_TYPE_WRITE_NO_RSP, NULL, NULL);
+ BtaGattQueue::WriteCharacteristic(
+ p_cb->conn_id, p_cb->hid_srvc.control_point_handle, {(uint8_t)ctrl_type},
+ GATT_WRITE_NO_RSP, NULL, NULL);
}
/*******************************************************************************
@@ -2118,7 +1993,7 @@
if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/
!p_cb->in_bg_conn && to_add) {
/* add device into BG connection to accept remote initiated connection */
- BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, false, BTA_GATT_TRANSPORT_LE,
+ BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, false, GATT_TRANSPORT_LE,
false);
p_cb->in_bg_conn = true;
@@ -2140,7 +2015,8 @@
******************************************************************************/
uint8_t bta_hh_le_add_device(tBTA_HH_DEV_CB* p_cb,
tBTA_HH_MAINT_DEV* p_dev_info) {
- p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
+ p_cb->hid_handle = bta_hh_le_get_le_dev_hdl(p_cb->index);
+ if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) return BTA_HH_INVALID_HANDLE;
bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
/* update DI information */
@@ -2333,7 +2209,7 @@
// == BTA_HH_RPTT_INPUT))
// {
// p_rpt->client_cfg_value =
-// BTA_GATT_CLT_CONFIG_NOTIFICATION;
+// GATT_CLT_CONFIG_NOTIFICATION;
// }
// }
// }
diff --git a/bta/hh/bta_hh_main.cc b/bta/hh/bta_hh_main.cc
index e747773..2528391 100644
--- a/bta/hh/bta_hh_main.cc
+++ b/bta/hh/bta_hh_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -400,7 +400,7 @@
* force the index to be IDX_INVALID
*/
if ((index != BTA_HH_IDX_INVALID) &&
- (bta_hh_cb.kdev[index].in_use == false)) {
+ (!bta_hh_cb.kdev[index].in_use)) {
index = BTA_HH_IDX_INVALID;
}
}
diff --git a/bta/hh/bta_hh_utils.cc b/bta/hh/bta_hh_utils.cc
index c687a2a..c4c6061 100644
--- a/bta/hh/bta_hh_utils.cc
+++ b/bta/hh/bta_hh_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -437,7 +437,9 @@
}
if (bta_hh_cb.p_cback) {
- (*bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH*)&status);
+ tBTA_HH bta_hh;
+ bta_hh.status = status;
+ (*bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, &bta_hh);
/* all connections are down, no waiting for diconnect */
memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
}
diff --git a/bta/hl/bta_hl_act.cc b/bta/hl/bta_hl_act.cc
index 6c896f1..6d37bdf 100644
--- a/bta/hl/bta_hl_act.cc
+++ b/bta/hl/bta_hl_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,6 +39,8 @@
#include "sdp_api.h"
#include "utl.h"
+using bluetooth::Uuid;
+
/*****************************************************************************
* Local Function prototypes
****************************************************************************/
@@ -1817,7 +1819,6 @@
tBTA_HL_STATUS bta_hl_init_sdp(tBTA_HL_SDP_OPER sdp_oper, uint8_t app_idx,
uint8_t mcl_idx, uint8_t mdl_idx) {
tBTA_HL_MCL_CB* p_cb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
- tSDP_UUID uuid_list;
uint16_t attr_list[BTA_HL_NUM_SRCH_ATTR];
uint16_t num_attrs = BTA_HL_NUM_SRCH_ATTR;
tBTA_HL_STATUS status;
@@ -1843,8 +1844,7 @@
attr_list[8] = ATTR_ID_HDP_DATA_EXCH_SPEC;
attr_list[9] = ATTR_ID_HDP_MCAP_SUP_PROC;
- uuid_list.len = LEN_UUID_16;
- uuid_list.uu.uuid16 = UUID_SERVCLASS_HDP_PROFILE;
+ Uuid uuid_list = Uuid::From16Bit(UUID_SERVCLASS_HDP_PROFILE);
SDP_InitDiscoveryDb(p_cb->p_db, BTA_HL_DISC_SIZE, 1, &uuid_list, num_attrs,
attr_list);
diff --git a/bta/hl/bta_hl_api.cc b/bta/hl/bta_hl_api.cc
index 145c4f2..fa82245 100644
--- a/bta/hl/bta_hl_api.cc
+++ b/bta/hl/bta_hl_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/hl/bta_hl_ci.cc b/bta/hl/bta_hl_ci.cc
index b7bc2fd..e48c74b 100644
--- a/bta/hl/bta_hl_ci.cc
+++ b/bta/hl/bta_hl_ci.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/hl/bta_hl_int.h b/bta/hl/bta_hl_int.h
index c0ba647..c6dce11 100644
--- a/bta/hl/bta_hl_int.h
+++ b/bta/hl/bta_hl_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1998-2012 Broadcom Corporation
+ * Copyright 1998-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/hl/bta_hl_main.cc b/bta/hl/bta_hl_main.cc
index 69c0909..dcd0815 100644
--- a/bta/hl/bta_hl_main.cc
+++ b/bta/hl/bta_hl_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1998-2012 Broadcom Corporation
+ * Copyright 1998-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/hl/bta_hl_sdp.cc b/bta/hl/bta_hl_sdp.cc
index fe3da58..0a357f0 100644
--- a/bta/hl/bta_hl_sdp.cc
+++ b/bta/hl/bta_hl_sdp.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1998-2012 Broadcom Corporation
+ * Copyright 1998-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -220,9 +220,8 @@
add_proto_list.list_elem[0].params[0] = p_cb->data_psm;
add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_MCAP_DATA;
add_proto_list.list_elem[1].num_params = 0;
- result &=
- SDP_AddAdditionProtoLists(p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS,
- (tSDP_PROTO_LIST_ELEM*)&add_proto_list);
+ result &= SDP_AddAdditionProtoLists(
+ p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS, &add_proto_list);
}
if (result) {
@@ -410,9 +409,8 @@
add_proto_list.list_elem[0].params[0] = p_cb->data_psm;
add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_MCAP_DATA;
add_proto_list.list_elem[1].num_params = 0;
- result &=
- SDP_AddAdditionProtoLists(p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS,
- (tSDP_PROTO_LIST_ELEM*)&add_proto_list);
+ result &= SDP_AddAdditionProtoLists(
+ p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS, &add_proto_list);
}
if (result) {
diff --git a/bta/hl/bta_hl_utils.cc b/bta/hl/bta_hl_utils.cc
index 8cdacc9..0aa93b3 100644
--- a/bta/hl/bta_hl_utils.cc
+++ b/bta/hl/bta_hl_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h
index 1322368..b968ae6 100644
--- a/bta/include/bta_ag_api.h
+++ b/bta/include/bta_ag_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,9 +27,16 @@
#include "bta_api.h"
+#include <string>
+#include <vector>
+
/*****************************************************************************
* Constants and data types
****************************************************************************/
+/* Number of SCBs (AG service instances that can be registered) */
+#define BTA_AG_MAX_NUM_CLIENTS 6
+
+#define HFP_HSP_VERSION_UNKNOWN 0x0000
#define HFP_VERSION_1_1 0x0101
#define HFP_VERSION_1_5 0x0105
#define HFP_VERSION_1_6 0x0106
@@ -38,6 +45,9 @@
#define HSP_VERSION_1_0 0x0100
#define HSP_VERSION_1_2 0x0102
+#define HFP_VERSION_CONFIG_KEY "HfpVersion"
+#define HFP_SDP_FEATURES_CONFIG_KEY "HfpSdpFeatures"
+
/* Note, if you change the default version here, please also change the one in
* bta_hs_api.h, they are meant to be the same.
*/
@@ -57,6 +67,12 @@
#define BTA_AG_FEAT_EXTERR 0x00000100 /* Extended error codes */
#define BTA_AG_FEAT_CODEC 0x00000200 /* Codec Negotiation */
+/* AG SDP feature masks */
+#define BTA_AG_FEAT_WBS_SUPPORT 0x0020 /* Supports WBS */
+
+/* Only SDP feature bits 0 to 4 matches BRSF feature bits */
+#define HFP_SDP_BRSF_FEATURES_MASK 0x001F
+
/* Valid feature bit mask for HFP 1.6 (and below) */
#define HFP_1_6_FEAT_MASK 0x000003FF
@@ -73,14 +89,6 @@
typedef uint32_t tBTA_AG_FEAT;
-/* AG parse mode */
-#define BTA_AG_PARSE 0 /* Perform AT command parsing in AG */
-
-/* Pass data directly to phone's AT command interpreter */
-#define BTA_AG_PASS_THROUGH 1
-
-typedef uint8_t tBTA_AG_PARSE_MODE;
-
/* AG open status */
#define BTA_AG_SUCCESS 0 /* Connection successfully opened */
#define BTA_AG_FAIL_SDP 1 /* Open failed due to SDP */
@@ -140,6 +148,7 @@
#define BTA_AG_UNAT_RES 20 /* Response to unknown AT command event */
#define BTA_AG_MULTI_CALL_RES 21 /* SLC at three way call */
#define BTA_AG_BIND_RES 22 /* Activate/Deactivate HF indicator */
+#define BTA_AG_IND_RES_ON_DEMAND 33 /* Update an indicator value forcible */
typedef uint8_t tBTA_AG_RES;
@@ -268,7 +277,7 @@
} tBTA_AG_IND;
/* data type for BTA_AgResult() */
-typedef struct {
+struct tBTA_AG_RES_DATA {
char str[BTA_AG_AT_MAX_LEN + 1];
tBTA_AG_IND ind;
uint16_t num;
@@ -277,7 +286,8 @@
uint8_t
ok_flag; /* Indicates if response is finished, and if error occurred */
bool state;
-} tBTA_AG_RES_DATA;
+ static const tBTA_AG_RES_DATA kEmpty;
+};
/* AG callback events */
#define BTA_AG_ENABLE_EVT 0 /* AG enabled */
@@ -313,6 +323,7 @@
#define BTA_AG_AT_BCS_EVT 27 /* Codec select */
#define BTA_AG_AT_BIND_EVT 28 /* HF indicator */
#define BTA_AG_AT_BIEV_EVT 29 /* HF indicator updates from peer */
+#define BTA_AG_AT_BIA_EVT 32 /* AG indicator activation event from peer */
typedef uint8_t tBTA_AG_EVT;
@@ -356,7 +367,7 @@
tBTA_AG_HDR hdr;
RawAddress bd_addr;
char str[BTA_AG_AT_MAX_LEN + 1];
- uint16_t num;
+ uint32_t num;
uint8_t idx; /* call number used by CLCC and CHLD */
uint16_t lidx; /* long index, ex, HF indicator */
} tBTA_AG_VAL;
@@ -459,7 +470,7 @@
* Returns BTA_SUCCESS if OK, BTA_FAILURE otherwise.
*
******************************************************************************/
-tBTA_STATUS BTA_AgEnable(tBTA_AG_PARSE_MODE parse_mode, tBTA_AG_CBACK* p_cback);
+tBTA_STATUS BTA_AgEnable(tBTA_AG_CBACK* p_cback);
/*******************************************************************************
*
@@ -471,7 +482,7 @@
* Returns void
*
******************************************************************************/
-void BTA_AgDisable(void);
+void BTA_AgDisable();
/*******************************************************************************
*
@@ -484,7 +495,8 @@
*
******************************************************************************/
void BTA_AgRegister(tBTA_SERVICE_MASK services, tBTA_SEC sec_mask,
- tBTA_AG_FEAT features, const char* p_service_names[],
+ tBTA_AG_FEAT features,
+ const std::vector<std::string>& service_names,
uint8_t app_id);
/*******************************************************************************
@@ -512,8 +524,7 @@
* Returns void
*
******************************************************************************/
-void BTA_AgOpen(uint16_t handle, const RawAddress& bd_addr, tBTA_SEC sec_mask,
- tBTA_SERVICE_MASK services);
+void BTA_AgOpen(uint16_t handle, const RawAddress& bd_addr, tBTA_SEC sec_mask);
/*******************************************************************************
*
@@ -559,15 +570,13 @@
* Function BTA_AgResult
*
* Description Send an AT result code to a headset or hands-free device.
- * This function is only used when the AG parse mode is set
- * to BTA_AG_PARSE.
*
*
* Returns void
*
******************************************************************************/
void BTA_AgResult(uint16_t handle, tBTA_AG_RES result,
- tBTA_AG_RES_DATA* p_data);
+ const tBTA_AG_RES_DATA& data);
/*******************************************************************************
*
@@ -585,4 +594,6 @@
void BTA_AgSetScoAllowed(bool value);
+void BTA_AgSetActiveDevice(const RawAddress& active_device_addr);
+
#endif /* BTA_AG_API_H */
diff --git a/bta/include/bta_ag_ci.h b/bta/include/bta_ag_ci.h
deleted file mode 100644
index 01e3870..0000000
--- a/bta/include/bta_ag_ci.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2003-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * This is the interface file for audio gateway call-in functions.
- *
- ******************************************************************************/
-#ifndef BTA_AG_CI_H
-#define BTA_AG_CI_H
-
-#include "bta_ag_api.h"
-
-/*****************************************************************************
- * Function Declarations
- ****************************************************************************/
-/*******************************************************************************
- *
- * Function bta_ag_ci_rx_write
- *
- * Description This function is called to send data to the AG when the AG
- * is configured for AT command pass-through. The function
- * copies data to an event buffer and sends it.
- *
- * Returns void
- *
- ******************************************************************************/
-extern void bta_ag_ci_rx_write(uint16_t handle, char* p_data, uint16_t len);
-
-/******************************************************************************
- *
- * Function bta_ag_ci_slc_ready
- *
- * Description This function is called to notify AG that SLC is up at
- * the application. This funcion is only used when the app
- * is running in pass-through mode.
- *
- * Returns void
- *
- *****************************************************************************/
-extern void bta_ag_ci_slc_ready(uint16_t handle);
-
-/******************************************************************************
- *
- * Function bta_ag_ci_wbs_command
- *
- * Description This function is called to notify AG that a WBS command is
- * received
- *
- * Returns void
- *
- *****************************************************************************/
-extern void bta_ag_ci_wbs_command(uint16_t handle, char* p_data, uint16_t len);
-
-#endif /* BTA_AG_CI_H */
diff --git a/bta/include/bta_ag_co.h b/bta/include/bta_ag_co.h
deleted file mode 100644
index aed7def..0000000
--- a/bta/include/bta_ag_co.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2003-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * This is the interface file for audio gateway call-out functions.
- *
- ******************************************************************************/
-#ifndef BTA_AG_CO_H
-#define BTA_AG_CO_H
-
-#include "bta_ag_api.h"
-
-/*******************************************************************************
- *
- * Function bta_ag_co_init
- *
- * Description This callout function is executed by AG when it is
- * started by calling BTA_AgEnable(). This function can be
- * used by the phone to initialize audio paths or for other
- * initialization purposes.
- *
- *
- * Returns Void.
- *
- ******************************************************************************/
-extern void bta_ag_co_init(void);
-
-/*******************************************************************************
- *
- * Function bta_ag_co_data_open
- *
- * Description This function is executed by AG when a service level
- * connection
- * is opened. The phone can use this function to set
- * up data paths or perform any required initialization or
- * set up particular to the connected service.
- *
- *
- * Returns void
- *
- ******************************************************************************/
-extern void bta_ag_co_data_open(uint16_t handle, tBTA_SERVICE_ID service);
-
-/*******************************************************************************
- *
- * Function bta_ag_co_data_close
- *
- * Description This function is called by AG when a service level
- * connection is closed
- *
- *
- * Returns void
- *
- ******************************************************************************/
-extern void bta_ag_co_data_close(uint16_t handle);
-
-/*******************************************************************************
- *
- * Function bta_ag_co_tx_write
- *
- * Description This function is called by the AG to send data to the
- * phone when the AG is configured for AT command pass-through.
- * The implementation of this function must copy the data to
- * the phone's memory.
- *
- * Returns void
- *
- ******************************************************************************/
-extern void bta_ag_co_tx_write(uint16_t handle, uint8_t* p_data, uint16_t len);
-
-#endif /* BTA_AG_CO_H */
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index 814038c..9d4693e 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2014 Broadcom Corporation
+ * Copyright 2003-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -143,7 +143,7 @@
typedef struct {
tBTA_SERVICE_MASK srvc_mask;
uint8_t num_uuid;
- tBT_UUID* p_uuid;
+ bluetooth::Uuid* p_uuid;
} tBTA_SERVICE_MASK_EXT;
/* Security Setting Mask */
@@ -291,10 +291,6 @@
*/
tBTA_DM_INQ_FILT filter_type; /* Filter condition type. */
tBTA_DM_INQ_COND filter_cond; /* Filter condition data. */
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- uint8_t intl_duration
- [4]; /*duration array storing the interleave scan's time portions*/
-#endif
} tBTA_DM_INQ;
typedef struct {
@@ -762,7 +758,7 @@
uint32_t raw_data_size; /* size of raw data */
tBT_DEVICE_TYPE device_type; /* device type in case it is BLE device */
uint32_t num_uuids;
- uint8_t* p_uuid_list;
+ bluetooth::Uuid* p_uuid_list;
tBTA_STATUS result;
} tBTA_DM_DISC_RES;
@@ -770,7 +766,7 @@
typedef struct {
RawAddress bd_addr; /* BD address peer device. */
BD_NAME bd_name; /* Name of peer device. */
- tBT_UUID service; /* GATT based Services UUID found on peer device. */
+ bluetooth::Uuid service; /* GATT based Services UUID found on peer device. */
} tBTA_DM_DISC_BLE_RES;
/* Union of all search callback structures */
@@ -1073,7 +1069,7 @@
* Returns tBTA_STATUS
*
******************************************************************************/
-extern tBTA_STATUS BTA_EnableTestMode(void);
+extern void BTA_EnableTestMode(void);
/*******************************************************************************
*
@@ -1172,7 +1168,8 @@
* Returns void
*
******************************************************************************/
-extern void BTA_DmDiscoverUUID(const RawAddress& bd_addr, tSDP_UUID* uuid,
+extern void BTA_DmDiscoverUUID(const RawAddress& bd_addr,
+ const bluetooth::Uuid& uuid,
tBTA_DM_SEARCH_CBACK* p_cback, bool sdp_search);
/*******************************************************************************
@@ -1363,59 +1360,6 @@
extern void BTA_DmCloseACL(const RawAddress& bd_addr, bool remove_dev,
tBTA_TRANSPORT transport);
-/*******************************************************************************
- *
- * Function bta_dmexecutecallback
- *
- * Description This function will request BTA to execute a call back in the
- * context of BTU task.
- * This API was named in lower case because it is only intended
- * for the internal customers(like BTIF).
- *
- * Returns void
- *
- ******************************************************************************/
-extern void bta_dmexecutecallback(tBTA_DM_EXEC_CBACK* p_callback,
- void* p_param);
-
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
-/*******************************************************************************
- *
- * Function BTA_DmPcmInitSamples
- *
- * Description initialize the down sample converter.
- *
- * src_sps: original samples per second (source audio data)
- * (ex. 44100, 48000)
- * bits: number of bits per pcm sample (16)
- * n_channels: number of channels (i.e. mono(1), stereo(2)...)
- *
- * Returns none
- *
- ******************************************************************************/
-extern void BTA_DmPcmInitSamples(uint32_t src_sps, uint32_t bits,
- uint32_t n_channels);
-
-/*******************************************************************************
- * Function BTA_DmPcmResample
- *
- * Description Down sampling utility to convert higher sampling rate into
- * 8K/16bits
- * PCM samples.
- *
- * Parameters p_src: pointer to the buffer where the original sampling PCM
- * are stored.
- * in_bytes: Length of the input PCM sample buffer in byte.
- * p_dst: pointer to the buffer which is to be used to store
- * the converted PCM samples.
- *
- *
- * Returns int32_t: number of samples converted.
- *
- ******************************************************************************/
-extern int32_t BTA_DmPcmResample(void* p_src, uint32_t in_bytes, void* p_dst);
-#endif
-
/* BLE related API functions */
/*******************************************************************************
*
@@ -1704,7 +1648,9 @@
******************************************************************************/
extern void BTA_DmBleUpdateConnectionParams(const RawAddress& bd_addr,
uint16_t min_int, uint16_t max_int,
- uint16_t latency, uint16_t timeout);
+ uint16_t latency, uint16_t timeout,
+ uint16_t min_ce_len,
+ uint16_t max_ce_len);
/*******************************************************************************
*
diff --git a/bta/include/bta_ar_api.h b/bta/include/bta_ar_api.h
index ffa9c19..b2a8753 100644
--- a/bta/include/bta_ar_api.h
+++ b/bta/include/bta_ar_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@
* Returns void
*
******************************************************************************/
-extern void bta_ar_reg_avdt(tAVDT_REG* p_reg, tAVDT_CTRL_CBACK* p_cback,
+extern void bta_ar_reg_avdt(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback,
tBTA_SYS_ID sys_id);
/*******************************************************************************
@@ -86,7 +86,8 @@
* Returns void
*
******************************************************************************/
-extern void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr);
+extern void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr,
+ uint8_t scb_index);
/*******************************************************************************
*
diff --git a/bta/include/bta_av_api.h b/bta/include/bta_av_api.h
index 9add76b..4c0539e 100644
--- a/bta/include/bta_av_api.h
+++ b/bta/include/bta_av_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,9 +91,9 @@
/* handle index to mask */
#define BTA_AV_HNDL_TO_MSK(h) ((uint8_t)(1 << (h)))
-/* maximum number of streams created: 1 for audio, 1 for video */
+/* maximum number of streams created */
#ifndef BTA_AV_NUM_STRS
-#define BTA_AV_NUM_STRS 2
+#define BTA_AV_NUM_STRS 6
#endif
#ifndef BTA_AV_MAX_A2DP_MTU
@@ -101,109 +101,19 @@
#define BTA_AV_MAX_A2DP_MTU 1008
#endif
-#ifndef BTA_AV_MAX_VDP_MTU
-#define BTA_AV_MAX_VDP_MTU 1008
-#endif
-
/* operation id list for BTA_AvRemoteCmd */
-#define BTA_AV_RC_SELECT AVRC_ID_SELECT /* select */
-#define BTA_AV_RC_UP AVRC_ID_UP /* up */
-#define BTA_AV_RC_DOWN AVRC_ID_DOWN /* down */
-#define BTA_AV_RC_LEFT AVRC_ID_LEFT /* left */
-#define BTA_AV_RC_RIGHT AVRC_ID_RIGHT /* right */
-#define BTA_AV_RC_RIGHT_UP AVRC_ID_RIGHT_UP /* right-up */
-#define BTA_AV_RC_RIGHT_DOWN AVRC_ID_RIGHT_DOWN /* right-down */
-#define BTA_AV_RC_LEFT_UP AVRC_ID_LEFT_UP /* left-up */
-#define BTA_AV_RC_LEFT_DOWN AVRC_ID_LEFT_DOWN /* left-down */
-#define BTA_AV_RC_ROOT_MENU AVRC_ID_ROOT_MENU /* root menu */
-#define BTA_AV_RC_SETUP_MENU AVRC_ID_SETUP_MENU /* setup menu */
-#define BTA_AV_RC_CONT_MENU AVRC_ID_CONT_MENU /* contents menu */
-#define BTA_AV_RC_FAV_MENU AVRC_ID_FAV_MENU /* favorite menu */
-#define BTA_AV_RC_EXIT AVRC_ID_EXIT /* exit */
-#define BTA_AV_RC_0 AVRC_ID_0 /* 0 */
-#define BTA_AV_RC_1 AVRC_ID_1 /* 1 */
-#define BTA_AV_RC_2 AVRC_ID_2 /* 2 */
-#define BTA_AV_RC_3 AVRC_ID_3 /* 3 */
-#define BTA_AV_RC_4 AVRC_ID_4 /* 4 */
-#define BTA_AV_RC_5 AVRC_ID_5 /* 5 */
-#define BTA_AV_RC_6 AVRC_ID_6 /* 6 */
-#define BTA_AV_RC_7 AVRC_ID_7 /* 7 */
-#define BTA_AV_RC_8 AVRC_ID_8 /* 8 */
-#define BTA_AV_RC_9 AVRC_ID_9 /* 9 */
-#define BTA_AV_RC_DOT AVRC_ID_DOT /* dot */
-#define BTA_AV_RC_ENTER AVRC_ID_ENTER /* enter */
-#define BTA_AV_RC_CLEAR AVRC_ID_CLEAR /* clear */
-#define BTA_AV_RC_CHAN_UP AVRC_ID_CHAN_UP /* channel up */
-#define BTA_AV_RC_CHAN_DOWN AVRC_ID_CHAN_DOWN /* channel down */
-#define BTA_AV_RC_PREV_CHAN AVRC_ID_PREV_CHAN /* previous channel */
-#define BTA_AV_RC_SOUND_SEL AVRC_ID_SOUND_SEL /* sound select */
-#define BTA_AV_RC_INPUT_SEL AVRC_ID_INPUT_SEL /* input select */
-#define BTA_AV_RC_DISP_INFO AVRC_ID_DISP_INFO /* display information */
-#define BTA_AV_RC_HELP AVRC_ID_HELP /* help */
-#define BTA_AV_RC_PAGE_UP AVRC_ID_PAGE_UP /* page up */
-#define BTA_AV_RC_PAGE_DOWN AVRC_ID_PAGE_DOWN /* page down */
-#define BTA_AV_RC_POWER AVRC_ID_POWER /* power */
-#define BTA_AV_RC_VOL_UP AVRC_ID_VOL_UP /* volume up */
-#define BTA_AV_RC_VOL_DOWN AVRC_ID_VOL_DOWN /* volume down */
-#define BTA_AV_RC_MUTE AVRC_ID_MUTE /* mute */
-#define BTA_AV_RC_PLAY AVRC_ID_PLAY /* play */
-#define BTA_AV_RC_STOP AVRC_ID_STOP /* stop */
-#define BTA_AV_RC_PAUSE AVRC_ID_PAUSE /* pause */
-#define BTA_AV_RC_RECORD AVRC_ID_RECORD /* record */
-#define BTA_AV_RC_REWIND AVRC_ID_REWIND /* rewind */
-#define BTA_AV_RC_FAST_FOR AVRC_ID_FAST_FOR /* fast forward */
-#define BTA_AV_RC_EJECT AVRC_ID_EJECT /* eject */
-#define BTA_AV_RC_FORWARD AVRC_ID_FORWARD /* forward */
-#define BTA_AV_RC_BACKWARD AVRC_ID_BACKWARD /* backward */
-#define BTA_AV_RC_ANGLE AVRC_ID_ANGLE /* angle */
-#define BTA_AV_RC_SUBPICT AVRC_ID_SUBPICT /* subpicture */
-#define BTA_AV_RC_F1 AVRC_ID_F1 /* F1 */
-#define BTA_AV_RC_F2 AVRC_ID_F2 /* F2 */
-#define BTA_AV_RC_F3 AVRC_ID_F3 /* F3 */
-#define BTA_AV_RC_F4 AVRC_ID_F4 /* F4 */
-#define BTA_AV_RC_F5 AVRC_ID_F5 /* F5 */
-#define BTA_AV_VENDOR AVRC_ID_VENDOR /* vendor unique */
-
typedef uint8_t tBTA_AV_RC;
/* state flag for pass through command */
-#define BTA_AV_STATE_PRESS AVRC_STATE_PRESS /* key pressed */
-#define BTA_AV_STATE_RELEASE AVRC_STATE_RELEASE /* key released */
-
typedef uint8_t tBTA_AV_STATE;
/* command codes for BTA_AvVendorCmd */
-#define BTA_AV_CMD_CTRL AVRC_CMD_CTRL
-#define BTA_AV_CMD_STATUS AVRC_CMD_STATUS
-#define BTA_AV_CMD_SPEC_INQ AVRC_CMD_SPEC_INQ
-#define BTA_AV_CMD_NOTIF AVRC_CMD_NOTIF
-#define BTA_AV_CMD_GEN_INQ AVRC_CMD_GEN_INQ
-
typedef uint8_t tBTA_AV_CMD;
/* response codes for BTA_AvVendorRsp */
-#define BTA_AV_RSP_NOT_IMPL AVRC_RSP_NOT_IMPL
-#define BTA_AV_RSP_ACCEPT AVRC_RSP_ACCEPT
-#define BTA_AV_RSP_REJ AVRC_RSP_REJ
-#define BTA_AV_RSP_IN_TRANS AVRC_RSP_IN_TRANS
-#define BTA_AV_RSP_IMPL_STBL AVRC_RSP_IMPL_STBL
-#define BTA_AV_RSP_CHANGED AVRC_RSP_CHANGED
-#define BTA_AV_RSP_INTERIM AVRC_RSP_INTERIM
-
typedef uint8_t tBTA_AV_CODE;
/* error codes for BTA_AvProtectRsp */
-#define BTA_AV_ERR_NONE A2DP_SUCCESS /* Success, no error */
-#define BTA_AV_ERR_BAD_STATE \
- AVDT_ERR_BAD_STATE /* Message cannot be processed in this state */
-#define BTA_AV_ERR_RESOURCE AVDT_ERR_RESOURCE /* Insufficient resources */
-#define BTA_AV_ERR_BAD_CP_TYPE \
- A2DP_BAD_CP_TYPE /* The requested Content Protection Type is not supported \
- */
-#define BTA_AV_ERR_BAD_CP_FORMAT \
- A2DP_BAD_CP_FORMAT /* The format of Content Protection Data is not correct \
- */
-
typedef uint8_t tBTA_AV_ERR;
/* AV callback events */
@@ -244,6 +154,15 @@
typedef uint8_t tBTA_AV_EVT;
+typedef enum {
+ BTA_AV_CODEC_TYPE_UNKNOWN = 0x00,
+ BTA_AV_CODEC_TYPE_SBC = 0x01,
+ BTA_AV_CODEC_TYPE_AAC = 0x02,
+ BTA_AV_CODEC_TYPE_APTX = 0x04,
+ BTA_AV_CODEC_TYPE_APTXHD = 0x08,
+ BTA_AV_CODEC_TYPE_LDAC = 0x10
+} tBTA_AV_CODEC_TYPE;
+
/* Event associated with BTA_AV_ENABLE_EVT */
typedef struct { tBTA_AV_FEAT features; } tBTA_AV_ENABLE;
@@ -285,7 +204,7 @@
bool suspending;
} tBTA_AV_START;
-/* data associated with BTA_AV_SUSPEND_EVT */
+/* data associated with BTA_AV_SUSPEND_EVT, BTA_AV_STOP_EVT */
typedef struct {
tBTA_AV_CHNL chnl;
tBTA_AV_HNDL hndl;
@@ -449,10 +368,9 @@
typedef void(tBTA_AV_SINK_DATA_CBACK)(tBTA_AV_EVT event, tBTA_AV_MEDIA* p_data);
/* type for stream state machine action functions */
-typedef void (*tBTA_AV_ACT)(void* p_cb, void* p_data);
-
-/* type for registering VDP */
-typedef void(tBTA_AV_REG)(tAVDT_CS* p_cs, char* p_service_name, void* p_data);
+struct tBTA_AV_SCB;
+union tBTA_AV_DATA;
+typedef void (*tBTA_AV_ACT)(tBTA_AV_SCB* p_cb, tBTA_AV_DATA* p_data);
/* AV configuration structure */
typedef struct {
@@ -466,8 +384,6 @@
const uint16_t*
p_audio_flush_to; /* AVDTP audio transport channel flush timeout */
uint16_t audio_mqs; /* AVDTP audio channel max data queue size */
- uint16_t video_mtu; /* AVDTP video transport channel MTU at L2CAP */
- uint16_t video_flush_to; /* AVDTP video transport channel flush timeout */
bool avrc_group; /* true, to accept AVRC 1.3 group nevigation command */
uint8_t num_co_ids; /* company id count in p_meta_co_ids */
uint8_t num_evt_ids; /* event id count in p_meta_evt_ids */
@@ -477,8 +393,7 @@
p_meta_co_ids; /* the metadata Get Capabilities response for company id */
const uint8_t* p_meta_evt_ids; /* the the metadata Get Capabilities response
for event id */
- const tBTA_AV_ACT* p_act_tbl; /* the action function table for VDP stream */
- tBTA_AV_REG* p_reg; /* action function to register VDP */
+ const tBTA_AV_ACT* p_act_tbl; /* action function table for audio stream */
char avrc_controller_name[BTA_SERVICE_NAME_LEN]; /* Default AVRCP controller
name */
char avrc_target_name[BTA_SERVICE_NAME_LEN]; /* Default AVRCP target name*/
@@ -589,7 +504,7 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStart(void);
+void BTA_AvStart(tBTA_AV_HNDL handle);
/*******************************************************************************
*
@@ -602,7 +517,7 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStop(bool suspend);
+void BTA_AvStop(tBTA_AV_HNDL handle, bool suspend);
/*******************************************************************************
*
@@ -788,4 +703,23 @@
******************************************************************************/
void BTA_AvOffloadStartRsp(tBTA_AV_HNDL hndl, tBTA_AV_STATUS status);
+/**
+ * Obtain the Channel Index for a peer.
+ * If the peer already has associated internal state, the corresponding
+ * Channel Index for that state is returned. Otherwise, the Channel Index
+ * for unused internal state is returned instead.
+ *
+ * @param peer_address the peer address
+ * @return the peer Channel Index index if obtained, otherwise -1
+ */
+int BTA_AvObtainPeerChannelIndex(const RawAddress& peer_address);
+
+/**
+ * Dump debug-related information for the BTA AV module.
+ *
+ * @param fd the file descriptor to use for writing the ASCII formatted
+ * information
+ */
+void bta_debug_av_dump(int fd);
+
#endif /* BTA_AV_API_H */
diff --git a/bta/include/bta_av_ci.h b/bta/include/bta_av_ci.h
index 3b68f05..07b59e6 100644
--- a/bta/include/bta_av_ci.h
+++ b/bta/include/bta_av_ci.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
*
* Description This function sends an event to the AV indicating that
* the phone has audio stream data ready to send and AV
- * should call bta_av_co_audio_src_data_path().
+ * should call bta_av_co_audio_source_data_path().
*
* Returns void
*
@@ -55,7 +55,7 @@
* Returns void
*
******************************************************************************/
-extern void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, uint8_t err_code,
+extern void bta_av_ci_setconfig(tBTA_AV_HNDL bta_av_handle, uint8_t err_code,
uint8_t category, uint8_t num_seid,
uint8_t* p_seid, bool recfg_needed,
uint8_t avdt_handle);
diff --git a/bta/include/bta_av_co.h b/bta/include/bta_av_co.h
index 0e71ac2..f83ff23 100644
--- a/bta/include/bta_av_co.h
+++ b/bta/include/bta_av_co.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@
*
******************************************************************************/
bool bta_av_co_audio_init(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg);
+ AvdtpSepConfig* p_cfg);
/*******************************************************************************
*
@@ -59,9 +59,10 @@
* Returns void.
*
******************************************************************************/
-void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, uint8_t num_seps,
- uint8_t num_snk, uint8_t num_src,
- const RawAddress& addr, uint16_t uuid_local);
+void bta_av_co_audio_disc_res(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint8_t num_seps,
+ uint8_t num_sinks, uint8_t num_sources,
+ uint16_t uuid_local);
/*******************************************************************************
*
@@ -75,7 +76,9 @@
* Returns Stream codec and content protection configuration info.
*
******************************************************************************/
-tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
+tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
uint8_t* p_sep_info_idx, uint8_t seid,
uint8_t* p_num_protect,
uint8_t* p_protect_info);
@@ -92,8 +95,9 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, const uint8_t* p_codec_info,
- uint8_t seid, const RawAddress& addr,
+void bta_av_co_audio_setconfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, uint8_t seid,
uint8_t num_protect,
const uint8_t* p_protect_info,
uint8_t t_local_sep, uint8_t avdt_handle);
@@ -111,7 +115,8 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_open(tBTA_AV_HNDL hndl, uint16_t mtu);
+void bta_av_co_audio_open(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu);
/*******************************************************************************
*
@@ -127,7 +132,8 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_close(tBTA_AV_HNDL hndl);
+void bta_av_co_audio_close(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
/*******************************************************************************
*
@@ -140,8 +146,9 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_start(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
- bool* p_no_rtp_hdr);
+void bta_av_co_audio_start(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, bool* p_no_rtp_header);
/*******************************************************************************
*
@@ -154,11 +161,12 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_stop(tBTA_AV_HNDL hndl);
+void bta_av_co_audio_stop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
/*******************************************************************************
*
- * Function bta_av_co_audio_src_data_path
+ * Function bta_av_co_audio_source_data_path
*
* Description This function is called to get the next data buffer from
* the audio codec
@@ -167,14 +175,14 @@
* Otherwise, a buffer (BT_HDR*) containing the audio data.
*
******************************************************************************/
-void* bta_av_co_audio_src_data_path(const uint8_t* p_codec_info,
- uint32_t* p_timestamp);
+BT_HDR* bta_av_co_audio_source_data_path(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp);
/*******************************************************************************
*
* Function bta_av_co_audio_drop
*
- * Description An Audio packet is dropped. .
+ * Description An Audio packet is dropped.
* It's very likely that the connected headset with this handle
* is moved far away. The implementation may want to reduce
* the encoder bit rate setting to reduce the packet size.
@@ -182,7 +190,8 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_drop(tBTA_AV_HNDL hndl);
+void bta_av_co_audio_drop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
/*******************************************************************************
*
@@ -196,7 +205,8 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay);
+void bta_av_co_audio_delay(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t delay);
/*******************************************************************************
*
@@ -211,6 +221,18 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_update_mtu(tBTA_AV_HNDL hndl, uint16_t mtu);
+void bta_av_co_audio_update_mtu(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu);
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_content_protect_is_active
+ **
+ ** Description Get the current configuration of content protection
+ **
+ ** Returns TRUE if the current streaming has CP, FALSE otherwise
+ **
+ ******************************************************************************/
+bool bta_av_co_content_protect_is_active(const RawAddress& peer_address);
#endif /* BTA_AV_CO_H */
diff --git a/bta/include/bta_closure_api.h b/bta/include/bta_closure_api.h
index 8c4e11a..a4c0188 100644
--- a/bta/include/bta_closure_api.h
+++ b/bta/include/bta_closure_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
#include <base/callback_forward.h>
#include <base/location.h>
+#include <hardware/bluetooth.h>
+
/*
* This method post a closure for execution on bta thread. Please see
* documentation at
@@ -30,7 +32,7 @@
* for how to handle dynamic memory ownership/smart pointers with base::Owned(),
* base::Passed(), base::ConstRef() and others.
*/
-void do_in_bta_thread(const tracked_objects::Location& from_here,
- const base::Closure& task);
+bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here,
+ const base::Closure& task);
#endif /* BTA_CLOSURE_API_H */
diff --git a/bta/include/bta_dm_api.h b/bta/include/bta_dm_api.h
index 76cb618..8fdff76 100644
--- a/bta/include/bta_dm_api.h
+++ b/bta/include/bta_dm_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_dm_ci.h b/bta/include/bta_dm_ci.h
index a517da5..dbbace6 100644
--- a/bta/include/bta_dm_ci.h
+++ b/bta/include/bta_dm_ci.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_dm_co.h b/bta/include/bta_dm_co.h
index 80e99c4..ddb9d22 100644
--- a/bta/include/bta_dm_co.h
+++ b/bta/include/bta_dm_co.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index 8034dc7..4dcc76a 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2013 Broadcom Corporation
+ * Copyright 2003-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,13 +27,10 @@
#include "bta_api.h"
#include "gatt_api.h"
-#include "osi/include/list.h"
#include <base/callback_forward.h>
#include <vector>
-using std::vector;
-
#ifndef BTA_GATT_DEBUG
#define BTA_GATT_DEBUG false
#endif
@@ -46,65 +43,10 @@
**************************/
/* GATT ID */
typedef struct {
- tBT_UUID uuid; /* uuid of the attribute */
- uint8_t inst_id; /* instance ID */
+ bluetooth::Uuid uuid; /* uuid of the attribute */
+ uint8_t inst_id; /* instance ID */
} __attribute__((packed)) tBTA_GATT_ID;
-/* Success code and error codes */
-#define BTA_GATT_OK GATT_SUCCESS
-#define BTA_GATT_INVALID_HANDLE GATT_INVALID_HANDLE /* 0x0001 */
-#define BTA_GATT_READ_NOT_PERMIT GATT_READ_NOT_PERMIT /* 0x0002 */
-#define BTA_GATT_WRITE_NOT_PERMIT GATT_WRITE_NOT_PERMIT /* 0x0003 */
-#define BTA_GATT_INVALID_PDU GATT_INVALID_PDU /* 0x0004 */
-#define BTA_GATT_INSUF_AUTHENTICATION GATT_INSUF_AUTHENTICATION /* 0x0005 */
-#define BTA_GATT_REQ_NOT_SUPPORTED GATT_REQ_NOT_SUPPORTED /* 0x0006 */
-#define BTA_GATT_INVALID_OFFSET GATT_INVALID_OFFSET /* 0x0007 */
-#define BTA_GATT_INSUF_AUTHORIZATION GATT_INSUF_AUTHORIZATION /* 0x0008 */
-#define BTA_GATT_PREPARE_Q_FULL GATT_PREPARE_Q_FULL /* 0x0009 */
-#define BTA_GATT_NOT_FOUND GATT_NOT_FOUND /* 0x000a */
-#define BTA_GATT_NOT_LONG GATT_NOT_LONG /* 0x000b */
-#define BTA_GATT_INSUF_KEY_SIZE GATT_INSUF_KEY_SIZE /* 0x000c */
-#define BTA_GATT_INVALID_ATTR_LEN GATT_INVALID_ATTR_LEN /* 0x000d */
-#define BTA_GATT_ERR_UNLIKELY GATT_ERR_UNLIKELY /* 0x000e */
-#define BTA_GATT_INSUF_ENCRYPTION GATT_INSUF_ENCRYPTION /* 0x000f */
-#define BTA_GATT_UNSUPPORT_GRP_TYPE GATT_UNSUPPORT_GRP_TYPE /* 0x0010 */
-#define BTA_GATT_INSUF_RESOURCE GATT_INSUF_RESOURCE /* 0x0011 */
-
-#define BTA_GATT_NO_RESOURCES GATT_NO_RESOURCES /* 0x80 */
-#define BTA_GATT_INTERNAL_ERROR GATT_INTERNAL_ERROR /* 0x81 */
-#define BTA_GATT_WRONG_STATE GATT_WRONG_STATE /* 0x82 */
-#define BTA_GATT_DB_FULL GATT_DB_FULL /* 0x83 */
-#define BTA_GATT_BUSY GATT_BUSY /* 0x84 */
-#define BTA_GATT_ERROR GATT_ERROR /* 0x85 */
-#define BTA_GATT_CMD_STARTED GATT_CMD_STARTED /* 0x86 */
-#define BTA_GATT_ILLEGAL_PARAMETER GATT_ILLEGAL_PARAMETER /* 0x87 */
-#define BTA_GATT_PENDING GATT_PENDING /* 0x88 */
-#define BTA_GATT_AUTH_FAIL GATT_AUTH_FAIL /* 0x89 */
-#define BTA_GATT_MORE GATT_MORE /* 0x8a */
-#define BTA_GATT_INVALID_CFG GATT_INVALID_CFG /* 0x8b */
-#define BTA_GATT_SERVICE_STARTED GATT_SERVICE_STARTED /* 0x8c */
-#define BTA_GATT_ENCRYPED_MITM GATT_ENCRYPED_MITM /* GATT_SUCCESS */
-#define BTA_GATT_ENCRYPED_NO_MITM GATT_ENCRYPED_NO_MITM /* 0x8d */
-#define BTA_GATT_NOT_ENCRYPTED GATT_NOT_ENCRYPTED /* 0x8e */
-#define BTA_GATT_CONGESTED GATT_CONGESTED /* 0x8f */
-
-#define BTA_GATT_DUP_REG 0x90 /* 0x90 */
-#define BTA_GATT_ALREADY_OPEN 0x91 /* 0x91 */
-#define BTA_GATT_CANCEL 0x92 /* 0x92 */
-
-/* 0xE0 ~ 0xFC reserved for future use */
-#define BTA_GATT_CCC_CFG_ERR \
- GATT_CCC_CFG_ERR /* 0xFD Client Characteristic Configuration Descriptor \
- Improperly Configured */
-#define BTA_GATT_PRC_IN_PROGRESS \
- GATT_PRC_IN_PROGRESS /* 0xFE Procedure Already in progress */
-#define BTA_GATT_OUT_OF_RANGE \
- GATT_OUT_OF_RANGE /* 0xFFAttribute value out of range */
-
-typedef uint8_t tBTA_GATT_STATUS;
-
-#define BTA_GATT_INVALID_CONN_ID GATT_INVALID_CONN_ID
-
/* Client callback function events */
#define BTA_GATTC_DEREG_EVT 1 /* GATT client deregistered event */
#define BTA_GATTC_OPEN_EVT 2 /* GATTC open request status event */
@@ -124,8 +66,6 @@
typedef uint8_t tBTA_GATTC_EVT;
-typedef tGATT_IF tBTA_GATTC_IF;
-
typedef struct {
uint16_t unit; /* as UUIUD defined by SIG */
uint16_t descr; /* as UUID as defined by SIG */
@@ -134,52 +74,19 @@
uint8_t name_spc; /* The name space of the description */
} tBTA_GATT_CHAR_PRES;
-#define BTA_GATT_CLT_CONFIG_NONE GATT_CLT_CONFIG_NONE /* 0x0000 */
-#define BTA_GATT_CLT_CONFIG_NOTIFICATION \
- GATT_CLT_CONFIG_NOTIFICATION /* 0x0001 */
-#define BTA_GATT_CLT_CONFIG_INDICATION GATT_CLT_CONFIG_INDICATION /* 0x0002 */
-typedef uint16_t tBTA_GATT_CLT_CHAR_CONFIG;
-
-/* characteristic descriptor: server configuration value
-*/
-#define BTA_GATT_SVR_CONFIG_NONE GATT_SVR_CONFIG_NONE /* 0x0000 */
-#define BTA_GATT_SVR_CONFIG_BROADCAST GATT_SVR_CONFIG_BROADCAST /* 0x0001 */
-typedef uint16_t tBTA_GATT_SVR_CHAR_CONFIG;
-
/* Characteristic Aggregate Format attribute value
-*/
+ */
#define BTA_GATT_AGGR_HANDLE_NUM_MAX 10
typedef struct {
uint8_t num_handle;
uint16_t handle_list[BTA_GATT_AGGR_HANDLE_NUM_MAX];
} tBTA_GATT_CHAR_AGGRE;
-typedef tGATT_VALID_RANGE tBTA_GATT_VALID_RANGE;
typedef struct {
uint16_t len;
uint8_t* p_value;
} tBTA_GATT_UNFMT;
-#define BTA_GATT_MAX_ATTR_LEN GATT_MAX_ATTR_LEN
-
-#define BTA_GATTC_TYPE_WRITE GATT_WRITE
-#define BTA_GATTC_TYPE_WRITE_NO_RSP GATT_WRITE_NO_RSP
-typedef uint8_t tBTA_GATTC_WRITE_TYPE;
-
-#define BTA_GATT_CONN_UNKNOWN 0
-#define BTA_GATT_CONN_L2C_FAILURE \
- GATT_CONN_L2C_FAILURE /* general l2cap resource failure */
-#define BTA_GATT_CONN_TIMEOUT GATT_CONN_TIMEOUT /* 0x08 connection timeout */
-#define BTA_GATT_CONN_TERMINATE_PEER_USER \
- GATT_CONN_TERMINATE_PEER_USER /* 0x13 connection terminate by peer user */
-#define BTA_GATT_CONN_TERMINATE_LOCAL_HOST \
- GATT_CONN_TERMINATE_LOCAL_HOST /* 0x16 connectionterminated by local host */
-#define BTA_GATT_CONN_FAIL_ESTABLISH \
- GATT_CONN_FAIL_ESTABLISH /* 0x03E connection fail to establish */
-#define BTA_GATT_CONN_LMP_TIMEOUT \
- GATT_CONN_LMP_TIMEOUT /* 0x22 connection fail for LMP response tout */
-#define BTA_GATT_CONN_CANCEL \
- GATT_CONN_CANCEL /* 0x0100 L2CAP connection cancelled */
#define BTA_GATT_CONN_NONE 0x0101 /* 0x0101 no connection to cancel */
typedef uint16_t tBTA_GATT_REASON;
@@ -190,17 +97,6 @@
uint16_t handles[BTA_GATTC_MULTI_MAX];
} tBTA_GATTC_MULTI;
-#define BTA_GATT_AUTH_REQ_NONE GATT_AUTH_REQ_NONE
-#define BTA_GATT_AUTH_REQ_NO_MITM \
- GATT_AUTH_REQ_NO_MITM /* unauthenticated encryption */
-#define BTA_GATT_AUTH_REQ_MITM \
- GATT_AUTH_REQ_MITM /* authenticated encryption \
- */
-#define BTA_GATT_AUTH_REQ_SIGNED_NO_MITM GATT_AUTH_REQ_SIGNED_NO_MITM
-#define BTA_GATT_AUTH_REQ_SIGNED_MITM GATT_AUTH_REQ_SIGNED_MITM
-
-typedef tGATT_AUTH_REQ tBTA_GATT_AUTH_REQ;
-
enum {
BTA_GATTC_ATTR_TYPE_INCL_SRVC,
BTA_GATTC_ATTR_TYPE_CHAR,
@@ -210,7 +106,7 @@
typedef uint8_t tBTA_GATTC_ATTR_TYPE;
typedef struct {
- tBT_UUID uuid;
+ bluetooth::Uuid uuid;
uint16_t s_handle;
uint16_t e_handle; /* used for service only */
uint8_t attr_type;
@@ -222,33 +118,32 @@
/* callback data structure */
typedef struct {
- tBTA_GATT_STATUS status;
- tBTA_GATTC_IF client_if;
- tBT_UUID app_uuid;
+ tGATT_STATUS status;
+ tGATT_IF client_if;
} tBTA_GATTC_REG;
typedef struct {
uint16_t conn_id;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
uint16_t handle;
uint16_t len;
- uint8_t value[BTA_GATT_MAX_ATTR_LEN];
+ uint8_t value[GATT_MAX_ATTR_LEN];
} tBTA_GATTC_READ;
typedef struct {
uint16_t conn_id;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
uint16_t handle;
} tBTA_GATTC_WRITE;
typedef struct {
uint16_t conn_id;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
} tBTA_GATTC_EXEC_CMPL;
typedef struct {
uint16_t conn_id;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
} tBTA_GATTC_SEARCH_CMPL;
typedef struct {
@@ -258,23 +153,23 @@
typedef struct {
uint16_t conn_id;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
uint16_t mtu;
} tBTA_GATTC_CFG_MTU;
typedef struct {
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
uint16_t conn_id;
- tBTA_GATTC_IF client_if;
+ tGATT_IF client_if;
RawAddress remote_bda;
tBTA_TRANSPORT transport;
uint16_t mtu;
} tBTA_GATTC_OPEN;
typedef struct {
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
uint16_t conn_id;
- tBTA_GATTC_IF client_if;
+ tGATT_IF client_if;
RawAddress remote_bda;
tBTA_GATT_REASON reason; /* disconnect reason code, not useful when connect
event is reported */
@@ -285,7 +180,7 @@
RawAddress bda;
uint16_t handle;
uint16_t len;
- uint8_t value[BTA_GATT_MAX_ATTR_LEN];
+ uint8_t value[GATT_MAX_ATTR_LEN];
bool is_notify;
} tBTA_GATTC_NOTIFY;
@@ -295,36 +190,36 @@
} tBTA_GATTC_CONGEST;
typedef struct {
- tBTA_GATT_STATUS status;
- tBTA_GATTC_IF client_if;
+ tGATT_STATUS status;
+ tGATT_IF client_if;
uint16_t conn_id;
RawAddress remote_bda;
} tBTA_GATTC_OPEN_CLOSE;
typedef struct {
- tBTA_GATTC_IF client_if;
+ tGATT_IF client_if;
RawAddress remote_bda;
} tBTA_GATTC_ENC_CMPL_CB;
typedef struct {
- tBTA_GATTC_IF server_if;
+ tGATT_IF server_if;
uint16_t conn_id;
uint8_t tx_phy;
uint8_t rx_phy;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
} tBTA_GATTC_PHY_UPDATE;
typedef struct {
- tBTA_GATTC_IF server_if;
+ tGATT_IF server_if;
uint16_t conn_id;
uint16_t interval;
uint16_t latency;
uint16_t timeout;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
} tBTA_GATTC_CONN_UPDATE;
typedef union {
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
tBTA_GATTC_SEARCH_CMPL search_cmpl; /* discovery complete */
tBTA_GATTC_SRVC_RES srvc_res; /* discovery result */
@@ -344,7 +239,7 @@
} tBTA_GATTC;
/* GATTC enable callback function */
-typedef void(tBTA_GATTC_ENB_CBACK)(tBTA_GATT_STATUS status);
+typedef void(tBTA_GATTC_ENB_CBACK)(tGATT_STATUS status);
/* Client callback function */
typedef void(tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
@@ -374,130 +269,61 @@
#define BTA_GATTS_CONN_UPDATE_EVT 22
typedef uint8_t tBTA_GATTS_EVT;
-typedef tGATT_IF tBTA_GATTS_IF;
-
-/* Attribute permissions
-*/
-#define BTA_GATT_PERM_READ GATT_PERM_READ /* bit 0 - 0x0001 */
-#define BTA_GATT_PERM_READ_ENCRYPTED \
- GATT_PERM_READ_ENCRYPTED /* bit 1 - 0x0002 */
-#define BTA_GATT_PERM_READ_ENC_MITM \
- GATT_PERM_READ_ENC_MITM /* bit 2 - 0x0004 */
-#define BTA_GATT_PERM_WRITE GATT_PERM_WRITE /* bit 4 - 0x0010 */
-#define BTA_GATT_PERM_WRITE_ENCRYPTED \
- GATT_PERM_WRITE_ENCRYPTED /* bit 5 - 0x0020 */
-#define BTA_GATT_PERM_WRITE_ENC_MITM \
- GATT_PERM_WRITE_ENC_MITM /* bit 6 - 0x0040 */
-#define BTA_GATT_PERM_WRITE_SIGNED \
- GATT_PERM_WRITE_SIGNED /* bit 7 - 0x0080 \
- */
-#define BTA_GATT_PERM_WRITE_SIGNED_MITM \
- GATT_PERM_WRITE_SIGNED_MITM /* bit 8 - 0x0100 */
-typedef uint16_t tBTA_GATT_PERM;
#define BTA_GATTS_INVALID_APP 0xff
#define BTA_GATTS_INVALID_IF 0
-/* definition of characteristic properties */
-#define BTA_GATT_CHAR_PROP_BIT_BROADCAST \
- GATT_CHAR_PROP_BIT_BROADCAST /* 0x01 \
- */
-#define BTA_GATT_CHAR_PROP_BIT_READ GATT_CHAR_PROP_BIT_READ /* 0x02 */
-#define BTA_GATT_CHAR_PROP_BIT_WRITE_NR GATT_CHAR_PROP_BIT_WRITE_NR /* 0x04 */
-#define BTA_GATT_CHAR_PROP_BIT_WRITE GATT_CHAR_PROP_BIT_WRITE /* 0x08 */
-#define BTA_GATT_CHAR_PROP_BIT_NOTIFY GATT_CHAR_PROP_BIT_NOTIFY /* 0x10 */
-#define BTA_GATT_CHAR_PROP_BIT_INDICATE GATT_CHAR_PROP_BIT_INDICATE /* 0x20 */
-#define BTA_GATT_CHAR_PROP_BIT_AUTH GATT_CHAR_PROP_BIT_AUTH /* 0x40 */
-#define BTA_GATT_CHAR_PROP_BIT_EXT_PROP GATT_CHAR_PROP_BIT_EXT_PROP /* 0x80 */
-typedef uint8_t tBTA_GATT_CHAR_PROP;
-
#ifndef BTA_GATTC_CHAR_DESCR_MAX
#define BTA_GATTC_CHAR_DESCR_MAX 7
#endif
/*********************** NV callback Data Definitions **********************
-*/
+ */
typedef struct {
- tBT_UUID app_uuid128;
- tBT_UUID svc_uuid;
+ bluetooth::Uuid app_uuid128;
+ bluetooth::Uuid svc_uuid;
uint16_t svc_inst;
uint16_t s_handle;
uint16_t e_handle;
bool is_primary; /* primary service or secondary */
} tBTA_GATTS_HNDL_RANGE;
-#define BTA_GATTS_SRV_CHG_CMD_ADD_CLIENT GATTS_SRV_CHG_CMD_ADD_CLIENT
-#define BTA_GATTS_SRV_CHG_CMD_UPDATE_CLIENT GATTS_SRV_CHG_CMD_UPDATE_CLIENT
-#define BTA_GATTS_SRV_CHG_CMD_REMOVE_CLIENT GATTS_SRV_CHG_CMD_REMOVE_CLIENT
-#define BTA_GATTS_SRV_CHG_CMD_READ_NUM_CLENTS GATTS_SRV_CHG_CMD_READ_NUM_CLENTS
-#define BTA_GATTS_SRV_CHG_CMD_READ_CLENT GATTS_SRV_CHG_CMD_READ_CLENT
-typedef tGATTS_SRV_CHG_CMD tBTA_GATTS_SRV_CHG_CMD;
-
-typedef tGATTS_SRV_CHG tBTA_GATTS_SRV_CHG;
-typedef tGATTS_SRV_CHG_REQ tBTA_GATTS_SRV_CHG_REQ;
-typedef tGATTS_SRV_CHG_RSP tBTA_GATTS_SRV_CHG_RSP;
-
-#define BTA_GATT_TRANSPORT_LE GATT_TRANSPORT_LE
-#define BTA_GATT_TRANSPORT_BR_EDR GATT_TRANSPORT_BR_EDR
-#define BTA_GATT_TRANSPORT_LE_BR_EDR GATT_TRANSPORT_LE_BR_EDR
-typedef uint8_t tBTA_GATT_TRANSPORT;
-
-/* attribute value */
-typedef tGATT_VALUE tBTA_GATT_VALUE;
-
-/* attribute response data */
-typedef tGATTS_RSP tBTA_GATTS_RSP;
-
-/* attribute request data from the client */
-#define BTA_GATT_PREP_WRITE_CANCEL 0x00
-#define BTA_GATT_PREP_WRITE_EXEC 0x01
-typedef tGATT_EXEC_FLAG tBTA_GATT_EXEC_FLAG;
-
-/* read request always based on UUID */
-typedef tGATT_READ_REQ tTA_GBATT_READ_REQ;
-
-/* write request data */
-typedef tGATT_WRITE_REQ tBTA_GATT_WRITE_REQ;
-
-/* callback data for server access request from client */
-typedef tGATTS_DATA tBTA_GATTS_REQ_DATA;
-
typedef struct {
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
RawAddress remote_bda;
uint32_t trans_id;
uint16_t conn_id;
- tBTA_GATTS_REQ_DATA* p_data;
+ tGATTS_DATA* p_data;
} tBTA_GATTS_REQ;
typedef struct {
- tBTA_GATTS_IF server_if;
- tBTA_GATT_STATUS status;
- tBT_UUID uuid;
+ tGATT_IF server_if;
+ tGATT_STATUS status;
+ bluetooth::Uuid uuid;
} tBTA_GATTS_REG_OPER;
typedef struct {
- tBTA_GATTS_IF server_if;
+ tGATT_IF server_if;
uint16_t service_id;
uint16_t svc_instance;
bool is_primary;
- tBTA_GATT_STATUS status;
- tBT_UUID uuid;
+ tGATT_STATUS status;
+ bluetooth::Uuid uuid;
} tBTA_GATTS_CREATE;
typedef struct {
- tBTA_GATTS_IF server_if;
+ tGATT_IF server_if;
uint16_t service_id;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
} tBTA_GATTS_SRVC_OPER;
typedef struct {
- tBTA_GATTS_IF server_if;
+ tGATT_IF server_if;
RawAddress remote_bda;
uint16_t conn_id;
tBTA_GATT_REASON reason; /* report disconnect reason */
- tBTA_GATT_TRANSPORT transport;
+ tGATT_TRANSPORT transport;
} tBTA_GATTS_CONN;
typedef struct {
@@ -507,24 +333,24 @@
typedef struct {
uint16_t conn_id; /* connection ID */
- tBTA_GATT_STATUS status; /* notification/indication status */
+ tGATT_STATUS status; /* notification/indication status */
} tBTA_GATTS_CONF;
typedef struct {
- tBTA_GATTS_IF server_if;
+ tGATT_IF server_if;
uint16_t conn_id;
uint8_t tx_phy;
uint8_t rx_phy;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
} tBTA_GATTS_PHY_UPDATE;
typedef struct {
- tBTA_GATTS_IF server_if;
+ tGATT_IF server_if;
uint16_t conn_id;
uint16_t interval;
uint16_t latency;
uint16_t timeout;
- tBTA_GATT_STATUS status;
+ tGATT_STATUS status;
} tBTA_GATTS_CONN_UPDATE;
/* GATTS callback data */
@@ -532,52 +358,56 @@
tBTA_GATTS_REG_OPER reg_oper;
tBTA_GATTS_CREATE create;
tBTA_GATTS_SRVC_OPER srvc_oper;
- tBTA_GATT_STATUS status; /* BTA_GATTS_LISTEN_EVT */
+ tGATT_STATUS status; /* BTA_GATTS_LISTEN_EVT */
tBTA_GATTS_REQ req_data;
- tBTA_GATTS_CONN conn; /* BTA_GATTS_CONN_EVT */
- tBTA_GATTS_CONGEST congest; /* BTA_GATTS_CONGEST_EVT callback data */
- tBTA_GATTS_CONF confirm; /* BTA_GATTS_CONF_EVT callback data */
+ tBTA_GATTS_CONN conn; /* BTA_GATTS_CONN_EVT */
+ tBTA_GATTS_CONGEST congest; /* BTA_GATTS_CONGEST_EVT callback data */
+ tBTA_GATTS_CONF confirm; /* BTA_GATTS_CONF_EVT callback data */
tBTA_GATTS_PHY_UPDATE phy_update; /* BTA_GATTS_PHY_UPDATE_EVT callback data */
tBTA_GATTS_CONN_UPDATE
conn_update; /* BTA_GATTS_CONN_UPDATE_EVT callback data */
} tBTA_GATTS;
/* GATTS enable callback function */
-typedef void(tBTA_GATTS_ENB_CBACK)(tBTA_GATT_STATUS status);
+typedef void(tBTA_GATTS_ENB_CBACK)(tGATT_STATUS status);
/* Server callback function */
typedef void(tBTA_GATTS_CBACK)(tBTA_GATTS_EVT event, tBTA_GATTS* p_data);
-typedef struct {
- tBT_UUID uuid;
+struct tBTA_GATTC_CHARACTERISTIC;
+struct tBTA_GATTC_DESCRIPTOR;
+struct tBTA_GATTC_INCLUDED_SVC;
+
+struct tBTA_GATTC_SERVICE {
+ bluetooth::Uuid uuid;
bool is_primary;
uint16_t handle;
uint16_t s_handle;
uint16_t e_handle;
- list_t* characteristics; /* list of tBTA_GATTC_CHARACTERISTIC */
- list_t* included_svc; /* list of tBTA_GATTC_INCLUDED_SVC */
-} __attribute__((packed, aligned(alignof(tBT_UUID)))) tBTA_GATTC_SERVICE;
+ std::vector<tBTA_GATTC_CHARACTERISTIC> characteristics;
+ std::vector<tBTA_GATTC_INCLUDED_SVC> included_svc;
+};
-typedef struct {
- tBT_UUID uuid;
+struct tBTA_GATTC_CHARACTERISTIC {
+ bluetooth::Uuid uuid;
+ // this is used only during discovery, and not persisted in cache
+ uint16_t declaration_handle;
+ uint16_t value_handle;
+ tGATT_CHAR_PROP properties;
+ std::vector<tBTA_GATTC_DESCRIPTOR> descriptors;
+};
+
+struct tBTA_GATTC_DESCRIPTOR {
+ bluetooth::Uuid uuid;
uint16_t handle;
- tBTA_GATT_CHAR_PROP properties;
- tBTA_GATTC_SERVICE* service; /* owning service*/
- list_t* descriptors; /* list of tBTA_GATTC_DESCRIPTOR */
-} __attribute__((packed, aligned(alignof(tBT_UUID)))) tBTA_GATTC_CHARACTERISTIC;
+};
-typedef struct {
- tBT_UUID uuid;
- uint16_t handle;
- tBTA_GATTC_CHARACTERISTIC* characteristic; /* owning characteristic */
-} __attribute__((packed)) tBTA_GATTC_DESCRIPTOR;
-
-typedef struct {
- tBT_UUID uuid;
+struct tBTA_GATTC_INCLUDED_SVC {
+ bluetooth::Uuid uuid;
uint16_t handle;
tBTA_GATTC_SERVICE* owning_service; /* owning service*/
tBTA_GATTC_SERVICE* included_service;
-} __attribute__((packed)) tBTA_GATTC_INCLUDED_SVC;
+};
/*****************************************************************************
* External Function Declarations
@@ -623,7 +453,7 @@
* Returns None
*
******************************************************************************/
-extern void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if);
+extern void BTA_GATTC_AppDeregister(tGATT_IF client_if);
/*******************************************************************************
*
@@ -638,13 +468,12 @@
* initiating_phys: LE PHY to use, optional
*
******************************************************************************/
-extern void BTA_GATTC_Open(tBTA_GATTC_IF client_if,
- const RawAddress& remote_bda, bool is_direct,
- tBTA_GATT_TRANSPORT transport, bool opportunistic);
-extern void BTA_GATTC_Open(tBTA_GATTC_IF client_if,
- const RawAddress& remote_bda, bool is_direct,
- tBTA_GATT_TRANSPORT transport, bool opportunistic,
- uint8_t initiating_phys);
+extern void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda,
+ bool is_direct, tGATT_TRANSPORT transport,
+ bool opportunistic);
+extern void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda,
+ bool is_direct, tGATT_TRANSPORT transport,
+ bool opportunistic, uint8_t initiating_phys);
/*******************************************************************************
*
@@ -660,7 +489,7 @@
* Returns void
*
******************************************************************************/
-extern void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if,
+extern void BTA_GATTC_CancelOpen(tGATT_IF client_if,
const RawAddress& remote_bda, bool is_direct);
/*******************************************************************************
@@ -693,14 +522,14 @@
*
******************************************************************************/
extern void BTA_GATTC_ServiceSearchRequest(uint16_t conn_id,
- tBT_UUID* p_srvc_uuid);
+ bluetooth::Uuid* p_srvc_uuid);
/**
* This function is called to send "Find service by UUID" request. Used only for
* PTS tests.
*/
extern void BTA_GATTC_DiscoverServiceByUuid(uint16_t conn_id,
- tBT_UUID* p_srvc_uuid);
+ const bluetooth::Uuid& p_srvc_uuid);
/*******************************************************************************
*
@@ -711,10 +540,11 @@
*
* Parameters conn_id: connection ID which identify the server.
*
- * Returns returns list_t of tBTA_GATTC_SERVICE or NULL.
+ * Returns returns list of tBTA_GATTC_SERVICE or NULL.
*
******************************************************************************/
-extern const list_t* BTA_GATTC_GetServices(uint16_t conn_id);
+extern const std::vector<tBTA_GATTC_SERVICE>* BTA_GATTC_GetServices(
+ uint16_t conn_id);
/*******************************************************************************
*
@@ -748,6 +578,16 @@
extern const tBTA_GATTC_DESCRIPTOR* BTA_GATTC_GetDescriptor(uint16_t conn_id,
uint16_t handle);
+/* Return characteristic that owns descriptor with handle equal to |handle|, or
+ * NULL */
+extern const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetOwningCharacteristic(
+ uint16_t conn_id, uint16_t handle);
+
+/* Return service that owns descriptor or characteristic with handle equal to
+ * |handle|, or NULL */
+extern const tBTA_GATTC_SERVICE* BTA_GATTC_GetOwningService(uint16_t conn_id,
+ uint16_t handle);
+
/*******************************************************************************
*
* Function BTA_GATTC_GetGattDb
@@ -783,16 +623,16 @@
*
******************************************************************************/
void BTA_GATTC_ReadCharacteristic(uint16_t conn_id, uint16_t handle,
- tBTA_GATT_AUTH_REQ auth_req,
+ tGATT_AUTH_REQ auth_req,
GATT_READ_OP_CB callback, void* cb_data);
/**
* This function is called to read a value of characteristic with uuid equal to
* |uuid|
*/
-void BTA_GATTC_ReadUsingCharUuid(uint16_t conn_id, tBT_UUID uuid,
+void BTA_GATTC_ReadUsingCharUuid(uint16_t conn_id, const bluetooth::Uuid& uuid,
uint16_t s_handle, uint16_t e_handle,
- tBTA_GATT_AUTH_REQ auth_req,
+ tGATT_AUTH_REQ auth_req,
GATT_READ_OP_CB callback, void* cb_data);
/*******************************************************************************
@@ -808,8 +648,8 @@
*
******************************************************************************/
void BTA_GATTC_ReadCharDescr(uint16_t conn_id, uint16_t handle,
- tBTA_GATT_AUTH_REQ auth_req,
- GATT_READ_OP_CB callback, void* cb_data);
+ tGATT_AUTH_REQ auth_req, GATT_READ_OP_CB callback,
+ void* cb_data);
/*******************************************************************************
*
@@ -826,9 +666,9 @@
*
******************************************************************************/
void BTA_GATTC_WriteCharValue(uint16_t conn_id, uint16_t handle,
- tBTA_GATTC_WRITE_TYPE write_type,
- vector<uint8_t> value,
- tBTA_GATT_AUTH_REQ auth_req,
+ tGATT_WRITE_TYPE write_type,
+ std::vector<uint8_t> value,
+ tGATT_AUTH_REQ auth_req,
GATT_WRITE_OP_CB callback, void* cb_data);
/*******************************************************************************
@@ -845,8 +685,8 @@
*
******************************************************************************/
void BTA_GATTC_WriteCharDescr(uint16_t conn_id, uint16_t handle,
- vector<uint8_t> value,
- tBTA_GATT_AUTH_REQ auth_req,
+ std::vector<uint8_t> value,
+ tGATT_AUTH_REQ auth_req,
GATT_WRITE_OP_CB callback, void* cb_data);
/*******************************************************************************
@@ -877,8 +717,8 @@
* Returns OK if registration succeed, otherwise failed.
*
******************************************************************************/
-extern tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications(
- tBTA_GATTC_IF client_if, const RawAddress& remote_bda, uint16_t handle);
+extern tGATT_STATUS BTA_GATTC_RegisterForNotifications(
+ tGATT_IF client_if, const RawAddress& remote_bda, uint16_t handle);
/*******************************************************************************
*
@@ -894,8 +734,8 @@
* Returns OK if deregistration succeed, otherwise failed.
*
******************************************************************************/
-extern tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications(
- tBTA_GATTC_IF client_if, const RawAddress& remote_bda, uint16_t handle);
+extern tGATT_STATUS BTA_GATTC_DeregisterForNotifications(
+ tGATT_IF client_if, const RawAddress& remote_bda, uint16_t handle);
/*******************************************************************************
*
@@ -913,8 +753,8 @@
*
******************************************************************************/
extern void BTA_GATTC_PrepareWrite(uint16_t conn_id, uint16_t handle,
- uint16_t offset, vector<uint8_t> value,
- tBTA_GATT_AUTH_REQ auth_req,
+ uint16_t offset, std::vector<uint8_t> value,
+ tGATT_AUTH_REQ auth_req,
GATT_WRITE_OP_CB callback, void* cb_data);
/*******************************************************************************
@@ -947,7 +787,7 @@
******************************************************************************/
extern void BTA_GATTC_ReadMultiple(uint16_t conn_id,
tBTA_GATTC_MULTI* p_read_multi,
- tBTA_GATT_AUTH_REQ auth_req);
+ tGATT_AUTH_REQ auth_req);
/*******************************************************************************
*
@@ -1020,7 +860,7 @@
* Returns None
*
******************************************************************************/
-extern void BTA_GATTS_AppRegister(tBT_UUID* p_app_uuid,
+extern void BTA_GATTS_AppRegister(const bluetooth::Uuid& app_uuid,
tBTA_GATTS_CBACK* p_cback);
/*******************************************************************************
@@ -1034,7 +874,7 @@
* Returns void
*
******************************************************************************/
-extern void BTA_GATTS_AppDeregister(tBTA_GATTS_IF server_if);
+extern void BTA_GATTS_AppDeregister(tGATT_IF server_if);
/*******************************************************************************
*
@@ -1047,12 +887,17 @@
* Parameters server_if: server interface.
* service: pointer to vector describing service.
*
- * Returns Returns |BTA_GATT_OK| on success or |BTA_GATT_ERROR| if the
+ * Returns Returns |GATT_SUCCESS| on success or |GATT_ERROR| if the
* service cannot be added.
*
******************************************************************************/
-extern uint16_t BTA_GATTS_AddService(tBTA_GATTS_IF server_if,
- vector<btgatt_db_element_t>& service);
+typedef base::Callback<void(uint8_t status, int server_if,
+ std::vector<btgatt_db_element_t> service)>
+ BTA_GATTS_AddServiceCb;
+
+extern void BTA_GATTS_AddService(tGATT_IF server_if,
+ std::vector<btgatt_db_element_t> service,
+ BTA_GATTS_AddServiceCb cb);
/*******************************************************************************
*
@@ -1099,7 +944,7 @@
*
******************************************************************************/
extern void BTA_GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_id,
- vector<uint8_t> value,
+ std::vector<uint8_t> value,
bool need_confirm);
/*******************************************************************************
@@ -1117,7 +962,7 @@
*
******************************************************************************/
extern void BTA_GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id,
- tBTA_GATT_STATUS status, tBTA_GATTS_RSP* p_msg);
+ tGATT_STATUS status, tGATTS_RSP* p_msg);
/*******************************************************************************
*
@@ -1133,9 +978,8 @@
* Returns void
*
******************************************************************************/
-extern void BTA_GATTS_Open(tBTA_GATTS_IF server_if,
- const RawAddress& remote_bda, bool is_direct,
- tBTA_GATT_TRANSPORT transport);
+extern void BTA_GATTS_Open(tGATT_IF server_if, const RawAddress& remote_bda,
+ bool is_direct, tGATT_TRANSPORT transport);
/*******************************************************************************
*
@@ -1151,7 +995,7 @@
* Returns void
*
******************************************************************************/
-extern void BTA_GATTS_CancelOpen(tBTA_GATTS_IF server_if,
+extern void BTA_GATTS_CancelOpen(tGATT_IF server_if,
const RawAddress& remote_bda, bool is_direct);
/*******************************************************************************
diff --git a/bta/include/bta_gatt_queue.h b/bta/include/bta_gatt_queue.h
new file mode 100644
index 0000000..963fc13
--- /dev/null
+++ b/bta/include/bta_gatt_queue.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+
+#include <list>
+#include <unordered_map>
+#include <unordered_set>
+#include "bta_gatt_api.h"
+
+/* BTA GATTC implementation does not allow for multiple commands queuing. So one
+ * client making calls to BTA_GATTC_ReadCharacteristic, BTA_GATTC_ReadCharDescr,
+ * BTA_GATTC_WriteCharValue, BTA_GATTC_WriteCharDescr must wait for the callacks
+ * before scheduling next operation.
+ *
+ * Methods below can be used as replacement to BTA_GATTC_* in BTA app. They do
+ * queue the commands if another command is currently being executed.
+ *
+ * If you decide to use those methods in your app, make sure to not mix it with
+ * existing BTA_GATTC_* API.
+ */
+class BtaGattQueue {
+ public:
+ static void Clean(uint16_t conn_id);
+ static void ReadCharacteristic(uint16_t conn_id, uint16_t handle,
+ GATT_READ_OP_CB cb, void* cb_data);
+ static void ReadDescriptor(uint16_t conn_id, uint16_t handle,
+ GATT_READ_OP_CB cb, void* cb_data);
+ static void WriteCharacteristic(uint16_t conn_id, uint16_t handle,
+ std::vector<uint8_t> value,
+ tGATT_WRITE_TYPE write_type,
+ GATT_WRITE_OP_CB cb, void* cb_data);
+ static void WriteDescriptor(uint16_t conn_id, uint16_t handle,
+ std::vector<uint8_t> value,
+ tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
+ void* cb_data);
+
+ /* Holds pending GATT operations */
+ struct gatt_operation {
+ uint8_t type;
+ uint16_t handle;
+ GATT_READ_OP_CB read_cb;
+ void* read_cb_data;
+ GATT_WRITE_OP_CB write_cb;
+ void* write_cb_data;
+
+ /* write-specific fields */
+ tGATT_WRITE_TYPE write_type;
+ std::vector<uint8_t> value;
+ };
+
+ private:
+ static void mark_as_not_executing(uint16_t conn_id);
+ static void gatt_execute_next_op(uint16_t conn_id);
+ static void gatt_read_op_finished(uint16_t conn_id, tGATT_STATUS status,
+ uint16_t handle, uint16_t len,
+ uint8_t* value, void* data);
+ static void gatt_write_op_finished(uint16_t conn_id, tGATT_STATUS status,
+ uint16_t handle, void* data);
+
+ // maps connection id to operations waiting for execution
+ static std::unordered_map<uint16_t, std::list<gatt_operation>> gatt_op_queue;
+ // contain connection ids that currently execute operations
+ static std::unordered_set<uint16_t> gatt_op_queue_executing;
+};
\ No newline at end of file
diff --git a/bta/include/bta_gatts_co.h b/bta/include/bta_gatts_co.h
index bf8277f..eb820f7 100644
--- a/bta/include/bta_gatts_co.h
+++ b/bta/include/bta_gatts_co.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2010-2012 Broadcom Corporation
+ * Copyright 2010-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,9 +60,9 @@
* false - if the request can not be processed
*
******************************************************************************/
-extern bool bta_gatts_co_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
- tBTA_GATTS_SRV_CHG_REQ* p_req,
- tBTA_GATTS_SRV_CHG_RSP* p_rsp);
+extern bool bta_gatts_co_srv_chg(tGATTS_SRV_CHG_CMD cmd,
+ tGATTS_SRV_CHG_REQ* p_req,
+ tGATTS_SRV_CHG_RSP* p_rsp);
/*******************************************************************************
*
diff --git a/bta/include/bta_hd_api.h b/bta/include/bta_hd_api.h
index 31cb7a0..2bb78f1 100644
--- a/bta/include/bta_hd_api.h
+++ b/bta/include/bta_hd_api.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_hearing_aid_api.h b/bta/include/bta_hearing_aid_api.h
new file mode 100644
index 0000000..96ad7e6
--- /dev/null
+++ b/bta/include/bta_hearing_aid_api.h
@@ -0,0 +1,90 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <base/callback_forward.h>
+#include <hardware/bt_hearing_aid.h>
+
+
+/** Implementations of HearingAid will also implement this interface */
+class HearingAidAudioReceiver {
+ public:
+ virtual ~HearingAidAudioReceiver() = default;
+ virtual void OnAudioDataReady(const std::vector<uint8_t>& data) = 0;
+ virtual void OnAudioSuspend();
+ virtual void OnAudioResume();
+};
+
+class HearingAid {
+ public:
+ virtual ~HearingAid() = default;
+
+ static void Initialize(bluetooth::hearing_aid::HearingAidCallbacks* callbacks,
+ base::Closure initCb);
+ static void CleanUp();
+ static bool IsInitialized();
+ static HearingAid* Get();
+ static void DebugDump(int fd);
+
+ static void AddFromStorage(const RawAddress& address, uint16_t psm,
+ uint8_t capabilities, uint16_t codec,
+ uint16_t audioControlPointHandle,
+ uint16_t volumeHandle, uint64_t hiSyncId,
+ uint16_t render_delay, uint16_t preparation_delay,
+ uint16_t is_white_listed);
+
+ static int GetDeviceCount();
+
+ virtual void Connect(const RawAddress& address) = 0;
+ virtual void Disconnect(const RawAddress& address) = 0;
+ virtual void SetVolume(int8_t volume) = 0;
+};
+
+/* Represents configuration of audio codec, as exchanged between hearing aid and
+ * phone.
+ * It can also be passed to the audio source to configure its parameters.
+ */
+struct CodecConfiguration {
+ /** sampling rate that the codec expects to receive from audio framework */
+ uint32_t sample_rate;
+
+ /** bitrate that codec expects to receive from audio framework in bits per
+ * channel */
+ uint32_t bit_rate;
+
+ /** Data interval determines how often we send samples to the remote. This
+ * should match how often we grab data from audio source, optionally we can
+ * grab data every 2 or 3 intervals, but this would increase latency.
+ *
+ * Value is provided in ms, must be divisable by 1.25 to make sure the
+ * connection interval is integer.
+ */
+ uint16_t data_interval_ms;
+};
+
+/** Represents source of audio for hearing aids */
+class HearingAidAudioSource {
+ public:
+ static void Start(const CodecConfiguration& codecConfiguration,
+ HearingAidAudioReceiver* audioReceiver);
+ static void Stop();
+ static void Initialize();
+ static void CleanUp();
+ static void DebugDump(int fd);
+};
diff --git a/bta/include/bta_hf_client_api.h b/bta/include/bta_hf_client_api.h
index 5d725e7..69dc109 100644
--- a/bta/include/bta_hf_client_api.h
+++ b/bta/include/bta_hf_client_api.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_hh_api.h b/bta/include/bta_hh_api.h
index 6960d6f..9198b46 100644
--- a/bta/include/bta_hh_api.h
+++ b/bta/include/bta_hh_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -79,8 +79,13 @@
#if (BTA_HH_LE_INCLUDED == TRUE)
/* GATT_MAX_PHY_CHANNEL can not exceed 14 for the design of BTA HH */
+#if GATT_MAX_PHY_CHANNEL > 14
+#define BTA_HH_LE_MAX_KNOWN 14
+#else
#define BTA_HH_LE_MAX_KNOWN GATT_MAX_PHY_CHANNEL
-#define BTA_HH_MAX_DEVICE (HID_HOST_MAX_DEVICES + GATT_MAX_PHY_CHANNEL)
+#endif
+
+#define BTA_HH_MAX_DEVICE (HID_HOST_MAX_DEVICES + BTA_HH_LE_MAX_KNOWN)
#else
#define BTA_HH_MAX_DEVICE HID_HOST_MAX_DEVICES
#endif
diff --git a/bta/include/bta_hh_co.h b/bta/include/bta_hh_co.h
index 7781d00..da884bc 100644
--- a/bta/include/bta_hh_co.h
+++ b/bta/include/bta_hh_co.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2005-2012 Broadcom Corporation
+ * Copyright 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_hl_api.h b/bta/include/bta_hl_api.h
index 414d42d..12532d7 100644
--- a/bta/include/bta_hl_api.h
+++ b/bta/include/bta_hl_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_hl_ci.h b/bta/include/bta_hl_ci.h
index ad1499f..73a7cd4 100644
--- a/bta/include/bta_hl_ci.h
+++ b/bta/include/bta_hl_ci.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_hl_co.h b/bta/include/bta_hl_co.h
index 82b6243..9a36911 100644
--- a/bta/include/bta_hl_co.h
+++ b/bta/include/bta_hl_co.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_jv_api.h b/bta/include/bta_jv_api.h
index 54824c4..39f72fd 100644
--- a/bta/include/bta_jv_api.h
+++ b/bta/include/bta_jv_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -246,7 +246,6 @@
uint32_t handle; /* The connection handle */
uint32_t req_id; /* The req_id in the associated BTA_JvL2capWrite() */
uint16_t len; /* The length of the data written. */
- uint8_t* p_data; /* The buffer where data is held */
bool cong; /* congestion status */
} tBTA_JV_L2CAP_WRITE;
@@ -256,7 +255,6 @@
uint16_t channel; /* The connection channel */
RawAddress addr; /* The peer address */
uint32_t req_id; /* The req_id in the associated BTA_JvL2capWrite() */
- uint8_t* p_data; /* The buffer where data is held */
uint16_t len; /* The length of the data written. */
bool cong; /* congestion status */
} tBTA_JV_L2CAP_WRITE_FIXED;
@@ -442,11 +440,10 @@
* request a new channel will be made. set channel to <= 0 to
* automatically assign an channel ID.
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
+ * Returns void
*
******************************************************************************/
-tBTA_JV_STATUS BTA_JvGetChannelId(int conn_type, uint32_t id, int32_t channel);
+void BTA_JvGetChannelId(int conn_type, uint32_t id, int32_t channel);
/*******************************************************************************
*
@@ -475,7 +472,8 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvStartDiscovery(const RawAddress& bd_addr,
- uint16_t num_uuid, tSDP_UUID* p_uuid_list,
+ uint16_t num_uuid,
+ const bluetooth::Uuid* p_uuid_list,
uint32_t rfcomm_slot_id);
/*******************************************************************************
@@ -514,17 +512,10 @@
* When the connection is established or failed,
* tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
- *
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capConnectLE(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
- const tL2CAP_ERTM_INFO* ertm_info,
- uint16_t remote_chan, uint16_t rx_mtu,
- tL2CAP_CFG_INFO* cfg,
- const RawAddress& peer_bd_addr,
- tBTA_JV_L2CAP_CBACK* p_cback,
- uint32_t l2cap_socket_id);
+void BTA_JvL2capConnectLE(uint16_t remote_chan, const RawAddress& peer_bd_addr,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id);
/*******************************************************************************
*
@@ -537,15 +528,13 @@
* When the connection is established or failed,
* tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
- *
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capConnect(
- int conn_type, tBTA_SEC sec_mask, tBTA_JV_ROLE role,
- const tL2CAP_ERTM_INFO* ertm_info, uint16_t remote_psm, uint16_t rx_mtu,
- tL2CAP_CFG_INFO* cfg, const RawAddress& peer_bd_addr,
- tBTA_JV_L2CAP_CBACK* p_cback, uint32_t l2cap_socket_id);
+void BTA_JvL2capConnect(int conn_type, tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info,
+ uint16_t remote_psm, uint16_t rx_mtu,
+ std::unique_ptr<tL2CAP_CFG_INFO> cfg,
+ const RawAddress& peer_bd_addr,
+ tBTA_JV_L2CAP_CBACK* p_cback, uint32_t l2cap_socket_id);
/*******************************************************************************
*
@@ -583,17 +572,15 @@
* established, tBTA_JV_L2CAP_CBACK is called with
* BTA_JV_L2CAP_OPEN_EVT.
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
+ * Returns void
*
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capStartServer(int conn_type, tBTA_SEC sec_mask,
- tBTA_JV_ROLE role,
- const tL2CAP_ERTM_INFO* ertm_info,
- uint16_t local_psm, uint16_t rx_mtu,
- tL2CAP_CFG_INFO* cfg,
- tBTA_JV_L2CAP_CBACK* p_cback,
- uint32_t l2cap_socket_id);
+void BTA_JvL2capStartServer(int conn_type, tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info,
+ uint16_t local_psm, uint16_t rx_mtu,
+ std::unique_ptr<tL2CAP_CFG_INFO> cfg,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id);
/*******************************************************************************
*
@@ -606,16 +593,11 @@
* BTA_JV_L2CAP_START_EVT. When the connection is established,
* tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT.
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
+ * Returns void
*
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capStartServerLE(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
- const tL2CAP_ERTM_INFO* ertm_info,
- uint16_t local_chan, uint16_t rx_mtu,
- tL2CAP_CFG_INFO* cfg,
- tBTA_JV_L2CAP_CBACK* p_cback,
- uint32_t l2cap_socket_id);
+void BTA_JvL2capStartServerLE(uint16_t local_chan, tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id);
/*******************************************************************************
*
@@ -686,8 +668,7 @@
* BTA_JV_FAILURE, otherwise.
*
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id,
- uint8_t* p_data, uint16_t len,
+tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id, BT_HDR* msg,
uint32_t user_id);
/*******************************************************************************
@@ -699,15 +680,10 @@
* called with BTA_JV_L2CAP_WRITE_FIXED_EVT. Works for
* fixed-channel connections
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
- *
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capWriteFixed(uint16_t channel, const RawAddress& addr,
- uint32_t req_id,
- tBTA_JV_L2CAP_CBACK* p_cback,
- uint8_t* p_data, uint16_t len,
- uint32_t user_id);
+void BTA_JvL2capWriteFixed(uint16_t channel, const RawAddress& addr,
+ uint32_t req_id, tBTA_JV_L2CAP_CBACK* p_cback,
+ BT_HDR* msg, uint32_t user_id);
/*******************************************************************************
*
diff --git a/bta/include/bta_jv_co.h b/bta/include/bta_jv_co.h
index e3a4130..fdee4ef 100644
--- a/bta/include/bta_jv_co.h
+++ b/bta/include/bta_jv_co.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2007-2012 Broadcom Corporation
+ * Copyright 2007-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_mce_api.h b/bta/include/bta_mce_api.h
index 27d6236..182e5da 100644
--- a/bta/include/bta_mce_api.h
+++ b/bta/include/bta_mce_api.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_op_api.h b/bta/include/bta_op_api.h
index 3918568..bab96ff 100644
--- a/bta/include/bta_op_api.h
+++ b/bta/include/bta_op_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_pan_api.h b/bta/include/bta_pan_api.h
index 1eaaa2d..ce8a3c8 100644
--- a/bta/include/bta_pan_api.h
+++ b/bta/include/bta_pan_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_pan_ci.h b/bta/include/bta_pan_ci.h
index 889d77b..3711700 100644
--- a/bta/include/bta_pan_ci.h
+++ b/bta/include/bta_pan_ci.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_pan_co.h b/bta/include/bta_pan_co.h
index 1ce512d..acd212e 100644
--- a/bta/include/bta_pan_co.h
+++ b/bta/include/bta_pan_co.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/include/bta_sdp_api.h b/bta/include/bta_sdp_api.h
index 4dc5885..078167a 100644
--- a/bta/include/bta_sdp_api.h
+++ b/bta/include/bta_sdp_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,8 @@
#include "bta_api.h"
#include "btm_api.h"
+using bluetooth::Uuid;
+
/* status values */
#define BTA_SDP_SUCCESS 0 /* Successful operation. */
#define BTA_SDP_FAILURE 1 /* Generic failure. */
@@ -55,7 +57,7 @@
typedef struct {
tBTA_SDP_STATUS status;
RawAddress remote_addr;
- tBT_UUID uuid;
+ bluetooth::Uuid uuid;
int record_count;
bluetooth_sdp_record records[BTA_SDP_MAX_RECORDS];
} tBTA_SDP_SEARCH_COMP;
@@ -104,7 +106,7 @@
*
******************************************************************************/
extern tBTA_SDP_STATUS BTA_SdpSearch(const RawAddress& bd_addr,
- tSDP_UUID* uuid);
+ const bluetooth::Uuid& uuid);
/*******************************************************************************
*
diff --git a/bta/include/utl.h b/bta/include/utl.h
index 88ec332..10afd25 100644
--- a/bta/include/utl.h
+++ b/bta/include/utl.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/jv/bta_jv_act.cc b/bta/jv/bta_jv_act.cc
index d1d66aa..69fa3f2 100644
--- a/bta/jv/bta_jv_act.cc
+++ b/bta/jv/bta_jv_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
*
******************************************************************************/
#include <arpa/inet.h>
+#include <bluetooth/uuid.h>
#include <hardware/bluetooth.h>
#include <pthread.h>
#include <stdlib.h>
@@ -38,16 +39,22 @@
#include "bta_sys.h"
#include "btm_api.h"
#include "btm_int.h"
+#include "device/include/controller.h"
#include "gap_api.h"
#include "l2c_api.h"
#include "osi/include/allocator.h"
#include "port_api.h"
#include "rfcdefs.h"
#include "sdp_api.h"
+#include "stack/l2cap/l2c_int.h"
#include "utl.h"
#include "osi/include/osi.h"
+using bluetooth::Uuid;
+
+tBTA_JV_CB bta_jv_cb;
+
/* one of these exists for each client */
struct fc_client {
struct fc_client* next_all_list;
@@ -81,13 +88,6 @@
static void fcchan_data_cbk(uint16_t chan, const RawAddress& bd_addr,
BT_HDR* p_buf);
-extern void uuid_to_string_legacy(bt_uuid_t* p_uuid, char* str, size_t str_len);
-static inline void logu(const char* title, const uint8_t* p_uuid) {
- char uuids[128];
- uuid_to_string_legacy((bt_uuid_t*)p_uuid, uuids, sizeof(uuids));
- APPL_TRACE_DEBUG("%s: %s", title, uuids);
-}
-
static tBTA_JV_PCB* bta_jv_add_rfc_port(tBTA_JV_RFC_CB* p_cb,
tBTA_JV_PCB* p_pcb_open);
static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(uint32_t jv_handle);
@@ -95,8 +95,6 @@
static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB* p_cb);
static void bta_jv_pm_state_change(tBTA_JV_PM_CB* p_cb,
const tBTA_JV_CONN_STATE state);
-tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB* p_cb,
- const tBTA_JV_CONN_STATE new_st);
/*******************************************************************************
*
@@ -126,8 +124,8 @@
if (bta_jv_cb.sec_id[i]) used++;
}
if (used == BTA_JV_NUM_SERVICE_ID)
- APPL_TRACE_ERROR("get_sec_id_used, sec id exceeds the limit:%d",
- BTA_JV_NUM_SERVICE_ID);
+ LOG(ERROR) << __func__
+ << ": sec id exceeds the limit=" << BTA_JV_NUM_SERVICE_ID;
return used;
}
static int get_rfc_cb_used(void) {
@@ -137,8 +135,8 @@
if (bta_jv_cb.rfc_cb[i].handle) used++;
}
if (used == BTA_JV_MAX_RFC_CONN)
- APPL_TRACE_ERROR("get_sec_id_used, rfc ctrl block exceeds the limit:%d",
- BTA_JV_MAX_RFC_CONN);
+ LOG(ERROR) << __func__
+ << ": rfc ctrl block exceeds the limit=" << BTA_JV_MAX_RFC_CONN;
return used;
}
@@ -184,8 +182,8 @@
p_cb->curr_sess = 1;
for (j = 0; j < BTA_JV_MAX_RFC_SR_SESSION; j++) p_cb->rfc_hdl[j] = 0;
p_cb->rfc_hdl[0] = port_handle;
- APPL_TRACE_DEBUG("bta_jv_alloc_rfc_cb port_handle:%d handle:0x%2x",
- port_handle, p_cb->handle);
+ VLOG(2) << __func__ << "port_handle=" << +port_handle
+ << ", handle=" << loghex(p_cb->handle);
p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
p_pcb->handle = p_cb->handle;
@@ -196,10 +194,9 @@
}
}
if (p_cb == NULL) {
- APPL_TRACE_ERROR(
- "bta_jv_alloc_rfc_cb: port_handle:%d, ctrl block exceeds "
- "limit:%d",
- port_handle, BTA_JV_MAX_RFC_CONN);
+ LOG(ERROR) << __func__ << "port_handle=" << port_handle
+ << " ctrl block exceeds limit:" << port_handle,
+ BTA_JV_MAX_RFC_CONN;
}
return p_cb;
}
@@ -246,10 +243,8 @@
handle &= ~BTA_JV_RFCOMM_MASK;
if (handle) p_cb = &bta_jv_cb.rfc_cb[handle - 1];
} else {
- APPL_TRACE_WARNING(
- "bta_jv_rfc_port_to_cb(port_handle:0x%x):jv handle:0x%x not"
- " FOUND",
- port_handle, bta_jv_cb.port_cb[port_handle - 1].handle);
+ LOG(WARNING) << __func__
+ << ": jv handle not found port_handle:" << port_handle;
}
return p_cb;
}
@@ -261,55 +256,48 @@
int close_pending = 0;
if (!p_cb || !p_pcb) {
- APPL_TRACE_ERROR("bta_jv_free_sr_rfc_cb, p_cb or p_pcb cannot be null");
+ LOG(ERROR) << __func__ << " p_cb or p_pcb cannot be null";
return BTA_JV_FAILURE;
}
- APPL_TRACE_DEBUG(
- "bta_jv_free_sr_rfc_cb: max_sess:%d, curr_sess:%d, p_pcb:%p, user:"
- "%p, state:%d, jv handle: 0x%x",
- p_cb->max_sess, p_cb->curr_sess, p_pcb, p_pcb->rfcomm_slot_id,
- p_pcb->state, p_pcb->handle);
+ VLOG(2) << __func__ << ": max_sess=" << p_cb->max_sess
+ << ", curr_sess=" << p_cb->curr_sess << ", p_pcb=" << p_pcb
+ << ", user=" << p_pcb->rfcomm_slot_id << ", state=" << p_pcb->state
+ << ", jv handle=" << loghex(p_pcb->handle);
if (p_cb->curr_sess <= 0) return BTA_JV_SUCCESS;
switch (p_pcb->state) {
case BTA_JV_ST_CL_CLOSING:
case BTA_JV_ST_SR_CLOSING:
- APPL_TRACE_WARNING(
- "bta_jv_free_sr_rfc_cb: return on closing, port state:%d, "
- "scn:%d, p_pcb:%p, user_data:%p",
- p_pcb->state, p_cb->scn, p_pcb, p_pcb->rfcomm_slot_id);
+ LOG(WARNING) << __func__
+ << ": return on closing, port state=" << p_pcb->state
+ << ", scn=" << p_cb->scn << ", p_pcb=" << p_pcb
+ << ", user_data=" << p_pcb->rfcomm_slot_id;
status = BTA_JV_FAILURE;
return status;
case BTA_JV_ST_CL_OPEN:
case BTA_JV_ST_CL_OPENING:
- APPL_TRACE_DEBUG(
- "bta_jv_free_sr_rfc_cb: state: %d, scn:%d,"
- " user_data:%p",
- p_pcb->state, p_cb->scn, p_pcb->rfcomm_slot_id);
+ VLOG(2) << __func__ << ": state=" << p_pcb->state << ", scn=" << p_cb->scn
+ << ", user_data=" << p_pcb->rfcomm_slot_id;
p_pcb->state = BTA_JV_ST_CL_CLOSING;
break;
case BTA_JV_ST_SR_LISTEN:
p_pcb->state = BTA_JV_ST_SR_CLOSING;
remove_server = true;
- APPL_TRACE_DEBUG(
- "bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_LISTEN, scn:%d,"
- " user_data:%p",
- p_cb->scn, p_pcb->rfcomm_slot_id);
+ VLOG(2) << __func__ << ": state: BTA_JV_ST_SR_LISTEN, scn=" << p_cb->scn
+ << ", user_data=" << p_pcb->rfcomm_slot_id;
break;
case BTA_JV_ST_SR_OPEN:
p_pcb->state = BTA_JV_ST_SR_CLOSING;
- APPL_TRACE_DEBUG(
- "bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_OPEN, scn:%d,"
- " user_data:%p",
- p_cb->scn, p_pcb->rfcomm_slot_id);
+ VLOG(2) << ": state: BTA_JV_ST_SR_OPEN, scn=" << p_cb->scn
+ << " user_data=" << p_pcb->rfcomm_slot_id;
break;
default:
- APPL_TRACE_WARNING(
- "bta_jv_free_sr_rfc_cb():failed, ignore port state:%d, scn:"
- "%d, p_pcb:%p, jv handle: 0x%x, port_handle: %d, user_data:%p",
- p_pcb->state, p_cb->scn, p_pcb, p_pcb->handle, p_pcb->port_handle,
- p_pcb->rfcomm_slot_id);
+ LOG(WARNING) << __func__ << ":failed, ignore port state= " << p_pcb->state
+ << ", scn=" << p_cb->scn << ", p_pcb= " << p_pcb
+ << ", jv handle=" << loghex(p_pcb->handle)
+ << ", port_handle=" << p_pcb->port_handle
+ << ", user_data=" << p_pcb->rfcomm_slot_id;
status = BTA_JV_FAILURE;
break;
}
@@ -322,11 +310,11 @@
port_status = RFCOMM_RemoveServer(p_pcb->port_handle);
if (port_status != PORT_SUCCESS) {
status = BTA_JV_FAILURE;
- APPL_TRACE_WARNING(
- "bta_jv_free_rfc_cb(jv handle: 0x%x, state %d)::"
- "port_status: %d, port_handle: %d, close_pending: %d:Remove",
- p_pcb->handle, p_pcb->state, port_status, p_pcb->port_handle,
- close_pending);
+ LOG(WARNING) << __func__ << ": Remove jv handle=" << loghex(p_pcb->handle)
+ << ", state=" << p_pcb->state
+ << ", port_status=" << port_status
+ << ", port_handle=" << p_pcb->port_handle
+ << ", close_pending=" << close_pending;
}
}
if (!close_pending) {
@@ -431,14 +419,10 @@
appid_counter++;
}
- APPL_TRACE_API(
- "%s(jv_handle: 0x%2x), idx: %d, "
- "app_id: 0x%x",
- __func__, jv_handle, i, bta_jv_cb.pm_cb[i].app_id);
- APPL_TRACE_API(
- "%s, bd_counter = %d, "
- "appid_counter = %d",
- __func__, bd_counter, appid_counter);
+ VLOG(2) << __func__ << ": jv_handle=" << loghex(jv_handle)
+ << ", idx=" << i << "app_id=" << bta_jv_cb.pm_cb[i].app_id
+ << ", bd_counter=" << bd_counter
+ << ", appid_counter=" << appid_counter;
if (bd_counter > 1) {
bta_jv_pm_conn_idle(&bta_jv_cb.pm_cb[i]);
}
@@ -460,11 +444,9 @@
bta_jv_rfc_port_to_pcb(bta_jv_cb.rfc_cb[hi].rfc_hdl[si]);
if (p_pcb) {
if (NULL == p_pcb->p_pm_cb)
- APPL_TRACE_WARNING(
- "%s(jv_handle:"
- " 0x%x):port_handle: 0x%x, p_pm_cb: %d: no link to "
- "pm_cb?",
- __func__, jv_handle, p_pcb->port_handle, i);
+ LOG(WARNING) << __func__ << ": jv_handle=" << loghex(jv_handle)
+ << ", port_handle=" << p_pcb->port_handle
+ << ", i=" << i << ", no link to pm_cb?";
p_cb = &p_pcb->p_pm_cb;
}
}
@@ -472,10 +454,8 @@
if (jv_handle < BTA_JV_MAX_L2C_CONN) {
tBTA_JV_L2C_CB* p_l2c_cb = &bta_jv_cb.l2c_cb[jv_handle];
if (NULL == p_l2c_cb->p_pm_cb)
- APPL_TRACE_WARNING(
- "%s(jv_handle: "
- "0x%x): p_pm_cb: %d: no link to pm_cb?",
- __func__, jv_handle, i);
+ LOG(WARNING) << __func__ << ": jv_handle=" << loghex(jv_handle)
+ << ", i=" << i << " no link to pm_cb?";
p_cb = &p_l2c_cb->p_pm_cb;
}
}
@@ -534,10 +514,10 @@
}
}
}
- APPL_TRACE_API(
- "bta_jv_alloc_set_pm_profile_cb(handle 0x%2x, app_id %d): "
- "idx: %d, (BTA_JV_PM_MAX_NUM: %d), pp_cb: 0x%x",
- jv_handle, app_id, i, BTA_JV_PM_MAX_NUM, pp_cb);
+ VLOG(2) << __func__ << ": handle=" << loghex(jv_handle)
+ << ", app_id=" << app_id << ", idx=" << i
+ << ", BTA_JV_PM_MAX_NUM=" << BTA_JV_PM_MAX_NUM
+ << ", pp_cb=" << pp_cb;
break;
}
}
@@ -550,11 +530,9 @@
bta_jv_cb.pm_cb[i].state = BTA_JV_PM_IDLE_ST;
return &bta_jv_cb.pm_cb[i];
}
- APPL_TRACE_WARNING(
- "bta_jv_alloc_set_pm_profile_cb(jv_handle: 0x%x, app_id: %d) "
- "return NULL",
- jv_handle, app_id);
- return (tBTA_JV_PM_CB*)NULL;
+ LOG(WARNING) << __func__ << ": handle=" << loghex(jv_handle)
+ << ", app_id=" << app_id << ", return NULL";
+ return NULL;
}
/*******************************************************************************
@@ -580,27 +558,27 @@
case TCS_PSM_INTERCOM: /* 5 */
case TCS_PSM_CORDLESS: /* 7 */
- if (false == bta_sys_is_register(BTA_ID_CT) &&
- false == bta_sys_is_register(BTA_ID_CG))
+ if (!bta_sys_is_register(BTA_ID_CT) &&
+ !bta_sys_is_register(BTA_ID_CG))
ret = true;
break;
case BT_PSM_BNEP: /* F */
- if (false == bta_sys_is_register(BTA_ID_PAN)) ret = true;
+ if (!bta_sys_is_register(BTA_ID_PAN)) ret = true;
break;
case HID_PSM_CONTROL: /* 0x11 */
case HID_PSM_INTERRUPT: /* 0x13 */
// FIX: allow HID Device and HID Host to coexist
- if (false == bta_sys_is_register(BTA_ID_HD) ||
- false == bta_sys_is_register(BTA_ID_HH))
+ if (!bta_sys_is_register(BTA_ID_HD) ||
+ !bta_sys_is_register(BTA_ID_HH))
ret = true;
break;
case AVCT_PSM: /* 0x17 */
case AVDT_PSM: /* 0x19 */
- if ((false == bta_sys_is_register(BTA_ID_AV)) &&
- (false == bta_sys_is_register(BTA_ID_AVK)))
+ if ((!bta_sys_is_register(BTA_ID_AV)) &&
+ (!bta_sys_is_register(BTA_ID_AVK)))
ret = true;
break;
@@ -615,37 +593,18 @@
return ret;
}
-/*******************************************************************************
- *
- * Function bta_jv_enable
- *
- * Description Initialises the JAVA I/F
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_enable(tBTA_JV_MSG* p_data) {
+/* Initialises the JAVA I/F */
+void bta_jv_enable(tBTA_JV_DM_CBACK* p_cback) {
tBTA_JV_STATUS status = BTA_JV_SUCCESS;
- bta_jv_cb.p_dm_cback = p_data->enable.p_cback;
+ bta_jv_cb.p_dm_cback = p_cback;
tBTA_JV bta_jv;
bta_jv.status = status;
bta_jv_cb.p_dm_cback(BTA_JV_ENABLE_EVT, &bta_jv, 0);
memset(bta_jv_cb.free_psm_list, 0, sizeof(bta_jv_cb.free_psm_list));
}
-/*******************************************************************************
- *
- * Function bta_jv_disable
- *
- * Description Disables the BT device manager
- * free the resources used by java
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_disable(UNUSED_ATTR tBTA_JV_MSG* p_data) {
- APPL_TRACE_ERROR("%s", __func__);
-}
+/** Disables the BT device manager free the resources used by java */
+void bta_jv_disable() { LOG(ERROR) << __func__; }
/**
* We keep a list of PSM's that have been freed from JAVA, for reuse.
@@ -659,7 +618,7 @@
for (int i = 0; i < cnt; i++) {
uint16_t psm = bta_jv_cb.free_psm_list[i];
if (psm != 0) {
- APPL_TRACE_DEBUG("%s(): Reusing PSM: 0x%04d", __func__, psm)
+ VLOG(2) << __func__ << ": Reusing PSM=" << loghex(psm);
bta_jv_cb.free_psm_list[i] = 0;
return psm;
}
@@ -680,39 +639,33 @@
}
if (free_index != -1) {
bta_jv_cb.free_psm_list[free_index] = psm;
- APPL_TRACE_DEBUG("%s(): Recycling PSM: 0x%04d", __func__, psm)
+ VLOG(2) << __func__ << ": Recycling PSM=" << loghex(psm);
} else {
- APPL_TRACE_ERROR("%s unable to free psm 0x%x no more free slots", __func__,
- psm);
+ LOG(ERROR) << __func__ << ": unable to free psm=" << loghex(psm)
+ << " no more free slots";
}
}
-/*******************************************************************************
- *
- * Function bta_jv_get_channel_id
- *
- * Description Obtain a free SCN (Server Channel Number)
- * (RFCOMM channel or L2CAP PSM)
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_get_channel_id(tBTA_JV_MSG* p_data) {
+/** Obtain a free SCN (Server Channel Number) (RFCOMM channel or L2CAP PSM) */
+void bta_jv_get_channel_id(
+ int32_t type /* One of BTA_JV_CONN_TYPE_ */,
+ int32_t channel /* optionally request a specific channel */,
+ uint32_t l2cap_socket_id, uint32_t rfcomm_slot_id) {
uint16_t psm = 0;
- switch (p_data->alloc_channel.type) {
+ switch (type) {
case BTA_JV_CONN_TYPE_RFCOMM: {
- int32_t channel = p_data->alloc_channel.channel;
uint8_t scn = 0;
if (channel > 0) {
- if (BTM_TryAllocateSCN(channel) == false) {
- APPL_TRACE_ERROR("rfc channel:%d already in use or invalid", channel);
+ if (!BTM_TryAllocateSCN(channel)) {
+ LOG(ERROR) << "rfc channel=" << channel
+ << " already in use or invalid";
channel = 0;
}
} else {
channel = BTM_AllocateSCN();
if (channel == 0) {
- APPL_TRACE_ERROR("run out of rfc channels");
+ LOG(ERROR) << "run out of rfc channels";
channel = 0;
}
}
@@ -723,8 +676,7 @@
if (bta_jv_cb.p_dm_cback) {
tBTA_JV bta_jv;
bta_jv.scn = scn;
- bta_jv_cb.p_dm_cback(BTA_JV_GET_SCN_EVT, &bta_jv,
- p_data->alloc_channel.rfcomm_slot_id);
+ bta_jv_cb.p_dm_cback(BTA_JV_GET_SCN_EVT, &bta_jv, rfcomm_slot_id);
}
return;
}
@@ -732,10 +684,14 @@
psm = bta_jv_get_free_psm();
if (psm == 0) {
psm = L2CA_AllocatePSM();
- APPL_TRACE_DEBUG("%s() returned PSM: 0x%04x", __func__, psm);
+ VLOG(2) << __func__ << ": returned PSM=" << loghex(psm);
}
break;
case BTA_JV_CONN_TYPE_L2CAP_LE:
+ psm = L2CA_AllocateLePSM();
+ if (psm == 0) {
+ LOG(ERROR) << __func__ << ": Error: No free LE PSM available";
+ }
break;
default:
break;
@@ -744,24 +700,14 @@
if (bta_jv_cb.p_dm_cback) {
tBTA_JV bta_jv;
bta_jv.psm = psm;
- bta_jv_cb.p_dm_cback(BTA_JV_GET_PSM_EVT, &bta_jv,
- p_data->alloc_channel.l2cap_socket_id);
+ bta_jv_cb.p_dm_cback(BTA_JV_GET_PSM_EVT, &bta_jv, l2cap_socket_id);
}
}
-/*******************************************************************************
- *
- * Function bta_jv_free_scn
- *
- * Description free a SCN
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_free_scn(tBTA_JV_MSG* p_data) {
- uint16_t scn = p_data->free_channel.scn;
-
- switch (p_data->free_channel.type) {
+/** free a SCN */
+void bta_jv_free_scn(int32_t type /* One of BTA_JV_CONN_TYPE_ */,
+ uint16_t scn) {
+ switch (type) {
case BTA_JV_CONN_TYPE_RFCOMM: {
if (scn > 0 && scn <= BTA_JV_MAX_SCN && bta_jv_cb.scn[scn - 1]) {
/* this scn is used by JV */
@@ -774,42 +720,13 @@
bta_jv_set_free_psm(scn);
break;
case BTA_JV_CONN_TYPE_L2CAP_LE:
- // TODO: Not yet implemented...
+ VLOG(2) << __func__ << ": type=BTA_JV_CONN_TYPE_L2CAP_LE. psm=" << scn;
+ L2CA_FreeLePSM(scn);
break;
default:
break;
}
}
-static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID* u) {
- static uint8_t bt_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-
- logu("in, uuid:", u->uu.uuid128);
- APPL_TRACE_DEBUG("uuid len:%d", u->len);
- if (u->len == 16) {
- if (memcmp(&u->uu.uuid128[4], &bt_base_uuid[4], 12) == 0) {
- tBT_UUID su;
- memset(&su, 0, sizeof(su));
- if (u->uu.uuid128[0] == 0 && u->uu.uuid128[1] == 0) {
- su.len = 2;
- uint16_t u16;
- memcpy(&u16, &u->uu.uuid128[2], sizeof(u16));
- su.uu.uuid16 = ntohs(u16);
- APPL_TRACE_DEBUG("shorten to 16 bits uuid: %x", su.uu.uuid16);
- } else {
- su.len = 4;
- uint32_t u32;
- memcpy(&u32, &u->uu.uuid128[0], sizeof(u32));
- su.uu.uuid32 = ntohl(u32);
- APPL_TRACE_DEBUG("shorten to 32 bits uuid: %x", su.uu.uuid32);
- }
- return su;
- }
- }
- APPL_TRACE_DEBUG("cannot shorten none-reserved 128 bits uuid");
- return *u;
-}
/*******************************************************************************
*
@@ -824,7 +741,7 @@
tBTA_JV_STATUS status;
uint32_t* p_rfcomm_slot_id = static_cast<uint32_t*>(user_data);
- APPL_TRACE_DEBUG("bta_jv_start_discovery_cback res: 0x%x", result);
+ VLOG(2) << __func__ << ": res=" << loghex(result);
bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
if (bta_jv_cb.p_dm_cback) {
@@ -834,12 +751,10 @@
if (result == SDP_SUCCESS || result == SDP_DB_FULL) {
tSDP_DISC_REC* p_sdp_rec = NULL;
tSDP_PROTOCOL_ELEM pe;
- logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128);
- tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid);
- logu("shorten uuid:", su.uu.uuid128);
- p_sdp_rec =
- SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec);
- APPL_TRACE_DEBUG("p_sdp_rec:%p", p_sdp_rec);
+ VLOG(2) << __func__ << ": bta_jv_cb.uuid=" << bta_jv_cb.uuid;
+ p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db,
+ bta_jv_cb.uuid, p_sdp_rec);
+ VLOG(2) << __func__ << ": p_sdp_rec=" << p_sdp_rec;
if (p_sdp_rec &&
SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
dcomp.scn = (uint8_t)pe.params[0];
@@ -855,61 +770,49 @@
}
}
-/*******************************************************************************
- *
- * Function bta_jv_start_discovery
- *
- * Description Discovers services on a remote device
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_start_discovery(tBTA_JV_MSG* p_data) {
+/* Discovers services on a remote device */
+void bta_jv_start_discovery(const RawAddress& bd_addr, uint16_t num_uuid,
+ bluetooth::Uuid* uuid_list,
+ uint32_t rfcomm_slot_id) {
tBTA_JV_STATUS status = BTA_JV_FAILURE;
- APPL_TRACE_DEBUG("bta_jv_start_discovery in, sdp_active:%d",
- bta_jv_cb.sdp_active);
+ VLOG(2) << __func__ << ": in, sdp_active=" << bta_jv_cb.sdp_active;
if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE) {
/* SDP is still in progress */
status = BTA_JV_BUSY;
if (bta_jv_cb.p_dm_cback) {
tBTA_JV bta_jv;
bta_jv.status = status;
- bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv,
- p_data->start_discovery.rfcomm_slot_id);
+ bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv, rfcomm_slot_id);
}
return;
}
/* init the database/set up the filter */
- APPL_TRACE_DEBUG(
- "call SDP_InitDiscoveryDb, p_data->start_discovery.num_uuid:%d",
- p_data->start_discovery.num_uuid);
+ VLOG(2) << __func__ << ": call SDP_InitDiscoveryDb, num_uuid=", num_uuid;
SDP_InitDiscoveryDb(p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size,
- p_data->start_discovery.num_uuid,
- p_data->start_discovery.uuid_list, 0, NULL);
+ num_uuid, uuid_list, 0, NULL);
/* tell SDP to keep the raw data */
p_bta_jv_cfg->p_sdp_db->raw_data = p_bta_jv_cfg->p_sdp_raw_data;
p_bta_jv_cfg->p_sdp_db->raw_size = p_bta_jv_cfg->sdp_raw_size;
bta_jv_cb.p_sel_raw_data = 0;
- bta_jv_cb.uuid = p_data->start_discovery.uuid_list[0];
+ bta_jv_cb.uuid = uuid_list[0];
bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_YES;
- uint32_t* rfcomm_slot_id = (uint32_t*)osi_malloc(sizeof(uint32_t));
- *rfcomm_slot_id = p_data->start_discovery.rfcomm_slot_id;
+ uint32_t* rfcomm_slot_id_copy = (uint32_t*)osi_malloc(sizeof(uint32_t));
+ *rfcomm_slot_id_copy = rfcomm_slot_id;
- if (!SDP_ServiceSearchAttributeRequest2(
- p_data->start_discovery.bd_addr, p_bta_jv_cfg->p_sdp_db,
- bta_jv_start_discovery_cback, (void*)rfcomm_slot_id)) {
+ if (!SDP_ServiceSearchAttributeRequest2(bd_addr, p_bta_jv_cfg->p_sdp_db,
+ bta_jv_start_discovery_cback,
+ (void*)rfcomm_slot_id_copy)) {
bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
/* failed to start SDP. report the failure right away */
if (bta_jv_cb.p_dm_cback) {
tBTA_JV bta_jv;
bta_jv.status = status;
- bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv,
- p_data->start_discovery.rfcomm_slot_id);
+ bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv, rfcomm_slot_id);
}
}
/*
@@ -917,42 +820,23 @@
*/
}
-/*******************************************************************************
- *
- * Function bta_jv_create_record
- *
- * Description Create an SDP record with the given attributes
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_create_record(tBTA_JV_MSG* p_data) {
- tBTA_JV_API_CREATE_RECORD* cr = &(p_data->create_record);
+/* Create an SDP record with the given attributes */
+void bta_jv_create_record(uint32_t rfcomm_slot_id) {
tBTA_JV_CREATE_RECORD evt_data;
evt_data.status = BTA_JV_SUCCESS;
if (bta_jv_cb.p_dm_cback) {
// callback immediately to create the sdp record in stack thread context
tBTA_JV bta_jv;
bta_jv.create_rec = evt_data;
- bta_jv_cb.p_dm_cback(BTA_JV_CREATE_RECORD_EVT, &bta_jv, cr->rfcomm_slot_id);
+ bta_jv_cb.p_dm_cback(BTA_JV_CREATE_RECORD_EVT, &bta_jv, rfcomm_slot_id);
}
}
-/*******************************************************************************
- *
- * Function bta_jv_delete_record
- *
- * Description Delete an SDP record
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_delete_record(tBTA_JV_MSG* p_data) {
- tBTA_JV_API_ADD_ATTRIBUTE* dr = &(p_data->add_attr);
- if (dr->handle) {
+/* Delete an SDP record */
+void bta_jv_delete_record(uint32_t handle) {
+ if (handle) {
/* this is a record created by btif layer*/
- SDP_DeleteRecord(dr->handle);
+ SDP_DeleteRecord(handle);
}
}
@@ -965,13 +849,15 @@
* Returns void
*
******************************************************************************/
-static void bta_jv_l2cap_client_cback(uint16_t gap_handle, uint16_t event) {
+static void bta_jv_l2cap_client_cback(uint16_t gap_handle, uint16_t event,
+ tGAP_CB_DATA* data) {
tBTA_JV_L2C_CB* p_cb = &bta_jv_cb.l2c_cb[gap_handle];
tBTA_JV evt_data;
if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) return;
- APPL_TRACE_DEBUG("%s: %d evt:x%x", __func__, gap_handle, event);
+ VLOG(2) << __func__ << ": gap_handle=" << gap_handle
+ << ", evt=" << loghex(event);
evt_data.l2c_open.status = BTA_JV_SUCCESS;
evt_data.l2c_open.handle = gap_handle;
@@ -1016,59 +902,49 @@
}
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_connect
- *
- * Description makes an l2cap client connection
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_connect(tBTA_JV_MSG* p_data) {
- tBTA_JV_L2C_CB* p_cb;
- tBTA_JV_L2CAP_CL_INIT evt_data;
+/* makes an l2cap client connection */
+void bta_jv_l2cap_connect(int32_t type, tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ uint16_t remote_psm, uint16_t rx_mtu,
+ const RawAddress& peer_bd_addr,
+ std::unique_ptr<tL2CAP_CFG_INFO> cfg_param,
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id) {
uint16_t handle = GAP_INVALID_HANDLE;
- uint8_t sec_id;
- tL2CAP_CFG_INFO cfg;
- tBTA_JV_API_L2CAP_CONNECT* cc = &(p_data->l2cap_connect);
uint8_t chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
- tL2CAP_ERTM_INFO* ertm_info = NULL;
+ tL2CAP_CFG_INFO cfg;
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
-
- if (cc->has_cfg == true) {
- cfg = cc->cfg;
+ if (cfg_param) {
+ cfg = *cfg_param;
if (cfg.fcr_present && cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
chan_mode_mask = GAP_FCR_CHAN_OPT_ERTM;
}
}
- if (cc->has_ertm_info == true) {
- ertm_info = &(cc->ertm_info);
- }
-
/* We need to use this value for MTU to be able to handle cases where cfg is
* not set in req. */
cfg.mtu_present = true;
- cfg.mtu = cc->rx_mtu;
+ cfg.mtu = rx_mtu;
/* TODO: DM role manager
- L2CA_SetDesireRole(cc->role);
+ L2CA_SetDesireRole(role);
*/
- sec_id = bta_jv_alloc_sec_id();
+ uint8_t sec_id = bta_jv_alloc_sec_id();
+ tBTA_JV_L2CAP_CL_INIT evt_data;
evt_data.sec_id = sec_id;
evt_data.status = BTA_JV_FAILURE;
if (sec_id) {
/* PSM checking is not required for LE COC */
- if ((cc->type != BTA_JV_CONN_TYPE_L2CAP) ||
- (bta_jv_check_psm(cc->remote_psm))) /* allowed */
+ if ((type != BTA_JV_CONN_TYPE_L2CAP) ||
+ (bta_jv_check_psm(remote_psm))) /* allowed */
{
- handle = GAP_ConnOpen("", sec_id, 0, &cc->peer_bd_addr, cc->remote_psm,
- &cfg, ertm_info, cc->sec_mask, chan_mode_mask,
- bta_jv_l2cap_client_cback, cc->type);
+ uint16_t max_mps = 0xffff; // Let GAP_ConnOpen set the max_mps.
+ handle = GAP_ConnOpen("", sec_id, 0, &peer_bd_addr, remote_psm, max_mps,
+ &cfg, ertm_info.get(), sec_mask, chan_mode_mask,
+ bta_jv_l2cap_client_cback, type);
if (handle != GAP_INVALID_HANDLE) {
evt_data.status = BTA_JV_SUCCESS;
}
@@ -1076,10 +952,11 @@
}
if (evt_data.status == BTA_JV_SUCCESS) {
+ tBTA_JV_L2C_CB* p_cb;
p_cb = &bta_jv_cb.l2c_cb[handle];
p_cb->handle = handle;
- p_cb->p_cback = cc->p_cback;
- p_cb->l2cap_socket_id = cc->l2cap_socket_id;
+ p_cb->p_cback = p_cback;
+ p_cb->l2cap_socket_id = l2cap_socket_id;
p_cb->psm = 0; /* not a server */
p_cb->sec_id = sec_id;
p_cb->state = BTA_JV_ST_CL_OPENING;
@@ -1088,30 +965,21 @@
}
evt_data.handle = handle;
- if (cc->p_cback) {
+ if (p_cback) {
tBTA_JV bta_jv;
bta_jv.l2c_cl_init = evt_data;
- cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &bta_jv, cc->l2cap_socket_id);
+ p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &bta_jv, l2cap_socket_id);
}
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_close
- *
- * Description Close an L2CAP client connection
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_close(tBTA_JV_MSG* p_data) {
+/** Close an L2CAP client connection */
+void bta_jv_l2cap_close(uint32_t handle, tBTA_JV_L2C_CB* p_cb) {
tBTA_JV_L2CAP_CLOSE evt_data;
- tBTA_JV_API_L2CAP_CLOSE* cc = &(p_data->l2cap_close);
- tBTA_JV_L2CAP_CBACK* p_cback = cc->p_cb->p_cback;
- uint32_t l2cap_socket_id = cc->p_cb->l2cap_socket_id;
+ tBTA_JV_L2CAP_CBACK* p_cback = p_cb->p_cback;
+ uint32_t l2cap_socket_id = p_cb->l2cap_socket_id;
- evt_data.handle = cc->handle;
- evt_data.status = bta_jv_free_l2c_cb(cc->p_cb);
+ evt_data.handle = handle;
+ evt_data.status = bta_jv_free_l2c_cb(p_cb);
evt_data.async = false;
if (p_cback) {
@@ -1130,7 +998,8 @@
* Returns void
*
******************************************************************************/
-static void bta_jv_l2cap_server_cback(uint16_t gap_handle, uint16_t event) {
+static void bta_jv_l2cap_server_cback(uint16_t gap_handle, uint16_t event,
+ tGAP_CB_DATA* data) {
tBTA_JV_L2C_CB* p_cb = &bta_jv_cb.l2c_cb[gap_handle];
tBTA_JV evt_data;
tBTA_JV_L2CAP_CBACK* p_cback;
@@ -1138,7 +1007,8 @@
if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) return;
- APPL_TRACE_DEBUG("%s: %d evt:x%x", __func__, gap_handle, event);
+ VLOG(2) << __func__ << ": gap_handle=" << gap_handle
+ << ", evt=" << loghex(event);
evt_data.l2c_open.status = BTA_JV_SUCCESS;
evt_data.l2c_open.handle = gap_handle;
@@ -1184,100 +1054,78 @@
}
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_start_server
- *
- * Description starts an L2CAP server
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_start_server(tBTA_JV_MSG* p_data) {
- tBTA_JV_L2C_CB* p_cb;
- uint8_t sec_id;
+/** starts an L2CAP server */
+void bta_jv_l2cap_start_server(int32_t type, tBTA_SEC sec_mask,
+ tBTA_JV_ROLE role, uint16_t local_psm,
+ uint16_t rx_mtu,
+ std::unique_ptr<tL2CAP_CFG_INFO> cfg_param,
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id) {
uint16_t handle;
- tL2CAP_CFG_INFO cfg;
tBTA_JV_L2CAP_START evt_data;
- tBTA_JV_API_L2CAP_SERVER* ls = &(p_data->l2cap_server);
uint8_t chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
- tL2CAP_ERTM_INFO* ertm_info = NULL;
+ tL2CAP_CFG_INFO cfg;
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
-
- if (ls->has_cfg == true) {
- cfg = ls->cfg;
+ if (cfg_param) {
+ cfg = *cfg_param;
if (cfg.fcr_present && cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
chan_mode_mask = GAP_FCR_CHAN_OPT_ERTM;
}
}
- if (ls->has_ertm_info == true) {
- ertm_info = &(ls->ertm_info);
- }
-
// FIX: MTU=0 means not present
- if (ls->rx_mtu > 0) {
+ if (rx_mtu > 0) {
cfg.mtu_present = true;
- cfg.mtu = ls->rx_mtu;
+ cfg.mtu = rx_mtu;
} else {
cfg.mtu_present = false;
cfg.mtu = 0;
}
/* TODO DM role manager
- L2CA_SetDesireRole(ls->role);
+ L2CA_SetDesireRole(role);
*/
- sec_id = bta_jv_alloc_sec_id();
+ uint8_t sec_id = bta_jv_alloc_sec_id();
+ uint16_t max_mps = 0xffff; // Let GAP_ConnOpen set the max_mps.
/* PSM checking is not required for LE COC */
- if (0 == sec_id || ((ls->type == BTA_JV_CONN_TYPE_L2CAP) &&
- (false == bta_jv_check_psm(ls->local_psm))) ||
- (handle = GAP_ConnOpen("JV L2CAP", sec_id, 1, nullptr, ls->local_psm,
- &cfg, ertm_info, ls->sec_mask, chan_mode_mask,
- bta_jv_l2cap_server_cback, ls->type)) ==
+ if (0 == sec_id ||
+ ((type == BTA_JV_CONN_TYPE_L2CAP) && (!bta_jv_check_psm(local_psm))) ||
+ (handle = GAP_ConnOpen("JV L2CAP", sec_id, 1, nullptr, local_psm, max_mps,
+ &cfg, ertm_info.get(), sec_mask, chan_mode_mask,
+ bta_jv_l2cap_server_cback, type)) ==
GAP_INVALID_HANDLE) {
bta_jv_free_sec_id(&sec_id);
evt_data.status = BTA_JV_FAILURE;
} else {
- p_cb = &bta_jv_cb.l2c_cb[handle];
+ tBTA_JV_L2C_CB* p_cb = &bta_jv_cb.l2c_cb[handle];
evt_data.status = BTA_JV_SUCCESS;
evt_data.handle = handle;
evt_data.sec_id = sec_id;
- p_cb->p_cback = ls->p_cback;
- p_cb->l2cap_socket_id = ls->l2cap_socket_id;
+ p_cb->p_cback = p_cback;
+ p_cb->l2cap_socket_id = l2cap_socket_id;
p_cb->handle = handle;
p_cb->sec_id = sec_id;
p_cb->state = BTA_JV_ST_SR_LISTEN;
- p_cb->psm = ls->local_psm;
+ p_cb->psm = local_psm;
}
- if (ls->p_cback) {
+ if (p_cback) {
tBTA_JV bta_jv;
bta_jv.l2c_start = evt_data;
- ls->p_cback(BTA_JV_L2CAP_START_EVT, &bta_jv, ls->l2cap_socket_id);
+ p_cback(BTA_JV_L2CAP_START_EVT, &bta_jv, l2cap_socket_id);
}
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_stop_server
- *
- * Description stops an L2CAP server
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_stop_server(tBTA_JV_MSG* p_data) {
- tBTA_JV_L2C_CB* p_cb;
- tBTA_JV_L2CAP_CLOSE evt_data;
- tBTA_JV_API_L2CAP_SERVER* ls = &(p_data->l2cap_server);
- tBTA_JV_L2CAP_CBACK* p_cback;
+/* stops an L2CAP server */
+void bta_jv_l2cap_stop_server(uint16_t local_psm, uint32_t l2cap_socket_id) {
for (int i = 0; i < BTA_JV_MAX_L2C_CONN; i++) {
- if (bta_jv_cb.l2c_cb[i].psm == ls->local_psm) {
- p_cb = &bta_jv_cb.l2c_cb[i];
- p_cback = p_cb->p_cback;
- uint32_t l2cap_socket_id = p_cb->l2cap_socket_id;
+ if (bta_jv_cb.l2c_cb[i].psm == local_psm) {
+ tBTA_JV_L2C_CB* p_cb = &bta_jv_cb.l2c_cb[i];
+ tBTA_JV_L2CAP_CBACK* p_cback = p_cb->p_cback;
+ tBTA_JV_L2CAP_CLOSE evt_data;
evt_data.handle = p_cb->handle;
evt_data.status = bta_jv_free_l2c_cb(p_cb);
evt_data.async = false;
@@ -1291,127 +1139,73 @@
}
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_read
- *
- * Description Read data from an L2CAP connection
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_read(tBTA_JV_MSG* p_data) {
- tBTA_JV_L2CAP_READ evt_data;
- tBTA_JV_API_L2CAP_READ* rc = &(p_data->l2cap_read);
+/* Write data to an L2CAP connection */
+void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, BT_HDR* msg,
+ uint32_t user_id, tBTA_JV_L2C_CB* p_cb) {
+ /* As we check this callback exists before the tBTA_JV_API_L2CAP_WRITE can be
+ * send through the API this check should not be needed. But the API is not
+ * designed to be used (safely at least) in a multi-threaded scheduler, hence
+ * if the peer device disconnects the l2cap link after the API is called, but
+ * before this message is handled, the ->p_cback will be cleared at this
+ * point. At first glanch this seems highly unlikely, but for all
+ * obex-profiles with two channels connected - e.g. MAP, this happens around 1
+ * of 4 disconnects, as a disconnect on the server channel causes a disconnect
+ * to be send on the client (notification) channel, but at the peer typically
+ * disconnects both the OBEX disconnect request crosses the incoming l2cap
+ * disconnect. If p_cback is cleared, we simply discard the data. RISK: The
+ * caller must handle any cleanup based on another signal than
+ * BTA_JV_L2CAP_WRITE_EVT, which is typically not possible, as the pointer to
+ * the allocated buffer is stored in this message, and can therefore not be
+ * freed, hence we have a mem-leak-by-design.*/
+ if (!p_cb->p_cback) {
+ /* As this pointer is checked in the API function, this occurs only when the
+ * channel is disconnected after the API function is called, but before the
+ * message is handled. */
+ LOG(ERROR) << __func__ << ": p_cb->p_cback == NULL";
+ osi_free(msg);
+ return;
+ }
+ tBTA_JV_L2CAP_WRITE evt_data;
evt_data.status = BTA_JV_FAILURE;
- evt_data.handle = rc->handle;
- evt_data.req_id = rc->req_id;
- evt_data.p_data = rc->p_data;
- evt_data.len = 0;
+ evt_data.handle = handle;
+ evt_data.req_id = req_id;
+ evt_data.cong = p_cb->cong;
+ evt_data.len = msg->len;
- if (BT_PASS ==
- GAP_ConnReadData(rc->handle, rc->p_data, rc->len, &evt_data.len)) {
- evt_data.status = BTA_JV_SUCCESS;
+ bta_jv_pm_conn_busy(p_cb->p_pm_cb);
+
+ // TODO: this was set only for non-fixed channel packets. Is that needed ?
+ msg->event = BT_EVT_TO_BTU_SP_DATA;
+
+ if (evt_data.cong) {
+ osi_free(msg);
+ } else {
+ if (GAP_ConnWriteData(handle, msg) == BT_PASS)
+ evt_data.status = BTA_JV_SUCCESS;
}
tBTA_JV bta_jv;
- bta_jv.l2c_read = evt_data;
- rc->p_cback(BTA_JV_L2CAP_READ_EVT, &bta_jv, rc->l2cap_socket_id);
+ bta_jv.l2c_write = evt_data;
+ p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, &bta_jv, user_id);
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_write
- *
- * Description Write data to an L2CAP connection
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_write(tBTA_JV_MSG* p_data) {
- tBTA_JV_L2CAP_WRITE evt_data;
- tBTA_JV_API_L2CAP_WRITE* ls = &(p_data->l2cap_write);
-
- /* As we check this callback exists before the tBTA_JV_API_L2CAP_WRITE can be
- * send through the
- * API this check should not be needed.
- * But the API is not designed to be used (safely at least) in a
- * multi-threaded scheduler, hence
- * if the peer device disconnects the l2cap link after the API is called, but
- * before this
- * message is handled, the ->p_cback will be cleared at this point. At first
- * glanch this seems
- * highly unlikely, but for all obex-profiles with two channels connected -
- * e.g. MAP, this
- * happens around 1 of 4 disconnects, as a disconnect on the server channel
- * causes a disconnect
- * to be send on the client (notification) channel, but at the peer typically
- * disconnects both
- * the OBEX disconnect request crosses the incoming l2cap disconnect.
- * If p_cback is cleared, we simply discard the data.
- * RISK: The caller must handle any cleanup based on another signal than
- * BTA_JV_L2CAP_WRITE_EVT,
- * which is typically not possible, as the pointer to the allocated
- * buffer is stored
- * in this message, and can therefore not be freed, hence we have a
- * mem-leak-by-design.*/
- if (ls->p_cb->p_cback != NULL) {
- evt_data.status = BTA_JV_FAILURE;
- evt_data.handle = ls->handle;
- evt_data.req_id = ls->req_id;
- evt_data.p_data = ls->p_data;
- evt_data.cong = ls->p_cb->cong;
- evt_data.len = 0;
- bta_jv_pm_conn_busy(ls->p_cb->p_pm_cb);
- if (!evt_data.cong &&
- BT_PASS ==
- GAP_ConnWriteData(ls->handle, ls->p_data, ls->len, &evt_data.len)) {
- evt_data.status = BTA_JV_SUCCESS;
- }
- tBTA_JV bta_jv;
- bta_jv.l2c_write = evt_data;
- ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, &bta_jv, ls->user_id);
- } else {
- /* As this pointer is checked in the API function, this occurs only when the
- * channel is
- * disconnected after the API function is called, but before the message is
- * handled. */
- APPL_TRACE_ERROR("%s() ls->p_cb->p_cback == NULL", __func__);
- }
-}
-
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_write_fixed
- *
- * Description Write data to an L2CAP connection using Fixed channels
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_write_fixed(tBTA_JV_MSG* p_data) {
+/* Write data to an L2CAP connection using Fixed channels */
+void bta_jv_l2cap_write_fixed(uint16_t channel, const RawAddress& addr,
+ uint32_t req_id, BT_HDR* msg, uint32_t user_id,
+ tBTA_JV_L2CAP_CBACK* p_cback) {
tBTA_JV_L2CAP_WRITE_FIXED evt_data;
- tBTA_JV_API_L2CAP_WRITE_FIXED* ls = &(p_data->l2cap_write_fixed);
- BT_HDR* msg =
- (BT_HDR*)osi_malloc(sizeof(BT_HDR) + ls->len + L2CAP_MIN_OFFSET);
-
evt_data.status = BTA_JV_FAILURE;
- evt_data.channel = ls->channel;
- evt_data.addr = ls->addr;
- evt_data.req_id = ls->req_id;
- evt_data.p_data = ls->p_data;
+ evt_data.channel = channel;
+ evt_data.addr = addr;
+ evt_data.req_id = req_id;
evt_data.len = 0;
- memcpy(((uint8_t*)(msg + 1)) + L2CAP_MIN_OFFSET, ls->p_data, ls->len);
- msg->len = ls->len;
- msg->offset = L2CAP_MIN_OFFSET;
-
- L2CA_SendFixedChnlData(ls->channel, ls->addr, msg);
+ L2CA_SendFixedChnlData(channel, addr, msg);
tBTA_JV bta_jv;
bta_jv.l2c_write_fixed = evt_data;
- ls->p_cback(BTA_JV_L2CAP_WRITE_FIXED_EVT, &bta_jv, ls->user_id);
+ p_cback(BTA_JV_L2CAP_WRITE_FIXED_EVT, &bta_jv, user_id);
}
/*******************************************************************************
@@ -1428,8 +1222,8 @@
uint16_t len, int type) {
tBTA_JV_RFC_CB* p_cb = bta_jv_rfc_port_to_cb(port_handle);
tBTA_JV_PCB* p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
- APPL_TRACE_DEBUG("%s, p_cb:%p, p_pcb:%p, len:%d, type:%d", __func__, p_cb,
- p_pcb, len, type);
+ VLOG(2) << __func__ << ": p_cb=" << p_cb << ", p_pcb=" << p_pcb
+ << ", len=" << len << ", type=" << type;
if (p_pcb != NULL) {
switch (type) {
case DATA_CO_CALLBACK_TYPE_INCOMING:
@@ -1439,7 +1233,7 @@
case DATA_CO_CALLBACK_TYPE_OUTGOING:
return bta_co_rfc_data_outgoing(p_pcb->rfcomm_slot_id, buf, len);
default:
- APPL_TRACE_ERROR("unknown callout type:%d", type);
+ LOG(ERROR) << __func__ << ": unknown callout type=" << type;
break;
}
}
@@ -1464,12 +1258,11 @@
uint16_t lcid;
tBTA_JV_RFCOMM_CBACK* p_cback; /* the callback function */
- APPL_TRACE_DEBUG("bta_jv_port_mgmt_cl_cback:code:%d, port_handle%d", code,
- port_handle);
+ VLOG(2) << __func__ << ": code=" << code << ", port_handle=" << port_handle;
if (NULL == p_cb || NULL == p_cb->p_cback) return;
- APPL_TRACE_DEBUG("bta_jv_port_mgmt_cl_cback code=%d port_handle:%d handle:%d",
- code, port_handle, p_cb->handle);
+ VLOG(2) << __func__ << ": code=" << code << ", port_handle=" << port_handle
+ << ", handle=" << p_cb->handle;
PORT_CheckConnection(port_handle, rem_bda, &lcid);
@@ -1509,12 +1302,11 @@
tBTA_JV_PCB* p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
tBTA_JV evt_data;
- APPL_TRACE_DEBUG("bta_jv_port_event_cl_cback:%d", port_handle);
+ VLOG(2) << __func__ << ": port_handle=" << port_handle;
if (NULL == p_cb || NULL == p_cb->p_cback) return;
- APPL_TRACE_DEBUG(
- "bta_jv_port_event_cl_cback code=x%x port_handle:%d handle:%d", code,
- port_handle, p_cb->handle);
+ VLOG(2) << __func__ << ": code=" << loghex(code)
+ << ", port_handle=" << port_handle << ", handle=" << p_cb->handle;
if (code & PORT_EV_RXCHAR) {
evt_data.data_ind.handle = p_cb->handle;
p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, p_pcb->rfcomm_slot_id);
@@ -1533,57 +1325,50 @@
}
}
-/*******************************************************************************
- *
- * Function bta_jv_rfcomm_connect
- *
- * Description Client initiates an RFCOMM connection
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_rfcomm_connect(tBTA_JV_MSG* p_data) {
+/* Client initiates an RFCOMM connection */
+void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ uint8_t remote_scn, const RawAddress& peer_bd_addr,
+ tBTA_JV_RFCOMM_CBACK* p_cback,
+ uint32_t rfcomm_slot_id) {
uint16_t handle = 0;
uint32_t event_mask = BTA_JV_RFC_EV_MASK;
tPORT_STATE port_state;
- uint8_t sec_id = 0;
- tBTA_JV_RFC_CB* p_cb = NULL;
- tBTA_JV_PCB* p_pcb;
- tBTA_JV_API_RFCOMM_CONNECT* cc = &(p_data->rfcomm_connect);
- tBTA_JV_RFCOMM_CL_INIT evt_data;
/* TODO DM role manager
- L2CA_SetDesireRole(cc->role);
+ L2CA_SetDesireRole(role);
*/
- sec_id = bta_jv_alloc_sec_id();
+ uint8_t sec_id = bta_jv_alloc_sec_id();
+
+ tBTA_JV_RFCOMM_CL_INIT evt_data;
memset(&evt_data, 0, sizeof(evt_data));
evt_data.sec_id = sec_id;
evt_data.status = BTA_JV_SUCCESS;
if (0 == sec_id ||
- BTM_SetSecurityLevel(true, "", sec_id, cc->sec_mask, BT_PSM_RFCOMM,
- BTM_SEC_PROTO_RFCOMM, cc->remote_scn) == false) {
+ !BTM_SetSecurityLevel(true, "", sec_id, sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, remote_scn)) {
evt_data.status = BTA_JV_FAILURE;
- APPL_TRACE_ERROR(
- "sec_id:%d is zero or BTM_SetSecurityLevel failed, remote_scn:%d",
- sec_id, cc->remote_scn);
+ LOG(ERROR) << __func__ << ": sec_id=" << +sec_id
+ << " is zero or BTM_SetSecurityLevel failed, remote_scn:"
+ << +remote_scn;
}
if (evt_data.status == BTA_JV_SUCCESS &&
- RFCOMM_CreateConnection(UUID_SERVCLASS_SERIAL_PORT, cc->remote_scn, false,
- BTA_JV_DEF_RFC_MTU, cc->peer_bd_addr, &handle,
+ RFCOMM_CreateConnection(UUID_SERVCLASS_SERIAL_PORT, remote_scn, false,
+ BTA_JV_DEF_RFC_MTU, peer_bd_addr, &handle,
bta_jv_port_mgmt_cl_cback) != PORT_SUCCESS) {
- APPL_TRACE_ERROR("bta_jv_rfcomm_connect, RFCOMM_CreateConnection failed");
+ LOG(ERROR) << __func__ << ": RFCOMM_CreateConnection failed";
evt_data.status = BTA_JV_FAILURE;
}
if (evt_data.status == BTA_JV_SUCCESS) {
- p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
+ tBTA_JV_PCB* p_pcb;
+ tBTA_JV_RFC_CB* p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
if (p_cb) {
- p_cb->p_cback = cc->p_cback;
+ p_cb->p_cback = p_cback;
p_cb->sec_id = sec_id;
p_cb->scn = 0;
p_pcb->state = BTA_JV_ST_CL_OPENING;
- p_pcb->rfcomm_slot_id = cc->rfcomm_slot_id;
+ p_pcb->rfcomm_slot_id = rfcomm_slot_id;
evt_data.use_co = true;
PORT_SetEventCallback(handle, bta_jv_port_event_cl_cback);
@@ -1599,12 +1384,12 @@
evt_data.handle = p_cb->handle;
} else {
evt_data.status = BTA_JV_FAILURE;
- APPL_TRACE_ERROR("run out of rfc control block");
+ LOG(ERROR) << __func__ << ": run out of rfc control block";
}
}
tBTA_JV bta_jv;
bta_jv.rfc_cl_init = evt_data;
- cc->p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, &bta_jv, cc->rfcomm_slot_id);
+ p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, &bta_jv, rfcomm_slot_id);
if (bta_jv.rfc_cl_init.status == BTA_JV_FAILURE) {
if (sec_id) bta_jv_free_sec_id(&sec_id);
if (handle) RFCOMM_RemoveConnection(handle);
@@ -1622,41 +1407,34 @@
if (rfc_handle && bta_jv_cb.port_cb[i].rfcomm_slot_id == rfcomm_slot_id) {
*pcb = &bta_jv_cb.port_cb[i];
*cb = &bta_jv_cb.rfc_cb[rfc_handle - 1];
- APPL_TRACE_DEBUG(
- "find_rfc_pcb(): FOUND rfc_cb_handle 0x%x, port.jv_handle:"
- " 0x%x, state: %d, rfc_cb->handle: 0x%x",
- rfc_handle, (*pcb)->handle, (*pcb)->state, (*cb)->handle);
+ VLOG(2) << __func__ << ": FOUND rfc_cb_handle=" << loghex(rfc_handle)
+ << ", port.jv_handle=" << loghex((*pcb)->handle)
+ << ", state=" << (*pcb)->state
+ << ", rfc_cb->handle=" << loghex((*cb)->handle);
return 1;
}
}
- APPL_TRACE_DEBUG("find_rfc_pcb: cannot find rfc_cb from user data: %u",
- rfcomm_slot_id);
+ VLOG(2) << __func__
+ << ": cannot find rfc_cb from user data:" << rfcomm_slot_id;
return 0;
}
-/*******************************************************************************
- *
- * Function bta_jv_rfcomm_close
- *
- * Description Close an RFCOMM connection
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_rfcomm_close(tBTA_JV_MSG* p_data) {
- tBTA_JV_API_RFCOMM_CLOSE* cc = &(p_data->rfcomm_close);
- tBTA_JV_RFC_CB* p_cb = NULL;
- tBTA_JV_PCB* p_pcb = NULL;
- APPL_TRACE_DEBUG("bta_jv_rfcomm_close, rfc handle:%d", cc->handle);
- if (!cc->handle) {
- APPL_TRACE_ERROR("bta_jv_rfcomm_close, rfc handle is null");
+/* Close an RFCOMM connection */
+void bta_jv_rfcomm_close(uint32_t handle, uint32_t rfcomm_slot_id) {
+ if (!handle) {
+ LOG(ERROR) << __func__ << ": rfc handle is null";
return;
}
- if (!find_rfc_pcb(cc->rfcomm_slot_id, &p_cb, &p_pcb)) return;
+ VLOG(2) << __func__ << ": rfc handle=" << handle;
+
+ tBTA_JV_RFC_CB* p_cb = NULL;
+ tBTA_JV_PCB* p_pcb = NULL;
+
+ if (!find_rfc_pcb(rfcomm_slot_id, &p_cb, &p_pcb)) return;
bta_jv_free_rfc_cb(p_cb, p_pcb);
- APPL_TRACE_DEBUG("bta_jv_rfcomm_close: sec id in use:%d, rfc_cb in use:%d",
- get_sec_id_used(), get_rfc_cb_used());
+ VLOG(2) << __func__ << ": sec id in use=" << get_sec_id_used()
+ << ", rfc_cb in use=" << get_rfc_cb_used();
}
/*******************************************************************************
@@ -1675,18 +1453,17 @@
tBTA_JV evt_data;
RawAddress rem_bda;
uint16_t lcid;
- APPL_TRACE_DEBUG("bta_jv_port_mgmt_sr_cback, code:%d, port_handle:%d", code,
- port_handle);
+ VLOG(2) << __func__ << ": code=" << code << ", port_handle=" << port_handle;
if (NULL == p_cb || NULL == p_cb->p_cback) {
- APPL_TRACE_ERROR("bta_jv_port_mgmt_sr_cback, p_cb:%p, p_cb->p_cback%p",
- p_cb, p_cb ? p_cb->p_cback : NULL);
+ LOG(ERROR) << __func__ << ": p_cb=" << p_cb
+ << ", p_cb->p_cback=" << (p_cb ? p_cb->p_cback : 0);
return;
}
uint32_t rfcomm_slot_id = p_pcb->rfcomm_slot_id;
- APPL_TRACE_DEBUG(
- "bta_jv_port_mgmt_sr_cback code=%d port_handle:0x%x handle:0x%x, "
- "p_pcb:%p, user:%d",
- code, port_handle, p_cb->handle, p_pcb, p_pcb->rfcomm_slot_id);
+ VLOG(2) << __func__ << ": code=" << code
+ << ", port_handle=" << loghex(port_handle)
+ << ", handle=" << loghex(p_cb->handle) << ", p_pcb" << p_pcb
+ << ", user=" << p_pcb->rfcomm_slot_id;
PORT_CheckConnection(port_handle, rem_bda, &lcid);
int failed = true;
@@ -1699,11 +1476,11 @@
evt_data.rfc_srv_open.new_listen_handle = p_pcb_new_listen->handle;
p_pcb_new_listen->rfcomm_slot_id =
p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, rfcomm_slot_id);
- APPL_TRACE_DEBUG("PORT_SUCCESS: curr_sess:%d, max_sess:%d",
- p_cb->curr_sess, p_cb->max_sess);
+ VLOG(2) << __func__ << ": curr_sess=" << p_cb->curr_sess
+ << ", max_sess=" << p_cb->max_sess;
failed = false;
} else
- APPL_TRACE_ERROR("bta_jv_add_rfc_port failed to create new listen port");
+ LOG(ERROR) << __func__ << ": failed to create new listen port";
}
if (failed) {
evt_data.rfc_close.handle = p_cb->handle;
@@ -1713,9 +1490,9 @@
p_pcb->cong = false;
tBTA_JV_RFCOMM_CBACK* p_cback = p_cb->p_cback;
- APPL_TRACE_DEBUG(
- "PORT_CLOSED before BTA_JV_RFCOMM_CLOSE_EVT: curr_sess:%d, max_sess:%d",
- p_cb->curr_sess, p_cb->max_sess);
+ VLOG(2) << __func__
+ << ": PORT_CLOSED before BTA_JV_RFCOMM_CLOSE_EVT: curr_sess="
+ << p_cb->curr_sess << ", max_sess=" << p_cb->max_sess;
if (BTA_JV_ST_SR_CLOSING == p_pcb->state) {
evt_data.rfc_close.async = false;
evt_data.rfc_close.status = BTA_JV_SUCCESS;
@@ -1724,9 +1501,9 @@
p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, rfcomm_slot_id);
// bta_jv_free_rfc_cb(p_cb, p_pcb);
- APPL_TRACE_DEBUG(
- "PORT_CLOSED after BTA_JV_RFCOMM_CLOSE_EVT: curr_sess:%d, max_sess:%d",
- p_cb->curr_sess, p_cb->max_sess);
+ VLOG(2) << __func__
+ << ": PORT_CLOSED after BTA_JV_RFCOMM_CLOSE_EVT: curr_sess="
+ << p_cb->curr_sess << ", max_sess=" << p_cb->max_sess;
}
}
@@ -1746,9 +1523,8 @@
if (NULL == p_cb || NULL == p_cb->p_cback) return;
- APPL_TRACE_DEBUG(
- "bta_jv_port_event_sr_cback code=x%x port_handle:%d handle:%d", code,
- port_handle, p_cb->handle);
+ VLOG(2) << __func__ << ": code=" << loghex(code)
+ << ", port_handle=" << port_handle << ", handle=" << p_cb->handle;
uint32_t user_data = p_pcb->rfcomm_slot_id;
if (code & PORT_EV_RXCHAR) {
@@ -1792,17 +1568,15 @@
if (p_pcb->state == BTA_JV_ST_SR_LISTEN) {
listen++;
if (p_pcb_open == p_pcb) {
- APPL_TRACE_DEBUG(
- "bta_jv_add_rfc_port, port_handle:%d, change the listen port "
- "to open state",
- p_pcb->port_handle);
+ VLOG(2) << __func__ << ": port_handle=" << p_pcb->port_handle
+ << ", change the listen port to open state";
p_pcb->state = BTA_JV_ST_SR_OPEN;
} else {
- APPL_TRACE_ERROR(
- "bta_jv_add_rfc_port, open pcb not matching listen one,"
- "listen count:%d, listen pcb handle:%d, open pcb:%d",
- listen, p_pcb->port_handle, p_pcb_open->handle);
+ LOG(ERROR) << __func__
+ << ": open pcb not matching listen one, count=" << listen
+ << ", listen pcb handle=" << p_pcb->port_handle
+ << ", open pcb=" << p_pcb_open->handle;
return NULL;
}
}
@@ -1812,9 +1586,9 @@
}
}
- APPL_TRACE_DEBUG(
- "bta_jv_add_rfc_port max_sess=%d used:%d curr_sess:%d, listen:%d si:%d",
- p_cb->max_sess, used, p_cb->curr_sess, listen, si);
+ VLOG(2) << __func__ << ": max_sess=" << p_cb->max_sess << ", used=" << used
+ << ", curr_sess=" << p_cb->curr_sess << ", listen=" << listen
+ << ", si=" << si;
if (used < p_cb->max_sess && listen == 1 && si) {
si--;
if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, true,
@@ -1837,80 +1611,69 @@
PORT_SetState(p_pcb->port_handle, &port_state);
p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si);
- APPL_TRACE_DEBUG(
- "bta_jv_add_rfc_port: p_pcb->handle:0x%x, curr_sess:%d",
- p_pcb->handle, p_cb->curr_sess);
+ VLOG(2) << __func__ << ": p_pcb->handle=" << loghex(p_pcb->handle)
+ << ", curr_sess=" << p_cb->curr_sess;
}
- } else
- APPL_TRACE_ERROR(
- "bta_jv_add_rfc_port, cannot create new rfc listen port");
+ } else {
+ LOG(ERROR) << __func__ << ": cannot create new rfc listen port";
+ return NULL;
+ }
}
- APPL_TRACE_DEBUG("bta_jv_add_rfc_port: sec id in use:%d, rfc_cb in use:%d",
- get_sec_id_used(), get_rfc_cb_used());
+ VLOG(2) << __func__ << ": sec id in use=" << get_sec_id_used()
+ << ", rfc_cb in use=" << get_rfc_cb_used();
return p_pcb;
}
-/*******************************************************************************
- *
- * Function bta_jv_rfcomm_start_server
- *
- * Description waits for an RFCOMM client to connect
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_rfcomm_start_server(tBTA_JV_MSG* p_data) {
+/* waits for an RFCOMM client to connect */
+void bta_jv_rfcomm_start_server(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ uint8_t local_scn, uint8_t max_session,
+ tBTA_JV_RFCOMM_CBACK* p_cback,
+ uint32_t rfcomm_slot_id) {
uint16_t handle = 0;
uint32_t event_mask = BTA_JV_RFC_EV_MASK;
tPORT_STATE port_state;
uint8_t sec_id = 0;
tBTA_JV_RFC_CB* p_cb = NULL;
tBTA_JV_PCB* p_pcb;
- tBTA_JV_API_RFCOMM_SERVER* rs = &(p_data->rfcomm_server);
tBTA_JV_RFCOMM_START evt_data;
/* TODO DM role manager
- L2CA_SetDesireRole(rs->role);
+ L2CA_SetDesireRole(role);
*/
memset(&evt_data, 0, sizeof(evt_data));
evt_data.status = BTA_JV_FAILURE;
- APPL_TRACE_DEBUG(
- "bta_jv_rfcomm_start_server: sec id in use:%d, rfc_cb in use:%d",
- get_sec_id_used(), get_rfc_cb_used());
+ VLOG(2) << __func__ << ": sec id in use=" << get_sec_id_used()
+ << ", rfc_cb in use=" << get_rfc_cb_used();
do {
sec_id = bta_jv_alloc_sec_id();
if (0 == sec_id ||
- BTM_SetSecurityLevel(false, "JV PORT", sec_id, rs->sec_mask,
- BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM,
- rs->local_scn) == false) {
- APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, run out of sec_id");
+ !BTM_SetSecurityLevel(false, "JV PORT", sec_id, sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, local_scn)) {
+ LOG(ERROR) << __func__ << ": run out of sec_id";
break;
}
- if (RFCOMM_CreateConnection(sec_id, rs->local_scn, true, BTA_JV_DEF_RFC_MTU,
+ if (RFCOMM_CreateConnection(sec_id, local_scn, true, BTA_JV_DEF_RFC_MTU,
RawAddress::kAny, &handle,
bta_jv_port_mgmt_sr_cback) != PORT_SUCCESS) {
- APPL_TRACE_ERROR(
- "bta_jv_rfcomm_start_server, RFCOMM_CreateConnection failed");
+ LOG(ERROR) << __func__ << ": RFCOMM_CreateConnection failed";
break;
}
p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
if (!p_cb) {
- APPL_TRACE_ERROR(
- "bta_jv_rfcomm_start_server, run out of rfc control block");
+ LOG(ERROR) << __func__ << ": run out of rfc control block";
break;
}
- p_cb->max_sess = rs->max_session;
- p_cb->p_cback = rs->p_cback;
+ p_cb->max_sess = max_session;
+ p_cb->p_cback = p_cback;
p_cb->sec_id = sec_id;
- p_cb->scn = rs->local_scn;
+ p_cb->scn = local_scn;
p_pcb->state = BTA_JV_ST_SR_LISTEN;
- p_pcb->rfcomm_slot_id = rs->rfcomm_slot_id;
+ p_pcb->rfcomm_slot_id = rfcomm_slot_id;
evt_data.status = BTA_JV_SUCCESS;
evt_data.handle = p_cb->handle;
evt_data.sec_id = sec_id;
@@ -1928,7 +1691,7 @@
tBTA_JV bta_jv;
bta_jv.rfc_start = evt_data;
- rs->p_cback(BTA_JV_RFCOMM_START_EVT, &bta_jv, rs->rfcomm_slot_id);
+ p_cback(BTA_JV_RFCOMM_START_EVT, &bta_jv, rfcomm_slot_id);
if (bta_jv.rfc_start.status == BTA_JV_SUCCESS) {
PORT_SetDataCOCallback(handle, bta_jv_port_data_co_cback);
} else {
@@ -1937,58 +1700,37 @@
}
}
-/*******************************************************************************
- *
- * Function bta_jv_rfcomm_stop_server
- *
- * Description stops an RFCOMM server
- *
- * Returns void
- *
- ******************************************************************************/
-
-void bta_jv_rfcomm_stop_server(tBTA_JV_MSG* p_data) {
- tBTA_JV_API_RFCOMM_SERVER* ls = &(p_data->rfcomm_server);
- tBTA_JV_RFC_CB* p_cb = NULL;
- tBTA_JV_PCB* p_pcb = NULL;
- APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server");
- if (!ls->handle) {
- APPL_TRACE_ERROR("bta_jv_rfcomm_stop_server, jv handle is null");
+/* stops an RFCOMM server */
+void bta_jv_rfcomm_stop_server(uint32_t handle, uint32_t rfcomm_slot_id) {
+ if (!handle) {
+ LOG(ERROR) << __func__ << ": jv handle is null";
return;
}
- if (!find_rfc_pcb(ls->rfcomm_slot_id, &p_cb, &p_pcb)) return;
- APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: p_pcb:%p, p_pcb->port_handle:%d",
- p_pcb, p_pcb->port_handle);
+ VLOG(2) << __func__;
+ tBTA_JV_RFC_CB* p_cb = NULL;
+ tBTA_JV_PCB* p_pcb = NULL;
+
+ if (!find_rfc_pcb(rfcomm_slot_id, &p_cb, &p_pcb)) return;
+ VLOG(2) << __func__ << ": p_pcb=" << p_pcb
+ << ", p_pcb->port_handle=" << p_pcb->port_handle;
bta_jv_free_rfc_cb(p_cb, p_pcb);
- APPL_TRACE_DEBUG(
- "bta_jv_rfcomm_stop_server: sec id in use:%d, rfc_cb in use:%d",
- get_sec_id_used(), get_rfc_cb_used());
+ VLOG(2) << __func__ << ": sec id in use=" << get_sec_id_used()
+ << ", rfc_cb in use=" << get_rfc_cb_used();
}
-/*******************************************************************************
- *
- * Function bta_jv_rfcomm_write
- *
- * Description write data to an RFCOMM connection
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_rfcomm_write(tBTA_JV_MSG* p_data) {
- tBTA_JV_API_RFCOMM_WRITE* wc = &(p_data->rfcomm_write);
- tBTA_JV_RFC_CB* p_cb = wc->p_cb;
- tBTA_JV_PCB* p_pcb = wc->p_pcb;
-
+/* write data to an RFCOMM connection */
+void bta_jv_rfcomm_write(uint32_t handle, uint32_t req_id, tBTA_JV_RFC_CB* p_cb,
+ tBTA_JV_PCB* p_pcb) {
if (p_pcb->state == BTA_JV_ST_NONE) {
- APPL_TRACE_ERROR("%s in state BTA_JV_ST_NONE - cannot write", __func__);
+ LOG(ERROR) << __func__ << ": in state BTA_JV_ST_NONE - cannot write";
return;
}
tBTA_JV_RFCOMM_WRITE evt_data;
evt_data.status = BTA_JV_FAILURE;
- evt_data.handle = p_cb->handle;
- evt_data.req_id = wc->req_id;
+ evt_data.handle = handle;
+ evt_data.req_id = req_id;
evt_data.cong = p_pcb->cong;
evt_data.len = 0;
@@ -2002,101 +1744,45 @@
// Update congestion flag
evt_data.cong = p_pcb->cong;
- if (p_cb->p_cback) {
- tBTA_JV bta_jv;
- bta_jv.rfc_write = evt_data;
- p_cb->p_cback(BTA_JV_RFCOMM_WRITE_EVT, &bta_jv, p_pcb->rfcomm_slot_id);
- } else {
- APPL_TRACE_ERROR("%s No JV callback set", __func__);
+ if (!p_cb->p_cback) {
+ LOG(ERROR) << __func__ << ": No JV callback set";
+ return;
}
+
+ tBTA_JV bta_jv;
+ bta_jv.rfc_write = evt_data;
+ p_cb->p_cback(BTA_JV_RFCOMM_WRITE_EVT, &bta_jv, p_pcb->rfcomm_slot_id);
}
-/*******************************************************************************
- *
- * Function bta_jv_set_pm_profile
- *
- * Description Set or free power mode profile for a JV application
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_set_pm_profile(tBTA_JV_MSG* p_data) {
+/* Set or free power mode profile for a JV application */
+void bta_jv_set_pm_profile(uint32_t handle, tBTA_JV_PM_ID app_id,
+ tBTA_JV_CONN_STATE init_st) {
tBTA_JV_STATUS status;
tBTA_JV_PM_CB* p_cb;
- APPL_TRACE_API("bta_jv_set_pm_profile(handle: 0x%x, app_id: %d, init_st: %d)",
- p_data->set_pm.handle, p_data->set_pm.app_id,
- p_data->set_pm.init_st);
+ VLOG(2) << __func__ << " handle=" << loghex(handle) << ", app_id=" << app_id
+ << ", init_st=" << +init_st;
/* clear PM control block */
- if (p_data->set_pm.app_id == BTA_JV_PM_ID_CLEAR) {
- status = bta_jv_free_set_pm_profile_cb(p_data->set_pm.handle);
+ if (app_id == BTA_JV_PM_ID_CLEAR) {
+ status = bta_jv_free_set_pm_profile_cb(handle);
if (status != BTA_JV_SUCCESS) {
- APPL_TRACE_WARNING("bta_jv_set_pm_profile() free pm cb failed: reason %d",
- status);
+ LOG(WARNING) << __func__ << ": free pm cb failed: reason=" << +status;
}
} else /* set PM control block */
{
- p_cb = bta_jv_alloc_set_pm_profile_cb(p_data->set_pm.handle,
- p_data->set_pm.app_id);
+ p_cb = bta_jv_alloc_set_pm_profile_cb(handle, app_id);
if (NULL != p_cb)
- bta_jv_pm_state_change(p_cb, p_data->set_pm.init_st);
+ bta_jv_pm_state_change(p_cb, init_st);
else
- APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb() failed");
+ LOG(WARNING) << __func__ << ": failed";
}
}
/*******************************************************************************
*
- * Function bta_jv_change_pm_state
- *
- * Description change jv pm connect state, used internally
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_change_pm_state(tBTA_JV_MSG* p_data) {
- tBTA_JV_API_PM_STATE_CHANGE* p_msg = (tBTA_JV_API_PM_STATE_CHANGE*)p_data;
-
- if (p_msg->p_cb) bta_jv_pm_state_change(p_msg->p_cb, p_msg->state);
-}
-
-/*******************************************************************************
- *
- * Function bta_jv_set_pm_conn_state
- *
- * Description Send pm event state change to jv state machine to serialize jv pm
- * changes in relation to other jv messages. internal API use
- * mainly.
- *
- * Params: p_cb: jv pm control block, NULL pointer returns failure
- * new_state: new PM connections state, setting is forced by action
- * function
- *
- * Returns BTA_JV_SUCCESS, BTA_JV_FAILURE (buffer allocation, or NULL ptr!)
- *
- ******************************************************************************/
-tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB* p_cb,
- const tBTA_JV_CONN_STATE new_st) {
- if (p_cb == NULL) return BTA_JV_FAILURE;
-
- APPL_TRACE_API("%s: handle:0x%x, state: %d", __func__, p_cb->handle, new_st);
-
- tBTA_JV_API_PM_STATE_CHANGE* p_msg = (tBTA_JV_API_PM_STATE_CHANGE*)osi_malloc(
- sizeof(tBTA_JV_API_PM_STATE_CHANGE));
- p_msg->hdr.event = BTA_JV_API_PM_STATE_CHANGE_EVT;
- p_msg->p_cb = p_cb;
- p_msg->state = new_st;
-
- bta_sys_sendmsg(p_msg);
-
- return BTA_JV_SUCCESS;
-}
-
-/*******************************************************************************
- *
* Function bta_jv_pm_conn_busy
*
* Description set pm connection busy state (input param safe)
@@ -2140,10 +1826,10 @@
******************************************************************************/
static void bta_jv_pm_state_change(tBTA_JV_PM_CB* p_cb,
const tBTA_JV_CONN_STATE state) {
- APPL_TRACE_API(
- "bta_jv_pm_state_change(p_cb: 0x%x, handle: 0x%x, busy/idle_state: %d"
- ", app_id: %d, conn_state: %d)",
- p_cb, p_cb->handle, p_cb->state, p_cb->app_id, state);
+ VLOG(2) << __func__ << ": p_cb=" << p_cb
+ << ", handle=" << loghex(p_cb->handle)
+ << ", busy/idle_state=" << p_cb->state << ", app_id=" << p_cb->app_id
+ << ", conn_state=" << state;
switch (state) {
case BTA_JV_CONN_OPEN:
@@ -2181,8 +1867,7 @@
break;
default:
- APPL_TRACE_WARNING("bta_jv_pm_state_change(state: %d): Invalid state",
- state);
+ LOG(WARNING) << __func__ << ": Invalid state=" << +state;
break;
}
}
@@ -2439,17 +2124,11 @@
if (sock_cback) sock_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, sock_id);
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_connect_le
- *
- * Description makes an le l2cap client connection
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_connect_le(tBTA_JV_MSG* p_data) {
- tBTA_JV_API_L2CAP_CONNECT* cc = &(p_data->l2cap_connect);
+/** makes an le l2cap client connection */
+void bta_jv_l2cap_connect_le(uint16_t remote_chan,
+ const RawAddress& peer_bd_addr,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id) {
tBTA_JV evt;
uint32_t id;
char call_init_f = true;
@@ -2458,15 +2137,15 @@
evt.l2c_cl_init.handle = GAP_INVALID_HANDLE;
evt.l2c_cl_init.status = BTA_JV_FAILURE;
- t = fcclient_alloc(cc->remote_chan, false, NULL);
+ t = fcclient_alloc(remote_chan, false, NULL);
if (!t) {
- cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, cc->l2cap_socket_id);
+ p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, l2cap_socket_id);
return;
}
- t->p_cback = cc->p_cback;
- t->l2cap_socket_id = cc->l2cap_socket_id;
- t->remote_addr = cc->peer_bd_addr;
+ t->p_cback = p_cback;
+ t->l2cap_socket_id = l2cap_socket_id;
+ t->remote_addr = peer_bd_addr;
id = t->id;
t->init_called = false;
@@ -2483,37 +2162,24 @@
else
fcclient_free(t);
}
- if (call_init_f)
- cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, cc->l2cap_socket_id);
+ if (call_init_f) p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, l2cap_socket_id);
t->init_called = true;
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_stop_server_le
- *
- * Description stops an LE L2CAP server
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_stop_server_le(tBTA_JV_MSG* p_data) {
- tBTA_JV evt;
- tBTA_JV_API_L2CAP_SERVER* ls = &(p_data->l2cap_server);
- tBTA_JV_L2CAP_CBACK* p_cback = NULL;
- struct fc_channel* fcchan;
+/* stops an LE L2CAP server */
+void bta_jv_l2cap_stop_server_le(uint16_t local_chan) {
struct fc_client* fcclient;
- uint32_t l2cap_socket_id;
+ tBTA_JV evt;
evt.l2c_close.status = BTA_JV_FAILURE;
evt.l2c_close.async = false;
evt.l2c_close.handle = GAP_INVALID_HANDLE;
- fcchan = fcchan_get(ls->local_chan, false);
+ struct fc_channel* fcchan = fcchan_get(local_chan, false);
if (fcchan) {
while ((fcclient = fcchan->clients)) {
- p_cback = fcclient->p_cback;
- l2cap_socket_id = fcclient->l2cap_socket_id;
+ tBTA_JV_L2CAP_CBACK* p_cback = fcclient->p_cback;
+ uint32_t l2cap_socket_id = fcclient->l2cap_socket_id;
evt.l2c_close.handle = fcclient->id;
evt.l2c_close.status = BTA_JV_SUCCESS;
@@ -2526,28 +2192,19 @@
}
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_start_server_le
- *
- * Description starts an LE L2CAP server
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_jv_l2cap_start_server_le(tBTA_JV_MSG* p_data) {
- tBTA_JV_API_L2CAP_SERVER* ss = &(p_data->l2cap_server);
+/** starts an LE L2CAP server */
+void bta_jv_l2cap_start_server_le(uint16_t local_chan,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id) {
tBTA_JV_L2CAP_START evt_data;
- struct fc_client* t;
-
evt_data.handle = GAP_INVALID_HANDLE;
evt_data.status = BTA_JV_FAILURE;
- t = fcclient_alloc(ss->local_chan, true, NULL);
+ struct fc_client* t = fcclient_alloc(local_chan, true, NULL);
if (!t) goto out;
- t->p_cback = ss->p_cback;
- t->l2cap_socket_id = ss->l2cap_socket_id;
+ t->p_cback = p_cback;
+ t->l2cap_socket_id = l2cap_socket_id;
// if we got here, we're registered...
evt_data.status = BTA_JV_SUCCESS;
@@ -2557,22 +2214,11 @@
out:
tBTA_JV bta_jv;
bta_jv.l2c_start = evt_data;
- ss->p_cback(BTA_JV_L2CAP_START_EVT, &bta_jv, ss->l2cap_socket_id);
+ p_cback(BTA_JV_L2CAP_START_EVT, &bta_jv, l2cap_socket_id);
}
-/*******************************************************************************
- *
- * Function bta_jv_l2cap_close_fixed
- *
- * Description close a fixed channel connection. calls no callbacks. idempotent
- *
- * Returns void
- *
- ******************************************************************************/
-extern void bta_jv_l2cap_close_fixed(tBTA_JV_MSG* p_data) {
- tBTA_JV_API_L2CAP_CLOSE* cc = &(p_data->l2cap_close);
- struct fc_client* t;
-
- t = fcclient_find_by_id(cc->handle);
+/* close a fixed channel connection. calls no callbacks. idempotent */
+extern void bta_jv_l2cap_close_fixed(uint32_t handle) {
+ struct fc_client* t = fcclient_find_by_id(handle);
if (t) fcclient_free(t);
}
diff --git a/bta/jv/bta_jv_api.cc b/bta/jv/bta_jv_api.cc
index 0478a3b..74818b6 100644
--- a/bta/jv/bta_jv_api.cc
+++ b/bta/jv/bta_jv_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,10 +22,14 @@
* Technology (JABWT) as specified by the JSR82 specificiation
*
******************************************************************************/
+#include <base/bind.h>
+#include <base/bind_helpers.h>
+#include <base/logging.h>
#include <string.h>
#include "bt_common.h"
#include "bta_api.h"
+#include "bta_closure_api.h"
#include "bta_jv_api.h"
#include "bta_jv_int.h"
#include "bta_sys.h"
@@ -34,11 +38,12 @@
#include "sdp_api.h"
#include "utl.h"
-/*****************************************************************************
- * Constants
- ****************************************************************************/
+using base::Bind;
+using bluetooth::Uuid;
-static const tBTA_SYS_REG bta_jv_reg = {bta_jv_sm_execute, NULL};
+namespace {
+bool bta_jv_enabled = false;
+}
/*******************************************************************************
*
@@ -55,52 +60,32 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK* p_cback) {
- tBTA_JV_STATUS status = BTA_JV_FAILURE;
- int i;
-
- APPL_TRACE_API("BTA_JvEnable");
- if (p_cback && false == bta_sys_is_register(BTA_ID_JV)) {
- memset(&bta_jv_cb, 0, sizeof(tBTA_JV_CB));
- /* set handle to invalid value by default */
- for (i = 0; i < BTA_JV_PM_MAX_NUM; i++) {
- bta_jv_cb.pm_cb[i].handle = BTA_JV_PM_HANDLE_CLEAR;
- }
-
- /* register with BTA system manager */
- bta_sys_register(BTA_ID_JV, &bta_jv_reg);
-
- if (p_cback) {
- tBTA_JV_API_ENABLE* p_buf =
- (tBTA_JV_API_ENABLE*)osi_malloc(sizeof(tBTA_JV_API_ENABLE));
- p_buf->hdr.event = BTA_JV_API_ENABLE_EVT;
- p_buf->p_cback = p_cback;
- bta_sys_sendmsg(p_buf);
- status = BTA_JV_SUCCESS;
- }
- } else {
- APPL_TRACE_ERROR("JVenable fails");
+ if (!p_cback || bta_jv_enabled) {
+ LOG(ERROR) << __func__ << ": failure";
+ return BTA_JV_FAILURE;
}
- return (status);
+
+ VLOG(2) << __func__;
+
+ memset(&bta_jv_cb, 0, sizeof(tBTA_JV_CB));
+ /* set handle to invalid value by default */
+ for (int i = 0; i < BTA_JV_PM_MAX_NUM; i++) {
+ bta_jv_cb.pm_cb[i].handle = BTA_JV_PM_HANDLE_CLEAR;
+ }
+
+ bta_jv_enabled = true;
+
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_enable, p_cback));
+ return BTA_JV_SUCCESS;
}
-/*******************************************************************************
- *
- * Function BTA_JvDisable
- *
- * Description Disable the Java I/F
- *
- * Returns void
- *
- ******************************************************************************/
+/** Disable the Java I/F */
void BTA_JvDisable(void) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
+ bta_jv_enabled = false;
- bta_sys_deregister(BTA_ID_JV);
- p_buf->event = BTA_JV_API_DISABLE_EVT;
-
- bta_sys_sendmsg(p_buf);
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_disable));
}
/*******************************************************************************
@@ -143,32 +128,20 @@
* channel Only used for RFCOMM - to try to allocate a specific RFCOMM
* channel.
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
+ * Returns void
*
******************************************************************************/
-tBTA_JV_STATUS BTA_JvGetChannelId(int conn_type, uint32_t id, int32_t channel) {
- tBTA_JV_API_ALLOC_CHANNEL* p_msg =
- (tBTA_JV_API_ALLOC_CHANNEL*)osi_malloc(sizeof(tBTA_JV_API_ALLOC_CHANNEL));
+void BTA_JvGetChannelId(int conn_type, uint32_t id, int32_t channel) {
+ VLOG(2) << __func__ << ": conn_type=" << conn_type;
- APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_JV_API_GET_CHANNEL_EVT;
- p_msg->type = conn_type;
- p_msg->channel = channel;
- if (conn_type == BTA_JV_CONN_TYPE_RFCOMM) {
- p_msg->rfcomm_slot_id = id;
- } else if (conn_type == BTA_JV_CONN_TYPE_L2CAP ||
- conn_type == BTA_JV_CONN_TYPE_L2CAP_LE) {
- p_msg->l2cap_socket_id = id;
- } else {
- APPL_TRACE_ERROR("%s: Invalid connection type");
- return BTA_JV_FAILURE;
+ if (conn_type != BTA_JV_CONN_TYPE_RFCOMM &&
+ conn_type != BTA_JV_CONN_TYPE_L2CAP &&
+ conn_type != BTA_JV_CONN_TYPE_L2CAP_LE) {
+ CHECK(false) << "Invalid conn_type=" << conn_type;
}
- bta_sys_sendmsg(p_msg);
-
- return BTA_JV_SUCCESS;
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_get_channel_id, conn_type, channel, id, id));
}
/*******************************************************************************
@@ -186,17 +159,9 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvFreeChannel(uint16_t channel, int conn_type) {
- tBTA_JV_API_FREE_CHANNEL* p_msg =
- (tBTA_JV_API_FREE_CHANNEL*)osi_malloc(sizeof(tBTA_JV_API_FREE_CHANNEL));
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_JV_API_FREE_SCN_EVT;
- p_msg->scn = channel;
- p_msg->type = conn_type;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_free_scn, conn_type, channel));
return BTA_JV_SUCCESS;
}
@@ -214,22 +179,16 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvStartDiscovery(const RawAddress& bd_addr,
- uint16_t num_uuid, tSDP_UUID* p_uuid_list,
+ uint16_t num_uuid, const Uuid* p_uuid_list,
uint32_t rfcomm_slot_id) {
- tBTA_JV_API_START_DISCOVERY* p_msg = (tBTA_JV_API_START_DISCOVERY*)osi_malloc(
- sizeof(tBTA_JV_API_START_DISCOVERY));
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
+ Uuid* uuid_list_copy = new Uuid[num_uuid];
+ memcpy(uuid_list_copy, p_uuid_list, num_uuid * sizeof(Uuid));
- p_msg->hdr.event = BTA_JV_API_START_DISCOVERY_EVT;
- p_msg->bd_addr = bd_addr;
- p_msg->num_uuid = num_uuid;
- memcpy(p_msg->uuid_list, p_uuid_list, num_uuid * sizeof(tSDP_UUID));
- p_msg->num_attr = 0;
- p_msg->rfcomm_slot_id = rfcomm_slot_id;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_start_discovery, bd_addr, num_uuid,
+ base::Owned(uuid_list_copy), rfcomm_slot_id));
return BTA_JV_SUCCESS;
}
@@ -246,16 +205,9 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvCreateRecordByUser(uint32_t rfcomm_slot_id) {
- tBTA_JV_API_CREATE_RECORD* p_msg =
- (tBTA_JV_API_CREATE_RECORD*)osi_malloc(sizeof(tBTA_JV_API_CREATE_RECORD));
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_JV_API_CREATE_RECORD_EVT;
- p_msg->rfcomm_slot_id = rfcomm_slot_id;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_create_record, rfcomm_slot_id));
return BTA_JV_SUCCESS;
}
@@ -270,16 +222,9 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvDeleteRecord(uint32_t handle) {
- tBTA_JV_API_ADD_ATTRIBUTE* p_msg =
- (tBTA_JV_API_ADD_ATTRIBUTE*)osi_malloc(sizeof(tBTA_JV_API_ADD_ATTRIBUTE));
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_JV_API_DELETE_RECORD_EVT;
- p_msg->handle = handle;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_delete_record, handle));
return BTA_JV_SUCCESS;
}
@@ -294,47 +239,14 @@
* When the connection is established or failed,
* tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
- *
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capConnectLE(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
- const tL2CAP_ERTM_INFO* ertm_info,
- uint16_t remote_chan, uint16_t rx_mtu,
- tL2CAP_CFG_INFO* cfg,
- const RawAddress& peer_bd_addr,
- tBTA_JV_L2CAP_CBACK* p_cback,
- uint32_t l2cap_socket_id) {
- APPL_TRACE_API("%s", __func__);
-
- if (p_cback == NULL) return BTA_JV_FAILURE; /* Nothing to do */
-
- tBTA_JV_API_L2CAP_CONNECT* p_msg =
- (tBTA_JV_API_L2CAP_CONNECT*)osi_malloc(sizeof(tBTA_JV_API_L2CAP_CONNECT));
- p_msg->hdr.event = BTA_JV_API_L2CAP_CONNECT_LE_EVT;
- p_msg->sec_mask = sec_mask;
- p_msg->role = role;
- p_msg->remote_chan = remote_chan;
- p_msg->rx_mtu = rx_mtu;
- if (cfg != NULL) {
- p_msg->has_cfg = true;
- p_msg->cfg = *cfg;
- } else {
- p_msg->has_cfg = false;
- }
- if (ertm_info != NULL) {
- p_msg->has_ertm_info = true;
- p_msg->ertm_info = *ertm_info;
- } else {
- p_msg->has_ertm_info = false;
- }
- p_msg->peer_bd_addr = peer_bd_addr;
- p_msg->p_cback = p_cback;
- p_msg->l2cap_socket_id = l2cap_socket_id;
-
- bta_sys_sendmsg(p_msg);
-
- return BTA_JV_SUCCESS;
+void BTA_JvL2capConnectLE(uint16_t remote_chan, const RawAddress& peer_bd_addr,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id) {
+ VLOG(2) << __func__;
+ CHECK(p_cback);
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_connect_le, remote_chan,
+ peer_bd_addr, p_cback, l2cap_socket_id));
}
/*******************************************************************************
@@ -348,46 +260,21 @@
* When the connection is established or failed,
* tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
- *
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capConnect(
- int conn_type, tBTA_SEC sec_mask, tBTA_JV_ROLE role,
- const tL2CAP_ERTM_INFO* ertm_info, uint16_t remote_psm, uint16_t rx_mtu,
- tL2CAP_CFG_INFO* cfg, const RawAddress& peer_bd_addr,
- tBTA_JV_L2CAP_CBACK* p_cback, uint32_t l2cap_socket_id) {
- APPL_TRACE_API("%s", __func__);
+void BTA_JvL2capConnect(int conn_type, tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info,
+ uint16_t remote_psm, uint16_t rx_mtu,
+ std::unique_ptr<tL2CAP_CFG_INFO> cfg,
+ const RawAddress& peer_bd_addr,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id) {
+ VLOG(2) << __func__;
+ CHECK(p_cback);
- if (p_cback == NULL) return BTA_JV_FAILURE; /* Nothing to do */
-
- tBTA_JV_API_L2CAP_CONNECT* p_msg =
- (tBTA_JV_API_L2CAP_CONNECT*)osi_malloc(sizeof(tBTA_JV_API_L2CAP_CONNECT));
- p_msg->hdr.event = BTA_JV_API_L2CAP_CONNECT_EVT;
- p_msg->type = conn_type;
- p_msg->sec_mask = sec_mask;
- p_msg->role = role;
- p_msg->remote_psm = remote_psm;
- p_msg->rx_mtu = rx_mtu;
- if (cfg != NULL) {
- p_msg->has_cfg = true;
- p_msg->cfg = *cfg;
- } else {
- p_msg->has_cfg = false;
- }
- if (ertm_info != NULL) {
- p_msg->has_ertm_info = true;
- p_msg->ertm_info = *ertm_info;
- } else {
- p_msg->has_ertm_info = false;
- }
- p_msg->peer_bd_addr = peer_bd_addr;
- p_msg->p_cback = p_cback;
- p_msg->l2cap_socket_id = l2cap_socket_id;
-
- bta_sys_sendmsg(p_msg);
-
- return BTA_JV_SUCCESS;
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_l2cap_connect, conn_type, sec_mask, role,
+ remote_psm, rx_mtu, peer_bd_addr, base::Passed(&cfg),
+ base::Passed(&ertm_info), p_cback, l2cap_socket_id));
}
/*******************************************************************************
@@ -401,22 +288,14 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvL2capClose(uint32_t handle) {
- tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
+ if (handle >= BTA_JV_MAX_L2C_CONN || !bta_jv_cb.l2c_cb[handle].p_cback)
+ return BTA_JV_FAILURE;
- if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback) {
- tBTA_JV_API_L2CAP_CLOSE* p_msg =
- (tBTA_JV_API_L2CAP_CLOSE*)osi_malloc(sizeof(tBTA_JV_API_L2CAP_CLOSE));
- p_msg->hdr.event = BTA_JV_API_L2CAP_CLOSE_EVT;
- p_msg->handle = handle;
- p_msg->p_cb = &bta_jv_cb.l2c_cb[handle];
-
- bta_sys_sendmsg(p_msg);
- status = BTA_JV_SUCCESS;
- }
-
- return status;
+ do_in_bta_thread(
+ FROM_HERE, Bind(&bta_jv_l2cap_close, handle, &bta_jv_cb.l2c_cb[handle]));
+ return BTA_JV_SUCCESS;
}
/*******************************************************************************
@@ -431,16 +310,9 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvL2capCloseLE(uint32_t handle) {
- tBTA_JV_API_L2CAP_CLOSE* p_msg =
- (tBTA_JV_API_L2CAP_CLOSE*)osi_malloc(sizeof(tBTA_JV_API_L2CAP_CLOSE));
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_JV_API_L2CAP_CLOSE_FIXED_EVT;
- p_msg->handle = handle;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_close_fixed, handle));
return BTA_JV_SUCCESS;
}
@@ -455,47 +327,22 @@
* established tBTA_JV_L2CAP_CBACK is called with
* BTA_JV_L2CAP_OPEN_EVT.
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
+ * Returns void
*
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capStartServer(int conn_type, tBTA_SEC sec_mask,
- tBTA_JV_ROLE role,
- const tL2CAP_ERTM_INFO* ertm_info,
- uint16_t local_psm, uint16_t rx_mtu,
- tL2CAP_CFG_INFO* cfg,
- tBTA_JV_L2CAP_CBACK* p_cback,
- uint32_t l2cap_socket_id) {
- APPL_TRACE_API("%s", __func__);
+void BTA_JvL2capStartServer(int conn_type, tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info,
+ uint16_t local_psm, uint16_t rx_mtu,
+ std::unique_ptr<tL2CAP_CFG_INFO> cfg,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id) {
+ VLOG(2) << __func__;
+ CHECK(p_cback);
- if (p_cback == NULL) return BTA_JV_FAILURE; /* Nothing to do */
-
- tBTA_JV_API_L2CAP_SERVER* p_msg =
- (tBTA_JV_API_L2CAP_SERVER*)osi_malloc(sizeof(tBTA_JV_API_L2CAP_SERVER));
- p_msg->hdr.event = BTA_JV_API_L2CAP_START_SERVER_EVT;
- p_msg->type = conn_type;
- p_msg->sec_mask = sec_mask;
- p_msg->role = role;
- p_msg->local_psm = local_psm;
- p_msg->rx_mtu = rx_mtu;
- if (cfg != NULL) {
- p_msg->has_cfg = true;
- p_msg->cfg = *cfg;
- } else {
- p_msg->has_cfg = false;
- }
- if (ertm_info != NULL) {
- p_msg->has_ertm_info = true;
- p_msg->ertm_info = *ertm_info;
- } else {
- p_msg->has_ertm_info = false;
- }
- p_msg->p_cback = p_cback;
- p_msg->l2cap_socket_id = l2cap_socket_id;
-
- bta_sys_sendmsg(p_msg);
-
- return BTA_JV_SUCCESS;
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_l2cap_start_server, conn_type, sec_mask, role,
+ local_psm, rx_mtu, base::Passed(&cfg),
+ base::Passed(&ertm_info), p_cback, l2cap_socket_id));
}
/*******************************************************************************
@@ -509,45 +356,15 @@
* established, tBTA_JV_L2CAP_CBACK is called with
* BTA_JV_L2CAP_OPEN_EVT.
*
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
+ * Returns void
*
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capStartServerLE(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
- const tL2CAP_ERTM_INFO* ertm_info,
- uint16_t local_chan, uint16_t rx_mtu,
- tL2CAP_CFG_INFO* cfg,
- tBTA_JV_L2CAP_CBACK* p_cback,
- uint32_t l2cap_socket_id) {
- APPL_TRACE_API("%s", __func__);
-
- if (p_cback == NULL) return BTA_JV_FAILURE; /* Nothing to do */
-
- tBTA_JV_API_L2CAP_SERVER* p_msg =
- (tBTA_JV_API_L2CAP_SERVER*)osi_malloc(sizeof(tBTA_JV_API_L2CAP_SERVER));
- p_msg->hdr.event = BTA_JV_API_L2CAP_START_SERVER_LE_EVT;
- p_msg->sec_mask = sec_mask;
- p_msg->role = role;
- p_msg->local_chan = local_chan;
- p_msg->rx_mtu = rx_mtu;
- if (cfg != NULL) {
- p_msg->has_cfg = true;
- p_msg->cfg = *cfg;
- } else {
- p_msg->has_cfg = false;
- }
- if (ertm_info != NULL) {
- p_msg->has_ertm_info = true;
- p_msg->ertm_info = *ertm_info;
- } else {
- p_msg->has_ertm_info = false;
- }
- p_msg->p_cback = p_cback;
- p_msg->l2cap_socket_id = l2cap_socket_id;
-
- bta_sys_sendmsg(p_msg);
-
- return BTA_JV_SUCCESS;
+void BTA_JvL2capStartServerLE(uint16_t local_chan, tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id) {
+ VLOG(2) << __func__;
+ CHECK(p_cback);
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_start_server_le, local_chan,
+ p_cback, l2cap_socket_id));
}
/*******************************************************************************
@@ -563,16 +380,10 @@
******************************************************************************/
tBTA_JV_STATUS BTA_JvL2capStopServer(uint16_t local_psm,
uint32_t l2cap_socket_id) {
- APPL_TRACE_API("%s", __func__);
+ VLOG(2) << __func__;
- tBTA_JV_API_L2CAP_SERVER* p_msg =
- (tBTA_JV_API_L2CAP_SERVER*)osi_malloc(sizeof(tBTA_JV_API_L2CAP_SERVER));
- p_msg->hdr.event = BTA_JV_API_L2CAP_STOP_SERVER_EVT;
- p_msg->local_psm = local_psm;
- p_msg->l2cap_socket_id = l2cap_socket_id;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_l2cap_stop_server, local_psm, l2cap_socket_id));
return BTA_JV_SUCCESS;
}
@@ -589,16 +400,9 @@
******************************************************************************/
tBTA_JV_STATUS BTA_JvL2capStopServerLE(uint16_t local_chan,
uint32_t l2cap_socket_id) {
- APPL_TRACE_API("%s", __func__);
+ VLOG(2) << __func__;
- tBTA_JV_API_L2CAP_SERVER* p_msg =
- (tBTA_JV_API_L2CAP_SERVER*)osi_malloc(sizeof(tBTA_JV_API_L2CAP_SERVER));
- p_msg->hdr.event = BTA_JV_API_L2CAP_STOP_SERVER_LE_EVT;
- p_msg->local_chan = local_chan;
- p_msg->l2cap_socket_id = l2cap_socket_id;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_stop_server_le, local_chan));
return BTA_JV_SUCCESS;
}
@@ -606,9 +410,7 @@
*
* Function BTA_JvL2capRead
*
- * Description This function reads data from an L2CAP connecti;
- tBTA_JV_RFC_CB *p_cb = rc->p_cb;
-on
+ * Description This function reads data from an L2CAP connection
* When the operation is complete, tBTA_JV_L2CAP_CBACK is
* called with BTA_JV_L2CAP_READ_EVT.
*
@@ -618,28 +420,25 @@
******************************************************************************/
tBTA_JV_STATUS BTA_JvL2capRead(uint32_t handle, uint32_t req_id,
uint8_t* p_data, uint16_t len) {
- tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ VLOG(2) << __func__;
+
+ if (handle >= BTA_JV_MAX_L2C_CONN || !bta_jv_cb.l2c_cb[handle].p_cback)
+ return BTA_JV_FAILURE;
+
tBTA_JV_L2CAP_READ evt_data;
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = handle;
+ evt_data.req_id = req_id;
+ evt_data.p_data = p_data;
+ evt_data.len = 0;
- APPL_TRACE_API("%s", __func__);
-
- if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback) {
- status = BTA_JV_SUCCESS;
- evt_data.status = BTA_JV_FAILURE;
- evt_data.handle = handle;
- evt_data.req_id = req_id;
- evt_data.p_data = p_data;
- evt_data.len = 0;
-
- if (BT_PASS ==
- GAP_ConnReadData((uint16_t)handle, p_data, len, &evt_data.len)) {
- evt_data.status = BTA_JV_SUCCESS;
- }
- bta_jv_cb.l2c_cb[handle].p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV*)&evt_data,
- bta_jv_cb.l2c_cb[handle].l2cap_socket_id);
+ if (BT_PASS ==
+ GAP_ConnReadData((uint16_t)handle, p_data, len, &evt_data.len)) {
+ evt_data.status = BTA_JV_SUCCESS;
}
-
- return (status);
+ bta_jv_cb.l2c_cb[handle].p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV*)&evt_data,
+ bta_jv_cb.l2c_cb[handle].l2cap_socket_id);
+ return BTA_JV_SUCCESS;
}
/*******************************************************************************
@@ -656,7 +455,7 @@
tBTA_JV_STATUS BTA_JvL2capReady(uint32_t handle, uint32_t* p_data_size) {
tBTA_JV_STATUS status = BTA_JV_FAILURE;
- APPL_TRACE_API("%s: %d", __func__, handle);
+ VLOG(2) << __func__ << ": handle=" << handle;
if (p_data_size && handle < BTA_JV_MAX_L2C_CONN &&
bta_jv_cb.l2c_cb[handle].p_cback) {
*p_data_size = 0;
@@ -675,36 +474,26 @@
* Description This function writes data to an L2CAP connection
* When the operation is complete, tBTA_JV_L2CAP_CBACK is
* called with BTA_JV_L2CAP_WRITE_EVT. Works for
- * PSM-based connections
+ * PSM-based connections. This function takes ownership of
+ * p_data, and will osi_free it. Data length must be smaller
+ * than remote maximum SDU size.
*
* Returns BTA_JV_SUCCESS, if the request is being processed.
* BTA_JV_FAILURE, otherwise.
*
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id,
- uint8_t* p_data, uint16_t len,
+tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id, BT_HDR* msg,
uint32_t user_id) {
- tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
-
- if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback) {
- tBTA_JV_API_L2CAP_WRITE* p_msg =
- (tBTA_JV_API_L2CAP_WRITE*)osi_malloc(sizeof(tBTA_JV_API_L2CAP_WRITE));
- p_msg->hdr.event = BTA_JV_API_L2CAP_WRITE_EVT;
- p_msg->handle = handle;
- p_msg->req_id = req_id;
- p_msg->p_data = p_data;
- p_msg->p_cb = &bta_jv_cb.l2c_cb[handle];
- p_msg->len = len;
- p_msg->user_id = user_id;
-
- bta_sys_sendmsg(p_msg);
-
- status = BTA_JV_SUCCESS;
+ if (handle >= BTA_JV_MAX_L2C_CONN || !bta_jv_cb.l2c_cb[handle].p_cback) {
+ osi_free(msg);
+ return BTA_JV_FAILURE;
}
- return status;
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_write, handle, req_id, msg,
+ user_id, &bta_jv_cb.l2c_cb[handle]));
+ return BTA_JV_SUCCESS;
}
/*******************************************************************************
@@ -714,35 +503,17 @@
* Description This function writes data to an L2CAP connection
* When the operation is complete, tBTA_JV_L2CAP_CBACK is
* called with BTA_JV_L2CAP_WRITE_EVT. Works for
- * fixed-channel connections
- *
- * Returns BTA_JV_SUCCESS, if the request is being processed.
- * BTA_JV_FAILURE, otherwise.
+ * fixed-channel connections. This function takes ownership of
+ * p_data, and will osi_free it.
*
******************************************************************************/
-tBTA_JV_STATUS BTA_JvL2capWriteFixed(uint16_t channel, const RawAddress& addr,
- uint32_t req_id,
- tBTA_JV_L2CAP_CBACK* p_cback,
- uint8_t* p_data, uint16_t len,
- uint32_t user_id) {
- tBTA_JV_API_L2CAP_WRITE_FIXED* p_msg =
- (tBTA_JV_API_L2CAP_WRITE_FIXED*)osi_malloc(
- sizeof(tBTA_JV_API_L2CAP_WRITE_FIXED));
+void BTA_JvL2capWriteFixed(uint16_t channel, const RawAddress& addr,
+ uint32_t req_id, tBTA_JV_L2CAP_CBACK* p_cback,
+ BT_HDR* msg, uint32_t user_id) {
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_JV_API_L2CAP_WRITE_FIXED_EVT;
- p_msg->channel = channel;
- p_msg->addr = addr;
- p_msg->req_id = req_id;
- p_msg->p_data = p_data;
- p_msg->p_cback = p_cback;
- p_msg->len = len;
- p_msg->user_id = user_id;
-
- bta_sys_sendmsg(p_msg);
-
- return BTA_JV_SUCCESS;
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_write_fixed, channel, addr,
+ req_id, msg, user_id, p_cback));
}
/*******************************************************************************
@@ -766,22 +537,13 @@
const RawAddress& peer_bd_addr,
tBTA_JV_RFCOMM_CBACK* p_cback,
uint32_t rfcomm_slot_id) {
- APPL_TRACE_API("%s", __func__);
+ VLOG(2) << __func__;
- if (p_cback == NULL) return BTA_JV_FAILURE; /* Nothing to do */
+ if (!p_cback) return BTA_JV_FAILURE; /* Nothing to do */
- tBTA_JV_API_RFCOMM_CONNECT* p_msg = (tBTA_JV_API_RFCOMM_CONNECT*)osi_malloc(
- sizeof(tBTA_JV_API_RFCOMM_CONNECT));
- p_msg->hdr.event = BTA_JV_API_RFCOMM_CONNECT_EVT;
- p_msg->sec_mask = sec_mask;
- p_msg->role = role;
- p_msg->remote_scn = remote_scn;
- p_msg->peer_bd_addr = peer_bd_addr;
- p_msg->p_cback = p_cback;
- p_msg->rfcomm_slot_id = rfcomm_slot_id;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_rfcomm_connect, sec_mask, role, remote_scn,
+ peer_bd_addr, p_cback, rfcomm_slot_id));
return BTA_JV_SUCCESS;
}
@@ -796,28 +558,18 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvRfcommClose(uint32_t handle, uint32_t rfcomm_slot_id) {
- tBTA_JV_STATUS status = BTA_JV_FAILURE;
uint32_t hi = ((handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
uint32_t si = BTA_JV_RFC_HDL_TO_SIDX(handle);
- APPL_TRACE_API("%s", __func__);
+ VLOG(2) << __func__;
- if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
- si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si]) {
- tBTA_JV_API_RFCOMM_CLOSE* p_msg =
- (tBTA_JV_API_RFCOMM_CLOSE*)osi_malloc(sizeof(tBTA_JV_API_RFCOMM_CLOSE));
- p_msg->hdr.event = BTA_JV_API_RFCOMM_CLOSE_EVT;
- p_msg->handle = handle;
- p_msg->p_cb = &bta_jv_cb.rfc_cb[hi];
- p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1];
- p_msg->rfcomm_slot_id = rfcomm_slot_id;
+ if (hi >= BTA_JV_MAX_RFC_CONN || !bta_jv_cb.rfc_cb[hi].p_cback ||
+ si >= BTA_JV_MAX_RFC_SR_SESSION || !bta_jv_cb.rfc_cb[hi].rfc_hdl[si])
+ return BTA_JV_FAILURE;
- bta_sys_sendmsg(p_msg);
-
- status = BTA_JV_SUCCESS;
- }
-
- return status;
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_rfcomm_close, handle, rfcomm_slot_id));
+ return BTA_JV_SUCCESS;
}
/*******************************************************************************
@@ -839,28 +591,20 @@
uint8_t local_scn, uint8_t max_session,
tBTA_JV_RFCOMM_CBACK* p_cback,
uint32_t rfcomm_slot_id) {
- APPL_TRACE_API("%s", __func__);
+ VLOG(2) << __func__;
if (p_cback == NULL) return BTA_JV_FAILURE; /* Nothing to do */
- tBTA_JV_API_RFCOMM_SERVER* p_msg =
- (tBTA_JV_API_RFCOMM_SERVER*)osi_malloc(sizeof(tBTA_JV_API_RFCOMM_SERVER));
if (max_session == 0) max_session = 1;
if (max_session > BTA_JV_MAX_RFC_SR_SESSION) {
- APPL_TRACE_DEBUG("max_session is too big. use max (%d)", max_session,
- BTA_JV_MAX_RFC_SR_SESSION);
+ LOG(INFO) << __func__ << "max_session is too big. use max "
+ << BTA_JV_MAX_RFC_SR_SESSION;
max_session = BTA_JV_MAX_RFC_SR_SESSION;
}
- p_msg->hdr.event = BTA_JV_API_RFCOMM_START_SERVER_EVT;
- p_msg->sec_mask = sec_mask;
- p_msg->role = role;
- p_msg->local_scn = local_scn;
- p_msg->max_session = max_session;
- p_msg->p_cback = p_cback;
- p_msg->rfcomm_slot_id = rfcomm_slot_id; // caller's private data
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_rfcomm_start_server, sec_mask, role, local_scn,
+ max_session, p_cback, rfcomm_slot_id));
return BTA_JV_SUCCESS;
}
@@ -877,17 +621,10 @@
******************************************************************************/
tBTA_JV_STATUS BTA_JvRfcommStopServer(uint32_t handle,
uint32_t rfcomm_slot_id) {
- tBTA_JV_API_RFCOMM_SERVER* p_msg =
- (tBTA_JV_API_RFCOMM_SERVER*)osi_malloc(sizeof(tBTA_JV_API_RFCOMM_SERVER));
+ VLOG(2) << __func__;
- APPL_TRACE_API("%s", __func__);
-
- p_msg->hdr.event = BTA_JV_API_RFCOMM_STOP_SERVER_EVT;
- p_msg->handle = handle;
- p_msg->rfcomm_slot_id = rfcomm_slot_id; // caller's private data
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_rfcomm_stop_server, handle, rfcomm_slot_id));
return BTA_JV_SUCCESS;
}
@@ -923,29 +660,24 @@
*
******************************************************************************/
tBTA_JV_STATUS BTA_JvRfcommWrite(uint32_t handle, uint32_t req_id) {
- tBTA_JV_STATUS status = BTA_JV_FAILURE;
uint32_t hi = ((handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
uint32_t si = BTA_JV_RFC_HDL_TO_SIDX(handle);
- APPL_TRACE_API("%s", __func__);
+ VLOG(2) << __func__;
- APPL_TRACE_DEBUG("handle:0x%x, hi:%d, si:%d", handle, hi, si);
- if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
- si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si]) {
- tBTA_JV_API_RFCOMM_WRITE* p_msg =
- (tBTA_JV_API_RFCOMM_WRITE*)osi_malloc(sizeof(tBTA_JV_API_RFCOMM_WRITE));
- p_msg->hdr.event = BTA_JV_API_RFCOMM_WRITE_EVT;
- p_msg->handle = handle;
- p_msg->req_id = req_id;
- p_msg->p_cb = &bta_jv_cb.rfc_cb[hi];
- p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1];
- APPL_TRACE_API("write ok");
-
- bta_sys_sendmsg(p_msg);
- status = BTA_JV_SUCCESS;
+ VLOG(2) << __func__ << "handle=" << loghex(handle) << ", hi=" << hi
+ << ", si=" << si;
+ if (hi >= BTA_JV_MAX_RFC_CONN || !bta_jv_cb.rfc_cb[hi].p_cback ||
+ si >= BTA_JV_MAX_RFC_SR_SESSION || !bta_jv_cb.rfc_cb[hi].rfc_hdl[si]) {
+ return BTA_JV_FAILURE;
}
- return status;
+ VLOG(2) << "write ok";
+
+ tBTA_JV_RFC_CB* p_cb = &bta_jv_cb.rfc_cb[hi];
+ do_in_bta_thread(FROM_HERE, Bind(&bta_jv_rfcomm_write, handle, req_id, p_cb,
+ &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1]));
+ return BTA_JV_SUCCESS;
}
/*******************************************************************************
@@ -973,17 +705,9 @@
******************************************************************************/
tBTA_JV_STATUS BTA_JvSetPmProfile(uint32_t handle, tBTA_JV_PM_ID app_id,
tBTA_JV_CONN_STATE init_st) {
- tBTA_JV_API_SET_PM_PROFILE* p_msg = (tBTA_JV_API_SET_PM_PROFILE*)osi_malloc(
- sizeof(tBTA_JV_API_SET_PM_PROFILE));
+ VLOG(2) << __func__ << " handle=" << loghex(handle) << ", app_id:" << app_id;
- APPL_TRACE_API("%s handle:0x%x, app_id:%d", __func__, handle, app_id);
-
- p_msg->hdr.event = BTA_JV_API_SET_PM_PROFILE_EVT;
- p_msg->handle = handle;
- p_msg->app_id = app_id;
- p_msg->init_st = init_st;
-
- bta_sys_sendmsg(p_msg);
-
+ do_in_bta_thread(FROM_HERE,
+ Bind(&bta_jv_set_pm_profile, handle, app_id, init_st));
return BTA_JV_SUCCESS;
}
diff --git a/bta/jv/bta_jv_cfg.cc b/bta/jv/bta_jv_cfg.cc
index b43b035..c01445e 100644
--- a/bta/jv/bta_jv_cfg.cc
+++ b/bta/jv/bta_jv_cfg.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,16 +43,16 @@
* BTA_JvStartDiscovery
* it can be de-allocated after the last call to access the database */
static uint8_t bta_jv_sdp_raw_data[BTA_JV_SDP_RAW_DATA_SIZE];
-static uint8_t __attribute__((aligned(4)))
-bta_jv_sdp_db_data[BTA_JV_SDP_DB_SIZE];
+static tSDP_DISCOVERY_DB
+ bta_jv_sdp_db_data[BTA_JV_SDP_DB_SIZE / sizeof(tSDP_DISCOVERY_DB)];
/* JV configuration structure */
const tBTA_JV_CFG bta_jv_cfg = {
BTA_JV_SDP_RAW_DATA_SIZE, /* The size of p_sdp_raw_data */
- BTA_JV_SDP_DB_SIZE, /* The size of p_sdp_db_data */
- bta_jv_sdp_raw_data, /* The data buffer to keep raw data */
- (tSDP_DISCOVERY_DB*)
- bta_jv_sdp_db_data /* The data buffer to keep SDP database */
+ (BTA_JV_SDP_DB_SIZE / sizeof(tSDP_DISCOVERY_DB)) *
+ sizeof(tSDP_DISCOVERY_DB), /* The size of p_sdp_db_data */
+ bta_jv_sdp_raw_data, /* The data buffer to keep raw data */
+ bta_jv_sdp_db_data /* The data buffer to keep SDP database */
};
-tBTA_JV_CFG* p_bta_jv_cfg = (tBTA_JV_CFG*)&bta_jv_cfg;
+const tBTA_JV_CFG* p_bta_jv_cfg = &bta_jv_cfg;
diff --git a/bta/jv/bta_jv_int.h b/bta/jv/bta_jv_int.h
index 94ee085..fa71580 100644
--- a/bta/jv/bta_jv_int.h
+++ b/bta/jv/bta_jv_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,62 +30,17 @@
#include "port_api.h"
#include "rfcdefs.h"
+#include <memory>
+
/*****************************************************************************
* Constants
****************************************************************************/
-enum {
- /* these events are handled by the state machine */
- BTA_JV_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_JV),
- BTA_JV_API_DISABLE_EVT,
- BTA_JV_API_GET_CHANNEL_EVT,
- BTA_JV_API_FREE_SCN_EVT,
- BTA_JV_API_START_DISCOVERY_EVT,
- BTA_JV_API_CREATE_RECORD_EVT,
- BTA_JV_API_DELETE_RECORD_EVT,
- BTA_JV_API_L2CAP_CONNECT_EVT,
- BTA_JV_API_L2CAP_CLOSE_EVT,
- BTA_JV_API_L2CAP_START_SERVER_EVT,
- BTA_JV_API_L2CAP_STOP_SERVER_EVT,
- BTA_JV_API_L2CAP_READ_EVT,
- BTA_JV_API_L2CAP_WRITE_EVT,
- BTA_JV_API_RFCOMM_CONNECT_EVT,
- BTA_JV_API_RFCOMM_CLOSE_EVT,
- BTA_JV_API_RFCOMM_START_SERVER_EVT,
- BTA_JV_API_RFCOMM_STOP_SERVER_EVT,
- BTA_JV_API_RFCOMM_WRITE_EVT,
- BTA_JV_API_SET_PM_PROFILE_EVT,
- BTA_JV_API_PM_STATE_CHANGE_EVT,
- BTA_JV_API_L2CAP_CONNECT_LE_EVT,
- BTA_JV_API_L2CAP_START_SERVER_LE_EVT,
- BTA_JV_API_L2CAP_STOP_SERVER_LE_EVT,
- BTA_JV_API_L2CAP_WRITE_FIXED_EVT,
- BTA_JV_API_L2CAP_CLOSE_FIXED_EVT,
- BTA_JV_MAX_INT_EVT
-};
-
#ifndef BTA_JV_RFC_EV_MASK
#define BTA_JV_RFC_EV_MASK \
(PORT_EV_RXCHAR | PORT_EV_TXEMPTY | PORT_EV_FC | PORT_EV_FCS)
#endif
-/* data type for BTA_JV_API_ENABLE_EVT */
-typedef struct {
- BT_HDR hdr;
- tBTA_JV_DM_CBACK* p_cback;
-} tBTA_JV_API_ENABLE;
-
-/* data type for BTA_JV_API_START_DISCOVERY_EVT */
-typedef struct {
- BT_HDR hdr;
- RawAddress bd_addr;
- uint16_t num_uuid;
- tSDP_UUID uuid_list[BTA_JV_MAX_UUIDS];
- uint16_t num_attr;
- uint16_t attr_list[BTA_JV_MAX_ATTRS];
- uint32_t rfcomm_slot_id;
-} tBTA_JV_API_START_DISCOVERY;
-
enum {
BTA_JV_PM_FREE_ST = 0, /* empty PM slot */
BTA_JV_PM_IDLE_ST,
@@ -151,199 +106,6 @@
int curr_sess; /* current sessions count*/
} tBTA_JV_RFC_CB;
-/* data type for BTA_JV_API_L2CAP_CONNECT_EVT & BTA_JV_API_L2CAP_CONNECT_LE_EVT
- */
-typedef struct {
- BT_HDR hdr;
- int32_t type; /* One of BTA_JV_CONN_TYPE_ */
- tBTA_SEC sec_mask;
- tBTA_JV_ROLE role;
- union {
- uint16_t remote_psm;
- uint16_t remote_chan;
- };
- uint16_t rx_mtu;
- RawAddress peer_bd_addr;
- int32_t has_cfg;
- tL2CAP_CFG_INFO cfg;
- int32_t has_ertm_info;
- tL2CAP_ERTM_INFO ertm_info;
- tBTA_JV_L2CAP_CBACK* p_cback;
- uint32_t l2cap_socket_id;
-} tBTA_JV_API_L2CAP_CONNECT;
-
-/* data type for BTA_JV_API_L2CAP_SERVER_EVT */
-typedef struct {
- BT_HDR hdr;
- int32_t type; /* One of BTA_JV_CONN_TYPE_ */
- tBTA_SEC sec_mask;
- tBTA_JV_ROLE role;
- union {
- uint16_t local_psm;
- uint16_t local_chan;
- };
- uint16_t rx_mtu;
- int32_t has_cfg;
- tL2CAP_CFG_INFO cfg;
- int32_t has_ertm_info;
- tL2CAP_ERTM_INFO ertm_info;
- tBTA_JV_L2CAP_CBACK* p_cback;
- uint32_t l2cap_socket_id;
-} tBTA_JV_API_L2CAP_SERVER;
-
-/* data type for BTA_JV_API_L2CAP_CLOSE_EVT */
-typedef struct {
- BT_HDR hdr;
- uint32_t handle;
- tBTA_JV_L2C_CB* p_cb;
-} tBTA_JV_API_L2CAP_CLOSE;
-
-/* data type for BTA_JV_API_L2CAP_READ_EVT */
-typedef struct {
- BT_HDR hdr;
- uint32_t handle;
- uint32_t req_id;
- tBTA_JV_L2CAP_CBACK* p_cback;
- uint8_t* p_data;
- uint16_t len;
- uint32_t l2cap_socket_id;
-} tBTA_JV_API_L2CAP_READ;
-
-/* data type for BTA_JV_API_L2CAP_WRITE_EVT */
-typedef struct {
- BT_HDR hdr;
- uint32_t handle;
- uint32_t req_id;
- tBTA_JV_L2C_CB* p_cb;
- uint8_t* p_data;
- uint16_t len;
- uint32_t user_id;
-} tBTA_JV_API_L2CAP_WRITE;
-
-/* data type for BTA_JV_API_L2CAP_WRITE_FIXED_EVT */
-typedef struct {
- BT_HDR hdr;
- uint16_t channel;
- RawAddress addr;
- uint32_t req_id;
- tBTA_JV_L2CAP_CBACK* p_cback;
- uint8_t* p_data;
- uint16_t len;
- uint32_t user_id;
-} tBTA_JV_API_L2CAP_WRITE_FIXED;
-
-/* data type for BTA_JV_API_RFCOMM_CONNECT_EVT */
-typedef struct {
- BT_HDR hdr;
- tBTA_SEC sec_mask;
- tBTA_JV_ROLE role;
- uint8_t remote_scn;
- RawAddress peer_bd_addr;
- tBTA_JV_RFCOMM_CBACK* p_cback;
- uint32_t rfcomm_slot_id;
-} tBTA_JV_API_RFCOMM_CONNECT;
-
-/* data type for BTA_JV_API_RFCOMM_SERVER_EVT */
-typedef struct {
- BT_HDR hdr;
- tBTA_SEC sec_mask;
- tBTA_JV_ROLE role;
- uint8_t local_scn;
- uint8_t max_session;
- uint32_t handle;
- tBTA_JV_RFCOMM_CBACK* p_cback;
- uint32_t rfcomm_slot_id;
-} tBTA_JV_API_RFCOMM_SERVER;
-
-/* data type for BTA_JV_API_SET_PM_PROFILE_EVT */
-typedef struct {
- BT_HDR hdr;
- uint32_t handle;
- tBTA_JV_PM_ID app_id;
- tBTA_JV_CONN_STATE init_st;
-} tBTA_JV_API_SET_PM_PROFILE;
-
-/* data type for BTA_JV_API_PM_STATE_CHANGE_EVT */
-typedef struct {
- BT_HDR hdr;
- tBTA_JV_PM_CB* p_cb;
- tBTA_JV_CONN_STATE state;
-} tBTA_JV_API_PM_STATE_CHANGE;
-
-/* data type for BTA_JV_API_RFCOMM_WRITE_EVT */
-typedef struct {
- BT_HDR hdr;
- uint32_t handle;
- uint32_t req_id;
- uint8_t* p_data;
- int len;
- tBTA_JV_RFC_CB* p_cb;
- tBTA_JV_PCB* p_pcb;
-} tBTA_JV_API_RFCOMM_WRITE;
-
-/* data type for BTA_JV_API_RFCOMM_CLOSE_EVT */
-typedef struct {
- BT_HDR hdr;
- uint32_t handle;
- tBTA_JV_RFC_CB* p_cb;
- tBTA_JV_PCB* p_pcb;
- uint32_t rfcomm_slot_id;
-} tBTA_JV_API_RFCOMM_CLOSE;
-
-/* data type for BTA_JV_API_CREATE_RECORD_EVT */
-typedef struct {
- BT_HDR hdr;
- uint32_t rfcomm_slot_id;
-} tBTA_JV_API_CREATE_RECORD;
-
-/* data type for BTA_JV_API_ADD_ATTRIBUTE_EVT */
-typedef struct {
- BT_HDR hdr;
- uint32_t handle;
- uint16_t attr_id;
- uint8_t* p_value;
- int32_t value_size;
-} tBTA_JV_API_ADD_ATTRIBUTE;
-
-/* data type for BTA_JV_API_FREE_SCN_EVT */
-typedef struct {
- BT_HDR hdr;
- int32_t type; /* One of BTA_JV_CONN_TYPE_ */
- uint16_t scn;
-} tBTA_JV_API_FREE_CHANNEL;
-
-/* data type for BTA_JV_API_ALLOC_CHANNEL_EVT */
-typedef struct {
- BT_HDR hdr;
- int32_t type; /* One of BTA_JV_CONN_TYPE_ */
- int32_t channel; /* optionally request a specific channel */
- uint32_t l2cap_socket_id;
- uint32_t rfcomm_slot_id;
-} tBTA_JV_API_ALLOC_CHANNEL;
-/* union of all data types */
-typedef union {
- /* GKI event buffer header */
- BT_HDR hdr;
- tBTA_JV_API_ENABLE enable;
- tBTA_JV_API_START_DISCOVERY start_discovery;
- tBTA_JV_API_ALLOC_CHANNEL alloc_channel;
- tBTA_JV_API_FREE_CHANNEL free_channel;
- tBTA_JV_API_CREATE_RECORD create_record;
- tBTA_JV_API_ADD_ATTRIBUTE add_attr;
- tBTA_JV_API_L2CAP_CONNECT l2cap_connect;
- tBTA_JV_API_L2CAP_READ l2cap_read;
- tBTA_JV_API_L2CAP_WRITE l2cap_write;
- tBTA_JV_API_L2CAP_CLOSE l2cap_close;
- tBTA_JV_API_L2CAP_SERVER l2cap_server;
- tBTA_JV_API_RFCOMM_CONNECT rfcomm_connect;
- tBTA_JV_API_RFCOMM_WRITE rfcomm_write;
- tBTA_JV_API_SET_PM_PROFILE set_pm;
- tBTA_JV_API_PM_STATE_CHANGE change_pm_state;
- tBTA_JV_API_RFCOMM_CLOSE rfcomm_close;
- tBTA_JV_API_RFCOMM_SERVER rfcomm_server;
- tBTA_JV_API_L2CAP_WRITE_FIXED l2cap_write_fixed;
-} tBTA_JV_MSG;
-
/* JV control block */
typedef struct {
/* the SDP handle reported to JV user is the (index + 1) to sdp_handle[].
@@ -361,7 +123,7 @@
uint16_t free_psm_list[BTA_JV_MAX_L2C_CONN]; /* PSMs freed by java
(can be reused) */
uint8_t sdp_active; /* see BTA_JV_SDP_ACT_* */
- tSDP_UUID uuid; /* current uuid of sdp discovery*/
+ bluetooth::Uuid uuid; /* current uuid of sdp discovery*/
tBTA_JV_PM_CB pm_cb[BTA_JV_PM_MAX_NUM]; /* PM on a per JV handle bases */
} tBTA_JV_CB;
@@ -377,33 +139,62 @@
/* config struct */
extern tBTA_JV_CFG* p_bta_jv_cfg;
-extern bool bta_jv_sm_execute(BT_HDR* p_msg);
-
-extern void bta_jv_enable(tBTA_JV_MSG* p_data);
-extern void bta_jv_disable(tBTA_JV_MSG* p_data);
-extern void bta_jv_get_channel_id(tBTA_JV_MSG* p_data);
-extern void bta_jv_free_scn(tBTA_JV_MSG* p_data);
-extern void bta_jv_start_discovery(tBTA_JV_MSG* p_data);
-extern void bta_jv_create_record(tBTA_JV_MSG* p_data);
-extern void bta_jv_delete_record(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_connect(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_close(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_start_server(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_stop_server(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_read(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_write(tBTA_JV_MSG* p_data);
-extern void bta_jv_rfcomm_connect(tBTA_JV_MSG* p_data);
-extern void bta_jv_rfcomm_close(tBTA_JV_MSG* p_data);
-extern void bta_jv_rfcomm_start_server(tBTA_JV_MSG* p_data);
-extern void bta_jv_rfcomm_stop_server(tBTA_JV_MSG* p_data);
-extern void bta_jv_rfcomm_read(tBTA_JV_MSG* p_data);
-extern void bta_jv_rfcomm_write(tBTA_JV_MSG* p_data);
-extern void bta_jv_set_pm_profile(tBTA_JV_MSG* p_data);
-extern void bta_jv_change_pm_state(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_connect_le(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_start_server_le(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_stop_server_le(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_write_fixed(tBTA_JV_MSG* p_data);
-extern void bta_jv_l2cap_close_fixed(tBTA_JV_MSG* p_data);
+extern void bta_jv_enable(tBTA_JV_DM_CBACK* p_cback);
+extern void bta_jv_disable();
+extern void bta_jv_get_channel_id(int32_t type, int32_t channel,
+ uint32_t l2cap_socket_id,
+ uint32_t rfcomm_slot_id);
+extern void bta_jv_free_scn(int32_t type, uint16_t scn);
+extern void bta_jv_start_discovery(const RawAddress& bd_addr, uint16_t num_uuid,
+ bluetooth::Uuid* uuid_list,
+ uint32_t rfcomm_slot_id);
+extern void bta_jv_create_record(uint32_t rfcomm_slot_id);
+extern void bta_jv_delete_record(uint32_t handle);
+extern void bta_jv_l2cap_connect(int32_t type, tBTA_SEC sec_mask,
+ tBTA_JV_ROLE role, uint16_t remote_psm,
+ uint16_t rx_mtu,
+ const RawAddress& peer_bd_addr,
+ std::unique_ptr<tL2CAP_CFG_INFO> cfg,
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id);
+extern void bta_jv_l2cap_close(uint32_t handle, tBTA_JV_L2C_CB* p_cb);
+extern void bta_jv_l2cap_start_server(
+ int32_t type, tBTA_SEC sec_mask, tBTA_JV_ROLE role, uint16_t local_psm,
+ uint16_t rx_mtu, std::unique_ptr<tL2CAP_CFG_INFO> cfg_param,
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info, tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id);
+extern void bta_jv_l2cap_stop_server(uint16_t local_psm,
+ uint32_t l2cap_socket_id);
+extern void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, BT_HDR* msg,
+ uint32_t user_id, tBTA_JV_L2C_CB* p_cb);
+extern void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ uint8_t remote_scn,
+ const RawAddress& peer_bd_addr,
+ tBTA_JV_RFCOMM_CBACK* p_cback,
+ uint32_t rfcomm_slot_id);
+extern void bta_jv_rfcomm_close(uint32_t handle, uint32_t rfcomm_slot_id);
+extern void bta_jv_rfcomm_start_server(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ uint8_t local_scn, uint8_t max_session,
+ tBTA_JV_RFCOMM_CBACK* p_cback,
+ uint32_t rfcomm_slot_id);
+extern void bta_jv_rfcomm_stop_server(uint32_t handle, uint32_t rfcomm_slot_id);
+extern void bta_jv_rfcomm_write(uint32_t handle, uint32_t req_id,
+ tBTA_JV_RFC_CB* p_cb, tBTA_JV_PCB* p_pcb);
+extern void bta_jv_set_pm_profile(uint32_t handle, tBTA_JV_PM_ID app_id,
+ tBTA_JV_CONN_STATE init_st);
+extern void bta_jv_l2cap_connect_le(uint16_t remote_chan,
+ const RawAddress& peer_bd_addr,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id);
+extern void bta_jv_l2cap_start_server_le(uint16_t local_chan,
+ tBTA_JV_L2CAP_CBACK* p_cback,
+ uint32_t l2cap_socket_id);
+extern void bta_jv_l2cap_stop_server_le(uint16_t local_chan);
+extern void bta_jv_l2cap_write_fixed(uint16_t channel, const RawAddress& addr,
+ uint32_t req_id, BT_HDR* msg,
+ uint32_t user_id,
+ tBTA_JV_L2CAP_CBACK* p_cback);
+extern void bta_jv_l2cap_close_fixed(uint32_t handle);
#endif /* BTA_JV_INT_H */
diff --git a/bta/jv/bta_jv_main.cc b/bta/jv/bta_jv_main.cc
deleted file mode 100644
index fd5ce3a..0000000
--- a/bta/jv/bta_jv_main.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * This is the main implementation file for the BTA Java I/F
- *
- ******************************************************************************/
-
-#include "bta_api.h"
-#include "bta_jv_api.h"
-#include "bta_jv_int.h"
-#include "bta_sys.h"
-
-/*****************************************************************************
- * Constants and types
- ****************************************************************************/
-
-tBTA_JV_CB bta_jv_cb;
-
-/* state machine action enumeration list */
-#define BTA_JV_NUM_ACTIONS (BTA_JV_MAX_INT_EVT & 0x00ff)
-
-/* type for action functions */
-typedef void (*tBTA_JV_ACTION)(tBTA_JV_MSG* p_data);
-
-/* action function list */
-const tBTA_JV_ACTION bta_jv_action[] = {
- bta_jv_enable, /* BTA_JV_API_ENABLE_EVT */
- bta_jv_disable, /* BTA_JV_API_DISABLE_EVT */
- bta_jv_get_channel_id, /* BTA_JV_API_GET_CHANNEL_EVT */
- bta_jv_free_scn, /* BTA_JV_API_FREE_SCN_EVT */
- bta_jv_start_discovery, /* BTA_JV_API_START_DISCOVERY_EVT */
- bta_jv_create_record, /* BTA_JV_API_CREATE_RECORD_EVT */
- bta_jv_delete_record, /* BTA_JV_API_DELETE_RECORD_EVT */
- bta_jv_l2cap_connect, /* BTA_JV_API_L2CAP_CONNECT_EVT */
- bta_jv_l2cap_close, /* BTA_JV_API_L2CAP_CLOSE_EVT */
- bta_jv_l2cap_start_server, /* BTA_JV_API_L2CAP_START_SERVER_EVT */
- bta_jv_l2cap_stop_server, /* BTA_JV_API_L2CAP_STOP_SERVER_EVT */
- bta_jv_l2cap_read, /* BTA_JV_API_L2CAP_READ_EVT */
- bta_jv_l2cap_write, /* BTA_JV_API_L2CAP_WRITE_EVT */
- bta_jv_rfcomm_connect, /* BTA_JV_API_RFCOMM_CONNECT_EVT */
- bta_jv_rfcomm_close, /* BTA_JV_API_RFCOMM_CLOSE_EVT */
- bta_jv_rfcomm_start_server, /* BTA_JV_API_RFCOMM_START_SERVER_EVT */
- bta_jv_rfcomm_stop_server, /* BTA_JV_API_RFCOMM_STOP_SERVER_EVT */
- bta_jv_rfcomm_write, /* BTA_JV_API_RFCOMM_WRITE_EVT */
- bta_jv_set_pm_profile, /* BTA_JV_API_SET_PM_PROFILE_EVT */
- bta_jv_change_pm_state, /* BTA_JV_API_PM_STATE_CHANGE_EVT */
- bta_jv_l2cap_connect_le, /* BTA_JV_API_L2CAP_CONNECT_LE_EVT */
- bta_jv_l2cap_start_server_le, /* BTA_JV_API_L2CAP_START_SERVER_LE_EVT */
- bta_jv_l2cap_stop_server_le, /* BTA_JV_API_L2CAP_STOP_SERVER_LE_EVT */
- bta_jv_l2cap_write_fixed, /* BTA_JV_API_L2CAP_WRITE_FIXED_EVT */
- bta_jv_l2cap_close_fixed, /* BTA_JV_API_L2CAP_CLOSE_FIXED_EVT */
-};
-
-/*******************************************************************************
- *
- * Function bta_jv_sm_execute
- *
- * Description State machine event handling function for JV
- *
- *
- * Returns void
- *
- ******************************************************************************/
-bool bta_jv_sm_execute(BT_HDR* p_msg) {
- bool ret = false;
- uint16_t action = (p_msg->event & 0x00ff);
- /* execute action functions */
-
- if (action < BTA_JV_NUM_ACTIONS) {
- (*bta_jv_action[action])((tBTA_JV_MSG*)p_msg);
- ret = true;
- }
-
- return (ret);
-}
diff --git a/bta/mce/bta_mce_act.cc b/bta/mce/bta_mce_act.cc
index f188b01..0d9bbf3 100644
--- a/bta/mce/bta_mce_act.cc
+++ b/bta/mce/bta_mce_act.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,12 +38,14 @@
#include "sdp_api.h"
#include "utl.h"
+using bluetooth::Uuid;
+
/*****************************************************************************
* Constants
****************************************************************************/
-static const tBT_UUID bta_mce_mas_uuid = {
- .len = 2, .uu.uuid16 = UUID_SERVCLASS_MESSAGE_ACCESS};
+static const Uuid bta_mce_mas_uuid =
+ Uuid::From16Bit(UUID_SERVCLASS_MESSAGE_ACCESS);
/*******************************************************************************
*
@@ -75,8 +77,8 @@
tSDP_DISC_ATTR* p_attr;
tSDP_PROTOCOL_ELEM pe;
- p_rec = SDP_FindServiceUUIDInDb(p_bta_mce_cfg->p_sdp_db,
- (tBT_UUID*)&bta_mce_mas_uuid, p_rec);
+ p_rec = SDP_FindServiceUUIDInDb(p_bta_mce_cfg->p_sdp_db, bta_mce_mas_uuid,
+ p_rec);
APPL_TRACE_DEBUG("p_rec:%p", p_rec);
@@ -167,7 +169,7 @@
bta_mce_cb.remote_addr = p_data->get_rmt_mas.bd_addr;
SDP_InitDiscoveryDb(p_bta_mce_cfg->p_sdp_db, p_bta_mce_cfg->sdp_db_size, 1,
- (tBT_UUID*)&bta_mce_mas_uuid, 0, NULL);
+ &bta_mce_mas_uuid, 0, NULL);
if (!SDP_ServiceSearchAttributeRequest2(p_data->get_rmt_mas.bd_addr,
p_bta_mce_cfg->p_sdp_db,
diff --git a/bta/mce/bta_mce_api.cc b/bta/mce/bta_mce_api.cc
index b44c210..7ab10da 100644
--- a/bta/mce/bta_mce_api.cc
+++ b/bta/mce/bta_mce_api.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@
APPL_TRACE_API("%", __func__);
- if (p_cback && false == bta_sys_is_register(BTA_ID_MCE)) {
+ if (p_cback && !bta_sys_is_register(BTA_ID_MCE)) {
memset(&bta_mce_cb, 0, sizeof(tBTA_MCE_CB));
/* register with BTA system manager */
diff --git a/bta/mce/bta_mce_cfg.cc b/bta/mce/bta_mce_cfg.cc
index 3beb265..ede80ba 100644
--- a/bta/mce/bta_mce_cfg.cc
+++ b/bta/mce/bta_mce_cfg.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,14 +32,14 @@
#define BTA_MCE_SDP_DB_SIZE 4500
#endif
-static uint8_t __attribute__((aligned(4)))
-bta_mce_sdp_db_data[BTA_MCE_SDP_DB_SIZE];
+static tSDP_DISCOVERY_DB
+ bta_mce_sdp_db_data[BTA_MCE_SDP_DB_SIZE / sizeof(tSDP_DISCOVERY_DB)];
/* MCE configuration structure */
const tBTA_MCE_CFG bta_mce_cfg = {
- BTA_MCE_SDP_DB_SIZE,
- (tSDP_DISCOVERY_DB*)
- bta_mce_sdp_db_data /* The data buffer to keep SDP database */
+ (BTA_MCE_SDP_DB_SIZE / sizeof(tSDP_DISCOVERY_DB)) *
+ sizeof(tSDP_DISCOVERY_DB),
+ bta_mce_sdp_db_data /* The data buffer to keep SDP database */
};
-tBTA_MCE_CFG* p_bta_mce_cfg = (tBTA_MCE_CFG*)&bta_mce_cfg;
+const tBTA_MCE_CFG* p_bta_mce_cfg = &bta_mce_cfg;
diff --git a/bta/mce/bta_mce_int.h b/bta/mce/bta_mce_int.h
index cff5875..4e1058f 100644
--- a/bta/mce/bta_mce_int.h
+++ b/bta/mce/bta_mce_int.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/mce/bta_mce_main.cc b/bta/mce/bta_mce_main.cc
index abd3e5c..d2a2ca1 100644
--- a/bta/mce/bta_mce_main.cc
+++ b/bta/mce/bta_mce_main.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/pan/bta_pan_act.cc b/bta/pan/bta_pan_act.cc
index 41e0bf6..04c06d0 100644
--- a/bta/pan/bta_pan_act.cc
+++ b/bta/pan/bta_pan_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -171,31 +171,25 @@
static void bta_pan_data_buf_ind_cback(uint16_t handle, const RawAddress& src,
const RawAddress& dst, uint16_t protocol,
BT_HDR* p_buf, bool ext, bool forward) {
- tBTA_PAN_SCB* p_scb;
- BT_HDR* p_new_buf;
-
- p_scb = bta_pan_scb_by_handle(handle);
+ tBTA_PAN_SCB* p_scb = bta_pan_scb_by_handle(handle);
if (p_scb == NULL) {
return;
}
- if (sizeof(tBTA_PAN_DATA_PARAMS) > p_buf->offset) {
- /* offset smaller than data structure in front of actual data */
- if (sizeof(BT_HDR) + sizeof(tBTA_PAN_DATA_PARAMS) + p_buf->len >
- PAN_BUF_SIZE) {
- android_errorWriteLog(0x534e4554, "63146237");
- APPL_TRACE_ERROR("%s: received buffer length too large: %d", __func__,
- p_buf->len);
- return;
- }
- p_new_buf = (BT_HDR*)osi_malloc(PAN_BUF_SIZE);
- memcpy((uint8_t*)(p_new_buf + 1) + sizeof(tBTA_PAN_DATA_PARAMS),
- (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len);
- p_new_buf->len = p_buf->len;
- p_new_buf->offset = sizeof(tBTA_PAN_DATA_PARAMS);
- } else {
- p_new_buf = p_buf;
+ if (sizeof(BT_HDR) + sizeof(tBTA_PAN_DATA_PARAMS) + p_buf->len >
+ PAN_BUF_SIZE) {
+ android_errorWriteLog(0x534e4554, "63146237");
+ APPL_TRACE_ERROR("%s: received buffer length too large: %d", __func__,
+ p_buf->len);
+ return;
}
+
+ BT_HDR* p_new_buf = (BT_HDR*)osi_malloc(PAN_BUF_SIZE);
+ memcpy((uint8_t*)(p_new_buf + 1) + sizeof(tBTA_PAN_DATA_PARAMS),
+ (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len);
+ p_new_buf->len = p_buf->len;
+ p_new_buf->offset = sizeof(tBTA_PAN_DATA_PARAMS);
+
/* copy params into the space before the data */
((tBTA_PAN_DATA_PARAMS*)p_new_buf)->src = src;
((tBTA_PAN_DATA_PARAMS*)p_new_buf)->dst = dst;
@@ -268,7 +262,7 @@
for (uint8_t index = 0; index < BTA_PAN_NUM_CONN; index++) {
p_scb = &bta_pan_cb.scb[index];
- if (p_scb->in_use == true && app_id == p_scb->app_id) {
+ if (p_scb->in_use && app_id == p_scb->app_id) {
/* save temp bd_addr */
bd_addr = p_scb->bd_addr;
found = true;
@@ -277,14 +271,14 @@
}
/* If cannot find a match then there is no connection at all */
- if (found == false) return false;
+ if (!found) return false;
/* Find whether there is another connection with different device other than
PANU.
Could be same service or different service */
for (uint8_t index = 0; index < BTA_PAN_NUM_CONN; index++) {
p_scb = &bta_pan_cb.scb[index];
- if (p_scb->in_use == true && p_scb->app_id != bta_pan_cb.app_id[0] &&
+ if (p_scb->in_use && p_scb->app_id != bta_pan_cb.app_id[0] &&
bd_addr != p_scb->bd_addr) {
return true;
}
@@ -583,7 +577,7 @@
/* if data path configured for rx pull */
if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PULL) {
/* if we can accept data */
- if (p_scb->pan_flow_enable == true) {
+ if (p_scb->pan_flow_enable) {
/* call application callout function for rx path */
bta_pan_co_rx_path(p_scb->handle, p_scb->app_id);
}
@@ -618,7 +612,7 @@
/* if configured for zero copy push */
else if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PUSH_BUF) {
/* if app can accept data */
- if (p_scb->app_flow_enable == true) {
+ if (p_scb->app_flow_enable) {
BT_HDR* p_buf;
/* read data from the queue */
diff --git a/bta/pan/bta_pan_api.cc b/bta/pan/bta_pan_api.cc
index 0011522..9f25735 100644
--- a/bta/pan/bta_pan_api.cc
+++ b/bta/pan/bta_pan_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/pan/bta_pan_ci.cc b/bta/pan/bta_pan_ci.cc
index 9863e78..d2fda39 100644
--- a/bta/pan/bta_pan_ci.cc
+++ b/bta/pan/bta_pan_ci.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -183,10 +183,10 @@
******************************************************************************/
BT_HDR* bta_pan_ci_readbuf(uint16_t handle, RawAddress& src, RawAddress& dst,
uint16_t* p_protocol, bool* p_ext, bool* p_forward) {
- tBTA_PAN_SCB* p_scb;
+ tBTA_PAN_SCB* p_scb = bta_pan_scb_by_handle(handle);
BT_HDR* p_buf;
- p_scb = bta_pan_scb_by_handle(handle);
+ if (p_scb == NULL) return NULL;
p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_scb->data_queue);
if (p_buf != NULL) {
diff --git a/bta/pan/bta_pan_int.h b/bta/pan/bta_pan_int.h
index 089fd1d..df79fcb 100644
--- a/bta/pan/bta_pan_int.h
+++ b/bta/pan/bta_pan_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/pan/bta_pan_main.cc b/bta/pan/bta_pan_main.cc
index 9ee5e0a..09df88f 100644
--- a/bta/pan/bta_pan_main.cc
+++ b/bta/pan/bta_pan_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,7 +51,8 @@
BTA_PAN_CONN_OPEN,
BTA_PAN_CONN_CLOSE,
BTA_PAN_FREE_BUF,
- BTA_PAN_IGNORE
+ BTA_PAN_IGNORE,
+ BTA_PAN_MAX_ACTIONS
};
/* type for action functions */
@@ -184,11 +185,9 @@
/* execute action functions */
for (i = 0; i < BTA_PAN_ACTIONS; i++) {
action = state_table[event][i];
- if (action != BTA_PAN_IGNORE) {
- (*bta_pan_action[action])(p_scb, p_data);
- } else {
- break;
- }
+ CHECK(action < BTA_PAN_MAX_ACTIONS);
+ if (action == BTA_PAN_IGNORE) continue;
+ (*bta_pan_action[action])(p_scb, p_data);
}
}
diff --git a/bta/pb/bta_pbs_int.h b/bta/pb/bta_pbs_int.h
index ae21ce4..cf597f8 100644
--- a/bta/pb/bta_pbs_int.h
+++ b/bta/pb/bta_pbs_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/sdp/bta_sdp.cc b/bta/sdp/bta_sdp.cc
index 735d0b7..1729db8 100644
--- a/bta/sdp/bta_sdp.cc
+++ b/bta/sdp/bta_sdp.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/sdp/bta_sdp_act.cc b/bta/sdp/bta_sdp_act.cc
index 172875f..80baed7 100644
--- a/bta/sdp/bta_sdp_act.cc
+++ b/bta/sdp/bta_sdp_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,55 +42,11 @@
* Constants
****************************************************************************/
-static const uint8_t UUID_OBEX_OBJECT_PUSH[] = {
- 0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
-static const uint8_t UUID_PBAP_PSE[] = {0x00, 0x00, 0x11, 0x2F, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-static const uint8_t UUID_MAP_MAS[] = {0x00, 0x00, 0x11, 0x32, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-static const uint8_t UUID_MAP_MNS[] = {0x00, 0x00, 0x11, 0x33, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-static const uint8_t UUID_SAP[] = {0x00, 0x00, 0x11, 0x2D, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-// TODO:
-// Both the fact that the UUIDs are declared in multiple places, plus the fact
-// that there is a mess of UUID comparison and shortening methods will have to
-// be fixed.
-// The btcore->uuid module should be used for all instances.
-
-#define UUID_MAX_LENGTH 16
-#define IS_UUID(u1, u2) !memcmp(u1, u2, UUID_MAX_LENGTH)
-
-static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID* u) {
- static uint8_t bt_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-
- APPL_TRACE_DEBUG("%s() - uuid len:%d", __func__, u->len);
- if (u->len != 16) return *u;
-
- if (memcmp(&u->uu.uuid128[4], &bt_base_uuid[4], 12) != 0) return *u;
-
- tBT_UUID su;
- memset(&su, 0, sizeof(su));
- if (u->uu.uuid128[0] == 0 && u->uu.uuid128[1] == 0) {
- su.len = 2;
- uint16_t u16;
- memcpy(&u16, &u->uu.uuid128[2], sizeof(u16));
- su.uu.uuid16 = ntohs(u16);
- } else {
- su.len = 4;
- uint32_t u32;
- memcpy(&u32, &u->uu.uuid128[0], sizeof(u32));
- su.uu.uuid32 = ntohl(u32);
- }
- return su;
-}
+static const Uuid UUID_OBEX_OBJECT_PUSH = Uuid::From16Bit(0x1105);
+static const Uuid UUID_PBAP_PSE = Uuid::From16Bit(0x112F);
+static const Uuid UUID_MAP_MAS = Uuid::From16Bit(0x1132);
+static const Uuid UUID_MAP_MNS = Uuid::From16Bit(0x1133);
+static const Uuid UUID_SAP = Uuid::From16Bit(0x112D);
static void bta_create_mns_sdp_record(bluetooth_sdp_record* record,
tSDP_DISC_REC* p_rec) {
@@ -373,74 +329,63 @@
record->hdr.user1_ptr = p_bta_sdp_cfg->p_sdp_db->raw_data;
}
-/*******************************************************************************
- *
- * Function bta_sdp_search_cback
- *
- * Description Callback from btm after search is completed
- *
- * Returns void
- *
- ******************************************************************************/
+/** Callback from btm after search is completed */
static void bta_sdp_search_cback(uint16_t result, void* user_data) {
- tSDP_DISC_REC* p_rec = NULL;
- tBTA_SDP_SEARCH_COMP evt_data;
tBTA_SDP_STATUS status = BTA_SDP_FAILURE;
int count = 0;
- tBT_UUID su;
APPL_TRACE_DEBUG("%s() - res: 0x%x", __func__, result);
- memset(&evt_data, 0, sizeof(evt_data));
bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_NONE;
if (bta_sdp_cb.p_dm_cback == NULL) return;
+ Uuid& uuid = *(reinterpret_cast<Uuid*>(user_data));
+
+ tBTA_SDP_SEARCH_COMP evt_data;
+ memset(&evt_data, 0, sizeof(evt_data));
evt_data.remote_addr = bta_sdp_cb.remote_addr;
- tBT_UUID* uuid = (tBT_UUID*)user_data;
- memcpy(&evt_data.uuid, uuid, sizeof(tBT_UUID));
- su = shorten_sdp_uuid(uuid);
+ evt_data.uuid = uuid;
if (result == SDP_SUCCESS || result == SDP_DB_FULL) {
+ tSDP_DISC_REC* p_rec = NULL;
do {
- p_rec = SDP_FindServiceUUIDInDb(p_bta_sdp_cfg->p_sdp_db, &su, p_rec);
+ p_rec = SDP_FindServiceUUIDInDb(p_bta_sdp_cfg->p_sdp_db, uuid, p_rec);
/* generate the matching record data pointer */
- if (p_rec != NULL) {
- status = BTA_SDP_SUCCESS;
- if (IS_UUID(UUID_MAP_MAS, uuid->uu.uuid128)) {
- APPL_TRACE_DEBUG("%s() - found MAP (MAS) uuid", __func__);
- bta_create_mas_sdp_record(&evt_data.records[count], p_rec);
- } else if (IS_UUID(UUID_MAP_MNS, uuid->uu.uuid128)) {
- APPL_TRACE_DEBUG("%s() - found MAP (MNS) uuid", __func__);
- bta_create_mns_sdp_record(&evt_data.records[count], p_rec);
- } else if (IS_UUID(UUID_PBAP_PSE, uuid->uu.uuid128)) {
- APPL_TRACE_DEBUG("%s() - found PBAP (PSE) uuid", __func__);
- bta_create_pse_sdp_record(&evt_data.records[count], p_rec);
- } else if (IS_UUID(UUID_OBEX_OBJECT_PUSH, uuid->uu.uuid128)) {
- APPL_TRACE_DEBUG("%s() - found Object Push Server (OPS) uuid",
- __func__);
- bta_create_ops_sdp_record(&evt_data.records[count], p_rec);
- } else if (IS_UUID(UUID_SAP, uuid->uu.uuid128)) {
- APPL_TRACE_DEBUG("%s() - found SAP uuid", __func__);
- bta_create_sap_sdp_record(&evt_data.records[count], p_rec);
- } else {
- /* we do not have specific structure for this */
- APPL_TRACE_DEBUG("%s() - profile not identified. using raw data",
- __func__);
- bta_create_raw_sdp_record(&evt_data.records[count], p_rec);
- p_rec = NULL; // Terminate loop
- /* For raw, we only extract the first entry, and then return the
- entire
- raw data chunk.
- TODO: Find a way to split the raw data into record chunks, and
- iterate
- to extract generic data for each chunk - e.g. rfcomm channel
- and
- service name. */
- }
- count++;
- } else {
+ if (!p_rec) {
APPL_TRACE_DEBUG("%s() - UUID not found", __func__);
+ continue;
}
+
+ status = BTA_SDP_SUCCESS;
+ if (uuid == UUID_MAP_MAS) {
+ APPL_TRACE_DEBUG("%s() - found MAP (MAS) uuid", __func__);
+ bta_create_mas_sdp_record(&evt_data.records[count], p_rec);
+ } else if (uuid == UUID_MAP_MNS) {
+ APPL_TRACE_DEBUG("%s() - found MAP (MNS) uuid", __func__);
+ bta_create_mns_sdp_record(&evt_data.records[count], p_rec);
+ } else if (uuid == UUID_PBAP_PSE) {
+ APPL_TRACE_DEBUG("%s() - found PBAP (PSE) uuid", __func__);
+ bta_create_pse_sdp_record(&evt_data.records[count], p_rec);
+ } else if (uuid == UUID_OBEX_OBJECT_PUSH) {
+ APPL_TRACE_DEBUG("%s() - found Object Push Server (OPS) uuid",
+ __func__);
+ bta_create_ops_sdp_record(&evt_data.records[count], p_rec);
+ } else if (uuid == UUID_SAP) {
+ APPL_TRACE_DEBUG("%s() - found SAP uuid", __func__);
+ bta_create_sap_sdp_record(&evt_data.records[count], p_rec);
+ } else {
+ /* we do not have specific structure for this */
+ APPL_TRACE_DEBUG("%s() - profile not identified. using raw data",
+ __func__);
+ bta_create_raw_sdp_record(&evt_data.records[count], p_rec);
+ p_rec = NULL; // Terminate loop
+ /* For raw, we only extract the first entry, and then return the
+ entire raw data chunk.
+ TODO: Find a way to split the raw data into record chunks, and
+ iterate to extract generic data for each chunk - e.g. rfcomm
+ channel and service name. */
+ }
+ count++;
} while (p_rec != NULL && count < BTA_SDP_MAX_RECORDS);
evt_data.record_count = count;
@@ -449,8 +394,7 @@
tBTA_SDP bta_sdp;
bta_sdp.sdp_search_comp = evt_data;
- bta_sdp_cb.p_dm_cback(BTA_SDP_SEARCH_COMP_EVT, &bta_sdp,
- (void*)&uuid->uu.uuid128);
+ bta_sdp_cb.p_dm_cback(BTA_SDP_SEARCH_COMP_EVT, &bta_sdp, (void*)&uuid);
osi_free(user_data); // We no longer need the user data to track the search
}
@@ -490,13 +434,14 @@
APPL_TRACE_DEBUG("%s in, sdp_active:%d", __func__, bta_sdp_cb.sdp_active);
+ const Uuid& uuid = p_data->get_search.uuid;
if (bta_sdp_cb.sdp_active != BTA_SDP_ACTIVE_NONE) {
/* SDP is still in progress */
status = BTA_SDP_BUSY;
if (bta_sdp_cb.p_dm_cback) {
tBTA_SDP_SEARCH_COMP result;
memset(&result, 0, sizeof(result));
- result.uuid = p_data->get_search.uuid;
+ result.uuid = uuid;
result.remote_addr = p_data->get_search.bd_addr;
result.status = status;
tBTA_SDP bta_sdp;
@@ -508,20 +453,15 @@
bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_YES;
bta_sdp_cb.remote_addr = p_data->get_search.bd_addr;
- /* set the uuid used in the search */
- tBT_UUID* bta_sdp_search_uuid =
- static_cast<tBT_UUID*>(osi_malloc(sizeof(tBT_UUID)));
- memcpy(bta_sdp_search_uuid, &(p_data->get_search.uuid), sizeof(tBT_UUID));
/* initialize the search for the uuid */
- APPL_TRACE_DEBUG("%s init discovery with UUID(len: %d):", __func__,
- bta_sdp_search_uuid->len);
- for (int x = 0; x < bta_sdp_search_uuid->len; x++) {
- APPL_TRACE_DEBUG("%X", bta_sdp_search_uuid->uu.uuid128[x]);
- }
+ APPL_TRACE_DEBUG("%s init discovery with UUID: %s", __func__,
+ uuid.ToString().c_str());
SDP_InitDiscoveryDb(p_bta_sdp_cfg->p_sdp_db, p_bta_sdp_cfg->sdp_db_size, 1,
- bta_sdp_search_uuid, 0, NULL);
+ &uuid, 0, NULL);
+ Uuid* bta_sdp_search_uuid = (Uuid*)osi_malloc(sizeof(Uuid));
+ *bta_sdp_search_uuid = uuid;
if (!SDP_ServiceSearchAttributeRequest2(
p_data->get_search.bd_addr, p_bta_sdp_cfg->p_sdp_db,
bta_sdp_search_cback, (void*)bta_sdp_search_uuid)) {
@@ -531,7 +471,7 @@
if (bta_sdp_cb.p_dm_cback) {
tBTA_SDP_SEARCH_COMP result;
memset(&result, 0, sizeof(result));
- result.uuid = p_data->get_search.uuid;
+ result.uuid = uuid;
result.remote_addr = p_data->get_search.bd_addr;
result.status = status;
tBTA_SDP bta_sdp;
diff --git a/bta/sdp/bta_sdp_api.cc b/bta/sdp/bta_sdp_api.cc
index bc6a9b9..17e449c 100644
--- a/bta/sdp/bta_sdp_api.cc
+++ b/bta/sdp/bta_sdp_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@
tBTA_SDP_STATUS status = BTA_SDP_FAILURE;
APPL_TRACE_API(__func__);
- if (p_cback && false == bta_sys_is_register(BTA_ID_SDP)) {
+ if (p_cback && !bta_sys_is_register(BTA_ID_SDP)) {
memset(&bta_sdp_cb, 0, sizeof(tBTA_SDP_CB));
/* register with BTA system manager */
@@ -87,7 +87,8 @@
* BTA_SDP_FAILURE, otherwise.
*
******************************************************************************/
-tBTA_SDP_STATUS BTA_SdpSearch(const RawAddress& bd_addr, tSDP_UUID* uuid) {
+tBTA_SDP_STATUS BTA_SdpSearch(const RawAddress& bd_addr,
+ const bluetooth::Uuid& uuid) {
tBTA_SDP_API_SEARCH* p_msg =
(tBTA_SDP_API_SEARCH*)osi_malloc(sizeof(tBTA_SDP_API_SEARCH));
@@ -95,8 +96,7 @@
p_msg->hdr.event = BTA_SDP_API_SEARCH_EVT;
p_msg->bd_addr = bd_addr;
- // p_msg->uuid = uuid;
- memcpy(&(p_msg->uuid), uuid, sizeof(tSDP_UUID));
+ p_msg->uuid = uuid;
bta_sys_sendmsg(p_msg);
diff --git a/bta/sdp/bta_sdp_cfg.cc b/bta/sdp/bta_sdp_cfg.cc
index 5be6755..beec3b5 100644
--- a/bta/sdp/bta_sdp_cfg.cc
+++ b/bta/sdp/bta_sdp_cfg.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,13 +28,13 @@
#define BTA_SDP_DB_SIZE 4500
#endif
-static uint8_t __attribute__((aligned(4))) bta_sdp_db_data[BTA_SDP_DB_SIZE];
+static tSDP_DISCOVERY_DB
+ bta_sdp_db_data[BTA_SDP_DB_SIZE / sizeof(tSDP_DISCOVERY_DB)];
/* SDP configuration structure */
const tBTA_SDP_CFG bta_sdp_cfg = {
- BTA_SDP_DB_SIZE,
- (tSDP_DISCOVERY_DB*)
- bta_sdp_db_data /* The data buffer to keep SDP database */
+ (BTA_SDP_DB_SIZE / sizeof(tSDP_DISCOVERY_DB)) * sizeof(tSDP_DISCOVERY_DB),
+ bta_sdp_db_data /* The data buffer to keep SDP database */
};
-tBTA_SDP_CFG* p_bta_sdp_cfg = (tBTA_SDP_CFG*)&bta_sdp_cfg;
+const tBTA_SDP_CFG* p_bta_sdp_cfg = &bta_sdp_cfg;
diff --git a/bta/sdp/bta_sdp_int.h b/bta/sdp/bta_sdp_int.h
index 0cb5b93..b6b68fa 100644
--- a/bta/sdp/bta_sdp_int.h
+++ b/bta/sdp/bta_sdp_int.h
@@ -2,8 +2,8 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@
typedef struct {
BT_HDR hdr;
RawAddress bd_addr;
- tSDP_UUID uuid;
+ bluetooth::Uuid uuid;
} tBTA_SDP_API_SEARCH;
/* data type for BTA_SDP_API_SEARCH_EVT */
diff --git a/bta/sys/bta_sys.h b/bta/sys/bta_sys.h
index 4edcfb3..a72f34b 100644
--- a/bta/sys/bta_sys.h
+++ b/bta/sys/bta_sys.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,8 @@
#include <base/logging.h>
#include <base/threading/thread.h>
+#include "bta/include/bta_closure_api.h"
+
/*****************************************************************************
* Constants and data types
****************************************************************************/
@@ -61,7 +63,6 @@
/* SW sub-systems */
#define BTA_ID_SYS 0 /* system manager */
/* BLUETOOTH PART - from 0 to BTA_ID_BLUETOOTH_MAX */
-#define BTA_ID_DM 1 /* device manager */
#define BTA_ID_DM_SEARCH 2 /* device manager search */
#define BTA_ID_DM_SEC 3 /* device manager security */
#define BTA_ID_DG 4 /* data gateway */
@@ -139,7 +140,7 @@
/* conn callback for role / low power manager*/
typedef void(tBTA_SYS_CONN_CBACK)(tBTA_SYS_CONN_STATUS status, uint8_t id,
- uint8_t app_id, const RawAddress* peer_addr);
+ uint8_t app_id, const RawAddress& peer_addr);
/* conn callback for role / low power manager*/
typedef void(tBTA_SYS_SSR_CFG_CBACK)(uint8_t id, uint8_t app_id,
@@ -223,8 +224,6 @@
extern bool bta_sys_is_register(uint8_t id);
extern uint16_t bta_sys_get_sys_features(void);
extern void bta_sys_sendmsg(void* p_msg);
-extern void do_in_bta_thread(const tracked_objects::Location& from_here,
- const base::Closure& task);
extern void bta_sys_start_timer(alarm_t* alarm, period_ms_t interval,
uint16_t event, uint16_t layer_specific);
extern void bta_sys_disable(tBTA_SYS_HW_MODULE module);
@@ -267,11 +266,11 @@
#endif
extern void bta_sys_role_chg_register(tBTA_SYS_CONN_CBACK* p_cback);
-extern void bta_sys_notify_role_chg(const RawAddress& p_bda, uint8_t new_role,
- uint8_t hci_status);
+extern void bta_sys_notify_role_chg(const RawAddress& peer_addr,
+ uint8_t new_role, uint8_t hci_status);
extern void bta_sys_collision_register(uint8_t bta_id,
tBTA_SYS_CONN_CBACK* p_cback);
-extern void bta_sys_notify_collision(const RawAddress& p_bda);
+extern void bta_sys_notify_collision(const RawAddress& peer_addr);
#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
extern void bta_sys_eir_register(tBTA_SYS_EIR_CBACK* p_cback);
diff --git a/bta/sys/bta_sys_conn.cc b/bta/sys/bta_sys_conn.cc
index 6d9fc17..ef9649b 100644
--- a/bta/sys/bta_sys_conn.cc
+++ b/bta/sys/bta_sys_conn.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -97,10 +97,12 @@
* Returns void
*
******************************************************************************/
-void bta_sys_notify_role_chg(const RawAddress& p_bda, uint8_t new_role,
+void bta_sys_notify_role_chg(const RawAddress& peer_addr, uint8_t new_role,
uint8_t hci_status) {
+ APPL_TRACE_DEBUG("%s: peer %s new_role:%d hci_status:0x%x", __func__,
+ peer_addr.ToString().c_str(), new_role, hci_status);
if (bta_sys_cb.p_role_cb) {
- bta_sys_cb.p_role_cb(BTA_SYS_ROLE_CHANGE, new_role, hci_status, &p_bda);
+ bta_sys_cb.p_role_cb(BTA_SYS_ROLE_CHANGE, new_role, hci_status, peer_addr);
}
}
@@ -137,13 +139,13 @@
* Returns void
*
******************************************************************************/
-void bta_sys_notify_collision(const RawAddress& p_bda) {
+void bta_sys_notify_collision(const RawAddress& peer_addr) {
uint8_t index;
for (index = 0; index < MAX_COLLISION_REG; index++) {
if ((bta_sys_cb.colli_reg.id[index] != 0) &&
(bta_sys_cb.colli_reg.p_coll_cback[index] != NULL)) {
- bta_sys_cb.colli_reg.p_coll_cback[index](0, BTA_ID_SYS, 0, &p_bda);
+ bta_sys_cb.colli_reg.p_coll_cback[index](0, BTA_ID_SYS, 0, peer_addr);
}
}
}
@@ -190,11 +192,11 @@
void bta_sys_conn_open(uint8_t id, uint8_t app_id,
const RawAddress& peer_addr) {
if (bta_sys_cb.prm_cb) {
- bta_sys_cb.prm_cb(BTA_SYS_CONN_OPEN, id, app_id, &peer_addr);
+ bta_sys_cb.prm_cb(BTA_SYS_CONN_OPEN, id, app_id, peer_addr);
}
if (bta_sys_cb.ppm_cb) {
- bta_sys_cb.ppm_cb(BTA_SYS_CONN_OPEN, id, app_id, &peer_addr);
+ bta_sys_cb.ppm_cb(BTA_SYS_CONN_OPEN, id, app_id, peer_addr);
}
}
@@ -212,11 +214,11 @@
void bta_sys_conn_close(uint8_t id, uint8_t app_id,
const RawAddress& peer_addr) {
if (bta_sys_cb.prm_cb) {
- bta_sys_cb.prm_cb(BTA_SYS_CONN_CLOSE, id, app_id, &peer_addr);
+ bta_sys_cb.prm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
}
if (bta_sys_cb.ppm_cb) {
- bta_sys_cb.ppm_cb(BTA_SYS_CONN_CLOSE, id, app_id, &peer_addr);
+ bta_sys_cb.ppm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
}
}
@@ -233,7 +235,7 @@
******************************************************************************/
void bta_sys_app_open(uint8_t id, uint8_t app_id, const RawAddress& peer_addr) {
if (bta_sys_cb.ppm_cb) {
- bta_sys_cb.ppm_cb(BTA_SYS_APP_OPEN, id, app_id, &peer_addr);
+ bta_sys_cb.ppm_cb(BTA_SYS_APP_OPEN, id, app_id, peer_addr);
}
}
@@ -250,7 +252,7 @@
void bta_sys_app_close(uint8_t id, uint8_t app_id,
const RawAddress& peer_addr) {
if (bta_sys_cb.ppm_cb) {
- bta_sys_cb.ppm_cb(BTA_SYS_APP_CLOSE, id, app_id, &peer_addr);
+ bta_sys_cb.ppm_cb(BTA_SYS_APP_CLOSE, id, app_id, peer_addr);
}
}
@@ -268,11 +270,11 @@
/* AG triggers p_sco_cb by bta_sys_sco_use. */
if ((id != BTA_ID_AG) && (bta_sys_cb.p_sco_cb)) {
/* without querying BTM_GetNumScoLinks() */
- bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, &peer_addr);
+ bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, peer_addr);
}
if (bta_sys_cb.ppm_cb) {
- bta_sys_cb.ppm_cb(BTA_SYS_SCO_OPEN, id, app_id, &peer_addr);
+ bta_sys_cb.ppm_cb(BTA_SYS_SCO_OPEN, id, app_id, peer_addr);
}
}
@@ -292,11 +294,11 @@
if ((id != BTA_ID_AG) && (bta_sys_cb.p_sco_cb)) {
num_sco_links = BTM_GetNumScoLinks();
- bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, &peer_addr);
+ bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, peer_addr);
}
if (bta_sys_cb.ppm_cb) {
- bta_sys_cb.ppm_cb(BTA_SYS_SCO_CLOSE, id, app_id, &peer_addr);
+ bta_sys_cb.ppm_cb(BTA_SYS_SCO_CLOSE, id, app_id, peer_addr);
}
}
@@ -315,7 +317,7 @@
/* AV streaming need to be suspended before SCO is connected. */
if (bta_sys_cb.p_sco_cb) {
/* without querying BTM_GetNumScoLinks() */
- bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, &peer_addr);
+ bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, peer_addr);
}
}
@@ -333,7 +335,7 @@
const RawAddress& peer_addr) {
if ((bta_sys_cb.p_sco_cb)) {
uint8_t num_sco_links = BTM_GetNumScoLinks();
- bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, &peer_addr);
+ bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, peer_addr);
}
}
/*******************************************************************************
@@ -366,8 +368,10 @@
******************************************************************************/
void bta_sys_set_policy(uint8_t id, uint8_t policy,
const RawAddress& peer_addr) {
+ APPL_TRACE_DEBUG("%s: peer %s id:%d policy:0x%x", __func__,
+ peer_addr.ToString().c_str(), id, policy);
if (bta_sys_cb.p_policy_cb) {
- bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_SET, id, policy, &peer_addr);
+ bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_SET, id, policy, peer_addr);
}
}
@@ -383,8 +387,10 @@
******************************************************************************/
void bta_sys_clear_policy(uint8_t id, uint8_t policy,
const RawAddress& peer_addr) {
+ APPL_TRACE_DEBUG("%s: peer %s id:%d policy:0x%x", __func__,
+ peer_addr.ToString().c_str(), id, policy);
if (bta_sys_cb.p_policy_cb) {
- bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_CLR, id, policy, &peer_addr);
+ bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_CLR, id, policy, peer_addr);
}
}
@@ -399,8 +405,10 @@
*
******************************************************************************/
void bta_sys_set_default_policy(uint8_t id, uint8_t policy) {
+ APPL_TRACE_DEBUG("%s: id:%d policy:0x%x", __func__, id, policy);
if (bta_sys_cb.p_policy_cb) {
- bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_SET, id, policy, NULL);
+ bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_SET, id, policy,
+ RawAddress::kEmpty);
}
}
@@ -415,8 +423,10 @@
*
******************************************************************************/
void bta_sys_clear_default_policy(uint8_t id, uint8_t policy) {
+ APPL_TRACE_DEBUG("%s: id:%d policy:0x%x", __func__, id, policy);
if (bta_sys_cb.p_policy_cb) {
- bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_CLR, id, policy, NULL);
+ bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_CLR, id, policy,
+ RawAddress::kEmpty);
}
}
@@ -432,11 +442,11 @@
******************************************************************************/
void bta_sys_idle(uint8_t id, uint8_t app_id, const RawAddress& peer_addr) {
if (bta_sys_cb.prm_cb) {
- bta_sys_cb.prm_cb(BTA_SYS_CONN_IDLE, id, app_id, &peer_addr);
+ bta_sys_cb.prm_cb(BTA_SYS_CONN_IDLE, id, app_id, peer_addr);
}
if (bta_sys_cb.ppm_cb) {
- bta_sys_cb.ppm_cb(BTA_SYS_CONN_IDLE, id, app_id, &peer_addr);
+ bta_sys_cb.ppm_cb(BTA_SYS_CONN_IDLE, id, app_id, peer_addr);
}
}
@@ -452,11 +462,11 @@
******************************************************************************/
void bta_sys_busy(uint8_t id, uint8_t app_id, const RawAddress& peer_addr) {
if (bta_sys_cb.prm_cb) {
- bta_sys_cb.prm_cb(BTA_SYS_CONN_BUSY, id, app_id, &peer_addr);
+ bta_sys_cb.prm_cb(BTA_SYS_CONN_BUSY, id, app_id, peer_addr);
}
if (bta_sys_cb.ppm_cb) {
- bta_sys_cb.ppm_cb(BTA_SYS_CONN_BUSY, id, app_id, &peer_addr);
+ bta_sys_cb.ppm_cb(BTA_SYS_CONN_BUSY, id, app_id, peer_addr);
}
}
diff --git a/bta/sys/bta_sys_int.h b/bta/sys/bta_sys_int.h
index dc88e45..fcf2199 100644
--- a/bta/sys/bta_sys_int.h
+++ b/bta/sys/bta_sys_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/sys/bta_sys_main.cc b/bta/sys/bta_sys_main.cc
index 777f23a..bdedcde 100644
--- a/bta/sys/bta_sys_main.cc
+++ b/bta/sys/bta_sys_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@
#include "osi/include/thread.h"
#include "utl.h"
-#if (defined BTA_AR_INCLUDED) && (BTA_AR_INCLUDED == true)
+#if (defined BTA_AR_INCLUDED) && (BTA_AR_INCLUDED == TRUE)
#include "bta_ar_api.h"
#endif
@@ -159,8 +159,12 @@
typedef const uint8_t (*tBTA_SYS_ST_TBL)[BTA_SYS_NUM_COLS];
/* state table */
-const tBTA_SYS_ST_TBL bta_sys_st_tbl[] = {bta_sys_hw_off, bta_sys_hw_starting,
- bta_sys_hw_on, bta_sys_hw_stopping};
+const tBTA_SYS_ST_TBL bta_sys_st_tbl[] = {
+ bta_sys_hw_off, /* BTA_SYS_HW_OFF */
+ bta_sys_hw_starting, /* BTA_SYS_HW_STARTING */
+ bta_sys_hw_on, /* BTA_SYS_HW_ON */
+ bta_sys_hw_stopping /* BTA_SYS_HW_STOPPING */
+};
/*******************************************************************************
*
@@ -181,9 +185,9 @@
bta_sys_register(BTA_ID_SYS, &bta_sys_hw_reg);
/* register for BTM notifications */
- BTM_RegisterForDeviceStatusNotif((tBTM_DEV_STATUS_CB*)&bta_sys_hw_btm_cback);
+ BTM_RegisterForDeviceStatusNotif(&bta_sys_hw_btm_cback);
-#if (defined BTA_AR_INCLUDED) && (BTA_AR_INCLUDED == true)
+#if (defined BTA_AR_INCLUDED) && (BTA_AR_INCLUDED == TRUE)
bta_ar_init();
#endif
}
@@ -543,19 +547,29 @@
*
* Description Post a closure to be ran in the bta thread
*
- * Returns void
+ * Returns BT_STATUS_SUCCESS on success
*
******************************************************************************/
-void do_in_bta_thread(const tracked_objects::Location& from_here,
- const base::Closure& task) {
+bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here,
+ const base::Closure& task) {
base::MessageLoop* bta_message_loop = get_message_loop();
-
- if (!bta_message_loop || !bta_message_loop->task_runner().get()) {
+ if (!bta_message_loop) {
APPL_TRACE_ERROR("%s: MessageLooper not initialized", __func__);
- return;
+ return BT_STATUS_FAIL;
}
- bta_message_loop->task_runner()->PostTask(from_here, task);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ bta_message_loop->task_runner();
+ if (!task_runner.get()) {
+ APPL_TRACE_ERROR("%s: task runner is dead", __func__);
+ return BT_STATUS_FAIL;
+ }
+
+ if (!task_runner->PostTask(from_here, task)) {
+ APPL_TRACE_ERROR("%s: Post task to task runner failed!", __func__);
+ return BT_STATUS_FAIL;
+ }
+ return BT_STATUS_SUCCESS;
}
/*******************************************************************************
@@ -595,7 +609,7 @@
switch (module) {
case BTA_SYS_HW_BLUETOOTH:
- bta_id = BTA_ID_DM;
+ bta_id = BTA_ID_DM_SEARCH;
bta_id_max = BTA_ID_BLUETOOTH_MAX;
break;
default:
@@ -605,7 +619,7 @@
for (; bta_id <= bta_id_max; bta_id++) {
if (bta_sys_cb.reg[bta_id] != NULL) {
- if (bta_sys_cb.is_reg[bta_id] == true &&
+ if (bta_sys_cb.is_reg[bta_id] &&
bta_sys_cb.reg[bta_id]->disable != NULL) {
(*bta_sys_cb.reg[bta_id]->disable)();
}
diff --git a/bta/sys/utl.cc b/bta/sys/utl.cc
index 7feda33..92318d4 100644
--- a/bta/sys/utl.cc
+++ b/bta/sys/utl.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/test/bta_hf_client_test.cc b/bta/test/bta_hf_client_test.cc
index 01d9f5f..107a2e5 100644
--- a/bta/test/bta_hf_client_test.cc
+++ b/bta/test/bta_hf_client_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/bta/test/gatt_cache_file_test.cc b/bta/test/gatt_cache_file_test.cc
new file mode 100644
index 0000000..3ea8902
--- /dev/null
+++ b/bta/test/gatt_cache_file_test.cc
@@ -0,0 +1,49 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+#include "bta/include/bta_gatt_api.h"
+
+using bluetooth::Uuid;
+
+/* This test makes sure that v3 cache element is properly encoded into file*/
+TEST(GattCacheTest, nv_attr_to_binary_test) {
+ tBTA_GATTC_NV_ATTR attr{
+ .uuid = Uuid::FromString("1800"),
+ .s_handle = 0x0001,
+ .e_handle = 0xFFFF,
+ .attr_type = 0x01,
+ .id = 0x02,
+ .prop = 0x03,
+ .is_primary = false,
+ .incl_srvc_handle = 0x4543,
+ };
+
+ constexpr size_t len = sizeof(tBTA_GATTC_NV_ATTR);
+ uint8_t binary_form[len] = {0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B,
+ 0x34, 0xFB, 0x01, 0x00, 0xFF, 0xFF, 0x01,
+ 0x02, 0x03, 0x00, 0x43, 0x45};
+
+ // USEFUL for debugging:
+ // LOG(ERROR) << " " << base::HexEncode(binary_form, len);
+ EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
+}
diff --git a/btcore/Android.bp b/btcore/Android.bp
index 3984098..6f5b0ad 100644
--- a/btcore/Android.bp
+++ b/btcore/Android.bp
@@ -11,17 +11,14 @@
"src/module.cc",
"src/osi_module.cc",
"src/property.cc",
- "src/uuid.cc",
],
shared_libs: [
"liblog",
],
+ header_libs: ["libbluetooth_headers"],
host_supported: true,
target: {
- darwin: {
- enabled: false,
- },
- linux: {
+ linux_glibc: {
cflags: ["-D_GNU_SOURCE"],
},
},
@@ -40,7 +37,6 @@
srcs: [
"test/device_class_test.cc",
"test/property_test.cc",
- "test/uuid_test.cc",
],
shared_libs: [
"liblog",
@@ -51,9 +47,4 @@
"libosi",
],
host_supported: true,
- target: {
- darwin: {
- enabled: false,
- }
- }
}
diff --git a/btcore/AndroidTest.xml b/btcore/AndroidTest.xml
index be321c5..27cd569 100644
--- a/btcore/AndroidTest.xml
+++ b/btcore/AndroidTest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/btcore/BUILD.gn b/btcore/BUILD.gn
index 01d5ec1..01b9cf7 100644
--- a/btcore/BUILD.gn
+++ b/btcore/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@
"src/hal_util.cc",
"src/module.cc",
"src/property.cc",
- "src/uuid.cc",
"src/osi_module.cc",
]
@@ -39,7 +38,6 @@
sources = [
"test/device_class_test.cc",
"test/property_test.cc",
- "test/uuid_test.cc",
"//osi/test/AllocationTestHarness.cc",
]
diff --git a/btcore/include/device_class.h b/btcore/include/device_class.h
index 2a11400..0bfbf3f 100644
--- a/btcore/include/device_class.h
+++ b/btcore/include/device_class.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/include/device_features.h b/btcore/include/device_features.h
index bf62949..6cb2df6 100644
--- a/btcore/include/device_features.h
+++ b/btcore/include/device_features.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/include/event_mask.h b/btcore/include/event_mask.h
index cabac9e..c3efe64 100644
--- a/btcore/include/event_mask.h
+++ b/btcore/include/event_mask.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/include/hal_util.h b/btcore/include/hal_util.h
index 46e4906..5de668f 100644
--- a/btcore/include/hal_util.h
+++ b/btcore/include/hal_util.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,9 +16,8 @@
#pragma once
-struct hw_module_t;
+#include <hardware/bluetooth.h>
-// Loads the Bluetooth library. If OS_GENERIC is defined, this function looks
-// explicitly for libbluetooth.default.so and loads it. On Android, this calls
-// the hw_get_module routine with the Bluetooth stack module id.
-int hal_util_load_bt_library(const struct hw_module_t** module);
+// Loads the Bluetooth library. This function looks explicitly for
+// libbluetooth.so and loads it.
+int hal_util_load_bt_library(const bt_interface_t** interface);
diff --git a/btcore/include/iac.h b/btcore/include/iac.h
index 6272b0a..39c830e 100644
--- a/btcore/include/iac.h
+++ b/btcore/include/iac.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/include/module.h b/btcore/include/module.h
index 1b29fbb..949d147 100644
--- a/btcore/include/module.h
+++ b/btcore/include/module.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/include/osi_module.h b/btcore/include/osi_module.h
index 964a3fa..d0a8039 100644
--- a/btcore/include/osi_module.h
+++ b/btcore/include/osi_module.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/include/property.h b/btcore/include/property.h
index 40e2f2a..b11cf7f 100644
--- a/btcore/include/property.h
+++ b/btcore/include/property.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
#pragma once
+#include <bluetooth/uuid.h>
#include <hardware/bluetooth.h>
#include <stdint.h>
#include <stdlib.h>
@@ -48,7 +49,7 @@
bt_property_t* property_new_name(const char* name);
bt_property_t* property_new_rssi(const int8_t rssi);
bt_property_t* property_new_scan_mode(bt_scan_mode_t scan_mode);
-bt_property_t* property_new_uuids(const bt_uuid_t* uuid, size_t count);
+bt_property_t* property_new_uuids(const bluetooth::Uuid* uuid, size_t count);
// Property resource frees both property and value.
void property_free(bt_property_t* property);
@@ -76,5 +77,5 @@
const bt_bdname_t* property_as_name(const bt_property_t* property);
int8_t property_as_rssi(const bt_property_t* property);
bt_scan_mode_t property_as_scan_mode(const bt_property_t* property);
-const bt_uuid_t* property_as_uuids(const bt_property_t* property,
- size_t* count);
+const bluetooth::Uuid* property_as_uuids(const bt_property_t* property,
+ size_t* count);
diff --git a/btcore/include/uuid.h b/btcore/include/uuid.h
deleted file mode 100644
index 6114ab3..0000000
--- a/btcore/include/uuid.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2014 Google, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <hardware/bluetooth.h>
-#include <stdbool.h>
-
-typedef struct uuid_string_t uuid_string_t;
-
-// Creates uuid string structure to hold a well formed UUID
-// string. Must release resources with |uuid_string_free|.
-// Returns NULL if no memory.
-uuid_string_t* uuid_string_new(void);
-
-// Frees a uuid string structure created from |uuid_string_new|.
-// |uuid_string| may be NULL.
-void uuid_string_free(uuid_string_t* uuid_string);
-
-// Returns a string pointer to the well formed UUID string
-// entry. |uuid_string| must not be NULL.
-const char* uuid_string_data(const uuid_string_t* uuid_string);
-
-// Creates uuid structure from a well formed UUID string
-// |uuid_string|. The caller takes ownership of the uuid
-// structure and must release resources with |uuid_free|.
-// |uuid_string| must not be NULL.
-//
-// Returns NULL if |uuid_string| is malformed or no memory.
-//
-// A well formed UUID string is structured like this:
-// "00112233-4455-6677-8899-aabbccddeeff"
-bt_uuid_t* uuid_new(const char* uuid_string);
-
-// Frees a uuid structure created from |uuid_new| and friends.
-// |uuid| may be NULL.
-void uuid_free(bt_uuid_t* uuid);
-
-// Returns true if the UUID is all zeros, false otherwise.
-// |uuid| may not be NULL.
-bool uuid_is_empty(const bt_uuid_t* uuid);
-
-// Returns true if the two UUIDs are equal, false otherwise.
-// |first| and |second| may not be NULL.
-bool uuid_is_equal(const bt_uuid_t* first, const bt_uuid_t* second);
-
-// Copies uuid |src| into |dest| and returns a pointer to |dest|.
-// |src| and |dest| must not be NULL.
-bt_uuid_t* uuid_copy(bt_uuid_t* dest, const bt_uuid_t* src);
-
-// Converts contents of |uuid| to a well formed UUID string
-// |uuid_string| using numbers and lower case letter. |uuid|
-// and |uuid_string| must not be NULL.
-void uuid_to_string(const bt_uuid_t* uuid, uuid_string_t* uuid_string);
-
-// Converts contents of |uuid| to a short uuid if possible. Returns
-// true if conversion is possible, false otherwise.
-// |uuid|, |uuid16| and |uuid32| must not be NULL.
-bool uuid_128_to_16(const bt_uuid_t* uuid, uint16_t* uuid16);
-bool uuid_128_to_32(const bt_uuid_t* uuid, uint32_t* uuid32);
diff --git a/btcore/include/version.h b/btcore/include/version.h
index a0696ad..d7787c7 100644
--- a/btcore/include/version.h
+++ b/btcore/include/version.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/src/device_class.cc b/btcore/src/device_class.cc
index d421b6d..911eeee 100644
--- a/btcore/src/device_class.cc
+++ b/btcore/src/device_class.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@
#include <string.h>
#include "btcore/include/device_class.h"
-#include "osi/include/osi.h"
typedef struct _bt_device_class_t {
uint32_t unused : 2; // LSBs
@@ -35,7 +34,9 @@
// Ensure the internal device class implementation and public one
// have equal size.
-COMPILE_ASSERT(sizeof(_bt_device_class_t) == sizeof(bt_device_class_t));
+static_assert(sizeof(_bt_device_class_t) == sizeof(bt_device_class_t),
+ "Internal and external device class implementation should have "
+ "the same size");
// [Major Service Classes]
// (https://www.bluetooth.org/en-us/specification/assigned-numbers/baseband)
diff --git a/btcore/src/hal_util.cc b/btcore/src/hal_util.cc
index 21be613..d043348 100644
--- a/btcore/src/hal_util.cc
+++ b/btcore/src/hal_util.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,8 +16,9 @@
#define LOG_TAG "hal_util"
+#include <base/logging.h>
+#include <base/strings/stringprintf.h>
#include <hardware/bluetooth.h>
-#include <hardware/hardware.h>
#include <dlfcn.h>
#include <errno.h>
@@ -26,66 +27,41 @@
#include "btcore/include/hal_util.h"
#include "osi/include/log.h"
-#if defined(OS_GENERIC)
+using base::StringPrintf;
-// TODO(armansito): All logging macros should include __func__ by default (see
-// Bug: 22671731)
-#define HULOGERR(fmt, args...) \
- LOG_ERROR(LOG_TAG, "[%s] failed to load the Bluetooth library: " fmt, \
- __func__, ##args)
+#define BLUETOOTH_LIBRARY_NAME "libbluetooth.so"
-// TODO(armansito): It might be better to pass the library name in a more
-// generic manner as opposed to hard-coding it here.
-static const char kBluetoothLibraryName[] = "libbluetooth.default.so";
-
-static int load_bt_library(const struct hw_module_t** module) {
- const char* id = BT_STACK_MODULE_ID;
- const char* sym = HAL_MODULE_INFO_SYM_AS_STR;
- struct hw_module_t* hmi = nullptr;
+int hal_util_load_bt_library(const bt_interface_t** interface) {
+ const char* sym = BLUETOOTH_INTERFACE_STRING;
+ bt_interface_t* itf = nullptr;
// Always try to load the default Bluetooth stack on GN builds.
- void* handle = dlopen(kBluetoothLibraryName, RTLD_NOW);
+ void* handle = dlopen(BLUETOOTH_LIBRARY_NAME, RTLD_NOW);
if (!handle) {
- char const* err_str = dlerror();
- HULOGERR("%s", err_str ? err_str : "error unknown");
+ const char* err_str = dlerror();
+ LOG(ERROR) << __func__ << ": failed to load bluetooth library, error="
+ << (err_str ? err_str : "error unknown");
goto error;
}
- // Get the address of the struct hal_module_info.
- hmi = (struct hw_module_t*)dlsym(handle, sym);
- if (!hmi) {
- HULOGERR("%s", sym);
+ // Get the address of the bt_interface_t.
+ itf = (bt_interface_t*)dlsym(handle, sym);
+ if (!itf) {
+ LOG(ERROR) << __func__ << ": failed to load symbol from Bluetooth library "
+ << sym;
goto error;
}
- // Check that the id matches.
- if (strcmp(id, hmi->id) != 0) {
- HULOGERR("id=%s does not match HAL module ID: %s", id, hmi->id);
- goto error;
- }
-
- hmi->dso = handle;
-
// Success.
- LOG_INFO(LOG_TAG, "[%s] loaded HAL id=%s path=%s hmi=%p handle=%p", __func__,
- id, kBluetoothLibraryName, hmi, handle);
+ LOG(INFO) << __func__ << " loaded HAL path=" << BLUETOOTH_LIBRARY_NAME
+ << " btinterface=" << itf << " handle=" << handle;
- *module = hmi;
+ *interface = itf;
return 0;
error:
- *module = NULL;
+ *interface = NULL;
if (handle) dlclose(handle);
return -EINVAL;
}
-
-#endif // defined(OS_GENERIC)
-
-int hal_util_load_bt_library(const struct hw_module_t** module) {
-#if defined(OS_GENERIC)
- return load_bt_library(module);
-#else // !defined(OS_GENERIC)
- return hw_get_module(BT_STACK_MODULE_ID, module);
-#endif // defined(OS_GENERIC)
-}
diff --git a/btcore/src/module.cc b/btcore/src/module.cc
index 1a0674a..88d4f80 100644
--- a/btcore/src/module.cc
+++ b/btcore/src/module.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/src/osi_module.cc b/btcore/src/osi_module.cc
index 1938d3f..9481c87 100644
--- a/btcore/src/osi_module.cc
+++ b/btcore/src/osi_module.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/src/property.cc b/btcore/src/property.cc
index 1e314f0..a3ce6f7 100644
--- a/btcore/src/property.cc
+++ b/btcore/src/property.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,10 @@
#include <base/logging.h>
#include <string.h>
#include "btcore/include/device_class.h"
-#include "btcore/include/uuid.h"
#include "osi/include/allocator.h"
+#include "osi/include/compat.h"
+
+using bluetooth::Uuid;
static bt_property_t* property_new_(void* val, size_t len,
bt_property_type_t type);
@@ -110,10 +112,9 @@
BT_PROPERTY_ADAPTER_SCAN_MODE);
}
-bt_property_t* property_new_uuids(const bt_uuid_t* uuid, size_t count) {
+bt_property_t* property_new_uuids(const Uuid* uuid, size_t count) {
CHECK(uuid != NULL);
- return property_new_((void*)uuid, sizeof(bt_uuid_t) * count,
- BT_PROPERTY_UUIDS);
+ return property_new_((void*)uuid, sizeof(Uuid) * count, BT_PROPERTY_UUIDS);
}
void property_free(bt_property_t* property) {
@@ -207,11 +208,10 @@
return *(const bt_scan_mode_t*)property->val;
}
-const bt_uuid_t* property_as_uuids(const bt_property_t* property,
- size_t* count) {
+const Uuid* property_as_uuids(const bt_property_t* property, size_t* count) {
CHECK(property_is_uuids(property));
- *count = sizeof(bt_uuid_t) / property->len;
- return (const bt_uuid_t*)property->val;
+ *count = sizeof(Uuid) / property->len;
+ return (const Uuid*)property->val;
}
static bt_property_t* property_new_(void* val, size_t len,
@@ -219,8 +219,12 @@
bt_property_t* property =
static_cast<bt_property_t*>(osi_calloc(sizeof(bt_property_t)));
- property->val = osi_malloc(len);
- memcpy(property->val, val, len);
+ property->val = osi_calloc(len + 1);
+ if (type == BT_PROPERTY_BDNAME) {
+ strlcpy((char*)property->val, (const char*)val, len);
+ } else {
+ memcpy(property->val, val, len);
+ }
property->type = type;
property->len = len;
diff --git a/btcore/src/uuid.cc b/btcore/src/uuid.cc
deleted file mode 100644
index 9985fe6..0000000
--- a/btcore/src/uuid.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2014 Google, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-#include <base/logging.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "btcore/include/uuid.h"
-#include "osi/include/allocator.h"
-
-static const size_t UUID_WELL_FORMED_STRING_LEN = 36;
-static const size_t UUID_WELL_FORMED_STRING_LEN_WITH_NULL = 36 + 1;
-
-typedef struct uuid_string_t { char string[0]; } uuid_string_t;
-
-static const bt_uuid_t empty_uuid = {{0}};
-
-// The base UUID is used for calculating 128-bit UUIDs from 16 and
-// 32 bit UUIDs as described in the SDP specification.
-static const bt_uuid_t base_uuid = {{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5f, 0x9b, 0x34, 0xfb,
-}};
-
-static bool uuid_is_base(const bt_uuid_t* uuid);
-
-uuid_string_t* uuid_string_new(void) {
- return static_cast<uuid_string_t*>(
- osi_calloc(UUID_WELL_FORMED_STRING_LEN_WITH_NULL));
-}
-
-void uuid_string_free(uuid_string_t* uuid_string) { osi_free(uuid_string); }
-
-const char* uuid_string_data(const uuid_string_t* uuid_string) {
- CHECK(uuid_string != NULL);
- return (const char*)uuid_string->string;
-}
-
-bt_uuid_t* uuid_new(const char* uuid_string) {
- CHECK(uuid_string != NULL);
-
- if (strlen(uuid_string) < UUID_WELL_FORMED_STRING_LEN) return NULL;
- if (uuid_string[8] != '-' || uuid_string[13] != '-' ||
- uuid_string[18] != '-' || uuid_string[23] != '-')
- return NULL;
-
- bt_uuid_t* uuid = static_cast<bt_uuid_t*>(osi_calloc(sizeof(bt_uuid_t)));
-
- const char* s = uuid_string;
- for (size_t i = 0; i < sizeof(bt_uuid_t); ++i, s += 2) {
- char buf[3] = {0};
- buf[0] = s[0];
- buf[1] = s[1];
- uuid->uu[i] = strtoul(buf, NULL, 16);
- // Adjust by skipping the dashes
- switch (i) {
- case 3:
- case 5:
- case 7:
- case 9:
- s++;
- break;
- }
- }
- return uuid;
-}
-
-void uuid_free(bt_uuid_t* uuid) { osi_free(uuid); }
-
-bool uuid_is_empty(const bt_uuid_t* uuid) {
- return !uuid || !memcmp(uuid, &empty_uuid, sizeof(bt_uuid_t));
-}
-
-bool uuid_is_equal(const bt_uuid_t* first, const bt_uuid_t* second) {
- CHECK(first != NULL);
- CHECK(second != NULL);
- return !memcmp(first, second, sizeof(bt_uuid_t));
-}
-
-bt_uuid_t* uuid_copy(bt_uuid_t* dest, const bt_uuid_t* src) {
- CHECK(dest != NULL);
- CHECK(src != NULL);
- return (bt_uuid_t*)memcpy(dest, src, sizeof(bt_uuid_t));
-}
-
-bool uuid_128_to_16(const bt_uuid_t* uuid, uint16_t* uuid16) {
- CHECK(uuid != NULL);
- CHECK(uuid16 != NULL);
-
- if (!uuid_is_base(uuid)) return false;
-
- *uuid16 = (uuid->uu[2] << 8) + uuid->uu[3];
- return true;
-}
-
-bool uuid_128_to_32(const bt_uuid_t* uuid, uint32_t* uuid32) {
- CHECK(uuid != NULL);
- CHECK(uuid32 != NULL);
-
- if (!uuid_is_base(uuid)) return false;
-
- *uuid32 = (uuid->uu[0] << 24) + (uuid->uu[1] << 16) + (uuid->uu[2] << 8) +
- uuid->uu[3];
- return true;
-}
-
-void uuid_to_string(const bt_uuid_t* uuid, uuid_string_t* uuid_string) {
- CHECK(uuid != NULL);
- CHECK(uuid_string != NULL);
-
- char* string = uuid_string->string;
- char* end = string + UUID_WELL_FORMED_STRING_LEN_WITH_NULL;
-
- // XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX
- for (int i = 0; i < 4; i++) {
- string += snprintf(string, end - string, "%02x", uuid->uu[i]);
- }
- *string = '-';
- ++string;
- for (int i = 4; i < 6; i++) {
- string += snprintf(string, end - string, "%02x", uuid->uu[i]);
- }
- *string = '-';
- ++string;
- for (int i = 6; i < 8; i++) {
- string += snprintf(string, end - string, "%02x", uuid->uu[i]);
- }
- *string = '-';
- ++string;
- for (int i = 8; i < 10; i++) {
- string += snprintf(string, end - string, "%02x", uuid->uu[i]);
- }
- *string = '-';
- ++string;
- for (int i = 10; i < 16; i++) {
- string += snprintf(string, end - string, "%02x", uuid->uu[i]);
- }
-}
-
-static bool uuid_is_base(const bt_uuid_t* uuid) {
- if (!uuid) return false;
-
- for (int i = 4; i < 16; i++) {
- if (uuid->uu[i] != base_uuid.uu[i]) return false;
- }
- return true;
-}
diff --git a/btcore/test/device_class_test.cc b/btcore/test/device_class_test.cc
index 434f9ca..5ce1523 100644
--- a/btcore/test/device_class_test.cc
+++ b/btcore/test/device_class_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btcore/test/property_test.cc b/btcore/test/property_test.cc
index e87c186..72eac76 100644
--- a/btcore/test/property_test.cc
+++ b/btcore/test/property_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
#include "btcore/include/property.h"
+using bluetooth::Uuid;
+
class PropertyTest : public AllocationTestHarness {};
TEST_F(PropertyTest, addr) {
@@ -131,38 +133,38 @@
}
TEST_F(PropertyTest, uuids) {
- bt_uuid_t uuid0 = {{
+ Uuid uuid0 = Uuid::From128BitBE({{
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb,
0xcc, 0xdd, 0xee, 0xff,
- }};
+ }});
bt_property_t* property = property_new_uuids(&uuid0, 1);
- EXPECT_EQ(0, strcmp((const char*)uuid0.uu, (char*)property->val));
+ EXPECT_EQ(0, memcmp(uuid0.To128BitBE().data(), property->val, sizeof(Uuid)));
EXPECT_EQ(BT_PROPERTY_UUIDS, property->type);
- EXPECT_EQ((int)sizeof(bt_uuid_t), property->len);
+ EXPECT_EQ((int)sizeof(Uuid), property->len);
size_t uuid_cnt1;
- const bt_uuid_t* uuid1 = property_as_uuids(property, &uuid_cnt1);
- EXPECT_EQ(0, memcmp(uuid1->uu, uuid1->uu, sizeof(bt_uuid_t)));
+ const Uuid* uuid1 = property_as_uuids(property, &uuid_cnt1);
+ EXPECT_EQ(uuid0, *uuid1);
property_free(property);
}
TEST_F(PropertyTest, copy) {
{
- bt_uuid_t uuids[] = {
- {{
+ Uuid uuids[] = {
+ Uuid::From128BitBE({{
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa,
0xbb, 0xcc, 0xdd, 0xee, 0xff,
- }},
- {{
+ }}),
+ Uuid::From128BitBE({{
0xf0, 0xe1, 0xd2, 0xc3, 0xf4, 0xe5, 0xd6, 0xc7, 0xf8, 0xe9, 0xda,
0xcb, 0xfc, 0xed, 0xde, 0xcf,
- }},
+ }}),
};
bt_property_t* property0 =
- property_new_uuids(uuids, sizeof(bt_uuid_t) / sizeof(uuids));
+ property_new_uuids(uuids, sizeof(uuids) / sizeof(Uuid));
bt_property_t property1;
property_copy(&property1, property0);
diff --git a/btcore/test/uuid_test.cc b/btcore/test/uuid_test.cc
deleted file mode 100644
index e9a40ed..0000000
--- a/btcore/test/uuid_test.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2014 Google, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-#include <gtest/gtest.h>
-#include "osi/test/AllocationTestHarness.h"
-
-#include "btcore/include/uuid.h"
-
-static const char* UUID_EMPTY = "00000000-0000-0000-0000-000000000000";
-static const char* UUID_ONES = "11111111-1111-1111-1111-111111111111";
-static const char* UUID_SEQUENTIAL = "01234567-89ab-cdef-ABCD-EF0123456789";
-static const char* UUID_BASE = "00000000-0000-1000-8000-00805f9b34fb";
-
-class UuidTest : public AllocationTestHarness {
- protected:
- virtual void SetUp() {}
-
- virtual void TearDown() {}
-};
-
-TEST_F(UuidTest, new_from_string) {
- bt_uuid_t* uuid;
-
- uuid = uuid_new("incorrect length");
- EXPECT_EQ(NULL, uuid);
-
- uuid = uuid_new("correct length but missing dashes --");
- EXPECT_EQ(NULL, uuid);
-
- uuid = uuid_new(UUID_ONES);
- ASSERT_TRUE(uuid != NULL);
- for (int i = 0; i < 16; i++) {
- EXPECT_EQ(0x11, uuid->uu[i]);
- }
- uuid_free(uuid);
-
- uuid = uuid_new(UUID_SEQUENTIAL);
- EXPECT_EQ(0x01, uuid->uu[0]);
- EXPECT_EQ(0x23, uuid->uu[1]);
- EXPECT_EQ(0x45, uuid->uu[2]);
- EXPECT_EQ(0x67, uuid->uu[3]);
- EXPECT_EQ(0x89, uuid->uu[4]);
- EXPECT_EQ(0xAB, uuid->uu[5]);
- EXPECT_EQ(0xCD, uuid->uu[6]);
- EXPECT_EQ(0xEF, uuid->uu[7]);
- EXPECT_EQ(0xab, uuid->uu[8]);
- EXPECT_EQ(0xcd, uuid->uu[9]);
- EXPECT_EQ(0xef, uuid->uu[10]);
- EXPECT_EQ(0x01, uuid->uu[11]);
- EXPECT_EQ(0x23, uuid->uu[12]);
- EXPECT_EQ(0x45, uuid->uu[13]);
- EXPECT_EQ(0x67, uuid->uu[14]);
- EXPECT_EQ(0x89, uuid->uu[15]);
- uuid_free(uuid);
-
- uuid = uuid_new(UUID_BASE);
- EXPECT_EQ(0x00, uuid->uu[0]);
- EXPECT_EQ(0x00, uuid->uu[1]);
- EXPECT_EQ(0x00, uuid->uu[2]);
- EXPECT_EQ(0x00, uuid->uu[3]);
- EXPECT_EQ(0x00, uuid->uu[4]);
- EXPECT_EQ(0x00, uuid->uu[5]);
- EXPECT_EQ(0x10, uuid->uu[6]);
- EXPECT_EQ(0x00, uuid->uu[7]);
- EXPECT_EQ(0x80, uuid->uu[8]);
- EXPECT_EQ(0x00, uuid->uu[9]);
- EXPECT_EQ(0x00, uuid->uu[10]);
- EXPECT_EQ(0x80, uuid->uu[11]);
- EXPECT_EQ(0x5f, uuid->uu[12]);
- EXPECT_EQ(0x9b, uuid->uu[13]);
- EXPECT_EQ(0x34, uuid->uu[14]);
- EXPECT_EQ(0xfb, uuid->uu[15]);
- uuid_free(uuid);
-}
-
-TEST_F(UuidTest, uuid_is_empty) {
- bt_uuid_t* uuid = NULL;
-
- uuid = uuid_new(UUID_EMPTY);
- ASSERT_TRUE(uuid != NULL);
- EXPECT_TRUE(uuid_is_empty(uuid));
- uuid_free(uuid);
-
- uuid = uuid_new(UUID_BASE);
- ASSERT_TRUE(uuid != NULL);
- EXPECT_FALSE(uuid_is_empty(uuid));
- uuid_free(uuid);
-}
-
-TEST_F(UuidTest, uuid_128_to_16) {
- bt_uuid_t* uuid = NULL;
- uint16_t uuid16 = 0xffff;
-
- uuid = uuid_new(UUID_ONES);
- EXPECT_FALSE(uuid_128_to_16(uuid, &uuid16));
- uuid_free(uuid);
- EXPECT_EQ((uint16_t)0xffff, uuid16);
-
- uuid = uuid_new(UUID_BASE);
- EXPECT_TRUE(uuid_128_to_16(uuid, &uuid16));
- uuid_free(uuid);
- EXPECT_NE((uint16_t)0xffff, uuid16);
- EXPECT_EQ((uint16_t)0, uuid16);
-}
-
-TEST_F(UuidTest, uuid_128_to_32) {
- bt_uuid_t* uuid = NULL;
- uint32_t uuid32 = 0xffffffff;
-
- uuid = uuid_new(UUID_ONES);
- EXPECT_FALSE(uuid_128_to_32(uuid, &uuid32));
- uuid_free(uuid);
- EXPECT_EQ((uint32_t)0xffffffff, uuid32);
-
- uuid = uuid_new(UUID_BASE);
- EXPECT_TRUE(uuid_128_to_32(uuid, &uuid32));
- uuid_free(uuid);
- EXPECT_NE((uint32_t)0xffffffff, uuid32);
- EXPECT_EQ((uint32_t)0, uuid32);
-}
-
-TEST_F(UuidTest, uuid_to_string) {
- bt_uuid_t* uuid = NULL;
-
- uuid_string_t* uuid_string = uuid_string_new();
- EXPECT_TRUE(uuid_string != NULL);
-
- uuid = uuid_new(UUID_BASE);
- EXPECT_TRUE(uuid != NULL);
- uuid_to_string(uuid, uuid_string);
- uuid_free(uuid);
-
- EXPECT_TRUE(!strcmp(UUID_BASE, uuid_string_data(uuid_string)));
-
- uuid = uuid_new(UUID_SEQUENTIAL);
- EXPECT_TRUE(uuid != NULL);
-
- uuid_to_string(uuid, uuid_string);
- uuid_free(uuid);
-
- char lower_case_buf[36 + 1];
- for (int i = 0; i < 36 + 1; i++) {
- lower_case_buf[i] = tolower(UUID_SEQUENTIAL[i]);
- }
- EXPECT_TRUE(!strcmp(lower_case_buf, uuid_string_data(uuid_string)));
- uuid_string_free(uuid_string);
-}
diff --git a/btif/Android.bp b/btif/Android.bp
index c5ff0765..4b2dc30 100644
--- a/btif/Android.bp
+++ b/btif/Android.bp
@@ -7,13 +7,14 @@
"system/bt/bta/dm",
"system/bt/btcore/include",
"system/bt/device/include",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/stack/include",
"system/bt/stack/l2cap",
"system/bt/stack/a2dp",
"system/bt/stack/btm",
"system/bt/stack/avdt",
"system/bt/udrv/include",
+ "system/bt/btif/avrcp",
"system/bt/btif/include",
"system/bt/btif/co",
"system/bt/hci/include",
@@ -21,6 +22,8 @@
"system/bt/embdrv/sbc/encoder/include",
"system/bt/embdrv/sbc/decoder/include",
"system/bt/utils/include",
+ "system/bt/include",
+ "system/libhwbinder/include",
]
// libbtif static library for target
@@ -30,10 +33,20 @@
defaults: ["fluoride_defaults"],
include_dirs: btifCommonIncludes,
srcs: [
+ // AVRCP Target Service
+ "avrcp/avrcp_service.cc",
+ // Callouts
+ "co/bta_dm_co.cc",
+ "co/bta_av_co.cc",
+ "co/bta_hh_co.cc",
+ "co/bta_hl_co.cc",
+ "co/bta_pan_co.cc",
+ "co/bta_gatts_co.cc",
// HAL layer
"src/bluetooth.cc",
// BTIF implementation
"src/btif_a2dp.cc",
+ "src/btif_a2dp_audio_interface.cc",
"src/btif_a2dp_control.cc",
"src/btif_a2dp_sink.cc",
"src/btif_a2dp_source.cc",
@@ -53,6 +66,7 @@
"src/btif_gatt_server.cc",
"src/btif_gatt_test.cc",
"src/btif_gatt_util.cc",
+ "src/btif_hearing_aid.cc",
"src/btif_hf.cc",
"src/btif_hf_client.cc",
"src/btif_hh.cc",
@@ -64,7 +78,6 @@
"src/btif_rc.cc",
"src/btif_sdp.cc",
"src/btif_sdp_server.cc",
- "src/btif_sm.cc",
"src/btif_sock.cc",
"src/btif_sock_rfc.cc",
"src/btif_sock_l2cap.cc",
@@ -76,14 +89,6 @@
"src/btif_uid.cc",
"src/btif_util.cc",
"src/stack_manager.cc",
- // Callouts
- "co/bta_ag_co.cc",
- "co/bta_dm_co.cc",
- "co/bta_av_co.cc",
- "co/bta_hh_co.cc",
- "co/bta_hl_co.cc",
- "co/bta_pan_co.cc",
- "co/bta_gatts_co.cc",
],
shared_libs: [
"libaudioclient",
@@ -91,9 +96,16 @@
"liblog",
"libz",
"libtinyxml2",
+ "android.hardware.bluetooth.a2dp@1.0",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "libutils",
],
whole_static_libs: [
+ "avrcp-target-service",
"libaudio-a2dp-hw-utils",
+ "lib-bt-packets",
],
cflags: ["-DBUILDCFG"],
@@ -106,17 +118,34 @@
defaults: ["fluoride_defaults"],
include_dirs: btifCommonIncludes,
srcs: ["test/btif_storage_test.cc"],
+ header_libs: ["libbluetooth_headers"],
shared_libs: [
+ "libaudioclient",
+ "android.hardware.bluetooth.a2dp@1.0",
+ "libhidlbase",
"liblog",
- "libhardware",
+ "libprotobuf-cpp-lite",
"libcutils",
+ "libutils",
],
static_libs: [
+ "libbt-bta",
"libbtcore",
- "libbtif",
"libbt-stack",
+ "libbt-sbc-encoder",
+ "libbt-utils",
+ "libFraunhoferAAC",
+ "libg722codec",
+ "libbtdevice",
+ "libbt-hci",
+ "libudrv-uipc",
"libbluetooth-types",
"libosi",
+ "libbt-protos-lite",
+ ],
+ whole_static_libs: [
+ "libbtif",
+ "libbluetooth-for-tests",
],
cflags: ["-DBUILDCFG"],
}
@@ -131,9 +160,31 @@
"src/btif_profile_queue.cc",
"test/btif_profile_queue_test.cc"
],
+ header_libs: ["libbluetooth_headers"],
shared_libs: [
"liblog",
- "libhardware",
+ "libcutils",
+ ],
+ static_libs: [
+ "libbluetooth-types",
+ "libosi",
+ ],
+ cflags: ["-DBUILDCFG"],
+}
+
+// btif state machine unit tests for target
+// ========================================================
+cc_test {
+ name: "net_test_btif_state_machine",
+ defaults: ["fluoride_defaults"],
+ include_dirs: btifCommonIncludes,
+ host_supported: true,
+ srcs: [
+ "test/btif_state_machine_test.cc"
+ ],
+ header_libs: ["libbluetooth_headers"],
+ shared_libs: [
+ "liblog",
"libcutils",
],
static_libs: [
diff --git a/btif/BUILD.gn b/btif/BUILD.gn
index 6f29584..de50a97 100644
--- a/btif/BUILD.gn
+++ b/btif/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@
"src/btif_gatt_server.cc",
"src/btif_gatt_test.cc",
"src/btif_gatt_util.cc",
+ "src/btif_hearing_aid.cc",
"src/btif_hf.cc",
"src/btif_hf_client.cc",
"src/btif_hh.cc",
@@ -50,7 +51,6 @@
"src/btif_rc.cc",
"src/btif_sdp.cc",
"src/btif_sdp_server.cc",
- "src/btif_sm.cc",
"src/btif_sock.cc",
"src/btif_sock_l2cap.cc",
"src/btif_sock_rfc.cc",
@@ -90,7 +90,7 @@
"//stack/btm",
"//stack/include",
"//third_party/tinyxml2",
- "//include",
+ "//internal_include",
"//udrv/include",
"//utils/include",
"//vnd/include",
diff --git a/btif/avrcp/avrcp_service.cc b/btif/avrcp/avrcp_service.cc
new file mode 100644
index 0000000..8c22365
--- /dev/null
+++ b/btif/avrcp/avrcp_service.cc
@@ -0,0 +1,465 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "avrcp_service.h"
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <base/task/cancelable_task_tracker.h>
+#include <base/threading/thread.h>
+#include <mutex>
+#include <sstream>
+
+#include "bta_closure_api.h"
+#include "btif_av.h"
+#include "btif_common.h"
+#include "device.h"
+
+namespace bluetooth {
+namespace avrcp {
+// Static variables and interface definitions
+AvrcpService* AvrcpService::instance_ = nullptr;
+AvrcpService::ServiceInterfaceImpl* AvrcpService::service_interface_ = nullptr;
+
+std::mutex jni_mutex_;
+base::MessageLoop* jni_message_loop_ = nullptr;
+base::CancelableTaskTracker task_tracker_;
+
+void do_in_avrcp_jni(const base::Closure& task) {
+ std::lock_guard<std::mutex> lock(jni_mutex_);
+
+ if (jni_message_loop_ == nullptr) {
+ LOG(WARNING) << __func__ << ": jni_message_loop_ is null";
+ return;
+ }
+
+ task_tracker_.PostTask(jni_message_loop_->task_runner().get(), FROM_HERE,
+ task);
+}
+
+class A2dpInterfaceImpl : public A2dpInterface {
+ RawAddress active_peer() override { return btif_av_source_active_peer(); }
+} a2dp_interface_;
+
+class AvrcpInterfaceImpl : public AvrcpInterface {
+ public:
+ uint16_t AddRecord(uint16_t service_uuid, const char* p_service_name,
+ const char* p_provider_name, uint16_t categories,
+ uint32_t sdp_handle, bool browse_supported,
+ uint16_t profile_version) override {
+ return AVRC_AddRecord(service_uuid, p_service_name, p_provider_name,
+ categories, sdp_handle, browse_supported,
+ profile_version);
+ }
+
+ uint16_t FindService(uint16_t service_uuid, const RawAddress& bd_addr,
+ tAVRC_SDP_DB_PARAMS* p_db,
+ tAVRC_FIND_CBACK p_cback) override {
+ return AVRC_FindService(service_uuid, bd_addr, p_db, p_cback);
+ }
+
+ uint16_t Open(uint8_t* p_handle, tAVRC_CONN_CB* p_ccb,
+ const RawAddress& bd_addr) override {
+ return AVRC_Open(p_handle, p_ccb, bd_addr);
+ }
+
+ uint16_t OpenBrowse(uint8_t handle, uint8_t conn_role) override {
+ return AVRC_OpenBrowse(handle, conn_role);
+ }
+
+ uint16_t GetPeerMtu(uint8_t handle) override {
+ return AVCT_GetPeerMtu(handle);
+ }
+
+ uint16_t GetBrowseMtu(uint8_t handle) override {
+ return AVCT_GetBrowseMtu(handle);
+ }
+
+ uint16_t Close(uint8_t handle) override { return AVRC_Close(handle); }
+
+ uint16_t CloseBrowse(uint8_t handle) override {
+ return AVRC_CloseBrowse(handle);
+ }
+
+ uint16_t MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
+ BT_HDR* p_pkt) override {
+ return AVRC_MsgReq(handle, label, ctype, p_pkt);
+ }
+} avrcp_interface_;
+
+class SdpInterfaceImpl : public SdpInterface {
+ public:
+ bool InitDiscoveryDb(tSDP_DISCOVERY_DB* a, uint32_t b, uint16_t c,
+ const bluetooth::Uuid* d, uint16_t e,
+ uint16_t* f) override {
+ return SDP_InitDiscoveryDb(a, b, c, d, e, f);
+ }
+
+ bool ServiceSearchAttributeRequest(const RawAddress& a, tSDP_DISCOVERY_DB* b,
+ tSDP_DISC_CMPL_CB* c) override {
+ return SDP_ServiceSearchAttributeRequest(a, b, c);
+ }
+
+ tSDP_DISC_REC* FindServiceInDb(tSDP_DISCOVERY_DB* a, uint16_t b,
+ t_sdp_disc_rec* c) override {
+ return SDP_FindServiceInDb(a, b, c);
+ }
+
+ tSDP_DISC_ATTR* FindAttributeInRec(t_sdp_disc_rec* a, uint16_t b) override {
+ return SDP_FindAttributeInRec(a, b);
+ }
+
+ bool FindProfileVersionInRec(t_sdp_disc_rec* a, uint16_t b,
+ uint16_t* c) override {
+ return SDP_FindProfileVersionInRec(a, b, c);
+ }
+} sdp_interface_;
+
+// A wrapper class for the media callbacks that handles thread
+// switching/synchronization so the devices don't have to worry about it.
+class MediaInterfaceWrapper : public MediaInterface {
+ public:
+ MediaInterfaceWrapper(MediaInterface* cb) : wrapped_(cb){};
+
+ void SendKeyEvent(uint8_t key, KeyState state) override {
+ do_in_avrcp_jni(base::Bind(&MediaInterface::SendKeyEvent,
+ base::Unretained(wrapped_), key, state));
+ }
+
+ void GetSongInfo(SongInfoCallback info_cb) override {
+ auto cb_lambda = [](SongInfoCallback cb, SongInfo data) {
+ do_in_bta_thread(FROM_HERE, base::Bind(cb, data));
+ };
+
+ auto bound_cb = base::Bind(cb_lambda, info_cb);
+
+ do_in_avrcp_jni(base::Bind(&MediaInterface::GetSongInfo,
+ base::Unretained(wrapped_), bound_cb));
+ }
+
+ void GetPlayStatus(PlayStatusCallback status_cb) override {
+ auto cb_lambda = [](PlayStatusCallback cb, PlayStatus status) {
+ do_in_bta_thread(FROM_HERE, base::Bind(cb, status));
+ };
+
+ auto bound_cb = base::Bind(cb_lambda, status_cb);
+
+ do_in_avrcp_jni(base::Bind(&MediaInterface::GetPlayStatus,
+ base::Unretained(wrapped_), bound_cb));
+ }
+
+ void GetNowPlayingList(NowPlayingCallback now_playing_cb) override {
+ auto cb_lambda = [](NowPlayingCallback cb, std::string curr_media_id,
+ std::vector<SongInfo> song_list) {
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(cb, curr_media_id, std::move(song_list)));
+ };
+
+ auto bound_cb = base::Bind(cb_lambda, now_playing_cb);
+
+ do_in_avrcp_jni(base::Bind(&MediaInterface::GetNowPlayingList,
+ base::Unretained(wrapped_), bound_cb));
+ }
+
+ void GetMediaPlayerList(MediaListCallback list_cb) override {
+ auto cb_lambda = [](MediaListCallback cb, uint16_t curr_player,
+ std::vector<MediaPlayerInfo> player_list) {
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(cb, curr_player, std::move(player_list)));
+ };
+
+ auto bound_cb = base::Bind(cb_lambda, list_cb);
+
+ do_in_avrcp_jni(base::Bind(&MediaInterface::GetMediaPlayerList,
+ base::Unretained(wrapped_), bound_cb));
+ }
+
+ void GetFolderItems(uint16_t player_id, std::string media_id,
+ FolderItemsCallback folder_cb) override {
+ auto cb_lambda = [](FolderItemsCallback cb,
+ std::vector<ListItem> item_list) {
+ do_in_bta_thread(FROM_HERE, base::Bind(cb, std::move(item_list)));
+ };
+
+ auto bound_cb = base::Bind(cb_lambda, folder_cb);
+
+ do_in_avrcp_jni(base::Bind(&MediaInterface::GetFolderItems,
+ base::Unretained(wrapped_), player_id, media_id,
+ bound_cb));
+ }
+
+ void SetBrowsedPlayer(uint16_t player_id,
+ SetBrowsedPlayerCallback browse_cb) override {
+ auto cb_lambda = [](SetBrowsedPlayerCallback cb, bool success,
+ std::string root_id, uint32_t num_items) {
+ do_in_bta_thread(FROM_HERE, base::Bind(cb, success, root_id, num_items));
+ };
+
+ auto bound_cb = base::Bind(cb_lambda, browse_cb);
+
+ do_in_avrcp_jni(base::Bind(&MediaInterface::SetBrowsedPlayer,
+ base::Unretained(wrapped_), player_id,
+ bound_cb));
+ }
+
+ void PlayItem(uint16_t player_id, bool now_playing,
+ std::string media_id) override {
+ do_in_avrcp_jni(base::Bind(&MediaInterface::PlayItem,
+ base::Unretained(wrapped_), player_id,
+ now_playing, media_id));
+ }
+
+ void SetActiveDevice(const RawAddress& address) override {
+ do_in_avrcp_jni(base::Bind(&MediaInterface::SetActiveDevice,
+ base::Unretained(wrapped_), address));
+ }
+
+ void RegisterUpdateCallback(MediaCallbacks* callback) override {
+ wrapped_->RegisterUpdateCallback(callback);
+ }
+
+ void UnregisterUpdateCallback(MediaCallbacks* callback) override {
+ wrapped_->UnregisterUpdateCallback(callback);
+ }
+
+ private:
+ MediaInterface* wrapped_;
+};
+
+// A wrapper class for the media callbacks that handles thread
+// switching/synchronization so the devices don't have to worry about it.
+class VolumeInterfaceWrapper : public VolumeInterface {
+ public:
+ VolumeInterfaceWrapper(VolumeInterface* interface) : wrapped_(interface){};
+
+ void DeviceConnected(const RawAddress& bdaddr) override {
+ do_in_avrcp_jni(
+ base::Bind(static_cast<void (VolumeInterface::*)(const RawAddress&)>(
+ &VolumeInterface::DeviceConnected),
+ base::Unretained(wrapped_), bdaddr));
+ }
+
+ void DeviceConnected(const RawAddress& bdaddr, VolumeChangedCb cb) override {
+ auto cb_lambda = [](VolumeChangedCb cb, int8_t volume) {
+ do_in_bta_thread(FROM_HERE, base::Bind(cb, volume));
+ };
+
+ auto bound_cb = base::Bind(cb_lambda, cb);
+
+ do_in_avrcp_jni(base::Bind(static_cast<void (VolumeInterface::*)(
+ const RawAddress&, VolumeChangedCb)>(
+ &VolumeInterface::DeviceConnected),
+ base::Unretained(wrapped_), bdaddr, bound_cb));
+ }
+
+ void DeviceDisconnected(const RawAddress& bdaddr) override {
+ do_in_avrcp_jni(base::Bind(&VolumeInterface::DeviceDisconnected,
+ base::Unretained(wrapped_), bdaddr));
+ }
+
+ void SetVolume(int8_t volume) override {
+ do_in_avrcp_jni(base::Bind(&VolumeInterface::SetVolume,
+ base::Unretained(wrapped_), volume));
+ }
+
+ private:
+ VolumeInterface* wrapped_;
+};
+
+void AvrcpService::Init(MediaInterface* media_interface,
+ VolumeInterface* volume_interface) {
+ LOG(INFO) << "AVRCP Target Service started";
+
+ // TODO (apanicke): Add a function that sets up the SDP records once we
+ // remove the AVRCP SDP setup in AVDTP (bta_av_main.cc)
+
+ media_interface_ = new MediaInterfaceWrapper(media_interface);
+ media_interface->RegisterUpdateCallback(instance_);
+
+ VolumeInterfaceWrapper* wrapped_volume_interface = nullptr;
+ if (volume_interface != nullptr) {
+ wrapped_volume_interface = new VolumeInterfaceWrapper(volume_interface);
+ }
+
+ volume_interface_ = wrapped_volume_interface;
+
+ ConnectionHandler::Initialize(
+ base::Bind(&AvrcpService::DeviceCallback, base::Unretained(instance_)),
+ &avrcp_interface_, &sdp_interface_, wrapped_volume_interface);
+ connection_handler_ = ConnectionHandler::Get();
+}
+
+void AvrcpService::Cleanup() {
+ LOG(INFO) << "AVRCP Target Service stopped";
+
+ connection_handler_->CleanUp();
+ connection_handler_ = nullptr;
+ if (volume_interface_ != nullptr) {
+ delete volume_interface_;
+ }
+ delete media_interface_;
+}
+
+AvrcpService* AvrcpService::Get() {
+ CHECK(instance_);
+ return instance_;
+}
+
+ServiceInterface* AvrcpService::GetServiceInterface() {
+ if (service_interface_ == nullptr) {
+ service_interface_ = new ServiceInterfaceImpl();
+ }
+
+ return service_interface_;
+}
+
+void AvrcpService::ConnectDevice(const RawAddress& bdaddr) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString();
+
+ connection_handler_->ConnectDevice(bdaddr);
+}
+
+void AvrcpService::DisconnectDevice(const RawAddress& bdaddr) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": address=" << bdaddr.ToString();
+ connection_handler_->DisconnectDevice(bdaddr);
+}
+
+void AvrcpService::SendMediaUpdate(bool track_changed, bool play_state,
+ bool queue) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << " track_changed=" << track_changed
+ << " : "
+ << " play_state=" << play_state << " : "
+ << " queue=" << queue;
+
+ // This function may be called on any thread, we need to make sure that the
+ // device update happens on the main thread.
+ for (auto device : instance_->connection_handler_->GetListOfDevices()) {
+ do_in_bta_thread(FROM_HERE, base::Bind(&Device::SendMediaUpdate,
+ base::Unretained(device.get()),
+ track_changed, play_state, queue));
+ }
+}
+
+void AvrcpService::SendFolderUpdate(bool available_players,
+ bool addressed_players, bool uids) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << " available_players=" << available_players
+ << " : "
+ << " addressed_players=" << addressed_players << " : "
+ << " uids=" << uids;
+
+ // Ensure that the update is posted to the correct thread
+ for (auto device : instance_->connection_handler_->GetListOfDevices()) {
+ do_in_bta_thread(
+ FROM_HERE,
+ base::Bind(&Device::SendFolderUpdate, base::Unretained(device.get()),
+ available_players, addressed_players, uids));
+ }
+}
+
+// Send out the track changed info to update the playback state for each device
+void AvrcpService::SendActiveDeviceChanged(const RawAddress& address) {
+ SendMediaUpdate(false, true, false);
+}
+
+void AvrcpService::DeviceCallback(std::shared_ptr<Device> new_device) {
+ if (new_device == nullptr) return;
+
+ // TODO (apanicke): Pass the interfaces into the connection handler
+ // so that the devices can be created with any interfaces they need.
+ new_device->RegisterInterfaces(media_interface_, &a2dp_interface_,
+ volume_interface_);
+}
+
+// Service Interface
+void AvrcpService::ServiceInterfaceImpl::Init(
+ MediaInterface* media_interface, VolumeInterface* volume_interface) {
+ std::lock_guard<std::mutex> lock(service_interface_lock_);
+
+ // TODO: This function should block until the service is completely up so
+ // that its possible to call Get() on the service immediately after calling
+ // init without issues.
+
+ CHECK(instance_ == nullptr);
+ instance_ = new AvrcpService();
+
+ {
+ std::lock_guard<std::mutex> jni_lock(jni_mutex_);
+ jni_message_loop_ = get_jni_message_loop();
+ }
+
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&AvrcpService::Init, base::Unretained(instance_),
+ media_interface, volume_interface));
+}
+
+bool AvrcpService::ServiceInterfaceImpl::ConnectDevice(
+ const RawAddress& bdaddr) {
+ std::lock_guard<std::mutex> lock(service_interface_lock_);
+ CHECK(instance_ != nullptr);
+ do_in_bta_thread(FROM_HERE, base::Bind(&AvrcpService::ConnectDevice,
+ base::Unretained(instance_), bdaddr));
+ return true;
+}
+
+bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice(
+ const RawAddress& bdaddr) {
+ std::lock_guard<std::mutex> lock(service_interface_lock_);
+ CHECK(instance_ != nullptr);
+ do_in_bta_thread(FROM_HERE, base::Bind(&AvrcpService::DisconnectDevice,
+ base::Unretained(instance_), bdaddr));
+ return true;
+}
+
+bool AvrcpService::ServiceInterfaceImpl::Cleanup() {
+ std::lock_guard<std::mutex> lock(service_interface_lock_);
+
+ if (instance_ == nullptr) return false;
+
+ {
+ std::lock_guard<std::mutex> jni_lock(jni_mutex_);
+ task_tracker_.TryCancelAll();
+ jni_message_loop_ = nullptr;
+ }
+
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&AvrcpService::Cleanup, base::Owned(instance_)));
+
+ // Setting instance to nullptr here is fine since it will be deleted on the
+ // other thread.
+ instance_ = nullptr;
+
+ return true;
+}
+
+void AvrcpService::DebugDump(int fd) {
+ if (instance_ == nullptr) {
+ dprintf(fd, "\nAVRCP Target Service not started\n");
+ return;
+ }
+
+ auto device_list = instance_->connection_handler_->GetListOfDevices();
+ dprintf(fd, "\nAVRCP Target Native Service: %zu devices\n",
+ device_list.size());
+
+ std::stringstream stream;
+ for (auto device : device_list) {
+ stream << *device << std::endl;
+ }
+ dprintf(fd, "%s", stream.str().c_str());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/btif/avrcp/avrcp_service.h b/btif/avrcp/avrcp_service.h
new file mode 100644
index 0000000..d26b200
--- /dev/null
+++ b/btif/avrcp/avrcp_service.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <map>
+#include <memory>
+
+#include "avrcp.h"
+#include "connection_handler.h"
+#include "osi/include/properties.h"
+#include "raw_address.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+/**
+ * AvrcpService is the management interface for AVRCP Target. It handles any
+ * required thread switching, interface registration, and provides an API
+ * for connecting and disconnecting devices.
+ * TODO (apanicke): Instead of providing a service interface implementation,
+ * have the AvrcpService itself be its interface so we don't have to access
+ * it indirectly.
+ */
+class AvrcpService : public MediaCallbacks {
+ public:
+ /**
+ * Gets a handle to the AvrcpService
+ *
+ * Currently used by A2DP to tell AVRCP to initiate a connection to the
+ * remote device.
+ */
+ static AvrcpService* Get();
+
+ /**
+ * Returns an interface to control this service. The Avrcp::ServiceInterface
+ * handles all thread switching between the caller thread and the thread the
+ * service runs on, that way whoever uses the interface doesn't need to be
+ * aware which thread the service runs on.
+ */
+ static ServiceInterface* GetServiceInterface();
+
+ void Init(MediaInterface* media_interface, VolumeInterface* volume_interface);
+ void Cleanup();
+
+ void ConnectDevice(const RawAddress& bdaddr);
+ void DisconnectDevice(const RawAddress& bdaddr);
+
+ // Functions inherited from MediaCallbacks in order to receive updates
+ void SendMediaUpdate(bool track_changed, bool play_state,
+ bool queue) override;
+ void SendFolderUpdate(bool available_players, bool addressed_player,
+ bool queue) override;
+ void SendActiveDeviceChanged(const RawAddress& address) override;
+
+ class ServiceInterfaceImpl : public ServiceInterface {
+ public:
+ void Init(MediaInterface* media_interface,
+ VolumeInterface* volume_interface) override;
+ bool ConnectDevice(const RawAddress& bdaddr) override;
+ bool DisconnectDevice(const RawAddress& bdaddr) override;
+ bool Cleanup() override;
+
+ private:
+ std::mutex service_interface_lock_;
+ };
+
+ static void DebugDump(int fd);
+
+ protected:
+ void DeviceCallback(std::shared_ptr<Device> device);
+
+ private:
+ static AvrcpService* instance_;
+ static ServiceInterfaceImpl* service_interface_;
+
+ MediaInterface* media_interface_ = nullptr;
+ VolumeInterface* volume_interface_ = nullptr;
+
+ ConnectionHandler* connection_handler_;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
+
+inline bool is_new_avrcp_enabled() {
+ return osi_property_get_bool("persist.bluetooth.enablenewavrcp", true);
+}
\ No newline at end of file
diff --git a/btif/co/bta_ag_co.cc b/btif/co/bta_ag_co.cc
deleted file mode 100644
index b27e57e..0000000
--- a/btif/co/bta_ag_co.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2009-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-#define LOG_TAG "bt_btif_bta_ag"
-
-#include "bta/include/bta_ag_co.h"
-#include "bta/ag/bta_ag_int.h"
-#include "bta/include/bta_ag_api.h"
-#include "bta/include/bta_ag_ci.h"
-#include "osi/include/osi.h"
-
-/*******************************************************************************
- *
- * Function bta_ag_co_init
- *
- * Description This callout function is executed by AG when it is
- * started by calling BTA_AgEnable(). This function can be
- * used by the phone to initialize audio paths or for other
- * initialization purposes.
- *
- *
- * Returns Void.
- *
- ******************************************************************************/
-void bta_ag_co_init(void) { BTM_WriteVoiceSettings(AG_VOICE_SETTINGS); }
-
-/*******************************************************************************
- *
- * Function bta_ag_co_data_open
- *
- * Description This function is executed by AG when a service level
- * connection is opened. The phone can use this function to
- * set up data paths or perform any required initialization or
- * set up particular to the connected service.
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_ag_co_data_open(uint16_t handle, tBTA_SERVICE_ID service) {
- BTIF_TRACE_DEBUG("bta_ag_co_data_open handle:%d service:%d", handle, service);
-}
-
-/*******************************************************************************
- *
- * Function bta_ag_co_data_close
- *
- * Description This function is called by AG when a service level
- * connection is closed
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_ag_co_data_close(uint16_t handle) {
- BTIF_TRACE_DEBUG("bta_ag_co_data_close handle:%d", handle);
-}
-
-/*******************************************************************************
- **
- ** Function bta_ag_co_tx_write
- **
- ** Description This function is called by the AG to send data to the
- ** phone when the AG is configured for AT command
- ** pass-through. The implementation of this function must copy
- ** the data to the phones memory.
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_ag_co_tx_write(uint16_t handle, UNUSED_ATTR uint8_t* p_data,
- uint16_t len) {
- BTIF_TRACE_DEBUG("bta_ag_co_tx_write: handle: %d, len: %d", handle, len);
-}
diff --git a/btif/co/bta_av_co.cc b/btif/co/bta_av_co.cc
index e931714..6147744 100644
--- a/btif/co/bta_av_co.cc
+++ b/btif/co/bta_av_co.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,407 +23,899 @@
*
******************************************************************************/
-#include "bta_av_co.h"
+#include <mutex>
+
+#include <base/bind.h>
#include <base/logging.h>
#include <string.h>
+
+#include "bt_target.h"
+
#include "a2dp_api.h"
#include "a2dp_sbc.h"
-#include "bt_target.h"
#include "bta_av_api.h"
#include "bta_av_ci.h"
+#include "bta_av_co.h"
#include "bta_sys.h"
#include "btif_av.h"
#include "btif_av_co.h"
#include "btif_util.h"
-#include "osi/include/mutex.h"
#include "osi/include/osi.h"
+#include "osi/include/properties.h"
-/*****************************************************************************
- ** Constants
- *****************************************************************************/
-
-/* Macro to retrieve the number of elements in a statically allocated array */
+// Macro to retrieve the number of elements in a statically allocated array
#define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a) / sizeof((__a)[0]))
-/* Macro to convert audio handle to index and vice versa */
-#define BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl) (((hndl) & (~BTA_AV_CHNL_MSK)) - 1)
-#define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO)
+// Macro to convert BTA AV audio handle to index and vice versa
+#define BTA_AV_CO_AUDIO_HANDLE_TO_INDEX(bta_av_handle) \
+ (((bta_av_handle) & (~BTA_AV_CHNL_MSK)) - 1)
+#define BTA_AV_CO_AUDIO_INDEX_TO_HANDLE(index) \
+ (((index) + 1) | BTA_AV_CHNL_AUDIO)
-/* SCMS-T protect info */
-const uint8_t bta_av_co_cp_scmst[AVDT_CP_INFO_LEN] = {0x02, 0x02, 0x00};
-
-/*****************************************************************************
- * Local data
- ****************************************************************************/
-typedef struct {
- uint8_t sep_info_idx; /* local SEP index (in BTA tables) */
- uint8_t seid; /* peer SEP index (in peer tables) */
- uint8_t codec_caps[AVDT_CODEC_SIZE]; /* peer SEP codec capabilities */
- uint8_t num_protect; /* peer SEP number of CP elements */
- uint8_t protect_info[AVDT_CP_INFO_LEN]; /* peer SEP content protection info */
-} tBTA_AV_CO_SINK;
-
-typedef struct {
- RawAddress addr; /* address of audio/video peer */
- tBTA_AV_CO_SINK
- sinks[BTAV_A2DP_CODEC_INDEX_MAX]; /* array of supported sinks */
- tBTA_AV_CO_SINK srcs[BTAV_A2DP_CODEC_INDEX_MAX]; /* array of supported srcs */
- uint8_t num_sinks; /* total number of sinks at peer */
- uint8_t num_srcs; /* total number of srcs at peer */
- uint8_t num_seps; /* total number of seids at peer */
- uint8_t num_rx_sinks; /* number of received sinks */
- uint8_t num_rx_srcs; /* number of received srcs */
- uint8_t num_sup_sinks; /* number of supported sinks in the sinks array */
- uint8_t num_sup_srcs; /* number of supported srcs in the srcs array */
- const tBTA_AV_CO_SINK* p_sink; /* currently selected sink */
- const tBTA_AV_CO_SINK* p_src; /* currently selected src */
- uint8_t codec_config[AVDT_CODEC_SIZE]; /* current codec configuration */
- bool cp_active; /* current CP configuration */
- bool acp; /* acceptor */
- bool reconfig_needed; /* reconfiguration is needed */
- bool opened; /* opened */
- uint16_t mtu; /* maximum transmit unit size */
- uint16_t uuid_to_connect; /* uuid of peer device */
- tBTA_AV_HNDL handle; /* handle to use */
-} tBTA_AV_CO_PEER;
-
-typedef struct {
- bool active;
- uint8_t flag;
-} tBTA_AV_CO_CP;
-
-class BtaAvCoCb {
+class BtaAvCoSep {
public:
- BtaAvCoCb() : codecs(nullptr) { reset(); }
-
- /* Connected peer information */
- tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS];
- /* Current codec configuration - access to this variable must be protected */
- uint8_t codec_config[AVDT_CODEC_SIZE];
- A2dpCodecs* codecs; /* Locally supported codecs */
- tBTA_AV_CO_CP cp;
-
- void reset() {
- delete codecs;
- codecs = nullptr;
- // TODO: Ugly leftover reset from the original C code. Should go away once
- // the rest of the code in this file migrates to C++.
- memset(peers, 0, sizeof(peers));
- memset(codec_config, 0, sizeof(codec_config));
- memset(&cp, 0, sizeof(cp));
-
- // Initialize the handles
- for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers); i++) {
- tBTA_AV_CO_PEER* p_peer = &peers[i];
- p_peer->handle = BTA_AV_CO_AUDIO_INDX_TO_HNDL(i);
- }
+ BtaAvCoSep()
+ : sep_info_idx(0), seid(0), codec_caps{}, num_protect(0), protect_info{} {
+ Reset();
}
+
+ /**
+ * Reset the state.
+ */
+ void Reset() {
+ sep_info_idx = 0;
+ seid = 0;
+ memset(codec_caps, 0, sizeof(codec_caps));
+ num_protect = 0;
+ memset(protect_info, 0, sizeof(protect_info));
+ }
+
+ uint8_t sep_info_idx; // Local SEP index (in BTA tables)
+ uint8_t seid; // Peer SEP index (in peer tables)
+ uint8_t codec_caps[AVDT_CODEC_SIZE]; // Peer SEP codec capabilities
+ uint8_t num_protect; // Peer SEP number of CP elements
+ uint8_t protect_info[AVDT_CP_INFO_LEN]; // Peer SEP content protection info
};
-/* Control block instance */
-static BtaAvCoCb bta_av_co_cb;
-
-static bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info);
-static bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect,
- const uint8_t* p_protect_info);
-static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
- const tBTA_AV_CO_PEER* p_peer);
-static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer);
-static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
- A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer);
-static bool bta_av_co_audio_update_selectable_codec(
- A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer);
-static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
- const uint8_t* new_codec_config,
- uint8_t num_protect,
- const uint8_t* p_protect_info);
-static bool bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER* p_peer,
- const uint8_t* p_ota_codec_config,
- uint8_t num_protect,
- const uint8_t* p_protect_info,
- bool* p_restart_output);
-
-/*******************************************************************************
- **
- ** Function bta_av_co_cp_get_flag
- **
- ** Description Get content protection flag
- ** AVDT_CP_SCMS_COPY_NEVER
- ** AVDT_CP_SCMS_COPY_ONCE
- ** AVDT_CP_SCMS_COPY_FREE
- **
- ** Returns The current flag value
- **
- ******************************************************************************/
-static uint8_t bta_av_co_cp_get_flag(void) { return bta_av_co_cb.cp.flag; }
-
-/*******************************************************************************
- **
- ** Function bta_av_co_cp_set_flag
- **
- ** Description Set content protection flag
- ** AVDT_CP_SCMS_COPY_NEVER
- ** AVDT_CP_SCMS_COPY_ONCE
- ** AVDT_CP_SCMS_COPY_FREE
- **
- ** Returns true if setting the SCMS flag is supported else false
- **
- ******************************************************************************/
-static bool bta_av_co_cp_set_flag(uint8_t cp_flag) {
- APPL_TRACE_DEBUG("%s: cp_flag = %d", __func__, cp_flag);
-
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
-#else
- if (cp_flag != AVDT_CP_SCMS_COPY_FREE) {
- return false;
+class BtaAvCoPeer {
+ public:
+ BtaAvCoPeer()
+ : addr(RawAddress::kEmpty),
+ num_sinks(0),
+ num_sources(0),
+ num_seps(0),
+ num_rx_sinks(0),
+ num_rx_sources(0),
+ num_sup_sinks(0),
+ num_sup_sources(0),
+ p_sink(nullptr),
+ p_source(nullptr),
+ codec_config{},
+ acceptor(false),
+ reconfig_needed(false),
+ opened(false),
+ mtu(0),
+ uuid_to_connect(0),
+ bta_av_handle_(0),
+ codecs_(nullptr),
+ content_protect_active_(false) {
+ Reset(0);
}
+
+ /**
+ * Initialize the state.
+ *
+ * @param codec_priorities the codec priorities to use for the initialization
+ */
+ void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
+
+ /**
+ * Reset the state.
+ *
+ * @param bta_av_handle the BTA AV handle to use
+ */
+ void Reset(tBTA_AV_HNDL bta_av_handle);
+
+ /**
+ * Get the BTA AV handle.
+ *
+ * @return the BTA AV handle
+ */
+ tBTA_AV_HNDL BtaAvHandle() const { return bta_av_handle_; }
+
+ /**
+ * Get the A2DP codecs.
+ *
+ * @return the A2DP codecs
+ */
+ A2dpCodecs* GetCodecs() { return codecs_; }
+
+ bool ContentProtectActive() const { return content_protect_active_; }
+ void SetContentProtectActive(bool cp_active) {
+ content_protect_active_ = cp_active;
+ }
+
+ RawAddress addr; // Peer address
+ BtaAvCoSep sinks[BTAV_A2DP_CODEC_INDEX_MAX]; // Supported sinks
+ BtaAvCoSep sources[BTAV_A2DP_CODEC_INDEX_MAX]; // Supported sources
+ uint8_t num_sinks; // Total number of sinks at peer
+ uint8_t num_sources; // Total number of sources at peer
+ uint8_t num_seps; // Total number of SEPs at peer
+ uint8_t num_rx_sinks; // Number of received sinks
+ uint8_t num_rx_sources; // Number of received sources
+ uint8_t num_sup_sinks; // Number of supported sinks
+ uint8_t num_sup_sources; // Number of supported sources
+ const BtaAvCoSep* p_sink; // Currently selected sink
+ const BtaAvCoSep* p_source; // Currently selected source
+ uint8_t codec_config[AVDT_CODEC_SIZE]; // Current codec configuration
+ bool acceptor; // True if acceptor
+ bool reconfig_needed; // True if reconfiguration is needed
+ bool opened; // True if opened
+ uint16_t mtu; // Maximum Transmit Unit size
+ uint16_t uuid_to_connect; // UUID of peer device
+
+ private:
+ tBTA_AV_HNDL bta_av_handle_; // BTA AV handle to use
+ A2dpCodecs* codecs_; // Locally supported codecs
+ bool content_protect_active_; // True if Content Protect is active
+};
+
+class BtaAvCo {
+ public:
+ BtaAvCo(bool content_protect_enabled)
+ : active_peer_(nullptr),
+ codec_config_{},
+ content_protect_enabled_(content_protect_enabled),
+ content_protect_flag_(0) {
+ Reset();
+ }
+
+ /**
+ * Initialize the state.
+ *
+ * @param codec_priorities the codec priorities to use for the initialization
+ */
+ void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
+
+ /**
+ * Get the current codec configuration for the active peer.
+ *
+ * @return the current codec configuration if found, otherwise nullptr
+ */
+ A2dpCodecConfig* GetActivePeerCurrentCodec();
+
+ /**
+ * Get the current codec configuration for a peer.
+ *
+ * @param peer_address the peer address
+ * @return the current codec configuration if found, otherwise nullptr
+ */
+ A2dpCodecConfig* GetPeerCurrentCodec(const RawAddress& peer_address);
+
+ /**
+ * Find the peer UUID for a given BTA AV handle.
+ *
+ * @param bta_av_handle the BTA AV handle to use
+ * @return the peer UUID if found, otherwise 0
+ */
+ uint16_t FindPeerUuid(tBTA_AV_HNDL bta_av_handle);
+
+ /**
+ * Process the AVDTP discovery result: number of Stream End Points (SEP)
+ * found during the AVDTP stream discovery process.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param num_seps the number of discovered SEPs
+ * @param num_sinks number of discovered Sink SEPs
+ * @param num_sources number of discovered Source SEPs
+ * @param uuid_local local UUID
+ */
+ void ProcessDiscoveryResult(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint8_t num_seps,
+ uint8_t num_sinks, uint8_t num_sources,
+ uint16_t uuid_local);
+
+ /**
+ * Process retrieved codec configuration and content protection from
+ * Peer Sink SEP.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param p_codec_info the peer sink capability filled-in by the caller.
+ * On success, it will contain the current codec configuration for the peer.
+ * @param p_sep_info_idx the peer SEP index for the corresponding peer
+ * sink capability filled-in by the caller. On success, it will contain
+ * the SEP index for the current codec configuration for the peer.
+ * @param seid the peer SEP index in peer tables
+ * @param p_num_protect the peer SEP number of content protection elements
+ * filled-in by the caller. On success, it will contain the SEP number of
+ * content protection elements for the current codec configuration for the
+ * peer.
+ * @param p_protect_info the peer SEP content protection info filled-in by
+ * the caller. On success, it will contain the SEP content protection info
+ * for the current codec configuration for the peer.
+ * @return A2DP_SUCCESS on success, otherwise A2DP_FAIL
+ */
+ tA2DP_STATUS ProcessSourceGetConfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
+ uint8_t* p_sep_info_idx, uint8_t seid,
+ uint8_t* p_num_protect,
+ uint8_t* p_protect_info);
+
+ /**
+ * Process retrieved codec configuration and content protection from
+ * Peer Source SEP.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param p_codec_info the peer source capability filled-in by the caller.
+ * On success, it will contain the current codec configuration for the peer.
+ * @param p_sep_info_idx the peer SEP index for the corresponding peer
+ * source capability filled-in by the caller. On success, it will contain
+ * the SEP index for the current codec configuration for the peer.
+ * @param seid the peer SEP index in peer tables
+ * @param p_num_protect the peer SEP number of content protection elements
+ * filled-in by the caller. On success, it will contain the SEP number of
+ * content protection elements for the current codec configuration for the
+ * peer.
+ * @param p_protect_info the peer SEP content protection info filled-in by
+ * the caller. On success, it will contain the SEP content protection info
+ * for the current codec configuration for the peer.
+ * @return A2DP_SUCCESS on success, otherwise A2DP_FAIL
+ */
+ tA2DP_STATUS ProcessSinkGetConfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
+ uint8_t* p_sep_info_idx, uint8_t seid,
+ uint8_t* p_num_protect,
+ uint8_t* p_protect_info);
+
+ /**
+ * Process AVDTP Set Config to set the codec and content protection
+ * configuration of the audio stream.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param p_codec_info the codec configuration to set
+ * @param seid stream endpoint ID of stream initiating the operation
+ * @param peer_address the peer address
+ * @param num_protect the peer SEP number of content protection elements
+ * @param p_protect_info the peer SEP conntent protection info
+ * @param t_local_sep the local SEP: AVDT_TSEP_SRC or AVDT_TSEP_SNK
+ * @param avdt_handle the AVDTP handle
+ */
+ void ProcessSetConfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, uint8_t seid,
+ uint8_t num_protect, const uint8_t* p_protect_info,
+ uint8_t t_local_sep, uint8_t avdt_handle);
+
+ /**
+ * Process AVDTP Open when the stream connection is opened.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param mtu the MTU of the connection
+ */
+ void ProcessOpen(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
+ uint16_t mtu);
+
+ /**
+ * Process AVDTP Close when the stream connection is closed.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ */
+ void ProcessClose(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address);
+
+ /**
+ * Process AVDTP Start when the audio data streaming is started.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param p_codec_info the codec configuration
+ * @param p_no_rtp_header on return, set to true if the audio data packets
+ * should not contain RTP header
+ */
+ void ProcessStart(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
+ const uint8_t* p_codec_info, bool* p_no_rtp_header);
+
+ /**
+ * Process AVDTP Stop when the audio data streaming is stopped.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ */
+ void ProcessStop(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address);
+
+ /**
+ * Get the next encoded audio data packet to send.
+ *
+ * @param p_codec_info the codec configuration
+ * @param p_timestamp on return, set to the timestamp of the data packet
+ * @return the next encoded data packet or nullptr if no encoded data to send
+ */
+ BT_HDR* GetNextSourceDataPacket(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp);
+
+ /**
+ * An audio packet has been dropped.
+ * This signal can be used by the encoder to reduce the encoder bit rate
+ * setting.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ */
+ void DataPacketWasDropped(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
+
+ /**
+ * Process AVDTP Audio Delay when the initial delay report is received by
+ * the Source.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param delay the reported delay in 1/10th of a millisecond
+ */
+ void ProcessAudioDelay(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t delay);
+
+ /**
+ * Update the MTU of the audio data connection.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param mtu the new MTU of the audio data connection
+ */
+ void UpdateMtu(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
+ uint16_t mtu);
+
+ /**
+ * Set the active peer.
+ *
+ * @param peer_address the peer address
+ * @return true on success, otherwise false
+ */
+ bool SetActivePeer(const RawAddress& peer_address);
+
+ /**
+ * Get the encoder parameters for a peer.
+ *
+ * @param peer_address the peer address
+ * @param p_peer_params on return, set to the peer's encoder parameters
+ */
+ void GetPeerEncoderParameters(const RawAddress& peer_address,
+ tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params);
+
+ /**
+ * Get the Source encoder interface for the current codec.
+ *
+ * @return the Source encoder interface for the current codec
+ */
+ const tA2DP_ENCODER_INTERFACE* GetSourceEncoderInterface();
+
+ /**
+ * Get the Sink decoder interface for the current codec.
+ *
+ * @return the Sink decoder interface for the current codec
+ */
+ const tA2DP_DECODER_INTERFACE* GetSinkDecoderInterface();
+
+ /**
+ * Set the codec user configuration.
+ *
+ * @param peer_address the peer address
+ * @param codec_user_config the codec user configuration to set
+ * @return true on success, otherwise false
+ */
+ bool SetCodecUserConfig(const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_user_config);
+
+ /**
+ * Set the codec audio configuration.
+ *
+ * @param codec_audio_config the codec audio configuration to set
+ * @return true on success, otherwise false
+ */
+ bool SetCodecAudioConfig(const btav_a2dp_codec_config_t& codec_audio_config);
+
+ /**
+ * Report the source codec state for a peer
+ *
+ * @param p_peer the peer to report
+ * @return true on success, otherwise false
+ */
+ bool ReportSourceCodecState(BtaAvCoPeer* p_peer);
+
+ /**
+ * Report the sink codec state for a peer
+ *
+ * @param p_peer the peer to report
+ * @return true on success, otherwise false
+ */
+ bool ReportSinkCodecState(BtaAvCoPeer* p_peer);
+
+ /**
+ * Get the content protection flag.
+ *
+ * @return the content protection flag. It should be one of the following:
+ * AVDT_CP_SCMS_COPY_NEVER, AVDT_CP_SCMS_COPY_ONCE, AVDT_CP_SCMS_COPY_FREE
+ */
+ uint8_t ContentProtectFlag() const { return content_protect_flag_; }
+
+ /**
+ * Set the content protection flag.
+ *
+ * @param cp_flag the content protection flag. It should be one of the
+ * following:
+ * AVDT_CP_SCMS_COPY_NEVER, AVDT_CP_SCMS_COPY_ONCE, AVDT_CP_SCMS_COPY_FREE
+ * NOTE: If Content Protection is not enabled on the system, then
+ * the only acceptable vailue is AVDT_CP_SCMS_COPY_FREE.
+ */
+ void SetContentProtectFlag(uint8_t cp_flag) {
+ if (!ContentProtectEnabled() && (cp_flag != AVDT_CP_SCMS_COPY_FREE)) {
+ return;
+ }
+ content_protect_flag_ = cp_flag;
+ }
+
+ /**
+ * Dump debug-related information.
+ *
+ * @param fd the file descritor to use for writing the ASCII formatted
+ * information
+ */
+ void DebugDump(int fd);
+
+ /**
+ * Find the peer entry for a given peer address.
+ *
+ * @param peer_address the peer address to use
+ * @return the peer entry if found, otherwise nullptr
+ */
+ BtaAvCoPeer* FindPeer(const RawAddress& peer_address);
+
+ /**
+ * Find the peer Sink SEP entry for a given codec index.
+ *
+ * @param p_peer the peer to use
+ * @param codec_index the codec index to use
+ * @return the peer Sink SEP for the codec index if found, otherwise nullptr
+ */
+ BtaAvCoSep* FindPeerSink(BtaAvCoPeer* p_peer,
+ btav_a2dp_codec_index_t codec_index);
+
+ /**
+ * Find the peer Source SEP entry for a given codec index.
+ *
+ * @param p_peer the peer to use
+ * @param codec_config the codec index to use
+ * @return the peer Source SEP for the codec index if found, otherwise nullptr
+ */
+ BtaAvCoSep* FindPeerSource(BtaAvCoPeer* p_peer,
+ btav_a2dp_codec_index_t codec_index);
+
+ private:
+ /**
+ * Reset the state.
+ */
+ void Reset();
+
+ /**
+ * Find the peer entry for a given BTA AV handle.
+ *
+ * @param bta_av_handle the BTA AV handle to use
+ * @return the peer entry if found, otherwise nullptr
+ */
+ BtaAvCoPeer* FindPeer(tBTA_AV_HNDL bta_av_handle);
+
+ /**
+ * Find the peer entry for a given BTA AV handle and update it with the
+ * peer address.
+ *
+ * @param bta_av_handle the BTA AV handle to use
+ * @param peer_address the peer address
+ * @return the peer entry if found, otherwise nullptr
+ */
+ BtaAvCoPeer* FindPeerAndUpdate(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
+
+ /**
+ * Select the Source codec configuration based on peer codec support.
+ *
+ * Furthermore, the local state for the remaining non-selected codecs is
+ * updated to reflect whether the codec is selectable.
+ *
+ * @param p_peer the peer to use
+ * @return a pointer to the corresponding SEP Sink entry on success,
+ * otherwise nullptr
+ */
+ const BtaAvCoSep* SelectSourceCodec(BtaAvCoPeer* p_peer);
+
+ /**
+ * Select the Sink codec configuration based on peer codec support.
+ *
+ * Furthermore, the local state for the remaining non-selected codecs is
+ * updated to reflect whether the codec is selectable.
+ *
+ * @param p_peer the peer to use
+ * @return a pointer to the corresponding SEP Source entry on success,
+ * otherwise nullptr
+ */
+ const BtaAvCoSep* SelectSinkCodec(BtaAvCoPeer* p_peer);
+
+ /**
+ * Save new codec configuration.
+ *
+ * @param p_peer the peer to use
+ * @param new_codec_config the new codec configuration to use
+ * @param num_protect the number of content protection elements
+ * @param p_protect_info the content protection info to use
+ */
+ void SaveNewCodecConfig(BtaAvCoPeer* p_peer, const uint8_t* new_codec_config,
+ uint8_t num_protect, const uint8_t* p_protect_info);
+
+ /**
+ * Set the Over-The-Air preferred codec configuration.
+ *
+ * The OTA prefered codec configuration is ignored if the current
+ * codec configuration contains explicit user configuration, or if the
+ * codec configuration for the same codec contains explicit user
+ * configuration.
+ *
+ * @param p_peer is the peer device that sent the OTA codec configuration
+ * @param p_ota_codec_config contains the received OTA A2DP codec
+ * configuration from the remote peer. Note: this is not the peer codec
+ * capability, but the codec configuration that the peer would like to use.
+ * @param num_protect is the number of content protection methods to use
+ * @param p_protect_info contains the content protection information to use.
+ * @param p_restart_output if there is a change in the encoder configuration
+ * that requires restarting of the A2DP connection, flag |p_restart_output|
+ * is set to true.
+ * @return true on success, otherwise false
+ */
+ bool SetCodecOtaConfig(BtaAvCoPeer* p_peer, const uint8_t* p_ota_codec_config,
+ uint8_t num_protect, const uint8_t* p_protect_info,
+ bool* p_restart_output);
+
+ /**
+ * Update all selectable Source codecs with the corresponding codec
+ * information from a Sink peer.
+ *
+ * @param p_peer the peer Sink SEP to use
+ * @return the number of codecs that have been updated
+ */
+ size_t UpdateAllSelectableSourceCodecs(BtaAvCoPeer* p_peer);
+
+ /**
+ * Update a selectable Source codec with the corresponding codec information
+ * from a Sink peer.
+ *
+ * @param codec_config the codec config info to identify the codec to update
+ * @param p_peer the peer Sink SEP to use
+ * @return true if the codec is updated, otherwise false
+ */
+ bool UpdateSelectableSourceCodec(const A2dpCodecConfig& codec_config,
+ BtaAvCoPeer* p_peer);
+
+ /**
+ * Update all selectable Sink codecs with the corresponding codec
+ * information from a Source peer.
+ *
+ * @param p_peer the peer Source SEP to use
+ * @return the number of codecs that have been updated
+ */
+ size_t UpdateAllSelectableSinkCodecs(BtaAvCoPeer* p_peer);
+
+ /**
+ * Update a selectable Sink codec with the corresponding codec information
+ * from a Source peer.
+ *
+ * @param codec_config the codec config info to identify the codec to update
+ * @param p_peer the peer Source SEP to use
+ * @return true if the codec is updated, otherwise false
+ */
+ bool UpdateSelectableSinkCodec(const A2dpCodecConfig& codec_config,
+ BtaAvCoPeer* p_peer);
+
+ /**
+ * Attempt to select Source codec configuration for a Sink peer.
+ *
+ * @param codec_config the codec configuration to use
+ * @param p_peer the Sink peer to use
+ * @return a pointer to the corresponding SEP Sink entry on success,
+ * otnerwise nullptr
+ */
+ const BtaAvCoSep* AttemptSourceCodecSelection(
+ const A2dpCodecConfig& codec_config, BtaAvCoPeer* p_peer);
+
+ /**
+ * Attempt to select Sink codec configuration for a Source peer.
+ *
+ * @param codec_config the codec configuration to use
+ * @param p_peer the Source peer to use
+ * @return a pointer to the corresponding SEP Source entry on success,
+ * otnerwise nullptr
+ */
+ const BtaAvCoSep* AttemptSinkCodecSelection(
+ const A2dpCodecConfig& codec_config, BtaAvCoPeer* p_peer);
+
+ /**
+ * Check if a peer SEP has content protection enabled.
+ *
+ * @param p_sep the peer SEP to check
+ * @return true if the peer SEP has content protection enabled,
+ * otherwise false
+ */
+ bool AudioSepHasContentProtection(const BtaAvCoSep* p_sep);
+
+ /**
+ * Check if a content protection service is SCMS-T.
+ *
+ * @param p_orotect_info the content protection info to check
+ * @return true if the Contention Protection in @param p_protect_info
+ * is SCMS-T, otherwise false
+ */
+ static bool ContentProtectIsScmst(const uint8_t* p_protect_info);
+
+ /**
+ * Check if audio protect info contains SCMS-T Content Protection.
+ *
+ * @param num_protect number of protect schemes
+ * @param p_protect_info the protect info to check
+ * @return true if @param p_protect_info contains SCMS-T, otherwise false
+ */
+ static bool AudioProtectHasScmst(uint8_t num_protect,
+ const uint8_t* p_protect_info);
+
+ bool ContentProtectEnabled() const { return content_protect_enabled_; }
+
+ std::recursive_mutex codec_lock_; // Protect access to the codec state
+ std::vector<btav_a2dp_codec_config_t> codec_priorities_; // Configured
+ BtaAvCoPeer peers_[BTA_AV_NUM_STRS]; // Connected peer information
+ BtaAvCoPeer* active_peer_; // The current active peer
+ uint8_t codec_config_[AVDT_CODEC_SIZE]; // Current codec configuration
+ const bool content_protect_enabled_; // True if Content Protect is enabled
+ uint8_t content_protect_flag_; // Content Protect flag
+};
+
+// SCMS-T protect info
+const uint8_t bta_av_co_cp_scmst[AVDT_CP_INFO_LEN] = {0x02, 0x02, 0x00};
+
+// Control block instance
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+static const bool kContentProtectEnabled = true;
+#else
+static const bool kContentProtectEnabled = false;
#endif
- bta_av_co_cb.cp.flag = cp_flag;
- return true;
+static BtaAvCo bta_av_co_cb(kContentProtectEnabled);
+
+void BtaAvCoPeer::Init(
+ const std::vector<btav_a2dp_codec_config_t>& codec_priorities) {
+ Reset(bta_av_handle_);
+ // Reset the current config
+ codecs_ = new A2dpCodecs(codec_priorities);
+ codecs_->init();
+ A2DP_InitDefaultCodec(codec_config);
}
-/*******************************************************************************
- **
- ** Function bta_av_co_get_peer
- **
- ** Description find the peer entry for a given handle
- **
- ** Returns the control block
- **
- ******************************************************************************/
-static tBTA_AV_CO_PEER* bta_av_co_get_peer(tBTA_AV_HNDL hndl) {
+void BtaAvCoPeer::Reset(tBTA_AV_HNDL bta_av_handle) {
+ addr = RawAddress::kEmpty;
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(sinks); i++) {
+ BtaAvCoSep& sink = sinks[i];
+ sink.Reset();
+ }
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(sources); i++) {
+ BtaAvCoSep& source = sources[i];
+ source.Reset();
+ }
+ num_sinks = 0;
+ num_sources = 0;
+ num_seps = 0;
+ num_rx_sinks = 0;
+ num_rx_sources = 0;
+ num_sup_sinks = 0;
+ num_sup_sources = 0;
+ p_sink = nullptr;
+ p_source = nullptr;
+ memset(codec_config, 0, sizeof(codec_config));
+ acceptor = false;
+ reconfig_needed = false;
+ opened = false;
+ mtu = 0;
+ uuid_to_connect = 0;
+
+ bta_av_handle_ = bta_av_handle;
+ delete codecs_;
+ codecs_ = nullptr;
+ content_protect_active_ = false;
+}
+
+void BtaAvCo::Init(
+ const std::vector<btav_a2dp_codec_config_t>& codec_priorities) {
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ // Reset the control block
+ Reset();
+ codec_priorities_ = codec_priorities;
+
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ BtaAvCoPeer* p_peer = &peers_[i];
+ p_peer->Init(codec_priorities);
+ }
+}
+
+void BtaAvCo::Reset() {
+ codec_priorities_.clear();
+ active_peer_ = nullptr;
+ content_protect_flag_ = 0;
+ memset(codec_config_, 0, sizeof(codec_config_));
+
+ if (ContentProtectEnabled()) {
+ SetContentProtectFlag(AVDT_CP_SCMS_COPY_NEVER);
+ } else {
+ SetContentProtectFlag(AVDT_CP_SCMS_COPY_FREE);
+ }
+
+ // Reset the peers and initialize the handles
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ BtaAvCoPeer* p_peer = &peers_[i];
+ p_peer->Reset(BTA_AV_CO_AUDIO_INDEX_TO_HANDLE(i));
+ }
+}
+
+A2dpCodecConfig* BtaAvCo::GetActivePeerCurrentCodec() {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ if (active_peer_ == nullptr || active_peer_->GetCodecs() == nullptr) {
+ return nullptr;
+ }
+ return active_peer_->GetCodecs()->getCurrentCodecConfig();
+}
+
+A2dpCodecConfig* BtaAvCo::GetPeerCurrentCodec(const RawAddress& peer_address) {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ BtaAvCoPeer* peer = FindPeer(peer_address);
+ if (peer == nullptr || peer->GetCodecs() == nullptr) {
+ return nullptr;
+ }
+ return peer->GetCodecs()->getCurrentCodecConfig();
+}
+
+BtaAvCoPeer* BtaAvCo::FindPeer(const RawAddress& peer_address) {
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ BtaAvCoPeer* p_peer = &peers_[i];
+ if (p_peer->addr == peer_address) {
+ return p_peer;
+ }
+ }
+ return nullptr;
+}
+
+BtaAvCoPeer* BtaAvCo::FindPeer(tBTA_AV_HNDL bta_av_handle) {
uint8_t index;
- index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl);
+ index = BTA_AV_CO_AUDIO_HANDLE_TO_INDEX(bta_av_handle);
- APPL_TRACE_DEBUG("%s: handle = %d index = %d", __func__, hndl, index);
+ APPL_TRACE_DEBUG("%s: bta_av_handle = 0x%x index = %d", __func__,
+ bta_av_handle, index);
- /* Sanity check */
- if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers)) {
- APPL_TRACE_ERROR("%s: peer index out of bounds: %d", __func__, index);
- return NULL;
+ // Sanity check
+ if (index >= BTA_AV_CO_NUM_ELEMENTS(peers_)) {
+ APPL_TRACE_ERROR(
+ "%s: peer index %d for BTA AV handle 0x%x is out of bounds", __func__,
+ index, bta_av_handle);
+ return nullptr;
}
- return &bta_av_co_cb.peers[index];
+ return &peers_[index];
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_init
- **
- ** Description This callout function is executed by AV when it is
- ** started by calling BTA_AvRegister(). This function can be
- ** used by the phone to initialize audio paths or for other
- ** initialization purposes.
- **
- **
- ** Returns Stream codec and content protection capabilities info.
- **
- ******************************************************************************/
-bool bta_av_co_audio_init(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg) {
- return A2DP_InitCodecConfig(codec_index, p_cfg);
+BtaAvCoPeer* BtaAvCo::FindPeerAndUpdate(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle = 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
+
+ BtaAvCoPeer* p_peer = FindPeer(bta_av_handle);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR("%s: peer entry for BTA AV handle 0x%x peer %s not found",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ return nullptr;
+ }
+
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle = 0x%x previous address %s",
+ __func__, peer_address.ToString().c_str(), bta_av_handle,
+ p_peer->addr.ToString().c_str());
+ p_peer->addr = peer_address;
+ return p_peer;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_disc_res
- **
- ** Description This callout function is executed by AV to report the
- ** number of stream end points (SEP) were found during the
- ** AVDT stream discovery process.
- **
- **
- ** Returns void.
- **
- ******************************************************************************/
-void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, uint8_t num_seps,
- uint8_t num_sink, uint8_t num_src,
- const RawAddress& addr, uint16_t uuid_local) {
- tBTA_AV_CO_PEER* p_peer;
+uint16_t BtaAvCo::FindPeerUuid(tBTA_AV_HNDL bta_av_handle) {
+ BtaAvCoPeer* p_peer = FindPeer(bta_av_handle);
+ if (p_peer == nullptr) {
+ return 0;
+ }
+ return p_peer->uuid_to_connect;
+}
- APPL_TRACE_DEBUG("%s: h:x%x num_seps:%d num_sink:%d num_src:%d", __func__,
- hndl, num_seps, num_sink, num_src);
+void BtaAvCo::ProcessDiscoveryResult(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t num_seps, uint8_t num_sinks,
+ uint8_t num_sources, uint16_t uuid_local) {
+ APPL_TRACE_DEBUG(
+ "%s: peer %s bta_av_handle:0x%x num_seps:%d num_sinks:%d num_sources:%d",
+ __func__, peer_address.ToString().c_str(), bta_av_handle, num_seps,
+ num_sinks, num_sources);
- /* Find the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
return;
}
/* Sanity check : this should never happen */
if (p_peer->opened) {
- APPL_TRACE_ERROR("%s: peer already opened", __func__);
+ APPL_TRACE_ERROR("%s: peer %s already opened", __func__,
+ peer_address.ToString().c_str());
}
/* Copy the discovery results */
- p_peer->addr = addr;
- p_peer->num_sinks = num_sink;
- p_peer->num_srcs = num_src;
+ p_peer->addr = peer_address;
+ p_peer->num_sinks = num_sinks;
+ p_peer->num_sources = num_sources;
p_peer->num_seps = num_seps;
p_peer->num_rx_sinks = 0;
- p_peer->num_rx_srcs = 0;
+ p_peer->num_rx_sources = 0;
p_peer->num_sup_sinks = 0;
- if (uuid_local == UUID_SERVCLASS_AUDIO_SINK)
+ p_peer->num_sup_sources = 0;
+ if (uuid_local == UUID_SERVCLASS_AUDIO_SINK) {
p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SOURCE;
- else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE)
+ } else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE) {
p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SINK;
+ }
}
-/*******************************************************************************
- **
- ** Function bta_av_audio_sink_getconfig
- **
- ** Description This callout function is executed by AV to retrieve the
- ** desired codec and content protection configuration for the
- ** A2DP Sink audio stream in Initiator.
- **
- **
- ** Returns Pass or Fail for current getconfig.
- **
- ******************************************************************************/
-static tA2DP_STATUS bta_av_audio_sink_getconfig(
- tBTA_AV_HNDL hndl, uint8_t* p_codec_info, uint8_t* p_sep_info_idx,
- uint8_t seid, uint8_t* p_num_protect, uint8_t* p_protect_info) {
- tA2DP_STATUS result = A2DP_FAIL;
- tBTA_AV_CO_PEER* p_peer;
-
- APPL_TRACE_DEBUG("%s: handle:0x%x codec:%s seid:%d", __func__, hndl,
+tA2DP_STATUS BtaAvCo::ProcessSourceGetConfig(
+ tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
+ uint8_t* p_codec_info, uint8_t* p_sep_info_idx, uint8_t seid,
+ uint8_t* p_num_protect, uint8_t* p_protect_info) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle:0x%x codec:%s seid:%d", __func__,
+ peer_address.ToString().c_str(), bta_av_handle,
A2DP_CodecName(p_codec_info), seid);
APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
__func__, *p_num_protect, p_protect_info[0],
p_protect_info[1], p_protect_info[2]);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_codec_info).c_str());
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
return A2DP_FAIL;
}
-
- APPL_TRACE_DEBUG("%s: peer(o=%d,n_sinks=%d,n_rx_sinks=%d,n_sup_sinks=%d)",
- __func__, p_peer->opened, p_peer->num_srcs,
- p_peer->num_rx_srcs, p_peer->num_sup_srcs);
-
- p_peer->num_rx_srcs++;
-
- /* Check the peer's SOURCE codec */
- if (A2DP_IsPeerSourceCodecValid(p_codec_info)) {
- /* If there is room for a new one */
- if (p_peer->num_sup_srcs < BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs)) {
- tBTA_AV_CO_SINK* p_src = &p_peer->srcs[p_peer->num_sup_srcs++];
-
- APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
- p_codec_info[1], p_codec_info[2], p_codec_info[3],
- p_codec_info[4], p_codec_info[5], p_codec_info[6]);
-
- memcpy(p_src->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
- p_src->sep_info_idx = *p_sep_info_idx;
- p_src->seid = seid;
- p_src->num_protect = *p_num_protect;
- memcpy(p_src->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
- } else {
- APPL_TRACE_ERROR("%s: no more room for SRC info", __func__);
- }
- }
-
- /* If last SINK get capabilities or all supported codec caps retrieved */
- if ((p_peer->num_rx_srcs == p_peer->num_srcs) ||
- (p_peer->num_sup_srcs == BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs))) {
- APPL_TRACE_DEBUG("%s: last SRC reached", __func__);
-
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_lock();
-
- /* Find a src that matches the codec config */
- const tBTA_AV_CO_SINK* p_src =
- bta_av_co_find_peer_src_supports_codec(p_peer);
- if (p_src != NULL) {
- uint8_t pref_config[AVDT_CODEC_SIZE];
- APPL_TRACE_DEBUG("%s: codec supported", __func__);
-
- /* Build the codec configuration for this sink */
- /* Save the new configuration */
- p_peer->p_src = p_src;
- /* get preferred config from src_caps */
- if (A2DP_BuildSrc2SinkConfig(p_src->codec_caps, pref_config) !=
- A2DP_SUCCESS) {
- mutex_global_unlock();
- return A2DP_FAIL;
- }
- memcpy(p_peer->codec_config, pref_config, AVDT_CODEC_SIZE);
-
- APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__,
- p_peer->codec_config[1], p_peer->codec_config[2],
- p_peer->codec_config[3], p_peer->codec_config[4],
- p_peer->codec_config[5], p_peer->codec_config[6]);
- /* By default, no content protection */
- *p_num_protect = 0;
-
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- p_peer->cp_active = false;
- bta_av_co_cb.cp.active = false;
-#endif
-
- *p_sep_info_idx = p_src->sep_info_idx;
- memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE);
- result = A2DP_SUCCESS;
- }
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_unlock();
- }
- return result;
-}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_getconfig
- **
- ** Description This callout function is executed by AV to retrieve the
- ** desired codec and content protection configuration for the
- ** audio stream.
- **
- **
- ** Returns Stream codec and content protection configuration info.
- **
- ******************************************************************************/
-tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
- uint8_t* p_sep_info_idx, uint8_t seid,
- uint8_t* p_num_protect,
- uint8_t* p_protect_info) {
- tBTA_AV_CO_PEER* p_peer;
-
- APPL_TRACE_DEBUG("%s", __func__);
- A2DP_DumpCodecInfo(p_codec_info);
-
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
- return A2DP_FAIL;
- }
-
- if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE) {
- return bta_av_audio_sink_getconfig(hndl, p_codec_info, p_sep_info_idx, seid,
- p_num_protect, p_protect_info);
- }
- APPL_TRACE_DEBUG("%s: handle:0x%x codec:%s seid:%d", __func__, hndl,
- A2DP_CodecName(p_codec_info), seid);
- APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
- __func__, *p_num_protect, p_protect_info[0],
- p_protect_info[1], p_protect_info[2]);
APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)",
__func__, p_peer->opened, p_peer->num_sinks,
p_peer->num_rx_sinks, p_peer->num_sup_sinks);
p_peer->num_rx_sinks++;
- /* Check the peer's SINK codec */
+ // Check the peer's Sink codec
if (A2DP_IsPeerSinkCodecValid(p_codec_info)) {
- /* If there is room for a new one */
+ // If there is room for a new one
if (p_peer->num_sup_sinks < BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks)) {
- tBTA_AV_CO_SINK* p_sink = &p_peer->sinks[p_peer->num_sup_sinks++];
+ BtaAvCoSep* p_sink = &p_peer->sinks[p_peer->num_sup_sinks++];
APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
p_codec_info[1], p_codec_info[2], p_codec_info[3],
@@ -435,149 +927,286 @@
p_sink->num_protect = *p_num_protect;
memcpy(p_sink->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
} else {
- APPL_TRACE_ERROR("%s: no more room for SINK info", __func__);
+ APPL_TRACE_ERROR("%s: peer %s : no more room for Sink info", __func__,
+ p_peer->addr.ToString().c_str());
}
}
- // Check if this is the last SINK get capabilities or all supported codec
+ // Check if this is the last Sink get capabilities or all supported codec
// capabilities are retrieved.
if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
(p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
return A2DP_FAIL;
}
- APPL_TRACE_DEBUG("%s: last sink reached", __func__);
+ APPL_TRACE_DEBUG("%s: last Sink codec reached for peer %s", __func__,
+ p_peer->addr.ToString().c_str());
- const tBTA_AV_CO_SINK* p_sink = bta_av_co_audio_set_codec(p_peer);
- if (p_sink == NULL) {
- APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__);
- return A2DP_FAIL;
+ // Select the Source codec
+ const BtaAvCoSep* p_sink = nullptr;
+ if (p_peer->acceptor) {
+ UpdateAllSelectableSourceCodecs(p_peer);
+ if (p_peer->p_sink == nullptr) {
+ // Update the selected codec
+ p_peer->p_sink =
+ FindPeerSink(p_peer, A2DP_SourceCodecIndex(p_peer->codec_config));
+ }
+ p_sink = p_peer->p_sink;
+ if (p_sink == nullptr) {
+ APPL_TRACE_ERROR("%s: cannot find the selected codec for peer %s",
+ __func__, p_peer->addr.ToString().c_str());
+ return A2DP_FAIL;
+ }
+ } else {
+ p_sink = SelectSourceCodec(p_peer);
+ if (p_sink == nullptr) {
+ APPL_TRACE_ERROR("%s: cannot set up codec for peer %s", __func__,
+ p_peer->addr.ToString().c_str());
+ return A2DP_FAIL;
+ }
}
// By default, no content protection
*p_num_protect = 0;
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- if (p_peer->cp_active) {
+ if (ContentProtectEnabled() && p_peer->ContentProtectActive()) {
*p_num_protect = AVDT_CP_INFO_LEN;
memcpy(p_protect_info, bta_av_co_cp_scmst, AVDT_CP_INFO_LEN);
}
-#endif
- // If acceptor -> reconfig otherwise reply for configuration.
- if (p_peer->acp) {
- // Stop fetching caps once we retrieved a supported codec.
- APPL_TRACE_EVENT("%s: no need to fetch more SEPs", __func__);
- *p_sep_info_idx = p_peer->num_seps;
+ // If acceptor -> reconfig otherwise reply for configuration
+ *p_sep_info_idx = p_sink->sep_info_idx;
+ APPL_TRACE_EVENT("%s: peer %s acceptor:%s reconfig_needed:%s", __func__,
+ p_peer->addr.ToString().c_str(),
+ (p_peer->acceptor) ? "true" : "false",
+ (p_peer->reconfig_needed) ? "true" : "false");
+ if (p_peer->acceptor) {
if (p_peer->reconfig_needed) {
- APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, hndl);
- BTA_AvReconfig(hndl, true, p_sink->sep_info_idx, p_peer->codec_config,
- *p_num_protect, bta_av_co_cp_scmst);
+ APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x) for peer %s", __func__,
+ bta_av_handle, p_peer->addr.ToString().c_str());
+ BTA_AvReconfig(bta_av_handle, true, p_sink->sep_info_idx,
+ p_peer->codec_config, *p_num_protect, bta_av_co_cp_scmst);
}
} else {
- *p_sep_info_idx = p_sink->sep_info_idx;
memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE);
}
return A2DP_SUCCESS;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_setconfig
- **
- ** Description This callout function is executed by AV to set the codec
- ** and content protection configuration of the audio stream.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, const uint8_t* p_codec_info,
- UNUSED_ATTR uint8_t seid,
- UNUSED_ATTR const RawAddress& addr,
- uint8_t num_protect,
+tA2DP_STATUS BtaAvCo::ProcessSinkGetConfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
+ uint8_t* p_sep_info_idx,
+ uint8_t seid, uint8_t* p_num_protect,
+ uint8_t* p_protect_info) {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle:0x%x codec:%s seid:%d", __func__,
+ peer_address.ToString().c_str(), bta_av_handle,
+ A2DP_CodecName(p_codec_info), seid);
+ APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
+ __func__, *p_num_protect, p_protect_info[0],
+ p_protect_info[1], p_protect_info[2]);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_codec_info).c_str());
+
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ return A2DP_FAIL;
+ }
+ APPL_TRACE_DEBUG(
+ "%s: peer %s found (o=%d, n_sources=%d, n_rx_sources=%d, "
+ "n_sup_sources=%d)",
+ __func__, p_peer->addr.ToString().c_str(), p_peer->opened,
+ p_peer->num_sources, p_peer->num_rx_sources, p_peer->num_sup_sources);
+
+ p_peer->num_rx_sources++;
+
+ // Check the peer's Source codec
+ if (A2DP_IsPeerSourceCodecValid(p_codec_info)) {
+ // If there is room for a new one
+ if (p_peer->num_sup_sources < BTA_AV_CO_NUM_ELEMENTS(p_peer->sources)) {
+ BtaAvCoSep* p_source = &p_peer->sources[p_peer->num_sup_sources++];
+
+ APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
+ p_codec_info[1], p_codec_info[2], p_codec_info[3],
+ p_codec_info[4], p_codec_info[5], p_codec_info[6]);
+
+ memcpy(p_source->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
+ p_source->sep_info_idx = *p_sep_info_idx;
+ p_source->seid = seid;
+ p_source->num_protect = *p_num_protect;
+ memcpy(p_source->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
+ } else {
+ APPL_TRACE_ERROR("%s: peer %s : no more room for Source info", __func__,
+ p_peer->addr.ToString().c_str());
+ }
+ }
+
+ // Check if this is the last Source get capabilities or all supported codec
+ // capabilities are retrieved.
+ if ((p_peer->num_rx_sources != p_peer->num_sources) &&
+ (p_peer->num_sup_sources != BTA_AV_CO_NUM_ELEMENTS(p_peer->sources))) {
+ return A2DP_FAIL;
+ }
+ APPL_TRACE_DEBUG("%s: last Source codec reached for peer %s", __func__,
+ p_peer->addr.ToString().c_str());
+
+ // Select the Sink codec
+ const BtaAvCoSep* p_source = nullptr;
+ if (p_peer->acceptor) {
+ UpdateAllSelectableSinkCodecs(p_peer);
+ if (p_peer->p_source == nullptr) {
+ // Update the selected codec
+ p_peer->p_source =
+ FindPeerSource(p_peer, A2DP_SinkCodecIndex(p_peer->codec_config));
+ }
+ p_source = p_peer->p_source;
+ if (p_source == nullptr) {
+ APPL_TRACE_ERROR("%s: cannot find the selected codec for peer %s",
+ __func__, p_peer->addr.ToString().c_str());
+ return A2DP_FAIL;
+ }
+ } else {
+ p_source = SelectSinkCodec(p_peer);
+ if (p_source == nullptr) {
+ APPL_TRACE_ERROR("%s: cannot set up codec for the peer %s", __func__,
+ p_peer->addr.ToString().c_str());
+ return A2DP_FAIL;
+ }
+ }
+
+ // By default, no content protection
+ *p_num_protect = 0;
+ if (ContentProtectEnabled() && p_peer->ContentProtectActive()) {
+ *p_num_protect = AVDT_CP_INFO_LEN;
+ memcpy(p_protect_info, bta_av_co_cp_scmst, AVDT_CP_INFO_LEN);
+ }
+
+ // If acceptor -> reconfig otherwise reply for configuration
+ *p_sep_info_idx = p_source->sep_info_idx;
+ APPL_TRACE_EVENT("%s: peer %s acceptor:%s reconfig_needed:%s", __func__,
+ p_peer->addr.ToString().c_str(),
+ (p_peer->acceptor) ? "true" : "false",
+ (p_peer->reconfig_needed) ? "true" : "false");
+ if (p_peer->acceptor) {
+ if (p_peer->reconfig_needed) {
+ APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x) for peer %s", __func__,
+ bta_av_handle, p_peer->addr.ToString().c_str());
+ BTA_AvReconfig(bta_av_handle, true, p_source->sep_info_idx,
+ p_peer->codec_config, *p_num_protect, bta_av_co_cp_scmst);
+ }
+ } else {
+ memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE);
+ }
+
+ return A2DP_SUCCESS;
+}
+
+void BtaAvCo::ProcessSetConfig(tBTA_AV_HNDL bta_av_handle,
+ UNUSED_ATTR const RawAddress& peer_address,
+ const uint8_t* p_codec_info,
+ UNUSED_ATTR uint8_t seid, uint8_t num_protect,
const uint8_t* p_protect_info,
uint8_t t_local_sep, uint8_t avdt_handle) {
- tBTA_AV_CO_PEER* p_peer;
tA2DP_STATUS status = A2DP_SUCCESS;
uint8_t category = A2DP_SUCCESS;
bool reconfig_needed = false;
+ APPL_TRACE_DEBUG(
+ "%s: bta_av_handle=0x%x peer_address=%s seid=%d "
+ "num_protect=%d t_local_sep=%d avdt_handle=%d",
+ __func__, bta_av_handle, peer_address.ToString().c_str(), seid,
+ num_protect, t_local_sep, avdt_handle);
APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__,
p_codec_info[1], p_codec_info[2], p_codec_info[3],
p_codec_info[4], p_codec_info[5], p_codec_info[6]);
- APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
- num_protect, p_protect_info[0], p_protect_info[1],
+ APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
+ __func__, num_protect, p_protect_info[0], p_protect_info[1],
p_protect_info[2]);
- A2DP_DumpCodecInfo(p_codec_info);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_codec_info).c_str());
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
- /* Call call-in rejecting the configuration */
- bta_av_ci_setconfig(hndl, A2DP_BUSY, AVDT_ASC_CODEC, 0, NULL, false,
- avdt_handle);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ // Call call-in rejecting the configuration
+ bta_av_ci_setconfig(bta_av_handle, A2DP_BUSY, AVDT_ASC_CODEC, 0, nullptr,
+ false, avdt_handle);
return;
}
- APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)",
- __func__, p_peer->opened, p_peer->num_sinks,
- p_peer->num_rx_sinks, p_peer->num_sup_sinks);
+ APPL_TRACE_DEBUG(
+ "%s: peer %s found (o=%d, n_sinks=%d, n_rx_sinks=%d, "
+ "n_sup_sinks=%d)",
+ __func__, p_peer->addr.ToString().c_str(), p_peer->opened,
+ p_peer->num_sinks, p_peer->num_rx_sinks, p_peer->num_sup_sinks);
- /* Sanity check: should not be opened at this point */
+ // Sanity check: should not be opened at this point
if (p_peer->opened) {
- APPL_TRACE_ERROR("%s: peer already in use", __func__);
+ APPL_TRACE_ERROR("%s: peer %s already in use", __func__,
+ p_peer->addr.ToString().c_str());
}
if (num_protect != 0) {
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- /* If CP is supported */
- if ((num_protect != 1) ||
- (bta_av_co_cp_is_scmst(p_protect_info) == false)) {
- APPL_TRACE_ERROR("%s: wrong CP configuration", __func__);
+ if (ContentProtectEnabled()) {
+ if ((num_protect != 1) ||
+ !BtaAvCo::ContentProtectIsScmst(p_protect_info)) {
+ APPL_TRACE_ERROR("%s: wrong CP configuration for peer %s", __func__,
+ p_peer->addr.ToString().c_str());
+ status = A2DP_BAD_CP_TYPE;
+ category = AVDT_ASC_PROTECT;
+ }
+ } else {
+ // Do not support content protection for the time being
+ APPL_TRACE_ERROR("%s: wrong CP configuration for peer %s", __func__,
+ p_peer->addr.ToString().c_str());
status = A2DP_BAD_CP_TYPE;
category = AVDT_ASC_PROTECT;
}
-#else
- /* Do not support content protection for the time being */
- APPL_TRACE_ERROR("%s: wrong CP configuration", __func__);
- status = A2DP_BAD_CP_TYPE;
- category = AVDT_ASC_PROTECT;
-#endif
}
if (status == A2DP_SUCCESS) {
bool codec_config_supported = false;
if (t_local_sep == AVDT_TSEP_SNK) {
- APPL_TRACE_DEBUG("%s: peer is A2DP SRC", __func__);
+ APPL_TRACE_DEBUG("%s: peer %s is A2DP Source", __func__,
+ p_peer->addr.ToString().c_str());
codec_config_supported = A2DP_IsSinkCodecSupported(p_codec_info);
if (codec_config_supported) {
- // If Peer is SRC, and our config subset matches with what is
+ // If Peer is Source, and our config subset matches with what is
// requested by peer, then just accept what peer wants.
- bta_av_co_save_new_codec_config(p_peer, p_codec_info, num_protect,
- p_protect_info);
+ SaveNewCodecConfig(p_peer, p_codec_info, num_protect, p_protect_info);
}
}
if (t_local_sep == AVDT_TSEP_SRC) {
- APPL_TRACE_DEBUG("%s: peer is A2DP SINK", __func__);
- bool restart_output = false;
- if ((bta_av_co_cb.codecs == nullptr) ||
- !bta_av_co_set_codec_ota_config(p_peer, p_codec_info, num_protect,
- p_protect_info, &restart_output)) {
- APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
- A2DP_CodecName(p_codec_info));
+ APPL_TRACE_DEBUG("%s: peer %s is A2DP SINK", __func__,
+ p_peer->addr.ToString().c_str());
+ // Ignore the restart_output flag: accepting the remote device's
+ // codec selection should not trigger codec reconfiguration.
+ bool dummy_restart_output = false;
+ if ((p_peer->GetCodecs() == nullptr) ||
+ !SetCodecOtaConfig(p_peer, p_codec_info, num_protect, p_protect_info,
+ &dummy_restart_output)) {
+ APPL_TRACE_ERROR("%s: cannot set source codec %s for peer %s", __func__,
+ A2DP_CodecName(p_codec_info),
+ p_peer->addr.ToString().c_str());
} else {
codec_config_supported = true;
// Check if reconfiguration is needed
- if (restart_output ||
- ((num_protect == 1) && (!bta_av_co_cb.cp.active))) {
+ if (((num_protect == 1) && !p_peer->ContentProtectActive())) {
reconfig_needed = true;
}
}
}
- /* Check if codec configuration is supported */
+ // Check if codec configuration is supported
if (!codec_config_supported) {
category = AVDT_ASC_CODEC;
status = A2DP_WRONG_CODEC;
@@ -585,124 +1214,106 @@
}
if (status != A2DP_SUCCESS) {
- APPL_TRACE_DEBUG("%s: reject s=%d c=%d", __func__, status, category);
- /* Call call-in rejecting the configuration */
- bta_av_ci_setconfig(hndl, status, category, 0, NULL, false, avdt_handle);
+ APPL_TRACE_DEBUG("%s: peer %s reject s=%d c=%d", __func__,
+ p_peer->addr.ToString().c_str(), status, category);
+ // Call call-in rejecting the configuration
+ bta_av_ci_setconfig(bta_av_handle, status, category, 0, nullptr, false,
+ avdt_handle);
return;
}
- /* Mark that this is an acceptor peer */
- p_peer->acp = true;
+ // Mark that this is an acceptor peer
+ p_peer->acceptor = true;
p_peer->reconfig_needed = reconfig_needed;
- APPL_TRACE_DEBUG("%s: accept reconf=%d", __func__, reconfig_needed);
- /* Call call-in accepting the configuration */
- bta_av_ci_setconfig(hndl, A2DP_SUCCESS, A2DP_SUCCESS, 0, NULL,
+ APPL_TRACE_DEBUG("%s: peer %s accept reconf=%d", __func__,
+ p_peer->addr.ToString().c_str(), reconfig_needed);
+ // Call call-in accepting the configuration
+ bta_av_ci_setconfig(bta_av_handle, A2DP_SUCCESS, A2DP_SUCCESS, 0, nullptr,
reconfig_needed, avdt_handle);
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_open
- **
- ** Description This function is called by AV when the audio stream
- ** connection is opened.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_open(tBTA_AV_HNDL hndl, uint16_t mtu) {
- tBTA_AV_CO_PEER* p_peer;
+void BtaAvCo::ProcessOpen(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x mtu:%d", __func__,
+ peer_address.ToString().c_str(), bta_av_handle, mtu);
- APPL_TRACE_DEBUG("%s: handle: %d mtu:%d", __func__, hndl, mtu);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ return;
+ }
+ p_peer->opened = true;
+ p_peer->mtu = mtu;
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
- } else {
- p_peer->opened = true;
- p_peer->mtu = mtu;
+ // The first connected peer becomes the active peer
+ if (active_peer_ == nullptr) {
+ active_peer_ = p_peer;
}
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_close
- **
- ** Description This function is called by AV when the audio stream
- ** connection is closed.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_close(tBTA_AV_HNDL hndl) {
- tBTA_AV_CO_PEER* p_peer;
+void BtaAvCo::ProcessClose(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
+ btif_av_reset_audio_delay();
- APPL_TRACE_DEBUG("%s", __func__);
-
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer) {
- /* Mark the peer closed and clean the peer info */
- memset(p_peer, 0, sizeof(*p_peer));
- } else {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ return;
}
+ // Reset the active peer
+ if (active_peer_ == p_peer) {
+ active_peer_ = nullptr;
+ }
+ // Mark the peer closed and clean the peer info
+ p_peer->Init(codec_priorities_);
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_start
- **
- ** Description This function is called by AV when the audio streaming data
- ** transfer is started.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_start(UNUSED_ATTR tBTA_AV_HNDL hndl,
- UNUSED_ATTR uint8_t* p_codec_info,
- UNUSED_ATTR bool* p_no_rtp_hdr) {
- APPL_TRACE_DEBUG("%s", __func__);
+void BtaAvCo::ProcessStart(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, bool* p_no_rtp_header) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
+
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ return;
+ }
+
+ bool add_rtp_header =
+ A2DP_UsesRtpHeader(p_peer->ContentProtectActive(), p_codec_info);
+
+ APPL_TRACE_DEBUG("%s: bta_av_handle: 0x%x add_rtp_header: %s", __func__,
+ bta_av_handle, add_rtp_header ? "true" : "false");
+ *p_no_rtp_header = !add_rtp_header;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_stop
- **
- ** Description This function is called by AV when the audio streaming data
- ** transfer is stopped.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_stop(UNUSED_ATTR tBTA_AV_HNDL hndl) {
- APPL_TRACE_DEBUG("%s", __func__);
+void BtaAvCo::ProcessStop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
+ // Nothing to do
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_src_data_path
- **
- ** Description This function is called to manage data transfer from
- ** the audio codec to AVDTP.
- **
- ** Returns Pointer to the GKI buffer to send, NULL if no buffer to
- ** send
- **
- ******************************************************************************/
-void* bta_av_co_audio_src_data_path(const uint8_t* p_codec_info,
- uint32_t* p_timestamp) {
+BT_HDR* BtaAvCo::GetNextSourceDataPacket(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp) {
BT_HDR* p_buf;
APPL_TRACE_DEBUG("%s: codec: %s", __func__, A2DP_CodecName(p_codec_info));
p_buf = btif_a2dp_source_audio_readbuf();
- if (p_buf == NULL) return NULL;
+ if (p_buf == nullptr) return nullptr;
/*
* Retrieve the timestamp information from the media packet,
@@ -719,387 +1330,154 @@
A2DP_GetCodecType(p_codec_info));
}
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- if (bta_av_co_cb.cp.active) {
+ if (ContentProtectEnabled() && (active_peer_ != nullptr) &&
+ active_peer_->ContentProtectActive()) {
p_buf->len++;
p_buf->offset--;
uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
- *p = bta_av_co_cp_get_flag();
+ *p = ContentProtectFlag();
}
-#endif
return p_buf;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_drop
- **
- ** Description An Audio packet is dropped. .
- ** It's very likely that the connected headset with this
- ** handle is moved far away. The implementation may want to
- ** reduce the encoder bit rate setting to reduce the packet
- ** size.
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_drop(tBTA_AV_HNDL hndl) {
- APPL_TRACE_ERROR("%s: dropped audio packet on handle 0x%x", __func__, hndl);
+void BtaAvCo::DataPacketWasDropped(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ APPL_TRACE_ERROR("%s: peer %s dropped audio packet on handle 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_delay
- **
- ** Description This function is called by AV when the audio stream
- ** connection needs to send the initial delay report to the
- ** connected SRC.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay) {
- APPL_TRACE_ERROR("%s: handle: x%x, delay:0x%x", __func__, hndl, delay);
+void BtaAvCo::ProcessAudioDelay(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint16_t delay) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x delay:0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle, delay);
+
+ btif_av_set_audio_delay(delay);
}
-void bta_av_co_audio_update_mtu(tBTA_AV_HNDL hndl, uint16_t mtu) {
- tBTA_AV_CO_PEER* p_peer;
+void BtaAvCo::UpdateMtu(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x mtu: %d", __func__,
+ peer_address.ToString().c_str(), bta_av_handle, mtu);
- APPL_TRACE_DEBUG("%s: handle: %d mtu: %d", __func__, hndl, mtu);
-
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
return;
}
p_peer->mtu = mtu;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_cp_is_scmst
- **
- ** Description Check if a content protection service is SCMS-T
- **
- ** Returns true if this CP is SCMS-T, false otherwise
- **
- ******************************************************************************/
-static bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info) {
- APPL_TRACE_DEBUG("%s", __func__);
+bool BtaAvCo::SetActivePeer(const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
- if (*p_protect_info >= AVDT_CP_LOSC) {
- uint16_t cp_id;
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
- p_protect_info++;
- STREAM_TO_UINT16(cp_id, p_protect_info);
- if (cp_id == AVDT_CP_SCMS_T_ID) {
- APPL_TRACE_DEBUG("%s: SCMS-T found", __func__);
- return true;
- }
+ if (peer_address.IsEmpty()) {
+ // Reset the active peer;
+ active_peer_ = nullptr;
+ memset(codec_config_, 0, sizeof(codec_config_));
+ return true;
}
- return false;
-}
-
-// Check if audio protect info contains SCMS-T Copy Protection
-// Returns true if |p_protect_info| contains SCMS-T, otherwise false.
-static bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect,
- const uint8_t* p_protect_info) {
- APPL_TRACE_DEBUG("%s", __func__);
-
- while (num_protect--) {
- if (bta_av_co_cp_is_scmst(p_protect_info)) return true;
- /* Move to the next SC */
- p_protect_info += *p_protect_info + 1;
- }
- APPL_TRACE_DEBUG("%s: SCMS-T not found", __func__);
- return false;
-}
-
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_sink_supports_cp
- **
- ** Description Check if a sink supports the current content protection
- **
- ** Returns true if the sink supports this CP, false otherwise
- **
- ******************************************************************************/
-static bool bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK* p_sink) {
- APPL_TRACE_DEBUG("%s", __func__);
-
- /* Check if content protection is enabled for this stream */
- if (bta_av_co_cp_get_flag() != AVDT_CP_SCMS_COPY_FREE) {
- return bta_av_co_audio_protect_has_scmst(p_sink->num_protect,
- p_sink->protect_info);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeer(peer_address);
+ if (p_peer == nullptr) {
+ return false;
}
- APPL_TRACE_DEBUG("%s: not required", __func__);
+ active_peer_ = p_peer;
+ memcpy(codec_config_, active_peer_->codec_config, AVDT_CODEC_SIZE);
+ APPL_TRACE_DEBUG("%s: codec = %s", __func__,
+ A2DP_CodecInfoString(codec_config_).c_str());
+ ReportSourceCodecState(active_peer_);
return true;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_find_peer_src_supports_codec
- **
- ** Description Find a peer acting as src that supports codec config
- **
- ** Returns The peer source that supports the codec, otherwise NULL.
- **
- ******************************************************************************/
-static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
- const tBTA_AV_CO_PEER* p_peer) {
- APPL_TRACE_DEBUG("%s: peer num_sup_srcs = %d", __func__,
- p_peer->num_sup_srcs);
-
- for (size_t index = 0; index < p_peer->num_sup_srcs; index++) {
- const uint8_t* p_codec_caps = p_peer->srcs[index].codec_caps;
- if (A2DP_CodecTypeEquals(bta_av_co_cb.codec_config, p_codec_caps) &&
- A2DP_IsPeerSourceCodecSupported(p_codec_caps)) {
- return &p_peer->srcs[index];
- }
- }
- return NULL;
-}
-
-//
-// Select the current codec configuration based on peer codec support.
-// Furthermore, the local state for the remaining non-selected codecs is
-// updated to reflect whether the codec is selectable.
-// Return a pointer to the corresponding |tBTA_AV_CO_SINK| sink entry
-// on success, otherwise NULL.
-//
-static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer) {
- tBTA_AV_CO_SINK* p_sink = NULL;
-
- // Update all selectable codecs.
- // This is needed to update the selectable parameters for each codec.
- // NOTE: The selectable codec info is used only for informational purpose.
- for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
- APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__,
- iter->name().c_str());
- bta_av_co_audio_update_selectable_codec(*iter, p_peer);
- }
-
- // Select the codec
- for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
- APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str());
- p_sink = bta_av_co_audio_codec_selected(*iter, p_peer);
- if (p_sink != NULL) {
- APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str());
- break;
- }
- APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str());
- }
-
- // NOTE: Unconditionally dispatch the event to make sure a callback with
- // the most recent codec info is generated.
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
-
- return p_sink;
-}
-
-// Select an open device for the preferred codec specified by |codec_config|.
-// Return the corresponding peer that supports the codec, otherwise NULL.
-static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
- A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer) {
- uint8_t new_codec_config[AVDT_CODEC_SIZE];
-
- APPL_TRACE_DEBUG("%s", __func__);
-
- // Find the peer sink for the codec
- tBTA_AV_CO_SINK* p_sink = NULL;
- for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
- btav_a2dp_codec_index_t peer_codec_index =
- A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
- if (peer_codec_index != codec_config.codecIndex()) {
- continue;
- }
- if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) {
- APPL_TRACE_DEBUG(
- "%s: peer sink for codec %s does not support "
- "Copy Protection",
- __func__, codec_config.name().c_str());
- continue;
- }
- p_sink = &p_peer->sinks[index];
- break;
- }
- if (p_sink == NULL) {
- APPL_TRACE_DEBUG("%s: peer sink for codec %s not found", __func__,
- codec_config.name().c_str());
- return NULL;
- }
- if (!bta_av_co_cb.codecs->setCodecConfig(
- p_sink->codec_caps, true /* is_capability */, new_codec_config,
- true /* select_current_codec */)) {
- APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
- codec_config.name().c_str());
- return NULL;
- }
- p_peer->p_sink = p_sink;
-
- bta_av_co_save_new_codec_config(p_peer, new_codec_config, p_sink->num_protect,
- p_sink->protect_info);
- // NOTE: Event BTIF_AV_SOURCE_CONFIG_UPDATED_EVT is dispatched by the caller
-
- return p_sink;
-}
-
-// Update a selectable codec |codec_config| with the corresponding codec
-// information from a peer device |p_peer|.
-// Returns true if the codec is updated, otherwise false.
-static bool bta_av_co_audio_update_selectable_codec(
- A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer) {
- uint8_t new_codec_config[AVDT_CODEC_SIZE];
-
- APPL_TRACE_DEBUG("%s", __func__);
-
- // Find the peer sink for the codec
- const tBTA_AV_CO_SINK* p_sink = NULL;
- for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
- btav_a2dp_codec_index_t peer_codec_index =
- A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
- if (peer_codec_index != codec_config.codecIndex()) {
- continue;
- }
- if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) {
- APPL_TRACE_DEBUG(
- "%s: peer sink for codec %s does not support "
- "Copy Protection",
- __func__, codec_config.name().c_str());
- continue;
- }
- p_sink = &p_peer->sinks[index];
- break;
- }
- if (p_sink == NULL) {
- // The peer sink device does not support this codec
- return false;
- }
- if (!bta_av_co_cb.codecs->setCodecConfig(
- p_sink->codec_caps, true /* is_capability */, new_codec_config,
- false /* select_current_codec */)) {
- APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__,
- codec_config.name().c_str());
- return false;
- }
- return true;
-}
-
-static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
- const uint8_t* new_codec_config,
- uint8_t num_protect,
- const uint8_t* p_protect_info) {
- APPL_TRACE_DEBUG("%s", __func__);
- A2DP_DumpCodecInfo(new_codec_config);
-
- // Protect access to bta_av_co_cb.codec_config
- mutex_global_lock();
-
- memcpy(bta_av_co_cb.codec_config, new_codec_config,
- sizeof(bta_av_co_cb.codec_config));
- memcpy(p_peer->codec_config, new_codec_config, AVDT_CODEC_SIZE);
-
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- /* Check if this sink supports SCMS */
- bool cp_active =
- bta_av_co_audio_protect_has_scmst(num_protect, p_protect_info);
- bta_av_co_cb.cp.active = cp_active;
- p_peer->cp_active = cp_active;
-#endif
-
- // Protect access to bta_av_co_cb.codec_config
- mutex_global_unlock();
-}
-
-void bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params) {
+void BtaAvCo::GetPeerEncoderParameters(
+ const RawAddress& peer_address,
+ tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params) {
uint16_t min_mtu = 0xFFFF;
+ CHECK(p_peer_params != nullptr) << "Peer address " << peer_address;
- APPL_TRACE_DEBUG("%s", __func__);
- CHECK(p_peer_params != nullptr);
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_lock();
-
- /* Compute the MTU */
- for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
- const tBTA_AV_CO_PEER* p_peer = &bta_av_co_cb.peers[i];
+ // Compute the MTU
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ const BtaAvCoPeer* p_peer = &peers_[i];
if (!p_peer->opened) continue;
+ if (p_peer->addr != peer_address) continue;
if (p_peer->mtu < min_mtu) min_mtu = p_peer->mtu;
}
p_peer_params->peer_mtu = min_mtu;
- p_peer_params->is_peer_edr = btif_av_is_peer_edr();
- p_peer_params->peer_supports_3mbps = btif_av_peer_supports_3mbps();
-
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_unlock();
+ p_peer_params->is_peer_edr = btif_av_is_peer_edr(peer_address);
+ p_peer_params->peer_supports_3mbps =
+ btif_av_peer_supports_3mbps(peer_address);
+ APPL_TRACE_DEBUG(
+ "%s: peer_address=%s peer_mtu=%d is_peer_edr=%s peer_supports_3mbps=%s",
+ __func__, peer_address.ToString().c_str(), p_peer_params->peer_mtu,
+ logbool(p_peer_params->is_peer_edr).c_str(),
+ logbool(p_peer_params->peer_supports_3mbps).c_str());
}
-const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) {
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_lock();
+const tA2DP_ENCODER_INTERFACE* BtaAvCo::GetSourceEncoderInterface() {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
- const tA2DP_ENCODER_INTERFACE* encoder_interface =
- A2DP_GetEncoderInterface(bta_av_co_cb.codec_config);
-
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_unlock();
-
- return encoder_interface;
+ return A2DP_GetEncoderInterface(codec_config_);
}
-bool bta_av_co_set_codec_user_config(
+const tA2DP_DECODER_INTERFACE* BtaAvCo::GetSinkDecoderInterface() {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ return A2DP_GetDecoderInterface(codec_config_);
+}
+
+bool BtaAvCo::SetCodecUserConfig(
+ const RawAddress& peer_address,
const btav_a2dp_codec_config_t& codec_user_config) {
uint8_t result_codec_config[AVDT_CODEC_SIZE];
- const tBTA_AV_CO_SINK* p_sink = nullptr;
+ const BtaAvCoSep* p_sink = nullptr;
bool restart_input = false;
bool restart_output = false;
bool config_updated = false;
bool success = true;
- // Find the peer that is currently open
- tBTA_AV_CO_PEER* p_peer = nullptr;
- for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
- tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i];
- if (p_peer_tmp->opened) {
- p_peer = p_peer_tmp;
- break;
- }
- }
+ APPL_TRACE_DEBUG("%s: peer_address=%s codec_user_config=%s", __func__,
+ peer_address.ToString().c_str(),
+ codec_user_config.ToString().c_str());
+
+ BtaAvCoPeer* p_peer = FindPeer(peer_address);
if (p_peer == nullptr) {
- APPL_TRACE_ERROR("%s: no open peer to configure", __func__);
+ APPL_TRACE_ERROR("%s: cannot find peer %s to configure", __func__,
+ peer_address.ToString().c_str());
success = false;
goto done;
}
// Find the peer SEP codec to use
if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) {
- for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
- btav_a2dp_codec_index_t peer_codec_index =
- A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
- if (peer_codec_index != codec_user_config.codec_type) continue;
- if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue;
- p_sink = &p_peer->sinks[index];
- break;
- }
+ p_sink = FindPeerSink(p_peer, codec_user_config.codec_type);
} else {
// Use the current sink codec
p_sink = p_peer->p_sink;
}
if (p_sink == nullptr) {
- APPL_TRACE_ERROR("%s: cannot find peer SEP to configure for codec type %d",
- __func__, codec_user_config.codec_type);
+ APPL_TRACE_ERROR(
+ "%s: peer %s : cannot find peer SEP to configure for codec type %d",
+ __func__, p_peer->addr.ToString().c_str(),
+ codec_user_config.codec_type);
success = false;
goto done;
}
tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
- bta_av_co_get_peer_params(&peer_params);
- if (!bta_av_co_cb.codecs->setCodecUserConfig(
+ GetPeerEncoderParameters(p_peer->addr, &peer_params);
+ if (!p_peer->GetCodecs()->setCodecUserConfig(
codec_user_config, &peer_params, p_sink->codec_caps,
result_codec_config, &restart_input, &restart_output,
&config_updated)) {
@@ -1109,152 +1487,74 @@
if (restart_output) {
uint8_t num_protect = 0;
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN;
-#endif
+ if (ContentProtectEnabled() && p_peer->ContentProtectActive()) {
+ num_protect = AVDT_CP_INFO_LEN;
+ }
- p_sink = bta_av_co_audio_set_codec(p_peer);
- if (p_sink == NULL) {
- APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__);
+ p_sink = SelectSourceCodec(p_peer);
+ if (p_sink == nullptr) {
+ APPL_TRACE_ERROR("%s: peer %s : cannot set up codec for the peer SINK",
+ __func__, p_peer->addr.ToString().c_str());
success = false;
goto done;
}
// Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
(p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
- APPL_TRACE_WARNING("%s: not all peer's capabilities have been retrieved",
- __func__);
+ APPL_TRACE_WARNING(
+ "%s: peer %s : not all peer's capabilities have been retrieved",
+ __func__, p_peer->addr.ToString().c_str());
success = false;
goto done;
}
- APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, p_peer->handle);
- BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx,
+ p_peer->acceptor = false;
+ APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x)", __func__,
+ p_peer->BtaAvHandle());
+ BTA_AvReconfig(p_peer->BtaAvHandle(), true, p_sink->sep_info_idx,
p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
}
done:
- // NOTE: We uncoditionally send the upcall even if there is no change
+ // NOTE: We unconditionally send the upcall even if there is no change
// or the user config failed. Thus, the caller would always know whether the
// request succeeded or failed.
// NOTE: Currently, the input is restarted by sending an upcall
// and informing the Media Framework about the change.
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
+ if (p_peer != nullptr) {
+ return ReportSourceCodecState(p_peer);
+ }
return success;
}
-// Sets the Over-The-Air preferred codec configuration.
-// The OTA prefered codec configuration is ignored if the current
-// codec configuration contains explicit user configuration, or if the
-// codec configuration for the same codec contains explicit user
-// configuration.
-// |p_peer| is the peer device that sent the OTA codec configuration.
-// |p_ota_codec_config| contains the received OTA A2DP codec configuration
-// from the remote peer. Note: this is not the peer codec capability,
-// but the codec configuration that the peer would like to use.
-// |num_protect| is the number of content protection methods to use.
-// |p_protect_info| contains the content protection information to use.
-// If there is a change in the encoder configuration tht requires restarting
-// of the A2DP connection, flag |p_restart_output| is set to true.
-// Returns true on success, otherwise false.
-static bool bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER* p_peer,
- const uint8_t* p_ota_codec_config,
- uint8_t num_protect,
- const uint8_t* p_protect_info,
- bool* p_restart_output) {
- uint8_t result_codec_config[AVDT_CODEC_SIZE];
- bool restart_input = false;
- bool restart_output = false;
- bool config_updated = false;
-
- APPL_TRACE_DEBUG("%s", __func__);
- A2DP_DumpCodecInfo(p_ota_codec_config);
-
- *p_restart_output = false;
-
- // Find the peer SEP codec to use
- btav_a2dp_codec_index_t ota_codec_index =
- A2DP_SourceCodecIndex(p_ota_codec_config);
- if (ota_codec_index == BTAV_A2DP_CODEC_INDEX_MAX) {
- APPL_TRACE_WARNING("%s: invalid peer codec config", __func__);
- return false;
- }
- const tBTA_AV_CO_SINK* p_sink = nullptr;
- for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
- btav_a2dp_codec_index_t peer_codec_index =
- A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
- if (peer_codec_index != ota_codec_index) continue;
- if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue;
- p_sink = &p_peer->sinks[index];
- break;
- }
- if ((p_peer->num_sup_sinks > 0) && (p_sink == nullptr)) {
- // There are no peer SEPs if we didn't do the discovery procedure yet.
- // We have all the information we need from the peer, so we can
- // proceed with the OTA codec configuration.
- APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__);
- return false;
- }
-
- tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
- bta_av_co_get_peer_params(&peer_params);
- if (!bta_av_co_cb.codecs->setCodecOtaConfig(
- p_ota_codec_config, &peer_params, result_codec_config, &restart_input,
- &restart_output, &config_updated)) {
- APPL_TRACE_ERROR("%s: cannot set OTA config", __func__);
- return false;
- }
-
- if (restart_output) {
- APPL_TRACE_DEBUG("%s: restart output", __func__);
- A2DP_DumpCodecInfo(result_codec_config);
-
- *p_restart_output = true;
- p_peer->p_sink = p_sink;
- bta_av_co_save_new_codec_config(p_peer, result_codec_config, num_protect,
- p_protect_info);
- }
-
- if (restart_input || config_updated) {
- // NOTE: Currently, the input is restarted by sending an upcall
- // and informing the Media Framework about the change.
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
- }
-
- return true;
-}
-
-bool bta_av_co_set_codec_audio_config(
+bool BtaAvCo::SetCodecAudioConfig(
const btav_a2dp_codec_config_t& codec_audio_config) {
uint8_t result_codec_config[AVDT_CODEC_SIZE];
bool restart_output = false;
bool config_updated = false;
+ APPL_TRACE_DEBUG("%s: codec_audio_config: %s", __func__,
+ codec_audio_config.ToString().c_str());
+
// Find the peer that is currently open
- tBTA_AV_CO_PEER* p_peer = nullptr;
- for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
- tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i];
- if (p_peer_tmp->opened) {
- p_peer = p_peer_tmp;
- break;
- }
- }
+ BtaAvCoPeer* p_peer = active_peer_;
if (p_peer == nullptr) {
- APPL_TRACE_ERROR("%s: no open peer to configure", __func__);
+ APPL_TRACE_ERROR("%s: no active peer to configure", __func__);
return false;
}
// Use the current sink codec
- const tBTA_AV_CO_SINK* p_sink = p_peer->p_sink;
+ const BtaAvCoSep* p_sink = p_peer->p_sink;
if (p_sink == nullptr) {
- APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__);
+ APPL_TRACE_ERROR("%s: peer %s : cannot find peer SEP to configure",
+ __func__, p_peer->addr.ToString().c_str());
return false;
}
tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
- bta_av_co_get_peer_params(&peer_params);
- if (!bta_av_co_cb.codecs->setCodecAudioConfig(
+ GetPeerEncoderParameters(p_peer->addr, &peer_params);
+ if (!p_peer->GetCodecs()->setCodecAudioConfig(
codec_audio_config, &peer_params, p_sink->codec_caps,
result_codec_config, &restart_output, &config_updated)) {
return false;
@@ -1262,22 +1562,24 @@
if (restart_output) {
uint8_t num_protect = 0;
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN;
-#endif
+ if (ContentProtectEnabled() && p_peer->ContentProtectActive()) {
+ num_protect = AVDT_CP_INFO_LEN;
+ }
- bta_av_co_save_new_codec_config(p_peer, result_codec_config,
- p_sink->num_protect, p_sink->protect_info);
+ SaveNewCodecConfig(p_peer, result_codec_config, p_sink->num_protect,
+ p_sink->protect_info);
// Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
(p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
- APPL_TRACE_WARNING("%s: not all peer's capabilities have been retrieved",
- __func__);
+ APPL_TRACE_WARNING(
+ "%s: peer %s : not all peer's capabilities have been retrieved",
+ __func__, p_peer->addr.ToString().c_str());
} else {
- APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__,
- p_peer->handle);
- BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx,
+ p_peer->acceptor = false;
+ APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x)", __func__,
+ p_peer->BtaAvHandle());
+ BTA_AvReconfig(p_peer->BtaAvHandle(), true, p_sink->sep_info_idx,
p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
}
}
@@ -1285,50 +1587,575 @@
if (config_updated) {
// NOTE: Currently, the input is restarted by sending an upcall
// and informing the Media Framework about the change.
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
+ return ReportSourceCodecState(p_peer);
}
return true;
}
-A2dpCodecs* bta_av_get_a2dp_codecs(void) { return bta_av_co_cb.codecs; }
+bool BtaAvCo::ReportSourceCodecState(BtaAvCoPeer* p_peer) {
+ btav_a2dp_codec_config_t codec_config;
+ std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities;
+ std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities;
-A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) {
- A2dpCodecConfig* current_codec;
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ p_peer->addr.ToString().c_str());
+ A2dpCodecs* codecs = p_peer->GetCodecs();
+ CHECK(codecs != nullptr);
+ if (!codecs->getCodecConfigAndCapabilities(&codec_config,
+ &codecs_local_capabilities,
+ &codecs_selectable_capabilities)) {
+ APPL_TRACE_WARNING(
+ "%s: Peer %s : error reporting audio source codec state: "
+ "cannot get codec config and capabilities",
+ __func__, p_peer->addr.ToString().c_str());
+ return false;
+ }
+ APPL_TRACE_DEBUG("%s: peer %s codec_config=%s", __func__,
+ p_peer->addr.ToString().c_str(),
+ codec_config.ToString().c_str());
+ btif_av_report_source_codec_state(p_peer->addr, codec_config,
+ codecs_local_capabilities,
+ codecs_selectable_capabilities);
+ return true;
+}
- mutex_global_lock();
- if (bta_av_co_cb.codecs == nullptr) {
- mutex_global_unlock();
+bool BtaAvCo::ReportSinkCodecState(BtaAvCoPeer* p_peer) {
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ p_peer->addr.ToString().c_str());
+ // Nothing to do (for now)
+ return true;
+}
+void BtaAvCo::DebugDump(int fd) {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ dprintf(fd, "\nA2DP Codecs and Peers State:\n");
+ dprintf(fd, " Active peer: %s\n",
+ (active_peer_ != nullptr) ? active_peer_->addr.ToString().c_str()
+ : "null");
+
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ const BtaAvCoPeer& peer = peers_[i];
+ dprintf(fd, " Peer: %s\n", peer.addr.ToString().c_str());
+ dprintf(fd, " Number of sinks: %u\n", peer.num_sinks);
+ dprintf(fd, " Number of sources: %u\n", peer.num_sources);
+ dprintf(fd, " Number of SEPs: %u\n", peer.num_seps);
+ dprintf(fd, " Number of received sinks: %u\n", peer.num_rx_sinks);
+ dprintf(fd, " Number of received sources: %u\n", peer.num_rx_sources);
+ dprintf(fd, " Number of supported sinks: %u\n", peer.num_sup_sinks);
+ dprintf(fd, " Number of supported sources: %u\n", peer.num_sup_sources);
+ dprintf(fd, " Acceptor: %s\n", (peer.acceptor) ? "true" : "false");
+ dprintf(fd, " Reconfig needed: %s\n",
+ (peer.reconfig_needed) ? "true" : "false");
+ dprintf(fd, " Opened: %s\n", (peer.opened) ? "true" : "false");
+ dprintf(fd, " MTU: %u\n", peer.mtu);
+ dprintf(fd, " UUID to connect: 0x%x\n", peer.uuid_to_connect);
+ dprintf(fd, " BTA AV handle: %u\n", peer.BtaAvHandle());
+ }
+
+ //
+ // Active peer codec-specific stats
+ //
+ if (active_peer_ != nullptr) {
+ A2dpCodecs* a2dp_codecs = active_peer_->GetCodecs();
+ if (a2dp_codecs != nullptr) {
+ a2dp_codecs->debug_codec_dump(fd);
+ }
+ }
+}
+
+bool BtaAvCo::ContentProtectIsScmst(const uint8_t* p_protect_info) {
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ if (*p_protect_info >= AVDT_CP_LOSC) {
+ uint16_t cp_id;
+ p_protect_info++;
+ STREAM_TO_UINT16(cp_id, p_protect_info);
+ if (cp_id == AVDT_CP_SCMS_T_ID) {
+ APPL_TRACE_DEBUG("%s: SCMS-T found", __func__);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BtaAvCo::AudioProtectHasScmst(uint8_t num_protect,
+ const uint8_t* p_protect_info) {
+ APPL_TRACE_DEBUG("%s", __func__);
+ while (num_protect--) {
+ if (BtaAvCo::ContentProtectIsScmst(p_protect_info)) return true;
+ // Move to the next Content Protect schema
+ p_protect_info += *p_protect_info + 1;
+ }
+ APPL_TRACE_DEBUG("%s: SCMS-T not found", __func__);
+ return false;
+}
+
+bool BtaAvCo::AudioSepHasContentProtection(const BtaAvCoSep* p_sep) {
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ // Check if content protection is enabled for this stream
+ if (ContentProtectFlag() != AVDT_CP_SCMS_COPY_FREE) {
+ return BtaAvCo::AudioProtectHasScmst(p_sep->num_protect,
+ p_sep->protect_info);
+ }
+
+ APPL_TRACE_DEBUG("%s: not required", __func__);
+ return true;
+}
+
+const BtaAvCoSep* BtaAvCo::SelectSourceCodec(BtaAvCoPeer* p_peer) {
+ const BtaAvCoSep* p_sink = nullptr;
+
+ // Update all selectable codecs.
+ // This is needed to update the selectable parameters for each codec.
+ // NOTE: The selectable codec info is used only for informational purpose.
+ UpdateAllSelectableSourceCodecs(p_peer);
+
+ // Select the codec
+ for (const auto& iter : p_peer->GetCodecs()->orderedSourceCodecs()) {
+ APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str());
+ p_sink = AttemptSourceCodecSelection(*iter, p_peer);
+ if (p_sink != nullptr) {
+ APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str());
+ break;
+ }
+ APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str());
+ }
+
+ // NOTE: Unconditionally dispatch the event to make sure a callback with
+ // the most recent codec info is generated.
+ ReportSourceCodecState(p_peer);
+
+ return p_sink;
+}
+
+const BtaAvCoSep* BtaAvCo::SelectSinkCodec(BtaAvCoPeer* p_peer) {
+ const BtaAvCoSep* p_source = nullptr;
+
+ // Update all selectable codecs.
+ // This is needed to update the selectable parameters for each codec.
+ // NOTE: The selectable codec info is used only for informational purpose.
+ UpdateAllSelectableSinkCodecs(p_peer);
+
+ // Select the codec
+ for (const auto& iter : p_peer->GetCodecs()->orderedSinkCodecs()) {
+ APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str());
+ p_source = AttemptSinkCodecSelection(*iter, p_peer);
+ if (p_source != nullptr) {
+ APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str());
+ break;
+ }
+ APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str());
+ }
+
+ // NOTE: Unconditionally dispatch the event to make sure a callback with
+ // the most recent codec info is generated.
+ ReportSinkCodecState(p_peer);
+
+ return p_source;
+}
+
+BtaAvCoSep* BtaAvCo::FindPeerSink(BtaAvCoPeer* p_peer,
+ btav_a2dp_codec_index_t codec_index) {
+ if (codec_index == BTAV_A2DP_CODEC_INDEX_MAX) {
+ APPL_TRACE_WARNING("%s: invalid codec index for peer %s", __func__,
+ p_peer->addr.ToString().c_str());
return nullptr;
}
- current_codec = bta_av_co_cb.codecs->getCurrentCodecConfig();
- mutex_global_unlock();
- return current_codec;
+ // Find the peer Sink for the codec
+ for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
+ BtaAvCoSep* p_sink = &p_peer->sinks[index];
+ btav_a2dp_codec_index_t peer_codec_index =
+ A2DP_SourceCodecIndex(p_sink->codec_caps);
+ if (peer_codec_index != codec_index) {
+ continue;
+ }
+ if (!AudioSepHasContentProtection(p_sink)) {
+ APPL_TRACE_DEBUG(
+ "%s: peer Sink for codec %s does not support "
+ "Content Protection",
+ __func__, A2DP_CodecIndexStr(codec_index));
+ continue;
+ }
+ return p_sink;
+ }
+ return nullptr;
+}
+
+BtaAvCoSep* BtaAvCo::FindPeerSource(BtaAvCoPeer* p_peer,
+ btav_a2dp_codec_index_t codec_index) {
+ if (codec_index == BTAV_A2DP_CODEC_INDEX_MAX) {
+ APPL_TRACE_WARNING("%s: invalid codec index for peer %s", __func__,
+ p_peer->addr.ToString().c_str());
+ return nullptr;
+ }
+
+ // Find the peer Source for the codec
+ for (size_t index = 0; index < p_peer->num_sup_sources; index++) {
+ BtaAvCoSep* p_source = &p_peer->sources[index];
+ btav_a2dp_codec_index_t peer_codec_index =
+ A2DP_SinkCodecIndex(p_source->codec_caps);
+ if (peer_codec_index != codec_index) {
+ continue;
+ }
+ if (!AudioSepHasContentProtection(p_source)) {
+ APPL_TRACE_DEBUG(
+ "%s: peer Source for codec %s does not support "
+ "Content Protection",
+ __func__, A2DP_CodecIndexStr(codec_index));
+ continue;
+ }
+ return p_source;
+ }
+ return nullptr;
+}
+
+const BtaAvCoSep* BtaAvCo::AttemptSourceCodecSelection(
+ const A2dpCodecConfig& codec_config, BtaAvCoPeer* p_peer) {
+ uint8_t new_codec_config[AVDT_CODEC_SIZE];
+
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ // Find the peer Sink for the codec
+ BtaAvCoSep* p_sink = FindPeerSink(p_peer, codec_config.codecIndex());
+ if (p_sink == nullptr) {
+ APPL_TRACE_DEBUG("%s: peer Sink for codec %s not found", __func__,
+ codec_config.name().c_str());
+ return nullptr;
+ }
+ if (!p_peer->GetCodecs()->setCodecConfig(
+ p_sink->codec_caps, true /* is_capability */, new_codec_config,
+ true /* select_current_codec */)) {
+ APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
+ codec_config.name().c_str());
+ return nullptr;
+ }
+ p_peer->p_sink = p_sink;
+
+ SaveNewCodecConfig(p_peer, new_codec_config, p_sink->num_protect,
+ p_sink->protect_info);
+
+ return p_sink;
+}
+
+const BtaAvCoSep* BtaAvCo::AttemptSinkCodecSelection(
+ const A2dpCodecConfig& codec_config, BtaAvCoPeer* p_peer) {
+ uint8_t new_codec_config[AVDT_CODEC_SIZE];
+
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ // Find the peer Source for the codec
+ BtaAvCoSep* p_source = FindPeerSource(p_peer, codec_config.codecIndex());
+ if (p_source == nullptr) {
+ APPL_TRACE_DEBUG("%s: peer Source for codec %s not found", __func__,
+ codec_config.name().c_str());
+ return nullptr;
+ }
+ if (!p_peer->GetCodecs()->setSinkCodecConfig(
+ p_source->codec_caps, true /* is_capability */, new_codec_config,
+ true /* select_current_codec */)) {
+ APPL_TRACE_DEBUG("%s: cannot set sink codec %s", __func__,
+ codec_config.name().c_str());
+ return nullptr;
+ }
+ p_peer->p_source = p_source;
+
+ SaveNewCodecConfig(p_peer, new_codec_config, p_source->num_protect,
+ p_source->protect_info);
+
+ return p_source;
+}
+
+size_t BtaAvCo::UpdateAllSelectableSourceCodecs(BtaAvCoPeer* p_peer) {
+ APPL_TRACE_DEBUG("%s: peer %s", __func__, p_peer->addr.ToString().c_str());
+
+ size_t updated_codecs = 0;
+ for (const auto& iter : p_peer->GetCodecs()->orderedSourceCodecs()) {
+ APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__,
+ iter->name().c_str());
+ if (UpdateSelectableSourceCodec(*iter, p_peer)) {
+ updated_codecs++;
+ }
+ }
+ return updated_codecs;
+}
+
+bool BtaAvCo::UpdateSelectableSourceCodec(const A2dpCodecConfig& codec_config,
+ BtaAvCoPeer* p_peer) {
+ APPL_TRACE_DEBUG("%s: peer %s", __func__, p_peer->addr.ToString().c_str());
+
+ // Find the peer Sink for the codec
+ const BtaAvCoSep* p_sink = FindPeerSink(p_peer, codec_config.codecIndex());
+ if (p_sink == nullptr) {
+ // The peer Sink device does not support this codec
+ return false;
+ }
+ if (!p_peer->GetCodecs()->setPeerSinkCodecCapabilities(p_sink->codec_caps)) {
+ APPL_TRACE_WARNING("%s: cannot update peer %s codec capabilities for %s",
+ __func__, p_peer->addr.ToString().c_str(),
+ A2DP_CodecName(p_sink->codec_caps));
+ return false;
+ }
+ return true;
+}
+
+size_t BtaAvCo::UpdateAllSelectableSinkCodecs(BtaAvCoPeer* p_peer) {
+ APPL_TRACE_DEBUG("%s: peer %s", __func__, p_peer->addr.ToString().c_str());
+
+ size_t updated_codecs = 0;
+ for (const auto& iter : p_peer->GetCodecs()->orderedSinkCodecs()) {
+ APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__,
+ iter->name().c_str());
+ if (UpdateSelectableSinkCodec(*iter, p_peer)) {
+ updated_codecs++;
+ }
+ }
+ return updated_codecs;
+}
+
+bool BtaAvCo::UpdateSelectableSinkCodec(const A2dpCodecConfig& codec_config,
+ BtaAvCoPeer* p_peer) {
+ APPL_TRACE_DEBUG("%s: peer %s", __func__, p_peer->addr.ToString().c_str());
+
+ // Find the peer Source for the codec
+ const BtaAvCoSep* p_source =
+ FindPeerSource(p_peer, codec_config.codecIndex());
+ if (p_source == nullptr) {
+ // The peer Source device does not support this codec
+ return false;
+ }
+ if (!p_peer->GetCodecs()->setPeerSourceCodecCapabilities(
+ p_source->codec_caps)) {
+ APPL_TRACE_WARNING("%s: cannot update peer %s codec capabilities for %s",
+ __func__, p_peer->addr.ToString().c_str(),
+ A2DP_CodecName(p_source->codec_caps));
+ return false;
+ }
+ return true;
+}
+
+void BtaAvCo::SaveNewCodecConfig(BtaAvCoPeer* p_peer,
+ const uint8_t* new_codec_config,
+ uint8_t num_protect,
+ const uint8_t* p_protect_info) {
+ APPL_TRACE_DEBUG("%s: peer %s", __func__, p_peer->addr.ToString().c_str());
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(new_codec_config).c_str());
+
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ memcpy(codec_config_, new_codec_config, sizeof(codec_config_));
+ memcpy(p_peer->codec_config, new_codec_config, AVDT_CODEC_SIZE);
+
+ if (ContentProtectEnabled()) {
+ // Check if this Sink supports SCMS
+ bool cp_active = BtaAvCo::AudioProtectHasScmst(num_protect, p_protect_info);
+ p_peer->SetContentProtectActive(cp_active);
+ }
+}
+
+bool BtaAvCo::SetCodecOtaConfig(BtaAvCoPeer* p_peer,
+ const uint8_t* p_ota_codec_config,
+ uint8_t num_protect,
+ const uint8_t* p_protect_info,
+ bool* p_restart_output) {
+ uint8_t result_codec_config[AVDT_CODEC_SIZE];
+ bool restart_input = false;
+ bool restart_output = false;
+ bool config_updated = false;
+
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ p_peer->addr.ToString().c_str());
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_ota_codec_config).c_str());
+
+ *p_restart_output = false;
+
+ // Find the peer SEP codec to use
+ const BtaAvCoSep* p_sink =
+ FindPeerSink(p_peer, A2DP_SourceCodecIndex(p_ota_codec_config));
+ if ((p_peer->num_sup_sinks > 0) && (p_sink == nullptr)) {
+ // There are no peer SEPs if we didn't do the discovery procedure yet.
+ // We have all the information we need from the peer, so we can
+ // proceed with the OTA codec configuration.
+ APPL_TRACE_ERROR("%s: peer %s : cannot find peer SEP to configure",
+ __func__, p_peer->addr.ToString().c_str());
+ return false;
+ }
+
+ tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
+ GetPeerEncoderParameters(p_peer->addr, &peer_params);
+ if (!p_peer->GetCodecs()->setCodecOtaConfig(
+ p_ota_codec_config, &peer_params, result_codec_config, &restart_input,
+ &restart_output, &config_updated)) {
+ APPL_TRACE_ERROR("%s: peer %s : cannot set OTA config", __func__,
+ p_peer->addr.ToString().c_str());
+ return false;
+ }
+
+ if (restart_output) {
+ APPL_TRACE_DEBUG("%s: restart output", __func__);
+ APPL_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(result_codec_config).c_str());
+
+ *p_restart_output = true;
+ p_peer->p_sink = p_sink;
+ SaveNewCodecConfig(p_peer, result_codec_config, num_protect,
+ p_protect_info);
+ }
+
+ if (restart_input || config_updated) {
+ // NOTE: Currently, the input is restarted by sending an upcall
+ // and informing the Media Framework about the change.
+ ReportSourceCodecState(p_peer);
+ }
+
+ return true;
}
void bta_av_co_init(
const std::vector<btav_a2dp_codec_config_t>& codec_priorities) {
- APPL_TRACE_DEBUG("%s", __func__);
-
- /* Reset the control block */
- bta_av_co_cb.reset();
-
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_NEVER);
-#else
- bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_FREE);
-#endif
-
- /* Reset the current config */
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_lock();
- bta_av_co_cb.codecs = new A2dpCodecs(codec_priorities);
- bta_av_co_cb.codecs->init();
- A2DP_InitDefaultCodec(bta_av_co_cb.codec_config);
- mutex_global_unlock();
-
- // NOTE: Unconditionally dispatch the event to make sure a callback with
- // the most recent codec info is generated.
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
+ bta_av_co_cb.Init(codec_priorities);
}
+
+A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) {
+ return bta_av_co_cb.GetActivePeerCurrentCodec();
+}
+
+A2dpCodecConfig* bta_av_get_a2dp_peer_current_codec(
+ const RawAddress& peer_address) {
+ return bta_av_co_cb.GetPeerCurrentCodec(peer_address);
+}
+
+bool bta_av_co_audio_init(btav_a2dp_codec_index_t codec_index,
+ AvdtpSepConfig* p_cfg) {
+ return A2DP_InitCodecConfig(codec_index, p_cfg);
+}
+
+void bta_av_co_audio_disc_res(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint8_t num_seps,
+ uint8_t num_sinks, uint8_t num_sources,
+ uint16_t uuid_local) {
+ bta_av_co_cb.ProcessDiscoveryResult(bta_av_handle, peer_address, num_seps,
+ num_sinks, num_sources, uuid_local);
+}
+
+tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
+ uint8_t* p_sep_info_idx, uint8_t seid,
+ uint8_t* p_num_protect,
+ uint8_t* p_protect_info) {
+ uint16_t peer_uuid = bta_av_co_cb.FindPeerUuid(bta_av_handle);
+
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle=0x%x peer_uuid=0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle, peer_uuid);
+
+ switch (peer_uuid) {
+ case UUID_SERVCLASS_AUDIO_SOURCE:
+ return bta_av_co_cb.ProcessSinkGetConfig(
+ bta_av_handle, peer_address, p_codec_info, p_sep_info_idx, seid,
+ p_num_protect, p_protect_info);
+ case UUID_SERVCLASS_AUDIO_SINK:
+ return bta_av_co_cb.ProcessSourceGetConfig(
+ bta_av_handle, peer_address, p_codec_info, p_sep_info_idx, seid,
+ p_num_protect, p_protect_info);
+ default:
+ break;
+ }
+ APPL_TRACE_ERROR(
+ "%s: peer %s : Invalid peer UUID: 0x%x for bta_av_handle 0x%x",
+ peer_address.ToString().c_str(), peer_uuid, bta_av_handle);
+ return A2DP_FAIL;
+}
+
+void bta_av_co_audio_setconfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, uint8_t seid,
+ uint8_t num_protect,
+ const uint8_t* p_protect_info,
+ uint8_t t_local_sep, uint8_t avdt_handle) {
+ bta_av_co_cb.ProcessSetConfig(bta_av_handle, peer_address, p_codec_info, seid,
+ num_protect, p_protect_info, t_local_sep,
+ avdt_handle);
+}
+
+void bta_av_co_audio_open(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu) {
+ bta_av_co_cb.ProcessOpen(bta_av_handle, peer_address, mtu);
+}
+
+void bta_av_co_audio_close(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ bta_av_co_cb.ProcessClose(bta_av_handle, peer_address);
+}
+
+void bta_av_co_audio_start(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, bool* p_no_rtp_header) {
+ bta_av_co_cb.ProcessStart(bta_av_handle, peer_address, p_codec_info,
+ p_no_rtp_header);
+}
+
+void bta_av_co_audio_stop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ bta_av_co_cb.ProcessStop(bta_av_handle, peer_address);
+}
+
+BT_HDR* bta_av_co_audio_source_data_path(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp) {
+ return bta_av_co_cb.GetNextSourceDataPacket(p_codec_info, p_timestamp);
+}
+
+void bta_av_co_audio_drop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ bta_av_co_cb.DataPacketWasDropped(bta_av_handle, peer_address);
+}
+
+void bta_av_co_audio_delay(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t delay) {
+ bta_av_co_cb.ProcessAudioDelay(bta_av_handle, peer_address, delay);
+}
+
+void bta_av_co_audio_update_mtu(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu) {
+ bta_av_co_cb.UpdateMtu(bta_av_handle, peer_address, mtu);
+}
+
+bool bta_av_co_set_active_peer(const RawAddress& peer_address) {
+ return bta_av_co_cb.SetActivePeer(peer_address);
+}
+
+void bta_av_co_get_peer_params(const RawAddress& peer_address,
+ tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params) {
+ bta_av_co_cb.GetPeerEncoderParameters(peer_address, p_peer_params);
+}
+
+const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) {
+ return bta_av_co_cb.GetSourceEncoderInterface();
+}
+
+const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void) {
+ return bta_av_co_cb.GetSinkDecoderInterface();
+}
+
+bool bta_av_co_set_codec_user_config(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_user_config) {
+ return bta_av_co_cb.SetCodecUserConfig(peer_address, codec_user_config);
+}
+
+bool bta_av_co_set_codec_audio_config(
+ const btav_a2dp_codec_config_t& codec_audio_config) {
+ return bta_av_co_cb.SetCodecAudioConfig(codec_audio_config);
+}
+
+bool bta_av_co_content_protect_is_active(const RawAddress& peer_address) {
+ BtaAvCoPeer* p_peer = bta_av_co_cb.FindPeer(peer_address);
+ CHECK(p_peer != nullptr);
+ return p_peer->ContentProtectActive();
+}
+
+void btif_a2dp_codec_debug_dump(int fd) { bta_av_co_cb.DebugDump(fd); }
diff --git a/btif/co/bta_dm_co.cc b/btif/co/bta_dm_co.cc
index f6c7c1c..dfd512b 100644
--- a/btif/co/bta_dm_co.cc
+++ b/btif/co/bta_dm_co.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -165,99 +165,6 @@
bta_dm_ci_rmt_oob(result, bd_addr, p_c, p_r);
}
-// REMOVE FOR BLUEDROID ?
-
-#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTM_SCO_INCLUDED == TRUE)
-
-/*******************************************************************************
- *
- * Function btui_sco_codec_callback
- *
- * Description Callback for btui codec.
- *
- *
- * Returns void
- *
- ******************************************************************************/
-static void btui_sco_codec_callback(uint16_t event, uint16_t sco_handle) {
- bta_dm_sco_ci_data_ready(event, sco_handle);
-}
-
-/*******************************************************************************
- *
- * Function bta_dm_sco_co_open
- *
- * Description This function is executed when a SCO connection is open.
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_sco_co_open(uint16_t handle, uint8_t pkt_size, uint16_t event) {
- tBTUI_SCO_CODEC_CFG cfg;
-
- if (btui_cb.sco_hci) {
- BTIF_TRACE_DEBUG("bta_dm_sco_co_open handle:%d pkt_size:%d", handle,
- pkt_size);
- cfg.p_cback = btui_sco_codec_callback;
- cfg.pkt_size = pkt_size;
- cfg.cb_event = event;
- /* open and start the codec */
- btui_sco_codec_open(&cfg);
- btui_sco_codec_start(handle);
- }
-}
-
-/*******************************************************************************
- *
- * Function bta_dm_sco_co_close
- *
- * Description This function is called when a SCO connection is closed
- *
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_sco_co_close(void) {
- if (btui_cb.sco_hci) {
- BTIF_TRACE_DEBUG("bta_dm_sco_co_close close codec");
- /* close sco codec */
- btui_sco_codec_close();
-
- btui_cb.sco_hci = false;
- }
-}
-
-/*******************************************************************************
- *
- * Function bta_dm_sco_co_in_data
- *
- * Description This function is called to send incoming SCO data to
- * application.
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_sco_co_in_data(BT_HDR* p_buf) {
- if (btui_cfg.sco_use_mic)
- btui_sco_codec_inqdata(p_buf);
- else
- osi_free(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function bta_dm_sco_co_out_data
- *
- * Description This function is called to send SCO data over HCI.
- *
- * Returns void
- *
- ******************************************************************************/
-void bta_dm_sco_co_out_data(BT_HDR** p_buf) { btui_sco_codec_readbuf(p_buf); }
-
-#endif /* (BTM_SCO_HCI_INCLUDED == TRUE) && (BTM_SCO_INCLUDED == TRUE)*/
-
/*******************************************************************************
*
* Function bta_dm_co_le_io_key_req
diff --git a/btif/co/bta_gatts_co.cc b/btif/co/bta_gatts_co.cc
index 0466291..4fc308e 100644
--- a/btif/co/bta_gatts_co.cc
+++ b/btif/co/bta_gatts_co.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@
typedef struct {
bool enable;
uint8_t num_clients;
- tBTA_GATTS_SRV_CHG srv_chg[BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE];
+ tGATTS_SRV_CHG srv_chg[BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE];
} __attribute__((packed)) btif_gatts_srv_chg_cb_t;
/*****************************************************************************
@@ -121,9 +121,9 @@
* false - if the request can not be processed
*
******************************************************************************/
-bool bta_gatts_co_srv_chg(UNUSED_ATTR tBTA_GATTS_SRV_CHG_CMD cmd,
- UNUSED_ATTR tBTA_GATTS_SRV_CHG_REQ* p_req,
- UNUSED_ATTR tBTA_GATTS_SRV_CHG_RSP* p_rsp) {
+bool bta_gatts_co_srv_chg(UNUSED_ATTR tGATTS_SRV_CHG_CMD cmd,
+ UNUSED_ATTR tGATTS_SRV_CHG_REQ* p_req,
+ UNUSED_ATTR tGATTS_SRV_CHG_RSP* p_rsp) {
return false;
}
diff --git a/btif/co/bta_hh_co.cc b/btif/co/bta_hh_co.cc
index f6bc7cf..2f507f9 100644
--- a/btif/co/bta_hh_co.cc
+++ b/btif/co/bta_hh_co.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -473,12 +473,9 @@
// Create and send hid descriptor to kernel
memset(&ev, 0, sizeof(ev));
ev.type = UHID_CREATE;
- strncpy((char*)ev.u.create.name, dev_name, sizeof(ev.u.create.name) - 1);
- snprintf((char*)ev.u.create.uniq, sizeof(ev.u.create.uniq),
- "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", p_dev->bd_addr.address[5],
- p_dev->bd_addr.address[4], p_dev->bd_addr.address[3],
- p_dev->bd_addr.address[2], p_dev->bd_addr.address[1],
- p_dev->bd_addr.address[0]);
+ strlcpy((char*)ev.u.create.name, dev_name, sizeof(ev.u.create.name));
+ snprintf((char*)ev.u.create.uniq, sizeof(ev.u.create.uniq), "%s",
+ p_dev->bd_addr.ToString().c_str());
ev.u.create.rd_size = dscp_len;
ev.u.create.rd_data = p_dscp;
ev.u.create.bus = BUS_BLUETOOTH;
@@ -565,7 +562,7 @@
const char* bdstr = addrstr.c_str();
size_t len = btif_config_get_bin_length(bdstr, "HidReport");
- if (!p_num_rpt && len < sizeof(tBTA_HH_RPT_CACHE_ENTRY)) return NULL;
+ if (!p_num_rpt || len < sizeof(tBTA_HH_RPT_CACHE_ENTRY)) return NULL;
if (len > sizeof(sReportCache)) len = sizeof(sReportCache);
btif_config_get_bin(bdstr, "HidReport", (uint8_t*)sReportCache, &len);
diff --git a/btif/co/bta_hl_co.cc b/btif/co/bta_hl_co.cc
index a4ddbb6..c818351 100644
--- a/btif/co/bta_hl_co.cc
+++ b/btif/co/bta_hl_co.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/co/bta_pan_co.cc b/btif/co/bta_pan_co.cc
index 1868c78..a799d93 100644
--- a/btif/co/bta_pan_co.cc
+++ b/btif/co/bta_pan_co.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_a2dp.h b/btif/include/btif_a2dp.h
index 26f370a..7b7b2ca 100644
--- a/btif/include/btif_a2dp.h
+++ b/btif/include/btif_a2dp.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,11 +29,13 @@
// Process 'start' request from the BTIF state machine to prepare for A2DP
// streaming.
+// |peer_addr| is the peer address.
// |p_av_start| is the data associated with the request - see |tBTA_AV_START|.
// |pending_start| should be set to true if the BTIF state machine is in
// 'pending start' state.
// Returns true if an ACK for the local command was sent, otherwise false.
-bool btif_a2dp_on_started(tBTA_AV_START* p_av_start, bool pending_start);
+bool btif_a2dp_on_started(const RawAddress& peer_addr,
+ tBTA_AV_START* p_av_start, bool pending_start);
// Process 'stop' request from the BTIF state machine to stop A2DP streaming.
// |p_av_suspend| is the data associated with the request - see
@@ -48,10 +50,12 @@
// Process 'offload start' request from the BTIF state machine to start
// offloading of the A2DP streaming.
+// |peer_addr| is the peer address.
// |status| is the processing status of the request prior to this call.
// The value can be |BTA_AV_SUCCESS| if the processing has been successful
// so far, or |BTA_AV_FAIL*| if the request has already failed.
-void btif_a2dp_on_offload_started(tBTA_AV_STATUS status);
+void btif_a2dp_on_offload_started(const RawAddress& peer_addr,
+ tBTA_AV_STATUS status);
// Dump debug-related information for the A2DP module.
// |fd| is the file descriptor to use for writing the ASCII formatted
diff --git a/btif/include/btif_a2dp_audio_interface.h b/btif/include/btif_a2dp_audio_interface.h
new file mode 100644
index 0000000..d9babaa
--- /dev/null
+++ b/btif/include/btif_a2dp_audio_interface.h
@@ -0,0 +1,35 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef BTIF_A2DP_AUDIO_INTERFACE_H
+#define BTIF_A2DP_AUDIO_INTERFACE_H
+
+#include "bta_av_api.h"
+
+/*Default LDAC bitrate */
+#define DEFAULT_LDAC_BITRATE_48KHZ 660000
+#define DEFAULT_LDAC_BITRATE_441KHZ 606000
+
+void btif_a2dp_audio_on_started(tBTA_AV_STATUS status);
+void btif_a2dp_audio_on_stopped(tBTA_AV_STATUS status);
+void btif_a2dp_audio_on_suspended(tBTA_AV_STATUS status);
+void btif_a2dp_audio_interface_start_session(void);
+void btif_a2dp_audio_interface_end_session(void);
+
+#endif /* BTIF_A2DP_AUDIO_INTERFACE_H */
diff --git a/btif/include/btif_a2dp_control.h b/btif/include/btif_a2dp_control.h
index fb935f5..37a0f1b 100644
--- a/btif/include/btif_a2dp_control.h
+++ b/btif/include/btif_a2dp_control.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,4 +34,17 @@
// |status| is the acknowledement status - see |tA2DP_CTRL_ACK|.
void btif_a2dp_command_ack(tA2DP_CTRL_ACK status);
+// Increment the total number audio data bytes that have been encoded since
+// last encoding attempt.
+// |bytes_read| is the number of bytes to increment by.
+void btif_a2dp_control_log_bytes_read(uint32_t bytes_read);
+
+// Set the audio delay reported to the audio HAL in uints of 1/10ms.
+// |delay| is the audio delay to set.
+void btif_a2dp_control_set_audio_delay(uint16_t delay);
+
+// Reset the remote audio device's delay value and reset the counter that keeps
+// track of the number of audio bytes sent
+void btif_a2dp_control_reset_audio_delay(void);
+
#endif /* BTIF_A2DP_CONTROL_H */
diff --git a/btif/include/btif_a2dp_sink.h b/btif/include/btif_a2dp_sink.h
index 5057a39..25e65f4 100644
--- a/btif/include/btif_a2dp_sink.h
+++ b/btif/include/btif_a2dp_sink.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,16 +38,47 @@
BTIF_A2DP_SINK_FOCUS_GRANTED = 1
} btif_a2dp_sink_focus_state_t;
-// Initialize and startup the A2DP Sink module.
+// Initialize the A2DP Sink module.
// This function should be called by the BTIF state machine prior to using the
// module.
+bool btif_a2dp_sink_init(void);
+
+// Startup the A2DP Sink module.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_sink_init() to prepare for receiving and processing audio
+// streaming.
bool btif_a2dp_sink_startup(void);
-// Shutdown and cleanup the A2DP Sink module.
-// This function should be called by the BTIF state machine during
-// graceful shutdown and cleanup.
+// Start the A2DP Sink session.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_sink_startup() to start the streaming session for |peer_address|.
+bool btif_a2dp_sink_start_session(const RawAddress& peer_address);
+
+// Restart the A2DP Sink session.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_sink_startup() to restart the streaming session.
+// |old_peer_address| is the peer address of the old session. This address
+// can be empty.
+// |new_peer_address| is the peer address of the new session. This address
+// cannot be empty.
+bool btif_a2dp_sink_restart_session(const RawAddress& old_peer_address,
+ const RawAddress& new_peer_address);
+
+// End the A2DP Sink session.
+// This function should be called by the BTIF state machine to end the
+// streaming session for |peer_address|.
+bool btif_a2dp_sink_end_session(const RawAddress& peer_address);
+
+// Shutdown the A2DP Sink module.
+// This function should be called by the BTIF state machine before
+// btif_a2dp_sink_cleanup() to shutdown the processing of the audio streaming.
void btif_a2dp_sink_shutdown(void);
+// Cleanup the A2DP Sink module.
+// This function should be called by the BTIF state machine during graceful
+// cleanup.
+void btif_a2dp_sink_cleanup(void);
+
// Get the audio sample rate for the A2DP Sink module.
tA2DP_SAMPLE_RATE btif_a2dp_sink_get_sample_rate(void);
@@ -88,10 +119,6 @@
// information.
void btif_a2dp_sink_debug_dump(int fd);
-// Update the A2DP Sink related metrics.
-// This function should be called before collecting the metrics.
-void btif_a2dp_sink_update_metrics(void);
-
// Create a request to set the audio focus state for the audio track.
// |state| is the new state value - see |btif_a2dp_sink_focus_state_t|
// for valid values.
diff --git a/btif/include/btif_a2dp_source.h b/btif/include/btif_a2dp_source.h
index 2f1763d..bb96e1a 100644
--- a/btif/include/btif_a2dp_source.h
+++ b/btif/include/btif_a2dp_source.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,16 +24,45 @@
#include "bta_av_api.h"
-// Initialize and startup the A2DP Source module.
+// Initialize the A2DP Source module.
// This function should be called by the BTIF state machine prior to using the
// module.
+bool btif_a2dp_source_init(void);
+
+// Startup the A2DP Source module.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_source_init() to prepare to start streaming.
bool btif_a2dp_source_startup(void);
-// Shutdown and cleanup the A2DP Source module.
-// This function should be called by the BTIF state machine during
-// graceful shutdown and cleanup.
+// Start the A2DP Source session.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_source_startup() to start the streaming session for |peer_address|.
+bool btif_a2dp_source_start_session(const RawAddress& peer_address);
+
+// Restart the A2DP Source session.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_source_startup() to restart the streaming session.
+// |old_peer_address| is the peer address of the old session. This address
+// can be empty.
+// |new_peer_address| is the peer address of the new session. This address
+// cannot be empty.
+bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address,
+ const RawAddress& new_peer_address);
+
+// End the A2DP Source session.
+// This function should be called by the BTIF state machine to end the
+// streaming session for |peer_address|.
+bool btif_a2dp_source_end_session(const RawAddress& peer_address);
+
+// Shutdown the A2DP Source module.
+// This function should be called by the BTIF state machine to stop streaming.
void btif_a2dp_source_shutdown(void);
+// Cleanup the A2DP Source module.
+// This function should be called by the BTIF state machine during graceful
+// cleanup.
+void btif_a2dp_source_cleanup(void);
+
// Check whether the A2DP Source media task is running.
// Returns true if the A2DP Source media task is running, otherwise false.
bool btif_a2dp_source_media_task_is_running(void);
@@ -45,10 +74,6 @@
// Return true if the A2DP Source module is streaming.
bool btif_a2dp_source_is_streaming(void);
-// Setup the A2DP Source codec, and prepare the encoder.
-// This function should be called prior to starting A2DP streaming.
-void btif_a2dp_source_setup_codec(void);
-
// Process a request to start the A2DP audio encoding task.
void btif_a2dp_source_start_audio_req(void);
@@ -57,8 +82,10 @@
// Process a request to update the A2DP audio encoder with user preferred
// codec configuration.
+// The peer address is |peer_addr|.
// |codec_user_config| contains the preferred codec user configuration.
void btif_a2dp_source_encoder_user_config_update_req(
+ const RawAddress& peer_addr,
const btav_a2dp_codec_config_t& codec_user_config);
// Process a request to update the A2DP audio encoding with new audio
@@ -95,8 +122,4 @@
// information.
void btif_a2dp_source_debug_dump(int fd);
-// Update the A2DP Source related metrics.
-// This function should be called before collecting the metrics.
-void btif_a2dp_source_update_metrics(void);
-
#endif /* BTIF_A2DP_SOURCE_H */
diff --git a/btif/include/btif_api.h b/btif/include/btif_api.h
index 739eabe..519fc9c 100644
--- a/btif/include/btif_api.h
+++ b/btif/include/btif_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -184,8 +184,8 @@
* Returns bt_status_t
*
******************************************************************************/
-bt_status_t btif_get_remote_service_record(RawAddress* remote_addr,
- bt_uuid_t* uuid);
+bt_status_t btif_get_remote_service_record(const RawAddress& remote_addr,
+ const bluetooth::Uuid& uuid);
/*******************************************************************************
* BTIF DM API
@@ -329,8 +329,8 @@
* Returns bt_status_t
*
******************************************************************************/
-bt_status_t btif_dm_get_remote_service_record(RawAddress* remote_addr,
- bt_uuid_t* uuid);
+bt_status_t btif_dm_get_remote_service_record(const RawAddress& remote_addr,
+ const bluetooth::Uuid& uuid);
/*******************************************************************************
*
diff --git a/btif/include/btif_av.h b/btif/include/btif_av.h
index 3ba2d7d..486c2af 100644
--- a/btif/include/btif_av.h
+++ b/btif/include/btif_av.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,177 +16,195 @@
*
******************************************************************************/
-/*******************************************************************************
- *
- * Filename: btif_av.h
- *
- * Description: Main API header file for all BTIF AV functions accessed
- * from internal stack.
- *
- ******************************************************************************/
+/**
+ * BTIF AV API functions accessed internally.
+ */
#ifndef BTIF_AV_H
#define BTIF_AV_H
#include "bta_av_api.h"
#include "btif_common.h"
-#include "btif_sm.h"
-/*******************************************************************************
- * Type definitions for callback functions
- ******************************************************************************/
+/**
+ * When the local device is A2DP source, get the address of the active peer.
+ */
+RawAddress btif_av_source_active_peer(void);
-typedef enum {
- /* Reuse BTA_AV_XXX_EVT - No need to redefine them here */
- BTIF_AV_CONNECT_REQ_EVT = BTA_AV_MAX_EVT,
- BTIF_AV_DISCONNECT_REQ_EVT,
- BTIF_AV_START_STREAM_REQ_EVT,
- BTIF_AV_STOP_STREAM_REQ_EVT,
- BTIF_AV_SUSPEND_STREAM_REQ_EVT,
- BTIF_AV_SOURCE_CONFIG_REQ_EVT,
- BTIF_AV_SOURCE_CONFIG_UPDATED_EVT,
- BTIF_AV_SINK_CONFIG_REQ_EVT,
- BTIF_AV_OFFLOAD_START_REQ_EVT,
- BTIF_AV_CLEANUP_REQ_EVT,
-} btif_av_sm_event_t;
+/**
+ * When the local device is A2DP sink, get the address of the active peer.
+ */
+RawAddress btif_av_sink_active_peer(void);
-/*******************************************************************************
- * BTIF AV API
- ******************************************************************************/
-
-/*******************************************************************************
- *
- * Function btif_av_get_addr
- *
- * Description Fetches current AV BD address
- *
- * Returns BD address
- *
- ******************************************************************************/
-
-RawAddress btif_av_get_addr(void);
-
-/*******************************************************************************
- * Function btif_av_is_sink_enabled
- *
- * Description Checks if A2DP Sink is enabled or not
- *
- * Returns true if A2DP Sink is enabled, false otherwise
- *
- ******************************************************************************/
-
+/**
+ * Check whether A2DP Sink is enabled.
+ */
bool btif_av_is_sink_enabled(void);
-/*******************************************************************************
- *
- * Function btif_av_stream_ready
- *
- * Description Checks whether AV is ready for starting a stream
- *
- * Returns None
- *
- ******************************************************************************/
+/**
+ * Start streaming.
+ */
+void btif_av_stream_start(void);
+/**
+ * Stop streaming.
+ *
+ * @param peer_address the peer address or RawAddress::kEmpty to stop all peers
+ */
+void btif_av_stream_stop(const RawAddress& peer_address);
+
+/**
+ * Suspend streaming.
+ */
+void btif_av_stream_suspend(void);
+
+/**
+ * Start offload streaming.
+ */
+void btif_av_stream_start_offload(void);
+
+/**
+ * Check whether ready to start the A2DP stream.
+ */
bool btif_av_stream_ready(void);
-/*******************************************************************************
- *
- * Function btif_av_stream_started_ready
- *
- * Description Checks whether AV ready for media start in streaming state
- *
- * Returns None
- *
- ******************************************************************************/
-
+/**
+ * Check whether the A2DP stream is in started state and ready
+ * for media start.
+ */
bool btif_av_stream_started_ready(void);
-/*******************************************************************************
- *
- * Function btif_dispatch_sm_event
- *
- * Description Send event to AV statemachine
- *
- * Returns None
- *
- ******************************************************************************/
-
-/* used to pass events to AV statemachine from other tasks */
-void btif_dispatch_sm_event(btif_av_sm_event_t event, void* p_data, int len);
-
-/*******************************************************************************
- *
- * Function btif_av_init
- *
- * Description Initializes btif AV if not already done
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-
-bt_status_t btif_av_init(int service_id);
-
-/*******************************************************************************
- *
- * Function btif_av_is_connected
- *
- * Description Checks if av has a connected sink
- *
- * Returns bool
- *
- ******************************************************************************/
-
+/**
+ * Check whether there is a connected peer (either Source or Sink)
+ */
bool btif_av_is_connected(void);
-/*******************************************************************************
+/**
+ * Get the Stream Endpoint Type of the Active peer.
*
- * Function btif_av_get_peer_sep
- *
- * Description Get the stream endpoint type.
- *
- * Returns The stream endpoint type: either AVDT_TSEP_SRC or
- * AVDT_TSEP_SNK.
- *
- ******************************************************************************/
-
+ * @return the stream endpoint type: either AVDT_TSEP_SRC or AVDT_TSEP_SNK
+ */
uint8_t btif_av_get_peer_sep(void);
-/*******************************************************************************
- *
- * Function btif_av_is_peer_edr
- *
- * Description Check if the connected a2dp device supports
- * EDR or not. Only when connected this function
- * will accurately provide a true capability of
- * remote peer. If not connected it will always be false.
- *
- * Returns true if remote device is capable of EDR
- *
- ******************************************************************************/
-
-bool btif_av_is_peer_edr(void);
-
-/******************************************************************************
- *
- * Function btif_av_clear_remote_suspend_flag
- *
- * Description Clears remote suspended flag
- *
- * Returns Void
- ******************************************************************************/
+/**
+ * Clear the remote suspended flag for the active peer.
+ */
void btif_av_clear_remote_suspend_flag(void);
-/*******************************************************************************
+/**
+ * Process AVRCP Open event.
*
- * Function btif_av_peer_supports_3mbps
- *
- * Description Check if the connected A2DP device supports
- * 3 Mbps EDR. This function will only work while connected.
- * If not connected it will always return false.
- *
- * Returns true if remote device is EDR and supports 3 Mbps
- *
- ******************************************************************************/
-bool btif_av_peer_supports_3mbps(void);
+ * @param peer_address the peer address
+ */
+void btif_av_avrcp_event_open(const RawAddress& peer_address);
+/**
+ * Process AVRCP Close event.
+ *
+ * @param peer_address the peer address
+ */
+void btif_av_avrcp_event_close(const RawAddress& peer_address);
+
+/**
+ * Process AVRCP Remote Play event.
+ *
+ * @param peer_address the peer address
+ */
+void btif_av_avrcp_event_remote_play(const RawAddress& peer_address);
+
+/**
+ * Check whether the connected A2DP peer supports EDR.
+ *
+ * The value can be provided only if the remote peer is connected.
+ * Otherwise, the answer will be always false.
+ *
+ * @param peer_address the peer address
+ * @return true if the remote peer is capable of EDR
+ */
+bool btif_av_is_peer_edr(const RawAddress& peer_address);
+
+/**
+ * Check whether the connected A2DP peer supports 3 Mbps EDR.
+ *
+ * The value can be provided only if the remote peer is connected.
+ * Otherwise, the answer will be always false.
+ *
+ * @param peer_address the peer address
+ * @return true if the remote peer is capable of EDR and supports 3 Mbps
+ */
+bool btif_av_peer_supports_3mbps(const RawAddress& peer_address);
+
+/**
+ * Report A2DP Source Codec State for a peer.
+ *
+ * @param peer_address the address of the peer to report
+ * @param codec_config the codec config to report
+ * @param codecs_local_capabilities the codecs local capabilities to report
+ * @param codecs_selectable_capabilities the codecs selectable capabilities
+ * to report
+ */
+void btif_av_report_source_codec_state(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_config,
+ const std::vector<btav_a2dp_codec_config_t>& codecs_local_capabilities,
+ const std::vector<btav_a2dp_codec_config_t>&
+ codecs_selectable_capabilities);
+
+/**
+ * Initialize / shut down the A2DP Source service.
+ *
+ * @param enable true to enable the A2DP Source service, false to disable it
+ * @return BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
+ */
+bt_status_t btif_av_source_execute_service(bool enable);
+
+/**
+ * Initialize / shut down the A2DP Sink service.
+ *
+ * @param enable true to enable the A2DP Sink service, false to disable it
+ * @return BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
+ */
+bt_status_t btif_av_sink_execute_service(bool enable);
+
+/**
+ * Peer ACL disconnected.
+ *
+ * @param peer_address the disconnected peer address
+ */
+void btif_av_acl_disconnected(const RawAddress& peer_address);
+
+/**
+ * Dump debug-related information for the BTIF AV module.
+ *
+ * @param fd the file descriptor to use for writing the ASCII formatted
+ * information
+ */
+void btif_debug_av_dump(int fd);
+
+/**
+ * Set the audio delay for the stream.
+ *
+ * @param delay the delay to set in units of 1/10ms
+ */
+void btif_av_set_audio_delay(uint16_t delay);
+
+/**
+ * Reset the audio delay and count of audio bytes sent to zero.
+ */
+void btif_av_reset_audio_delay(void);
+
+/**
+ * Called to disconnect peer device when
+ * remote initiatied offload start failed
+ *
+ * @param peer_address to disconnect
+ *
+ */
+void btif_av_src_disconnect_sink(const RawAddress& peer_address);
+
+/**
+ * check A2DP offload support enabled
+ * @param none
+ */
+bool btif_av_is_a2dp_offload_enabled(void);
#endif /* BTIF_AV_H */
diff --git a/btif/include/btif_av_co.h b/btif/include/btif_av_co.h
index 8c1266f..df7454f 100644
--- a/btif/include/btif_av_co.h
+++ b/btif/include/btif_av_co.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,14 +22,16 @@
#include "btif/include/btif_a2dp_source.h"
#include "stack/include/a2dp_codec_api.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+// Sets the active peer to |peer_addr|.
+// Returns true on success, otherwise false.
+bool bta_av_co_set_active_peer(const RawAddress& peer_addr);
// Gets the A2DP peer parameters that are used to initialize the encoder.
+// The peer address is |peer_addr|.
// The parameters are stored in |p_peer_params|.
// |p_peer_params| cannot be null.
-void bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params);
+void bta_av_co_get_peer_params(const RawAddress& peer_addr,
+ tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params);
// Gets the current A2DP encoder interface that can be used to encode and
// prepare A2DP packets for transmission - see |tA2DP_ENCODER_INTERFACE|.
@@ -37,10 +39,18 @@
// otherwise NULL.
const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void);
+// Gets the current A2DP decoder interface that can be used to decode received
+// A2DP packets - see |tA2DP_DECODER_INTERFACE|.
+// Returns the A2DP decoder interface if the current codec is setup, otherwise
+// NULL.
+const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void);
+
// Sets the user preferred codec configuration.
+// The peer address is |peer_addr|.
// |codec_user_config| contains the preferred codec configuration.
// Returns true on success, otherwise false.
bool bta_av_co_set_codec_user_config(
+ const RawAddress& peer_addr,
const btav_a2dp_codec_config_t& codec_user_config);
// Sets the Audio HAL selected audio feeding parameters.
@@ -55,17 +65,20 @@
void bta_av_co_init(
const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
-// Gets the initialized A2DP codecs.
-// Returns a pointer to the |A2dpCodecs| object with the initialized A2DP
-// codecs, or nullptr if no codecs are initialized.
-A2dpCodecs* bta_av_get_a2dp_codecs(void);
-
-// Gets the current A2DP codec.
-// Returns a pointer to the current |A2dpCodec| if valid, otherwise nullptr.
+// Gets the current A2DP codec for the active peer.
+// Returns a pointer to the current |A2dpCodecConfig| if valid, otherwise
+// nullptr.
A2dpCodecConfig* bta_av_get_a2dp_current_codec(void);
-#ifdef __cplusplus
-}
-#endif
+// Gets the current A2DP codec for a peer identified by |peer_address|.
+// Returns a pointer to the current |A2dpCodecConfig| if valid, otherwise
+// nullptr.
+A2dpCodecConfig* bta_av_get_a2dp_peer_current_codec(
+ const RawAddress& peer_address);
+
+// Dump A2DP codec debug-related information for the A2DP module.
+// |fd| is the file descriptor to use for writing the ASCII formatted
+// information.
+void btif_a2dp_codec_debug_dump(int fd);
#endif // BTIF_AV_CO_H
diff --git a/btif/include/btif_avrcp_audio_track.h b/btif/include/btif_avrcp_audio_track.h
index 6986e43..720fe60 100644
--- a/btif/include/btif_avrcp_audio_track.h
+++ b/btif/include/btif_avrcp_audio_track.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_common.h b/btif/include/btif_common.h
index ae726e7..af0beb0 100644
--- a/btif/include/btif_common.h
+++ b/btif/include/btif_common.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <base/bind.h>
+#include <base/message_loop/message_loop.h>
#include <base/tracked_objects.h>
#include <hardware/bluetooth.h>
@@ -77,14 +78,14 @@
extern bt_callbacks_t* bt_hal_cbacks;
-#define HAL_CBACK(P_CB, P_CBACK, ...) \
- do { \
- if ((P_CB) && (P_CB)->P_CBACK) { \
- BTIF_TRACE_API("HAL %s->%s", #P_CB, #P_CBACK); \
- (P_CB)->P_CBACK(__VA_ARGS__); \
- } else { \
- ASSERTC(0, "Callback is NULL", 0); \
- } \
+#define HAL_CBACK(P_CB, P_CBACK, ...) \
+ do { \
+ if ((P_CB) && (P_CB)->P_CBACK) { \
+ BTIF_TRACE_API("%s: HAL %s->%s", __func__, #P_CB, #P_CBACK); \
+ (P_CB)->P_CBACK(__VA_ARGS__); \
+ } else { \
+ ASSERTC(0, "Callback is NULL", 0); \
+ } \
} while (0)
/**
@@ -176,6 +177,8 @@
extern bt_status_t do_in_jni_thread(const base::Closure& task);
extern bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here,
const base::Closure& task);
+extern bool is_on_jni_thread();
+extern base::MessageLoop* get_jni_message_loop();
/**
* This template wraps callback into callback that will be executed on jni
* thread
diff --git a/btif/include/btif_config.h b/btif/include/btif_config.h
index 7031802..028afa7 100644
--- a/btif/include/btif_config.h
+++ b/btif/include/btif_config.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,31 +23,36 @@
#include "bt_types.h"
+#include <list>
+#include <string>
+#include "osi/include/config.h"
+
static const char BTIF_CONFIG_MODULE[] = "btif_config_module";
-typedef struct btif_config_section_iter_t btif_config_section_iter_t;
-
bool btif_config_has_section(const char* section);
-bool btif_config_exist(const char* section, const char* key);
-bool btif_config_get_int(const char* section, const char* key, int* value);
-bool btif_config_set_int(const char* section, const char* key, int value);
-bool btif_config_get_str(const char* section, const char* key, char* value,
- int* size_bytes);
-bool btif_config_set_str(const char* section, const char* key,
- const char* value);
-bool btif_config_get_bin(const char* section, const char* key, uint8_t* value,
- size_t* length);
-bool btif_config_set_bin(const char* section, const char* key,
+bool btif_config_exist(const std::string& section, const std::string& key);
+bool btif_config_get_int(const std::string& section, const std::string& key,
+ int* value);
+bool btif_config_set_int(const std::string& section, const std::string& key,
+ int value);
+bool btif_config_get_uint64(const std::string& section, const std::string& key,
+ uint64_t* value);
+bool btif_config_set_uint64(const std::string& section, const std::string& key,
+ uint64_t value);
+bool btif_config_get_str(const std::string& section, const std::string& key,
+ char* value, int* size_bytes);
+bool btif_config_set_str(const std::string& section, const std::string& key,
+ const std::string& value);
+bool btif_config_get_bin(const std::string& section, const std::string& key,
+ uint8_t* value, size_t* length);
+bool btif_config_set_bin(const std::string& section, const std::string& key,
const uint8_t* value, size_t length);
-bool btif_config_remove(const char* section, const char* key);
+bool btif_config_remove(const std::string& section, const std::string& key);
-size_t btif_config_get_bin_length(const char* section, const char* key);
+size_t btif_config_get_bin_length(const std::string& section,
+ const std::string& key);
-const btif_config_section_iter_t* btif_config_section_begin(void);
-const btif_config_section_iter_t* btif_config_section_end(void);
-const btif_config_section_iter_t* btif_config_section_next(
- const btif_config_section_iter_t* section);
-const char* btif_config_section_name(const btif_config_section_iter_t* section);
+std::list<section_t>& btif_config_sections();
void btif_config_save(void);
void btif_config_flush(void);
diff --git a/btif/include/btif_config_transcode.h b/btif/include/btif_config_transcode.h
index 66aac8a..e61b943 100644
--- a/btif/include/btif_config_transcode.h
+++ b/btif/include/btif_config_transcode.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,6 @@
#pragma once
-typedef struct config_t config_t;
+#include "osi/include/config.h"
-config_t* btif_config_transcode(const char* xml_filename);
+std::unique_ptr<config_t> btif_config_transcode(const char* xml_filename);
diff --git a/btif/include/btif_debug.h b/btif/include/btif_debug.h
index 463a4a1..55e4e50 100644
--- a/btif/include/btif_debug.h
+++ b/btif/include/btif_debug.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_debug_btsnoop.h b/btif/include/btif_debug_btsnoop.h
index e82421a..766057d 100644
--- a/btif/include/btif_debug_btsnoop.h
+++ b/btif/include/btif_debug_btsnoop.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_debug_conn.h b/btif/include/btif_debug_conn.h
index 6ee374e..19703dd 100644
--- a/btif/include/btif_debug_conn.h
+++ b/btif/include/btif_debug_conn.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_dm.h b/btif/include/btif_dm.h
index adafdef..6105ab5 100644
--- a/btif/include/btif_dm.h
+++ b/btif/include/btif_dm.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_gatt.h b/btif/include/btif_gatt.h
index e84811e..88f18a7 100644
--- a/btif/include/btif_gatt.h
+++ b/btif/include/btif_gatt.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_gatt_util.h b/btif/include/btif_gatt_util.h
index 731f519..284a45c 100644
--- a/btif/include/btif_gatt_util.h
+++ b/btif/include/btif_gatt_util.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,18 +24,10 @@
#include "bta/include/bta_gatt_api.h"
-void btif_to_bta_uuid(tBT_UUID* p_dest, const bt_uuid_t* p_src);
-void btif_to_bta_response(tBTA_GATTS_RSP* p_dest, btgatt_response_t* p_src);
-void btif_to_bta_uuid_mask(tBTM_BLE_PF_COND_MASK* p_mask,
- const bt_uuid_t* p_src, const bt_uuid_t* svc_uuid);
-
-void bta_to_btif_uuid(bt_uuid_t* p_dest, tBT_UUID* p_src);
-
-uint16_t set_read_value(btgatt_read_params_t* p_dest, tBTA_GATTC_READ* p_src);
-uint16_t get_uuid16(tBT_UUID* p_uuid);
+void btif_to_bta_response(tGATTS_RSP* p_dest, btgatt_response_t* p_src);
void btif_gatt_check_encrypted_link(RawAddress bd_addr,
- tBTA_GATT_TRANSPORT transport);
+ tGATT_TRANSPORT transport);
extern void btif_gatt_move_track_adv_data(btgatt_track_adv_info_t* p_dest,
btgatt_track_adv_info_t* p_src);
diff --git a/btif/include/btif_hd.h b/btif/include/btif_hd.h
index a119ebd..7ed7d56 100644
--- a/btif/include/btif_hd.h
+++ b/btif/include/btif_hd.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_hf.h b/btif/include/btif_hf.h
index 1cafb8b..68553b4 100644
--- a/btif/include/btif_hf.h
+++ b/btif/include/btif_hf.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,13 +16,34 @@
*
******************************************************************************/
-#ifndef BTIF_HF_H
-#define BTIF_HF_H
+#pragma once
-#include <stdbool.h>
+#include <hardware/bluetooth_headset_interface.h>
-// Check whether there is a Hands-Free call in progress.
-// Returns true if no call is in progress.
-bool btif_hf_is_call_idle(void);
+namespace bluetooth {
+namespace headset {
-#endif /* BTIF_HF_H */
+/**
+ * Get an instance of the headset interface from the loaded shared library
+ *
+ * @return an instance of the headset interface
+ */
+Interface* GetInterface();
+
+/**
+ * Check whether there is a Hands-Free call in progress.
+ *
+ * @return true if no call is in progress.
+ */
+bool IsCallIdle();
+
+/**
+ * Start up or shutdown the service
+ *
+ * @param b_enable true to enable, false to disable
+ * @return BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
+ */
+bt_status_t ExecuteService(bool b_enable);
+
+} // namespace headset
+} // namespace bluetooth
diff --git a/btif/include/btif_hh.h b/btif/include/btif_hh.h
index 8505b08..2364544 100644
--- a/btif/include/btif_hh.h
+++ b/btif/include/btif_hh.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -88,6 +88,7 @@
btif_hh_added_device_t added_devices[BTIF_HH_MAX_ADDED_DEV];
btif_hh_device_t* p_curr_dev;
bool service_dereg_active;
+ RawAddress pending_conn_address;
} btif_hh_cb_t;
/*******************************************************************************
diff --git a/btif/include/btif_hl.h b/btif/include/btif_hl.h
index b5022ef..69a99b5 100644
--- a/btif/include/btif_hl.h
+++ b/btif/include/btif_hl.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_mce.h b/btif/include/btif_mce.h
index dabcb39..1eea206 100644
--- a/btif/include/btif_mce.h
+++ b/btif/include/btif_mce.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_pan.h b/btif/include/btif_pan.h
index 96874d6..dada5b3 100644
--- a/btif/include/btif_pan.h
+++ b/btif/include/btif_pan.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_pan_internal.h b/btif/include/btif_pan_internal.h
index a902946..5b536af 100644
--- a/btif/include/btif_pan_internal.h
+++ b/btif/include/btif_pan_internal.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_profile_queue.h b/btif/include/btif_profile_queue.h
index df48c77..da4e992 100644
--- a/btif/include/btif_profile_queue.h
+++ b/btif/include/btif_profile_queue.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,16 @@
btif_connect_cb_t connect_cb);
void btif_queue_cleanup(uint16_t uuid);
void btif_queue_advance();
+
+/**
+ * Dispatch the next pending connect request.
+ * NOTE: Must be called on the JNI thread.
+ *
+ * @return BT_STATUS_SUCCESS on success, otherwise the corresponding error
+ * code
+ */
bt_status_t btif_queue_connect_next(void);
+
void btif_queue_release();
#endif
diff --git a/btif/include/btif_rc.h b/btif/include/btif_rc.h
new file mode 100644
index 0000000..cd2d0cc
--- /dev/null
+++ b/btif/include/btif_rc.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BTIF_RC_H
+#define BTIF_RC_H
+
+#include "bta_av_api.h"
+
+class RawAddress;
+
+void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data);
+uint8_t btif_rc_get_connected_peer_handle(const RawAddress& peer_addr);
+void btif_rc_check_handle_pending_play(const RawAddress& peer_addr,
+ bool bSendToApp);
+bool btif_rc_is_connected_peer(const RawAddress& peer_addr);
+
+#endif // BTIF_RC_H
diff --git a/btif/include/btif_sdp.h b/btif/include/btif_sdp.h
index 7e224b0..9f0daed 100644
--- a/btif/include/btif_sdp.h
+++ b/btif/include/btif_sdp.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_sm.h b/btif/include/btif_sm.h
deleted file mode 100644
index 129e312..0000000
--- a/btif/include/btif_sm.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2009-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/*****************************************************************************
- *
- * Filename: btif_sm.h
- *
- * Description: Generic BTIF state machine API
- *
- *****************************************************************************/
-
-#ifndef BTIF_SM_H
-#define BTIF_SM_H
-
-#include <hardware/bluetooth.h>
-
-#include "stack/include/bt_types.h"
-
-/*****************************************************************************
- * Constants & Macros
- *****************************************************************************/
-
-/* Generic Enter/Exit state machine events */
-#define BTIF_SM_ENTER_EVT 0xFFFF
-#define BTIF_SM_EXIT_EVT 0xFFFE
-
-/*****************************************************************************
- * Type definitions and return values
- *****************************************************************************/
-typedef uint32_t btif_sm_state_t;
-typedef uint32_t btif_sm_event_t;
-typedef void* btif_sm_handle_t;
-typedef bool (*btif_sm_handler_t)(btif_sm_event_t event, void* data);
-
-/*****************************************************************************
- * Functions
- *
- * NOTE: THESE APIs SHOULD BE INVOKED ONLY IN THE BTIF CONTEXT
- *
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * Function btif_sm_init
- *
- * Description Initializes the state machine with the state handlers
- * The caller should ensure that the table and the corresponding
- * states match. The location that 'p_handlers' points to shall
- * be available until the btif_sm_shutdown API is invoked.
- *
- * Returns Returns a pointer to the initialized state machine handle.
- *
- *****************************************************************************/
-btif_sm_handle_t btif_sm_init(const btif_sm_handler_t* p_handlers,
- btif_sm_state_t initial_state);
-
-/*****************************************************************************
- *
- * Function btif_sm_shutdown
- *
- * Description Tears down the state machine
- *
- * Returns None
- *
- *****************************************************************************/
-void btif_sm_shutdown(btif_sm_handle_t handle);
-
-/*****************************************************************************
- *
- * Function btif_sm_get_state
- *
- * Description Fetches the current state of the state machine
- *
- * Returns Current state
- *
- *****************************************************************************/
-btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle);
-
-/*****************************************************************************
- *
- * Function btif_sm_dispatch
- *
- * Description Dispatches the 'event' along with 'data' to the current state
- * handler
- *
- * Returns Returns BT_STATUS_OK on success, BT_STATUS_FAIL otherwise
- *
- *****************************************************************************/
-bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event,
- void* data);
-
-/*****************************************************************************
- *
- * Function btif_sm_change_state
- *
- * Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT'
- * shall be invoked before exiting the current state. The
- * 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new
- * state
- *
- * Returns Returns BT_STATUS_OK on success, BT_STATUS_FAIL otherwise
- *
- *****************************************************************************/
-bt_status_t btif_sm_change_state(btif_sm_handle_t handle,
- btif_sm_state_t state);
-
-#endif /* BTIF_SM_H */
diff --git a/btif/include/btif_sock.h b/btif/include/btif_sock.h
index e65def6..cb0378e 100644
--- a/btif/include/btif_sock.h
+++ b/btif/include/btif_sock.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
#include <hardware/bt_sock.h>
-btsock_interface_t* btif_sock_get_interface(void);
+const btsock_interface_t* btif_sock_get_interface(void);
bt_status_t btif_sock_init(uid_set_t* uid_set);
void btif_sock_cleanup(void);
diff --git a/btif/include/btif_sock_l2cap.h b/btif/include/btif_sock_l2cap.h
index 2715be0..f921279 100644
--- a/btif/include/btif_sock_l2cap.h
+++ b/btif/include/btif_sock_l2cap.h
@@ -10,7 +10,6 @@
#include <hardware/bluetooth.h>
#define L2CAP_MASK_FIXED_CHANNEL 0x10000
-#define L2CAP_MASK_LE_COC_CHANNEL 0x20000
bt_status_t btsock_l2cap_init(int handle, uid_set_t* set);
bt_status_t btsock_l2cap_cleanup();
diff --git a/btif/include/btif_sock_rfc.h b/btif/include/btif_sock_rfc.h
index 5c588b5..a37447e 100644
--- a/btif/include/btif_sock_rfc.h
+++ b/btif/include/btif_sock_rfc.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,12 +31,12 @@
bt_status_t btsock_rfc_init(int handle, uid_set_t* set);
bt_status_t btsock_rfc_cleanup();
-bt_status_t btsock_rfc_listen(const char* name, const uint8_t* uuid,
+bt_status_t btsock_rfc_listen(const char* name, const bluetooth::Uuid* uuid,
int channel, int* sock_fd, int flags,
int app_uid);
-bt_status_t btsock_rfc_connect(const RawAddress* bd_addr, const uint8_t* uuid,
- int channel, int* sock_fd, int flags,
- int app_uid);
+bt_status_t btsock_rfc_connect(const RawAddress* bd_addr,
+ const bluetooth::Uuid* uuid, int channel,
+ int* sock_fd, int flags, int app_uid);
void btsock_rfc_signaled(int fd, int flags, uint32_t user_id);
#endif
diff --git a/btif/include/btif_sock_sco.h b/btif/include/btif_sock_sco.h
index 50530ce..9d1d805 100644
--- a/btif/include/btif_sock_sco.h
+++ b/btif/include/btif_sock_sco.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2013 Google, Inc.
+ * Copyright 2013 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_sock_sdp.h b/btif/include/btif_sock_sdp.h
index 7672c7c..5421cd1 100644
--- a/btif/include/btif_sock_sdp.h
+++ b/btif/include/btif_sock_sdp.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,34 +19,21 @@
#ifndef BTIF_SOCK_SDP_H
#define BTIF_SOCK_SDP_H
+#include <bluetooth/uuid.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
-static const uint8_t UUID_OBEX_OBJECT_PUSH[] = {
- 0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
-static const uint8_t UUID_PBAP_PSE[] = {0x00, 0x00, 0x11, 0x2F, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-static const uint8_t UUID_MAP_MAS[] = {0x00, 0x00, 0x11, 0x32, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-static const uint8_t UUID_SAP[] = {0x00, 0x00, 0x11, 0x2D, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-static const uint8_t UUID_SPP[] = {0x00, 0x00, 0x11, 0x01, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
+static const bluetooth::Uuid UUID_OBEX_OBJECT_PUSH =
+ bluetooth::Uuid::From16Bit(0x1105);
+static const bluetooth::Uuid UUID_PBAP_PSE = bluetooth::Uuid::From16Bit(0x112F);
+static const bluetooth::Uuid UUID_MAP_MAS = bluetooth::Uuid::From16Bit(0x1132);
+static const bluetooth::Uuid UUID_SAP = bluetooth::Uuid::From16Bit(0x112D);
+static const bluetooth::Uuid UUID_SPP = bluetooth::Uuid::From16Bit(0x1101);
-static inline bool is_uuid_empty(const uint8_t* uuid) {
- static uint8_t empty_uuid[16];
- return uuid == NULL || memcmp(uuid, empty_uuid, sizeof(empty_uuid)) == 0;
-}
-
-int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn);
+int add_rfc_sdp_rec(const char* name, bluetooth::Uuid uuid, int scn);
void del_rfc_sdp_rec(int handle);
bool is_reserved_rfc_channel(int channel);
-int get_reserved_rfc_channel(const uint8_t* uuid);
+int get_reserved_rfc_channel(const bluetooth::Uuid& uuid);
#endif
diff --git a/btif/include/btif_sock_thread.h b/btif/include/btif_sock_thread.h
index d50a09d..4b111a4 100644
--- a/btif/include/btif_sock_thread.h
+++ b/btif/include/btif_sock_thread.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_sock_util.h b/btif/include/btif_sock_util.h
index 90cfb9a..0dfbbfb 100644
--- a/btif/include/btif_sock_util.h
+++ b/btif/include/btif_sock_util.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,8 +29,6 @@
#include <stdint.h>
-void dump_bin(const char* title, const char* data, int size);
-
int sock_send_fd(int sock_fd, const uint8_t* buffer, int len, int send_fd);
int sock_send_all(int sock_fd, const uint8_t* buf, int len);
int sock_recv_all(int sock_fd, uint8_t* buf, int len);
diff --git a/btif/include/btif_state_machine.h b/btif/include/btif_state_machine.h
new file mode 100644
index 0000000..49b1583
--- /dev/null
+++ b/btif/include/btif_state_machine.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BTIF_STATE_MACHINE_H
+#define BTIF_STATE_MACHINE_H
+
+#include <map>
+#include <utility>
+
+#include <base/logging.h>
+
+/**
+ * State machine used by BTIF components.
+ */
+class BtifStateMachine {
+ public:
+ enum { kStateInvalid = -1 };
+
+ /**
+ * A class to represent the state in the State Machine.
+ */
+ class State {
+ friend class BtifStateMachine;
+
+ public:
+ /**
+ * Constructor.
+ *
+ * @param sm the State Machine to use
+ * @param state_id the unique State ID. It should be a non-negative number.
+ */
+ State(BtifStateMachine& sm, int state_id) : sm_(sm), state_id_(state_id) {}
+
+ virtual ~State() = default;
+
+ /**
+ * Process an event.
+ * TODO: The arguments are wrong - used for backward compatibility.
+ * Will be replaced later.
+ *
+ * @param event the event type
+ * @param p_data the event data
+ * @return true if the processing was completed, otherwise false
+ */
+ virtual bool ProcessEvent(uint32_t event, void* p_data) = 0;
+
+ /**
+ * Get the State ID.
+ *
+ * @return the State ID
+ */
+ int StateId() const { return state_id_; }
+
+ protected:
+ /**
+ * Called when a state is entered.
+ */
+ virtual void OnEnter() {}
+
+ /**
+ * Called when a state is exited.
+ */
+ virtual void OnExit() {}
+
+ /**
+ * Transition the State Machine to a new state.
+ *
+ * @param dest_state_id the state ID to transition to. It must be one
+ * of the unique state IDs when the corresponding state was created.
+ */
+ void TransitionTo(int dest_state_id) { sm_.TransitionTo(dest_state_id); }
+
+ /**
+ * Transition the State Machine to a new state.
+ *
+ * @param dest_state the state to transition to. It cannot be nullptr.
+ */
+ void TransitionTo(BtifStateMachine::State* dest_state) {
+ sm_.TransitionTo(dest_state);
+ }
+
+ private:
+ BtifStateMachine& sm_;
+ int state_id_;
+ };
+
+ BtifStateMachine()
+ : initial_state_(nullptr),
+ previous_state_(nullptr),
+ current_state_(nullptr) {}
+ ~BtifStateMachine() {
+ for (auto& kv : states_) delete kv.second;
+ }
+
+ /**
+ * Start the State Machine operation.
+ */
+ void Start() { TransitionTo(initial_state_); }
+
+ /**
+ * Quit the State Machine operation.
+ */
+ void Quit() { previous_state_ = current_state_ = nullptr; }
+
+ /**
+ * Get the current State ID.
+ *
+ * @return the current State ID
+ */
+ int StateId() const {
+ if (current_state_ != nullptr) {
+ return current_state_->StateId();
+ }
+ return kStateInvalid;
+ }
+
+ /**
+ * Get the previous current State ID.
+ *
+ * @return the previous State ID
+ */
+ int PreviousStateId() const {
+ if (previous_state_ != nullptr) {
+ return previous_state_->StateId();
+ }
+ return kStateInvalid;
+ }
+
+ /**
+ * Process an event.
+ * TODO: The arguments are wrong - used for backward compatibility.
+ * Will be replaced later.
+ *
+ * @param event the event type
+ * @param p_data the event data
+ * @return true if the processing was completed, otherwise false
+ */
+ bool ProcessEvent(uint32_t event, void* p_data) {
+ if (current_state_ == nullptr) return false;
+ return current_state_->ProcessEvent(event, p_data);
+ }
+
+ /**
+ * Transition the State Machine to a new state.
+ *
+ * @param dest_state_id the state ID to transition to. It must be one
+ * of the unique state IDs when the corresponding state was created.
+ */
+ void TransitionTo(int dest_state_id) {
+ auto it = states_.find(dest_state_id);
+
+ CHECK(it != states_.end()) << "Unknown State ID: " << dest_state_id;
+ State* dest_state = it->second;
+ TransitionTo(dest_state);
+ }
+
+ /**
+ * Transition the State Machine to a new state.
+ *
+ * @param dest_state the state to transition to. It cannot be nullptr.
+ */
+ void TransitionTo(BtifStateMachine::State* dest_state) {
+ if (current_state_ != nullptr) {
+ current_state_->OnExit();
+ }
+ previous_state_ = current_state_;
+ current_state_ = dest_state;
+ current_state_->OnEnter();
+ }
+
+ /**
+ * Add a state to the State Machine.
+ * The state machine takes ownership on the state - i.e., the state will
+ * be deleted by the State Machine itself.
+ *
+ * @param state the state to add
+ */
+ void AddState(State* state) {
+ states_.insert(std::make_pair(state->StateId(), state));
+ }
+
+ /**
+ * Set the initial state of the State Machine.
+ *
+ * @param initial_state the initial state
+ */
+ void SetInitialState(State* initial_state) { initial_state_ = initial_state; }
+
+ private:
+ State* initial_state_;
+ State* previous_state_;
+ State* current_state_;
+ std::map<int, State*> states_;
+};
+
+#endif // BTIF_STATE_MACHINE_H
diff --git a/btif/include/btif_storage.h b/btif/include/btif_storage.h
index 1f7efd3..fb90673 100644
--- a/btif/include/btif_storage.h
+++ b/btif/include/btif_storage.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
#ifndef BTIF_STORAGE_H
#define BTIF_STORAGE_H
+#include <bluetooth/uuid.h>
#include <hardware/bluetooth.h>
#include "bt_target.h"
@@ -194,6 +195,15 @@
******************************************************************************/
bt_status_t btif_storage_remove_hid_info(RawAddress* remote_bd_addr);
+/** Loads information about bonded hearing aid devices */
+void btif_storage_load_bonded_hearing_aids();
+
+/** Deletes the bonded hearing aid device info from NVRAM */
+void btif_storage_remove_hearing_aid(const RawAddress& address);
+
+/** Remove the hearing aid device from white list */
+void btif_storage_remove_hearing_aid_white_list(const RawAddress& address);
+
/*******************************************************************************
*
* Function btif_storage_is_retricted_device
@@ -208,10 +218,12 @@
bool btif_storage_is_restricted_device(const RawAddress* remote_bd_addr);
bt_status_t btif_storage_add_ble_bonding_key(RawAddress* remote_bd_addr,
- char* key, uint8_t key_type,
+ const uint8_t* key,
+ uint8_t key_type,
uint8_t key_length);
bt_status_t btif_storage_get_ble_bonding_key(RawAddress* remote_bd_addr,
- uint8_t key_type, char* key_value,
+ uint8_t key_type,
+ uint8_t* key_value,
int key_length);
bt_status_t btif_storage_add_ble_local_key(char* key, uint8_t key_type,
@@ -272,7 +284,7 @@
/******************************************************************************
* Exported for unit tests
*****************************************************************************/
-size_t btif_split_uuids_string(const char* str, bt_uuid_t* p_uuid,
+size_t btif_split_uuids_string(const char* str, bluetooth::Uuid* p_uuid,
size_t max_uuids);
#endif /* BTIF_STORAGE_H */
diff --git a/btif/include/btif_uid.h b/btif/include/btif_uid.h
index 35faedb..de71906 100644
--- a/btif/include/btif_uid.h
+++ b/btif/include/btif_uid.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/include/btif_util.h b/btif/include/btif_util.h
index a1a6492..007cfa5 100644
--- a/btif/include/btif_util.h
+++ b/btif/include/btif_util.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@
#define BTIF_UTIL_H
#include <hardware/bluetooth.h>
-#include <hardware/bt_hf.h>
#include <stdbool.h>
#include <sys/time.h>
@@ -51,10 +50,7 @@
const char* dump_hf_client_event(uint16_t event);
const char* dump_hh_event(uint16_t event);
const char* dump_hd_event(uint16_t event);
-const char* dump_hf_conn_state(uint16_t event);
-const char* dump_hf_call_state(bthf_call_state_t call_state);
const char* dump_property_type(bt_property_type_t type);
-const char* dump_hf_audio_state(uint16_t event);
const char* dump_adapter_scan_mode(bt_scan_mode_t mode);
const char* dump_thread_evt(bt_cb_thread_evt evt);
const char* dump_av_conn_state(uint16_t event);
@@ -65,17 +61,7 @@
uint32_t devclass2uint(DEV_CLASS dev_class);
void uint2devclass(uint32_t dev, DEV_CLASS dev_class);
-void uuid16_to_uuid128(uint16_t uuid16, bt_uuid_t* uuid128);
-
-// Takes a |str| containing a 128-bit GUID formatted UUID and stores the
-// result in |p_uuid|. |str| must be formatted in this format:
-// "12345678-1234-1234-1234-123456789012"
-// |p_uuid| cannot be null. Returns true if parsing was successful, false
-// otherwise. Returns false if |str| is null.
-bool string_to_uuid(const char* str, bt_uuid_t* p_uuid);
int ascii_2_hex(const char* p_ascii, int len, uint8_t* p_hex);
-void uuid_to_string_legacy(bt_uuid_t* p_uuid, char* str, size_t str_len);
-
#endif /* BTIF_UTIL_H */
diff --git a/btif/include/stack_manager.h b/btif/include/stack_manager.h
index 90d81c5..1920ddd 100644
--- a/btif/include/stack_manager.h
+++ b/btif/include/stack_manager.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/src/bluetooth.cc b/btif/src/bluetooth.cc
index 1d2c66a..92a4092 100644
--- a/btif/src/bluetooth.cc
+++ b/btif/src/bluetooth.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,10 +33,11 @@
#include <unistd.h>
#include <hardware/bluetooth.h>
+#include <hardware/bluetooth_headset_interface.h>
#include <hardware/bt_av.h>
#include <hardware/bt_gatt.h>
#include <hardware/bt_hd.h>
-#include <hardware/bt_hf.h>
+#include <hardware/bt_hearing_aid.h>
#include <hardware/bt_hf_client.h>
#include <hardware/bt_hh.h>
#include <hardware/bt_hl.h>
@@ -46,14 +47,18 @@
#include <hardware/bt_sdp.h>
#include <hardware/bt_sock.h>
+#include "avrcp_service.h"
#include "bt_utils.h"
+#include "bta/include/bta_hearing_aid_api.h"
#include "bta/include/bta_hf_client_api.h"
-#include "btif/include/btif_debug_btsnoop.h"
-#include "btif/include/btif_debug_conn.h"
#include "btif_a2dp.h"
#include "btif_api.h"
+#include "btif_av.h"
#include "btif_config.h"
#include "btif_debug.h"
+#include "btif_debug_btsnoop.h"
+#include "btif_debug_conn.h"
+#include "btif_hf.h"
#include "btif_storage.h"
#include "btsnoop.h"
#include "btsnoop_mem.h"
@@ -69,6 +74,8 @@
/* Test interface includes */
#include "mca_api.h"
+using bluetooth::hearing_aid::HearingAidInterface;
+
/*******************************************************************************
* Static variables
******************************************************************************/
@@ -82,36 +89,36 @@
/* list all extended interfaces here */
-/* handsfree profile */
-extern bthf_interface_t* btif_hf_get_interface();
/* handsfree profile - client */
-extern bthf_client_interface_t* btif_hf_client_get_interface();
+extern const bthf_client_interface_t* btif_hf_client_get_interface();
/* advanced audio profile */
-extern btav_source_interface_t* btif_av_get_src_interface();
-extern btav_sink_interface_t* btif_av_get_sink_interface();
+extern const btav_source_interface_t* btif_av_get_src_interface();
+extern const btav_sink_interface_t* btif_av_get_sink_interface();
/*rfc l2cap*/
-extern btsock_interface_t* btif_sock_get_interface();
+extern const btsock_interface_t* btif_sock_get_interface();
/* hid host profile */
-extern bthh_interface_t* btif_hh_get_interface();
+extern const bthh_interface_t* btif_hh_get_interface();
/* hid device profile */
-extern bthd_interface_t* btif_hd_get_interface();
+extern const bthd_interface_t* btif_hd_get_interface();
/* health device profile */
-extern bthl_interface_t* btif_hl_get_interface();
+extern const bthl_interface_t* btif_hl_get_interface();
/*pan*/
-extern btpan_interface_t* btif_pan_get_interface();
+extern const btpan_interface_t* btif_pan_get_interface();
/*map client*/
-extern btmce_interface_t* btif_mce_get_interface();
+extern const btmce_interface_t* btif_mce_get_interface();
/* gatt */
extern const btgatt_interface_t* btif_gatt_get_interface();
/* avrc target */
-extern btrc_interface_t* btif_rc_get_interface();
+extern const btrc_interface_t* btif_rc_get_interface();
/* avrc controller */
-extern btrc_interface_t* btif_rc_ctrl_get_interface();
+extern const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface();
/*SDP search client*/
-extern btsdp_interface_t* btif_sdp_get_interface();
+extern const btsdp_interface_t* btif_sdp_get_interface();
+/*Hearing Aid client*/
+extern HearingAidInterface* btif_hearing_aid_get_interface();
/* List all test interface here */
-extern btmcap_test_interface_t* stack_mcap_get_interface();
+extern const btmcap_test_interface_t* stack_mcap_get_interface();
/*******************************************************************************
* Functions
@@ -170,28 +177,28 @@
static int get_adapter_properties(void) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_get_adapter_properties();
}
static int get_adapter_property(bt_property_type_t type) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_get_adapter_property(type);
}
static int set_adapter_property(const bt_property_t* property) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_set_adapter_property(property);
}
int get_remote_device_properties(RawAddress* remote_addr) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_get_remote_device_properties(remote_addr);
}
@@ -199,7 +206,7 @@
int get_remote_device_property(RawAddress* remote_addr,
bt_property_type_t type) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_get_remote_device_property(remote_addr, type);
}
@@ -207,42 +214,43 @@
int set_remote_device_property(RawAddress* remote_addr,
const bt_property_t* property) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_set_remote_device_property(remote_addr, property);
}
-int get_remote_service_record(RawAddress* remote_addr, bt_uuid_t* uuid) {
+int get_remote_service_record(const RawAddress& remote_addr,
+ const bluetooth::Uuid& uuid) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_get_remote_service_record(remote_addr, uuid);
}
int get_remote_services(RawAddress* remote_addr) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_get_remote_services(*remote_addr);
}
static int start_discovery(void) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_start_discovery();
}
static int cancel_discovery(void) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_cancel_discovery();
}
static int create_bond(const RawAddress* bd_addr, int transport) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_create_bond(bd_addr, transport);
}
@@ -250,14 +258,14 @@
static int create_bond_out_of_band(const RawAddress* bd_addr, int transport,
const bt_out_of_band_data_t* oob_data) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_create_bond_out_of_band(bd_addr, transport, oob_data);
}
static int cancel_bond(const RawAddress* bd_addr) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_cancel_bond(bd_addr);
}
@@ -267,14 +275,14 @@
return BT_STATUS_SUCCESS;
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_remove_bond(bd_addr);
}
static int get_connection_state(const RawAddress* bd_addr) {
/* sanity check */
- if (interface_ready() == false) return 0;
+ if (!interface_ready()) return 0;
return btif_dm_get_connection_state(bd_addr);
}
@@ -282,7 +290,7 @@
static int pin_reply(const RawAddress* bd_addr, uint8_t accept, uint8_t pin_len,
bt_pin_code_t* pin_code) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_pin_reply(bd_addr, accept, pin_len, pin_code);
}
@@ -290,33 +298,31 @@
static int ssp_reply(const RawAddress* bd_addr, bt_ssp_variant_t variant,
uint8_t accept, uint32_t passkey) {
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_ssp_reply(bd_addr, variant, accept, passkey);
}
static int read_energy_info() {
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
btif_dm_read_energy_info();
return BT_STATUS_SUCCESS;
}
static void dump(int fd, const char** arguments) {
- if (arguments != NULL && arguments[0] != NULL) {
- if (strncmp(arguments[0], "--proto-bin", 11) == 0) {
- system_bt_osi::BluetoothMetricsLogger::GetInstance()->WriteBase64(fd,
- true);
- return;
- }
- }
btif_debug_conn_dump(fd);
btif_debug_bond_event_dump(fd);
btif_debug_a2dp_dump(fd);
+ btif_debug_av_dump(fd);
+ bta_debug_av_dump(fd);
+ stack_debug_avdtp_api_dump(fd);
+ bluetooth::avrcp::AvrcpService::DebugDump(fd);
btif_debug_config_dump(fd);
BTA_HfClientDumpStatistics(fd);
wakelock_debug_dump(fd);
osi_allocator_debug_dump(fd);
alarm_debug_dump(fd);
+ HearingAid::DebugDump(fd);
#if (BTSNOOP_MEM == TRUE)
btif_debug_btsnoop_dump(fd);
#endif
@@ -324,15 +330,19 @@
close(fd);
}
+static void dumpMetrics(std::string* output) {
+ system_bt_osi::BluetoothMetricsLogger::GetInstance()->WriteString(output);
+}
+
static const void* get_profile_interface(const char* profile_id) {
LOG_INFO(LOG_TAG, "%s: id = %s", __func__, profile_id);
/* sanity check */
- if (interface_ready() == false) return NULL;
+ if (!interface_ready()) return NULL;
/* check for supported profile interfaces */
if (is_profile(profile_id, BT_PROFILE_HANDSFREE_ID))
- return btif_hf_get_interface();
+ return bluetooth::headset::GetInterface();
if (is_profile(profile_id, BT_PROFILE_HANDSFREE_CLIENT_ID))
return btif_hf_client_get_interface();
@@ -373,6 +383,8 @@
if (is_profile(profile_id, BT_TEST_INTERFACE_MCAP_ID))
return stack_mcap_get_interface();
+ if (is_profile(profile_id, BT_PROFILE_HEARING_AID_ID))
+ return btif_hearing_aid_get_interface();
return NULL;
}
@@ -380,7 +392,7 @@
LOG_INFO(LOG_TAG, "%s", __func__);
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dut_mode_configure(enable);
}
@@ -389,7 +401,7 @@
LOG_INFO(LOG_TAG, "%s", __func__);
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dut_mode_send(opcode, buf, len);
}
@@ -398,7 +410,7 @@
LOG_INFO(LOG_TAG, "%s", __func__);
/* sanity check */
- if (interface_ready() == false) return BT_STATUS_NOT_READY;
+ if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_le_test_mode(opcode, buf, len);
}
@@ -413,7 +425,11 @@
return btif_config_clear() ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
-static const bt_interface_t bluetoothInterface = {
+static bluetooth::avrcp::ServiceInterface* get_avrcp_service(void) {
+ return bluetooth::avrcp::AvrcpService::GetServiceInterface();
+}
+
+EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
sizeof(bluetoothInterface),
init,
enable,
@@ -443,44 +459,9 @@
set_os_callouts,
read_energy_info,
dump,
+ dumpMetrics,
config_clear,
interop_database_clear,
interop_database_add,
+ get_avrcp_service,
};
-
-const bt_interface_t* bluetooth__get_bluetooth_interface() {
- /* fixme -- add property to disable bt interface ? */
-
- return &bluetoothInterface;
-}
-
-static int close_bluetooth_stack(UNUSED_ATTR struct hw_device_t* device) {
- cleanup();
- return 0;
-}
-
-static int open_bluetooth_stack(const struct hw_module_t* module,
- UNUSED_ATTR char const* name,
- struct hw_device_t** abstraction) {
- static bluetooth_device_t device;
- device.common.tag = HARDWARE_DEVICE_TAG;
- device.common.version = 0;
- device.common.close = close_bluetooth_stack;
- device.get_bluetooth_interface = bluetooth__get_bluetooth_interface;
- device.common.module = (struct hw_module_t*)module;
- *abstraction = (struct hw_device_t*)&device;
- return 0;
-}
-
-static struct hw_module_methods_t bt_stack_module_methods = {
- .open = open_bluetooth_stack,
-};
-
-EXPORT_SYMBOL struct hw_module_t HAL_MODULE_INFO_SYM = {
- .tag = HARDWARE_MODULE_TAG,
- .version_major = 1,
- .version_minor = 0,
- .id = BT_HARDWARE_MODULE_ID,
- .name = "Bluetooth Stack",
- .author = "The Android Open Source Project",
- .methods = &bt_stack_module_methods};
diff --git a/btif/src/btif_a2dp.cc b/btif/src/btif_a2dp.cc
index 62a217a..86485d4 100644
--- a/btif/src/btif_a2dp.cc
+++ b/btif/src/btif_a2dp.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,16 +25,19 @@
#include "bt_common.h"
#include "bta_av_api.h"
#include "btif_a2dp.h"
+#include "btif_a2dp_audio_interface.h"
#include "btif_a2dp_control.h"
#include "btif_a2dp_sink.h"
#include "btif_a2dp_source.h"
#include "btif_av.h"
+#include "btif_av_co.h"
+#include "btif_hf.h"
#include "btif_util.h"
#include "osi/include/log.h"
void btif_a2dp_on_idle(void) {
- APPL_TRACE_WARNING("## ON A2DP IDLE ## peer_sep = %d",
- btif_av_get_peer_sep());
+ LOG_INFO(LOG_TAG, "%s: ## ON A2DP IDLE ## peer_sep = %d", __func__,
+ btif_av_get_peer_sep());
if (btif_av_get_peer_sep() == AVDT_TSEP_SNK) {
btif_a2dp_source_on_idle();
} else if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) {
@@ -42,88 +45,138 @@
}
}
-bool btif_a2dp_on_started(tBTA_AV_START* p_av_start, bool pending_start) {
+bool btif_a2dp_on_started(const RawAddress& peer_addr,
+ tBTA_AV_START* p_av_start, bool pending_start) {
bool ack = false;
- APPL_TRACE_WARNING("## ON A2DP STARTED ##");
+ LOG_INFO(LOG_TAG,
+ "%s: ## ON A2DP STARTED ## peer %s pending_start:%s p_av_start:%p",
+ __func__, peer_addr.ToString().c_str(),
+ logbool(pending_start).c_str(), p_av_start);
if (p_av_start == NULL) {
/* ack back a local start request */
- btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
+
+ if (!btif_av_is_a2dp_offload_enabled()) {
+ btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
+ return true;
+ } else if (bluetooth::headset::IsCallIdle()) {
+ btif_av_stream_start_offload();
+ } else {
+ LOG_ERROR(LOG_TAG, "%s: peer %s call in progress, do not start offload",
+ __func__, peer_addr.ToString().c_str());
+ btif_a2dp_audio_on_started(A2DP_CTRL_ACK_INCALL_FAILURE);
+ }
return true;
}
- APPL_TRACE_WARNING(
- "%s: pending_start = %d status = %d suspending = %d initiator = %d",
- __func__, pending_start, p_av_start->status, p_av_start->suspending,
- p_av_start->initiator);
+ LOG_INFO(LOG_TAG,
+ "%s: peer %s pending_start:%s status:%d suspending:%s initiator:%s",
+ __func__, peer_addr.ToString().c_str(),
+ logbool(pending_start).c_str(), p_av_start->status,
+ logbool(p_av_start->suspending).c_str(),
+ logbool(p_av_start->initiator).c_str());
if (p_av_start->status == BTA_AV_SUCCESS) {
if (!p_av_start->suspending) {
if (p_av_start->initiator) {
if (pending_start) {
- btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
+ if (btif_av_is_a2dp_offload_enabled()) {
+ btif_av_stream_start_offload();
+ } else {
+ btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
+ }
ack = true;
}
} else {
- /* We were remotely started, make sure codec
- * is setup before datapath is started.
- */
- btif_a2dp_source_setup_codec();
+ // We were started remotely
+ if (btif_av_is_a2dp_offload_enabled()) {
+ btif_av_stream_start_offload();
+ }
}
/* media task is autostarted upon a2dp audiopath connection */
}
} else if (pending_start) {
- APPL_TRACE_WARNING("%s: A2DP start request failed: status = %d", __func__,
- p_av_start->status);
- btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+ LOG_ERROR(LOG_TAG, "%s: peer %s A2DP start request failed: status = %d",
+ __func__, peer_addr.ToString().c_str(), p_av_start->status);
+ if (btif_av_is_a2dp_offload_enabled()) {
+ btif_a2dp_audio_on_started(p_av_start->status);
+ } else {
+ btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+ }
ack = true;
}
return ack;
}
void btif_a2dp_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) {
- APPL_TRACE_WARNING("## ON A2DP STOPPED ##");
+ LOG_INFO(LOG_TAG, "%s: ## ON A2DP STOPPED ## p_av_suspend=%p", __func__,
+ p_av_suspend);
if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) {
btif_a2dp_sink_on_stopped(p_av_suspend);
return;
}
-
- btif_a2dp_source_on_stopped(p_av_suspend);
-}
-
-void btif_a2dp_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) {
- APPL_TRACE_WARNING("## ON A2DP SUSPENDED ##");
- if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) {
- btif_a2dp_sink_on_suspended(p_av_suspend);
- } else {
- btif_a2dp_source_on_suspended(p_av_suspend);
+ if (!btif_av_is_a2dp_offload_enabled()) {
+ btif_a2dp_source_on_stopped(p_av_suspend);
+ } else if (p_av_suspend != NULL) {
+ btif_a2dp_audio_on_stopped(p_av_suspend->status);
}
}
-void btif_a2dp_on_offload_started(tBTA_AV_STATUS status) {
+void btif_a2dp_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) {
+ LOG_INFO(LOG_TAG, "%s: ## ON A2DP SUSPENDED ## p_av_suspend=%p", __func__,
+ p_av_suspend);
+ if (!btif_av_is_a2dp_offload_enabled()) {
+ if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) {
+ btif_a2dp_sink_on_suspended(p_av_suspend);
+ } else {
+ btif_a2dp_source_on_suspended(p_av_suspend);
+ }
+ } else {
+ btif_a2dp_audio_on_suspended(p_av_suspend->status);
+ }
+}
+
+void btif_a2dp_on_offload_started(const RawAddress& peer_addr,
+ tBTA_AV_STATUS status) {
tA2DP_CTRL_ACK ack;
- APPL_TRACE_EVENT("%s status %d", __func__, status);
+ LOG_INFO(LOG_TAG, "%s: peer %s status %d", __func__,
+ peer_addr.ToString().c_str(), status);
switch (status) {
case BTA_AV_SUCCESS:
ack = A2DP_CTRL_ACK_SUCCESS;
break;
case BTA_AV_FAIL_RESOURCES:
- APPL_TRACE_ERROR("%s FAILED UNSUPPORTED", __func__);
+ LOG_ERROR(LOG_TAG, "%s: peer %s FAILED UNSUPPORTED", __func__,
+ peer_addr.ToString().c_str());
ack = A2DP_CTRL_ACK_UNSUPPORTED;
break;
default:
- APPL_TRACE_ERROR("%s FAILED: status = %d", __func__, status);
+ LOG_ERROR(LOG_TAG, "%s: peer %s FAILED: status = %d", __func__,
+ peer_addr.ToString().c_str(), status);
ack = A2DP_CTRL_ACK_FAILURE;
break;
}
- btif_a2dp_command_ack(ack);
+ if (btif_av_is_a2dp_offload_enabled()) {
+ btif_a2dp_audio_on_started(status);
+ if (ack != BTA_AV_SUCCESS && btif_av_stream_started_ready()) {
+ // Offload request will return with failure from btif_av sm if
+ // suspend is triggered for remote start. Disconnect only if SoC
+ // returned failure for offload VSC
+ LOG_ERROR(LOG_TAG, "%s: peer %s offload start failed", __func__,
+ peer_addr.ToString().c_str());
+ btif_av_src_disconnect_sink(peer_addr);
+ }
+ } else {
+ btif_a2dp_command_ack(ack);
+ }
}
void btif_debug_a2dp_dump(int fd) {
btif_a2dp_source_debug_dump(fd);
btif_a2dp_sink_debug_dump(fd);
+ btif_a2dp_codec_debug_dump(fd);
}
diff --git a/btif/src/btif_a2dp_audio_interface.cc b/btif/src/btif_a2dp_audio_interface.cc
new file mode 100644
index 0000000..7343bbe
--- /dev/null
+++ b/btif/src/btif_a2dp_audio_interface.cc
@@ -0,0 +1,506 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2017 Google, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "btif_a2dp_audio_interface"
+
+#include "btif_a2dp_audio_interface.h"
+
+#include <mutex>
+
+#include <a2dp_vendor.h>
+#include <a2dp_vendor_ldac_constants.h>
+#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioHost.h>
+#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioOffload.h>
+#include <android/hardware/bluetooth/a2dp/1.0/types.h>
+#include <base/logging.h>
+#include <hwbinder/ProcessState.h>
+#include <utils/RefBase.h>
+#include "a2dp_sbc.h"
+#include "bt_common.h"
+#include "bta/av/bta_av_int.h"
+#include "btif_a2dp.h"
+#include "btif_a2dp_control.h"
+#include "btif_a2dp_sink.h"
+#include "btif_a2dp_source.h"
+#include "btif_av.h"
+#include "btif_av_co.h"
+#include "btif_hf.h"
+#include "osi/include/metrics.h"
+#include "osi/include/osi.h"
+
+using system_bt_osi::A2dpSessionMetrics;
+using system_bt_osi::BluetoothMetricsLogger;
+
+using android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload;
+using android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost;
+using android::hardware::bluetooth::a2dp::V1_0::Status;
+using android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration;
+using android::hardware::bluetooth::a2dp::V1_0::CodecType;
+using android::hardware::bluetooth::a2dp::V1_0::SampleRate;
+using android::hardware::bluetooth::a2dp::V1_0::BitsPerSample;
+using android::hardware::bluetooth::a2dp::V1_0::ChannelMode;
+using android::hardware::ProcessState;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+using ::android::wp;
+android::sp<IBluetoothAudioOffload> btAudio;
+
+#define CASE_RETURN_STR(const) \
+ case const: \
+ return #const;
+static uint8_t a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
+static Status mapToStatus(uint8_t resp);
+uint8_t btif_a2dp_audio_process_request(uint8_t cmd);
+
+static void btif_a2dp_audio_send_start_req();
+static void btif_a2dp_audio_send_suspend_req();
+static void btif_a2dp_audio_send_stop_req();
+static void btif_a2dp_audio_interface_init();
+static void btif_a2dp_audio_interface_deinit();
+static void btif_a2dp_audio_interface_restart_session();
+// Delay reporting
+// static void btif_a2dp_audio_send_sink_latency();
+
+class A2dpOffloadAudioStats {
+ public:
+ A2dpOffloadAudioStats() { Reset(); }
+ void Reset() {
+ std::lock_guard<std::recursive_mutex> lock(lock_);
+ ResetPreserveSession();
+ codec_index_ = -1;
+ }
+ void ResetPreserveSession() {
+ std::lock_guard<std::recursive_mutex> lock(lock_);
+ audio_start_time_ms_ = -1;
+ audio_stop_time_ms_ = -1;
+ }
+ void StoreMetrics() {
+ std::lock_guard<std::recursive_mutex> lock(lock_);
+ if (audio_start_time_ms_ < 0 || audio_stop_time_ms_ < 0) {
+ return;
+ }
+ A2dpSessionMetrics metrics;
+ metrics.codec_index = codec_index_;
+ metrics.is_a2dp_offload = true;
+ if (audio_stop_time_ms_ > audio_start_time_ms_) {
+ metrics.audio_duration_ms = audio_stop_time_ms_ - audio_start_time_ms_;
+ }
+ BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics);
+ }
+ void LogAudioStart() {
+ std::lock_guard<std::recursive_mutex> lock(lock_);
+ audio_start_time_ms_ = time_get_os_boottime_ms();
+ }
+ void LogAudioStop() {
+ std::lock_guard<std::recursive_mutex> lock(lock_);
+ audio_stop_time_ms_ = time_get_os_boottime_ms();
+ }
+ void LogAudioStopMetricsAndReset() {
+ std::lock_guard<std::recursive_mutex> lock(lock_);
+ LogAudioStop();
+ StoreMetrics();
+ ResetPreserveSession();
+ }
+ void SetCodecIndex(int64_t codec_index) {
+ std::lock_guard<std::recursive_mutex> lock(lock_);
+ codec_index_ = codec_index;
+ }
+
+ private:
+ std::recursive_mutex lock_;
+ int64_t audio_start_time_ms_ = -1;
+ int64_t audio_stop_time_ms_ = -1;
+ int64_t codec_index_ = -1;
+};
+
+static A2dpOffloadAudioStats a2dp_offload_audio_stats;
+
+class BluetoothAudioHost : public IBluetoothAudioHost {
+ public:
+ Return<void> startStream() {
+ btif_a2dp_audio_send_start_req();
+ return Void();
+ }
+ Return<void> suspendStream() {
+ btif_a2dp_audio_send_suspend_req();
+ return Void();
+ }
+ Return<void> stopStream() {
+ btif_a2dp_audio_send_stop_req();
+ return Void();
+ }
+
+ // TODO : Delay reporting
+ /* Return<void> a2dp_get_sink_latency() {
+ LOG_INFO(LOG_TAG,"%s:start ", __func__);
+ btif_a2dp_audio_send_sink_latency();
+ return Void();
+ }*/
+};
+
+class BluetoothAudioDeathRecipient : public hidl_death_recipient {
+ public:
+ virtual void serviceDied(
+ uint64_t /*cookie*/,
+ const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+ LOG_ERROR(LOG_TAG, "%s", __func__);
+ // Restart the session on the correct thread
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&btif_a2dp_audio_interface_restart_session));
+ }
+};
+sp<BluetoothAudioDeathRecipient> bluetoothAudioDeathRecipient =
+ new BluetoothAudioDeathRecipient();
+
+static Status mapToStatus(uint8_t resp) {
+ switch (resp) {
+ case A2DP_CTRL_ACK_SUCCESS:
+ return Status::SUCCESS;
+ break;
+ case A2DP_CTRL_ACK_PENDING:
+ return Status::PENDING;
+ break;
+ case A2DP_CTRL_ACK_FAILURE:
+ case A2DP_CTRL_ACK_INCALL_FAILURE:
+ case A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS:
+ return Status::FAILURE;
+ default:
+ APPL_TRACE_WARNING("%s: unknown status recevied :%d", __func__, resp);
+ return Status::FAILURE;
+ break;
+ }
+}
+
+static void btif_a2dp_get_codec_configuration(
+ CodecConfiguration* p_codec_info) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ tBT_A2DP_OFFLOAD a2dp_offload;
+ A2dpCodecConfig* a2dpCodecConfig = bta_av_get_a2dp_current_codec();
+ a2dpCodecConfig->getCodecSpecificConfig(&a2dp_offload);
+ btav_a2dp_codec_config_t codec_config;
+ codec_config = a2dpCodecConfig->getCodecConfig();
+ a2dp_offload_audio_stats.SetCodecIndex(a2dpCodecConfig->codecIndex());
+ switch (codec_config.codec_type) {
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
+ p_codec_info->codecType =
+ (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
+ BTA_AV_CODEC_TYPE_SBC;
+ p_codec_info->codecSpecific.sbcData.codecParameters =
+ a2dp_offload.codec_info[0];
+ LOG_INFO(LOG_TAG, " %s: codec parameters =%d", __func__,
+ a2dp_offload.codec_info[0]);
+ p_codec_info->codecSpecific.sbcData.minBitpool =
+ a2dp_offload.codec_info[1];
+ p_codec_info->codecSpecific.sbcData.maxBitpool =
+ a2dp_offload.codec_info[2];
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
+ p_codec_info->codecType =
+ (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
+ BTA_AV_CODEC_TYPE_AAC;
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
+ p_codec_info->codecType =
+ (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
+ BTA_AV_CODEC_TYPE_APTX;
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
+ p_codec_info->codecType =
+ (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
+ BTA_AV_CODEC_TYPE_APTXHD;
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
+ p_codec_info->codecType =
+ (::android::hardware::bluetooth::a2dp::V1_0::CodecType)
+ BTA_AV_CODEC_TYPE_LDAC;
+ p_codec_info->codecSpecific.ldacData.bitrateIndex =
+ a2dp_offload.codec_info[6];
+ break;
+ default:
+ APPL_TRACE_ERROR("%s: Unknown Codec type :%d ", __func__,
+ codec_config.codec_type);
+ }
+
+ // Obtain the MTU
+ RawAddress peer_addr = btif_av_source_active_peer();
+ tA2DP_ENCODER_INIT_PEER_PARAMS peer_param;
+ bta_av_co_get_peer_params(peer_addr, &peer_param);
+ int effectiveMtu = a2dpCodecConfig->getEffectiveMtu();
+ if (effectiveMtu > 0 && effectiveMtu < peer_param.peer_mtu) {
+ p_codec_info->peerMtu = effectiveMtu;
+ } else {
+ p_codec_info->peerMtu = peer_param.peer_mtu;
+ }
+ LOG_INFO(LOG_TAG, "%s: peer MTU: %d effective MTU: %d result MTU: %d",
+ __func__, peer_param.peer_mtu, effectiveMtu, p_codec_info->peerMtu);
+
+ p_codec_info->sampleRate =
+ (::android::hardware::bluetooth::a2dp::V1_0::SampleRate)
+ codec_config.sample_rate;
+ p_codec_info->bitsPerSample =
+ (::android::hardware::bluetooth::a2dp::V1_0::BitsPerSample)
+ codec_config.bits_per_sample;
+ p_codec_info->channelMode =
+ (::android::hardware::bluetooth::a2dp::V1_0::ChannelMode)
+ codec_config.channel_mode;
+ p_codec_info->encodedAudioBitrate = a2dpCodecConfig->getTrackBitRate();
+}
+
+static void btif_a2dp_audio_interface_init() {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+
+ btAudio = IBluetoothAudioOffload::getService();
+ CHECK(btAudio != nullptr);
+
+ auto death_link = btAudio->linkToDeath(bluetoothAudioDeathRecipient, 0);
+ if (!death_link.isOk()) {
+ LOG_ERROR(LOG_TAG, "%s: Cannot observe the Bluetooth Audio HAL's death",
+ __func__);
+ }
+
+ LOG_DEBUG(
+ LOG_TAG, "%s: IBluetoothAudioOffload::getService() returned %p (%s)",
+ __func__, btAudio.get(), (btAudio->isRemote() ? "remote" : "local"));
+
+ LOG_INFO(LOG_TAG, "%s:Init returned", __func__);
+}
+
+static void btif_a2dp_audio_interface_deinit() {
+ LOG_INFO(LOG_TAG, "%s: start", __func__);
+ if (btAudio != nullptr) {
+ auto death_unlink = btAudio->unlinkToDeath(bluetoothAudioDeathRecipient);
+ if (!death_unlink.isOk()) {
+ LOG_ERROR(LOG_TAG,
+ "%s: Error unlinking death observer from Bluetooth Audio HAL",
+ __func__);
+ }
+ }
+ btAudio = nullptr;
+}
+
+void btif_a2dp_audio_interface_start_session() {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+ system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+ a2dp_offload_audio_stats.Reset();
+ btif_a2dp_audio_interface_init();
+ CHECK(btAudio != nullptr);
+ CodecConfiguration codec_info;
+ btif_a2dp_get_codec_configuration(&codec_info);
+ android::sp<IBluetoothAudioHost> host_if = new BluetoothAudioHost();
+ btAudio->startSession(host_if, codec_info);
+}
+
+void btif_a2dp_audio_interface_end_session() {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
+ BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+ system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+ a2dp_offload_audio_stats.Reset();
+ if (btAudio == nullptr) return;
+ auto ret = btAudio->endSession();
+ if (!ret.isOk()) {
+ LOG_ERROR(LOG_TAG, "HAL server is dead");
+ }
+ btif_a2dp_audio_interface_deinit();
+}
+
+// Conditionally restart the session only if it was started before
+static void btif_a2dp_audio_interface_restart_session() {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ if (btAudio == nullptr) {
+ LOG_INFO(LOG_TAG, "%s: nothing to restart - session was not started",
+ __func__);
+ return;
+ }
+ btAudio = nullptr;
+ btif_a2dp_audio_interface_start_session();
+}
+
+void btif_a2dp_audio_on_started(tBTA_AV_STATUS status) {
+ LOG_INFO(LOG_TAG, "%s: status = %d", __func__, status);
+ if (btAudio != nullptr) {
+ if (a2dp_cmd_pending == A2DP_CTRL_CMD_START) {
+ LOG_INFO(LOG_TAG, "%s: calling method onStarted", __func__);
+ auto hal_status = mapToStatus(status);
+ btAudio->streamStarted(hal_status);
+ if (hal_status == Status::SUCCESS) {
+ a2dp_offload_audio_stats.LogAudioStart();
+ }
+ }
+ }
+}
+
+void btif_a2dp_audio_on_suspended(tBTA_AV_STATUS status) {
+ LOG_INFO(LOG_TAG, "%s: status = %d", __func__, status);
+ if (btAudio != nullptr) {
+ if (a2dp_cmd_pending == A2DP_CTRL_CMD_SUSPEND) {
+ LOG_INFO(LOG_TAG, "calling method onSuspended");
+ auto hal_status = mapToStatus(status);
+ btAudio->streamSuspended(hal_status);
+ if (hal_status == Status::SUCCESS) {
+ a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
+ }
+ }
+ }
+}
+
+void btif_a2dp_audio_on_stopped(tBTA_AV_STATUS status) {
+ LOG_INFO(LOG_TAG, "%s: status = %d", __func__, status);
+ if (btAudio != nullptr && a2dp_cmd_pending == A2DP_CTRL_CMD_START) {
+ LOG_INFO(LOG_TAG, "%s: Remote disconnected when start under progress",
+ __func__);
+ btAudio->streamStarted(mapToStatus(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS));
+ a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
+ }
+}
+void btif_a2dp_audio_send_start_req() {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ uint8_t resp;
+ resp = btif_a2dp_audio_process_request(A2DP_CTRL_CMD_START);
+ if (btAudio != nullptr) {
+ auto status = mapToStatus(resp);
+ auto ret = btAudio->streamStarted(status);
+ if (status == Status::SUCCESS) {
+ a2dp_offload_audio_stats.LogAudioStart();
+ }
+ if (!ret.isOk()) LOG_ERROR(LOG_TAG, "HAL server died");
+ }
+}
+void btif_a2dp_audio_send_suspend_req() {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ uint8_t resp;
+ resp = btif_a2dp_audio_process_request(A2DP_CTRL_CMD_SUSPEND);
+ if (btAudio != nullptr) {
+ auto status = mapToStatus(resp);
+ auto ret = btAudio->streamSuspended(status);
+ if (status == Status::SUCCESS) {
+ a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
+ }
+ if (!ret.isOk()) LOG_ERROR(LOG_TAG, "HAL server died");
+ }
+}
+
+void btif_a2dp_audio_send_stop_req() {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ btif_a2dp_audio_process_request(A2DP_CTRL_CMD_STOP);
+ a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
+}
+
+/*void btif_a2dp_audio_send_sink_latency()
+{
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ uint16_t sink_latency = btif_av_get_sink_latency();
+ if (btAudio != nullptr) {
+ auto ret = btAudio->a2dp_on_get_sink_latency(sink_latency);
+ if (!ret.isOk()) LOG_ERROR(LOG_TAG, "server died");
+ }
+}*/
+
+uint8_t btif_a2dp_audio_process_request(uint8_t cmd) {
+ LOG_INFO(LOG_TAG, "%s: cmd: %s", __func__,
+ audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd));
+ a2dp_cmd_pending = cmd;
+ uint8_t status;
+ switch (cmd) {
+ case A2DP_CTRL_CMD_START:
+ /*
+ * Don't send START request to stack while we are in a call.
+ * Some headsets such as "Sony MW600", don't allow AVDTP START
+ * while in a call, and respond with BAD_STATE.
+ */
+ if (!bluetooth::headset::IsCallIdle()) {
+ APPL_TRACE_WARNING("%s: A2DP command %s failed as call state is busy",
+ __func__,
+ audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd));
+ status = A2DP_CTRL_ACK_INCALL_FAILURE;
+ break;
+ }
+ if (btif_av_stream_started_ready()) {
+ /*
+ * Already started, setup audio data channel listener and ACK
+ * back immediately.
+ */
+ status = A2DP_CTRL_ACK_SUCCESS;
+ break;
+ }
+ if (btif_av_stream_ready()) {
+ /*
+ * Post start event and wait for audio path to open.
+ * If we are the source, the ACK will be sent after the start
+ * procedure is completed, othewise send it now.
+ */
+ btif_av_stream_start();
+ if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) {
+ status = A2DP_CTRL_ACK_SUCCESS;
+ break;
+ }
+ /*Return pending and ack when start stream cfm received from remote*/
+ status = A2DP_CTRL_ACK_PENDING;
+ break;
+ }
+
+ APPL_TRACE_WARNING("%s: A2DP command %s while AV stream is not ready",
+ __func__,
+ audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd));
+ return A2DP_CTRL_ACK_FAILURE;
+ break;
+
+ case A2DP_CTRL_CMD_STOP:
+ if (btif_av_get_peer_sep() == AVDT_TSEP_SNK &&
+ !btif_a2dp_source_is_streaming()) {
+ /* We are already stopped, just ack back */
+ status = A2DP_CTRL_ACK_SUCCESS;
+ break;
+ }
+ btif_av_stream_stop(RawAddress::kEmpty);
+ return A2DP_CTRL_ACK_SUCCESS;
+ break;
+
+ case A2DP_CTRL_CMD_SUSPEND:
+ /* Local suspend */
+ if (btif_av_stream_started_ready()) {
+ btif_av_stream_suspend();
+ status = A2DP_CTRL_ACK_PENDING;
+ break;
+ }
+ /* If we are not in started state, just ack back ok and let
+ * audioflinger close the channel. This can happen if we are
+ * remotely suspended, clear REMOTE SUSPEND flag.
+ */
+ btif_av_clear_remote_suspend_flag();
+ status = A2DP_CTRL_ACK_SUCCESS;
+ break;
+
+ case A2DP_CTRL_CMD_OFFLOAD_START:
+ btif_av_stream_start_offload();
+ status = A2DP_CTRL_ACK_PENDING;
+ break;
+
+ default:
+ APPL_TRACE_ERROR("UNSUPPORTED CMD (%d)", cmd);
+ status = A2DP_CTRL_ACK_FAILURE;
+ break;
+ }
+ LOG_INFO(LOG_TAG, "a2dp-ctrl-cmd : %s DONE returning status %d",
+ audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd), status);
+ return status;
+}
diff --git a/btif/src/btif_a2dp_control.cc b/btif/src/btif_a2dp_control.cc
index af59644..fb62480 100644
--- a/btif/src/btif_a2dp_control.cc
+++ b/btif/src/btif_a2dp_control.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,20 +37,27 @@
#define A2DP_DATA_READ_POLL_MS 10
+struct {
+ uint64_t total_bytes_read = 0;
+ uint16_t audio_delay = 0;
+ struct timespec timestamp = {};
+} delay_report_stats;
+
static void btif_a2dp_data_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
static void btif_a2dp_ctrl_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
/* We can have max one command pending */
static tA2DP_CTRL_CMD a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
+std::unique_ptr<tUIPC_STATE> a2dp_uipc;
void btif_a2dp_control_init(void) {
- UIPC_Init(NULL);
- UIPC_Open(UIPC_CH_ID_AV_CTRL, btif_a2dp_ctrl_cb);
+ a2dp_uipc = UIPC_Init();
+ UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, btif_a2dp_ctrl_cb, A2DP_CTRL_PATH);
}
void btif_a2dp_control_cleanup(void) {
/* This calls blocks until UIPC is fully closed */
- UIPC_Close(UIPC_CH_ID_ALL);
+ UIPC_Close(*a2dp_uipc, UIPC_CH_ID_ALL);
}
static void btif_a2dp_recv_ctrl_data(void) {
@@ -58,20 +65,27 @@
int n;
uint8_t read_cmd = 0; /* The read command size is one octet */
- n = UIPC_Read(UIPC_CH_ID_AV_CTRL, NULL, &read_cmd, 1);
+ n = UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, NULL, &read_cmd, 1);
cmd = static_cast<tA2DP_CTRL_CMD>(read_cmd);
/* detach on ctrl channel means audioflinger process was terminated */
if (n == 0) {
APPL_TRACE_WARNING("%s: CTRL CH DETACHED", __func__);
- UIPC_Close(UIPC_CH_ID_AV_CTRL);
+ UIPC_Close(*a2dp_uipc, UIPC_CH_ID_AV_CTRL);
return;
}
- APPL_TRACE_WARNING("%s: a2dp-ctrl-cmd : %s", __func__,
+ // Don't log A2DP_CTRL_GET_PRESENTATION_POSITION by default, because it
+ // could be very chatty when audio is streaming.
+ if (cmd == A2DP_CTRL_GET_PRESENTATION_POSITION) {
+ APPL_TRACE_DEBUG("%s: a2dp-ctrl-cmd : %s", __func__,
audio_a2dp_hw_dump_ctrl_event(cmd));
- a2dp_cmd_pending = cmd;
+ } else {
+ APPL_TRACE_WARNING("%s: a2dp-ctrl-cmd : %s", __func__,
+ audio_a2dp_hw_dump_ctrl_event(cmd));
+ }
+ a2dp_cmd_pending = cmd;
switch (cmd) {
case A2DP_CTRL_CMD_CHECK_READY:
if (btif_a2dp_source_media_task_is_shutting_down()) {
@@ -97,7 +111,9 @@
* Some headsets such as "Sony MW600", don't allow AVDTP START
* while in a call, and respond with BAD_STATE.
*/
- if (!btif_hf_is_call_idle()) {
+ if (!bluetooth::headset::IsCallIdle()) {
+ APPL_TRACE_WARNING("%s: A2DP command %s while call state is busy",
+ __func__, audio_a2dp_hw_dump_ctrl_event(cmd));
btif_a2dp_command_ack(A2DP_CTRL_ACK_INCALL_FAILURE);
break;
}
@@ -111,14 +127,15 @@
if (btif_av_stream_ready()) {
/* Setup audio data channel listener */
- UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
+ UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb,
+ A2DP_DATA_PATH);
/*
* Post start event and wait for audio path to open.
* If we are the source, the ACK will be sent after the start
* procedure is completed, othewise send it now.
*/
- btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
+ btif_av_stream_start();
if (btif_av_get_peer_sep() == AVDT_TSEP_SRC)
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
break;
@@ -129,7 +146,8 @@
* Already started, setup audio data channel listener and ACK
* back immediately.
*/
- UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
+ UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb,
+ A2DP_DATA_PATH);
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
break;
}
@@ -145,15 +163,14 @@
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
break;
}
-
- btif_dispatch_sm_event(BTIF_AV_STOP_STREAM_REQ_EVT, NULL, 0);
+ btif_av_stream_stop(RawAddress::kEmpty);
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
break;
case A2DP_CTRL_CMD_SUSPEND:
/* Local suspend */
if (btif_av_stream_started_ready()) {
- btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+ btif_av_stream_suspend();
break;
}
/* If we are not in started state, just ack back ok and let
@@ -169,9 +186,10 @@
tA2DP_CHANNEL_COUNT channel_count = btif_a2dp_sink_get_channel_count();
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
- UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, reinterpret_cast<uint8_t*>(&sample_rate),
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<uint8_t*>(&sample_rate),
sizeof(tA2DP_SAMPLE_RATE));
- UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, &channel_count,
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0, &channel_count,
sizeof(tA2DP_CHANNEL_COUNT));
break;
}
@@ -194,25 +212,27 @@
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
// Send the current codec config
- UIPC_Send(UIPC_CH_ID_AV_CTRL, 0,
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
reinterpret_cast<const uint8_t*>(&codec_config.sample_rate),
sizeof(btav_a2dp_codec_sample_rate_t));
- UIPC_Send(UIPC_CH_ID_AV_CTRL, 0,
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
reinterpret_cast<const uint8_t*>(&codec_config.bits_per_sample),
sizeof(btav_a2dp_codec_bits_per_sample_t));
- UIPC_Send(UIPC_CH_ID_AV_CTRL, 0,
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
reinterpret_cast<const uint8_t*>(&codec_config.channel_mode),
sizeof(btav_a2dp_codec_channel_mode_t));
// Send the current codec capability
- UIPC_Send(UIPC_CH_ID_AV_CTRL, 0,
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
reinterpret_cast<const uint8_t*>(&codec_capability.sample_rate),
sizeof(btav_a2dp_codec_sample_rate_t));
- UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, reinterpret_cast<const uint8_t*>(
- &codec_capability.bits_per_sample),
- sizeof(btav_a2dp_codec_bits_per_sample_t));
- UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, reinterpret_cast<const uint8_t*>(
- &codec_capability.channel_mode),
- sizeof(btav_a2dp_codec_channel_mode_t));
+ UIPC_Send(
+ *a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<const uint8_t*>(&codec_capability.bits_per_sample),
+ sizeof(btav_a2dp_codec_bits_per_sample_t));
+ UIPC_Send(
+ *a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
+ reinterpret_cast<const uint8_t*>(&codec_capability.channel_mode),
+ sizeof(btav_a2dp_codec_channel_mode_t));
break;
}
@@ -224,7 +244,7 @@
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
// Send the current codec config
- if (UIPC_Read(UIPC_CH_ID_AV_CTRL, 0,
+ if (UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
reinterpret_cast<uint8_t*>(&codec_config.sample_rate),
sizeof(btav_a2dp_codec_sample_rate_t)) !=
sizeof(btav_a2dp_codec_sample_rate_t)) {
@@ -232,7 +252,7 @@
__func__);
break;
}
- if (UIPC_Read(UIPC_CH_ID_AV_CTRL, 0,
+ if (UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
reinterpret_cast<uint8_t*>(&codec_config.bits_per_sample),
sizeof(btav_a2dp_codec_bits_per_sample_t)) !=
sizeof(btav_a2dp_codec_bits_per_sample_t)) {
@@ -240,7 +260,7 @@
__func__);
break;
}
- if (UIPC_Read(UIPC_CH_ID_AV_CTRL, 0,
+ if (UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
reinterpret_cast<uint8_t*>(&codec_config.channel_mode),
sizeof(btav_a2dp_codec_channel_mode_t)) !=
sizeof(btav_a2dp_codec_channel_mode_t)) {
@@ -259,22 +279,55 @@
}
case A2DP_CTRL_CMD_OFFLOAD_START:
- btif_dispatch_sm_event(BTIF_AV_OFFLOAD_START_REQ_EVT, NULL, 0);
+ btif_av_stream_start_offload();
break;
+ case A2DP_CTRL_GET_PRESENTATION_POSITION: {
+ btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
+
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
+ (uint8_t*)&(delay_report_stats.total_bytes_read),
+ sizeof(uint64_t));
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0,
+ (uint8_t*)&(delay_report_stats.audio_delay), sizeof(uint16_t));
+
+ uint32_t seconds = delay_report_stats.timestamp.tv_sec;
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0, (uint8_t*)&seconds,
+ sizeof(seconds));
+
+ uint32_t nsec = delay_report_stats.timestamp.tv_nsec;
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0, (uint8_t*)&nsec,
+ sizeof(nsec));
+ break;
+ }
default:
APPL_TRACE_ERROR("%s: UNSUPPORTED CMD (%d)", __func__, cmd);
btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
break;
}
- APPL_TRACE_WARNING("%s: a2dp-ctrl-cmd : %s DONE", __func__,
+
+ // Don't log A2DP_CTRL_GET_PRESENTATION_POSITION by default, because it
+ // could be very chatty when audio is streaming.
+ if (cmd == A2DP_CTRL_GET_PRESENTATION_POSITION) {
+ APPL_TRACE_DEBUG("%s: a2dp-ctrl-cmd : %s DONE", __func__,
audio_a2dp_hw_dump_ctrl_event(cmd));
+ } else {
+ APPL_TRACE_WARNING("%s: a2dp-ctrl-cmd : %s DONE", __func__,
+ audio_a2dp_hw_dump_ctrl_event(cmd));
+ }
}
static void btif_a2dp_ctrl_cb(UNUSED_ATTR tUIPC_CH_ID ch_id,
tUIPC_EVENT event) {
- APPL_TRACE_WARNING("%s: A2DP-CTRL-CHANNEL EVENT %s", __func__,
+ // Don't log UIPC_RX_DATA_READY_EVT by default, because it
+ // could be very chatty when audio is streaming.
+ if (event == UIPC_RX_DATA_READY_EVT) {
+ APPL_TRACE_DEBUG("%s: A2DP-CTRL-CHANNEL EVENT %s", __func__,
dump_uipc_event(event));
+ } else {
+ APPL_TRACE_WARNING("%s: A2DP-CTRL-CHANNEL EVENT %s", __func__,
+ dump_uipc_event(event));
+ }
switch (event) {
case UIPC_OPEN_EVT:
@@ -283,7 +336,8 @@
case UIPC_CLOSE_EVT:
/* restart ctrl server unless we are shutting down */
if (btif_a2dp_source_media_task_is_running())
- UIPC_Open(UIPC_CH_ID_AV_CTRL, btif_a2dp_ctrl_cb);
+ UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, btif_a2dp_ctrl_cb,
+ A2DP_CTRL_PATH);
break;
case UIPC_RX_DATA_READY_EVT:
@@ -308,8 +362,9 @@
* Read directly from media task from here on (keep callback for
* connection events.
*/
- UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REG_REMOVE_ACTIVE_READSET, NULL);
- UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO,
+ UIPC_Ioctl(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO,
+ UIPC_REG_REMOVE_ACTIVE_READSET, NULL);
+ UIPC_Ioctl(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO,
reinterpret_cast<void*>(A2DP_DATA_READ_POLL_MS));
if (btif_av_get_peer_sep() == AVDT_TSEP_SNK) {
@@ -330,7 +385,7 @@
*/
if (btif_a2dp_source_is_streaming()) {
/* Post stop event and wait for audio path to stop */
- btif_dispatch_sm_event(BTIF_AV_STOP_STREAM_REQ_EVT, NULL, 0);
+ btif_av_stream_stop(RawAddress::kEmpty);
}
break;
@@ -344,8 +399,15 @@
void btif_a2dp_command_ack(tA2DP_CTRL_ACK status) {
uint8_t ack = status;
- APPL_TRACE_WARNING("%s: ## a2dp ack : %s, status %d ##", __func__,
+ // Don't log A2DP_CTRL_GET_PRESENTATION_POSITION by default, because it
+ // could be very chatty when audio is streaming.
+ if (a2dp_cmd_pending == A2DP_CTRL_GET_PRESENTATION_POSITION) {
+ APPL_TRACE_DEBUG("%s: ## a2dp ack : %s, status %d ##", __func__,
audio_a2dp_hw_dump_ctrl_event(a2dp_cmd_pending), status);
+ } else {
+ APPL_TRACE_WARNING("%s: ## a2dp ack : %s, status %d ##", __func__,
+ audio_a2dp_hw_dump_ctrl_event(a2dp_cmd_pending), status);
+ }
/* Sanity check */
if (a2dp_cmd_pending == A2DP_CTRL_CMD_NONE) {
@@ -357,5 +419,22 @@
a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
/* Acknowledge start request */
- UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, &ack, sizeof(ack));
+ UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0, &ack, sizeof(ack));
+}
+
+void btif_a2dp_control_log_bytes_read(uint32_t bytes_read) {
+ delay_report_stats.total_bytes_read += bytes_read;
+ clock_gettime(CLOCK_MONOTONIC, &delay_report_stats.timestamp);
+}
+
+void btif_a2dp_control_set_audio_delay(uint16_t delay) {
+ APPL_TRACE_DEBUG("%s: DELAY: %.1f ms", __func__, (float)delay / 10);
+ delay_report_stats.audio_delay = delay;
+}
+
+void btif_a2dp_control_reset_audio_delay(void) {
+ APPL_TRACE_DEBUG("%s", __func__);
+ delay_report_stats.audio_delay = 0;
+ delay_report_stats.total_bytes_read = 0;
+ delay_report_stats.timestamp = {};
}
diff --git a/btif/src/btif_a2dp_sink.cc b/btif/src/btif_a2dp_sink.cc
index 4ccf39f..c17b33a 100644
--- a/btif/src/btif_a2dp_sink.cc
+++ b/btif/src/btif_a2dp_sink.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,9 @@
#define LOG_TAG "bt_btif_a2dp_sink"
-#include <string.h>
+#include <atomic>
+#include <cstring>
+#include <mutex>
#include "bt_common.h"
#include "btif_a2dp.h"
@@ -33,8 +35,7 @@
#include "osi/include/osi.h"
#include "osi/include/thread.h"
-#include "oi_codec_sbc.h"
-#include "oi_status.h"
+using LockGuard = std::lock_guard<std::mutex>;
/**
* The receiving queue buffer size.
@@ -71,13 +72,6 @@
btif_a2dp_sink_focus_state_t focus_state;
} tBTIF_MEDIA_SINK_FOCUS_UPDATE;
-typedef struct {
- uint16_t num_frames_to_be_processed;
- uint16_t len;
- uint16_t offset;
- uint16_t layer_specific;
-} tBT_SBC_HDR;
-
/* BTIF A2DP Sink control block */
typedef struct {
thread_t* worker_thread;
@@ -85,25 +79,26 @@
fixed_queue_t* rx_audio_queue;
bool rx_flush; /* discards any incoming data when true */
alarm_t* decode_alarm;
- uint8_t frames_to_process;
tA2DP_SAMPLE_RATE sample_rate;
tA2DP_CHANNEL_COUNT channel_count;
btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */
void* audio_track;
+ const tA2DP_DECODER_INTERFACE* decoder_interface;
} tBTIF_A2DP_SINK_CB;
+// Mutex for below data structures.
+static std::mutex g_mutex;
+
static tBTIF_A2DP_SINK_CB btif_a2dp_sink_cb;
-static int btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF;
+static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF};
-static OI_CODEC_SBC_DECODER_CONTEXT btif_a2dp_sink_context;
-static uint32_t btif_a2dp_sink_context_data[CODEC_DATA_WORDS(
- 2, SBC_CODEC_FAST_FILTER_BUFFERS)];
-static int16_t
- btif_a2dp_sink_pcm_data[15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS];
-
+static void btif_a2dp_sink_init_delayed(void* context);
static void btif_a2dp_sink_startup_delayed(void* context);
+static void btif_a2dp_sink_start_session_delayed(void* context);
+static void btif_a2dp_sink_end_session_delayed(void* context);
static void btif_a2dp_sink_shutdown_delayed(void* context);
+static void btif_a2dp_sink_cleanup_delayed(void* context);
static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, void* context);
static void btif_a2dp_sink_audio_handle_stop_decoding(void);
static void btif_decode_alarm_cb(void* context);
@@ -111,7 +106,7 @@
static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context);
static void btif_a2dp_sink_audio_rx_flush_req(void);
/* Handle incoming media packets A2DP SINK streaming */
-static void btif_a2dp_sink_handle_inc_media(tBT_SBC_HDR* p_msg);
+static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg);
static void btif_a2dp_sink_decoder_update_event(
tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf);
static void btif_a2dp_sink_clear_track_event(void);
@@ -132,21 +127,22 @@
return "UNKNOWN A2DP SINK EVENT";
}
-bool btif_a2dp_sink_startup(void) {
+bool btif_a2dp_sink_init(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
+
if (btif_a2dp_sink_state != BTIF_A2DP_SINK_STATE_OFF) {
- APPL_TRACE_ERROR("%s: A2DP Sink media task already running", __func__);
+ LOG_ERROR(LOG_TAG, "%s: A2DP Sink media task already running", __func__);
return false;
}
memset(&btif_a2dp_sink_cb, 0, sizeof(btif_a2dp_sink_cb));
btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_STARTING_UP;
- APPL_TRACE_EVENT("## A2DP SINK START MEDIA THREAD ##");
-
/* Start A2DP Sink media task */
btif_a2dp_sink_cb.worker_thread = thread_new("btif_a2dp_sink_worker_thread");
if (btif_a2dp_sink_cb.worker_thread == NULL) {
- APPL_TRACE_ERROR("%s: unable to start up media thread", __func__);
+ LOG_ERROR(LOG_TAG, "%s: unable to start up media thread", __func__);
btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF;
return false;
}
@@ -161,56 +157,152 @@
thread_get_reactor(btif_a2dp_sink_cb.worker_thread),
btif_a2dp_sink_command_ready, NULL);
- APPL_TRACE_EVENT("## A2DP SINK MEDIA THREAD STARTED ##");
-
- /* Schedule the rest of the startup operations */
- thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_startup_delayed,
+ /* Schedule the rest of the operations */
+ thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_init_delayed,
NULL);
return true;
}
-static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) {
+static void btif_a2dp_sink_init_delayed(UNUSED_ATTR void* context) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
raise_priority_a2dp(TASK_HIGH_MEDIA);
btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_RUNNING;
}
-void btif_a2dp_sink_shutdown(void) {
- if ((btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) ||
- (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_SHUTTING_DOWN)) {
- return;
+bool btif_a2dp_sink_startup(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_startup_delayed,
+ NULL);
+ return true;
+}
+
+static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
+ // Nothing to do
+}
+
+bool btif_a2dp_sink_start_session(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ thread_post(btif_a2dp_sink_cb.worker_thread,
+ btif_a2dp_sink_start_session_delayed, NULL);
+ return true;
+}
+
+static void btif_a2dp_sink_start_session_delayed(UNUSED_ATTR void* context) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
+ // Nothing to do
+}
+
+bool btif_a2dp_sink_restart_session(const RawAddress& old_peer_address,
+ const RawAddress& new_peer_address) {
+ LOG_INFO(LOG_TAG, "%s: old_peer_address=%s new_peer_address=%s", __func__,
+ old_peer_address.ToString().c_str(),
+ new_peer_address.ToString().c_str());
+
+ CHECK(!new_peer_address.IsEmpty());
+
+ if (!old_peer_address.IsEmpty()) {
+ btif_a2dp_sink_end_session(old_peer_address);
}
- /* Make sure no channels are restarted while shutting down */
- btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_SHUTTING_DOWN;
+ if (!bta_av_co_set_active_peer(new_peer_address)) {
+ LOG_ERROR(LOG_TAG, "%s: Cannot stream audio: cannot set active peer to %s",
+ __func__, new_peer_address.ToString().c_str());
+ return false;
+ }
- APPL_TRACE_EVENT("## A2DP SINK STOP MEDIA THREAD ##");
+ if (old_peer_address.IsEmpty()) {
+ btif_a2dp_sink_startup();
+ }
+ btif_a2dp_sink_start_session(new_peer_address);
- // Stop the timer
- alarm_free(btif_a2dp_sink_cb.decode_alarm);
- btif_a2dp_sink_cb.decode_alarm = NULL;
+ return true;
+}
- // Exit the thread
- fixed_queue_free(btif_a2dp_sink_cb.cmd_msg_queue, NULL);
- btif_a2dp_sink_cb.cmd_msg_queue = NULL;
+bool btif_a2dp_sink_end_session(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ thread_post(btif_a2dp_sink_cb.worker_thread,
+ btif_a2dp_sink_end_session_delayed, NULL);
+ return true;
+}
+
+static void btif_a2dp_sink_end_session_delayed(UNUSED_ATTR void* context) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
+ // Nothing to do
+}
+
+void btif_a2dp_sink_shutdown(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_shutdown_delayed,
NULL);
- thread_free(btif_a2dp_sink_cb.worker_thread);
- btif_a2dp_sink_cb.worker_thread = NULL;
}
static void btif_a2dp_sink_shutdown_delayed(UNUSED_ATTR void* context) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
+ // Nothing to do
+}
+
+void btif_a2dp_sink_cleanup(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+
+ alarm_t* decode_alarm;
+ fixed_queue_t* cmd_msg_queue;
+ thread_t* worker_thread;
+
+ // Make sure the sink is shutdown
+ btif_a2dp_sink_shutdown();
+
+ {
+ LockGuard lock(g_mutex);
+ if ((btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) ||
+ (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_SHUTTING_DOWN)) {
+ return;
+ }
+ // Make sure no channels are restarted while shutting down
+ btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_SHUTTING_DOWN;
+
+ decode_alarm = btif_a2dp_sink_cb.decode_alarm;
+ btif_a2dp_sink_cb.decode_alarm = NULL;
+
+ cmd_msg_queue = btif_a2dp_sink_cb.cmd_msg_queue;
+ btif_a2dp_sink_cb.cmd_msg_queue = NULL;
+
+ worker_thread = btif_a2dp_sink_cb.worker_thread;
+ btif_a2dp_sink_cb.worker_thread = NULL;
+ }
+
+ // Stop the timer
+ alarm_free(decode_alarm);
+
+ // Exit the thread
+ fixed_queue_free(cmd_msg_queue, NULL);
+ thread_post(worker_thread, btif_a2dp_sink_cleanup_delayed, NULL);
+ thread_free(worker_thread);
+}
+
+static void btif_a2dp_sink_cleanup_delayed(UNUSED_ATTR void* context) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
+
fixed_queue_free(btif_a2dp_sink_cb.rx_audio_queue, NULL);
btif_a2dp_sink_cb.rx_audio_queue = NULL;
-
btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF;
}
tA2DP_SAMPLE_RATE btif_a2dp_sink_get_sample_rate(void) {
+ LockGuard lock(g_mutex);
return btif_a2dp_sink_cb.sample_rate;
}
tA2DP_CHANNEL_COUNT btif_a2dp_sink_get_channel_count(void) {
+ LockGuard lock(g_mutex);
return btif_a2dp_sink_cb.channel_count;
}
@@ -239,7 +331,7 @@
btif_a2dp_sink_audio_rx_flush_event();
break;
default:
- APPL_TRACE_ERROR("ERROR in %s unknown event %d", __func__, p_msg->event);
+ LOG_ERROR(LOG_TAG, "%s: unknown event %d", __func__, p_msg->event);
break;
}
@@ -248,6 +340,7 @@
}
void btif_a2dp_sink_update_decoder(const uint8_t* p_codec_info) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf =
reinterpret_cast<tBTIF_MEDIA_SINK_DECODER_UPDATE*>(
osi_malloc(sizeof(tBTIF_MEDIA_SINK_DECODER_UPDATE)));
@@ -263,37 +356,51 @@
}
void btif_a2dp_sink_on_idle(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
if (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) return;
-
btif_a2dp_sink_audio_handle_stop_decoding();
btif_a2dp_sink_clear_track_event_req();
- APPL_TRACE_DEBUG("Stopped BT track");
}
void btif_a2dp_sink_on_stopped(UNUSED_ATTR tBTA_AV_SUSPEND* p_av_suspend) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
if (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) return;
-
btif_a2dp_sink_audio_handle_stop_decoding();
}
void btif_a2dp_sink_on_suspended(UNUSED_ATTR tBTA_AV_SUSPEND* p_av_suspend) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
if (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) return;
-
btif_a2dp_sink_audio_handle_stop_decoding();
}
static void btif_a2dp_sink_audio_handle_stop_decoding(void) {
- btif_a2dp_sink_cb.rx_flush = true;
- btif_a2dp_sink_audio_rx_flush_req();
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ alarm_t* old_alarm;
+ {
+ LockGuard lock(g_mutex);
+ btif_a2dp_sink_cb.rx_flush = true;
+ btif_a2dp_sink_audio_rx_flush_req();
+ old_alarm = btif_a2dp_sink_cb.decode_alarm;
+ btif_a2dp_sink_cb.decode_alarm = NULL;
+ }
- alarm_free(btif_a2dp_sink_cb.decode_alarm);
- btif_a2dp_sink_cb.decode_alarm = NULL;
+ // Drop the lock here, btif_decode_alarm_cb may in the process of being called
+ // while we alarm free leading to deadlock.
+ //
+ // alarm_free waits for btif_decode_alarm_cb which is waiting for g_mutex.
+ alarm_free(old_alarm);
+
+ {
+ LockGuard lock(g_mutex);
#ifndef OS_GENERIC
- BtifAvrcpAudioTrackPause(btif_a2dp_sink_cb.audio_track);
+ BtifAvrcpAudioTrackPause(btif_a2dp_sink_cb.audio_track);
#endif
+ }
}
static void btif_decode_alarm_cb(UNUSED_ATTR void* context) {
+ LockGuard lock(g_mutex);
if (btif_a2dp_sink_cb.worker_thread != NULL) {
thread_post(btif_a2dp_sink_cb.worker_thread,
btif_a2dp_sink_avk_handle_timer, NULL);
@@ -301,7 +408,8 @@
}
static void btif_a2dp_sink_clear_track_event(void) {
- APPL_TRACE_DEBUG("%s", __func__);
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
#ifndef OS_GENERIC
BtifAvrcpAudioTrackStop(btif_a2dp_sink_cb.audio_track);
@@ -310,7 +418,9 @@
btif_a2dp_sink_cb.audio_track = NULL;
}
+// Must be called while locked.
static void btif_a2dp_sink_audio_handle_start_decoding(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
if (btif_a2dp_sink_cb.decode_alarm != NULL)
return; // Already started decoding
@@ -327,54 +437,31 @@
btif_decode_alarm_cb, NULL);
}
-static void btif_a2dp_sink_handle_inc_media(tBT_SBC_HDR* p_msg) {
- uint8_t* sbc_start_frame = ((uint8_t*)(p_msg + 1) + p_msg->offset + 1);
- int count;
- uint32_t pcmBytes, availPcmBytes;
- int16_t* pcmDataPointer =
- btif_a2dp_sink_pcm_data; /* Will be overwritten on next packet receipt */
- OI_STATUS status;
- int num_sbc_frames = p_msg->num_frames_to_be_processed;
- uint32_t sbc_frame_len = p_msg->len - 1;
- availPcmBytes = sizeof(btif_a2dp_sink_pcm_data);
-
- if ((btif_av_get_peer_sep() == AVDT_TSEP_SNK) ||
- (btif_a2dp_sink_cb.rx_flush)) {
- APPL_TRACE_DEBUG("State Changed happened in this tick");
- return;
- }
-
- APPL_TRACE_DEBUG("%s Number of SBC frames %d, frame_len %d", __func__,
- num_sbc_frames, sbc_frame_len);
-
- for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count++) {
- pcmBytes = availPcmBytes;
- status = OI_CODEC_SBC_DecodeFrame(
- &btif_a2dp_sink_context, (const OI_BYTE**)&sbc_start_frame,
- (uint32_t*)&sbc_frame_len, (int16_t*)pcmDataPointer,
- (uint32_t*)&pcmBytes);
- if (!OI_SUCCESS(status)) {
- APPL_TRACE_ERROR("%s: Decoding failure: %d", __func__, status);
- break;
- }
- availPcmBytes -= pcmBytes;
- pcmDataPointer += pcmBytes / 2;
- p_msg->offset += (p_msg->len - 1) - sbc_frame_len;
- p_msg->len = sbc_frame_len + 1;
- }
-
+static void btif_a2dp_sink_on_decode_complete(uint8_t* data, uint32_t len) {
#ifndef OS_GENERIC
- BtifAvrcpAudioTrackWriteData(
- btif_a2dp_sink_cb.audio_track, (void*)btif_a2dp_sink_pcm_data,
- (sizeof(btif_a2dp_sink_pcm_data) - availPcmBytes));
+ BtifAvrcpAudioTrackWriteData(btif_a2dp_sink_cb.audio_track,
+ reinterpret_cast<void*>(data), len);
#endif
}
-static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) {
- tBT_SBC_HDR* p_msg;
- int num_sbc_frames;
- int num_frames_to_process;
+// Must be called while locked.
+static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg) {
+ if ((btif_av_get_peer_sep() == AVDT_TSEP_SNK) ||
+ (btif_a2dp_sink_cb.rx_flush)) {
+ APPL_TRACE_DEBUG("%s: state changed happened in this tick", __func__);
+ return;
+ }
+ CHECK(btif_a2dp_sink_cb.decoder_interface);
+ if (!btif_a2dp_sink_cb.decoder_interface->decode_packet(p_msg)) {
+ LOG_ERROR(LOG_TAG, "%s: decoding failed", __func__);
+ }
+}
+
+static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) {
+ LockGuard lock(g_mutex);
+
+ BT_HDR* p_msg;
if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) {
APPL_TRACE_DEBUG("%s: empty queue", __func__);
return;
@@ -392,63 +479,41 @@
return;
}
- num_frames_to_process = btif_a2dp_sink_cb.frames_to_process;
- APPL_TRACE_DEBUG(" Process Frames + ");
-
- do {
- p_msg = (tBT_SBC_HDR*)fixed_queue_try_peek_first(
- btif_a2dp_sink_cb.rx_audio_queue);
- if (p_msg == NULL) return;
- /* Number of frames in queue packets */
- num_sbc_frames = p_msg->num_frames_to_be_processed;
- APPL_TRACE_DEBUG("Frames left in topmost packet %d", num_sbc_frames);
- APPL_TRACE_DEBUG("Remaining frames to process in tick %d",
- num_frames_to_process);
- APPL_TRACE_DEBUG("Number of packets in queue %d",
+ APPL_TRACE_DEBUG("%s: process frames begin", __func__);
+ while (true) {
+ p_msg = (BT_HDR*)fixed_queue_try_dequeue(btif_a2dp_sink_cb.rx_audio_queue);
+ if (p_msg == NULL) {
+ break;
+ }
+ APPL_TRACE_DEBUG("%s: number of packets in queue %zu", __func__,
fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue));
- if (num_sbc_frames > num_frames_to_process) {
- /* Queue packet has more frames */
- p_msg->num_frames_to_be_processed = num_frames_to_process;
- btif_a2dp_sink_handle_inc_media(p_msg);
- p_msg->num_frames_to_be_processed =
- num_sbc_frames - num_frames_to_process;
- num_frames_to_process = 0;
- break;
- }
/* Queue packet has less frames */
btif_a2dp_sink_handle_inc_media(p_msg);
- p_msg =
- (tBT_SBC_HDR*)fixed_queue_try_dequeue(btif_a2dp_sink_cb.rx_audio_queue);
- if (p_msg == NULL) {
- APPL_TRACE_ERROR("Insufficient data in queue");
- break;
- }
- num_frames_to_process =
- num_frames_to_process - p_msg->num_frames_to_be_processed;
osi_free(p_msg);
- } while (num_frames_to_process > 0);
-
- APPL_TRACE_DEBUG("Process Frames - ");
+ }
+ APPL_TRACE_DEBUG("%s: process frames end", __func__);
}
/* when true media task discards any rx frames */
void btif_a2dp_sink_set_rx_flush(bool enable) {
- APPL_TRACE_EVENT("## DROP RX %d ##", enable);
+ LOG_INFO(LOG_TAG, "%s: enable=%s", __func__, (enable) ? "true" : "false");
+ LockGuard lock(g_mutex);
+
btif_a2dp_sink_cb.rx_flush = enable;
}
static void btif_a2dp_sink_audio_rx_flush_event(void) {
- /* Flush all received SBC buffers (encoded) */
- APPL_TRACE_DEBUG("%s", __func__);
-
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
+ // Flush all received encoded audio buffers
fixed_queue_flush(btif_a2dp_sink_cb.rx_audio_queue, osi_free);
}
static void btif_a2dp_sink_decoder_update_event(
tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf) {
- OI_STATUS status;
-
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__,
p_buf->codec_info[1], p_buf->codec_info[2],
p_buf->codec_info[3], p_buf->codec_info[4],
@@ -456,33 +521,39 @@
int sample_rate = A2DP_GetTrackSampleRate(p_buf->codec_info);
if (sample_rate == -1) {
- APPL_TRACE_ERROR("%s: cannot get the track frequency", __func__);
+ LOG_ERROR(LOG_TAG, "%s: cannot get the track frequency", __func__);
return;
}
int channel_count = A2DP_GetTrackChannelCount(p_buf->codec_info);
if (channel_count == -1) {
- APPL_TRACE_ERROR("%s: cannot get the channel count", __func__);
+ LOG_ERROR(LOG_TAG, "%s: cannot get the channel count", __func__);
return;
}
int channel_type = A2DP_GetSinkTrackChannelType(p_buf->codec_info);
if (channel_type == -1) {
- APPL_TRACE_ERROR("%s: cannot get the Sink channel type", __func__);
+ LOG_ERROR(LOG_TAG, "%s: cannot get the Sink channel type", __func__);
return;
}
btif_a2dp_sink_cb.sample_rate = sample_rate;
btif_a2dp_sink_cb.channel_count = channel_count;
btif_a2dp_sink_cb.rx_flush = false;
- APPL_TRACE_DEBUG("%s: Reset to Sink role", __func__);
- status = OI_CODEC_SBC_DecoderReset(
- &btif_a2dp_sink_context, btif_a2dp_sink_context_data,
- sizeof(btif_a2dp_sink_context_data), 2, 2, false);
- if (!OI_SUCCESS(status)) {
- APPL_TRACE_ERROR("%s: OI_CODEC_SBC_DecoderReset failed with error code %d",
- __func__, status);
+ APPL_TRACE_DEBUG("%s: reset to Sink role", __func__);
+
+ btif_a2dp_sink_cb.decoder_interface = bta_av_co_get_decoder_interface();
+ if (btif_a2dp_sink_cb.decoder_interface == NULL) {
+ LOG_ERROR(LOG_TAG, "%s: cannot stream audio: no source decoder interface",
+ __func__);
+ return;
}
- APPL_TRACE_DEBUG("%s: A2dpSink: SBC create track", __func__);
+ if (!btif_a2dp_sink_cb.decoder_interface->decoder_init(
+ btif_a2dp_sink_on_decode_complete)) {
+ LOG_ERROR(LOG_TAG, "%s: failed to initialize decoder", __func__);
+ return;
+ }
+
+ APPL_TRACE_DEBUG("%s: create audio track", __func__);
btif_a2dp_sink_cb.audio_track =
#ifndef OS_GENERIC
BtifAvrcpAudioTrackCreate(sample_rate, channel_type);
@@ -490,21 +561,13 @@
NULL;
#endif
if (btif_a2dp_sink_cb.audio_track == NULL) {
- APPL_TRACE_ERROR("%s: A2dpSink: Track creation failed", __func__);
+ LOG_ERROR(LOG_TAG, "%s: track creation failed", __func__);
return;
}
-
- btif_a2dp_sink_cb.frames_to_process = A2DP_GetSinkFramesCountToProcess(
- BTIF_SINK_MEDIA_TIME_TICK_MS, p_buf->codec_info);
- APPL_TRACE_DEBUG("%s: Frames to be processed in 20 ms %d", __func__,
- btif_a2dp_sink_cb.frames_to_process);
- if (btif_a2dp_sink_cb.frames_to_process == 0) {
- APPL_TRACE_ERROR("%s: Cannot compute the number of frames to process",
- __func__);
- }
}
uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) {
+ LockGuard lock(g_mutex);
if (btif_a2dp_sink_cb.rx_flush) /* Flush enabled, do not enqueue */
return fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue);
@@ -517,17 +580,11 @@
BTIF_TRACE_VERBOSE("%s +", __func__);
/* Allocate and queue this buffer */
- tBT_SBC_HDR* p_msg = reinterpret_cast<tBT_SBC_HDR*>(
- osi_malloc(sizeof(tBT_SBC_HDR) + p_pkt->offset + p_pkt->len));
- memcpy((uint8_t*)(p_msg + 1), (uint8_t*)(p_pkt + 1) + p_pkt->offset,
- p_pkt->len);
- p_msg->num_frames_to_be_processed =
- (*((uint8_t*)(p_pkt + 1) + p_pkt->offset)) & 0x0f;
- p_msg->len = p_pkt->len;
+ BT_HDR* p_msg =
+ reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(*p_msg) + p_pkt->len));
+ memcpy(p_msg, p_pkt, sizeof(*p_msg));
p_msg->offset = 0;
- p_msg->layer_specific = p_pkt->layer_specific;
- BTIF_TRACE_VERBOSE("%s: frames to process %d, len %d", __func__,
- p_msg->num_frames_to_be_processed, p_msg->len);
+ memcpy(p_msg->data, p_pkt->data + p_pkt->offset, p_pkt->len);
fixed_queue_enqueue(btif_a2dp_sink_cb.rx_audio_queue, p_msg);
if (fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue) ==
MAX_A2DP_DELAYED_START_FRAME_COUNT) {
@@ -539,6 +596,7 @@
}
void btif_a2dp_sink_audio_rx_flush_req(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) {
/* Queue is already empty */
return;
@@ -554,12 +612,10 @@
}
void btif_a2dp_sink_set_focus_state_req(btif_a2dp_sink_focus_state_t state) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
tBTIF_MEDIA_SINK_FOCUS_UPDATE* p_buf =
reinterpret_cast<tBTIF_MEDIA_SINK_FOCUS_UPDATE*>(
osi_malloc(sizeof(tBTIF_MEDIA_SINK_FOCUS_UPDATE)));
-
- APPL_TRACE_EVENT("%s", __func__);
-
p_buf->focus_state = state;
p_buf->hdr.event = BTIF_MEDIA_SINK_SET_FOCUS_STATE;
fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf);
@@ -567,6 +623,9 @@
static void btif_a2dp_sink_set_focus_state_event(
btif_a2dp_sink_focus_state_t state) {
+ LOG_INFO(LOG_TAG, "%s: state=%d", __func__, state);
+ LockGuard lock(g_mutex);
+
if (!btif_av_is_connected()) return;
APPL_TRACE_DEBUG("%s: setting focus state to %d", __func__, state);
btif_a2dp_sink_cb.rx_focus_state = state;
@@ -579,13 +638,16 @@
}
void btif_a2dp_sink_set_audio_track_gain(float gain) {
- APPL_TRACE_DEBUG("%s set gain to %f", __func__, gain);
+ LOG_INFO(LOG_TAG, "%s: set gain to %f", __func__, gain);
+ LockGuard lock(g_mutex);
+
#ifndef OS_GENERIC
BtifAvrcpSetAudioTrackGain(btif_a2dp_sink_cb.audio_track, gain);
#endif
}
static void btif_a2dp_sink_clear_track_event_req(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR)));
p_buf->event = BTIF_MEDIA_SINK_CLEAR_TRACK;
diff --git a/btif/src/btif_a2dp_source.cc b/btif/src/btif_a2dp_source.cc
index 8d264ce..efd842b 100644
--- a/btif/src/btif_a2dp_source.cc
+++ b/btif/src/btif_a2dp_source.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,10 +20,11 @@
#define LOG_TAG "bt_btif_a2dp_source"
#define ATRACE_TAG ATRACE_TAG_AUDIO
-#include <base/logging.h>
+#include <base/run_loop.h>
#ifndef OS_GENERIC
#include <cutils/trace.h>
#endif
+#include <inttypes.h>
#include <limits.h>
#include <string.h>
#include <algorithm>
@@ -32,6 +33,7 @@
#include "bt_common.h"
#include "bta_av_ci.h"
#include "btif_a2dp.h"
+#include "btif_a2dp_audio_interface.h"
#include "btif_a2dp_control.h"
#include "btif_a2dp_source.h"
#include "btif_av.h"
@@ -40,15 +42,19 @@
#include "osi/include/fixed_queue.h"
#include "osi/include/log.h"
#include "osi/include/metrics.h"
-#include "osi/include/mutex.h"
#include "osi/include/osi.h"
#include "osi/include/thread.h"
#include "osi/include/time.h"
#include "uipc.h"
+#include <condition_variable>
+#include <mutex>
+
using system_bt_osi::BluetoothMetricsLogger;
using system_bt_osi::A2dpSessionMetrics;
+extern std::unique_ptr<tUIPC_STATE> a2dp_uipc;
+
/**
* The typical runlevel of the tx queue size is ~1 buffer
* but due to link flow control or thread preemption in lower
@@ -56,42 +62,22 @@
*/
#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ (MAX_PCM_FRAME_NUM_PER_TICK * 2)
-enum {
- BTIF_A2DP_SOURCE_STATE_OFF,
- BTIF_A2DP_SOURCE_STATE_STARTING_UP,
- BTIF_A2DP_SOURCE_STATE_RUNNING,
- BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN
-};
+class SchedulingStats {
+ public:
+ SchedulingStats() { Reset(); }
+ void Reset() {
+ total_updates = 0;
+ last_update_us = 0;
+ overdue_scheduling_count = 0;
+ total_overdue_scheduling_delta_us = 0;
+ max_overdue_scheduling_delta_us = 0;
+ premature_scheduling_count = 0;
+ total_premature_scheduling_delta_us = 0;
+ max_premature_scheduling_delta_us = 0;
+ exact_scheduling_count = 0;
+ total_scheduling_time_us = 0;
+ }
-/* BTIF Media Source event definition */
-enum {
- BTIF_MEDIA_AUDIO_TX_START = 1,
- BTIF_MEDIA_AUDIO_TX_STOP,
- BTIF_MEDIA_AUDIO_TX_FLUSH,
- BTIF_MEDIA_SOURCE_ENCODER_INIT,
- BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE,
- BTIF_MEDIA_AUDIO_FEEDING_UPDATE
-};
-
-/* tBTIF_A2DP_SOURCE_ENCODER_INIT msg structure */
-typedef struct {
- BT_HDR hdr;
- tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
-} tBTIF_A2DP_SOURCE_ENCODER_INIT;
-
-/* tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE msg structure */
-typedef struct {
- BT_HDR hdr;
- btav_a2dp_codec_config_t user_config;
-} tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE;
-
-/* tBTIF_A2DP_AUDIO_FEEDING_UPDATE msg structure */
-typedef struct {
- BT_HDR hdr;
- btav_a2dp_codec_config_t feeding_params;
-} tBTIF_A2DP_AUDIO_FEEDING_UPDATE;
-
-typedef struct {
// Counter for total updates
size_t total_updates;
@@ -121,14 +107,39 @@
// Accumulated and counted scheduling time (in us)
uint64_t total_scheduling_time_us;
-} scheduling_stats_t;
+};
-typedef struct {
+class BtifMediaStats {
+ public:
+ BtifMediaStats() { Reset(); }
+ void Reset() {
+ session_start_us = 0;
+ session_end_us = 0;
+ tx_queue_enqueue_stats.Reset();
+ tx_queue_dequeue_stats.Reset();
+ tx_queue_total_frames = 0;
+ tx_queue_max_frames_per_packet = 0;
+ tx_queue_total_queueing_time_us = 0;
+ tx_queue_max_queueing_time_us = 0;
+ tx_queue_total_readbuf_calls = 0;
+ tx_queue_last_readbuf_us = 0;
+ tx_queue_total_flushed_messages = 0;
+ tx_queue_last_flushed_us = 0;
+ tx_queue_total_dropped_messages = 0;
+ tx_queue_max_dropped_messages = 0;
+ tx_queue_dropouts = 0;
+ tx_queue_last_dropouts_us = 0;
+ media_read_total_underflow_bytes = 0;
+ media_read_total_underflow_count = 0;
+ media_read_last_underflow_us = 0;
+ codec_index = -1;
+ }
+
uint64_t session_start_us;
uint64_t session_end_us;
- scheduling_stats_t tx_queue_enqueue_stats;
- scheduling_stats_t tx_queue_dequeue_stats;
+ SchedulingStats tx_queue_enqueue_stats;
+ SchedulingStats tx_queue_dequeue_stats;
size_t tx_queue_total_frames;
size_t tx_queue_max_frames_per_packet;
@@ -150,64 +161,201 @@
size_t media_read_total_underflow_bytes;
size_t media_read_total_underflow_count;
uint64_t media_read_last_underflow_us;
-} btif_media_stats_t;
-typedef struct {
- thread_t* worker_thread;
- fixed_queue_t* cmd_msg_queue;
+ int codec_index = -1;
+};
+
+class BtWorkerThread {
+ public:
+ BtWorkerThread(const std::string& thread_name)
+ : thread_name_(thread_name),
+ message_loop_(nullptr),
+ run_loop_(nullptr),
+ message_loop_thread_(nullptr),
+ started_(false) {}
+
+ void StartUp() {
+ if (message_loop_thread_ != nullptr) {
+ return; // Already started up
+ }
+ message_loop_thread_ = thread_new(thread_name_.c_str());
+ CHECK(message_loop_thread_ != nullptr);
+ started_ = false;
+ thread_post(message_loop_thread_, &BtWorkerThread::RunThread, this);
+ {
+ // Block until run_loop_ is allocated and ready to run
+ std::unique_lock<std::mutex> start_lock(start_up_mutex_);
+ while (!started_) {
+ start_up_cv_.wait(start_lock);
+ }
+ }
+ }
+
+ bool DoInThread(const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ if ((message_loop_ == nullptr) || !message_loop_->task_runner().get()) {
+ LOG_ERROR(
+ LOG_TAG,
+ "%s: Dropping message for thread %s: message loop is not initialized",
+ __func__, thread_name_.c_str());
+ return false;
+ }
+ if (!message_loop_->task_runner()->PostTask(from_here, task)) {
+ LOG_ERROR(LOG_TAG,
+ "%s: Posting task to message loop for thread %s failed",
+ __func__, thread_name_.c_str());
+ return false;
+ }
+ return true;
+ }
+
+ void ShutDown() {
+ if ((run_loop_ != nullptr) && (message_loop_ != nullptr)) {
+ message_loop_->task_runner()->PostTask(FROM_HERE,
+ run_loop_->QuitClosure());
+ }
+ thread_free(message_loop_thread_);
+ message_loop_thread_ = nullptr;
+ }
+
+ private:
+ static void RunThread(void* context) {
+ auto wt = static_cast<BtWorkerThread*>(context);
+ wt->Run();
+ }
+
+ void Run() {
+ LOG_INFO(LOG_TAG, "%s: message loop for thread %s started", __func__,
+ thread_name_.c_str());
+ message_loop_ = new base::MessageLoop();
+ run_loop_ = new base::RunLoop();
+ {
+ std::unique_lock<std::mutex> start_lock(start_up_mutex_);
+ started_ = true;
+ start_up_cv_.notify_all();
+ }
+ // Blocking util ShutDown() is called
+ run_loop_->Run();
+ delete message_loop_;
+ message_loop_ = nullptr;
+ delete run_loop_;
+ run_loop_ = nullptr;
+ LOG_INFO(LOG_TAG, "%s: message loop for thread %s finished", __func__,
+ thread_name_.c_str());
+ }
+
+ std::string thread_name_;
+ base::MessageLoop* message_loop_;
+ base::RunLoop* run_loop_;
+ thread_t* message_loop_thread_;
+ // For start-up
+ bool started_;
+ std::mutex start_up_mutex_;
+ std::condition_variable start_up_cv_;
+};
+
+class BtifA2dpSource {
+ public:
+ enum RunState {
+ kStateOff,
+ kStateStartingUp,
+ kStateRunning,
+ kStateShuttingDown
+ };
+
+ BtifA2dpSource()
+ : tx_audio_queue(nullptr),
+ tx_flush(false),
+ media_alarm(nullptr),
+ encoder_interface(nullptr),
+ encoder_interval_ms(0),
+ state_(kStateOff) {}
+
+ void Reset() {
+ fixed_queue_free(tx_audio_queue, nullptr);
+ tx_audio_queue = nullptr;
+ tx_flush = false;
+ alarm_free(media_alarm);
+ media_alarm = nullptr;
+ encoder_interface = nullptr;
+ encoder_interval_ms = 0;
+ stats.Reset();
+ accumulated_stats.Reset();
+ state_ = kStateOff;
+ }
+
+ BtifA2dpSource::RunState State() const { return state_; }
+ std::string StateStr() const {
+ switch (state_) {
+ case kStateOff:
+ return "STATE_OFF";
+ case kStateStartingUp:
+ return "STATE_STARTING_UP";
+ case kStateRunning:
+ return "STATE_RUNNING";
+ case kStateShuttingDown:
+ return "STATE_SHUTTING_DOWN";
+ }
+ }
+
+ void SetState(BtifA2dpSource::RunState state) { state_ = state; }
+
fixed_queue_t* tx_audio_queue;
bool tx_flush; /* Discards any outgoing data when true */
alarm_t* media_alarm;
const tA2DP_ENCODER_INTERFACE* encoder_interface;
period_ms_t encoder_interval_ms; /* Local copy of the encoder interval */
- btif_media_stats_t stats;
- btif_media_stats_t accumulated_stats;
-} tBTIF_A2DP_SOURCE_CB;
+ BtifMediaStats stats;
+ BtifMediaStats accumulated_stats;
-static tBTIF_A2DP_SOURCE_CB btif_a2dp_source_cb;
-static int btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_OFF;
+ private:
+ BtifA2dpSource::RunState state_;
+};
-static void btif_a2dp_source_command_ready(fixed_queue_t* queue, void* context);
-static void btif_a2dp_source_startup_delayed(void* context);
-static void btif_a2dp_source_shutdown_delayed(void* context);
+static BtWorkerThread btif_a2dp_source_thread("btif_a2dp_source_thread");
+static BtifA2dpSource btif_a2dp_source_cb;
+
+static void btif_a2dp_source_init_delayed(void);
+static void btif_a2dp_source_startup_delayed(void);
+static void btif_a2dp_source_start_session_delayed(
+ const RawAddress& peer_address);
+static void btif_a2dp_source_end_session_delayed(
+ const RawAddress& peer_address);
+static void btif_a2dp_source_shutdown_delayed(void);
+static void btif_a2dp_source_cleanup_delayed(void);
static void btif_a2dp_source_audio_tx_start_event(void);
static void btif_a2dp_source_audio_tx_stop_event(void);
-static void btif_a2dp_source_audio_tx_flush_event(BT_HDR* p_msg);
-static void btif_a2dp_source_encoder_init_event(BT_HDR* p_msg);
-static void btif_a2dp_source_encoder_user_config_update_event(BT_HDR* p_msg);
-static void btif_a2dp_source_audio_feeding_update_event(BT_HDR* p_msg);
-static void btif_a2dp_source_encoder_init(void);
-static void btif_a2dp_source_encoder_init_req(
- tBTIF_A2DP_SOURCE_ENCODER_INIT* p_msg);
+static void btif_a2dp_source_audio_tx_flush_event(void);
+// Set up the A2DP Source codec, and prepare the encoder.
+// The peer address is |peer_addr|.
+// This function should be called prior to starting A2DP streaming.
+static void btif_a2dp_source_setup_codec(const RawAddress& peer_addr);
+static void btif_a2dp_source_setup_codec_delayed(
+ const RawAddress& peer_address);
+static void btif_a2dp_source_encoder_user_config_update_event(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_user_config);
+static void btif_a2dp_source_audio_feeding_update_event(
+ const btav_a2dp_codec_config_t& codec_audio_config);
static bool btif_a2dp_source_audio_tx_flush_req(void);
static void btif_a2dp_source_alarm_cb(void* context);
-static void btif_a2dp_source_audio_handle_timer(void* context);
+static void btif_a2dp_source_audio_handle_timer(void);
static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len);
-static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n);
+static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n,
+ uint32_t bytes_read);
static void log_tstamps_us(const char* comment, uint64_t timestamp_us);
-static void update_scheduling_stats(scheduling_stats_t* stats, uint64_t now_us,
+static void update_scheduling_stats(SchedulingStats* stats, uint64_t now_us,
uint64_t expected_delta);
+// Update the A2DP Source related metrics.
+// This function should be called before collecting the metrics.
+static void btif_a2dp_source_update_metrics(void);
static void btm_read_rssi_cb(void* data);
static void btm_read_failed_contact_counter_cb(void* data);
static void btm_read_automatic_flush_timeout_cb(void* data);
static void btm_read_tx_power_cb(void* data);
-UNUSED_ATTR static const char* dump_media_event(uint16_t event) {
- switch (event) {
- CASE_RETURN_STR(BTIF_MEDIA_AUDIO_TX_START)
- CASE_RETURN_STR(BTIF_MEDIA_AUDIO_TX_STOP)
- CASE_RETURN_STR(BTIF_MEDIA_AUDIO_TX_FLUSH)
- CASE_RETURN_STR(BTIF_MEDIA_SOURCE_ENCODER_INIT)
- CASE_RETURN_STR(BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE)
- CASE_RETURN_STR(BTIF_MEDIA_AUDIO_FEEDING_UPDATE)
- default:
- break;
- }
- return "UNKNOWN A2DP SOURCE EVENT";
-}
-
-void btif_a2dp_source_accumulate_scheduling_stats(scheduling_stats_t* src,
- scheduling_stats_t* dst) {
+void btif_a2dp_source_accumulate_scheduling_stats(SchedulingStats* src,
+ SchedulingStats* dst) {
dst->total_updates += src->total_updates;
dst->last_update_us = src->last_update_us;
dst->overdue_scheduling_count += src->overdue_scheduling_count;
@@ -226,8 +374,8 @@
dst->total_scheduling_time_us += src->total_scheduling_time_us;
}
-void btif_a2dp_source_accumulate_stats(btif_media_stats_t* src,
- btif_media_stats_t* dst) {
+void btif_a2dp_source_accumulate_stats(BtifMediaStats* src,
+ BtifMediaStats* dst) {
dst->tx_queue_total_frames += src->tx_queue_total_frames;
dst->tx_queue_max_frames_per_packet = std::max(
dst->tx_queue_max_frames_per_packet, src->tx_queue_max_frames_per_packet);
@@ -248,304 +396,346 @@
dst->media_read_total_underflow_count +=
src->media_read_total_underflow_count;
dst->media_read_last_underflow_us = src->media_read_last_underflow_us;
+ if (dst->codec_index < 0) dst->codec_index = src->codec_index;
btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_enqueue_stats,
&dst->tx_queue_enqueue_stats);
btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_dequeue_stats,
&dst->tx_queue_dequeue_stats);
- memset(src, 0, sizeof(btif_media_stats_t));
+ src->Reset();
+}
+
+bool btif_a2dp_source_init(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+
+ // Start A2DP Source media task
+ btif_a2dp_source_thread.StartUp();
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_init_delayed));
+ return true;
+}
+
+static void btif_a2dp_source_init_delayed(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ // Nothing to do
}
bool btif_a2dp_source_startup(void) {
- if (btif_a2dp_source_state != BTIF_A2DP_SOURCE_STATE_OFF) {
- APPL_TRACE_ERROR("%s: A2DP Source media task already running", __func__);
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
+
+ if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateOff) {
+ LOG_ERROR(LOG_TAG, "%s: A2DP Source media task already running", __func__);
return false;
}
- memset(&btif_a2dp_source_cb, 0, sizeof(btif_a2dp_source_cb));
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_STARTING_UP;
-
- APPL_TRACE_EVENT("## A2DP SOURCE START MEDIA THREAD ##");
-
- /* Start A2DP Source media task */
- btif_a2dp_source_cb.worker_thread =
- thread_new("btif_a2dp_source_worker_thread");
- if (btif_a2dp_source_cb.worker_thread == NULL) {
- APPL_TRACE_ERROR("%s: unable to start up media thread", __func__);
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_OFF;
- return false;
- }
-
+ btif_a2dp_source_cb.Reset();
+ btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateStartingUp);
btif_a2dp_source_cb.tx_audio_queue = fixed_queue_new(SIZE_MAX);
- btif_a2dp_source_cb.cmd_msg_queue = fixed_queue_new(SIZE_MAX);
- fixed_queue_register_dequeue(
- btif_a2dp_source_cb.cmd_msg_queue,
- thread_get_reactor(btif_a2dp_source_cb.worker_thread),
- btif_a2dp_source_command_ready, NULL);
-
- APPL_TRACE_EVENT("## A2DP SOURCE MEDIA THREAD STARTED ##");
-
- /* Schedule the rest of the startup operations */
- thread_post(btif_a2dp_source_cb.worker_thread,
- btif_a2dp_source_startup_delayed, NULL);
+ // Schedule the rest of the operations
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_startup_delayed));
return true;
}
-static void btif_a2dp_source_startup_delayed(UNUSED_ATTR void* context) {
+static void btif_a2dp_source_startup_delayed(void) {
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
+
raise_priority_a2dp(TASK_HIGH_MEDIA);
btif_a2dp_control_init();
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_RUNNING;
- BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
- system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+ btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateRunning);
+}
+
+bool btif_a2dp_source_start_session(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_a2dp_source_cb.StateStr().c_str());
+ btif_a2dp_source_setup_codec(peer_address);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE,
+ base::Bind(&btif_a2dp_source_start_session_delayed, peer_address));
+ return true;
+}
+
+static void btif_a2dp_source_start_session_delayed(
+ const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_a2dp_source_cb.StateStr().c_str());
+ if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateRunning) {
+ LOG_ERROR(LOG_TAG, "%s: A2DP Source media task is not running", __func__);
+ return;
+ }
+ if (btif_av_is_a2dp_offload_enabled()) {
+ btif_a2dp_audio_interface_start_session();
+ } else {
+ BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+ system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+ }
+}
+
+bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address,
+ const RawAddress& new_peer_address) {
+ bool is_streaming = alarm_is_scheduled(btif_a2dp_source_cb.media_alarm);
+ LOG_INFO(LOG_TAG,
+ "%s: old_peer_address=%s new_peer_address=%s is_streaming=%s "
+ "state=%s",
+ __func__, old_peer_address.ToString().c_str(),
+ new_peer_address.ToString().c_str(), logbool(is_streaming).c_str(),
+ btif_a2dp_source_cb.StateStr().c_str());
+
+ CHECK(!new_peer_address.IsEmpty());
+
+ // Must stop first the audio streaming
+ if (is_streaming) {
+ btif_a2dp_source_stop_audio_req();
+ }
+
+ // If the old active peer was valid, end the old session.
+ // Otherwise, time to startup the A2DP Source processing.
+ if (!old_peer_address.IsEmpty()) {
+ btif_a2dp_source_end_session(old_peer_address);
+ } else {
+ btif_a2dp_source_startup();
+ }
+
+ // Start the session.
+ // If audio was streaming before, start audio streaming as well.
+ btif_a2dp_source_start_session(new_peer_address);
+ if (is_streaming) {
+ btif_a2dp_source_start_audio_req();
+ }
+ return true;
+}
+
+bool btif_a2dp_source_end_session(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_a2dp_source_cb.StateStr().c_str());
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE,
+ base::Bind(&btif_a2dp_source_end_session_delayed, peer_address));
+ return true;
+}
+
+static void btif_a2dp_source_end_session_delayed(
+ const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_a2dp_source_cb.StateStr().c_str());
+ if (!btif_av_is_a2dp_offload_enabled()) {
+ BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+ system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+ }
+ if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateRunning) {
+ btif_av_stream_stop(peer_address);
+ } else {
+ LOG_ERROR(LOG_TAG, "%s: A2DP Source media task is not running", __func__);
+ }
+ if (btif_av_is_a2dp_offload_enabled()) {
+ btif_a2dp_audio_interface_end_session();
+ }
}
void btif_a2dp_source_shutdown(void) {
- if ((btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) ||
- (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN)) {
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
+
+ if ((btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) ||
+ (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateShuttingDown)) {
return;
}
/* Make sure no channels are restarted while shutting down */
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN;
+ btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateShuttingDown);
- APPL_TRACE_EVENT("## A2DP SOURCE STOP MEDIA THREAD ##");
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_shutdown_delayed));
+}
+
+static void btif_a2dp_source_shutdown_delayed(void) {
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
// Stop the timer
alarm_free(btif_a2dp_source_cb.media_alarm);
- btif_a2dp_source_cb.media_alarm = NULL;
+ btif_a2dp_source_cb.media_alarm = nullptr;
- // Exit the thread
- fixed_queue_free(btif_a2dp_source_cb.cmd_msg_queue, NULL);
- btif_a2dp_source_cb.cmd_msg_queue = NULL;
- thread_post(btif_a2dp_source_cb.worker_thread,
- btif_a2dp_source_shutdown_delayed, NULL);
- thread_free(btif_a2dp_source_cb.worker_thread);
- btif_a2dp_source_cb.worker_thread = NULL;
+ btif_a2dp_control_cleanup();
+ if (btif_av_is_a2dp_offload_enabled())
+ btif_a2dp_audio_interface_end_session();
+ fixed_queue_free(btif_a2dp_source_cb.tx_audio_queue, nullptr);
+ btif_a2dp_source_cb.tx_audio_queue = nullptr;
+
+ btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateOff);
}
-static void btif_a2dp_source_shutdown_delayed(UNUSED_ATTR void* context) {
- btif_a2dp_control_cleanup();
- fixed_queue_free(btif_a2dp_source_cb.tx_audio_queue, NULL);
- btif_a2dp_source_cb.tx_audio_queue = NULL;
+void btif_a2dp_source_cleanup(void) {
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_OFF;
- BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
- system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+ // Make sure the source is shutdown
+ btif_a2dp_source_shutdown();
+
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_cleanup_delayed));
+
+ // Exit the thread
+ btif_a2dp_source_thread.ShutDown();
+}
+
+static void btif_a2dp_source_cleanup_delayed(void) {
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
+ // Nothing to do
}
bool btif_a2dp_source_media_task_is_running(void) {
- return (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_RUNNING);
+ return (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateRunning);
}
bool btif_a2dp_source_media_task_is_shutting_down(void) {
- return (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN);
+ return (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateShuttingDown);
}
bool btif_a2dp_source_is_streaming(void) {
return alarm_is_scheduled(btif_a2dp_source_cb.media_alarm);
}
-static void btif_a2dp_source_command_ready(fixed_queue_t* queue,
- UNUSED_ATTR void* context) {
- BT_HDR* p_msg = (BT_HDR*)fixed_queue_dequeue(queue);
-
- LOG_VERBOSE(LOG_TAG, "%s: event %d %s", __func__, p_msg->event,
- dump_media_event(p_msg->event));
-
- switch (p_msg->event) {
- case BTIF_MEDIA_AUDIO_TX_START:
- btif_a2dp_source_audio_tx_start_event();
- break;
- case BTIF_MEDIA_AUDIO_TX_STOP:
- btif_a2dp_source_audio_tx_stop_event();
- break;
- case BTIF_MEDIA_AUDIO_TX_FLUSH:
- btif_a2dp_source_audio_tx_flush_event(p_msg);
- break;
- case BTIF_MEDIA_SOURCE_ENCODER_INIT:
- btif_a2dp_source_encoder_init_event(p_msg);
- break;
- case BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE:
- btif_a2dp_source_encoder_user_config_update_event(p_msg);
- break;
- case BTIF_MEDIA_AUDIO_FEEDING_UPDATE:
- btif_a2dp_source_audio_feeding_update_event(p_msg);
- break;
- default:
- APPL_TRACE_ERROR("ERROR in %s unknown event %d", __func__, p_msg->event);
- break;
- }
-
- osi_free(p_msg);
- LOG_VERBOSE(LOG_TAG, "%s: %s DONE", __func__, dump_media_event(p_msg->event));
-}
-
-void btif_a2dp_source_setup_codec(void) {
- APPL_TRACE_EVENT("## A2DP SOURCE SETUP CODEC ##");
-
- mutex_global_lock();
-
- /* Init the encoding task */
- btif_a2dp_source_encoder_init();
-
- mutex_global_unlock();
-}
-
-void btif_a2dp_source_start_audio_req(void) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = BTIF_MEDIA_AUDIO_TX_START;
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
- memset(&btif_a2dp_source_cb.stats, 0, sizeof(btif_media_stats_t));
- // Assign session_start_us to 1 when time_get_os_boottime_us() is 0 to
- // indicate btif_a2dp_source_start_audio_req() has been called
- btif_a2dp_source_cb.stats.session_start_us = time_get_os_boottime_us();
- if (btif_a2dp_source_cb.stats.session_start_us == 0) {
- btif_a2dp_source_cb.stats.session_start_us = 1;
- }
- btif_a2dp_source_cb.stats.session_end_us = 0;
-}
-
-void btif_a2dp_source_stop_audio_req(void) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = BTIF_MEDIA_AUDIO_TX_STOP;
-
- /*
- * Explicitly check whether btif_a2dp_source_cb.cmd_msg_queue is not NULL
- * to avoid a race condition during shutdown of the Bluetooth stack.
- * This race condition is triggered when A2DP audio is streaming on
- * shutdown:
- * "btif_a2dp_source_on_stopped() -> btif_a2dp_source_stop_audio_req()"
- * is called to stop the particular audio stream, and this happens right
- * after the "BTIF_AV_CLEANUP_REQ_EVT -> btif_a2dp_source_shutdown()"
- * processing during the shutdown of the Bluetooth stack.
- */
- if (btif_a2dp_source_cb.cmd_msg_queue != NULL) {
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
- }
- btif_a2dp_source_cb.stats.session_end_us = time_get_os_boottime_us();
- btif_a2dp_source_update_metrics();
- btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats,
- &btif_a2dp_source_cb.accumulated_stats);
-}
-
-static void btif_a2dp_source_encoder_init(void) {
- tBTIF_A2DP_SOURCE_ENCODER_INIT msg;
+static void btif_a2dp_source_setup_codec(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_a2dp_source_cb.StateStr().c_str());
// Check to make sure the platform has 8 bits/byte since
// we're using that in frame size calculations now.
CHECK(CHAR_BIT == 8);
- APPL_TRACE_DEBUG("%s", __func__);
-
- bta_av_co_get_peer_params(&msg.peer_params);
- btif_a2dp_source_encoder_init_req(&msg);
+ btif_a2dp_source_audio_tx_flush_req();
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE,
+ base::Bind(&btif_a2dp_source_setup_codec_delayed, peer_address));
}
-static void btif_a2dp_source_encoder_init_req(
- tBTIF_A2DP_SOURCE_ENCODER_INIT* p_msg) {
- tBTIF_A2DP_SOURCE_ENCODER_INIT* p_buf =
- (tBTIF_A2DP_SOURCE_ENCODER_INIT*)osi_malloc(
- sizeof(tBTIF_A2DP_SOURCE_ENCODER_INIT));
+static void btif_a2dp_source_setup_codec_delayed(
+ const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_a2dp_source_cb.StateStr().c_str());
- memcpy(p_buf, p_msg, sizeof(tBTIF_A2DP_SOURCE_ENCODER_INIT));
- p_buf->hdr.event = BTIF_MEDIA_SOURCE_ENCODER_INIT;
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
-}
+ tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
+ bta_av_co_get_peer_params(peer_address, &peer_params);
-static void btif_a2dp_source_encoder_init_event(BT_HDR* p_msg) {
- tBTIF_A2DP_SOURCE_ENCODER_INIT* p_encoder_init =
- (tBTIF_A2DP_SOURCE_ENCODER_INIT*)p_msg;
-
- APPL_TRACE_DEBUG("%s", __func__);
-
+ if (!bta_av_co_set_active_peer(peer_address)) {
+ LOG_ERROR(LOG_TAG, "%s: Cannot stream audio: cannot set active peer to %s",
+ __func__, peer_address.ToString().c_str());
+ return;
+ }
btif_a2dp_source_cb.encoder_interface = bta_av_co_get_encoder_interface();
- if (btif_a2dp_source_cb.encoder_interface == NULL) {
- APPL_TRACE_ERROR("%s: Cannot stream audio: no source encoder interface",
- __func__);
+ if (btif_a2dp_source_cb.encoder_interface == nullptr) {
+ LOG_ERROR(LOG_TAG, "%s: Cannot stream audio: no source encoder interface",
+ __func__);
return;
}
A2dpCodecConfig* a2dp_codec_config = bta_av_get_a2dp_current_codec();
if (a2dp_codec_config == nullptr) {
- APPL_TRACE_ERROR("%s: Cannot stream audio: current codec is not set",
- __func__);
+ LOG_ERROR(LOG_TAG, "%s: Cannot stream audio: current codec is not set",
+ __func__);
return;
}
btif_a2dp_source_cb.encoder_interface->encoder_init(
- &p_encoder_init->peer_params, a2dp_codec_config,
- btif_a2dp_source_read_callback, btif_a2dp_source_enqueue_callback);
+ &peer_params, a2dp_codec_config, btif_a2dp_source_read_callback,
+ btif_a2dp_source_enqueue_callback);
// Save a local copy of the encoder_interval_ms
btif_a2dp_source_cb.encoder_interval_ms =
btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms();
}
-void btif_a2dp_source_encoder_user_config_update_req(
- const btav_a2dp_codec_config_t& codec_user_config) {
- tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE* p_buf =
- (tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE*)osi_malloc(
- sizeof(tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE));
+void btif_a2dp_source_start_audio_req(void) {
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
- p_buf->user_config = codec_user_config;
- p_buf->hdr.event = BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE;
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_tx_start_event));
}
-static void btif_a2dp_source_encoder_user_config_update_event(BT_HDR* p_msg) {
- tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE* p_user_config =
- (tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE*)p_msg;
+void btif_a2dp_source_stop_audio_req(void) {
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
- APPL_TRACE_DEBUG("%s", __func__);
- if (!bta_av_co_set_codec_user_config(p_user_config->user_config)) {
- APPL_TRACE_ERROR("%s: cannot update codec user configuration", __func__);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_tx_stop_event));
+}
+
+void btif_a2dp_source_encoder_user_config_update_req(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_user_config) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_a2dp_source_cb.StateStr().c_str());
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_encoder_user_config_update_event,
+ peer_address, codec_user_config));
+}
+
+static void btif_a2dp_source_encoder_user_config_update_event(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_user_config) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_a2dp_source_cb.StateStr().c_str());
+ if (!bta_av_co_set_codec_user_config(peer_address, codec_user_config)) {
+ LOG_ERROR(LOG_TAG, "%s: cannot update codec user configuration", __func__);
}
}
void btif_a2dp_source_feeding_update_req(
const btav_a2dp_codec_config_t& codec_audio_config) {
- tBTIF_A2DP_AUDIO_FEEDING_UPDATE* p_buf =
- (tBTIF_A2DP_AUDIO_FEEDING_UPDATE*)osi_malloc(
- sizeof(tBTIF_A2DP_AUDIO_FEEDING_UPDATE));
-
- p_buf->feeding_params = codec_audio_config;
- p_buf->hdr.event = BTIF_MEDIA_AUDIO_FEEDING_UPDATE;
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_feeding_update_event,
+ codec_audio_config));
}
-static void btif_a2dp_source_audio_feeding_update_event(BT_HDR* p_msg) {
- tBTIF_A2DP_AUDIO_FEEDING_UPDATE* p_feeding =
- (tBTIF_A2DP_AUDIO_FEEDING_UPDATE*)p_msg;
-
- APPL_TRACE_DEBUG("%s", __func__);
- if (!bta_av_co_set_codec_audio_config(p_feeding->feeding_params)) {
- APPL_TRACE_ERROR("%s: cannot update codec audio feeding parameters",
- __func__);
+static void btif_a2dp_source_audio_feeding_update_event(
+ const btav_a2dp_codec_config_t& codec_audio_config) {
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
+ if (!bta_av_co_set_codec_audio_config(codec_audio_config)) {
+ LOG_ERROR(LOG_TAG, "%s: cannot update codec audio feeding parameters",
+ __func__);
}
}
void btif_a2dp_source_on_idle(void) {
- if (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) return;
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
+ if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return;
/* Make sure media task is stopped */
btif_a2dp_source_stop_audio_req();
}
void btif_a2dp_source_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) {
- APPL_TRACE_EVENT("## ON A2DP SOURCE STOPPED ##");
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
- if (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) return;
+ if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return;
/* allow using this api for other than suspend */
- if (p_av_suspend != NULL) {
+ if (p_av_suspend != nullptr) {
if (p_av_suspend->status != BTA_AV_SUCCESS) {
- APPL_TRACE_EVENT("AV STOP FAILED (%d)", p_av_suspend->status);
+ LOG_ERROR(LOG_TAG, "%s: A2DP stop request failed: status=%d", __func__,
+ p_av_suspend->status);
if (p_av_suspend->initiator) {
- APPL_TRACE_WARNING("%s: A2DP stop request failed: status = %d",
- __func__, p_av_suspend->status);
+ LOG_WARN(LOG_TAG, "%s: A2DP stop request failed: status=%d", __func__,
+ p_av_suspend->status);
btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
}
return;
@@ -563,15 +753,16 @@
}
void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) {
- APPL_TRACE_EVENT("## ON A2DP SOURCE SUSPENDED ##");
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
- if (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) return;
+ if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return;
/* check for status failures */
if (p_av_suspend->status != BTA_AV_SUCCESS) {
if (p_av_suspend->initiator) {
- APPL_TRACE_WARNING("%s: A2DP suspend request failed: status = %d",
- __func__, p_av_suspend->status);
+ LOG_WARN(LOG_TAG, "%s: A2DP suspend request failed: status=%d", __func__,
+ p_av_suspend->status);
btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
}
}
@@ -587,50 +778,79 @@
/* when true media task discards any tx frames */
void btif_a2dp_source_set_tx_flush(bool enable) {
- APPL_TRACE_EVENT("## DROP TX %d ##", enable);
+ LOG_INFO(LOG_TAG, "%s: enable=%s state=%s", __func__,
+ (enable) ? "true" : "false", btif_a2dp_source_cb.StateStr().c_str());
btif_a2dp_source_cb.tx_flush = enable;
}
static void btif_a2dp_source_audio_tx_start_event(void) {
- APPL_TRACE_DEBUG(
- "%s media_alarm is %srunning, streaming %s", __func__,
- alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ",
- btif_a2dp_source_is_streaming() ? "true" : "false");
+ LOG_INFO(LOG_TAG, "%s: media_alarm is %srunning, streaming %s state=%s",
+ __func__,
+ alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ",
+ btif_a2dp_source_is_streaming() ? "true" : "false",
+ btif_a2dp_source_cb.StateStr().c_str());
+
+ if (btif_av_is_a2dp_offload_enabled()) return;
/* Reset the media feeding state */
- CHECK(btif_a2dp_source_cb.encoder_interface != NULL);
+ CHECK(btif_a2dp_source_cb.encoder_interface != nullptr);
btif_a2dp_source_cb.encoder_interface->feeding_reset();
APPL_TRACE_EVENT(
- "starting timer %dms",
+ "%s: starting timer %" PRIu64 " ms", __func__,
btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms());
-
alarm_free(btif_a2dp_source_cb.media_alarm);
btif_a2dp_source_cb.media_alarm =
alarm_new_periodic("btif.a2dp_source_media_alarm");
- if (btif_a2dp_source_cb.media_alarm == NULL) {
- LOG_ERROR(LOG_TAG, "%s unable to allocate media alarm", __func__);
+ if (btif_a2dp_source_cb.media_alarm == nullptr) {
+ LOG_ERROR(LOG_TAG, "%s: unable to allocate media alarm", __func__);
return;
}
alarm_set(btif_a2dp_source_cb.media_alarm,
btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms(),
- btif_a2dp_source_alarm_cb, NULL);
+ btif_a2dp_source_alarm_cb, nullptr);
+
+ btif_a2dp_source_cb.stats.Reset();
+ // Assign session_start_us to 1 when time_get_os_boottime_us() is 0 to
+ // indicate btif_a2dp_source_start_audio_req() has been called
+ btif_a2dp_source_cb.stats.session_start_us = time_get_os_boottime_us();
+ if (btif_a2dp_source_cb.stats.session_start_us == 0) {
+ btif_a2dp_source_cb.stats.session_start_us = 1;
+ }
+ btif_a2dp_source_cb.stats.session_end_us = 0;
+ A2dpCodecConfig* codec_config = bta_av_get_a2dp_current_codec();
+ if (codec_config != nullptr) {
+ btif_a2dp_source_cb.stats.codec_index = codec_config->codecIndex();
+ }
}
static void btif_a2dp_source_audio_tx_stop_event(void) {
- APPL_TRACE_DEBUG(
- "%s media_alarm is %srunning, streaming %s", __func__,
- alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ",
- btif_a2dp_source_is_streaming() ? "true" : "false");
+ LOG_INFO(LOG_TAG, "%s: media_alarm is %srunning, streaming %s state=%s",
+ __func__,
+ alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ",
+ btif_a2dp_source_is_streaming() ? "true" : "false",
+ btif_a2dp_source_cb.StateStr().c_str());
- const bool send_ack = btif_a2dp_source_is_streaming();
+ if (btif_av_is_a2dp_offload_enabled()) return;
+
+ btif_a2dp_source_cb.stats.session_end_us = time_get_os_boottime_us();
+ btif_a2dp_source_update_metrics();
+ btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats,
+ &btif_a2dp_source_cb.accumulated_stats);
+
+ uint8_t p_buf[AUDIO_STREAM_OUTPUT_BUFFER_SZ * 2];
+ uint16_t event;
+
+ // Keep track of audio data still left in the pipe
+ btif_a2dp_control_log_bytes_read(
+ UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, &event, p_buf, sizeof(p_buf)));
/* Stop the timer first */
alarm_free(btif_a2dp_source_cb.media_alarm);
- btif_a2dp_source_cb.media_alarm = NULL;
+ btif_a2dp_source_cb.media_alarm = nullptr;
- UIPC_Close(UIPC_CH_ID_AV_AUDIO);
+ UIPC_Close(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO);
/*
* Try to send acknowldegment once the media stream is
@@ -645,50 +865,54 @@
* to get the ACK for any pending command in such cases.
*/
- if (send_ack) btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
+ btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
/* audio engine stopped, reset tx suspended flag */
btif_a2dp_source_cb.tx_flush = false;
/* Reset the media feeding state */
- if (btif_a2dp_source_cb.encoder_interface != NULL)
+ if (btif_a2dp_source_cb.encoder_interface != nullptr)
btif_a2dp_source_cb.encoder_interface->feeding_reset();
}
static void btif_a2dp_source_alarm_cb(UNUSED_ATTR void* context) {
- thread_post(btif_a2dp_source_cb.worker_thread,
- btif_a2dp_source_audio_handle_timer, NULL);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_handle_timer));
}
-static void btif_a2dp_source_audio_handle_timer(UNUSED_ATTR void* context) {
+static void btif_a2dp_source_audio_handle_timer(void) {
+ if (btif_av_is_a2dp_offload_enabled()) return;
+
uint64_t timestamp_us = time_get_os_boottime_us();
log_tstamps_us("A2DP Source tx timer", timestamp_us);
- if (alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) {
- CHECK(btif_a2dp_source_cb.encoder_interface != NULL);
- size_t transmit_queue_length =
- fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue);
-#ifndef OS_GENERIC
- ATRACE_INT("btif TX queue", transmit_queue_length);
-#endif
- if (btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length !=
- NULL) {
- btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length(
- transmit_queue_length);
- }
- btif_a2dp_source_cb.encoder_interface->send_frames(timestamp_us);
- bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
- update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_enqueue_stats,
- timestamp_us,
- btif_a2dp_source_cb.encoder_interval_ms * 1000);
- } else {
- APPL_TRACE_ERROR("ERROR Media task Scheduled after Suspend");
+ if (!alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) {
+ LOG_ERROR(LOG_TAG, "%s: ERROR Media task Scheduled after Suspend",
+ __func__);
+ return;
}
+ CHECK(btif_a2dp_source_cb.encoder_interface != nullptr);
+ size_t transmit_queue_length =
+ fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue);
+#ifndef OS_GENERIC
+ ATRACE_INT("btif TX queue", transmit_queue_length);
+#endif
+ if (btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length !=
+ nullptr) {
+ btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length(
+ transmit_queue_length);
+ }
+ btif_a2dp_source_cb.encoder_interface->send_frames(timestamp_us);
+ bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
+ update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_enqueue_stats,
+ timestamp_us,
+ btif_a2dp_source_cb.encoder_interval_ms * 1000);
}
static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len) {
uint16_t event;
- uint32_t bytes_read = UIPC_Read(UIPC_CH_ID_AV_AUDIO, &event, p_buf, len);
+ uint32_t bytes_read =
+ UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, &event, p_buf, len);
if (bytes_read < len) {
LOG_WARN(LOG_TAG, "%s: UNDERFLOW: ONLY READ %d BYTES OUT OF %d", __func__,
@@ -703,8 +927,10 @@
return bytes_read;
}
-static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n) {
+static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n,
+ uint32_t bytes_read) {
uint64_t now_us = time_get_os_boottime_us();
+ btif_a2dp_control_log_bytes_read(bytes_read);
/* Check if timer was stopped (media task stopped) */
if (!alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) {
@@ -747,7 +973,7 @@
}
// Request additional debug info if we had to flush buffers
- RawAddress peer_bda = btif_av_get_addr();
+ RawAddress peer_bda = btif_av_source_active_peer();
tBTM_STATUS status = BTM_ReadRSSI(peer_bda, btm_read_rssi_cb);
if (status != BTM_CMD_STARTED) {
LOG_WARN(LOG_TAG, "%s: Cannot read RSSI: status %d", __func__, status);
@@ -776,18 +1002,20 @@
btif_a2dp_source_cb.stats.tx_queue_total_frames += frames_n;
btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet = std::max(
frames_n, btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet);
- CHECK(btif_a2dp_source_cb.encoder_interface != NULL);
+ CHECK(btif_a2dp_source_cb.encoder_interface != nullptr);
fixed_queue_enqueue(btif_a2dp_source_cb.tx_audio_queue, p_buf);
return true;
}
-static void btif_a2dp_source_audio_tx_flush_event(UNUSED_ATTR BT_HDR* p_msg) {
+static void btif_a2dp_source_audio_tx_flush_event(void) {
/* Flush all enqueued audio buffers (encoded) */
- APPL_TRACE_DEBUG("%s", __func__);
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
+ if (btif_av_is_a2dp_offload_enabled()) return;
- if (btif_a2dp_source_cb.encoder_interface != NULL)
+ if (btif_a2dp_source_cb.encoder_interface != nullptr)
btif_a2dp_source_cb.encoder_interface->feeding_flush();
btif_a2dp_source_cb.stats.tx_queue_total_flushed_messages +=
@@ -796,27 +1024,15 @@
time_get_os_boottime_us();
fixed_queue_flush(btif_a2dp_source_cb.tx_audio_queue, osi_free);
- UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REQ_RX_FLUSH, NULL);
+ UIPC_Ioctl(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, UIPC_REQ_RX_FLUSH, nullptr);
}
static bool btif_a2dp_source_audio_tx_flush_req(void) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
+ LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
+ btif_a2dp_source_cb.StateStr().c_str());
- p_buf->event = BTIF_MEDIA_AUDIO_TX_FLUSH;
-
- /*
- * Explicitly check whether the btif_a2dp_source_cb.cmd_msg_queue is not
- * NULL to avoid a race condition during shutdown of the Bluetooth stack.
- * This race condition is triggered when A2DP audio is streaming on
- * shutdown:
- * "btif_a2dp_source_on_stopped() -> btif_a2dp_source_audio_tx_flush_req()"
- * is called to stop the particular audio stream, and this happens right
- * after the "BTIF_AV_CLEANUP_REQ_EVT -> btif_a2dp_source_shutdown()"
- * processing during the shutdown of the Bluetooth stack.
- */
- if (btif_a2dp_source_cb.cmd_msg_queue != NULL)
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
-
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_tx_flush_event));
return true;
}
@@ -827,7 +1043,7 @@
btif_a2dp_source_cb.stats.tx_queue_total_readbuf_calls++;
btif_a2dp_source_cb.stats.tx_queue_last_readbuf_us = now_us;
- if (p_buf != NULL) {
+ if (p_buf != nullptr) {
// Update the statistics
update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_dequeue_stats,
now_us,
@@ -839,13 +1055,14 @@
static void log_tstamps_us(const char* comment, uint64_t timestamp_us) {
static uint64_t prev_us = 0;
- APPL_TRACE_DEBUG("[%s] ts %08llu, diff : %08llu, queue sz %d", comment,
- timestamp_us, timestamp_us - prev_us,
+ APPL_TRACE_DEBUG("%s: [%s] ts %08" PRIu64 ", diff : %08" PRIu64
+ ", queue sz %zu",
+ __func__, comment, timestamp_us, timestamp_us - prev_us,
fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue));
prev_us = timestamp_us;
}
-static void update_scheduling_stats(scheduling_stats_t* stats, uint64_t now_us,
+static void update_scheduling_stats(SchedulingStats* stats, uint64_t now_us,
uint64_t expected_delta) {
uint64_t last_us = stats->last_update_us;
@@ -888,12 +1105,9 @@
btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats,
&btif_a2dp_source_cb.accumulated_stats);
uint64_t now_us = time_get_os_boottime_us();
- btif_media_stats_t* accumulated_stats =
- &btif_a2dp_source_cb.accumulated_stats;
- scheduling_stats_t* enqueue_stats =
- &accumulated_stats->tx_queue_enqueue_stats;
- scheduling_stats_t* dequeue_stats =
- &accumulated_stats->tx_queue_dequeue_stats;
+ BtifMediaStats* accumulated_stats = &btif_a2dp_source_cb.accumulated_stats;
+ SchedulingStats* enqueue_stats = &accumulated_stats->tx_queue_enqueue_stats;
+ SchedulingStats* dequeue_stats = &accumulated_stats->tx_queue_dequeue_stats;
size_t ave_size;
uint64_t ave_time_us;
@@ -1050,53 +1264,49 @@
(unsigned long long)dequeue_stats->max_premature_scheduling_delta_us /
1000,
(unsigned long long)ave_time_us / 1000);
-
- //
- // Codec-specific stats
- //
- A2dpCodecs* a2dp_codecs = bta_av_get_a2dp_codecs();
- if (a2dp_codecs != nullptr) {
- a2dp_codecs->debug_codec_dump(fd);
- }
}
-void btif_a2dp_source_update_metrics(void) {
- btif_media_stats_t* stats = &btif_a2dp_source_cb.stats;
- scheduling_stats_t* enqueue_stats = &stats->tx_queue_enqueue_stats;
+static void btif_a2dp_source_update_metrics(void) {
+ BtifMediaStats stats = btif_a2dp_source_cb.stats;
+ SchedulingStats enqueue_stats = stats.tx_queue_enqueue_stats;
A2dpSessionMetrics metrics;
+ metrics.codec_index = stats.codec_index;
+ metrics.is_a2dp_offload = btif_av_is_a2dp_offload_enabled();
// session_start_us is 0 when btif_a2dp_source_start_audio_req() is not called
// mark the metric duration as invalid (-1) in this case
- if (stats->session_start_us != 0) {
- int64_t session_end_us = stats->session_end_us == 0
+ if (stats.session_start_us != 0) {
+ int64_t session_end_us = stats.session_end_us == 0
? time_get_os_boottime_us()
- : stats->session_end_us;
- metrics.audio_duration_ms =
- (session_end_us - stats->session_start_us) / 1000;
+ : stats.session_end_us;
+ if (static_cast<uint64_t>(session_end_us) > stats.session_start_us) {
+ metrics.audio_duration_ms =
+ (session_end_us - stats.session_start_us) / 1000;
+ }
}
- if (enqueue_stats->total_updates > 1) {
+ if (enqueue_stats.total_updates > 1) {
metrics.media_timer_min_ms =
btif_a2dp_source_cb.encoder_interval_ms -
- (enqueue_stats->max_premature_scheduling_delta_us / 1000);
+ (enqueue_stats.max_premature_scheduling_delta_us / 1000);
metrics.media_timer_max_ms =
btif_a2dp_source_cb.encoder_interval_ms +
- (enqueue_stats->max_overdue_scheduling_delta_us / 1000);
+ (enqueue_stats.max_overdue_scheduling_delta_us / 1000);
- metrics.total_scheduling_count = enqueue_stats->overdue_scheduling_count +
- enqueue_stats->premature_scheduling_count +
- enqueue_stats->exact_scheduling_count;
+ metrics.total_scheduling_count = enqueue_stats.overdue_scheduling_count +
+ enqueue_stats.premature_scheduling_count +
+ enqueue_stats.exact_scheduling_count;
if (metrics.total_scheduling_count > 0) {
- metrics.media_timer_avg_ms = enqueue_stats->total_scheduling_time_us /
+ metrics.media_timer_avg_ms = enqueue_stats.total_scheduling_time_us /
(1000 * metrics.total_scheduling_count);
}
- metrics.buffer_overruns_max_count = stats->tx_queue_max_dropped_messages;
- metrics.buffer_overruns_total = stats->tx_queue_total_dropped_messages;
- metrics.buffer_underruns_count = stats->media_read_total_underflow_count;
+ metrics.buffer_overruns_max_count = stats.tx_queue_max_dropped_messages;
+ metrics.buffer_overruns_total = stats.tx_queue_total_dropped_messages;
+ metrics.buffer_underruns_count = stats.media_read_total_underflow_count;
metrics.buffer_underruns_average = 0;
if (metrics.buffer_underruns_count > 0) {
metrics.buffer_underruns_average =
- stats->media_read_total_underflow_bytes /
+ stats.media_read_total_underflow_bytes /
metrics.buffer_underruns_count;
}
}
@@ -1105,24 +1315,24 @@
static void btm_read_rssi_cb(void* data) {
if (data == nullptr) {
- LOG_ERROR(LOG_TAG, "%s Read RSSI request timed out", __func__);
+ LOG_ERROR(LOG_TAG, "%s: Read RSSI request timed out", __func__);
return;
}
tBTM_RSSI_RESULT* result = (tBTM_RSSI_RESULT*)data;
if (result->status != BTM_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s unable to read remote RSSI (status %d)", __func__,
+ LOG_ERROR(LOG_TAG, "%s: unable to read remote RSSI (status %d)", __func__,
result->status);
return;
}
- LOG_WARN(LOG_TAG, "%s device: %s, rssi: %d", __func__,
+ LOG_WARN(LOG_TAG, "%s: device: %s, rssi: %d", __func__,
result->rem_bda.ToString().c_str(), result->rssi);
}
static void btm_read_failed_contact_counter_cb(void* data) {
if (data == nullptr) {
- LOG_ERROR(LOG_TAG, "%s Read Failed Contact Counter request timed out",
+ LOG_ERROR(LOG_TAG, "%s: Read Failed Contact Counter request timed out",
__func__);
return;
}
@@ -1130,18 +1340,18 @@
tBTM_FAILED_CONTACT_COUNTER_RESULT* result =
(tBTM_FAILED_CONTACT_COUNTER_RESULT*)data;
if (result->status != BTM_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s unable to read Failed Contact Counter (status %d)",
+ LOG_ERROR(LOG_TAG, "%s: unable to read Failed Contact Counter (status %d)",
__func__, result->status);
return;
}
- LOG_WARN(LOG_TAG, "%s device: %s, Failed Contact Counter: %u", __func__,
+ LOG_WARN(LOG_TAG, "%s: device: %s, Failed Contact Counter: %u", __func__,
result->rem_bda.ToString().c_str(), result->failed_contact_counter);
}
static void btm_read_automatic_flush_timeout_cb(void* data) {
if (data == nullptr) {
- LOG_ERROR(LOG_TAG, "%s Read Automatic Flush Timeout request timed out",
+ LOG_ERROR(LOG_TAG, "%s: Read Automatic Flush Timeout request timed out",
__func__);
return;
}
@@ -1149,28 +1359,28 @@
tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT* result =
(tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT*)data;
if (result->status != BTM_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s unable to read Automatic Flush Timeout (status %d)",
+ LOG_ERROR(LOG_TAG, "%s: unable to read Automatic Flush Timeout (status %d)",
__func__, result->status);
return;
}
- LOG_WARN(LOG_TAG, "%s device: %s, Automatic Flush Timeout: %u", __func__,
+ LOG_WARN(LOG_TAG, "%s: device: %s, Automatic Flush Timeout: %u", __func__,
result->rem_bda.ToString().c_str(), result->automatic_flush_timeout);
}
static void btm_read_tx_power_cb(void* data) {
if (data == nullptr) {
- LOG_ERROR(LOG_TAG, "%s Read Tx Power request timed out", __func__);
+ LOG_ERROR(LOG_TAG, "%s: Read Tx Power request timed out", __func__);
return;
}
tBTM_TX_POWER_RESULT* result = (tBTM_TX_POWER_RESULT*)data;
if (result->status != BTM_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s unable to read Tx Power (status %d)", __func__,
+ LOG_ERROR(LOG_TAG, "%s: unable to read Tx Power (status %d)", __func__,
result->status);
return;
}
- LOG_WARN(LOG_TAG, "%s device: %s, Tx Power: %d", __func__,
+ LOG_WARN(LOG_TAG, "%s: device: %s, Tx Power: %d", __func__,
result->rem_bda.ToString().c_str(), result->tx_power);
}
diff --git a/btif/src/btif_av.cc b/btif/src/btif_av.cc
index 0178e36..8d416c1 100644
--- a/btif/src/btif_av.cc
+++ b/btif/src/btif_av.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2016 Broadcom Corporation
+ * Copyright 2009-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,11 @@
#include "btif_av.h"
+#include <base/bind.h>
#include <base/logging.h>
+#include <base/strings/stringprintf.h>
#include <string.h>
+#include <map>
#include <hardware/bluetooth.h>
#include <hardware/bt_av.h>
@@ -30,87 +33,556 @@
#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
#include "bt_common.h"
#include "bt_utils.h"
-#include "bta_api.h"
+#include "bta/include/bta_api.h"
+#include "bta/include/bta_closure_api.h"
+#include "btif/include/btif_a2dp_source.h"
#include "btif_a2dp.h"
+#include "btif_a2dp_audio_interface.h"
#include "btif_a2dp_control.h"
#include "btif_a2dp_sink.h"
#include "btif_av_co.h"
#include "btif_profile_queue.h"
+#include "btif_rc.h"
+#include "btif_state_machine.h"
#include "btif_util.h"
#include "btu.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
+#include "osi/include/properties.h"
/*****************************************************************************
* Constants & Macros
*****************************************************************************/
-#define BTIF_AV_SERVICE_NAME "Advanced Audio"
-#define BTIF_AVK_SERVICE_NAME "Advanced Audio Sink"
-
-#define BTIF_TIMEOUT_AV_OPEN_ON_RC_MS (2 * 1000)
-
-typedef enum {
- BTIF_AV_STATE_IDLE = 0x0,
- BTIF_AV_STATE_OPENING,
- BTIF_AV_STATE_OPENED,
- BTIF_AV_STATE_STARTED,
- BTIF_AV_STATE_CLOSING
-} btif_av_state_t;
-
-/* Should not need dedicated suspend state as actual actions are no
- different than open state. Suspend flags are needed however to prevent
- media task from trying to restart stream during remote suspend or while
- we are in the process of a local suspend */
-
-#define BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING 0x1
-#define BTIF_AV_FLAG_REMOTE_SUSPEND 0x2
-#define BTIF_AV_FLAG_PENDING_START 0x4
-#define BTIF_AV_FLAG_PENDING_STOP 0x8
+static const std::string kBtifAvSourceServiceName = "Advanced Audio Source";
+static const std::string kBtifAvSinkServiceName = "Advanced Audio Sink";
+static constexpr int kDefaultMaxConnectedAudioDevices = 1;
+static constexpr tBTA_AV_HNDL kBtaHandleUnknown = 0;
/*****************************************************************************
* Local type definitions
*****************************************************************************/
typedef struct {
- tBTA_AV_HNDL bta_handle;
- RawAddress peer_bda;
- bool self_initiated_connection;
- btif_sm_handle_t sm_handle;
- uint8_t flags;
- tBTA_AV_EDR edr;
- uint8_t peer_sep; /* sep type of peer device */
- std::vector<btav_a2dp_codec_config_t> codec_priorities;
-} btif_av_cb_t;
-
-typedef struct {
- RawAddress* target_bda;
- uint16_t uuid;
-} btif_av_connect_req_t;
-
-typedef struct {
int sample_rate;
int channel_count;
- RawAddress peer_bd;
+ RawAddress peer_address;
} btif_av_sink_config_req_t;
+/**
+ * BTIF AV events
+ */
+typedef enum {
+ /* Reuse BTA_AV_XXX_EVT - No need to redefine them here */
+ BTIF_AV_CONNECT_REQ_EVT = BTA_AV_MAX_EVT,
+ BTIF_AV_DISCONNECT_REQ_EVT,
+ BTIF_AV_START_STREAM_REQ_EVT,
+ BTIF_AV_STOP_STREAM_REQ_EVT,
+ BTIF_AV_SUSPEND_STREAM_REQ_EVT,
+ BTIF_AV_SINK_CONFIG_REQ_EVT,
+ BTIF_AV_ACL_DISCONNECTED,
+ BTIF_AV_OFFLOAD_START_REQ_EVT,
+ BTIF_AV_AVRCP_OPEN_EVT,
+ BTIF_AV_AVRCP_CLOSE_EVT,
+ BTIF_AV_AVRCP_REMOTE_PLAY_EVT,
+} btif_av_sm_event_t;
+
+class BtifAvEvent {
+ public:
+ BtifAvEvent(uint32_t event, const void* p_data, size_t data_length);
+ BtifAvEvent(const BtifAvEvent& other);
+ BtifAvEvent() = delete;
+ ~BtifAvEvent();
+ BtifAvEvent& operator=(const BtifAvEvent& other);
+
+ uint32_t Event() const { return event_; }
+ void* Data() const { return data_; }
+ size_t DataLength() const { return data_length_; }
+ std::string ToString() const;
+ static std::string EventName(uint32_t event);
+
+ private:
+ void DeepCopy(uint32_t event, const void* p_data, size_t data_length);
+ void DeepFree();
+
+ uint32_t event_;
+ void* data_;
+ size_t data_length_;
+};
+
+class BtifAvPeer;
+
+// Should not need dedicated Suspend state as actual actions are no
+// different than Open state. Suspend flags are needed however to prevent
+// media task from trying to restart stream during remote Suspend or while
+// we are in the process of a local Suspend.
+class BtifAvStateMachine : public BtifStateMachine {
+ public:
+ enum {
+ kStateIdle, // AVDTP disconnected
+ kStateOpening, // Opening AVDTP connection
+ kStateOpened, // AVDTP is in OPEN state
+ kStateStarted, // A2DP stream started
+ kStateClosing, // Closing AVDTP connection
+ };
+
+ class StateIdle : public State {
+ public:
+ StateIdle(BtifAvStateMachine& sm)
+ : State(sm, kStateIdle), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ class StateOpening : public State {
+ public:
+ StateOpening(BtifAvStateMachine& sm)
+ : State(sm, kStateOpening), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ class StateOpened : public State {
+ public:
+ StateOpened(BtifAvStateMachine& sm)
+ : State(sm, kStateOpened), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ class StateStarted : public State {
+ public:
+ StateStarted(BtifAvStateMachine& sm)
+ : State(sm, kStateStarted), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ class StateClosing : public State {
+ public:
+ StateClosing(BtifAvStateMachine& sm)
+ : State(sm, kStateClosing), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ BtifAvStateMachine(BtifAvPeer& btif_av_peer) : peer_(btif_av_peer) {
+ state_idle_ = new StateIdle(*this);
+ state_opening_ = new StateOpening(*this);
+ state_opened_ = new StateOpened(*this);
+ state_started_ = new StateStarted(*this);
+ state_closing_ = new StateClosing(*this);
+
+ AddState(state_idle_);
+ AddState(state_opening_);
+ AddState(state_opened_);
+ AddState(state_started_);
+ AddState(state_closing_);
+ SetInitialState(state_idle_);
+ }
+
+ BtifAvPeer& Peer() { return peer_; }
+
+ private:
+ BtifAvPeer& peer_;
+ StateIdle* state_idle_;
+ StateOpening* state_opening_;
+ StateOpened* state_opened_;
+ StateStarted* state_started_;
+ StateClosing* state_closing_;
+};
+
+class BtifAvPeer {
+ public:
+ enum {
+ kFlagLocalSuspendPending = 0x1,
+ kFlagRemoteSuspend = 0x2,
+ kFlagPendingStart = 0x4,
+ kFlagPendingStop = 0x8,
+ };
+ static constexpr period_ms_t kTimeoutAvOpenOnRcMs = 2 * 1000; // 2s
+
+ BtifAvPeer(const RawAddress& peer_address, uint8_t peer_sep,
+ tBTA_AV_HNDL bta_handle, uint8_t peer_id);
+ ~BtifAvPeer();
+
+ bt_status_t Init();
+ void Cleanup();
+
+ /**
+ * Check whether the peer can be deleted.
+ *
+ * @return true if the pair can be deleted, otherwise false
+ */
+ bool CanBeDeleted() const;
+
+ /**
+ * Check whether the peer is the active one.
+ *
+ * @return true if this peer is the active one
+ */
+ bool IsActivePeer() const { return (PeerAddress() == ActivePeerAddress()); }
+
+ /**
+ * Get the address of the active peer.
+ *
+ * @return the address of the active peer
+ */
+ const RawAddress& ActivePeerAddress() const;
+
+ const RawAddress& PeerAddress() const { return peer_address_; }
+ bool IsSource() const { return (peer_sep_ == AVDT_TSEP_SRC); }
+ bool IsSink() const { return (peer_sep_ == AVDT_TSEP_SNK); }
+ uint8_t PeerSep() const { return peer_sep_; }
+ /**
+ * Get the local device's Service Class UUID
+ *
+ * @return the local device's Service Class UUID: UUID_SERVCLASS_AUDIO_SOURCE
+ * or UUID_SERVCLASS_AUDIO_SINK
+ */
+ uint16_t LocalUuidServiceClass() const {
+ return (IsSink() ? UUID_SERVCLASS_AUDIO_SOURCE : UUID_SERVCLASS_AUDIO_SINK);
+ }
+ tBTA_AV_HNDL BtaHandle() const { return bta_handle_; }
+ void SetBtaHandle(tBTA_AV_HNDL bta_handle) { bta_handle_ = bta_handle; }
+ uint8_t PeerId() const { return peer_id_; }
+
+ BtifAvStateMachine& StateMachine() { return state_machine_; }
+ const BtifAvStateMachine& StateMachine() const { return state_machine_; }
+ alarm_t* AvOpenOnRcTimer() { return av_open_on_rc_timer_; }
+ const alarm_t* AvOpenOnRcTimer() const { return av_open_on_rc_timer_; }
+
+ void SetEdr(tBTA_AV_EDR edr) { edr_ = edr; }
+ bool IsEdr() const { return (edr_ != 0); }
+ bool Is3Mbps() const { return ((edr_ & BTA_AV_EDR_3MBPS) != 0); }
+
+ bool IsConnected() const;
+ bool IsStreaming() const;
+
+ /**
+ * Check whether any of the flags specified by the bitlags mask is set.
+ *
+ * @param bitflags_mask the bitflags to check
+ * @return true if any of the flags to check is set, otherwise false.
+ */
+ bool CheckFlags(uint8_t bitflags_mask) const {
+ return ((flags_ & bitflags_mask) != 0);
+ }
+
+ /**
+ * Set only the flags as specified by the bitflags mask.
+ *
+ * @param bitflags_mask the bitflags to set
+ */
+ void SetFlags(uint8_t bitflags_mask) { flags_ |= bitflags_mask; }
+
+ /**
+ * Clear only the flags as specified by the bitflags mask.
+ *
+ * @param bitflags_mask the bitflags to clear
+ */
+ void ClearFlags(uint8_t bitflags_mask) { flags_ &= ~bitflags_mask; }
+
+ /**
+ * Clear all flags.
+ */
+ void ClearAllFlags() { flags_ = 0; }
+
+ /**
+ * Get a string representation of the flags that are set.
+ */
+ std::string FlagsToString() const;
+
+ bool SelfInitiatedConnection() const { return self_initiated_connection_; }
+ void SetSelfInitiatedConnection(bool v) { self_initiated_connection_ = v; }
+
+ private:
+ const RawAddress peer_address_;
+ const uint8_t peer_sep_; // SEP type of peer device
+ tBTA_AV_HNDL bta_handle_;
+ const uint8_t peer_id_;
+ BtifAvStateMachine state_machine_;
+ alarm_t* av_open_on_rc_timer_;
+ tBTA_AV_EDR edr_;
+ uint8_t flags_;
+ bool self_initiated_connection_;
+};
+
+class BtifAvSource {
+ public:
+ // The PeerId is used as AppId for BTA_AvRegister() purpose
+ static constexpr uint8_t kPeerIdMin = 0;
+ static constexpr uint8_t kPeerIdMax = BTA_AV_NUM_STRS;
+
+ BtifAvSource()
+ : callbacks_(nullptr),
+ enabled_(false),
+ a2dp_offload_enabled_(false),
+ max_connected_peers_(kDefaultMaxConnectedAudioDevices) {}
+ ~BtifAvSource();
+
+ bt_status_t Init(
+ btav_source_callbacks_t* callbacks, int max_connected_audio_devices,
+ const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
+ void Cleanup();
+
+ btav_source_callbacks_t* Callbacks() { return callbacks_; }
+ bool Enabled() const { return enabled_; }
+ bool A2dpOffloadEnabled() const { return a2dp_offload_enabled_; }
+
+ BtifAvPeer* FindPeer(const RawAddress& peer_address);
+ BtifAvPeer* FindPeerByHandle(tBTA_AV_HNDL bta_handle);
+ BtifAvPeer* FindPeerByPeerId(uint8_t peer_id);
+ BtifAvPeer* FindOrCreatePeer(const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle);
+
+ /**
+ * Check whether a connection to a peer is allowed.
+ * The check considers the maximum number of connected peers.
+ *
+ * @param peer_address the peer address to connect to
+ * @return true if connection is allowed, otherwise false
+ */
+ bool AllowedToConnect(const RawAddress& peer_address) const;
+
+ /**
+ * Delete a peer.
+ *
+ * @param peer_address the peer to delete
+ * @return true on success, otherwise false
+ */
+ bool DeletePeer(const RawAddress& peer_address);
+
+ /**
+ * Delete all peers that have transitioned to Idle state and can be deleted.
+ * If a peer was just created/initialized, then it cannot be deleted yet.
+ */
+ void DeleteIdlePeers();
+
+ /**
+ * Get the active peer.
+ *
+ * @return the active peer
+ */
+ const RawAddress& ActivePeer() const { return active_peer_; }
+
+ /**
+ * Set the active peer.
+ *
+ * @param peer_address the active peer address or RawAddress::kEmpty to
+ * reset the active peer
+ * @return true on success, otherwise false
+ */
+ bool SetActivePeer(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer: %s", __PRETTY_FUNCTION__,
+ peer_address.ToString().c_str());
+
+ if (active_peer_ == peer_address) return true; // Nothing has changed
+ if (peer_address.IsEmpty()) {
+ BTIF_TRACE_EVENT("%s: peer address is empty, shutdown the Audio source",
+ __func__);
+ if (!bta_av_co_set_active_peer(peer_address)) {
+ BTIF_TRACE_WARNING("%s: unable to set active peer to empty in BtaAvCo",
+ __func__);
+ }
+ btif_a2dp_source_end_session(active_peer_);
+ btif_a2dp_source_shutdown();
+ active_peer_ = peer_address;
+ return true;
+ }
+
+ BtifAvPeer* peer = FindPeer(peer_address);
+ if (peer != nullptr && !peer->IsConnected()) {
+ BTIF_TRACE_ERROR("%s: Error setting %s as active Source peer", __func__,
+ peer->PeerAddress().ToString().c_str());
+ return false;
+ }
+
+ if (!btif_a2dp_source_restart_session(active_peer_, peer_address)) {
+ return false;
+ }
+ active_peer_ = peer_address;
+ return true;
+ }
+
+ /**
+ * Update source codec configuration for a peer.
+ *
+ * @param peer_address the address of the peer to update
+ * @param codec_preferences the updated codec preferences
+ */
+ void UpdateCodecConfig(
+ const RawAddress& peer_address,
+ const std::vector<btav_a2dp_codec_config_t>& codec_preferences) {
+ // Restart the session if the codec for the active peer is updated
+ bool restart_session =
+ ((active_peer_ == peer_address) && !active_peer_.IsEmpty());
+ if (restart_session) {
+ btif_a2dp_source_end_session(active_peer_);
+ }
+
+ for (auto cp : codec_preferences) {
+ BTIF_TRACE_DEBUG("%s: codec_preference=%s", __func__,
+ cp.ToString().c_str());
+ btif_a2dp_source_encoder_user_config_update_req(peer_address, cp);
+ }
+ if (restart_session) {
+ btif_a2dp_source_start_session(active_peer_);
+ }
+ }
+
+ const std::map<RawAddress, BtifAvPeer*>& Peers() const { return peers_; }
+
+ void RegisterAllBtaHandles();
+ void DeregisterAllBtaHandles();
+ void BtaHandleRegistered(uint8_t peer_id, tBTA_AV_HNDL bta_handle);
+
+ private:
+ void CleanupAllPeers();
+
+ btav_source_callbacks_t* callbacks_;
+ bool enabled_;
+ bool a2dp_offload_enabled_;
+ int max_connected_peers_;
+ std::map<RawAddress, BtifAvPeer*> peers_;
+ RawAddress active_peer_;
+ std::map<uint8_t, tBTA_AV_HNDL> peer_id2bta_handle_;
+};
+
+class BtifAvSink {
+ public:
+ // The PeerId is used as AppId for BTA_AvRegister() purpose
+ static constexpr uint8_t kPeerIdMin = 0;
+ static constexpr uint8_t kPeerIdMax = BTA_AV_NUM_STRS;
+
+ BtifAvSink()
+ : callbacks_(nullptr),
+ enabled_(false),
+ max_connected_peers_(kDefaultMaxConnectedAudioDevices) {}
+ ~BtifAvSink();
+
+ bt_status_t Init(btav_sink_callbacks_t* callbacks);
+ void Cleanup();
+
+ btav_sink_callbacks_t* Callbacks() { return callbacks_; }
+ bool Enabled() const { return enabled_; }
+
+ BtifAvPeer* FindPeer(const RawAddress& peer_address);
+ BtifAvPeer* FindPeerByHandle(tBTA_AV_HNDL bta_handle);
+ BtifAvPeer* FindPeerByPeerId(uint8_t peer_id);
+ BtifAvPeer* FindOrCreatePeer(const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle);
+
+ /**
+ * Check whether a connection to a peer is allowed.
+ * The check considers the maximum number of connected peers.
+ *
+ * @param peer_address the peer address to connect to
+ * @return true if connection is allowed, otherwise false
+ */
+ bool AllowedToConnect(const RawAddress& peer_address) const;
+
+ /**
+ * Delete a peer.
+ *
+ * @param peer_address the peer to delete
+ * @return true on success, otherwise false
+ */
+ bool DeletePeer(const RawAddress& peer_address);
+
+ /**
+ * Delete all peers that have transitioned to Idle state and can be deleted.
+ * If a peer was just created/initialized, then it cannot be deleted yet.
+ */
+ void DeleteIdlePeers();
+
+ /**
+ * Get the active peer.
+ *
+ * @return the active peer
+ */
+ const RawAddress& ActivePeer() const { return active_peer_; }
+
+ /**
+ * Set the active peer.
+ *
+ * @param peer_address the active peer address or RawAddress::kEmpty to
+ * reset the active peer
+ * @return true on success, otherwise false
+ */
+ bool SetActivePeer(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer: %s", __PRETTY_FUNCTION__,
+ peer_address.ToString().c_str());
+
+ if (active_peer_ == peer_address) return true; // Nothing has changed
+ if (peer_address.IsEmpty()) {
+ BTIF_TRACE_EVENT("%s: peer address is empty, shutdown the Audio sink",
+ __func__);
+ if (!bta_av_co_set_active_peer(peer_address)) {
+ BTIF_TRACE_WARNING("%s: unable to set active peer to empty in BtaAvCo",
+ __func__);
+ }
+ btif_a2dp_sink_end_session(active_peer_);
+ btif_a2dp_sink_shutdown();
+ active_peer_ = peer_address;
+ return true;
+ }
+
+ BtifAvPeer* peer = FindPeer(peer_address);
+ if (peer != nullptr && !peer->IsConnected()) {
+ BTIF_TRACE_ERROR("%s: Error setting %s as active Sink peer", __func__,
+ peer->PeerAddress().ToString().c_str());
+ return false;
+ }
+
+ if (!btif_a2dp_sink_restart_session(active_peer_, peer_address)) {
+ return false;
+ }
+ active_peer_ = peer_address;
+ return true;
+ }
+
+ const std::map<RawAddress, BtifAvPeer*>& Peers() const { return peers_; }
+
+ void RegisterAllBtaHandles();
+ void DeregisterAllBtaHandles();
+ void BtaHandleRegistered(uint8_t peer_id, tBTA_AV_HNDL bta_handle);
+
+ private:
+ void CleanupAllPeers();
+
+ btav_sink_callbacks_t* callbacks_;
+ bool enabled_;
+ int max_connected_peers_;
+ std::map<RawAddress, BtifAvPeer*> peers_;
+ RawAddress active_peer_;
+ std::map<uint8_t, tBTA_AV_HNDL> peer_id2bta_handle_;
+};
+
/*****************************************************************************
* Static variables
*****************************************************************************/
-static btav_source_callbacks_t* bt_av_src_callbacks = NULL;
-static btav_sink_callbacks_t* bt_av_sink_callbacks = NULL;
-static btif_av_cb_t btif_av_cb = {
- 0, {{0}}, false, 0, 0, 0, 0, std::vector<btav_a2dp_codec_config_t>()};
-static alarm_t* av_open_on_rc_timer = NULL;
-
-/* both interface and media task needs to be ready to alloc incoming request */
-#define CHECK_BTAV_INIT() \
- do { \
- if (((bt_av_src_callbacks == NULL) && (bt_av_sink_callbacks == NULL)) || \
- (btif_av_cb.sm_handle == NULL)) { \
- BTIF_TRACE_WARNING("%s: BTAV not initialized", __func__); \
- return BT_STATUS_NOT_READY; \
- } \
- } while (0)
+static BtifAvSource btif_av_source;
+static BtifAvSink btif_av_sink;
/* Helper macro to avoid code duplication in the state machine handlers */
#define CHECK_RC_EVENT(e, d) \
@@ -126,44 +598,50 @@
btif_rc_handler(e, d); \
} break;
-static bool btif_av_state_idle_handler(btif_sm_event_t event, void* data);
-static bool btif_av_state_opening_handler(btif_sm_event_t event, void* data);
-static bool btif_av_state_opened_handler(btif_sm_event_t event, void* data);
-static bool btif_av_state_started_handler(btif_sm_event_t event, void* data);
-static bool btif_av_state_closing_handler(btif_sm_event_t event, void* data);
+static bt_status_t src_disconnect_sink(const RawAddress& peer_address);
+static bt_status_t sink_disconnect_src(const RawAddress& peer_address);
+static void btif_av_source_dispatch_sm_event(const RawAddress& peer_address,
+ btif_av_sm_event_t event);
+static void btif_av_sink_dispatch_sm_event(const RawAddress& peer_address,
+ btif_av_sm_event_t event);
+static void btif_av_handle_event(uint8_t peer_sep,
+ const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle,
+ const BtifAvEvent& btif_av_event);
+static void btif_report_connection_state(const RawAddress& peer_address,
+ btav_connection_state_t state);
+static void btif_report_audio_state(const RawAddress& peer_address,
+ btav_audio_state_t state);
+static void btif_av_report_sink_audio_config_state(
+ const RawAddress& peer_address, int sample_rate, int channel_count);
+static void btif_av_source_initiate_av_open_timer_timeout(void* data);
+static void btif_av_sink_initiate_av_open_timer_timeout(void* data);
+static void bta_av_sink_media_callback(tBTA_AV_EVT event,
+ tBTA_AV_MEDIA* p_data);
-static const btif_sm_handler_t btif_av_state_handlers[] = {
- btif_av_state_idle_handler, btif_av_state_opening_handler,
- btif_av_state_opened_handler, btif_av_state_started_handler,
- btif_av_state_closing_handler};
-
-static void btif_av_event_free_data(btif_sm_event_t event, void* p_data);
-
-/*************************************************************************
- * Extern functions
- ************************************************************************/
-extern void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data);
-extern bool btif_rc_get_connected_peer(RawAddress* peer_addr);
-extern uint8_t btif_rc_get_connected_peer_handle(const RawAddress& peer_addr);
-extern void btif_rc_check_handle_pending_play(const RawAddress& peer_addr,
- bool bSendToApp);
+static BtifAvPeer* btif_av_source_find_peer(const RawAddress& peer_address) {
+ return btif_av_source.FindPeer(peer_address);
+}
+static BtifAvPeer* btif_av_sink_find_peer(const RawAddress& peer_address) {
+ return btif_av_sink.FindPeer(peer_address);
+}
+static BtifAvPeer* btif_av_find_peer(const RawAddress& peer_address) {
+ if (btif_av_source.Enabled()) return btif_av_source_find_peer(peer_address);
+ if (btif_av_sink.Enabled()) return btif_av_sink_find_peer(peer_address);
+ return nullptr;
+}
+static BtifAvPeer* btif_av_find_active_peer() {
+ if (btif_av_source.Enabled())
+ return btif_av_source_find_peer(btif_av_source.ActivePeer());
+ if (btif_av_sink.Enabled())
+ return btif_av_sink_find_peer(btif_av_sink.ActivePeer());
+ return nullptr;
+}
/*****************************************************************************
* Local helper functions
*****************************************************************************/
-const char* dump_av_sm_state_name(btif_av_state_t state) {
- switch (state) {
- CASE_RETURN_STR(BTIF_AV_STATE_IDLE)
- CASE_RETURN_STR(BTIF_AV_STATE_OPENING)
- CASE_RETURN_STR(BTIF_AV_STATE_OPENED)
- CASE_RETURN_STR(BTIF_AV_STATE_STARTED)
- CASE_RETURN_STR(BTIF_AV_STATE_CLOSING)
- default:
- return "UNKNOWN_STATE";
- }
-}
-
const char* dump_av_sm_event_name(btif_av_sm_event_t event) {
switch ((int)event) {
CASE_RETURN_STR(BTA_AV_ENABLE_EVT)
@@ -189,976 +667,67 @@
CASE_RETURN_STR(BTA_AV_REJECT_EVT)
CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT)
CASE_RETURN_STR(BTA_AV_OFFLOAD_START_RSP_EVT)
- CASE_RETURN_STR(BTIF_SM_ENTER_EVT)
- CASE_RETURN_STR(BTIF_SM_EXIT_EVT)
CASE_RETURN_STR(BTIF_AV_CONNECT_REQ_EVT)
CASE_RETURN_STR(BTIF_AV_DISCONNECT_REQ_EVT)
CASE_RETURN_STR(BTIF_AV_START_STREAM_REQ_EVT)
CASE_RETURN_STR(BTIF_AV_STOP_STREAM_REQ_EVT)
CASE_RETURN_STR(BTIF_AV_SUSPEND_STREAM_REQ_EVT)
- CASE_RETURN_STR(BTIF_AV_SOURCE_CONFIG_REQ_EVT)
- CASE_RETURN_STR(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT)
CASE_RETURN_STR(BTIF_AV_SINK_CONFIG_REQ_EVT)
+ CASE_RETURN_STR(BTIF_AV_ACL_DISCONNECTED)
CASE_RETURN_STR(BTIF_AV_OFFLOAD_START_REQ_EVT)
+ CASE_RETURN_STR(BTIF_AV_AVRCP_OPEN_EVT)
+ CASE_RETURN_STR(BTIF_AV_AVRCP_CLOSE_EVT)
+ CASE_RETURN_STR(BTIF_AV_AVRCP_REMOTE_PLAY_EVT)
default:
return "UNKNOWN_EVENT";
}
}
-/****************************************************************************
- * Local helper functions
- ****************************************************************************/
-/*******************************************************************************
- *
- * Function btif_initiate_av_open_timer_timeout
- *
- * Description Timer to trigger AV open if the remote headset establishes
- * RC connection w/o AV connection. The timer is needed to IOP
- * with headsets that do establish AV after RC connection.
- *
- * Returns void
- *
- ******************************************************************************/
-static void btif_initiate_av_open_timer_timeout(UNUSED_ATTR void* data) {
- RawAddress peer_addr;
- btif_av_connect_req_t connect_req;
+BtifAvEvent::BtifAvEvent(uint32_t event, const void* p_data, size_t data_length)
+ : event_(event), data_(nullptr), data_length_(0) {
+ DeepCopy(event, p_data, data_length);
+}
- /* is there at least one RC connection - There should be */
- if (btif_rc_get_connected_peer(&peer_addr)) {
- BTIF_TRACE_DEBUG("%s: Issuing connect to the remote RC peer", __func__);
- /* In case of AVRCP connection request, we will initiate SRC connection */
- connect_req.target_bda = &peer_addr;
- if (bt_av_sink_callbacks != NULL)
- connect_req.uuid = UUID_SERVCLASS_AUDIO_SINK;
- else if (bt_av_src_callbacks != NULL)
- connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
- btif_dispatch_sm_event(BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req,
- sizeof(connect_req));
+BtifAvEvent::BtifAvEvent(const BtifAvEvent& other)
+ : event_(0), data_(nullptr), data_length_(0) {
+ *this = other;
+}
+
+BtifAvEvent& BtifAvEvent::operator=(const BtifAvEvent& other) {
+ DeepFree();
+ DeepCopy(other.Event(), other.Data(), other.DataLength());
+ return *this;
+}
+
+BtifAvEvent::~BtifAvEvent() { DeepFree(); }
+
+std::string BtifAvEvent::ToString() const {
+ return BtifAvEvent::EventName(event_);
+}
+
+std::string BtifAvEvent::EventName(uint32_t event) {
+ std::string name = dump_av_sm_event_name((btif_av_sm_event_t)event);
+ std::stringstream ss_value;
+ ss_value << "(0x" << std::hex << event << ")";
+ return name + ss_value.str();
+}
+
+void BtifAvEvent::DeepCopy(uint32_t event, const void* p_data,
+ size_t data_length) {
+ event_ = event;
+ data_length_ = data_length;
+ if (data_length == 0) {
+ data_ = nullptr;
} else {
- BTIF_TRACE_ERROR("%s: No connected RC peers", __func__);
- }
-}
-
-/*****************************************************************************
- * Static functions
- *****************************************************************************/
-
-/*******************************************************************************
- *
- * Function btif_report_connection_state
- *
- * Description Updates the components via the callbacks about the
- * connection state of a2dp connection.
- *
- * Returns None
- *
- ******************************************************************************/
-static void btif_report_connection_state(btav_connection_state_t state,
- RawAddress* bd_addr) {
- if (bt_av_sink_callbacks != NULL) {
- HAL_CBACK(bt_av_sink_callbacks, connection_state_cb, state, bd_addr);
- } else if (bt_av_src_callbacks != NULL) {
- HAL_CBACK(bt_av_src_callbacks, connection_state_cb, state, bd_addr);
- }
-}
-
-/*******************************************************************************
- *
- * Function btif_report_audio_state
- *
- * Description Updates the components via the callbacks about the audio
- * state of a2dp connection. The state is updated when either
- * the remote ends starts streaming (started state) or whenever
- * it transitions out of started state (to opened or streaming)
- * state.
- *
- * Returns None
- *
- ******************************************************************************/
-static void btif_report_audio_state(btav_audio_state_t state,
- RawAddress* bd_addr) {
- if (bt_av_sink_callbacks != NULL) {
- HAL_CBACK(bt_av_sink_callbacks, audio_state_cb, state, bd_addr);
- } else if (bt_av_src_callbacks != NULL) {
- HAL_CBACK(bt_av_src_callbacks, audio_state_cb, state, bd_addr);
- }
-}
-
-static void btif_update_source_codec(void* p_data) {
- BTIF_TRACE_DEBUG("%s", __func__);
-
- // copy to avoid alignment problems
- btav_a2dp_codec_config_t req;
- memcpy(&req, p_data, sizeof(req));
-
- btif_a2dp_source_encoder_user_config_update_req(req);
-}
-
-static void btif_report_source_codec_state(UNUSED_ATTR void* p_data) {
- btav_a2dp_codec_config_t codec_config;
- std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities;
- std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities;
-
- A2dpCodecs* a2dp_codecs = bta_av_get_a2dp_codecs();
- if (a2dp_codecs == nullptr) return;
- if (!a2dp_codecs->getCodecConfigAndCapabilities(
- &codec_config, &codecs_local_capabilities,
- &codecs_selectable_capabilities)) {
- BTIF_TRACE_WARNING(
- "%s: error reporting audio source codec state: "
- "cannot get codec config and capabilities",
- __func__);
- return;
- }
- if (bt_av_src_callbacks != NULL) {
- HAL_CBACK(bt_av_src_callbacks, audio_config_cb, codec_config,
- codecs_local_capabilities, codecs_selectable_capabilities);
- }
-}
-
-/*****************************************************************************
- *
- * Function btif_av_state_idle_handler
- *
- * Description State managing disconnected AV link
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_idle_handler(btif_sm_event_t event, void* p_data) {
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- switch (event) {
- case BTIF_SM_ENTER_EVT:
- /* clear the peer_bda */
- btif_av_cb.peer_bda = RawAddress::kEmpty;
- btif_av_cb.flags = 0;
- btif_av_cb.edr = 0;
- bta_av_co_init(btif_av_cb.codec_priorities);
- btif_a2dp_on_idle();
- break;
-
- case BTIF_SM_EXIT_EVT:
- break;
-
- case BTA_AV_ENABLE_EVT:
- break;
-
- case BTA_AV_REGISTER_EVT:
- btif_av_cb.bta_handle = ((tBTA_AV*)p_data)->registr.hndl;
- break;
-
- case BTA_AV_PENDING_EVT:
- case BTIF_AV_CONNECT_REQ_EVT: {
- if (event == BTIF_AV_CONNECT_REQ_EVT) {
- btif_av_connect_req_t* connect_req_p = (btif_av_connect_req_t*)p_data;
- btif_av_cb.peer_bda = *connect_req_p->target_bda;
- btif_av_cb.self_initiated_connection = true;
- BTA_AvOpen(btif_av_cb.peer_bda, btif_av_cb.bta_handle, true,
- BTA_SEC_AUTHENTICATE, connect_req_p->uuid);
- } else if (event == BTA_AV_PENDING_EVT) {
- btif_av_cb.peer_bda = ((tBTA_AV*)p_data)->pend.bd_addr;
- btif_av_cb.self_initiated_connection = false;
- if (bt_av_src_callbacks != NULL) {
- BTA_AvOpen(btif_av_cb.peer_bda, btif_av_cb.bta_handle, true,
- BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SOURCE);
- }
- if (bt_av_sink_callbacks != NULL) {
- BTA_AvOpen(btif_av_cb.peer_bda, btif_av_cb.bta_handle, true,
- BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SINK);
- }
- }
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING);
- } break;
-
- case BTA_AV_RC_OPEN_EVT:
- /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it
- * connects. So
- * as per the AV WP, an AVRC connection cannot exist without an AV
- * connection. Therefore,
- * we initiate an AV connection if an RC_OPEN_EVT is received when we are
- * in AV_CLOSED state.
- * We initiate the AV connection after a small 3s timeout to avoid any
- * collisions from the
- * headsets, as some headsets initiate the AVRC connection first and then
- * immediately initiate the AV connection
- *
- * TODO: We may need to do this only on an AVRCP Play. FixMe
- */
-
- BTIF_TRACE_WARNING("%s: BTA_AV_RC_OPEN_EVT received w/o AV", __func__);
- alarm_set_on_mloop(av_open_on_rc_timer, BTIF_TIMEOUT_AV_OPEN_ON_RC_MS,
- btif_initiate_av_open_timer_timeout, NULL);
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTA_AV_RC_BROWSE_OPEN_EVT:
- BTIF_TRACE_DEBUG("%s: BTA_AV_RC_BROWSE_OPEN_EVT received", __func__);
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- /*
- * In case Signalling channel is not down
- * and remote started Streaming Procedure
- * we have to handle config and open event in
- * idle_state. We hit these scenarios while running
- * PTS test case for AVRCP Controller
- */
- case BTIF_AV_SINK_CONFIG_REQ_EVT: {
- btif_av_sink_config_req_t req;
- // copy to avoid alignment problems
- memcpy(&req, p_data, sizeof(req));
-
- BTIF_TRACE_WARNING(
- "%s: BTIF_AV_SINK_CONFIG_REQ_EVT sample_rate=%d "
- "channel_count=%d",
- __func__, req.sample_rate, req.channel_count);
- if (bt_av_sink_callbacks != NULL) {
- HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(req.peer_bd),
- req.sample_rate, req.channel_count);
- }
- } break;
-
- case BTA_AV_OPEN_EVT: {
- tBTA_AV* p_bta_data = (tBTA_AV*)p_data;
- btav_connection_state_t state;
- btif_sm_state_t av_state;
- BTIF_TRACE_WARNING("%s: BTA_AV_OPEN_EVT status=%d, edr=0x%x", __func__,
- p_bta_data->open.status, p_bta_data->open.edr);
-
- if (p_bta_data->open.status == BTA_AV_SUCCESS) {
- state = BTAV_CONNECTION_STATE_CONNECTED;
- av_state = BTIF_AV_STATE_OPENED;
- btif_av_cb.edr = p_bta_data->open.edr;
-
- btif_av_cb.peer_sep = p_bta_data->open.sep;
- } else {
- BTIF_TRACE_WARNING("%s: BTA_AV_OPEN_EVT::FAILED status=%d", __func__,
- p_bta_data->open.status);
- state = BTAV_CONNECTION_STATE_DISCONNECTED;
- av_state = BTIF_AV_STATE_IDLE;
- }
-
- /* inform the application of the event */
- btif_report_connection_state(state, &(btif_av_cb.peer_bda));
- /* change state to open/idle based on the status */
- btif_sm_change_state(btif_av_cb.sm_handle, av_state);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /* if queued PLAY command, send it now */
- btif_rc_check_handle_pending_play(
- p_bta_data->open.bd_addr,
- (p_bta_data->open.status == BTA_AV_SUCCESS));
- } else if ((btif_av_cb.peer_sep == AVDT_TSEP_SRC) &&
- (p_bta_data->open.status == BTA_AV_SUCCESS)) {
- /* Bring up AVRCP connection too */
- BTA_AvOpenRc(btif_av_cb.bta_handle);
- }
- btif_queue_advance();
- } break;
-
- case BTA_AV_REMOTE_CMD_EVT:
- case BTA_AV_VENDOR_CMD_EVT:
- case BTA_AV_META_MSG_EVT:
- case BTA_AV_RC_FEAT_EVT:
- case BTA_AV_REMOTE_RSP_EVT:
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTA_AV_RC_CLOSE_EVT:
- BTIF_TRACE_DEBUG("%s: BTA_AV_RC_CLOSE_EVT: Stopping AV timer.", __func__);
- alarm_cancel(av_open_on_rc_timer);
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTIF_TRACE_ERROR(
- "%s: BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started IDLE",
- __func__);
- btif_a2dp_on_offload_started(BTA_AV_FAIL);
- break;
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
-
- return true;
-}
-/*****************************************************************************
- *
- * Function btif_av_state_opening_handler
- *
- * Description Intermediate state managing events during establishment
- * of avdtp channel
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_opening_handler(btif_sm_event_t event, void* p_data) {
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- switch (event) {
- case BTIF_SM_ENTER_EVT:
- /* inform the application that we are entering connecting state */
- btif_report_connection_state(BTAV_CONNECTION_STATE_CONNECTING,
- &(btif_av_cb.peer_bda));
- break;
-
- case BTIF_SM_EXIT_EVT:
- break;
-
- case BTA_AV_REJECT_EVT:
- BTIF_TRACE_WARNING("%s: Received BTA_AV_REJECT_EVT", __func__);
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
- &(btif_av_cb.peer_bda));
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- if (btif_av_cb.self_initiated_connection) {
- btif_queue_advance();
- }
- break;
-
- case BTA_AV_OPEN_EVT: {
- tBTA_AV* p_bta_data = (tBTA_AV*)p_data;
- btav_connection_state_t state;
- btif_sm_state_t av_state;
- BTIF_TRACE_WARNING("%s: BTA_AV_OPEN_EVT status=%d, edr=0x%x", __func__,
- p_bta_data->open.status, p_bta_data->open.edr);
-
- if (p_bta_data->open.status == BTA_AV_SUCCESS) {
- state = BTAV_CONNECTION_STATE_CONNECTED;
- av_state = BTIF_AV_STATE_OPENED;
- btif_av_cb.edr = p_bta_data->open.edr;
-
- btif_av_cb.peer_sep = p_bta_data->open.sep;
- } else {
- BTIF_TRACE_WARNING("%s: BTA_AV_OPEN_EVT::FAILED status: %d", __func__,
- p_bta_data->open.status);
- RawAddress peer_addr;
- uint8_t peer_handle = BTRC_HANDLE_NONE;
- if (btif_rc_get_connected_peer(&peer_addr) &&
- btif_av_cb.peer_bda == peer_addr) {
- /*
- * Disconnect AVRCP connection, if
- * A2DP conneciton failed, for any reason
- */
- BTIF_TRACE_WARNING("%s: Disconnecting AVRCP: peer_addr=%s", __func__,
- peer_addr.ToString().c_str());
- peer_handle = btif_rc_get_connected_peer_handle(peer_addr);
- if (peer_handle != BTRC_HANDLE_NONE) {
- BTA_AvCloseRc(peer_handle);
- }
- }
- state = BTAV_CONNECTION_STATE_DISCONNECTED;
- av_state = BTIF_AV_STATE_IDLE;
- }
-
- /* inform the application of the event */
- btif_report_connection_state(state, &(btif_av_cb.peer_bda));
- /* change state to open/idle based on the status */
- btif_sm_change_state(btif_av_cb.sm_handle, av_state);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /* if queued PLAY command, send it now */
- btif_rc_check_handle_pending_play(
- p_bta_data->open.bd_addr,
- (p_bta_data->open.status == BTA_AV_SUCCESS));
- } else if ((btif_av_cb.peer_sep == AVDT_TSEP_SRC) &&
- (p_bta_data->open.status == BTA_AV_SUCCESS)) {
- /* Bring up AVRCP connection too */
- BTA_AvOpenRc(btif_av_cb.bta_handle);
- }
- if (btif_av_cb.self_initiated_connection) {
- btif_queue_advance();
- }
- } break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- case BTIF_AV_SINK_CONFIG_REQ_EVT: {
- btif_av_sink_config_req_t req;
- // copy to avoid alignment problems
- memcpy(&req, p_data, sizeof(req));
-
- BTIF_TRACE_WARNING(
- "%s: BTIF_AV_SINK_CONFIG_REQ_EVT sample_rate=%d "
- "channel_count=%d",
- __func__, req.sample_rate, req.channel_count);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC &&
- bt_av_sink_callbacks != NULL) {
- HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(btif_av_cb.peer_bda),
- req.sample_rate, req.channel_count);
- }
- } break;
-
- case BTIF_AV_CONNECT_REQ_EVT: {
- // Check for device, if same device which moved to opening then ignore
- // callback
- btif_av_connect_req_t* connect_req_p = (btif_av_connect_req_t*)p_data;
- RawAddress& target_bda = *connect_req_p->target_bda;
- if (btif_av_cb.peer_bda == target_bda) {
- BTIF_TRACE_WARNING(
- "%s: device %s is already connecting, ignore Connect request",
- __func__, btif_av_cb.peer_bda.ToString().c_str());
- } else {
- BTIF_TRACE_WARNING(
- "%s: device %s is already connecting, reject Connect request to %s",
- __func__, btif_av_cb.peer_bda.ToString().c_str(),
- target_bda.ToString().c_str());
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
- &target_bda);
- }
- // Ignore all connection request if we are already opening
- btif_queue_advance();
- } break;
-
- case BTA_AV_PENDING_EVT: {
- // Check for device, if same device which moved to opening then ignore
- // callback
- const RawAddress& bd_addr = ((tBTA_AV*)p_data)->pend.bd_addr;
- if (bd_addr == btif_av_cb.peer_bda) {
- BTIF_TRACE_WARNING(
- "%s: device %s is already connecting, ignore incoming request",
- __func__, btif_av_cb.peer_bda.ToString().c_str());
- } else {
- BTIF_TRACE_WARNING(
- "%s: device %s is already connecting, reject incoming request "
- "from %s",
- __func__, btif_av_cb.peer_bda.ToString().c_str(),
- bd_addr.ToString().c_str());
- BTA_AvDisconnect(bd_addr);
- }
- } break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTIF_TRACE_ERROR(
- "%s: BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started OPENING",
- __func__);
- btif_a2dp_on_offload_started(BTA_AV_FAIL);
- break;
-
- case BTA_AV_CLOSE_EVT:
- btif_a2dp_on_stopped(NULL);
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
- &(btif_av_cb.peer_bda));
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- if (btif_av_cb.self_initiated_connection) {
- btif_queue_advance();
- }
- break;
-
- case BTIF_AV_DISCONNECT_REQ_EVT:
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
- &(btif_av_cb.peer_bda));
- BTA_AvClose(btif_av_cb.bta_handle);
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- if (btif_av_cb.self_initiated_connection) {
- btif_queue_advance();
- }
- break;
-
- CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
- return true;
-}
-
-/*****************************************************************************
- *
- * Function btif_av_state_closing_handler
- *
- * Description Intermediate state managing events during closing
- * of avdtp channel
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_closing_handler(btif_sm_event_t event, void* p_data) {
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- switch (event) {
- case BTIF_SM_ENTER_EVT:
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /* immediately stop transmission of frames */
- btif_a2dp_source_set_tx_flush(true);
- /* wait for audioflinger to stop a2dp */
- }
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- btif_a2dp_sink_set_rx_flush(true);
- }
- break;
-
- case BTA_AV_STOP_EVT:
- case BTIF_AV_STOP_STREAM_REQ_EVT:
- btif_a2dp_on_stopped(NULL);
- break;
-
- case BTIF_SM_EXIT_EVT:
- break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- case BTA_AV_CLOSE_EVT:
-
- /* inform the application that we are disconnecting */
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
- &(btif_av_cb.peer_bda));
-
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- break;
-
- /* Handle the RC_CLOSE event for the cleanup */
- case BTA_AV_RC_CLOSE_EVT:
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- /* Handle the RC_BROWSE_CLOSE event for tetsing*/
- case BTA_AV_RC_BROWSE_CLOSE_EVT:
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTIF_TRACE_ERROR(
- "%s: BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Closing",
- __func__);
- btif_a2dp_on_offload_started(BTA_AV_FAIL);
- break;
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
- return true;
-}
-
-/*****************************************************************************
- *
- * Function btif_av_state_opened_handler
- *
- * Description Handles AV events while AVDTP is in OPEN state
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_opened_handler(btif_sm_event_t event, void* p_data) {
- tBTA_AV* p_av = (tBTA_AV*)p_data;
-
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- if ((event == BTA_AV_REMOTE_CMD_EVT) &&
- (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND) &&
- (p_av->remote_cmd.rc_id == BTA_AV_RC_PLAY)) {
- BTIF_TRACE_EVENT("%s: Resetting remote suspend flag on RC PLAY", __func__);
- btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+ data_ = osi_malloc(data_length_);
+ memcpy(data_, p_data, data_length);
}
switch (event) {
- case BTIF_SM_ENTER_EVT:
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_STOP;
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
- break;
-
- case BTIF_SM_EXIT_EVT:
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
- break;
-
- case BTIF_AV_START_STREAM_REQ_EVT:
- if (btif_av_cb.peer_sep != AVDT_TSEP_SRC) btif_a2dp_source_setup_codec();
- BTA_AvStart();
- btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
- break;
-
- case BTA_AV_START_EVT: {
- BTIF_TRACE_WARNING(
- "%s: BTA_AV_START_EVT status=%d suspending=%d initiator=%d "
- "flags=0x%x",
- __func__, p_av->start.status, p_av->start.suspending,
- p_av->start.initiator, btif_av_cb.flags);
-
- if ((p_av->start.status == BTA_SUCCESS) &&
- (p_av->start.suspending == true))
- return true;
-
- /* if remote tries to start a2dp when DUT is a2dp source
- * then suspend. In case a2dp is sink and call is active
- * then disconnect the AVDTP channel
- */
- if (!(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START)) {
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- BTIF_TRACE_WARNING("%s: trigger suspend as remote initiated!!",
- __func__);
- btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
- }
- }
-
- /* In case peer is A2DP SRC we do not want to ack commands on UIPC*/
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- if (btif_a2dp_on_started(
- &p_av->start,
- ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) != 0))) {
- /* only clear pending flag after acknowledgement */
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
- }
- }
-
- /* remain in open state if status failed */
- if (p_av->start.status != BTA_AV_SUCCESS) return false;
-
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- btif_a2dp_sink_set_rx_flush(
- false); /* remove flush state, ready for streaming*/
- }
-
- /* change state to started, send acknowledgement if start is pending */
- if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
- btif_a2dp_on_started(NULL, true);
- /* pending start flag will be cleared when exit current state */
- }
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_STARTED);
-
- } break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- case BTIF_AV_DISCONNECT_REQ_EVT:
- BTA_AvClose(btif_av_cb.bta_handle);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- BTA_AvCloseRc(btif_av_cb.bta_handle);
- }
-
- /* inform the application that we are disconnecting */
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING,
- &(btif_av_cb.peer_bda));
- break;
-
- case BTA_AV_CLOSE_EVT:
- /* avdtp link is closed */
- btif_a2dp_on_stopped(NULL);
-
- /* inform the application that we are disconnected */
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
- &(btif_av_cb.peer_bda));
-
- /* change state to idle, send acknowledgement if start is pending */
- if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
- btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
- /* pending start flag will be cleared when exit current state */
- }
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- break;
-
- case BTA_AV_RECONFIG_EVT:
- if ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) &&
- (p_av->reconfig.status == BTA_AV_SUCCESS)) {
- APPL_TRACE_WARNING("reconfig done BTA_AVstart()");
- BTA_AvStart();
- } else if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
- btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
- }
- break;
-
- case BTIF_AV_CONNECT_REQ_EVT: {
- btif_av_connect_req_t* connect_req_p = (btif_av_connect_req_t*)p_data;
- RawAddress& target_bda = *connect_req_p->target_bda;
- if (btif_av_cb.peer_bda == target_bda) {
- BTIF_TRACE_WARNING(
- "%s: Ignore BTIF_AV_CONNECT_REQ_EVT for same device: target_bda=%s",
- __func__, target_bda.ToString().c_str());
- } else {
- BTIF_TRACE_WARNING(
- "%s: Moved to opened by Other incoming Connect request: "
- "target_bda=%s",
- __func__, target_bda.ToString().c_str());
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
- &target_bda);
- }
- btif_queue_advance();
- } break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTIF_TRACE_ERROR(
- "%s: BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Opened",
- __func__);
- btif_a2dp_on_offload_started(BTA_AV_FAIL);
- break;
-
- CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
- return true;
-}
-
-/*****************************************************************************
- *
- * Function btif_av_state_started_handler
- *
- * Description Handles AV events while A2DP stream is started
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_started_handler(btif_sm_event_t event, void* p_data) {
- tBTA_AV* p_av = (tBTA_AV*)p_data;
-
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- switch (event) {
- case BTIF_SM_ENTER_EVT:
-
- /* we are again in started state, clear any remote suspend flags */
- btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
-
- /**
- * Report to components above that we have entered the streaming
- * stage, this should usually be followed by focus grant.
- * see update_audio_focus_state()
- */
- btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda));
- break;
-
- case BTIF_SM_EXIT_EVT:
- break;
-
- case BTIF_AV_START_STREAM_REQ_EVT:
- /* we were remotely started, just ack back the local request */
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
- btif_a2dp_on_started(NULL, true);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- /* fixme -- use suspend = true always to work around issue with BTA AV */
- case BTIF_AV_STOP_STREAM_REQ_EVT:
- case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
- BTIF_TRACE_WARNING("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
- /* set pending flag to ensure btif task is not trying to restart
- stream while suspend is in progress */
- btif_av_cb.flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
-
- /* if we were remotely suspended but suspend locally, local suspend
- always overrides */
- btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
-
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /*
- * Immediately stop transmission of frames while suspend is
- * pending.
- */
- btif_a2dp_source_set_tx_flush(true);
- }
-
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- btif_a2dp_on_stopped(NULL);
- }
-
- BTA_AvStop(true);
- break;
-
- case BTIF_AV_DISCONNECT_REQ_EVT:
- BTIF_TRACE_WARNING("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- /* request avdtp to close */
- BTA_AvClose(btif_av_cb.bta_handle);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- BTA_AvCloseRc(btif_av_cb.bta_handle);
- }
-
- /* inform the application that we are disconnecting */
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING,
- &(btif_av_cb.peer_bda));
-
- /* wait in closing state until fully closed */
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_CLOSING);
- break;
-
- case BTA_AV_SUSPEND_EVT:
- BTIF_TRACE_WARNING(
- "%s: BTA_AV_SUSPEND_EVT status=%d initiator=%d flags=0x%x", __func__,
- p_av->suspend.status, p_av->suspend.initiator, btif_av_cb.flags);
-
- /* a2dp suspended, stop media task until resumed */
- btif_a2dp_on_suspended(&p_av->suspend);
-
- /* if not successful, remain in current state */
- if (p_av->suspend.status != BTA_AV_SUCCESS) {
- btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
-
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /* suspend failed, reset back tx flush state */
- btif_a2dp_source_set_tx_flush(false);
- }
- return false;
- }
-
- if (p_av->suspend.initiator != true) {
- /* remote suspend, notify HAL and await audioflinger to
- suspend/stop stream */
-
- /* set remote suspend flag to block media task from restarting
- stream only if we did not already initiate a local suspend */
- if ((btif_av_cb.flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0)
- btif_av_cb.flags |= BTIF_AV_FLAG_REMOTE_SUSPEND;
-
- btif_report_audio_state(BTAV_AUDIO_STATE_REMOTE_SUSPEND,
- &(btif_av_cb.peer_bda));
- } else {
- btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED,
- &(btif_av_cb.peer_bda));
- }
-
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
-
- /* suspend completed and state changed, clear pending status */
- btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
- break;
-
- case BTA_AV_STOP_EVT:
- BTIF_TRACE_WARNING("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
- btif_a2dp_on_stopped(&p_av->suspend);
-
- btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda));
-
- /* if stop was successful, change state to open */
- if (p_av->suspend.status == BTA_AV_SUCCESS)
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
-
- break;
-
- case BTA_AV_CLOSE_EVT:
- BTIF_TRACE_WARNING("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
-
- /* avdtp link is closed */
- btif_a2dp_on_stopped(NULL);
-
- /* inform the application that we are disconnected */
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
- &(btif_av_cb.peer_bda));
-
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTA_AvOffloadStart(btif_av_cb.bta_handle);
- break;
-
- case BTA_AV_OFFLOAD_START_RSP_EVT:
- btif_a2dp_on_offload_started(p_av->status);
- break;
-
- CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
-
- return true;
-}
-
-/*****************************************************************************
- * Local event handlers
- *****************************************************************************/
-
-static void btif_av_handle_event(uint16_t event, char* p_param) {
- BTIF_TRACE_EVENT("%s: event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- switch (event) {
- case BTIF_AV_CLEANUP_REQ_EVT:
- btif_a2dp_source_shutdown();
- btif_a2dp_sink_shutdown();
- break;
-
- case BTA_AV_REGISTER_EVT:
- if (btif_av_cb.sm_handle == NULL) {
- btif_av_cb.bta_handle = ((tBTA_AV*)p_param)->registr.hndl;
- BTIF_TRACE_DEBUG("%s: BTA AV Handle updated", __func__);
- }
- /* FALLTHROUGH */
- default:
- btif_sm_dispatch(btif_av_cb.sm_handle, event, (void*)p_param);
- btif_av_event_free_data(event, p_param);
- }
-}
-
-void btif_av_event_deep_copy(uint16_t event, char* p_dest, char* p_src) {
- BTIF_TRACE_DEBUG("%s", __func__);
- tBTA_AV* av_src = (tBTA_AV*)p_src;
- tBTA_AV* av_dest = (tBTA_AV*)p_dest;
-
- // First copy the structure
- maybe_non_aligned_memcpy(av_dest, av_src, sizeof(*av_src));
- switch (event) {
- case BTA_AV_META_MSG_EVT:
+ case BTA_AV_META_MSG_EVT: {
+ CHECK(data_length >= sizeof(tBTA_AV));
+ const tBTA_AV* av_src = (const tBTA_AV*)p_data;
+ tBTA_AV* av_dest = (tBTA_AV*)data_;
if (av_src->meta_msg.p_data && av_src->meta_msg.len) {
av_dest->meta_msg.p_data = (uint8_t*)osi_calloc(av_src->meta_msg.len);
memcpy(av_dest->meta_msg.p_data, av_src->meta_msg.p_data,
@@ -1186,20 +755,19 @@
(uint8_t*)osi_calloc(p_msg_src->browse.browse_len);
memcpy(p_msg_dest->browse.p_browse_data,
p_msg_src->browse.p_browse_data, p_msg_src->browse.browse_len);
- android_errorWriteLog(0x534e4554, "109699112");
}
}
- break;
+ } break;
default:
break;
}
}
-static void btif_av_event_free_data(btif_sm_event_t event, void* p_data) {
- switch (event) {
+void BtifAvEvent::DeepFree() {
+ switch (event_) {
case BTA_AV_META_MSG_EVT: {
- tBTA_AV* av = (tBTA_AV*)p_data;
+ tBTA_AV* av = (tBTA_AV*)data_;
osi_free_and_reset((void**)&av->meta_msg.p_data);
if (av->meta_msg.p_msg) {
@@ -1216,46 +784,1753 @@
default:
break;
}
+
+ osi_free_and_reset((void**)&data_);
+ data_length_ = 0;
}
-static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
- btif_transfer_context(btif_av_handle_event, event, (char*)p_data,
- sizeof(tBTA_AV), btif_av_event_deep_copy);
+BtifAvPeer::BtifAvPeer(const RawAddress& peer_address, uint8_t peer_sep,
+ tBTA_AV_HNDL bta_handle, uint8_t peer_id)
+ : peer_address_(peer_address),
+ peer_sep_(peer_sep),
+ bta_handle_(bta_handle),
+ peer_id_(peer_id),
+ state_machine_(*this),
+ av_open_on_rc_timer_(nullptr),
+ edr_(0),
+ flags_(0),
+ self_initiated_connection_(false) {}
+
+BtifAvPeer::~BtifAvPeer() { alarm_free(av_open_on_rc_timer_); }
+
+std::string BtifAvPeer::FlagsToString() const {
+ std::string result;
+
+ if (flags_ & BtifAvPeer::kFlagLocalSuspendPending) {
+ if (!result.empty()) result += "|";
+ result += "LOCAL_SUSPEND_PENDING";
+ }
+ if (flags_ & BtifAvPeer::kFlagRemoteSuspend) {
+ if (!result.empty()) result += "|";
+ result += "REMOTE_SUSPEND";
+ }
+ if (flags_ & BtifAvPeer::kFlagPendingStart) {
+ if (!result.empty()) result += "|";
+ result += "PENDING_START";
+ }
+ if (flags_ & BtifAvPeer::kFlagPendingStop) {
+ if (!result.empty()) result += "|";
+ result += "PENDING_STOP";
+ }
+ if (result.empty()) result = "None";
+
+ return base::StringPrintf("0x%x(%s)", flags_, result.c_str());
}
-static void bte_av_sink_media_callback(tBTA_AV_EVT event,
+bt_status_t BtifAvPeer::Init() {
+ alarm_free(av_open_on_rc_timer_);
+ av_open_on_rc_timer_ = alarm_new("btif_av_peer.av_open_on_rc_timer");
+
+ state_machine_.Start();
+ return BT_STATUS_SUCCESS;
+}
+
+void BtifAvPeer::Cleanup() {
+ state_machine_.Quit();
+ alarm_free(av_open_on_rc_timer_);
+ av_open_on_rc_timer_ = nullptr;
+}
+
+bool BtifAvPeer::CanBeDeleted() const {
+ return (
+ (state_machine_.StateId() == BtifAvStateMachine::kStateIdle) &&
+ (state_machine_.PreviousStateId() != BtifAvStateMachine::kStateInvalid));
+}
+
+const RawAddress& BtifAvPeer::ActivePeerAddress() const {
+ if (IsSource()) {
+ return btif_av_sink.ActivePeer();
+ }
+ if (IsSink()) {
+ return btif_av_source.ActivePeer();
+ }
+ LOG(FATAL) << __PRETTY_FUNCTION__ << ": A2DP peer " << PeerAddress()
+ << " is neither Source nor Sink";
+ return RawAddress::kEmpty;
+}
+
+bool BtifAvPeer::IsConnected() const {
+ int state = state_machine_.StateId();
+ return ((state == BtifAvStateMachine::kStateOpened) ||
+ (state == BtifAvStateMachine::kStateStarted));
+}
+
+bool BtifAvPeer::IsStreaming() const {
+ int state = state_machine_.StateId();
+ return (state == BtifAvStateMachine::kStateStarted);
+}
+
+BtifAvSource::~BtifAvSource() { CleanupAllPeers(); }
+
+bt_status_t BtifAvSource::Init(
+ btav_source_callbacks_t* callbacks, int max_connected_audio_devices,
+ const std::vector<btav_a2dp_codec_config_t>& codec_priorities) {
+ LOG_INFO(LOG_TAG, "%s: max_connected_audio_devices=%d", __PRETTY_FUNCTION__,
+ max_connected_audio_devices);
+ if (enabled_) return BT_STATUS_SUCCESS;
+ CleanupAllPeers();
+ max_connected_peers_ = max_connected_audio_devices;
+
+ /* A2DP OFFLOAD */
+ char value_sup[PROPERTY_VALUE_MAX] = {'\0'};
+ char value_dis[PROPERTY_VALUE_MAX] = {'\0'};
+ osi_property_get("ro.bluetooth.a2dp_offload.supported", value_sup, "false");
+ osi_property_get("persist.bluetooth.a2dp_offload.disabled", value_dis,
+ "false");
+ a2dp_offload_enabled_ =
+ (strcmp(value_sup, "true") == 0) && (strcmp(value_dis, "false") == 0);
+ BTIF_TRACE_DEBUG("a2dp_offload.enable = %d", a2dp_offload_enabled_);
+
+ callbacks_ = callbacks;
+ bta_av_co_init(codec_priorities);
+
+ if (!btif_a2dp_source_init()) {
+ return BT_STATUS_FAIL;
+ }
+ btif_enable_service(BTA_A2DP_SOURCE_SERVICE_ID);
+ enabled_ = true;
+ return BT_STATUS_SUCCESS;
+}
+
+void BtifAvSource::Cleanup() {
+ LOG_INFO(LOG_TAG, "%s", __PRETTY_FUNCTION__);
+ if (!enabled_) return;
+
+ btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SOURCE);
+
+ do_in_bta_thread(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(&BtifAvSource::SetActivePeer),
+ base::Unretained(&btif_av_source), RawAddress::kEmpty));
+ do_in_bta_thread(FROM_HERE, base::Bind(&btif_a2dp_source_cleanup));
+
+ btif_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
+ CleanupAllPeers();
+
+ callbacks_ = nullptr;
+ enabled_ = false;
+}
+
+BtifAvPeer* BtifAvSource::FindPeer(const RawAddress& peer_address) {
+ auto it = peers_.find(peer_address);
+ if (it != peers_.end()) return it->second;
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSource::FindPeerByHandle(tBTA_AV_HNDL bta_handle) {
+ for (auto it : peers_) {
+ BtifAvPeer* peer = it.second;
+ if (peer->BtaHandle() == bta_handle) {
+ return peer;
+ }
+ }
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSource::FindPeerByPeerId(uint8_t peer_id) {
+ for (auto it : peers_) {
+ BtifAvPeer* peer = it.second;
+ if (peer->PeerId() == peer_id) {
+ return peer;
+ }
+ }
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSource::FindOrCreatePeer(const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle) {
+ BTIF_TRACE_DEBUG("%s: peer_address=%s bta_handle=0x%x", __PRETTY_FUNCTION__,
+ peer_address.ToString().c_str(), bta_handle);
+
+ BtifAvPeer* peer = FindPeer(peer_address);
+ if (peer != nullptr) return peer;
+
+ // Find next availabie Peer ID to use
+ uint8_t peer_id;
+ for (peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
+ if (FindPeerByPeerId(peer_id) == nullptr) break;
+ }
+ if (peer_id == kPeerIdMax) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot create peer for peer_address=%s : "
+ "cannot allocate unique Peer ID",
+ __PRETTY_FUNCTION__, peer_address.ToString().c_str());
+ return nullptr;
+ }
+ // Get the BTA Handle (if known)
+ if (bta_handle == kBtaHandleUnknown) {
+ auto it = peer_id2bta_handle_.find(peer_id);
+ if (it != peer_id2bta_handle_.end()) {
+ bta_handle = it->second;
+ }
+ }
+
+ LOG_INFO(LOG_TAG,
+ "%s: Create peer: peer_address=%s bta_handle=0x%x peer_id=%d",
+ __PRETTY_FUNCTION__, peer_address.ToString().c_str(), bta_handle,
+ peer_id);
+ peer = new BtifAvPeer(peer_address, AVDT_TSEP_SNK, bta_handle, peer_id);
+ peers_.insert(std::make_pair(peer_address, peer));
+ peer->Init();
+ return peer;
+}
+
+bool BtifAvSource::AllowedToConnect(const RawAddress& peer_address) const {
+ int connected = 0;
+
+ // Count peers that are in the process of connecting or already connected
+ for (auto it : peers_) {
+ const BtifAvPeer* peer = it.second;
+ switch (peer->StateMachine().StateId()) {
+ case BtifAvStateMachine::kStateOpening:
+ case BtifAvStateMachine::kStateOpened:
+ case BtifAvStateMachine::kStateStarted:
+ if (peer->PeerAddress() == peer_address) {
+ return true; // Already connected or accounted for
+ }
+ connected++;
+ break;
+ default:
+ break;
+ }
+ }
+ return (connected < max_connected_peers_);
+}
+
+bool BtifAvSource::DeletePeer(const RawAddress& peer_address) {
+ auto it = peers_.find(peer_address);
+ if (it == peers_.end()) return false;
+ BtifAvPeer* peer = it->second;
+ peer->Cleanup();
+ peers_.erase(it);
+ delete peer;
+ return true;
+}
+
+void BtifAvSource::DeleteIdlePeers() {
+ for (auto it = peers_.begin(); it != peers_.end();) {
+ BtifAvPeer* peer = it->second;
+ auto prev_it = it++;
+ if (!peer->CanBeDeleted()) continue;
+ LOG_INFO(LOG_TAG, "%s: Deleting idle peer: %s bta_handle=0x%x", __func__,
+ peer->PeerAddress().ToString().c_str(), peer->BtaHandle());
+ peer->Cleanup();
+ peers_.erase(prev_it);
+ delete peer;
+ }
+}
+
+void BtifAvSource::CleanupAllPeers() {
+ while (!peers_.empty()) {
+ auto it = peers_.begin();
+ BtifAvPeer* peer = it->second;
+ peer->Cleanup();
+ peers_.erase(it);
+ delete peer;
+ }
+}
+
+void BtifAvSource::RegisterAllBtaHandles() {
+ for (int peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
+ BTA_AvRegister(BTA_AV_CHNL_AUDIO, kBtifAvSourceServiceName.c_str(), peer_id,
+ nullptr, UUID_SERVCLASS_AUDIO_SOURCE);
+ }
+}
+
+void BtifAvSource::DeregisterAllBtaHandles() {
+ for (auto it : peer_id2bta_handle_) {
+ tBTA_AV_HNDL bta_handle = it.second;
+ BTA_AvDeregister(bta_handle);
+ }
+ peer_id2bta_handle_.clear();
+}
+
+void BtifAvSource::BtaHandleRegistered(uint8_t peer_id,
+ tBTA_AV_HNDL bta_handle) {
+ peer_id2bta_handle_.insert(std::make_pair(peer_id, bta_handle));
+
+ // Set the BTA Handle for the Peer (if exists)
+ BtifAvPeer* peer = FindPeerByPeerId(peer_id);
+ if (peer != nullptr) {
+ peer->SetBtaHandle(bta_handle);
+ }
+}
+
+BtifAvSink::~BtifAvSink() { CleanupAllPeers(); }
+
+bt_status_t BtifAvSink::Init(btav_sink_callbacks_t* callbacks) {
+ LOG_INFO(LOG_TAG, "%s", __PRETTY_FUNCTION__);
+ if (enabled_) return BT_STATUS_SUCCESS;
+
+ CleanupAllPeers();
+ max_connected_peers_ = kDefaultMaxConnectedAudioDevices;
+ callbacks_ = callbacks;
+
+ std::vector<btav_a2dp_codec_config_t> codec_priorities; // Default priorities
+ bta_av_co_init(codec_priorities);
+
+ if (!btif_a2dp_sink_init()) {
+ return BT_STATUS_FAIL;
+ }
+ btif_enable_service(BTA_A2DP_SINK_SERVICE_ID);
+ enabled_ = true;
+ return BT_STATUS_SUCCESS;
+}
+
+void BtifAvSink::Cleanup() {
+ LOG_INFO(LOG_TAG, "%s", __PRETTY_FUNCTION__);
+ if (!enabled_) return;
+
+ btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SINK);
+
+ do_in_bta_thread(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(&BtifAvSink::SetActivePeer),
+ base::Unretained(&btif_av_sink), RawAddress::kEmpty));
+ do_in_bta_thread(FROM_HERE, base::Bind(&btif_a2dp_sink_cleanup));
+
+ btif_disable_service(BTA_A2DP_SINK_SERVICE_ID);
+ CleanupAllPeers();
+
+ callbacks_ = nullptr;
+ enabled_ = false;
+}
+
+BtifAvPeer* BtifAvSink::FindPeer(const RawAddress& peer_address) {
+ auto it = peers_.find(peer_address);
+ if (it != peers_.end()) return it->second;
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSink::FindPeerByHandle(tBTA_AV_HNDL bta_handle) {
+ for (auto it : peers_) {
+ BtifAvPeer* peer = it.second;
+ if (peer->BtaHandle() == bta_handle) {
+ return peer;
+ }
+ }
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSink::FindPeerByPeerId(uint8_t peer_id) {
+ for (auto it : peers_) {
+ BtifAvPeer* peer = it.second;
+ if (peer->PeerId() == peer_id) {
+ return peer;
+ }
+ }
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSink::FindOrCreatePeer(const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle) {
+ BTIF_TRACE_DEBUG("%s: peer_address=%s bta_handle=0x%x", __PRETTY_FUNCTION__,
+ peer_address.ToString().c_str(), bta_handle);
+
+ BtifAvPeer* peer = FindPeer(peer_address);
+ if (peer != nullptr) return peer;
+
+ // Find next availabie Peer ID to use
+ uint8_t peer_id;
+ for (peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
+ if (FindPeerByPeerId(peer_id) == nullptr) break;
+ }
+ if (peer_id == kPeerIdMax) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot create peer for peer_address=%s : "
+ "cannot allocate unique Peer ID",
+ __PRETTY_FUNCTION__, peer_address.ToString().c_str());
+ return nullptr;
+ }
+
+ // Get the BTA Handle (if known)
+ if (bta_handle == kBtaHandleUnknown) {
+ auto it = peer_id2bta_handle_.find(peer_id);
+ if (it != peer_id2bta_handle_.end()) {
+ bta_handle = it->second;
+ }
+ }
+
+ LOG_INFO(LOG_TAG,
+ "%s: Create peer: peer_address=%s bta_handle=0x%x peer_id=%d",
+ __PRETTY_FUNCTION__, peer_address.ToString().c_str(), bta_handle,
+ peer_id);
+ peer = new BtifAvPeer(peer_address, AVDT_TSEP_SRC, bta_handle, peer_id);
+ peers_.insert(std::make_pair(peer_address, peer));
+ peer->Init();
+ return peer;
+}
+
+bool BtifAvSink::AllowedToConnect(const RawAddress& peer_address) const {
+ int connected = 0;
+
+ // Count peers that are in the process of connecting or already connected
+ for (auto it : peers_) {
+ const BtifAvPeer* peer = it.second;
+ switch (peer->StateMachine().StateId()) {
+ case BtifAvStateMachine::kStateOpening:
+ case BtifAvStateMachine::kStateOpened:
+ case BtifAvStateMachine::kStateStarted:
+ if (peer->PeerAddress() == peer_address) {
+ return true; // Already connected or accounted for
+ }
+ connected++;
+ break;
+ default:
+ break;
+ }
+ }
+ return (connected < max_connected_peers_);
+}
+
+bool BtifAvSink::DeletePeer(const RawAddress& peer_address) {
+ auto it = peers_.find(peer_address);
+ if (it == peers_.end()) return false;
+ BtifAvPeer* peer = it->second;
+ peer->Cleanup();
+ peers_.erase(it);
+ delete peer;
+ return true;
+}
+
+void BtifAvSink::DeleteIdlePeers() {
+ for (auto it = peers_.begin(); it != peers_.end();) {
+ BtifAvPeer* peer = it->second;
+ auto prev_it = it++;
+ if (!peer->CanBeDeleted()) continue;
+ LOG_INFO(LOG_TAG, "%s: Deleting idle peer: %s bta_handle=0x%x", __func__,
+ peer->PeerAddress().ToString().c_str(), peer->BtaHandle());
+ peer->Cleanup();
+ peers_.erase(prev_it);
+ delete peer;
+ }
+}
+
+void BtifAvSink::CleanupAllPeers() {
+ while (!peers_.empty()) {
+ auto it = peers_.begin();
+ BtifAvPeer* peer = it->second;
+ peer->Cleanup();
+ peers_.erase(it);
+ delete peer;
+ }
+}
+
+void BtifAvSink::RegisterAllBtaHandles() {
+ for (int peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
+ BTA_AvRegister(BTA_AV_CHNL_AUDIO, kBtifAvSinkServiceName.c_str(), peer_id,
+ bta_av_sink_media_callback, UUID_SERVCLASS_AUDIO_SINK);
+ }
+}
+
+void BtifAvSink::DeregisterAllBtaHandles() {
+ for (auto it : peer_id2bta_handle_) {
+ tBTA_AV_HNDL bta_handle = it.second;
+ BTA_AvDeregister(bta_handle);
+ }
+ peer_id2bta_handle_.clear();
+}
+
+void BtifAvSink::BtaHandleRegistered(uint8_t peer_id, tBTA_AV_HNDL bta_handle) {
+ peer_id2bta_handle_.insert(std::make_pair(peer_id, bta_handle));
+
+ // Set the BTA Handle for the Peer (if exists)
+ BtifAvPeer* peer = FindPeerByPeerId(peer_id);
+ if (peer != nullptr) {
+ peer->SetBtaHandle(bta_handle);
+ }
+}
+
+void BtifAvStateMachine::StateIdle::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ peer_.SetEdr(0);
+ peer_.ClearAllFlags();
+
+ // Stop A2DP if this is the active peer
+ if (peer_.IsActivePeer() || peer_.ActivePeerAddress().IsEmpty()) {
+ btif_a2dp_on_idle();
+ }
+
+ // Reset the active peer if this was the active peer and
+ // the Idle state was reentered
+ if (peer_.IsActivePeer() && peer_.CanBeDeleted()) {
+ if (peer_.IsSink()) {
+ btif_av_source.SetActivePeer(RawAddress::kEmpty);
+ } else if (peer_.IsSource()) {
+ btif_av_sink.SetActivePeer(RawAddress::kEmpty);
+ }
+ }
+
+ // Delete peers that are re-entering the Idle state
+ if (peer_.IsSink()) {
+ do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSource::DeleteIdlePeers,
+ base::Unretained(&btif_av_source)));
+ } else if (peer_.IsSource()) {
+ do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSink::DeleteIdlePeers,
+ base::Unretained(&btif_av_sink)));
+ }
+}
+
+void BtifAvStateMachine::StateIdle::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+}
+
+bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) {
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
+
+ switch (event) {
+ case BTA_AV_ENABLE_EVT:
+ break;
+
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ case BTIF_AV_ACL_DISCONNECTED:
+ // Ignore. Just re-enter Idle so the peer can be deleted
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ case BTIF_AV_DISCONNECT_REQ_EVT:
+ if (peer_.BtaHandle() != kBtaHandleUnknown) {
+ BTA_AvClose(peer_.BtaHandle());
+ if (peer_.IsSource()) {
+ BTA_AvCloseRc(peer_.BtaHandle());
+ }
+ }
+ // Re-enter Idle so the peer can be deleted
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ case BTIF_AV_CONNECT_REQ_EVT:
+ case BTA_AV_PENDING_EVT: {
+ bool can_connect = true;
+ peer_.SetSelfInitiatedConnection(event == BTIF_AV_CONNECT_REQ_EVT);
+ // Check whether connection is allowed
+ if (peer_.IsSink()) {
+ can_connect = btif_av_source.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) src_disconnect_sink(peer_.PeerAddress());
+ } else if (peer_.IsSource()) {
+ can_connect = btif_av_sink.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) sink_disconnect_src(peer_.PeerAddress());
+ }
+ if (!can_connect) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot connect to peer %s: too many connected "
+ "peers",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+ }
+ BTA_AvOpen(peer_.PeerAddress(), peer_.BtaHandle(), true,
+ BTA_SEC_AUTHENTICATE, peer_.LocalUuidServiceClass());
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpening);
+ } break;
+ case BTIF_AV_AVRCP_OPEN_EVT:
+ case BTA_AV_RC_OPEN_EVT: {
+ // IOP_FIX: Jabra 620 only does AVRCP Open without AV Open whenever it
+ // connects. So as per the AV WP, an AVRCP connection cannot exist
+ // without an AV connection. Therefore, we initiate an AV connection
+ // if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
+ // We initiate the AV connection after a small 3s timeout to avoid any
+ // collisions from the headsets, as some headsets initiate the AVRCP
+ // connection first and then immediately initiate the AV connection
+ //
+ // TODO: We may need to do this only on an AVRCP Play. FixMe
+ BTIF_TRACE_WARNING("%s: Peer %s : event=%s received without AV",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+
+ bool can_connect = true;
+ // Check whether connection is allowed
+ if (peer_.IsSink()) {
+ can_connect = btif_av_source.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) src_disconnect_sink(peer_.PeerAddress());
+ } else if (peer_.IsSource()) {
+ can_connect = btif_av_sink.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) sink_disconnect_src(peer_.PeerAddress());
+ }
+ if (!can_connect) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot connect to peer %s: too many connected "
+ "peers",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ break;
+ }
+ if (btif_av_source.Enabled()) {
+ alarm_set_on_mloop(
+ peer_.AvOpenOnRcTimer(), BtifAvPeer::kTimeoutAvOpenOnRcMs,
+ btif_av_source_initiate_av_open_timer_timeout, &peer_);
+ } else if (btif_av_sink.Enabled()) {
+ alarm_set_on_mloop(peer_.AvOpenOnRcTimer(),
+ BtifAvPeer::kTimeoutAvOpenOnRcMs,
+ btif_av_sink_initiate_av_open_timer_timeout, &peer_);
+ }
+ if (event == BTA_AV_RC_OPEN_EVT) {
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ }
+ } break;
+
+ case BTA_AV_RC_BROWSE_OPEN_EVT:
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ break;
+
+ // In case Signalling channel is not down and remote started Streaming
+ // Procedure, we have to handle Config and Open event in Idle state.
+ // We hit these scenarios while running PTS test case for AVRCP Controller.
+ case BTIF_AV_SINK_CONFIG_REQ_EVT: {
+ const btif_av_sink_config_req_t* p_config_req =
+ static_cast<const btif_av_sink_config_req_t*>(p_data);
+ btif_av_report_sink_audio_config_state(p_config_req->peer_address,
+ p_config_req->sample_rate,
+ p_config_req->channel_count);
+ } break;
+
+ case BTA_AV_OPEN_EVT: {
+ tBTA_AV* p_bta_data = (tBTA_AV*)p_data;
+ btav_connection_state_t state;
+ int av_state;
+ tBTA_AV_STATUS status = p_bta_data->open.status;
+ bool can_connect = true;
+
+ LOG_INFO(
+ LOG_TAG, "%s: Peer %s : event=%s flags=%s status=%d(%s) edr=0x%x",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), peer_.FlagsToString().c_str(),
+ status, (status == BTA_AV_SUCCESS) ? "SUCCESS" : "FAILED",
+ p_bta_data->open.edr);
+
+ if (p_bta_data->open.status == BTA_AV_SUCCESS) {
+ state = BTAV_CONNECTION_STATE_CONNECTED;
+ av_state = BtifAvStateMachine::kStateOpened;
+ peer_.SetEdr(p_bta_data->open.edr);
+ CHECK(peer_.PeerSep() == p_bta_data->open.sep);
+ // Check whether connection is allowed
+ if (peer_.IsSink()) {
+ can_connect = btif_av_source.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) src_disconnect_sink(peer_.PeerAddress());
+ } else if (peer_.IsSource()) {
+ can_connect = btif_av_sink.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) sink_disconnect_src(peer_.PeerAddress());
+ }
+ } else {
+ state = BTAV_CONNECTION_STATE_DISCONNECTED;
+ av_state = BtifAvStateMachine::kStateIdle;
+ }
+
+ if (!can_connect) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot connect to peer %s: too many connected "
+ "peers",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ } else {
+ // Report the connection state to the application
+ btif_report_connection_state(peer_.PeerAddress(), state);
+ // Change state to Open/Idle based on the status
+ peer_.StateMachine().TransitionTo(av_state);
+ if (peer_.IsSink()) {
+ // If queued PLAY command, send it now
+ btif_rc_check_handle_pending_play(
+ p_bta_data->open.bd_addr,
+ (p_bta_data->open.status == BTA_AV_SUCCESS));
+ } else if (peer_.IsSource() &&
+ (p_bta_data->open.status == BTA_AV_SUCCESS)) {
+ // Bring up AVRCP connection as well
+ BTA_AvOpenRc(peer_.BtaHandle());
+ }
+ }
+ btif_queue_advance();
+ } break;
+
+ case BTA_AV_REMOTE_CMD_EVT:
+ case BTA_AV_VENDOR_CMD_EVT:
+ case BTA_AV_META_MSG_EVT:
+ case BTA_AV_RC_FEAT_EVT:
+ case BTA_AV_REMOTE_RSP_EVT:
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ break;
+
+ case BTIF_AV_AVRCP_CLOSE_EVT:
+ case BTA_AV_RC_CLOSE_EVT: {
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s : Stopping AV timer",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ alarm_cancel(peer_.AvOpenOnRcTimer());
+
+ if (event == BTA_AV_RC_CLOSE_EVT) {
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ }
+ } break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTIF_TRACE_ERROR("%s: Peer %s : event=%s: stream is not Opened",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL);
+ break;
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+
+ return true;
+}
+
+void BtifAvStateMachine::StateOpening::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ // Inform the application that we are entering connecting state
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_CONNECTING);
+}
+
+void BtifAvStateMachine::StateOpening::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+}
+
+bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event,
+ void* p_data) {
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
+
+ switch (event) {
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ break; // Ignore
+
+ case BTIF_AV_ACL_DISCONNECTED:
+ // ACL Disconnected needs to be handled only in Opening state, because
+ // it is in an intermediate state. In other states we can handle
+ // incoming/outgoing connect/disconnect requests.
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s: transitioning to Idle due to ACL Disconnect",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+ case BTA_AV_REJECT_EVT:
+ BTIF_TRACE_WARNING("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+
+ case BTA_AV_OPEN_EVT: {
+ tBTA_AV* p_bta_data = (tBTA_AV*)p_data;
+ btav_connection_state_t state;
+ int av_state;
+ tBTA_AV_STATUS status = p_bta_data->open.status;
+
+ LOG_INFO(
+ LOG_TAG, "%s: Peer %s : event=%s flags=%s status=%d(%s) edr=0x%x",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), peer_.FlagsToString().c_str(),
+ status, (status == BTA_AV_SUCCESS) ? "SUCCESS" : "FAILED",
+ p_bta_data->open.edr);
+
+ if (p_bta_data->open.status == BTA_AV_SUCCESS) {
+ state = BTAV_CONNECTION_STATE_CONNECTED;
+ av_state = BtifAvStateMachine::kStateOpened;
+ peer_.SetEdr(p_bta_data->open.edr);
+ CHECK(peer_.PeerSep() == p_bta_data->open.sep);
+ } else {
+ if (btif_rc_is_connected_peer(peer_.PeerAddress())) {
+ // Disconnect the AVRCP connection, in case the A2DP connectiton
+ // failed for any reason.
+ BTIF_TRACE_WARNING("%s: Peer %s : Disconnecting AVRCP",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+ uint8_t peer_handle =
+ btif_rc_get_connected_peer_handle(peer_.PeerAddress());
+ if (peer_handle != BTRC_HANDLE_NONE) {
+ BTA_AvCloseRc(peer_handle);
+ }
+ }
+ state = BTAV_CONNECTION_STATE_DISCONNECTED;
+ av_state = BtifAvStateMachine::kStateIdle;
+ }
+
+ // Report the connection state to the application
+ btif_report_connection_state(peer_.PeerAddress(), state);
+ // Change state to Open/Idle based on the status
+ peer_.StateMachine().TransitionTo(av_state);
+ if (peer_.IsSink()) {
+ // If queued PLAY command, send it now
+ btif_rc_check_handle_pending_play(
+ p_bta_data->open.bd_addr,
+ (p_bta_data->open.status == BTA_AV_SUCCESS));
+ } else if (peer_.IsSource() &&
+ (p_bta_data->open.status == BTA_AV_SUCCESS)) {
+ // Bring up AVRCP connection as well
+ BTA_AvOpenRc(peer_.BtaHandle());
+ }
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ } break;
+
+ case BTIF_AV_SINK_CONFIG_REQ_EVT: {
+ const btif_av_sink_config_req_t* p_config_req =
+ static_cast<const btif_av_sink_config_req_t*>(p_data);
+ if (peer_.IsSource()) {
+ btif_av_report_sink_audio_config_state(p_config_req->peer_address,
+ p_config_req->sample_rate,
+ p_config_req->channel_count);
+ }
+ } break;
+
+ case BTIF_AV_CONNECT_REQ_EVT: {
+ // The device has moved already to Opening, hence don't report the
+ // connection state.
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s : device is already connecting, "
+ "ignore Connect request",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_queue_advance();
+ } break;
+
+ case BTA_AV_PENDING_EVT: {
+ // The device has moved already to Opening, hence don't report the
+ // connection state.
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s : device is already connecting, "
+ "ignore incoming request",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ } break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTIF_TRACE_ERROR("%s: Peer %s : event=%s: stream is not Opened",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL);
+ break;
+
+ case BTA_AV_CLOSE_EVT:
+ btif_a2dp_on_stopped(nullptr);
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+
+ case BTIF_AV_DISCONNECT_REQ_EVT:
+ BTA_AvClose(peer_.BtaHandle());
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+
+ CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+ return true;
+}
+
+void BtifAvStateMachine::StateOpened::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending |
+ BtifAvPeer::kFlagPendingStart |
+ BtifAvPeer::kFlagPendingStop);
+
+ // Set the active peer if the first connected device.
+ // NOTE: This should be done only if we are A2DP Sink, because the A2DP Sink
+ // implementation in Java doesn't support active devices (yet).
+ // For A2DP Source, the setting of the Active device is done by the
+ // ActiveDeviceManager in Java.
+ if (peer_.IsSource() && btif_av_sink.ActivePeer().IsEmpty()) {
+ if (!btif_av_sink.SetActivePeer(peer_.PeerAddress())) {
+ BTIF_TRACE_ERROR("%s: Error setting %s as active Source peer", __func__,
+ peer_.PeerAddress().ToString().c_str());
+ }
+ }
+}
+
+void BtifAvStateMachine::StateOpened::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ peer_.ClearFlags(BtifAvPeer::kFlagPendingStart);
+}
+
+bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event,
+ void* p_data) {
+ tBTA_AV* p_av = (tBTA_AV*)p_data;
+
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
+
+ if ((event == BTA_AV_REMOTE_CMD_EVT) &&
+ peer_.CheckFlags(BtifAvPeer::kFlagRemoteSuspend) &&
+ (p_av->remote_cmd.rc_id == AVRC_ID_PLAY)) {
+ BTIF_TRACE_EVENT("%s: Peer %s : Resetting remote suspend flag on RC PLAY",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+ peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+ }
+
+ switch (event) {
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ case BTIF_AV_ACL_DISCONNECTED:
+ break; // Ignore
+
+ case BTIF_AV_START_STREAM_REQ_EVT:
+ LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+ BTA_AvStart(peer_.BtaHandle());
+ peer_.SetFlags(BtifAvPeer::kFlagPendingStart);
+ break;
+
+ case BTA_AV_START_EVT: {
+ LOG_INFO(LOG_TAG,
+ "%s: Peer %s : event=%s status=%d suspending=%d "
+ "initiator=%d flags=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), p_av->start.status,
+ p_av->start.suspending, p_av->start.initiator,
+ peer_.FlagsToString().c_str());
+
+ if ((p_av->start.status == BTA_SUCCESS) && p_av->start.suspending)
+ return true;
+
+ // If remote tries to start A2DP when DUT is A2DP Source, then Suspend.
+ // If A2DP is Sink and call is active, then disconnect the AVDTP channel.
+ bool should_suspend = false;
+ if (peer_.IsSink() && !peer_.CheckFlags(BtifAvPeer::kFlagPendingStart |
+ BtifAvPeer::kFlagRemoteSuspend)) {
+ BTIF_TRACE_WARNING("%s: Peer %s : trigger Suspend as remote initiated",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+ should_suspend = true;
+ }
+
+ // If peer is A2DP Source, we do not want to ACK commands on UIPC
+ if (peer_.IsSink() &&
+ btif_a2dp_on_started(
+ peer_.PeerAddress(), &p_av->start,
+ peer_.CheckFlags(BtifAvPeer::kFlagPendingStart))) {
+ // Only clear pending flag after acknowledgement
+ peer_.ClearFlags(BtifAvPeer::kFlagPendingStart);
+ }
+
+ // Remain in Open state if status failed
+ if (p_av->start.status != BTA_AV_SUCCESS) return false;
+
+ if (peer_.IsSource() && peer_.IsActivePeer()) {
+ // Remove flush state, ready for streaming
+ btif_a2dp_sink_set_rx_flush(false);
+ }
+
+ // Change state to Started, send acknowledgement if start is pending
+ if (peer_.IsSink() && peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
+ btif_a2dp_on_started(peer_.PeerAddress(), nullptr, true);
+ // Pending start flag will be cleared when exit current state
+ }
+
+ if (should_suspend) {
+ btif_av_source_dispatch_sm_event(peer_.PeerAddress(),
+ BTIF_AV_SUSPEND_STREAM_REQ_EVT);
+ }
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateStarted);
+
+ } break;
+
+ case BTIF_AV_DISCONNECT_REQ_EVT:
+ BTA_AvClose(peer_.BtaHandle());
+ if (peer_.IsSource()) {
+ BTA_AvCloseRc(peer_.BtaHandle());
+ }
+
+ // Inform the application that we are disconnecting
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTING);
+
+ // Wait in closing state until fully closed
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateClosing);
+ break;
+
+ case BTA_AV_CLOSE_EVT:
+ // AVDTP link is closed
+ if (peer_.IsActivePeer()) {
+ btif_a2dp_on_stopped(nullptr);
+ }
+
+ // Change state to Idle, send acknowledgement if start is pending
+ if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
+ BTIF_TRACE_WARNING("%s: Peer %s : failed pending start request",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+ btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+ // Pending start flag will be cleared when exit current state
+ }
+
+ // Inform the application that we are disconnected
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ case BTA_AV_RECONFIG_EVT:
+ if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart) &&
+ (p_av->reconfig.status == BTA_AV_SUCCESS)) {
+ LOG_INFO(LOG_TAG,
+ "%s : Peer %s : Reconfig done - calling BTA_AvStart()",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ BTA_AvStart(peer_.BtaHandle());
+ } else if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
+ BTIF_TRACE_WARNING("%s: Peer %s : failed reconfiguration",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+ peer_.ClearFlags(BtifAvPeer::kFlagPendingStart);
+ btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+ }
+ break;
+
+ case BTIF_AV_CONNECT_REQ_EVT: {
+ BTIF_TRACE_WARNING("%s: Peer %s : Ignore %s for same device",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_queue_advance();
+ } break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTIF_TRACE_ERROR("%s: Peer %s : event=%s: stream is not Opened",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL);
+ break;
+
+ case BTIF_AV_AVRCP_REMOTE_PLAY_EVT:
+ if (peer_.CheckFlags(BtifAvPeer::kFlagRemoteSuspend)) {
+ BTIF_TRACE_EVENT(
+ "%s: Peer %s : Resetting remote suspend flag on RC PLAY",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+ }
+ break;
+
+ CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+ return true;
+}
+
+void BtifAvStateMachine::StateStarted::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ // We are again in started state, clear any remote suspend flags
+ peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+
+ // Report that we have entered the Streaming stage. Usually, this should
+ // be followed by focus grant. See update_audio_focus_state()
+ btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STARTED);
+}
+
+void BtifAvStateMachine::StateStarted::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+}
+
+bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event,
+ void* p_data) {
+ tBTA_AV* p_av = (tBTA_AV*)p_data;
+
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
+
+ switch (event) {
+ case BTIF_AV_ACL_DISCONNECTED:
+ break; // Ignore
+
+ case BTIF_AV_START_STREAM_REQ_EVT:
+ LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+ // We were started remotely, just ACK back the local request
+ if (peer_.IsSink())
+ btif_a2dp_on_started(peer_.PeerAddress(), nullptr, true);
+ break;
+
+ // FIXME -- use suspend = true always to work around issue with BTA AV
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+ // Set pending flag to ensure the BTIF task is not trying to restart
+ // the stream while suspend is in progress.
+ peer_.SetFlags(BtifAvPeer::kFlagLocalSuspendPending);
+
+ // If we were remotely suspended but suspend locally, local suspend
+ // always overrides.
+ peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+
+ if (peer_.IsSink()) {
+ // Immediately stop transmission of frames while suspend is pending
+ if (peer_.IsActivePeer()) {
+ if (event == BTIF_AV_STOP_STREAM_REQ_EVT) {
+ btif_a2dp_on_stopped(nullptr);
+ } else {
+ // (event == BTIF_AV_SUSPEND_STREAM_REQ_EVT)
+ btif_a2dp_source_set_tx_flush(true);
+ }
+ }
+ } else if (peer_.IsSource()) {
+ btif_a2dp_on_stopped(nullptr);
+ }
+ BTA_AvStop(peer_.BtaHandle(), true);
+ break;
+
+ case BTIF_AV_DISCONNECT_REQ_EVT:
+ LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ // Request AVDTP to close
+ BTA_AvClose(peer_.BtaHandle());
+ if (peer_.IsSource()) {
+ BTA_AvCloseRc(peer_.BtaHandle());
+ }
+
+ // Inform the application that we are disconnecting
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTING);
+
+ // Wait in closing state until fully closed
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateClosing);
+ break;
+
+ case BTA_AV_SUSPEND_EVT: {
+ LOG_INFO(LOG_TAG,
+ "%s: Peer %s : event=%s status=%d initiator=%d flags=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), p_av->suspend.status,
+ p_av->suspend.initiator, peer_.FlagsToString().c_str());
+
+ // A2DP suspended, stop A2DP encoder/decoder until resumed
+ btif_a2dp_on_suspended(&p_av->suspend);
+
+ // If not successful, remain in current state
+ if (p_av->suspend.status != BTA_AV_SUCCESS) {
+ peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending);
+
+ if (peer_.IsSink() && peer_.IsActivePeer()) {
+ // Suspend failed, reset back tx flush state
+ btif_a2dp_source_set_tx_flush(false);
+ }
+ return false;
+ }
+
+ btav_audio_state_t state = BTAV_AUDIO_STATE_REMOTE_SUSPEND;
+ if (p_av->suspend.initiator != true) {
+ // Remote suspend, notify HAL and await audioflinger to
+ // suspend/stop stream.
+ //
+ // Set remote suspend flag to block media task from restarting
+ // stream only if we did not already initiate a local suspend.
+ if (!peer_.CheckFlags(BtifAvPeer::kFlagLocalSuspendPending))
+ peer_.SetFlags(BtifAvPeer::kFlagRemoteSuspend);
+ } else {
+ state = BTAV_AUDIO_STATE_STOPPED;
+ }
+
+ // Suspend completed, clear pending status
+ peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending);
+
+ btif_report_audio_state(peer_.PeerAddress(), state);
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpened);
+ } break;
+
+ case BTA_AV_STOP_EVT:
+ LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ peer_.SetFlags(BtifAvPeer::kFlagPendingStop);
+ peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending);
+
+ btif_a2dp_on_stopped(&p_av->suspend);
+
+ btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STOPPED);
+
+ // If stop was successful, change state to Open
+ if (p_av->suspend.status == BTA_AV_SUCCESS)
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpened);
+
+ break;
+
+ case BTA_AV_CLOSE_EVT:
+ LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ peer_.SetFlags(BtifAvPeer::kFlagPendingStop);
+
+ // AVDTP link is closed
+ if (peer_.IsActivePeer()) {
+ btif_a2dp_on_stopped(nullptr);
+ }
+
+ // Inform the application that we are disconnected
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTA_AvOffloadStart(peer_.BtaHandle());
+ break;
+
+ case BTA_AV_OFFLOAD_START_RSP_EVT:
+ btif_a2dp_on_offload_started(peer_.PeerAddress(), p_av->status);
+ break;
+
+ CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+
+ return true;
+}
+
+void BtifAvStateMachine::StateClosing::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ if (peer_.IsActivePeer()) {
+ if (peer_.IsSink()) {
+ // Immediately stop transmission of frames
+ btif_a2dp_source_set_tx_flush(true);
+ // Wait for Audio Flinger to stop A2DP
+ } else if (peer_.IsSource()) {
+ btif_a2dp_sink_set_rx_flush(true);
+ }
+ }
+}
+
+void BtifAvStateMachine::StateClosing::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+}
+
+bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event,
+ void* p_data) {
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
+
+ switch (event) {
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ case BTIF_AV_ACL_DISCONNECTED:
+ break; // Ignore
+
+ case BTA_AV_STOP_EVT:
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ if (peer_.IsActivePeer()) {
+ btif_a2dp_on_stopped(nullptr);
+ }
+ break;
+
+ case BTA_AV_CLOSE_EVT:
+ // Inform the application that we are disconnecting
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ // Handle the RC_CLOSE event for the cleanup
+ case BTA_AV_RC_CLOSE_EVT:
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ break;
+
+ // Handle the RC_BROWSE_CLOSE event for testing
+ case BTA_AV_RC_BROWSE_CLOSE_EVT:
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTIF_TRACE_ERROR("%s: Peer %s : event=%s: stream is not Opened",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL);
+ break;
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Timer to trigger AV Open on the Source if the remote Sink device establishes
+ * AVRCP connection without AV connection. The timer is needed to interoperate
+ * with headsets that do establish AV after AVRCP connection.
+ */
+static void btif_av_source_initiate_av_open_timer_timeout(void* data) {
+ BtifAvPeer* peer = (BtifAvPeer*)data;
+
+ BTIF_TRACE_DEBUG("%s: Peer %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+
+ // Check if AVRCP is connected to the peer
+ if (!btif_rc_is_connected_peer(peer->PeerAddress())) {
+ BTIF_TRACE_ERROR("%s: AVRCP peer %s is not connected", __func__,
+ peer->PeerAddress().ToString().c_str());
+ return;
+ }
+
+ // Connect to the AVRCP peer
+ if (btif_av_source.Enabled() &&
+ btif_av_source.FindPeer(peer->PeerAddress()) == peer) {
+ BTIF_TRACE_DEBUG("%s: Connecting to AVRCP peer %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+ btif_av_source_dispatch_sm_event(peer->PeerAddress(),
+ BTIF_AV_CONNECT_REQ_EVT);
+ }
+}
+
+/**
+ * Timer to trigger AV Open on the Sink if the remote Source device establishes
+ * AVRCP connection without AV connection.
+ */
+static void btif_av_sink_initiate_av_open_timer_timeout(void* data) {
+ BtifAvPeer* peer = (BtifAvPeer*)data;
+
+ BTIF_TRACE_DEBUG("%s: Peer %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+
+ // Check if AVRCP is connected to the peer
+ if (!btif_rc_is_connected_peer(peer->PeerAddress())) {
+ BTIF_TRACE_ERROR("%s: AVRCP peer %s is not connected", __func__,
+ peer->PeerAddress().ToString().c_str());
+ return;
+ }
+
+ // Connect to the AVRCP peer
+ if (btif_av_sink.Enabled() &&
+ btif_av_sink.FindPeer(peer->PeerAddress()) == peer) {
+ BTIF_TRACE_DEBUG("%s: Connecting to AVRCP peer %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+ btif_av_sink_dispatch_sm_event(peer->PeerAddress(),
+ BTIF_AV_CONNECT_REQ_EVT);
+ }
+}
+
+/**
+ * Report the A2DP connection state
+ *
+ * @param peer_address the peer address
+ * @param state the connection state
+ */
+static void btif_report_connection_state(const RawAddress& peer_address,
+ btav_connection_state_t state) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%d", __func__,
+ peer_address.ToString().c_str(), state);
+
+ if (btif_av_source.Enabled()) {
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(btif_av_source.Callbacks()->connection_state_cb,
+ peer_address, state));
+ } else if (btif_av_sink.Enabled()) {
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(btif_av_sink.Callbacks()->connection_state_cb,
+ peer_address, state));
+ }
+}
+
+/**
+ * Report the audio state of the A2DP connection.
+ * The state is updated when either the remote ends starts streaming
+ * (Started state) or whenever it transitions out of Started state
+ * (to Opened or Streaming state).
+ *
+ * @param peer_address the peer address
+ * @param state the audio state
+ */
+static void btif_report_audio_state(const RawAddress& peer_address,
+ btav_audio_state_t state) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%d", __func__,
+ peer_address.ToString().c_str(), state);
+
+ if (btif_av_source.Enabled()) {
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(btif_av_source.Callbacks()->audio_state_cb,
+ peer_address, state));
+ } else if (btif_av_sink.Enabled()) {
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(btif_av_sink.Callbacks()->audio_state_cb,
+ peer_address, state));
+ }
+}
+
+void btif_av_report_source_codec_state(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_config,
+ const std::vector<btav_a2dp_codec_config_t>& codecs_local_capabilities,
+ const std::vector<btav_a2dp_codec_config_t>&
+ codecs_selectable_capabilities) {
+ BTIF_TRACE_EVENT("%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ if (btif_av_source.Enabled()) {
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(btif_av_source.Callbacks()->audio_config_cb, peer_address,
+ codec_config, codecs_local_capabilities,
+ codecs_selectable_capabilities));
+ }
+}
+
+/**
+ * Report the audio config state of the A2DP Sink connection.
+ *
+ * @param peer_address the peer address
+ * @param sample_rate the sample rate (in samples per second)
+ * @param channel_count the channel count (1 for Mono, 2 for Stereo)
+ */
+static void btif_av_report_sink_audio_config_state(
+ const RawAddress& peer_address, int sample_rate, int channel_count) {
+ LOG_INFO(LOG_TAG, "%s: Peer %s : sample_rate=%d channel_count=%d", __func__,
+ peer_address.ToString().c_str(), sample_rate, channel_count);
+ if (btif_av_sink.Enabled()) {
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(btif_av_sink.Callbacks()->audio_config_cb,
+ peer_address, sample_rate, channel_count));
+ }
+}
+
+/**
+ * Process BTIF or BTA AV or BTA AVRCP events. The processing is done on the
+ * JNI thread.
+ *
+ * @param peer_sep the corresponding peer's SEP: AVDT_TSEP_SRC if the peer
+ * is A2DP Source, or AVDT_TSEP_SNK if the peer is A2DP Sink.
+ * @param peer_address the peer address if known, otherwise RawAddress::kEmpty
+ * @param bta_handle the BTA handle for the peer if known, otherwise
+ * kBtaHandleUnknown
+ * @param btif_av_event the corresponding event
+ */
+static void btif_av_handle_event(uint8_t peer_sep,
+ const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle,
+ const BtifAvEvent& btif_av_event) {
+ BtifAvPeer* peer = nullptr;
+ BTIF_TRACE_EVENT("%s: peer_sep=%s (%d) peer_address=%s handle=0x%x event=%s",
+ __func__, (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink",
+ peer_sep, peer_address.ToString().c_str(), bta_handle,
+ btif_av_event.ToString().c_str());
+
+ // Find the peer
+ if (peer_address != RawAddress::kEmpty) {
+ if (peer_sep == AVDT_TSEP_SNK) {
+ peer = btif_av_source.FindOrCreatePeer(peer_address, bta_handle);
+ } else if (peer_sep == AVDT_TSEP_SRC) {
+ peer = btif_av_sink.FindOrCreatePeer(peer_address, bta_handle);
+ }
+ } else if (bta_handle != kBtaHandleUnknown) {
+ if (peer_sep == AVDT_TSEP_SNK) {
+ peer = btif_av_source.FindPeerByHandle(bta_handle);
+ } else if (peer_sep == AVDT_TSEP_SRC) {
+ peer = btif_av_sink.FindPeerByHandle(bta_handle);
+ }
+ }
+ if (peer == nullptr) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot find or create %s peer for peer_address=%s handle=0x%x : "
+ "event dropped: %s",
+ __func__, (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink",
+ peer_address.ToString().c_str(), bta_handle,
+ btif_av_event.ToString().c_str());
+ return;
+ }
+
+ peer->StateMachine().ProcessEvent(btif_av_event.Event(),
+ btif_av_event.Data());
+}
+
+/**
+ * Process BTA AV or BTA AVRCP events. The processing is done on the JNI
+ * thread.
+ *
+ * @param peer_sep the corresponding peer's SEP: AVDT_TSEP_SRC if the peer
+ * is A2DP Source, or AVDT_TSEP_SNK if the peer is A2DP Sink.
+ * @param btif_av_event the corresponding event
+ */
+static void btif_av_handle_bta_av_event(uint8_t peer_sep,
+ const BtifAvEvent& btif_av_event) {
+ RawAddress peer_address = RawAddress::kEmpty;
+ tBTA_AV_HNDL bta_handle = kBtaHandleUnknown;
+ tBTA_AV_EVT event = btif_av_event.Event();
+ tBTA_AV* p_data = (tBTA_AV*)btif_av_event.Data();
+
+ BTIF_TRACE_DEBUG("%s: peer_sep=%s (%d) event=%s", __func__,
+ (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink", peer_sep,
+ btif_av_event.ToString().c_str());
+
+ switch (event) {
+ case BTA_AV_ENABLE_EVT: {
+ const tBTA_AV_ENABLE& enable = p_data->enable;
+ BTIF_TRACE_DEBUG("%s: features=0x%x", __func__, enable.features);
+ return; // Nothing to do
+ }
+ case BTA_AV_REGISTER_EVT: {
+ const tBTA_AV_REGISTER& registr = p_data->registr;
+ bta_handle = registr.hndl;
+ uint8_t peer_id = registr.app_id; // The PeerId is used as AppId
+ BTIF_TRACE_DEBUG("%s: handle=0x%x app_id=%d", __func__, bta_handle,
+ registr.app_id);
+ if (peer_sep == AVDT_TSEP_SNK) {
+ btif_av_source.BtaHandleRegistered(peer_id, bta_handle);
+ } else if (peer_sep == AVDT_TSEP_SRC) {
+ btif_av_sink.BtaHandleRegistered(peer_id, bta_handle);
+ }
+ return; // Nothing else to do
+ }
+ case BTA_AV_OPEN_EVT: {
+ const tBTA_AV_OPEN& open = p_data->open;
+ peer_address = open.bd_addr;
+ bta_handle = open.hndl;
+ break;
+ }
+ case BTA_AV_CLOSE_EVT: {
+ const tBTA_AV_CLOSE& close = p_data->close;
+ bta_handle = close.hndl;
+ break;
+ }
+ case BTA_AV_START_EVT: {
+ const tBTA_AV_START& start = p_data->start;
+ bta_handle = start.hndl;
+ break;
+ }
+ case BTA_AV_SUSPEND_EVT:
+ case BTA_AV_STOP_EVT: {
+ const tBTA_AV_SUSPEND& suspend = p_data->suspend;
+ bta_handle = suspend.hndl;
+ break;
+ }
+ case BTA_AV_PROTECT_REQ_EVT: {
+ const tBTA_AV_PROTECT_REQ& protect_req = p_data->protect_req;
+ bta_handle = protect_req.hndl;
+ break;
+ }
+ case BTA_AV_PROTECT_RSP_EVT: {
+ const tBTA_AV_PROTECT_RSP& protect_rsp = p_data->protect_rsp;
+ bta_handle = protect_rsp.hndl;
+ break;
+ }
+ case BTA_AV_RC_OPEN_EVT: {
+ const tBTA_AV_RC_OPEN& rc_open = p_data->rc_open;
+ peer_address = rc_open.peer_addr;
+ break;
+ }
+ case BTA_AV_RC_CLOSE_EVT: {
+ const tBTA_AV_RC_CLOSE& rc_close = p_data->rc_close;
+ peer_address = rc_close.peer_addr;
+ break;
+ }
+ case BTA_AV_RC_BROWSE_OPEN_EVT: {
+ const tBTA_AV_RC_BROWSE_OPEN& rc_browse_open = p_data->rc_browse_open;
+ peer_address = rc_browse_open.peer_addr;
+ break;
+ }
+ case BTA_AV_RC_BROWSE_CLOSE_EVT: {
+ const tBTA_AV_RC_BROWSE_CLOSE& rc_browse_close = p_data->rc_browse_close;
+ peer_address = rc_browse_close.peer_addr;
+ break;
+ }
+ case BTA_AV_REMOTE_CMD_EVT:
+ case BTA_AV_REMOTE_RSP_EVT:
+ case BTA_AV_VENDOR_CMD_EVT:
+ case BTA_AV_VENDOR_RSP_EVT:
+ case BTA_AV_META_MSG_EVT:
+ case BTA_AV_OFFLOAD_START_RSP_EVT: {
+ // TODO: Might be wrong - this code will be removed once those
+ // events are received from the AVRCP module.
+ if (peer_sep == AVDT_TSEP_SNK) {
+ peer_address = btif_av_source.ActivePeer();
+ } else if (peer_sep == AVDT_TSEP_SRC) {
+ peer_address = btif_av_sink.ActivePeer();
+ }
+ break;
+ }
+ case BTA_AV_RECONFIG_EVT: {
+ const tBTA_AV_RECONFIG& reconfig = p_data->reconfig;
+ bta_handle = reconfig.hndl;
+ break;
+ }
+ case BTA_AV_PENDING_EVT: {
+ const tBTA_AV_PEND& pend = p_data->pend;
+ peer_address = pend.bd_addr;
+ break;
+ }
+ case BTA_AV_REJECT_EVT: {
+ const tBTA_AV_REJECT& reject = p_data->reject;
+ peer_address = reject.bd_addr;
+ bta_handle = reject.hndl;
+ break;
+ }
+ case BTA_AV_RC_FEAT_EVT: {
+ const tBTA_AV_RC_FEAT& rc_feat = p_data->rc_feat;
+ peer_address = rc_feat.peer_addr;
+ break;
+ }
+ }
+ BTIF_TRACE_DEBUG("%s: peer_address=%s handle=0x%x", __func__,
+ peer_address.ToString().c_str(), bta_handle);
+
+ btif_av_handle_event(peer_sep, peer_address, bta_handle, btif_av_event);
+}
+
+static void bta_av_source_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
+ BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV));
+ BTIF_TRACE_EVENT("%s: event=%s", __func__, btif_av_event.ToString().c_str());
+
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&btif_av_handle_bta_av_event,
+ AVDT_TSEP_SNK /* peer_sep */, btif_av_event));
+}
+
+static void bta_av_sink_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
+ BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV));
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&btif_av_handle_bta_av_event,
+ AVDT_TSEP_SRC /* peer_sep */, btif_av_event));
+}
+
+// TODO: All processing should be done on the JNI thread
+static void bta_av_sink_media_callback(tBTA_AV_EVT event,
tBTA_AV_MEDIA* p_data) {
+ BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
+
switch (event) {
case BTA_AV_SINK_MEDIA_DATA_EVT: {
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
- if ((state == BTIF_AV_STATE_STARTED) || (state == BTIF_AV_STATE_OPENED)) {
- uint8_t queue_len = btif_a2dp_sink_enqueue_buf((BT_HDR*)p_data);
- BTIF_TRACE_DEBUG("%s: packets in sink queue %d", __func__, queue_len);
+ BtifAvPeer* peer = btif_av_sink_find_peer(btif_av_sink.ActivePeer());
+ if (peer != nullptr) {
+ int state = peer->StateMachine().StateId();
+ if ((state == BtifAvStateMachine::kStateStarted) ||
+ (state == BtifAvStateMachine::kStateOpened)) {
+ uint8_t queue_len = btif_a2dp_sink_enqueue_buf((BT_HDR*)p_data);
+ BTIF_TRACE_DEBUG("%s: Packets in Sink queue %d", __func__, queue_len);
+ }
}
break;
}
case BTA_AV_SINK_MEDIA_CFG_EVT: {
btif_av_sink_config_req_t config_req;
- /* send a command to BT Media Task */
+ // Update the codec info of the A2DP Sink decoder
btif_a2dp_sink_update_decoder((uint8_t*)(p_data->avk_config.codec_info));
- /* Switch to BTIF context */
+
config_req.sample_rate =
A2DP_GetTrackSampleRate(p_data->avk_config.codec_info);
if (config_req.sample_rate == -1) {
- APPL_TRACE_ERROR("%s: cannot get the track frequency", __func__);
+ APPL_TRACE_ERROR("%s: Cannot get the track frequency", __func__);
break;
}
config_req.channel_count =
A2DP_GetTrackChannelCount(p_data->avk_config.codec_info);
if (config_req.channel_count == -1) {
- APPL_TRACE_ERROR("%s: cannot get the channel count", __func__);
+ APPL_TRACE_ERROR("%s: Cannot get the channel count", __func__);
break;
}
-
- config_req.peer_bd = p_data->avk_config.bd_addr;
- btif_transfer_context(btif_av_handle_event, BTIF_AV_SINK_CONFIG_REQ_EVT,
- (char*)&config_req, sizeof(config_req), NULL);
+ config_req.peer_address = p_data->avk_config.bd_addr;
+ BtifAvEvent btif_av_event(BTIF_AV_SINK_CONFIG_REQ_EVT, &config_req,
+ sizeof(config_req));
+ do_in_bta_thread(FROM_HERE, base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SRC, // peer_sep
+ config_req.peer_address,
+ kBtaHandleUnknown, btif_av_event));
break;
}
default:
@@ -1263,548 +2538,605 @@
}
}
-/*******************************************************************************
- *
- * Function btif_av_init
- *
- * Description Initializes btif AV if not already done
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-
-bt_status_t btif_av_init(int service_id) {
- if (btif_av_cb.sm_handle == NULL) {
- alarm_free(av_open_on_rc_timer);
- av_open_on_rc_timer = alarm_new("btif_av.av_open_on_rc_timer");
-
- switch (service_id) {
- case BTA_A2DP_SOURCE_SERVICE_ID:
- if (!btif_a2dp_source_startup())
- return BT_STATUS_FAIL; // Already running
- break;
- case BTA_A2DP_SINK_SERVICE_ID:
- if (!btif_a2dp_sink_startup())
- return BT_STATUS_FAIL; // Already running
- break;
- default:
- break;
- }
-
- btif_enable_service(service_id);
-
- /* Also initialize the AV state machine */
- btif_av_cb.sm_handle = btif_sm_init(
- (const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE);
- }
-
- return BT_STATUS_SUCCESS;
-}
-
-/*******************************************************************************
- *
- * Function init_src
- *
- * Description Initializes the AV interface for source mode
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-
+// Initializes the AV interface for source mode
static bt_status_t init_src(
- btav_source_callbacks_t* callbacks,
+ btav_source_callbacks_t* callbacks, int max_connected_audio_devices,
std::vector<btav_a2dp_codec_config_t> codec_priorities) {
BTIF_TRACE_EVENT("%s", __func__);
-
- btif_av_cb.codec_priorities = codec_priorities;
- bt_status_t status = btif_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
- if (status == BT_STATUS_SUCCESS) bt_av_src_callbacks = callbacks;
-
- return status;
+ return btif_av_source.Init(callbacks, max_connected_audio_devices,
+ codec_priorities);
}
-/*******************************************************************************
- *
- * Function init_sink
- *
- * Description Initializes the AV interface for sink mode
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-
+// Initializes the AV interface for sink mode
static bt_status_t init_sink(btav_sink_callbacks_t* callbacks) {
BTIF_TRACE_EVENT("%s", __func__);
-
- bt_status_t status = btif_av_init(BTA_A2DP_SINK_SERVICE_ID);
- if (status == BT_STATUS_SUCCESS) bt_av_sink_callbacks = callbacks;
-
- return status;
+ return btif_av_sink.Init(callbacks);
}
-/*******************************************************************************
- *
- * Function update_audio_focus_state
- *
- * Description Updates the final focus state reported by components calling
- * this module.
- *
- * Returns None
- *
- ******************************************************************************/
+// Updates the final focus state reported by components calling this module
static void update_audio_focus_state(int state) {
BTIF_TRACE_DEBUG("%s: state=%d", __func__, state);
btif_a2dp_sink_set_focus_state_req((btif_a2dp_sink_focus_state_t)state);
}
-/*******************************************************************************
- *
- * Function update_audio_track_gain
- *
- * Description Updates the track gain (used for ducking).
- *
- * Returns None
- *
- ******************************************************************************/
+// Updates the track gain (used for ducking).
static void update_audio_track_gain(float gain) {
BTIF_TRACE_DEBUG("%s: gain=%f", __func__, gain);
btif_a2dp_sink_set_audio_track_gain(gain);
}
-/*******************************************************************************
- *
- * Function connect
- *
- * Description Establishes the AV signalling channel with the remote
- * headset
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
+// Establishes the AV signalling channel with the remote headset
+static bt_status_t connect_int(RawAddress* peer_address, uint16_t uuid) {
+ BTIF_TRACE_EVENT("%s: peer_address=%s uuid=0x%x", __func__,
+ peer_address->ToString().c_str(), uuid);
-static bt_status_t connect_int(RawAddress* bd_addr, uint16_t uuid) {
- btif_av_connect_req_t connect_req;
- connect_req.target_bda = bd_addr;
- connect_req.uuid = uuid;
- BTIF_TRACE_EVENT("%s", __func__);
-
- btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT,
- (char*)&connect_req);
-
+ BtifAvPeer* peer = nullptr;
+ if (uuid == UUID_SERVCLASS_AUDIO_SOURCE) {
+ peer = btif_av_source.FindOrCreatePeer(*peer_address, kBtaHandleUnknown);
+ if (peer == nullptr) {
+ return BT_STATUS_FAIL;
+ }
+ } else if (uuid == UUID_SERVCLASS_AUDIO_SINK) {
+ peer = btif_av_sink.FindOrCreatePeer(*peer_address, kBtaHandleUnknown);
+ if (peer == nullptr) {
+ return BT_STATUS_FAIL;
+ }
+ }
+ peer->StateMachine().ProcessEvent(BTIF_AV_CONNECT_REQ_EVT, nullptr);
return BT_STATUS_SUCCESS;
}
-static bt_status_t src_connect_sink(RawAddress* bd_addr) {
- BTIF_TRACE_EVENT("%s", __func__);
- CHECK_BTAV_INIT();
-
- return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int);
+// Set the active peer
+static void set_active_peer_int(uint8_t peer_sep,
+ const RawAddress& peer_address) {
+ BTIF_TRACE_EVENT("%s: peer_sep=%s (%d) peer_address=%s", __func__,
+ (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink", peer_sep,
+ peer_address.ToString().c_str());
+ BtifAvPeer* peer = nullptr;
+ if (peer_sep == AVDT_TSEP_SNK) {
+ if (!btif_av_source.SetActivePeer(peer_address)) {
+ BTIF_TRACE_ERROR("%s: Error setting %s as active Sink peer", __func__,
+ peer_address.ToString().c_str());
+ }
+ return;
+ }
+ if (peer_sep == AVDT_TSEP_SRC) {
+ if (!btif_av_sink.SetActivePeer(peer_address)) {
+ BTIF_TRACE_ERROR("%s: Error setting %s as active Source peer", __func__,
+ peer_address.ToString().c_str());
+ }
+ return;
+ }
+ // If reached here, we could not set the active peer
+ BTIF_TRACE_ERROR("%s: Cannot set active %s peer to %s: peer not %s", __func__,
+ (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink",
+ peer_address.ToString().c_str(),
+ (peer == nullptr) ? "found" : "connected");
}
-static bt_status_t sink_connect_src(RawAddress* bd_addr) {
- BTIF_TRACE_EVENT("%s", __func__);
- CHECK_BTAV_INIT();
+static bt_status_t src_connect_sink(const RawAddress& peer_address) {
+ BTIF_TRACE_EVENT("%s: Peer %s", __func__, peer_address.ToString().c_str());
- return btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, bd_addr, connect_int);
+ if (!btif_av_source.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ RawAddress peer_address_copy(peer_address);
+ return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, &peer_address_copy,
+ connect_int);
}
-/*******************************************************************************
- *
- * Function disconnect
- *
- * Description Tears down the AV signalling channel with the remote headset
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t disconnect(RawAddress* bd_addr) {
- BTIF_TRACE_EVENT("%s", __func__);
- CHECK_BTAV_INIT();
+static bt_status_t sink_connect_src(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: Peer %s", __func__, peer_address.ToString().c_str());
- /* Switch to BTIF context */
- return btif_transfer_context(btif_av_handle_event, BTIF_AV_DISCONNECT_REQ_EVT,
- (char*)bd_addr, sizeof(RawAddress), NULL);
+ if (!btif_av_sink.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Sink is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ RawAddress peer_address_copy(peer_address);
+ return btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, &peer_address_copy,
+ connect_int);
+}
+
+static bt_status_t src_disconnect_sink(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: Peer %s", __func__, peer_address.ToString().c_str());
+
+ if (!btif_av_source.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ BtifAvEvent btif_av_event(BTIF_AV_DISCONNECT_REQ_EVT, &peer_address,
+ sizeof(peer_address));
+ return do_in_bta_thread(
+ FROM_HERE, base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SNK, // peer_sep
+ peer_address, kBtaHandleUnknown, btif_av_event));
+}
+
+static bt_status_t sink_disconnect_src(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: Peer %s", __func__, peer_address.ToString().c_str());
+
+ if (!btif_av_sink.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Sink is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ BtifAvEvent btif_av_event(BTIF_AV_DISCONNECT_REQ_EVT, &peer_address,
+ sizeof(peer_address));
+ return do_in_bta_thread(
+ FROM_HERE, base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SRC, // peer_sep
+ peer_address, kBtaHandleUnknown, btif_av_event));
+}
+
+static bt_status_t src_set_active_sink(const RawAddress& peer_address) {
+ BTIF_TRACE_EVENT("%s: Peer %s", __func__, peer_address.ToString().c_str());
+
+ if (!btif_av_source.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ return do_in_bta_thread(FROM_HERE, base::Bind(&set_active_peer_int,
+ AVDT_TSEP_SNK, // peer_sep
+ peer_address));
}
static bt_status_t codec_config_src(
+ const RawAddress& peer_address,
std::vector<btav_a2dp_codec_config_t> codec_preferences) {
BTIF_TRACE_EVENT("%s", __func__);
- CHECK_BTAV_INIT();
- for (auto cp : codec_preferences) {
- BTIF_TRACE_DEBUG(
- "%s: codec_type=%d codec_priority=%d "
- "sample_rate=0x%x bits_per_sample=0x%x "
- "channel_mode=0x%x codec_specific_1=%d "
- "codec_specific_2=%d codec_specific_3=%d "
- "codec_specific_4=%d",
- __func__, cp.codec_type, cp.codec_priority, cp.sample_rate,
- cp.bits_per_sample, cp.channel_mode, cp.codec_specific_1,
- cp.codec_specific_2, cp.codec_specific_3, cp.codec_specific_4);
- btif_transfer_context(btif_av_handle_event, BTIF_AV_SOURCE_CONFIG_REQ_EVT,
- reinterpret_cast<char*>(&cp), sizeof(cp), NULL);
+ if (!btif_av_source.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
}
- return BT_STATUS_SUCCESS;
-}
-
-/*******************************************************************************
- *
- * Function cleanup
- *
- * Description Shuts down the AV interface and does the cleanup
- *
- * Returns None
- *
- ******************************************************************************/
-static void cleanup(int service_uuid) {
- BTIF_TRACE_EVENT("%s", __func__);
-
- btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT, NULL, 0,
- NULL);
-
- btif_disable_service(service_uuid);
-
- alarm_free(av_open_on_rc_timer);
- av_open_on_rc_timer = NULL;
-
- /* Also shut down the AV state machine */
- btif_sm_shutdown(btif_av_cb.sm_handle);
- btif_av_cb.sm_handle = NULL;
+ return do_in_bta_thread(
+ FROM_HERE, base::Bind(&BtifAvSource::UpdateCodecConfig,
+ base::Unretained(&btif_av_source), peer_address,
+ codec_preferences));
}
static void cleanup_src(void) {
BTIF_TRACE_EVENT("%s", __func__);
-
- btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SOURCE);
- if (bt_av_src_callbacks) {
- bt_av_src_callbacks = NULL;
- if (bt_av_sink_callbacks == NULL) cleanup(BTA_A2DP_SOURCE_SERVICE_ID);
- }
+ do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSource::Cleanup,
+ base::Unretained(&btif_av_source)));
}
static void cleanup_sink(void) {
BTIF_TRACE_EVENT("%s", __func__);
-
- btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SINK);
- if (bt_av_sink_callbacks) {
- bt_av_sink_callbacks = NULL;
- if (bt_av_src_callbacks == NULL) cleanup(BTA_A2DP_SINK_SERVICE_ID);
- }
+ do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSink::Cleanup,
+ base::Unretained(&btif_av_sink)));
}
static const btav_source_interface_t bt_av_src_interface = {
sizeof(btav_source_interface_t),
init_src,
src_connect_sink,
- disconnect,
+ src_disconnect_sink,
+ src_set_active_sink,
codec_config_src,
cleanup_src,
};
static const btav_sink_interface_t bt_av_sink_interface = {
- sizeof(btav_sink_interface_t),
- init_sink,
- sink_connect_src,
- disconnect,
- cleanup_sink,
- update_audio_focus_state,
+ sizeof(btav_sink_interface_t), init_sink, sink_connect_src,
+ sink_disconnect_src, cleanup_sink, update_audio_focus_state,
update_audio_track_gain,
};
-/*******************************************************************************
- *
- * Function btif_av_get_addr
- *
- * Description Fetches current AV BD address
- *
- * Returns BD address
- *
- ******************************************************************************/
+RawAddress btif_av_source_active_peer(void) {
+ return btif_av_source.ActivePeer();
+}
+RawAddress btif_av_sink_active_peer(void) { return btif_av_sink.ActivePeer(); }
-RawAddress btif_av_get_addr(void) { return btif_av_cb.peer_bda; }
+bool btif_av_is_sink_enabled(void) { return btif_av_sink.Enabled(); }
-/*******************************************************************************
- * Function btif_av_is_sink_enabled
- *
- * Description Checks if A2DP Sink is enabled or not
- *
- * Returns true if A2DP Sink is enabled, false otherwise
- *
- ******************************************************************************/
-
-bool btif_av_is_sink_enabled(void) {
- return (bt_av_sink_callbacks != NULL) ? true : false;
+void btif_av_stream_start(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ btif_av_source_dispatch_sm_event(btif_av_source_active_peer(),
+ BTIF_AV_START_STREAM_REQ_EVT);
}
-/*******************************************************************************
- *
- * Function btif_av_stream_ready
- *
- * Description Checks whether AV is ready for starting a stream
- *
- * Returns None
- *
- ******************************************************************************/
+void btif_av_stream_stop(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s peer %s", __func__, peer_address.ToString().c_str());
+
+ if (!peer_address.IsEmpty()) {
+ btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_STOP_STREAM_REQ_EVT);
+ return;
+ }
+
+ // The active peer might have changed and we might be in the process
+ // of reconfiguring the stream. We need to stop the appopriate peer(s).
+ for (auto it : btif_av_source.Peers()) {
+ const BtifAvPeer* peer = it.second;
+ btif_av_source_dispatch_sm_event(peer->PeerAddress(),
+ BTIF_AV_STOP_STREAM_REQ_EVT);
+ }
+}
+
+void btif_av_stream_suspend(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ // The active peer might have changed and we might be in the process
+ // of reconfiguring the stream. We need to suspend the appropriate peer(s).
+ for (auto it : btif_av_source.Peers()) {
+ const BtifAvPeer* peer = it.second;
+ btif_av_source_dispatch_sm_event(peer->PeerAddress(),
+ BTIF_AV_SUSPEND_STREAM_REQ_EVT);
+ }
+}
+
+void btif_av_stream_start_offload(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ btif_av_source_dispatch_sm_event(btif_av_source_active_peer(),
+ BTIF_AV_OFFLOAD_START_REQ_EVT);
+}
+
+void btif_av_src_disconnect_sink(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer %s", __func__, peer_address.ToString().c_str());
+ src_disconnect_sink(peer_address);
+}
bool btif_av_stream_ready(void) {
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
-
- BTIF_TRACE_DEBUG("%s: sm_handle=%d, state=%d, flags=0x%x", __func__,
- btif_av_cb.sm_handle, state, btif_av_cb.flags);
-
- /* also make sure main adapter is enabled */
+ // Make sure the main adapter is enabled
if (btif_is_enabled() == 0) {
- BTIF_TRACE_EVENT("%s: main adapter not enabled", __func__);
+ BTIF_TRACE_EVENT("%s: Main adapter is not enabled", __func__);
return false;
}
- /* check if we are remotely suspended or stop is pending */
- if (btif_av_cb.flags &
- (BTIF_AV_FLAG_REMOTE_SUSPEND | BTIF_AV_FLAG_PENDING_STOP))
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
return false;
+ }
- return (state == BTIF_AV_STATE_OPENED);
+ int state = peer->StateMachine().StateId();
+ LOG_INFO(LOG_TAG, "%s: Peer %s : state=%d, flags=%s", __func__,
+ peer->PeerAddress().ToString().c_str(), state,
+ peer->FlagsToString().c_str());
+ // check if we are remotely suspended or stop is pending
+ if (peer->CheckFlags(BtifAvPeer::kFlagRemoteSuspend |
+ BtifAvPeer::kFlagPendingStop)) {
+ return false;
+ }
+
+ return (state == BtifAvStateMachine::kStateOpened);
}
-/*******************************************************************************
- *
- * Function btif_av_stream_started_ready
- *
- * Description Checks whether AV ready for media start in streaming state
- *
- * Returns None
- *
- ******************************************************************************/
-
bool btif_av_stream_started_ready(void) {
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
- bool ready = false;
-
- /* disallow media task to start if we have pending actions */
- if (btif_av_cb.flags &
- (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND |
- BTIF_AV_FLAG_PENDING_STOP)) {
- ready = false;
- } else {
- ready = (state == BTIF_AV_STATE_STARTED);
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+ return false;
}
- BTIF_TRACE_WARNING("%s: sm_handle=%d state=%d flags=0x%x ready=%d", __func__,
- btif_av_cb.sm_handle, state, btif_av_cb.flags, ready);
+ int state = peer->StateMachine().StateId();
+ bool ready = false;
+ if (peer->CheckFlags(BtifAvPeer::kFlagLocalSuspendPending |
+ BtifAvPeer::kFlagRemoteSuspend |
+ BtifAvPeer::kFlagPendingStop)) {
+ // Disallow media task to start if we have pending actions
+ ready = false;
+ } else {
+ ready = (state == BtifAvStateMachine::kStateStarted);
+ }
+ LOG_INFO(LOG_TAG, "%s: Peer %s : state=%d flags=%s ready=%d", __func__,
+ peer->PeerAddress().ToString().c_str(), state,
+ peer->FlagsToString().c_str(), ready);
return ready;
}
-/*******************************************************************************
- *
- * Function btif_dispatch_sm_event
- *
- * Description Send event to AV statemachine
- *
- * Returns None
- *
- ******************************************************************************/
+static void btif_av_source_dispatch_sm_event(const RawAddress& peer_address,
+ btif_av_sm_event_t event) {
+ BtifAvEvent btif_av_event(event, nullptr, 0);
+ BTIF_TRACE_EVENT("%s: peer_address=%s event=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_av_event.ToString().c_str());
-/* used to pass events to AV statemachine from other tasks */
-void btif_dispatch_sm_event(btif_av_sm_event_t event, void* p_data, int len) {
- /* Switch to BTIF context */
- btif_transfer_context(btif_av_handle_event, event, (char*)p_data, len, NULL);
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SNK, // peer_sep
+ peer_address, kBtaHandleUnknown, btif_av_event));
}
-/*******************************************************************************
- *
- * Function btif_av_execute_service
- *
- * Description Initializes/Shuts down the service
- *
- * Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
- *
- ******************************************************************************/
-bt_status_t btif_av_execute_service(bool b_enable) {
- if (b_enable) {
-/* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
- * handle this request in order to allow incoming connections to succeed.
- * We need to put this back once support for this is added */
+static void btif_av_sink_dispatch_sm_event(const RawAddress& peer_address,
+ btif_av_sm_event_t event) {
+ BtifAvEvent btif_av_event(event, nullptr, 0);
+ BTIF_TRACE_EVENT("%s: peer_address=%s event=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_av_event.ToString().c_str());
-/* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
- * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
- * be initiated by the app/audioflinger layers */
-/* Support for browsing for SDP record should work only if we enable BROWSE
- * while registering. */
-#if (AVRC_METADATA_INCLUDED == TRUE)
- BTA_AvEnable(BTA_SEC_AUTHENTICATE,
- BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
- BTA_AV_FEAT_NO_SCO_SSPD
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SRC, // peer_sep
+ peer_address, kBtaHandleUnknown, btif_av_event));
+}
+
+bt_status_t btif_av_source_execute_service(bool enable) {
+ BTIF_TRACE_EVENT("%s: Source service: %s", __func__,
+ (enable) ? "enable" : "disable");
+
+ if (enable) {
+ // TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
+ // handle this request in order to allow incoming connections to succeed.
+ // We need to put this back once support for this is added.
+
+ // Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
+ // auto-suspend av streaming on AG events(SCO or Call). The suspend shall
+ // be initiated by the app/audioflinger layers.
+ // Support for browsing for SDP record should work only if we enable BROWSE
+ // while registering.
+ tBTA_AV_FEAT features = BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA |
+ BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_NO_SCO_SSPD;
+
+ if (delay_reporting_enabled()) {
+ features |= BTA_AV_FEAT_DELAY_RPT;
+ }
+
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
- | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL |
- BTA_AV_FEAT_BROWSE
+ features |= BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_BROWSE;
#endif
- ,
- bte_av_callback);
-#else
- BTA_AvEnable(BTA_SEC_AUTHENTICATE,
- (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_NO_SCO_SSPD), bte_av_callback);
-#endif
- BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, NULL,
- UUID_SERVCLASS_AUDIO_SOURCE);
- } else {
- BTA_AvDeregister(btif_av_cb.bta_handle);
- BTA_AvDisable();
+ BTA_AvEnable(BTA_SEC_AUTHENTICATE, features, bta_av_source_callback);
+ btif_av_source.RegisterAllBtaHandles();
+ return BT_STATUS_SUCCESS;
}
+
+ // Disable the service
+ btif_av_source.DeregisterAllBtaHandles();
+ BTA_AvDisable();
return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function btif_av_sink_execute_service
- *
- * Description Initializes/Shuts down the service
- *
- * Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
- *
- ******************************************************************************/
-bt_status_t btif_av_sink_execute_service(bool b_enable) {
- if (b_enable) {
- /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
- * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
- * be initiated by the app/audioflinger layers */
- BTA_AvEnable(BTA_SEC_AUTHENTICATE,
- BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_RCCT |
- BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
- BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCTG |
- BTA_AV_FEAT_BROWSE,
- bte_av_callback);
- BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AVK_SERVICE_NAME, 0,
- bte_av_sink_media_callback, UUID_SERVCLASS_AUDIO_SINK);
- } else {
- BTA_AvDeregister(btif_av_cb.bta_handle);
- BTA_AvDisable();
+bt_status_t btif_av_sink_execute_service(bool enable) {
+ BTIF_TRACE_EVENT("%s: Sink service: %s", __func__,
+ (enable) ? "enable" : "disable");
+
+ if (enable) {
+ // Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
+ // auto-suspend AV streaming on AG events (SCO or Call). The suspend shall
+ // be initiated by the app/audioflinger layers.
+ tBTA_AV_FEAT features = BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_RCCT |
+ BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
+ BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCTG |
+ BTA_AV_FEAT_BROWSE;
+ BTA_AvEnable(BTA_SEC_AUTHENTICATE, features, bta_av_sink_callback);
+ btif_av_sink.RegisterAllBtaHandles();
+ return BT_STATUS_SUCCESS;
}
+
+ // Disable the service
+ btif_av_sink.DeregisterAllBtaHandles();
+ BTA_AvDisable();
return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function btif_av_get_src_interface
- *
- * Description Get the AV callback interface for A2DP source profile
- *
- * Returns btav_source_interface_t
- *
- ******************************************************************************/
+// Get the AV callback interface for A2DP source profile
const btav_source_interface_t* btif_av_get_src_interface(void) {
BTIF_TRACE_EVENT("%s", __func__);
return &bt_av_src_interface;
}
-/*******************************************************************************
- *
- * Function btif_av_get_sink_interface
- *
- * Description Get the AV callback interface for A2DP sink profile
- *
- * Returns btav_sink_interface_t
- *
- ******************************************************************************/
+// Get the AV callback interface for A2DP sink profile
const btav_sink_interface_t* btif_av_get_sink_interface(void) {
BTIF_TRACE_EVENT("%s", __func__);
return &bt_av_sink_interface;
}
-/*******************************************************************************
- *
- * Function btif_av_is_connected
- *
- * Description Checks if av has a connected sink
- *
- * Returns bool
- *
- ******************************************************************************/
bool btif_av_is_connected(void) {
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
- return ((state == BTIF_AV_STATE_OPENED) || (state == BTIF_AV_STATE_STARTED));
-}
-
-uint8_t btif_av_get_peer_sep(void) { return btif_av_cb.peer_sep; }
-
-/*******************************************************************************
- *
- * Function btif_av_is_peer_edr
- *
- * Description Check if the connected a2dp device supports
- * EDR or not. Only when connected this function
- * will accurately provide a true capability of
- * remote peer. If not connected it will always be false.
- *
- * Returns true if remote device is capable of EDR
- *
- ******************************************************************************/
-bool btif_av_is_peer_edr(void) {
- ASSERTC(btif_av_is_connected(), "No active a2dp connection", 0);
-
- if (btif_av_cb.edr)
- return true;
- else
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
return false;
-}
-
-/******************************************************************************
- *
- * Function btif_av_clear_remote_suspend_flag
- *
- * Description Clears btif_av_cd.flags if BTIF_AV_FLAG_REMOTE_SUSPEND is set
- *
- * Returns void
- *****************************************************************************/
-void btif_av_clear_remote_suspend_flag(void) {
- BTIF_TRACE_DEBUG("%s: flags=0x%x", __func__, btif_av_cb.flags);
- btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
-}
-
-/*******************************************************************************
- *
- * Function btif_av_peer_supports_3mbps
- *
- * Description Check if the connected A2DP device supports
- * 3 Mbps EDR. This function only works if connected.
- * If not connected it will always be false.
- *
- * Returns true if remote device is EDR and supports 3 Mbps
- *
- ******************************************************************************/
-bool btif_av_peer_supports_3mbps(void) {
- bool is3mbps = ((btif_av_cb.edr & BTA_AV_EDR_3MBPS) != 0);
- BTIF_TRACE_DEBUG("%s: connected %d, edr_3mbps %d", __func__,
- btif_av_is_connected(), is3mbps);
- return (btif_av_is_connected() && is3mbps);
-}
-
-/*******************************************************************************
- *
- * Function btif_av_move_idle
- *
- * Description Opening state is intermediate state. It cannot handle
- * incoming/outgoing connect/disconnect requests.When ACL
- * is disconnected and we are in opening state then move back
- * to idle state which is proper to handle connections.
- *
- * Returns Void
- *
- ******************************************************************************/
-void btif_av_move_idle(RawAddress bd_addr) {
- /* inform the application that ACL is disconnected and move to idle state */
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
- BTIF_TRACE_WARNING("%s: ACL Disconnected state %d bd_addr=%s peer_bda=%s",
- __func__, state, bd_addr.ToString().c_str(),
- btif_av_cb.peer_bda.ToString().c_str());
-
- if (state == BTIF_AV_STATE_OPENING && (bd_addr == btif_av_cb.peer_bda)) {
- BTIF_TRACE_DEBUG(
- "%s: Moving State from Opening to Idle due to ACL disconnect",
- __func__);
- btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
- &(btif_av_cb.peer_bda));
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
}
+
+ bool connected = peer->IsConnected();
+ BTIF_TRACE_DEBUG("%s: Peer %s is %s", __func__,
+ peer->PeerAddress().ToString().c_str(),
+ (connected) ? "connected" : "not connected");
+ return connected;
+}
+
+uint8_t btif_av_get_peer_sep(void) {
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+ return AVDT_TSEP_SNK;
+ }
+
+ uint8_t peer_sep = peer->PeerSep();
+ BTIF_TRACE_DEBUG("%s: Peer %s SEP is %s (%d)", __func__,
+ peer->PeerAddress().ToString().c_str(),
+ (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink", peer_sep);
+ return peer_sep;
+}
+
+void btif_av_clear_remote_suspend_flag(void) {
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+ return;
+ }
+
+ BTIF_TRACE_DEBUG("%s: Peer %s : flags=%s are cleared", __func__,
+ peer->PeerAddress().ToString().c_str(),
+ peer->FlagsToString().c_str());
+ peer->ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+}
+
+void btif_av_avrcp_event_open(const RawAddress& peer_address) {
+ // TODO: We need a better demultipexing mechanism whether the remote device
+ // is an A2DP Source or a Sink.
+ if (btif_av_source.Enabled()) {
+ BtifAvPeer* peer =
+ btif_av_source.FindOrCreatePeer(peer_address, kBtaHandleUnknown);
+ if (peer != nullptr) {
+ btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_OPEN_EVT);
+ return;
+ }
+ } else if (btif_av_sink.Enabled()) {
+ BtifAvPeer* peer =
+ btif_av_sink.FindOrCreatePeer(peer_address, kBtaHandleUnknown);
+ if (peer != nullptr) {
+ btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_OPEN_EVT);
+ return;
+ }
+ }
+ BTIF_TRACE_ERROR("%s: event ignored: cannot find or create peer state for %s",
+ __func__, peer_address.ToString().c_str());
+}
+
+void btif_av_avrcp_event_close(const RawAddress& peer_address) {
+ // TODO: We need a better demultipexing mechanism whether the remote device
+ // is an A2DP Source or a Sink.
+ if (btif_av_source.Enabled()) {
+ btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_CLOSE_EVT);
+ } else if (btif_av_sink.Enabled()) {
+ btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_CLOSE_EVT);
+ }
+}
+
+void btif_av_avrcp_event_remote_play(const RawAddress& peer_address) {
+ // TODO: We need a better demultipexing mechanism whether the remote device
+ // is an A2DP Source or a Sink.
+ if (btif_av_source.Enabled()) {
+ btif_av_source_dispatch_sm_event(peer_address,
+ BTIF_AV_AVRCP_REMOTE_PLAY_EVT);
+ } else if (btif_av_sink.Enabled()) {
+ btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_REMOTE_PLAY_EVT);
+ }
+}
+
+bool btif_av_is_peer_edr(const RawAddress& peer_address) {
+ BtifAvPeer* peer = btif_av_find_peer(peer_address);
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No peer found for peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ return false;
+ }
+ if (!peer->IsConnected()) {
+ BTIF_TRACE_WARNING("%s: Peer %s is not connected", __func__,
+ peer_address.ToString().c_str());
+ return false;
+ }
+
+ bool is_edr = peer->IsEdr();
+ BTIF_TRACE_DEBUG("%s: Peer %s : is_edr=%d", __func__,
+ peer_address.ToString().c_str(), is_edr);
+ return is_edr;
+}
+
+bool btif_av_peer_supports_3mbps(const RawAddress& peer_address) {
+ BtifAvPeer* peer = btif_av_find_peer(peer_address);
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No peer found for peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ return false;
+ }
+
+ bool is3mbps = peer->Is3Mbps();
+ bool is_connected = peer->IsConnected();
+ BTIF_TRACE_DEBUG("%s: Peer %s : connected=%d, edr_3mbps=%d", __func__,
+ peer_address.ToString().c_str(), is_connected, is3mbps);
+ return (is_connected && is3mbps);
+}
+
+void btif_av_acl_disconnected(const RawAddress& peer_address) {
+ // Inform the application that ACL is disconnected and move to idle state
+ LOG_INFO(LOG_TAG, "%s: Peer %s : ACL Disconnected", __func__,
+ peer_address.ToString().c_str());
+
+ if (btif_av_source.Enabled()) {
+ btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_ACL_DISCONNECTED);
+ } else if (btif_av_sink.Enabled()) {
+ btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_ACL_DISCONNECTED);
+ }
+}
+
+static void btif_debug_av_peer_dump(int fd, const BtifAvPeer& peer) {
+ std::string state_str;
+ int state = peer.StateMachine().StateId();
+ switch (state) {
+ case BtifAvStateMachine::kStateIdle:
+ state_str = "Idle";
+ break;
+ case BtifAvStateMachine::kStateOpening:
+ state_str = "Opening";
+ break;
+ case BtifAvStateMachine::kStateOpened:
+ state_str = "Opened";
+ break;
+ case BtifAvStateMachine::kStateStarted:
+ state_str = "Started";
+ break;
+ case BtifAvStateMachine::kStateClosing:
+ state_str = "Closing";
+ break;
+ default:
+ state_str = "Unknown(" + std::to_string(state) + ")";
+ break;
+ }
+
+ dprintf(fd, " Peer: %s\n", peer.PeerAddress().ToString().c_str());
+ dprintf(fd, " Connected: %s\n", peer.IsConnected() ? "true" : "false");
+ dprintf(fd, " Streaming: %s\n", peer.IsStreaming() ? "true" : "false");
+ dprintf(fd, " SEP: %d(%s)\n", peer.PeerSep(),
+ (peer.IsSource()) ? "Source" : "Sink");
+ dprintf(fd, " State Machine: %s\n", state_str.c_str());
+ dprintf(fd, " Flags: %s\n", peer.FlagsToString().c_str());
+ dprintf(fd, " OpenOnRcTimer: %s\n",
+ alarm_is_scheduled(peer.AvOpenOnRcTimer()) ? "Scheduled"
+ : "Not scheduled");
+ dprintf(fd, " BTA Handle: 0x%x\n", peer.BtaHandle());
+ dprintf(fd, " Peer ID: %d\n", peer.PeerId());
+ dprintf(fd, " EDR: %s\n", peer.IsEdr() ? "true" : "false");
+ dprintf(fd, " Support 3Mbps: %s\n", peer.Is3Mbps() ? "true" : "false");
+ dprintf(fd, " Self Initiated Connection: %s\n",
+ peer.SelfInitiatedConnection() ? "true" : "false");
+}
+
+static void btif_debug_av_source_dump(int fd) {
+ bool enabled = btif_av_source.Enabled();
+
+ dprintf(fd, "\nA2DP Source State: %s\n", (enabled) ? "Enabled" : "Disabled");
+ if (!enabled) return;
+ dprintf(fd, " Active peer: %s\n",
+ btif_av_source.ActivePeer().ToString().c_str());
+ for (auto it : btif_av_source.Peers()) {
+ const BtifAvPeer* peer = it.second;
+ btif_debug_av_peer_dump(fd, *peer);
+ }
+}
+
+static void btif_debug_av_sink_dump(int fd) {
+ bool enabled = btif_av_sink.Enabled();
+
+ dprintf(fd, "\nA2DP Sink State: %s\n", (enabled) ? "Enabled" : "Disabled");
+ if (!enabled) return;
+ dprintf(fd, " Active peer: %s\n",
+ btif_av_sink.ActivePeer().ToString().c_str());
+ dprintf(fd, " Peers:\n");
+ for (auto it : btif_av_sink.Peers()) {
+ const BtifAvPeer* peer = it.second;
+ btif_debug_av_peer_dump(fd, *peer);
+ }
+}
+
+void btif_debug_av_dump(int fd) {
+ btif_debug_av_source_dump(fd);
+ btif_debug_av_sink_dump(fd);
+}
+
+void btif_av_set_audio_delay(uint16_t delay) {
+ btif_a2dp_control_set_audio_delay(delay);
+}
+
+void btif_av_reset_audio_delay(void) { btif_a2dp_control_reset_audio_delay(); }
+
+bool btif_av_is_a2dp_offload_enabled() {
+ return btif_av_source.A2dpOffloadEnabled();
}
diff --git a/btif/src/btif_avrcp_audio_track.cc b/btif/src/btif_avrcp_audio_track.cc
index 8e192f7..76da406 100644
--- a/btif/src/btif_avrcp_audio_track.cc
+++ b/btif/src/btif_avrcp_audio_track.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/src/btif_ble_advertiser.cc b/btif/src/btif_ble_advertiser.cc
index 3c02882..e24bcde 100644
--- a/btif/src/btif_ble_advertiser.cc
+++ b/btif/src/btif_ble_advertiser.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google Inc.
+ * Copyright 2016 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -95,7 +95,7 @@
void RegisterAdvertiser(IdStatusCallback cb) override {
do_in_bta_thread(
FROM_HERE, Bind(&BleAdvertisingManager::RegisterAdvertiser,
- base::Unretained(BleAdvertisingManager::Get()),
+ BleAdvertisingManager::Get(),
Bind(&BleAdvertiserInterfaceImpl::RegisterAdvertiserCb,
base::Unretained(this), cb)));
}
@@ -115,33 +115,35 @@
}
void GetOwnAddress(uint8_t advertiser_id, GetAddressCallback cb) override {
+ if (!BleAdvertisingManager::IsInitialized()) return;
do_in_bta_thread(FROM_HERE,
Bind(&BleAdvertisingManager::GetOwnAddress,
- base::Unretained(BleAdvertisingManager::Get()),
- advertiser_id, jni_thread_wrapper(FROM_HERE, cb)));
+ BleAdvertisingManager::Get(), advertiser_id,
+ jni_thread_wrapper(FROM_HERE, cb)));
}
void SetParameters(uint8_t advertiser_id, AdvertiseParameters params,
ParametersCallback cb) override {
VLOG(1) << __func__;
+ if (!BleAdvertisingManager::IsInitialized()) return;
tBTM_BLE_ADV_PARAMS* p_params = new tBTM_BLE_ADV_PARAMS;
parseParams(p_params, params);
- do_in_bta_thread(
- FROM_HERE,
- Bind(&BleAdvertisingManager::SetParameters,
- base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
- base::Owned(p_params), jni_thread_wrapper(FROM_HERE, cb)));
+ do_in_bta_thread(FROM_HERE, Bind(&BleAdvertisingManager::SetParameters,
+ BleAdvertisingManager::Get(),
+ advertiser_id, base::Owned(p_params),
+ jni_thread_wrapper(FROM_HERE, cb)));
}
void SetData(int advertiser_id, bool set_scan_rsp, vector<uint8_t> data,
StatusCallback cb) override {
+ if (!BleAdvertisingManager::IsInitialized()) return;
do_in_bta_thread(
FROM_HERE,
- Bind(&BleAdvertisingManager::SetData,
- base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
- set_scan_rsp, std::move(data), jni_thread_wrapper(FROM_HERE, cb)));
+ Bind(&BleAdvertisingManager::SetData, BleAdvertisingManager::Get(),
+ advertiser_id, set_scan_rsp, std::move(data),
+ jni_thread_wrapper(FROM_HERE, cb)));
}
void Enable(uint8_t advertiser_id, bool enable, StatusCallback cb,
@@ -150,11 +152,11 @@
VLOG(1) << __func__ << " advertiser_id: " << +advertiser_id
<< " ,enable: " << enable;
+ if (!BleAdvertisingManager::IsInitialized()) return;
do_in_bta_thread(
FROM_HERE,
- Bind(&BleAdvertisingManager::Enable,
- base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
- enable, jni_thread_wrapper(FROM_HERE, cb), duration,
+ Bind(&BleAdvertisingManager::Enable, BleAdvertisingManager::Get(),
+ advertiser_id, enable, jni_thread_wrapper(FROM_HERE, cb), duration,
maxExtAdvEvents, jni_thread_wrapper(FROM_HERE, timeout_cb)));
}
@@ -165,13 +167,14 @@
MultiAdvCb timeout_cb) override {
VLOG(1) << __func__;
+ if (!BleAdvertisingManager::IsInitialized()) return;
tBTM_BLE_ADV_PARAMS* p_params = new tBTM_BLE_ADV_PARAMS;
parseParams(p_params, params);
do_in_bta_thread(
FROM_HERE,
Bind(&BleAdvertisingManager::StartAdvertising,
- base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
+ BleAdvertisingManager::Get(), advertiser_id,
jni_thread_wrapper(FROM_HERE, cb), base::Owned(p_params),
std::move(advertise_data), std::move(scan_response_data),
timeout_s * 100, jni_thread_wrapper(FROM_HERE, timeout_cb)));
@@ -187,6 +190,7 @@
IdStatusCallback timeout_cb) override {
VLOG(1) << __func__;
+ if (!BleAdvertisingManager::IsInitialized()) return;
tBTM_BLE_ADV_PARAMS* p_params = new tBTM_BLE_ADV_PARAMS;
parseParams(p_params, params);
@@ -196,11 +200,11 @@
do_in_bta_thread(
FROM_HERE,
Bind(&BleAdvertisingManager::StartAdvertisingSet,
- base::Unretained(BleAdvertisingManager::Get()),
- jni_thread_wrapper(FROM_HERE, cb), base::Owned(p_params),
- std::move(advertise_data), std::move(scan_response_data),
- base::Owned(p_periodic_params), std::move(periodic_data), duration,
- maxExtAdvEvents, jni_thread_wrapper(FROM_HERE, timeout_cb)));
+ BleAdvertisingManager::Get(), jni_thread_wrapper(FROM_HERE, cb),
+ base::Owned(p_params), std::move(advertise_data),
+ std::move(scan_response_data), base::Owned(p_periodic_params),
+ std::move(periodic_data), duration, maxExtAdvEvents,
+ jni_thread_wrapper(FROM_HERE, timeout_cb)));
}
void SetPeriodicAdvertisingParameters(
@@ -208,13 +212,14 @@
StatusCallback cb) override {
VLOG(1) << __func__ << " advertiser_id: " << +advertiser_id;
+ if (!BleAdvertisingManager::IsInitialized()) return;
tBLE_PERIODIC_ADV_PARAMS* p_periodic_params = new tBLE_PERIODIC_ADV_PARAMS;
parsePeriodicParams(p_periodic_params, periodic_params);
do_in_bta_thread(
FROM_HERE,
Bind(&BleAdvertisingManager::SetPeriodicAdvertisingParameters,
- base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
+ BleAdvertisingManager::Get(), advertiser_id,
base::Owned(p_periodic_params),
jni_thread_wrapper(FROM_HERE, cb)));
}
@@ -223,11 +228,11 @@
StatusCallback cb) override {
VLOG(1) << __func__ << " advertiser_id: " << +advertiser_id;
- do_in_bta_thread(
- FROM_HERE,
- Bind(&BleAdvertisingManager::SetPeriodicAdvertisingData,
- base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
- std::move(data), jni_thread_wrapper(FROM_HERE, cb)));
+ if (!BleAdvertisingManager::IsInitialized()) return;
+ do_in_bta_thread(FROM_HERE,
+ Bind(&BleAdvertisingManager::SetPeriodicAdvertisingData,
+ BleAdvertisingManager::Get(), advertiser_id,
+ std::move(data), jni_thread_wrapper(FROM_HERE, cb)));
}
void SetPeriodicAdvertisingEnable(int advertiser_id, bool enable,
@@ -235,11 +240,11 @@
VLOG(1) << __func__ << " advertiser_id: " << +advertiser_id
<< " ,enable: " << enable;
- do_in_bta_thread(
- FROM_HERE,
- Bind(&BleAdvertisingManager::SetPeriodicAdvertisingEnable,
- base::Unretained(BleAdvertisingManager::Get()), advertiser_id,
- enable, jni_thread_wrapper(FROM_HERE, cb)));
+ if (!BleAdvertisingManager::IsInitialized()) return;
+ do_in_bta_thread(FROM_HERE,
+ Bind(&BleAdvertisingManager::SetPeriodicAdvertisingEnable,
+ BleAdvertisingManager::Get(), advertiser_id, enable,
+ jni_thread_wrapper(FROM_HERE, cb)));
}
};
diff --git a/btif/src/btif_ble_scanner.cc b/btif/src/btif_ble_scanner.cc
index 02538c6..2587c8d 100644
--- a/btif/src/btif_ble_scanner.cc
+++ b/btif/src/btif_ble_scanner.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -90,33 +90,6 @@
remote_bdaddr_cache_ordered = {};
}
-void btif_gatts_upstreams_evt(uint16_t event, char* p_param) {
- LOG_VERBOSE(LOG_TAG, "%s: Event %d", __func__, event);
-
- tBTA_GATTC* p_data = (tBTA_GATTC*)p_param;
- switch (event) {
- case BTA_GATTC_DEREG_EVT:
- break;
-
- case BTA_GATTC_SEARCH_CMPL_EVT: {
- HAL_CBACK(bt_gatt_callbacks, client->search_complete_cb,
- p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
- break;
- }
-
- default:
- LOG_DEBUG(LOG_TAG, "%s: Unhandled event (%d)", __func__, event);
- break;
- }
-}
-
-void bta_gatts_cback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
- bt_status_t status =
- btif_transfer_context(btif_gatts_upstreams_evt, (uint16_t)event,
- (char*)p_data, sizeof(tBTA_GATTC), NULL);
- ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
-}
-
void bta_batch_scan_threshold_cb(tBTM_BLE_REF_VALUE ref_value) {
SCAN_CBACK_IN_JNI(batchscan_threshold_cb, ref_value);
}
@@ -227,6 +200,8 @@
SCAN_CBACK_IN_JNI(track_adv_event_cb, Owned(btif_scan_track_cb));
}
+void bta_cback(tBTA_GATTC_EVT, tBTA_GATTC*) {}
+
class BleScannerInterfaceImpl : public BleScannerInterface {
~BleScannerInterfaceImpl(){};
@@ -235,7 +210,7 @@
Bind(
[](RegisterCallback cb) {
BTA_GATTC_AppRegister(
- bta_gatts_cback,
+ bta_cback,
jni_thread_wrapper(FROM_HERE, std::move(cb)));
},
std::move(cb)));
@@ -255,9 +230,8 @@
}
btif_gattc_init_dev_cb();
- do_in_bta_thread(FROM_HERE,
- Bind(&BTA_DmBleObserve, true, 0,
- (tBTA_DM_SEARCH_CBACK*)bta_scan_results_cb));
+ do_in_bta_thread(
+ FROM_HERE, Bind(&BTA_DmBleObserve, true, 0, bta_scan_results_cb));
},
start));
}
@@ -280,93 +254,18 @@
jni_thread_wrapper(FROM_HERE, std::move(cb))));
}
- void ScanFilterAddRemove(int action, int filt_type, int filt_index,
- int company_id, int company_id_mask,
- const bt_uuid_t* p_uuid,
- const bt_uuid_t* p_uuid_mask,
- const RawAddress* bd_addr, char addr_type,
- vector<uint8_t> data, vector<uint8_t> mask,
- FilterConfigCallback cb) override {
- BTIF_TRACE_DEBUG("%s, %d, %d", __func__, action, filt_type);
+ void ScanFilterAdd(int filter_index, std::vector<ApcfCommand> filters,
+ FilterConfigCallback cb) override {
+ BTIF_TRACE_DEBUG("%s: %d", __func__, filter_index);
- /* If data is passed, both mask and data have to be the same length */
- if (data.size() != mask.size() && data.size() != 0 && mask.size() != 0)
- return;
-
- switch (filt_type) {
- case BTM_BLE_PF_ADDR_FILTER: {
- tBLE_BD_ADDR target_addr;
- target_addr.bda = *bd_addr;
- target_addr.type = addr_type;
-
- do_in_bta_thread(
- FROM_HERE,
- base::Bind(&BTM_LE_PF_addr_filter, action, filt_index,
- std::move(target_addr),
- jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type))));
- return;
- }
-
- case BTM_BLE_PF_SRVC_DATA:
- do_in_bta_thread(FROM_HERE,
- base::Bind(&BTM_LE_PF_srvc_data, action, filt_index));
- return;
-
- case BTM_BLE_PF_SRVC_UUID:
- case BTM_BLE_PF_SRVC_SOL_UUID: {
- tBT_UUID bt_uuid;
- btif_to_bta_uuid(&bt_uuid, p_uuid);
-
- if (p_uuid_mask == NULL) {
- do_in_bta_thread(
- FROM_HERE,
- base::Bind(&BTM_LE_PF_uuid_filter, action, filt_index, filt_type,
- bt_uuid, BTM_BLE_PF_LOGIC_AND, nullptr,
- jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type))));
- return;
- }
-
- tBTM_BLE_PF_COND_MASK* mask = new tBTM_BLE_PF_COND_MASK;
- btif_to_bta_uuid_mask(mask, p_uuid_mask, p_uuid);
- do_in_bta_thread(
- FROM_HERE,
- base::Bind(&BTM_LE_PF_uuid_filter, action, filt_index, filt_type,
- bt_uuid, BTM_BLE_PF_LOGIC_AND, base::Owned(mask),
- jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type))));
- return;
- }
-
- case BTM_BLE_PF_LOCAL_NAME: {
- do_in_bta_thread(
- FROM_HERE,
- base::Bind(&BTM_LE_PF_local_name, action, filt_index,
- std::move(data),
- jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type))));
- return;
- }
-
- case BTM_BLE_PF_MANU_DATA: {
- do_in_bta_thread(
- FROM_HERE,
- base::Bind(&BTM_LE_PF_manu_data, action, filt_index, company_id,
- company_id_mask, std::move(data), std::move(mask),
- jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type))));
- return;
- }
-
- case BTM_BLE_PF_SRVC_DATA_PATTERN: {
- do_in_bta_thread(
- FROM_HERE,
- base::Bind(&BTM_LE_PF_srvc_data_pattern, action, filt_index,
- std::move(data), std::move(mask),
- jni_thread_wrapper(FROM_HERE, Bind(cb, filt_type))));
- return;
- }
-
- default:
- LOG_ERROR(LOG_TAG, "%s: Unknown filter type (%d)!", __func__, action);
- return;
- }
+ do_in_bta_thread(
+ FROM_HERE,
+ base::Bind(
+ &BTM_LE_PF_set, filter_index, std::move(filters),
+ jni_thread_wrapper(
+ FROM_HERE,
+ Bind(std::move(cb),
+ 0 /*TODO: this used to be filter type, unused ?*/))));
}
void ScanFilterClear(int filter_index, FilterConfigCallback cb) override {
diff --git a/btif/src/btif_config.cc b/btif/src/btif_config.cc
index 1af751a..3155dc6 100644
--- a/btif/src/btif_config.cc
+++ b/btif/src/btif_config.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,7 +71,7 @@
static void delete_config_files(void);
static void btif_config_remove_unpaired(config_t* config);
static void btif_config_remove_restricted(config_t* config);
-static config_t* btif_config_open(const char* filename);
+static std::unique_ptr<config_t> btif_config_open(const char* filename);
static enum ConfigSource {
NOT_LOADED,
@@ -115,7 +115,7 @@
}
static std::mutex config_lock; // protects operations on |config|.
-static config_t* config;
+static std::unique_ptr<config_t> config;
static alarm_t* config_timer;
// Module lifecycle functions
@@ -154,29 +154,24 @@
}
if (!file_source.empty())
- config_set_string(config, INFO_SECTION, FILE_SOURCE, file_source.c_str());
+ config_set_string(config.get(), INFO_SECTION, FILE_SOURCE, file_source);
- if (!config) {
- LOG_ERROR(LOG_TAG, "%s unable to allocate a config object.", __func__);
- goto error;
- }
-
- btif_config_remove_unpaired(config);
+ btif_config_remove_unpaired(config.get());
// Cleanup temporary pairings if we have left guest mode
- if (!is_restricted_mode()) btif_config_remove_restricted(config);
+ if (!is_restricted_mode()) btif_config_remove_restricted(config.get());
// Read or set config file creation timestamp
- const char* time_str;
- time_str = config_get_string(config, INFO_SECTION, FILE_TIMESTAMP, NULL);
+ const std::string* time_str;
+ time_str = config_get_string(*config, INFO_SECTION, FILE_TIMESTAMP, NULL);
if (time_str != NULL) {
- strlcpy(btif_config_time_created, time_str, TIME_STRING_LENGTH);
+ strlcpy(btif_config_time_created, time_str->c_str(), TIME_STRING_LENGTH);
} else {
time_t current_time = time(NULL);
struct tm* time_created = localtime(¤t_time);
strftime(btif_config_time_created, TIME_STRING_LENGTH, TIME_STRING_FORMAT,
time_created);
- config_set_string(config, INFO_SECTION, FILE_TIMESTAMP,
+ config_set_string(config.get(), INFO_SECTION, FILE_TIMESTAMP,
btif_config_time_created);
}
@@ -195,21 +190,19 @@
error:
alarm_free(config_timer);
- config_free(config);
+ config.reset();
config_timer = NULL;
- config = NULL;
btif_config_source = NOT_LOADED;
return future_new_immediate(FUTURE_FAIL);
}
-static config_t* btif_config_open(const char* filename) {
- config_t* config = config_new(filename);
- if (!config) return NULL;
+static std::unique_ptr<config_t> btif_config_open(const char* filename) {
+ std::unique_ptr<config_t> config = config_new(filename);
+ if (!config) return nullptr;
- if (!config_has_section(config, "Adapter")) {
+ if (!config_has_section(*config, "Adapter")) {
LOG_ERROR(LOG_TAG, "Config is missing adapter section");
- config_free(config);
- return NULL;
+ return nullptr;
}
return config;
@@ -227,8 +220,7 @@
config_timer = NULL;
std::unique_lock<std::mutex> lock(config_lock);
- config_free(config);
- config = NULL;
+ config.reset();
return future_new_immediate(FUTURE_SUCCESS);
}
@@ -243,118 +235,128 @@
CHECK(section != NULL);
std::unique_lock<std::mutex> lock(config_lock);
- return config_has_section(config, section);
+ return config_has_section(*config, section);
}
-bool btif_config_exist(const char* section, const char* key) {
+bool btif_config_exist(const std::string& section, const std::string& key) {
CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
std::unique_lock<std::mutex> lock(config_lock);
- return config_has_key(config, section, key);
+ return config_has_key(*config, section, key);
}
-bool btif_config_get_int(const char* section, const char* key, int* value) {
+bool btif_config_get_int(const std::string& section, const std::string& key,
+ int* value) {
CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
CHECK(value != NULL);
std::unique_lock<std::mutex> lock(config_lock);
- bool ret = config_has_key(config, section, key);
- if (ret) *value = config_get_int(config, section, key, *value);
+ bool ret = config_has_key(*config, section, key);
+ if (ret) *value = config_get_int(*config, section, key, *value);
return ret;
}
-bool btif_config_set_int(const char* section, const char* key, int value) {
+bool btif_config_set_int(const std::string& section, const std::string& key,
+ int value) {
CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
std::unique_lock<std::mutex> lock(config_lock);
- config_set_int(config, section, key, value);
+ config_set_int(config.get(), section, key, value);
return true;
}
-bool btif_config_get_str(const char* section, const char* key, char* value,
- int* size_bytes) {
+bool btif_config_get_uint64(const std::string& section, const std::string& key,
+ uint64_t* value) {
CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
+ CHECK(value != NULL);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ bool ret = config_has_key(*config, section, key);
+ if (ret) *value = config_get_uint64(*config, section, key, *value);
+
+ return ret;
+}
+
+bool btif_config_set_uint64(const std::string& section, const std::string& key,
+ uint64_t value) {
+ CHECK(config != NULL);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ config_set_uint64(config.get(), section, key, value);
+
+ return true;
+}
+
+bool btif_config_get_str(const std::string& section, const std::string& key,
+ char* value, int* size_bytes) {
+ CHECK(config != NULL);
CHECK(value != NULL);
CHECK(size_bytes != NULL);
{
std::unique_lock<std::mutex> lock(config_lock);
- const char* stored_value = config_get_string(config, section, key, NULL);
+ const std::string* stored_value =
+ config_get_string(*config, section, key, NULL);
if (!stored_value) return false;
- strlcpy(value, stored_value, *size_bytes);
+ strlcpy(value, stored_value->c_str(), *size_bytes);
}
*size_bytes = strlen(value) + 1;
return true;
}
-bool btif_config_set_str(const char* section, const char* key,
- const char* value) {
+bool btif_config_set_str(const std::string& section, const std::string& key,
+ const std::string& value) {
CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
- CHECK(value != NULL);
std::unique_lock<std::mutex> lock(config_lock);
- config_set_string(config, section, key, value);
+ config_set_string(config.get(), section, key, value);
return true;
}
-bool btif_config_get_bin(const char* section, const char* key, uint8_t* value,
- size_t* length) {
+bool btif_config_get_bin(const std::string& section, const std::string& key,
+ uint8_t* value, size_t* length) {
CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
CHECK(value != NULL);
CHECK(length != NULL);
std::unique_lock<std::mutex> lock(config_lock);
- const char* value_str = config_get_string(config, section, key, NULL);
+ const std::string* value_str = config_get_string(*config, section, key, NULL);
if (!value_str) return false;
- size_t value_len = strlen(value_str);
+ size_t value_len = value_str->length();
if ((value_len % 2) != 0 || *length < (value_len / 2)) return false;
for (size_t i = 0; i < value_len; ++i)
- if (!isxdigit(value_str[i])) return false;
+ if (!isxdigit(value_str->c_str()[i])) return false;
- for (*length = 0; *value_str; value_str += 2, *length += 1)
- sscanf(value_str, "%02hhx", &value[*length]);
+ const char* ptr = value_str->c_str();
+ for (*length = 0; *ptr; ptr += 2, *length += 1)
+ sscanf(ptr, "%02hhx", &value[*length]);
return true;
}
-size_t btif_config_get_bin_length(const char* section, const char* key) {
+size_t btif_config_get_bin_length(const std::string& section,
+ const std::string& key) {
CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
std::unique_lock<std::mutex> lock(config_lock);
- const char* value_str = config_get_string(config, section, key, NULL);
+ const std::string* value_str = config_get_string(*config, section, key, NULL);
if (!value_str) return 0;
- size_t value_len = strlen(value_str);
+ size_t value_len = value_str->length();
return ((value_len % 2) != 0) ? 0 : (value_len / 2);
}
-bool btif_config_set_bin(const char* section, const char* key,
+bool btif_config_set_bin(const std::string& section, const std::string& key,
const uint8_t* value, size_t length) {
const char* lookup = "0123456789abcdef";
CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
if (length > 0) CHECK(value != NULL);
@@ -367,45 +369,20 @@
{
std::unique_lock<std::mutex> lock(config_lock);
- config_set_string(config, section, key, str);
+ config_set_string(config.get(), section, key, str);
}
osi_free(str);
return true;
}
-const btif_config_section_iter_t* btif_config_section_begin(void) {
- CHECK(config != NULL);
- return (const btif_config_section_iter_t*)config_section_begin(config);
-}
+std::list<section_t>& btif_config_sections() { return config->sections; }
-const btif_config_section_iter_t* btif_config_section_end(void) {
+bool btif_config_remove(const std::string& section, const std::string& key) {
CHECK(config != NULL);
- return (const btif_config_section_iter_t*)config_section_end(config);
-}
-
-const btif_config_section_iter_t* btif_config_section_next(
- const btif_config_section_iter_t* section) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- return (const btif_config_section_iter_t*)config_section_next(
- (const config_section_node_t*)section);
-}
-
-const char* btif_config_section_name(
- const btif_config_section_iter_t* section) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- return config_section_name((const config_section_node_t*)section);
-}
-
-bool btif_config_remove(const char* section, const char* key) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
std::unique_lock<std::mutex> lock(config_lock);
- return config_remove_key(config, section, key);
+ return config_remove_key(config.get(), section, key);
}
void btif_config_save(void) {
@@ -430,12 +407,10 @@
alarm_cancel(config_timer);
std::unique_lock<std::mutex> lock(config_lock);
- config_free(config);
config = config_new_empty();
- if (config == NULL) return false;
- bool ret = config_save(config, CONFIG_FILE_PATH);
+ bool ret = config_save(*config, CONFIG_FILE_PATH);
btif_config_source = RESET;
return ret;
}
@@ -454,10 +429,9 @@
std::unique_lock<std::mutex> lock(config_lock);
rename(CONFIG_FILE_PATH, CONFIG_BACKUP_PATH);
- config_t* config_paired = config_new_clone(config);
- btif_config_remove_unpaired(config_paired);
- config_save(config_paired, CONFIG_FILE_PATH);
- config_free(config_paired);
+ std::unique_ptr<config_t> config_paired = config_new_clone(*config);
+ btif_config_remove_unpaired(config_paired.get());
+ config_save(*config_paired, CONFIG_FILE_PATH);
}
static void btif_config_remove_unpaired(config_t* conf) {
@@ -467,23 +441,23 @@
// The paired config used to carry information about
// discovered devices during regular inquiry scans.
// We remove these now and cache them in memory instead.
- const config_section_node_t* snode = config_section_begin(conf);
- while (snode != config_section_end(conf)) {
- const char* section = config_section_name(snode);
+ for (auto it = conf->sections.begin(); it != conf->sections.end();) {
+ std::string& section = it->name;
if (RawAddress::IsValidAddress(section)) {
- if (!config_has_key(conf, section, "LinkKey") &&
- !config_has_key(conf, section, "LE_KEY_PENC") &&
- !config_has_key(conf, section, "LE_KEY_PID") &&
- !config_has_key(conf, section, "LE_KEY_PCSRK") &&
- !config_has_key(conf, section, "LE_KEY_LENC") &&
- !config_has_key(conf, section, "LE_KEY_LCSRK")) {
- snode = config_section_next(snode);
- config_remove_section(conf, section);
+ // TODO: config_has_key loop thorugh all data, maybe just make it so we
+ // loop just once ?
+ if (!config_has_key(*conf, section, "LinkKey") &&
+ !config_has_key(*conf, section, "LE_KEY_PENC") &&
+ !config_has_key(*conf, section, "LE_KEY_PID") &&
+ !config_has_key(*conf, section, "LE_KEY_PCSRK") &&
+ !config_has_key(*conf, section, "LE_KEY_LENC") &&
+ !config_has_key(*conf, section, "LE_KEY_LCSRK")) {
+ it = conf->sections.erase(it);
continue;
}
paired_devices++;
}
- snode = config_section_next(snode);
+ it++;
}
// should only happen once, at initial load time
@@ -516,24 +490,27 @@
break;
}
+ std::string original = "Original";
dprintf(fd, " Devices loaded: %d\n", btif_config_devices_loaded);
dprintf(fd, " File created/tagged: %s\n", btif_config_time_created);
dprintf(fd, " File source: %s\n",
- config_get_string(config, INFO_SECTION, FILE_SOURCE, "Original"));
+ config_get_string(*config, INFO_SECTION, FILE_SOURCE, &original)
+ ->c_str());
}
static void btif_config_remove_restricted(config_t* config) {
CHECK(config != NULL);
- const config_section_node_t* snode = config_section_begin(config);
- while (snode != config_section_end(config)) {
- const char* section = config_section_name(snode);
+ for (auto it = config->sections.begin(); it != config->sections.end();) {
+ const std::string& section = it->name;
if (RawAddress::IsValidAddress(section) &&
- config_has_key(config, section, "Restricted")) {
- BTIF_TRACE_DEBUG("%s: Removing restricted device %s", __func__, section);
- config_remove_section(config, section);
+ config_has_key(*config, section, "Restricted")) {
+ BTIF_TRACE_DEBUG("%s: Removing restricted device %s", __func__,
+ section.c_str());
+ it = config->sections.erase(it);
+ continue;
}
- snode = config_section_next(snode);
+ it++;
}
}
diff --git a/btif/src/btif_config_transcode.cc b/btif/src/btif_config_transcode.cc
index 102a3af..75ebd77 100644
--- a/btif/src/btif_config_transcode.cc
+++ b/btif/src/btif_config_transcode.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
using namespace tinyxml2;
-config_t* btif_config_transcode(const char* xml_filename) {
+std::unique_ptr<config_t> btif_config_transcode(const char* xml_filename) {
XMLDocument document;
int error = document.LoadFile(xml_filename);
if (error != XML_SUCCESS) {
@@ -42,11 +42,7 @@
return NULL;
}
- config_t* config = config_new_empty();
- if (!config) {
- LOG_ERROR(LOG_TAG, "%s unable to allocate config object.", __func__);
- return NULL;
- }
+ std::unique_ptr<config_t> config = config_new_empty();
for (XMLElement* i = rootElement->FirstChildElement(); i != NULL;
i = i->NextSiblingElement())
@@ -58,7 +54,7 @@
const char* key = k->Attribute("Tag");
const char* value = k->GetText();
if (section && key && value)
- config_set_string(config, section, key, value);
+ config_set_string(config.get(), section, key, value);
}
}
diff --git a/btif/src/btif_core.cc b/btif/src/btif_core.cc
index febf945..582ae47 100644
--- a/btif/src/btif_core.cc
+++ b/btif/src/btif_core.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
#include <base/at_exit.h>
#include <base/bind.h>
#include <base/run_loop.h>
+#include <base/threading/platform_thread.h>
#include <base/threading/thread.h>
#include <ctype.h>
#include <dirent.h>
@@ -45,6 +46,7 @@
#include "bt_common.h"
#include "bt_utils.h"
#include "bta_api.h"
+#include "bta_closure_api.h"
#include "bte.h"
#include "btif_api.h"
#include "btif_av.h"
@@ -65,6 +67,9 @@
#include "osi/include/thread.h"
#include "stack_manager.h"
+using base::PlatformThread;
+using bluetooth::Uuid;
+
/*******************************************************************************
* Constants & Macros
******************************************************************************/
@@ -128,6 +133,7 @@
static uid_set_t* uid_set = NULL;
base::MessageLoop* message_loop_ = NULL;
base::RunLoop* jni_run_loop = NULL;
+static base::PlatformThreadId btif_thread_id_ = -1;
/*******************************************************************************
* Static functions
@@ -219,14 +225,20 @@
**/
bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here,
const base::Closure& task) {
- if (!message_loop_ || !message_loop_->task_runner().get()) {
+ if (!message_loop_) {
BTIF_TRACE_WARNING("%s: Dropped message, message_loop not initialized yet!",
__func__);
return BT_STATUS_FAIL;
}
- if (message_loop_->task_runner()->PostTask(from_here, task))
- return BT_STATUS_SUCCESS;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ message_loop_->task_runner();
+ if (!task_runner.get()) {
+ BTIF_TRACE_WARNING("%s: task runner is dead", __func__);
+ return BT_STATUS_FAIL;
+ }
+
+ if (task_runner->PostTask(from_here, task)) return BT_STATUS_SUCCESS;
BTIF_TRACE_ERROR("%s: Post task to task runner failed!", __func__);
return BT_STATUS_FAIL;
@@ -236,6 +248,12 @@
return do_in_jni_thread(FROM_HERE, task);
}
+bool is_on_jni_thread() {
+ return btif_thread_id_ == PlatformThread::CurrentId();
+}
+
+base::MessageLoop* get_jni_message_loop() { return message_loop_; }
+
/*******************************************************************************
*
* Function btif_is_dut_mode
@@ -315,6 +333,7 @@
void run_message_loop(UNUSED_ATTR void* context) {
LOG_INFO(LOG_TAG, "%s entered", __func__);
+ btif_thread_id_ = PlatformThread::CurrentId();
// TODO(jpawlowski): exit_manager should be defined in main(), but there is no
// main method.
@@ -337,6 +356,7 @@
delete jni_run_loop;
jni_run_loop = NULL;
+ btif_thread_id_ = -1;
LOG_INFO(LOG_TAG, "%s finished", __func__);
}
/*******************************************************************************
@@ -458,7 +478,7 @@
bt_status_t btif_disable_bluetooth(void) {
LOG_INFO(LOG_TAG, "%s entered", __func__);
- btm_ble_multi_adv_cleanup();
+ do_in_bta_thread(FROM_HERE, base::Bind(&btm_ble_multi_adv_cleanup));
// TODO(jpawlowski): this should do whole BTA_VendorCleanup(), but it would
// kill the stack now.
@@ -509,7 +529,7 @@
bt_status_t btif_cleanup_bluetooth(void) {
LOG_INFO(LOG_TAG, "%s entered", __func__);
- BTA_VendorCleanup();
+ do_in_bta_thread(FROM_HERE, base::Bind(&BTA_VendorCleanup));
btif_dm_cleanup();
btif_jni_disassociate();
@@ -608,7 +628,7 @@
bt_scan_mode_t mode;
uint32_t disc_timeout;
RawAddress bonded_devices[BTM_SEC_MAX_DEVICE_RECORDS];
- bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS];
+ Uuid local_uuids[BT_MAX_NUM_UUIDS];
bt_status_t status;
/* RawAddress */
@@ -666,7 +686,7 @@
bt_bdname_t name, alias;
uint32_t cod, devtype;
- bt_uuid_t remote_uuids[BT_MAX_NUM_UUIDS];
+ Uuid remote_uuids[BT_MAX_NUM_UUIDS];
memset(remote_properties, 0, sizeof(remote_properties));
BTIF_STORAGE_FILL_PROPERTY(&remote_properties[num_props], BT_PROPERTY_BDNAME,
@@ -900,7 +920,7 @@
/* Allow get_adapter_property only for BDADDR and BDNAME if BT is disabled */
if (!btif_is_enabled() && (type != BT_PROPERTY_BDADDR) &&
- (type != BT_PROPERTY_BDNAME))
+ (type != BT_PROPERTY_BDNAME) && (type != BT_PROPERTY_CLASS_OF_DEVICE))
return BT_STATUS_NOT_READY;
req.read_req.bd_addr = RawAddress::kEmpty;
@@ -987,6 +1007,15 @@
if required */
storage_req_id = BTIF_CORE_STORAGE_ADAPTER_WRITE;
} break;
+ case BT_PROPERTY_CLASS_OF_DEVICE: {
+ DEV_CLASS dev_class;
+ memcpy(dev_class, property->val, DEV_CLASS_LEN);
+
+ BTIF_TRACE_EVENT("set property dev_class : 0x%02x%02x%02x", dev_class[0],
+ dev_class[1], dev_class[2]);
+
+ BTM_SetDeviceClass(dev_class);
+ } break;
case BT_PROPERTY_BDADDR:
case BT_PROPERTY_UUIDS:
case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
@@ -1095,8 +1124,8 @@
* Returns bt_status_t
*
******************************************************************************/
-bt_status_t btif_get_remote_service_record(RawAddress* remote_addr,
- bt_uuid_t* uuid) {
+bt_status_t btif_get_remote_service_record(const RawAddress& remote_addr,
+ const Uuid& uuid) {
if (!btif_is_enabled()) return BT_STATUS_NOT_READY;
return btif_dm_get_remote_service_record(remote_addr, uuid);
diff --git a/btif/src/btif_debug.cc b/btif/src/btif_debug.cc
index a26c301..04b6474 100644
--- a/btif/src/btif_debug.cc
+++ b/btif/src/btif_debug.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
#include "btif/include/btif_debug.h"
#include "btif/include/btif_debug_btsnoop.h"
-#include "include/bt_target.h"
+#include "internal_include/bt_target.h"
void btif_debug_init(void) {
#if (BTSNOOP_MEM == TRUE)
diff --git a/btif/src/btif_debug_btsnoop.cc b/btif/src/btif_debug_btsnoop.cc
index e52a177..1dcb835 100644
--- a/btif/src/btif_debug_btsnoop.cc
+++ b/btif/src/btif_debug_btsnoop.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
#include "btif/include/btif_debug.h"
#include "btif/include/btif_debug_btsnoop.h"
#include "hci/include/btsnoop_mem.h"
-#include "include/bt_target.h"
+#include "internal_include/bt_target.h"
#include "osi/include/ringbuffer.h"
#include "osi/include/time.h"
@@ -207,7 +207,7 @@
rc = btsnoop_compress(ringbuffer, buffer);
}
- if (rc == false) {
+ if (!rc) {
dprintf(fd, "%s Log compression failed", __func__);
goto error;
}
diff --git a/btif/src/btif_debug_conn.cc b/btif/src/btif_debug_conn.cc
index 9252a02..6b4d96f 100644
--- a/btif/src/btif_debug_conn.cc
+++ b/btif/src/btif_debug_conn.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/src/btif_dm.cc b/btif/src/btif_dm.cc
index eceab10..d1bb61c 100644
--- a/btif/src/btif_dm.cc
+++ b/btif/src/btif_dm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,16 +41,20 @@
#include <mutex>
+#include <bluetooth/uuid.h>
#include <hardware/bluetooth.h>
+#include <hardware/bt_hearing_aid.h>
#include "advertise_data_parser.h"
#include "bt_common.h"
#include "bta_closure_api.h"
#include "bta_gatt_api.h"
#include "btif_api.h"
+#include "btif_av.h"
#include "btif_config.h"
#include "btif_dm.h"
#include "btif_hd.h"
+#include "btif_hf.h"
#include "btif_hh.h"
#include "btif_sdp.h"
#include "btif_storage.h"
@@ -58,7 +62,7 @@
#include "btu.h"
#include "device/include/controller.h"
#include "device/include/interop.h"
-#include "include/stack_config.h"
+#include "internal_include/stack_config.h"
#include "osi/include/allocator.h"
#include "osi/include/log.h"
#include "osi/include/metrics.h"
@@ -67,10 +71,13 @@
#include "stack/btm/btm_int.h"
#include "stack_config.h"
+using bluetooth::Uuid;
/******************************************************************************
* Constants & Macros
*****************************************************************************/
+const Uuid UUID_HEARING_AID = Uuid::FromString("FDF0");
+
#define COD_MASK 0x07FF
#define COD_UNCLASSIFIED ((0x1F) << 8)
@@ -97,13 +104,6 @@
#error "default btif local name size exceeds stack supported length"
#endif
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
-#define BTIF_DM_INTERLEAVE_DURATION_BR_ONE 2
-#define BTIF_DM_INTERLEAVE_DURATION_LE_ONE 2
-#define BTIF_DM_INTERLEAVE_DURATION_BR_TWO 3
-#define BTIF_DM_INTERLEAVE_DURATION_LE_TWO 4
-#endif
-
#define ENCRYPTED_BREDR 2
#define ENCRYPTED_LE 4
@@ -182,8 +182,6 @@
#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id))
-#define UUID_HUMAN_INTERFACE_DEVICE "00001124-0000-1000-8000-00805f9b34fb"
-
#define MAX_BTIF_BOND_EVENT_ENTRIES 15
static skip_sdp_entry_t sdp_blacklist[] = {{76}}; // Apple Mouse and Keyboard
@@ -240,17 +238,15 @@
/******************************************************************************
* Externs
*****************************************************************************/
-extern bt_status_t btif_hf_execute_service(bool b_enable);
extern bt_status_t btif_av_execute_service(bool b_enable);
extern bt_status_t btif_av_sink_execute_service(bool b_enable);
extern bt_status_t btif_hh_execute_service(bool b_enable);
extern bt_status_t btif_hf_client_execute_service(bool b_enable);
extern bt_status_t btif_sdp_execute_service(bool b_enable);
extern int btif_hh_connect(const RawAddress* bd_addr);
-extern void bta_gatt_convert_uuid16_to_uuid128(uint8_t uuid_128[LEN_UUID_128],
- uint16_t uuid_16);
-extern void btif_av_move_idle(RawAddress bd_addr);
extern bt_status_t btif_hd_execute_service(bool b_enable);
+extern bluetooth::hearing_aid::HearingAidInterface*
+btif_hearing_aid_get_interface();
/******************************************************************************
* Functions
@@ -300,10 +296,10 @@
switch (service_id) {
case BTA_HFP_SERVICE_ID:
case BTA_HSP_SERVICE_ID: {
- btif_hf_execute_service(b_enable);
+ bluetooth::headset::ExecuteService(b_enable);
} break;
case BTA_A2DP_SOURCE_SERVICE_ID: {
- btif_av_execute_service(b_enable);
+ btif_av_source_execute_service(b_enable);
} break;
case BTA_A2DP_SINK_SERVICE_ID: {
btif_av_sink_execute_service(b_enable);
@@ -802,10 +798,10 @@
if (p_src_data->disc_res.result == BTA_SUCCESS) {
if (p_src_data->disc_res.num_uuids > 0) {
p_dest_data->disc_res.p_uuid_list =
- (uint8_t*)(p_dest + sizeof(tBTA_DM_SEARCH));
+ (Uuid*)(p_dest + sizeof(tBTA_DM_SEARCH));
memcpy(p_dest_data->disc_res.p_uuid_list,
p_src_data->disc_res.p_uuid_list,
- p_src_data->disc_res.num_uuids * MAX_UUID_SIZE);
+ p_src_data->disc_res.num_uuids * sizeof(Uuid));
osi_free_and_reset((void**)&p_src_data->disc_res.p_uuid_list);
}
osi_free_and_reset((void**)&p_src_data->disc_res.p_raw_data);
@@ -845,6 +841,14 @@
const RawAddress& bd_addr = p_pin_req->bd_addr;
memcpy(bd_name.name, p_pin_req->bd_name, BD_NAME_LEN);
+ if (pairing_cb.state == BT_BOND_STATE_BONDING &&
+ bd_addr != pairing_cb.bd_addr) {
+ BTIF_TRACE_WARNING("%s(): already in bonding state, reject request",
+ __FUNCTION__);
+ btif_dm_pin_reply(&bd_addr, 0, 0, NULL);
+ return;
+ }
+
bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
cod = devclass2uint(p_pin_req->dev_class);
@@ -856,7 +860,7 @@
/* check for auto pair possiblity only if bond was initiated by local device
*/
- if (pairing_cb.is_local_initiated && (p_pin_req->min_16_digit == false)) {
+ if (pairing_cb.is_local_initiated && !p_pin_req->min_16_digit) {
if (check_cod(&bd_addr, COD_AV_HEADSETS) ||
check_cod(&bd_addr, COD_AV_HEADPHONES) ||
check_cod(&bd_addr, COD_AV_PORTABLE_AUDIO) ||
@@ -928,10 +932,22 @@
RawAddress bd_addr = p_ssp_cfm_req->bd_addr;
memcpy(bd_name.name, p_ssp_cfm_req->bd_name, BD_NAME_LEN);
+ if (pairing_cb.state == BT_BOND_STATE_BONDING &&
+ bd_addr != pairing_cb.bd_addr) {
+ BTIF_TRACE_WARNING("%s(): already in bonding state, reject request",
+ __FUNCTION__);
+ btif_dm_ssp_reply(&bd_addr, BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 0, 0);
+ return;
+ }
+
/* Set the pairing_cb based on the local & remote authentication requirements
*/
bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
+ BTIF_TRACE_EVENT("%s: just_works:%d, loc_auth_req=%d, rmt_auth_req=%d",
+ __func__, p_ssp_cfm_req->just_works,
+ p_ssp_cfm_req->loc_auth_req, p_ssp_cfm_req->rmt_auth_req);
+
/* if just_works and bonding bit is not set treat this as temporary */
if (p_ssp_cfm_req->just_works &&
!(p_ssp_cfm_req->loc_auth_req & BTM_AUTH_BONDS) &&
@@ -1026,10 +1042,12 @@
bt_bond_state_t state = BT_BOND_STATE_NONE;
bool skip_sdp = false;
- BTIF_TRACE_DEBUG("%s: bond state=%d", __func__, pairing_cb.state);
+ BTIF_TRACE_DEBUG("%s: bond state=%d, success=%d, key_present=%d", __func__,
+ pairing_cb.state, p_auth_cmpl->success,
+ p_auth_cmpl->key_present);
RawAddress bd_addr = p_auth_cmpl->bd_addr;
- if ((p_auth_cmpl->success == true) && (p_auth_cmpl->key_present)) {
+ if ((p_auth_cmpl->success) && (p_auth_cmpl->key_present)) {
if ((p_auth_cmpl->key_type < HCI_LKEY_TYPE_DEBUG_COMB) ||
(p_auth_cmpl->key_type == HCI_LKEY_TYPE_AUTH_COMB) ||
(p_auth_cmpl->key_type == HCI_LKEY_TYPE_CHANGED_COMB) ||
@@ -1056,23 +1074,22 @@
}
}
- // We could have received a new link key without going through the pairing
- // flow. If so, we don't want to perform SDP or any other operations on the
- // authenticated device. Also, make sure that the link key is not derived from
- // secure LTK, because we will need to perform SDP in case of link key
- // derivation to allow bond state change notification for the BR/EDR transport
- // so that the subsequent BR/EDR connections to the remote can use the derived
- // link key.
- if (p_auth_cmpl->bd_addr != pairing_cb.bd_addr &&
- (!pairing_cb.ble.is_penc_key_rcvd)) {
- LOG(INFO) << __func__
- << " skipping SDP since we did not initiate pairing to "
- << p_auth_cmpl->bd_addr;
- return;
- }
-
- // Skip SDP for certain HID Devices
if (p_auth_cmpl->success) {
+ // We could have received a new link key without going through the pairing
+ // flow. If so, we don't want to perform SDP or any other operations on the
+ // authenticated device. Also, make sure that the link key is not derived
+ // from secure LTK, because we will need to perform SDP in case of link key
+ // derivation to allow bond state change notification for the BR/EDR
+ // transport so that the subsequent BR/EDR connections to the remote can use
+ // the derived link key.
+ if (p_auth_cmpl->bd_addr != pairing_cb.bd_addr &&
+ (!pairing_cb.ble.is_penc_key_rcvd)) {
+ LOG(INFO) << __func__
+ << " skipping SDP since we did not initiate pairing to "
+ << p_auth_cmpl->bd_addr;
+ return;
+ }
+
btif_storage_set_remote_addr_type(&bd_addr, p_auth_cmpl->addr_type);
btif_update_remote_properties(p_auth_cmpl->bd_addr, p_auth_cmpl->bd_name,
NULL, p_auth_cmpl->dev_type);
@@ -1091,14 +1108,11 @@
LOG_WARN(LOG_TAG, "%s: Incoming HID Connection", __func__);
bt_property_t prop;
RawAddress bd_addr;
- bt_uuid_t uuid;
- char uuid_str[128] = UUID_HUMAN_INTERFACE_DEVICE;
-
- string_to_uuid(uuid_str, &uuid);
+ Uuid uuid = Uuid::From16Bit(UUID_SERVCLASS_HUMAN_INTERFACE);
prop.type = BT_PROPERTY_UUIDS;
- prop.val = uuid.uu;
- prop.len = MAX_UUID_SIZE;
+ prop.val = &uuid;
+ prop.len = Uuid::kNumBytes128;
/* Send the event to the BTIF */
HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS,
@@ -1341,7 +1355,7 @@
* but instead wait for the cancel_cmpl_evt via the Busy Level
*
*/
- if (btif_dm_inquiry_in_progress == false) {
+ if (!btif_dm_inquiry_in_progress) {
btgatt_filt_param_setup_t adv_filt_param;
memset(&adv_filt_param, 0, sizeof(btgatt_filt_param_setup_t));
do_in_bta_thread(
@@ -1392,13 +1406,10 @@
if ((p_data->disc_res.result == BTA_SUCCESS) &&
(p_data->disc_res.num_uuids > 0)) {
prop.val = p_data->disc_res.p_uuid_list;
- prop.len = p_data->disc_res.num_uuids * MAX_UUID_SIZE;
+ prop.len = p_data->disc_res.num_uuids * Uuid::kNumBytes128;
for (i = 0; i < p_data->disc_res.num_uuids; i++) {
- char temp[256];
- uuid_to_string_legacy(
- (bt_uuid_t*)(p_data->disc_res.p_uuid_list + (i * MAX_UUID_SIZE)),
- temp, sizeof(temp));
- LOG_INFO(LOG_TAG, "%s index:%d uuid:%s", __func__, i, temp);
+ std::string temp = ((p_data->disc_res.p_uuid_list + i))->ToString();
+ LOG_INFO(LOG_TAG, "%s index:%d uuid:%s", __func__, i, temp.c_str());
}
}
@@ -1442,36 +1453,21 @@
break;
case BTA_DM_DISC_BLE_RES_EVT: {
- BTIF_TRACE_DEBUG("%s:, services 0x%x)", __func__,
- p_data->disc_ble_res.service.uu.uuid16);
- bt_uuid_t uuid;
- int i = 0;
- int j = 15;
+ BTIF_TRACE_DEBUG("%s: service %s", __func__,
+ p_data->disc_ble_res.service.ToString().c_str());
int num_properties = 0;
- if (p_data->disc_ble_res.service.uu.uuid16 == UUID_SERVCLASS_LE_HID) {
- BTIF_TRACE_DEBUG("%s: Found HOGP UUID", __func__);
+ if (p_data->disc_ble_res.service.As16Bit() == UUID_SERVCLASS_LE_HID ||
+ p_data->disc_ble_res.service == UUID_HEARING_AID) {
+ BTIF_TRACE_DEBUG("%s: Found HOGP or HEARING AID UUID", __func__);
bt_property_t prop[2];
- char temp[256];
bt_status_t ret;
- bta_gatt_convert_uuid16_to_uuid128(
- uuid.uu, p_data->disc_ble_res.service.uu.uuid16);
-
- while (i < j) {
- unsigned char c = uuid.uu[j];
- uuid.uu[j] = uuid.uu[i];
- uuid.uu[i] = c;
- i++;
- j--;
- }
-
- uuid_to_string_legacy(&uuid, temp, sizeof(temp));
- LOG_INFO(LOG_TAG, "%s uuid:%s", __func__, temp);
+ const auto& arr = p_data->disc_ble_res.service.To128BitBE();
RawAddress& bd_addr = p_data->disc_ble_res.bd_addr;
prop[0].type = BT_PROPERTY_UUIDS;
- prop[0].val = uuid.uu;
- prop[0].len = MAX_UUID_SIZE;
+ prop[0].val = (void*)arr.data();
+ prop[0].len = Uuid::kNumBytes128;
/* Also write this to the NVRAM */
ret = btif_storage_set_remote_device_property(&bd_addr, &prop[0]);
@@ -1649,12 +1645,13 @@
btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);
/*special handling for HID devices */
-#if (defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == true))
+#if (defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE))
btif_hh_remove_device(bd_addr);
#endif
#if (defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE))
btif_hd_remove_device(bd_addr);
#endif
+ btif_hearing_aid_get_interface()->RemoveDevice(bd_addr);
btif_storage_remove_bonded_device(&bd_addr);
bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_NONE);
break;
@@ -1688,7 +1685,7 @@
case BTA_DM_LINK_DOWN_EVT:
bd_addr = p_data->link_down.bd_addr;
btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);
- btif_av_move_idle(bd_addr);
+ btif_av_acl_disconnected(bd_addr);
BTIF_TRACE_DEBUG(
"BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
@@ -1896,7 +1893,7 @@
case BTA_DM_ROLE_CHG_EVT:
default:
- BTIF_TRACE_WARNING("btif_dm_cback : unhandled event (%d)", event);
+ BTIF_TRACE_WARNING("%s: unhandled event (%d)", __func__, event);
break;
}
@@ -2039,7 +2036,7 @@
case BTA_DM_DISC_RES_EVT: {
if ((p_data->disc_res.result == BTA_SUCCESS) &&
(p_data->disc_res.num_uuids > 0)) {
- param_len += (p_data->disc_res.num_uuids * MAX_UUID_SIZE);
+ param_len += (p_data->disc_res.num_uuids * Uuid::kNumBytes128);
}
} break;
}
@@ -2158,12 +2155,6 @@
/* Set inquiry params and call API */
inq_params.mode = BTA_DM_GENERAL_INQUIRY | BTA_BLE_GENERAL_INQUIRY;
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- inq_params.intl_duration[0] = BTIF_DM_INTERLEAVE_DURATION_BR_ONE;
- inq_params.intl_duration[1] = BTIF_DM_INTERLEAVE_DURATION_LE_ONE;
- inq_params.intl_duration[2] = BTIF_DM_INTERLEAVE_DURATION_BR_TWO;
- inq_params.intl_duration[3] = BTIF_DM_INTERLEAVE_DURATION_LE_TWO;
-#endif
inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION;
inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS;
@@ -2442,6 +2433,12 @@
prop->len = sizeof(uint32_t);
} break;
+ case BT_PROPERTY_CLASS_OF_DEVICE: {
+ DEV_CLASS dev_class = BTA_DM_COD;
+ memcpy(prop->val, dev_class, sizeof(DEV_CLASS));
+ prop->len = sizeof(DEV_CLASS);
+ } break;
+
default:
prop->len = 0;
return BT_STATUS_FAIL;
@@ -2478,7 +2475,8 @@
******************************************************************************/
bt_status_t btif_dm_get_remote_services_by_transport(RawAddress* remote_addr,
const int transport) {
- BTIF_TRACE_EVENT("%s", __func__);
+ BTIF_TRACE_EVENT("%s: transport=%d, remote_addr=%s", __func__, transport,
+ remote_addr->ToString().c_str());
/* Set the mask extension */
tBTA_SERVICE_MASK_EXT mask_ext;
@@ -2501,16 +2499,10 @@
*
* Returns bt_status_t
******************************************************************************/
-bt_status_t btif_dm_get_remote_service_record(RawAddress* remote_addr,
- bt_uuid_t* uuid) {
- BTIF_TRACE_EVENT("%s: bd_addr=%s", __func__, remote_addr->ToString().c_str());
-
- tSDP_UUID sdp_uuid;
- sdp_uuid.len = MAX_UUID_SIZE;
- memcpy(sdp_uuid.uu.uuid128, uuid->uu, MAX_UUID_SIZE);
-
- BTA_DmDiscoverUUID(*remote_addr, &sdp_uuid, bte_dm_remote_service_record_evt,
- true);
+bt_status_t btif_dm_get_remote_service_record(const RawAddress& remote_addr,
+ const Uuid& uuid) {
+ BTIF_TRACE_EVENT("%s: bd_addr=%s", __func__, remote_addr.ToString().c_str());
+ BTA_DmDiscoverUUID(remote_addr, uuid, bte_dm_remote_service_record_evt, true);
return BT_STATUS_SUCCESS;
}
@@ -2525,7 +2517,7 @@
btif_in_execute_service_request(*((tBTA_SERVICE_ID*)p_param), b_enable);
if (status == BT_STATUS_SUCCESS) {
bt_property_t property;
- bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS];
+ Uuid local_uuids[BT_MAX_NUM_UUIDS];
/* Now send the UUID_PROPERTY_CHANGED event to the upper layer */
BTIF_STORAGE_FILL_PROPERTY(&property, BT_PROPERTY_UUIDS,
@@ -2693,17 +2685,17 @@
*
******************************************************************************/
bool btif_dm_get_smp_config(tBTE_APPL_CFG* p_cfg) {
- if (!stack_config_get_interface()->get_pts_smp_options()) {
+ const std::string* recv = stack_config_get_interface()->get_pts_smp_options();
+ if (!recv) {
BTIF_TRACE_DEBUG("%s: SMP options not found in configuration", __func__);
return false;
}
char conf[64];
- const char* recv = stack_config_get_interface()->get_pts_smp_options();
char* pch;
char* endptr;
- strncpy(conf, recv, 64);
+ strncpy(conf, recv->c_str(), 64);
conf[63] = 0; // null terminate
pch = strtok(conf, ",");
@@ -2819,7 +2811,7 @@
/* Clear OOB data */
memset(&oob_cb, 0, sizeof(oob_cb));
- if ((p_auth_cmpl->success == true) && (p_auth_cmpl->key_present)) {
+ if ((p_auth_cmpl->success) && (p_auth_cmpl->key_present)) {
/* store keys */
}
if (p_auth_cmpl->success) {
@@ -2840,7 +2832,7 @@
} else {
btif_dm_save_ble_bonding_keys();
BTA_GATTC_Refresh(bd_addr);
- btif_dm_get_remote_services_by_transport(&bd_addr, BTA_GATT_TRANSPORT_LE);
+ btif_dm_get_remote_services_by_transport(&bd_addr, GATT_TRANSPORT_LE);
}
} else {
/*Map the HCI fail reason to bt status */
@@ -2913,33 +2905,33 @@
RawAddress bd_addr = pairing_cb.bd_addr;
if (pairing_cb.ble.is_penc_key_rcvd) {
- btif_storage_add_ble_bonding_key(&bd_addr, (char*)&pairing_cb.ble.penc_key,
- BTIF_DM_LE_KEY_PENC,
- sizeof(tBTM_LE_PENC_KEYS));
+ btif_storage_add_ble_bonding_key(
+ &bd_addr, (uint8_t*)&pairing_cb.ble.penc_key, BTIF_DM_LE_KEY_PENC,
+ sizeof(tBTM_LE_PENC_KEYS));
}
if (pairing_cb.ble.is_pid_key_rcvd) {
- btif_storage_add_ble_bonding_key(&bd_addr, (char*)&pairing_cb.ble.pid_key,
- BTIF_DM_LE_KEY_PID,
- sizeof(tBTM_LE_PID_KEYS));
+ btif_storage_add_ble_bonding_key(
+ &bd_addr, (uint8_t*)&pairing_cb.ble.pid_key, BTIF_DM_LE_KEY_PID,
+ sizeof(tBTM_LE_PID_KEYS));
}
if (pairing_cb.ble.is_pcsrk_key_rcvd) {
- btif_storage_add_ble_bonding_key(&bd_addr, (char*)&pairing_cb.ble.pcsrk_key,
- BTIF_DM_LE_KEY_PCSRK,
- sizeof(tBTM_LE_PCSRK_KEYS));
+ btif_storage_add_ble_bonding_key(
+ &bd_addr, (uint8_t*)&pairing_cb.ble.pcsrk_key, BTIF_DM_LE_KEY_PCSRK,
+ sizeof(tBTM_LE_PCSRK_KEYS));
}
if (pairing_cb.ble.is_lenc_key_rcvd) {
- btif_storage_add_ble_bonding_key(&bd_addr, (char*)&pairing_cb.ble.lenc_key,
- BTIF_DM_LE_KEY_LENC,
- sizeof(tBTM_LE_LENC_KEYS));
+ btif_storage_add_ble_bonding_key(
+ &bd_addr, (uint8_t*)&pairing_cb.ble.lenc_key, BTIF_DM_LE_KEY_LENC,
+ sizeof(tBTM_LE_LENC_KEYS));
}
if (pairing_cb.ble.is_lcsrk_key_rcvd) {
- btif_storage_add_ble_bonding_key(&bd_addr, (char*)&pairing_cb.ble.lcsrk_key,
- BTIF_DM_LE_KEY_LCSRK,
- sizeof(tBTM_LE_LCSRK_KEYS));
+ btif_storage_add_ble_bonding_key(
+ &bd_addr, (uint8_t*)&pairing_cb.ble.lcsrk_key, BTIF_DM_LE_KEY_LCSRK,
+ sizeof(tBTM_LE_LCSRK_KEYS));
}
if (pairing_cb.ble.is_lidk_key_rcvd) {
@@ -3159,7 +3151,7 @@
BTM_BleReceiverTest(buf[0], btif_dm_ble_rx_test_cback);
break;
case HCI_BLE_TEST_END:
- BTM_BleTestEnd((tBTM_CMPL_CB*)btif_dm_ble_test_end_cback);
+ BTM_BleTestEnd(btif_dm_ble_test_end_cback);
break;
default:
BTIF_TRACE_ERROR("%s: Unknown LE Test Mode Command 0x%x", __func__,
diff --git a/btif/src/btif_gatt.cc b/btif/src/btif_gatt.cc
index 67296f9..b4d0b10 100644
--- a/btif/src/btif_gatt.cc
+++ b/btif/src/btif_gatt.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/src/btif_gatt_client.cc b/btif/src/btif_gatt_client.cc
index 262234b..0e06bbb 100644
--- a/btif/src/btif_gatt_client.cc
+++ b/btif/src/btif_gatt_client.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2014 Broadcom Corporation
+ * Copyright 2009-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,6 +53,7 @@
using base::Bind;
using base::Owned;
+using bluetooth::Uuid;
using std::vector;
extern bt_status_t btif_gattc_test_command_impl(
@@ -127,7 +128,7 @@
HAL_CBACK(bt_gatt_callbacks, client->notify_cb, p_data->notify.conn_id,
data);
- if (p_data->notify.is_notify == false)
+ if (!p_data->notify.is_notify)
BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.handle);
break;
@@ -144,7 +145,7 @@
p_data->open.conn_id, p_data->open.status, p_data->open.mtu);
}
- if (p_data->open.status == BTA_GATT_OK)
+ if (p_data->open.status == GATT_SUCCESS)
btif_gatt_check_encrypted_link(p_data->open.remote_bda,
p_data->open.transport);
break;
@@ -203,7 +204,9 @@
ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
}
-void btm_read_rssi_cb(tBTM_RSSI_RESULT* p_result) {
+void btm_read_rssi_cb(void* p_void) {
+ tBTM_RSSI_RESULT* p_result = (tBTM_RSSI_RESULT*)p_void;
+
if (!p_result) return;
CLI_CBACK_IN_JNI(read_remote_rssi_cb, rssi_request_client_if,
@@ -214,30 +217,25 @@
* Client API Functions
******************************************************************************/
-bt_status_t btif_gattc_register_app(const bt_uuid_t& uuid) {
+bt_status_t btif_gattc_register_app(const Uuid& uuid) {
CHECK_BTGATT_INIT();
- tBT_UUID bt_uuid;
- btif_to_bta_uuid(&bt_uuid, &uuid);
-
return do_in_jni_thread(Bind(
- [](tBT_UUID bt_uuid) {
+ [](const Uuid& uuid) {
BTA_GATTC_AppRegister(
bta_gattc_cback,
base::Bind(
- [](tBT_UUID bt_uuid, uint8_t client_id, uint8_t status) {
+ [](const Uuid& uuid, uint8_t client_id, uint8_t status) {
do_in_jni_thread(Bind(
- [](tBT_UUID bt_uuid, uint8_t client_id, uint8_t status) {
- bt_uuid_t app_uuid;
- bta_to_btif_uuid(&app_uuid, &bt_uuid);
+ [](const Uuid& uuid, uint8_t client_id, uint8_t status) {
HAL_CBACK(bt_gatt_callbacks, client->register_client_cb,
- status, client_id, app_uuid);
+ status, client_id, uuid);
},
- bt_uuid, client_id, status));
+ uuid, client_id, status));
},
- bt_uuid));
+ uuid));
},
- bt_uuid));
+ uuid));
}
void btif_gattc_unregister_app_impl(int client_if) {
@@ -255,7 +253,7 @@
// Ensure device is in inquiry database
int addr_type = 0;
int device_type = 0;
- tBTA_GATT_TRANSPORT transport = (tBTA_GATT_TRANSPORT)BTA_GATT_TRANSPORT_LE;
+ tGATT_TRANSPORT transport = (tGATT_TRANSPORT)GATT_TRANSPORT_LE;
if (btif_get_address_type(address, &addr_type) &&
btif_get_device_type(address, &device_type) &&
@@ -287,18 +285,18 @@
} else {
switch (device_type) {
case BT_DEVICE_TYPE_BREDR:
- transport = BTA_GATT_TRANSPORT_BR_EDR;
+ transport = GATT_TRANSPORT_BR_EDR;
break;
case BT_DEVICE_TYPE_BLE:
- transport = BTA_GATT_TRANSPORT_LE;
+ transport = GATT_TRANSPORT_LE;
break;
case BT_DEVICE_TYPE_DUMO:
if (transport_p == GATT_TRANSPORT_LE)
- transport = BTA_GATT_TRANSPORT_LE;
+ transport = GATT_TRANSPORT_LE;
else
- transport = BTA_GATT_TRANSPORT_BR_EDR;
+ transport = GATT_TRANSPORT_BR_EDR;
break;
}
}
@@ -343,13 +341,11 @@
return do_in_jni_thread(Bind(&BTA_GATTC_Refresh, bd_addr));
}
-bt_status_t btif_gattc_search_service(int conn_id,
- const bt_uuid_t* filter_uuid) {
+bt_status_t btif_gattc_search_service(int conn_id, const Uuid* filter_uuid) {
CHECK_BTGATT_INIT();
if (filter_uuid) {
- tBT_UUID* uuid = new tBT_UUID;
- btif_to_bta_uuid(uuid, filter_uuid);
+ Uuid* uuid = new Uuid(*filter_uuid);
return do_in_jni_thread(
Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, base::Owned(uuid)));
} else {
@@ -358,11 +354,8 @@
}
}
-void btif_gattc_discover_service_by_uuid(int conn_id, const bt_uuid_t& p_uuid) {
- tBT_UUID* uuid = new tBT_UUID;
- btif_to_bta_uuid(uuid, &p_uuid);
- do_in_jni_thread(
- Bind(&BTA_GATTC_DiscoverServiceByUuid, conn_id, base::Owned(uuid)));
+void btif_gattc_discover_service_by_uuid(int conn_id, const Uuid& uuid) {
+ do_in_jni_thread(Bind(&BTA_GATTC_DiscoverServiceByUuid, conn_id, uuid));
}
void btif_gattc_get_gatt_db_impl(int conn_id) {
@@ -418,13 +411,11 @@
base::Owned(params));
}
-bt_status_t btif_gattc_read_using_char_uuid(int conn_id, const bt_uuid_t& uuid,
+bt_status_t btif_gattc_read_using_char_uuid(int conn_id, const Uuid& uuid,
uint16_t s_handle,
uint16_t e_handle, int auth_req) {
CHECK_BTGATT_INIT();
- tBT_UUID bt_uuid;
- btif_to_bta_uuid(&bt_uuid, &uuid);
- return do_in_jni_thread(Bind(&BTA_GATTC_ReadUsingCharUuid, conn_id, bt_uuid,
+ return do_in_jni_thread(Bind(&BTA_GATTC_ReadUsingCharUuid, conn_id, uuid,
s_handle, e_handle, auth_req,
read_using_char_uuid_cb, nullptr));
}
@@ -487,10 +478,10 @@
Bind(&BTA_GATTC_ExecuteWrite, conn_id, (uint8_t)execute));
}
-void btif_gattc_reg_for_notification_impl(tBTA_GATTC_IF client_if,
+void btif_gattc_reg_for_notification_impl(tGATT_IF client_if,
const RawAddress& bda,
uint16_t handle) {
- tBTA_GATT_STATUS status =
+ tGATT_STATUS status =
BTA_GATTC_RegisterForNotifications(client_if, bda, handle);
// TODO(jpawlowski): conn_id is currently unused
@@ -508,10 +499,10 @@
bd_addr, handle));
}
-void btif_gattc_dereg_for_notification_impl(tBTA_GATTC_IF client_if,
+void btif_gattc_dereg_for_notification_impl(tGATT_IF client_if,
const RawAddress& bda,
uint16_t handle) {
- tBTA_GATT_STATUS status =
+ tGATT_STATUS status =
BTA_GATTC_DeregisterForNotifications(client_if, bda, handle);
// TODO(jpawlowski): conn_id is currently unused
@@ -534,8 +525,8 @@
CHECK_BTGATT_INIT();
rssi_request_client_if = client_if;
- return do_in_jni_thread(Bind(base::IgnoreResult(&BTM_ReadRSSI), bd_addr,
- (tBTM_CMPL_CB*)btm_read_rssi_cb));
+ return do_in_jni_thread(
+ Bind(base::IgnoreResult(&BTM_ReadRSSI), bd_addr, btm_read_rssi_cb));
}
bt_status_t btif_gattc_configure_mtu(int conn_id, int mtu) {
@@ -546,10 +537,11 @@
void btif_gattc_conn_parameter_update_impl(RawAddress addr, int min_interval,
int max_interval, int latency,
- int timeout) {
+ int timeout, uint16_t min_ce_len,
+ uint16_t max_ce_len) {
if (BTA_DmGetConnectionState(addr))
BTA_DmBleUpdateConnectionParams(addr, min_interval, max_interval, latency,
- timeout);
+ timeout, min_ce_len, max_ce_len);
else
BTA_DmSetBlePrefConnParams(addr, min_interval, max_interval, latency,
timeout);
@@ -557,11 +549,13 @@
bt_status_t btif_gattc_conn_parameter_update(const RawAddress& bd_addr,
int min_interval, int max_interval,
- int latency, int timeout) {
+ int latency, int timeout,
+ uint16_t min_ce_len,
+ uint16_t max_ce_len) {
CHECK_BTGATT_INIT();
- return do_in_jni_thread(
- Bind(base::IgnoreResult(&btif_gattc_conn_parameter_update_impl), bd_addr,
- min_interval, max_interval, latency, timeout));
+ return do_in_jni_thread(Bind(
+ base::IgnoreResult(&btif_gattc_conn_parameter_update_impl), bd_addr,
+ min_interval, max_interval, latency, timeout, min_ce_len, max_ce_len));
}
bt_status_t btif_gattc_set_preferred_phy(const RawAddress& bd_addr,
diff --git a/btif/src/btif_gatt_server.cc b/btif/src/btif_gatt_server.cc
index bd3a94ce..b7fdc8c 100644
--- a/btif/src/btif_gatt_server.cc
+++ b/btif/src/btif_gatt_server.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,6 +51,7 @@
using base::Bind;
using base::Owned;
+using bluetooth::Uuid;
using std::vector;
/*******************************************************************************
@@ -96,9 +97,9 @@
case BTA_GATTS_EXEC_WRITE_EVT:
case BTA_GATTS_MTU_EVT:
p_dest_data->req_data.p_data =
- (tBTA_GATTS_REQ_DATA*)osi_malloc(sizeof(tBTA_GATTS_REQ_DATA));
+ (tGATTS_DATA*)osi_malloc(sizeof(tGATTS_DATA));
memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
- sizeof(tBTA_GATTS_REQ_DATA));
+ sizeof(tGATTS_DATA));
break;
default:
@@ -128,10 +129,9 @@
tBTA_GATTS* p_data = (tBTA_GATTS*)p_param;
switch (event) {
case BTA_GATTS_REG_EVT: {
- bt_uuid_t app_uuid;
- bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.uuid);
HAL_CBACK(bt_gatt_callbacks, server->register_server_cb,
- p_data->reg_oper.status, p_data->reg_oper.server_if, app_uuid);
+ p_data->reg_oper.status, p_data->reg_oper.server_if,
+ p_data->reg_oper.uuid);
break;
}
@@ -266,13 +266,11 @@
/*******************************************************************************
* Server API Functions
******************************************************************************/
-static bt_status_t btif_gatts_register_app(const bt_uuid_t& bt_uuid) {
+static bt_status_t btif_gatts_register_app(const Uuid& bt_uuid) {
CHECK_BTGATT_INIT();
- tBT_UUID* uuid = new tBT_UUID;
- btif_to_bta_uuid(uuid, &bt_uuid);
return do_in_jni_thread(
- Bind(&BTA_GATTS_AppRegister, base::Owned(uuid), &btapp_gatts_cback));
+ Bind(&BTA_GATTS_AppRegister, bt_uuid, &btapp_gatts_cback));
}
static bt_status_t btif_gatts_unregister_app(int server_if) {
@@ -285,7 +283,7 @@
// Ensure device is in inquiry database
int addr_type = 0;
int device_type = 0;
- tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
+ tGATT_TRANSPORT transport = GATT_TRANSPORT_LE;
if (btif_get_address_type(address, &addr_type) &&
btif_get_device_type(address, &device_type) &&
@@ -302,18 +300,18 @@
} else {
switch (device_type) {
case BT_DEVICE_TYPE_BREDR:
- transport = BTA_GATT_TRANSPORT_BR_EDR;
+ transport = GATT_TRANSPORT_BR_EDR;
break;
case BT_DEVICE_TYPE_BLE:
- transport = BTA_GATT_TRANSPORT_LE;
+ transport = GATT_TRANSPORT_LE;
break;
case BT_DEVICE_TYPE_DUMO:
if (transport_param == GATT_TRANSPORT_LE)
- transport = BTA_GATT_TRANSPORT_LE;
+ transport = GATT_TRANSPORT_LE;
else
- transport = BTA_GATT_TRANSPORT_BR_EDR;
+ transport = GATT_TRANSPORT_BR_EDR;
break;
}
}
@@ -348,33 +346,35 @@
Bind(&btif_gatts_close_impl, server_if, bd_addr, conn_id));
}
+static void on_service_added_cb(uint8_t status, int server_if,
+ vector<btgatt_db_element_t> service) {
+ HAL_CBACK(bt_gatt_callbacks, server->service_added_cb, status, server_if,
+ std::move(service));
+}
+
static void add_service_impl(int server_if,
vector<btgatt_db_element_t> service) {
- bt_uuid_t restricted_uuid1, restricted_uuid2;
- uuid_128_from_16(&restricted_uuid1, UUID_SERVCLASS_GATT_SERVER);
- uuid_128_from_16(&restricted_uuid2, UUID_SERVCLASS_GAP_SERVER);
-
// TODO(jpawlowski): btif should be a pass through layer, and no checks should
// be made here. This exception is added only until GATT server code is
// refactored, and one can distinguish stack-internal aps from external apps
- if (memcmp(&service[0].uuid, &restricted_uuid1, sizeof(bt_uuid_t)) == 0 ||
- memcmp(&service[0].uuid, &restricted_uuid2, sizeof(bt_uuid_t)) == 0) {
+ if (service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER) ||
+ service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) {
LOG_ERROR(LOG_TAG, "%s: Attept to register restricted service", __func__);
HAL_CBACK(bt_gatt_callbacks, server->service_added_cb, BT_STATUS_FAIL,
server_if, std::move(service));
return;
}
- int status = BTA_GATTS_AddService(server_if, service);
- HAL_CBACK(bt_gatt_callbacks, server->service_added_cb, status, server_if,
- std::move(service));
+ BTA_GATTS_AddService(
+ server_if, service,
+ jni_thread_wrapper(FROM_HERE, base::Bind(&on_service_added_cb)));
}
static bt_status_t btif_gatts_add_service(int server_if,
vector<btgatt_db_element_t> service) {
CHECK_BTGATT_INIT();
return do_in_jni_thread(
- Bind(&add_service_impl, server_if, std::move(service)));
+ FROM_HERE, Bind(&add_service_impl, server_if, std::move(service)));
}
static bt_status_t btif_gatts_stop_service(int server_if, int service_handle) {
@@ -404,7 +404,7 @@
static void btif_gatts_send_response_impl(int conn_id, int trans_id, int status,
btgatt_response_t response) {
- tBTA_GATTS_RSP rsp_struct;
+ tGATTS_RSP rsp_struct;
btif_to_bta_response(&rsp_struct, &response);
BTA_GATTS_SendRsp(conn_id, trans_id, status, &rsp_struct);
diff --git a/btif/src/btif_gatt_test.cc b/btif/src/btif_gatt_test.cc
index 4312533..1297d50 100644
--- a/btif/src/btif_gatt_test.cc
+++ b/btif/src/btif_gatt_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@
#include "osi/include/log.h"
#include "osi/include/osi.h"
+using bluetooth::Uuid;
/*******************************************************************************
* Typedefs & Macros
******************************************************************************/
@@ -65,27 +66,6 @@
* Callback functions
******************************************************************************/
-static char* format_uuid(tBT_UUID bt_uuid, char* str_buf, size_t buf_size) {
- if (bt_uuid.len == LEN_UUID_16) {
- snprintf(str_buf, buf_size, "0x%04x", bt_uuid.uu.uuid16);
- } else if (bt_uuid.len == LEN_UUID_128) {
- int x = snprintf(str_buf, buf_size, "%02x%02x%02x%02x-%02x%02x-%02x%02x",
- bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14],
- bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12],
- bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10],
- bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]);
- snprintf(&str_buf[x], buf_size - x, "%02x%02x-%02x%02x%02x%02x%02x%02x",
- bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6],
- bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4],
- bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2],
- bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]);
- } else {
- snprintf(str_buf, buf_size, "Unknown (len=%d)", bt_uuid.len);
- }
-
- return str_buf;
-}
-
static void btif_test_connect_cback(tGATT_IF, const RawAddress&,
uint16_t conn_id, bool connected,
tGATT_DISCONN_REASON, tBT_TRANSPORT) {
@@ -121,8 +101,6 @@
static void btif_test_discovery_result_cback(UNUSED_ATTR uint16_t conn_id,
tGATT_DISC_TYPE disc_type,
tGATT_DISC_RES* p_data) {
- char str_buf[50];
-
LOG_DEBUG(LOG_TAG, "------ GATT Discovery result %-22s -------",
disc_name[disc_type]);
LOG_DEBUG(LOG_TAG, " Attribute handle: 0x%04x (%d)", p_data->handle,
@@ -130,7 +108,7 @@
if (disc_type != GATT_DISC_CHAR_DSCPT) {
LOG_DEBUG(LOG_TAG, " Attribute type: %s",
- format_uuid(p_data->type, str_buf, sizeof(str_buf)));
+ p_data->type.ToString().c_str());
}
switch (disc_type) {
@@ -139,8 +117,7 @@
p_data->handle, p_data->value.group_value.e_handle,
p_data->handle, p_data->value.group_value.e_handle);
LOG_DEBUG(LOG_TAG, " Service UUID: %s",
- format_uuid(p_data->value.group_value.service_type, str_buf,
- sizeof(str_buf)));
+ p_data->value.group_value.service_type.ToString().c_str());
break;
case GATT_DISC_SRVC_BY_UUID:
@@ -156,21 +133,19 @@
p_data->value.incl_service.s_handle,
p_data->value.incl_service.e_handle);
LOG_DEBUG(LOG_TAG, " Service UUID: %s",
- format_uuid(p_data->value.incl_service.service_type, str_buf,
- sizeof(str_buf)));
+ p_data->value.incl_service.service_type.ToString().c_str());
break;
case GATT_DISC_CHAR:
LOG_DEBUG(LOG_TAG, " Properties: 0x%02x",
p_data->value.dclr_value.char_prop);
LOG_DEBUG(LOG_TAG, " Characteristic UUID: %s",
- format_uuid(p_data->value.dclr_value.char_uuid, str_buf,
- sizeof(str_buf)));
+ p_data->value.dclr_value.char_uuid.ToString().c_str());
break;
case GATT_DISC_CHAR_DSCPT:
LOG_DEBUG(LOG_TAG, " Descriptor UUID: %s",
- format_uuid(p_data->type, str_buf, sizeof(str_buf)));
+ p_data->type.ToString().c_str());
break;
}
@@ -205,8 +180,10 @@
{
LOG_DEBUG(LOG_TAG, "%s: ENABLE - enable=%d", __func__, params->u1);
if (params->u1) {
- tBT_UUID app_uuid = {LEN_UUID_128, {0xAE}};
- test_cb.gatt_if = GATT_Register(&app_uuid, &btif_test_callbacks);
+ std::array<uint8_t, Uuid::kNumBytes128> tmp;
+ tmp.fill(0xAE);
+ test_cb.gatt_if = GATT_Register(bluetooth::Uuid::From128BitBE(tmp),
+ &btif_test_callbacks);
GATT_StartIf(test_cb.gatt_if);
} else {
GATT_Deregister(test_cb.gatt_if);
@@ -217,12 +194,8 @@
case 0x02: /* Connect */
{
- LOG_DEBUG(LOG_TAG,
- "%s: CONNECT - device=%02x:%02x:%02x:%02x:%02x:%02x "
- "(dev_type=%d, addr_type=%d)",
- __func__, params->bda1->address[0], params->bda1->address[1],
- params->bda1->address[2], params->bda1->address[3],
- params->bda1->address[4], params->bda1->address[5], params->u1,
+ LOG_DEBUG(LOG_TAG, "%s: CONNECT - device=%s (dev_type=%d, addr_type=%d)",
+ __func__, params->bda1->ToString().c_str(), params->u1,
params->u2);
if (params->u1 == BT_DEVICE_TYPE_BLE)
@@ -246,7 +219,6 @@
case 0x04: /* Discover */
{
- char buf[50] = {0};
tGATT_DISC_PARAM param;
memset(¶m, 0, sizeof(tGATT_DISC_PARAM));
@@ -258,13 +230,12 @@
param.s_handle = params->u2;
param.e_handle = params->u3;
- btif_to_bta_uuid(¶m.service, params->uuid1);
+ param.service = *params->uuid1;
LOG_DEBUG(LOG_TAG,
"%s: DISCOVER (%s), conn_id=%d, uuid=%s, handles=0x%04x-0x%04x",
__func__, disc_name[params->u1], test_cb.conn_id,
- format_uuid(param.service, buf, sizeof(buf)), params->u2,
- params->u3);
+ param.service.ToString().c_str(), params->u2, params->u3);
GATTC_Discover(test_cb.conn_id, params->u1, ¶m);
break;
}
diff --git a/btif/src/btif_gatt_util.cc b/btif/src/btif_gatt_util.cc
index 9745917..16f2275 100644
--- a/btif/src/btif_gatt_util.cc
+++ b/btif/src/btif_gatt_util.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,63 +40,12 @@
#include "btif_util.h"
#include "osi/include/osi.h"
-#define GATTC_READ_VALUE_TYPE_VALUE 0x0000 /* Attribute value itself */
-#define GATTC_READ_VALUE_TYPE_AGG_FORMAT \
- 0x2905 /* Characteristic Aggregate Format*/
-
-static unsigned char BASE_UUID[16] = {0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00,
- 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00};
-
-int uuidType(const unsigned char* p_uuid) {
- int i = 0;
- int match = 0;
- int all_zero = 1;
-
- for (i = 0; i != 16; ++i) {
- if (i == 12 || i == 13) continue;
-
- if (p_uuid[i] == BASE_UUID[i]) ++match;
-
- if (p_uuid[i] != 0) all_zero = 0;
- }
- if (all_zero) return 0;
- if (match == 12) return LEN_UUID_32;
- if (match == 14) return LEN_UUID_16;
- return LEN_UUID_128;
-}
+using bluetooth::Uuid;
/*******************************************************************************
* BTIF -> BTA conversion functions
******************************************************************************/
-
-void btif_to_bta_uuid(tBT_UUID* p_dest, const bt_uuid_t* p_src) {
- char* p_byte = (char*)p_src;
- int i = 0;
-
- p_dest->len = uuidType(p_src->uu);
-
- switch (p_dest->len) {
- case LEN_UUID_16:
- p_dest->uu.uuid16 = (p_src->uu[13] << 8) + p_src->uu[12];
- break;
-
- case LEN_UUID_32:
- p_dest->uu.uuid32 = (p_src->uu[13] << 8) + p_src->uu[12];
- p_dest->uu.uuid32 += (p_src->uu[15] << 24) + (p_src->uu[14] << 16);
- break;
-
- case LEN_UUID_128:
- for (i = 0; i != 16; ++i) p_dest->uu.uuid128[i] = p_byte[i];
- break;
-
- default:
- LOG_ERROR(LOG_TAG, "%s: Unknown UUID length %d!", __func__, p_dest->len);
- break;
- }
-}
-
-void btif_to_bta_response(tBTA_GATTS_RSP* p_dest, btgatt_response_t* p_src) {
+void btif_to_bta_response(tGATTS_RSP* p_dest, btgatt_response_t* p_src) {
p_dest->attr_value.auth_req = p_src->attr_value.auth_req;
p_dest->attr_value.handle = p_src->attr_value.handle;
p_dest->attr_value.len = p_src->attr_value.len;
@@ -104,108 +53,6 @@
memcpy(p_dest->attr_value.value, p_src->attr_value.value, GATT_MAX_ATTR_LEN);
}
-void btif_to_bta_uuid_mask(tBTM_BLE_PF_COND_MASK* p_mask,
- const bt_uuid_t* uuid_mask,
- const bt_uuid_t* svc_uuid) {
- char* p_byte = (char*)uuid_mask;
- int uuid_len = uuidType(svc_uuid->uu);
- int i = 0;
-
- switch (uuid_len) {
- case LEN_UUID_16:
- p_mask->uuid16_mask = (uuid_mask->uu[13] << 8) + uuid_mask->uu[12];
- break;
-
- case LEN_UUID_32:
- p_mask->uuid32_mask = (uuid_mask->uu[13] << 8) + uuid_mask->uu[12];
- p_mask->uuid32_mask +=
- (uuid_mask->uu[15] << 24) + (uuid_mask->uu[14] << 16);
- break;
-
- case LEN_UUID_128:
- for (i = 0; i != 16; ++i) p_mask->uuid128_mask[i] = p_byte[i];
- break;
-
- default:
- break;
- }
-}
-
-/*******************************************************************************
- * BTA -> BTIF conversion functions
- ******************************************************************************/
-
-void bta_to_btif_uuid(bt_uuid_t* p_dest, tBT_UUID* p_src) {
- int i = 0;
-
- if (p_src->len == LEN_UUID_16 || p_src->len == LEN_UUID_32) {
- for (i = 0; i != 16; ++i) p_dest->uu[i] = BASE_UUID[i];
- }
-
- switch (p_src->len) {
- case 0:
- break;
-
- case LEN_UUID_16:
- p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
- p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
- break;
-
- case LEN_UUID_32:
- p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
- p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
- p_dest->uu[14] = (p_src->uu.uuid32 >> 16) & 0xff;
- p_dest->uu[15] = (p_src->uu.uuid32 >> 24) & 0xff;
- break;
-
- case LEN_UUID_128:
- for (i = 0; i != 16; ++i) p_dest->uu[i] = p_src->uu.uuid128[i];
- break;
-
- default:
- LOG_ERROR(LOG_TAG, "%s: Unknown UUID length %d!", __func__, p_src->len);
- break;
- }
-}
-
-/*******************************************************************************
- * Utility functions
- ******************************************************************************/
-
-uint16_t get_uuid16(tBT_UUID* p_uuid) {
- if (p_uuid->len == LEN_UUID_16) {
- return p_uuid->uu.uuid16;
- } else if (p_uuid->len == LEN_UUID_128) {
- uint16_t u16;
- uint8_t* p = &p_uuid->uu.uuid128[LEN_UUID_128 - 4];
- STREAM_TO_UINT16(u16, p);
- return u16;
- } else /* p_uuid->len == LEN_UUID_32 */
- {
- return (uint16_t)p_uuid->uu.uuid32;
- }
-}
-
-uint16_t set_read_value(btgatt_read_params_t* p_dest, tBTA_GATTC_READ* p_src) {
- uint16_t len = 0;
-
- p_dest->status = p_src->status;
- p_dest->handle = p_src->handle;
-
- if ((p_src->status == BTA_GATT_OK) && (p_src->len != 0)) {
- LOG_INFO(LOG_TAG, "%s len = %d ", __func__, p_src->len);
- p_dest->value.len = p_src->len;
- memcpy(p_dest->value.value, p_src->value, p_src->len);
-
- len += p_src->len;
- } else {
- p_dest->value.len = 0;
- }
-
- p_dest->value_type = GATTC_READ_VALUE_TYPE_VALUE;
- return len;
-}
-
/*******************************************************************************
* Encrypted link map handling
******************************************************************************/
@@ -226,12 +73,11 @@
#if (BLE_DELAY_REQUEST_ENC == FALSE)
void btif_gatt_check_encrypted_link(RawAddress bd_addr,
- tBTA_GATT_TRANSPORT transport_link) {
- char buf[100];
-
- if ((btif_storage_get_ble_bonding_key(&bd_addr, BTIF_DM_LE_KEY_PENC, buf,
- sizeof(tBTM_LE_PENC_KEYS)) ==
- BT_STATUS_SUCCESS) &&
+ tGATT_TRANSPORT transport_link) {
+ tBTM_LE_PENC_KEYS key;
+ if ((btif_storage_get_ble_bonding_key(
+ &bd_addr, BTIF_DM_LE_KEY_PENC, (uint8_t*)&key,
+ sizeof(tBTM_LE_PENC_KEYS)) == BT_STATUS_SUCCESS) &&
!btif_gatt_is_link_encrypted(bd_addr)) {
BTIF_TRACE_DEBUG("%s: transport = %d", __func__, transport_link);
BTA_DmSetEncryption(bd_addr, transport_link, &btif_gatt_set_encryption_cb,
@@ -240,7 +86,7 @@
}
#else
void btif_gatt_check_encrypted_link(UNUSED_ATTR RawAddress bd_addr,
- UNUSED_ATTR tBTA_GATT_TRANSPORT
+ UNUSED_ATTR tGATT_TRANSPORT
transport_link) {}
#endif
diff --git a/btif/src/btif_hd.cc b/btif/src/btif_hd.cc
index eb3dbbb..bc0992d 100644
--- a/btif/src/btif_hd.cc
+++ b/btif/src/btif_hd.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/src/btif_hearing_aid.cc b/btif/src/btif_hearing_aid.cc
new file mode 100644
index 0000000..48aab95
--- /dev/null
+++ b/btif/src/btif_hearing_aid.cc
@@ -0,0 +1,133 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/* Hearing Aid Profile Interface */
+
+#include "bta_closure_api.h"
+#include "bta_hearing_aid_api.h"
+#include "btif_common.h"
+#include "btif_storage.h"
+
+#include <base/bind.h>
+#include <base/location.h>
+#include <base/logging.h>
+#include <hardware/bluetooth.h>
+#include <hardware/bt_hearing_aid.h>
+
+using base::Bind;
+using base::Unretained;
+using bluetooth::hearing_aid::ConnectionState;
+using bluetooth::hearing_aid::HearingAidCallbacks;
+using bluetooth::hearing_aid::HearingAidInterface;
+
+// template specialization
+template <>
+base::Callback<void()> jni_thread_wrapper(
+ const tracked_objects::Location& from_here, base::Callback<void()> cb) {
+ return base::Bind(
+ [](const tracked_objects::Location& from_here,
+ base::Callback<void()> cb) { do_in_jni_thread(from_here, cb); },
+ from_here, std::move(cb));
+}
+
+namespace {
+class HearingAidInterfaceImpl;
+std::unique_ptr<HearingAidInterface> hearingAidInstance;
+
+class HearingAidInterfaceImpl
+ : public bluetooth::hearing_aid::HearingAidInterface,
+ public HearingAidCallbacks {
+ ~HearingAidInterfaceImpl() = default;
+
+ void Init(HearingAidCallbacks* callbacks) {
+ DVLOG(2) << __func__;
+ this->callbacks = callbacks;
+ do_in_bta_thread(
+ FROM_HERE,
+ Bind(&HearingAid::Initialize, this,
+ jni_thread_wrapper(FROM_HERE,
+ Bind(&btif_storage_load_bonded_hearing_aids))));
+ }
+
+ void OnConnectionState(ConnectionState state,
+ const RawAddress& address) override {
+ DVLOG(2) << __func__ << " address: " << address;
+ do_in_jni_thread(FROM_HERE, Bind(&HearingAidCallbacks::OnConnectionState,
+ Unretained(callbacks), state, address));
+ }
+
+ void OnDeviceAvailable(uint8_t capabilities, uint64_t hiSyncId,
+ const RawAddress& address) override {
+ DVLOG(2) << __func__ << " address: " << address
+ << ", hiSyncId: " << loghex(hiSyncId)
+ << ", capabilities: " << loghex(capabilities);
+ do_in_jni_thread(FROM_HERE, Bind(&HearingAidCallbacks::OnDeviceAvailable,
+ Unretained(callbacks), capabilities,
+ hiSyncId, address));
+ }
+
+ void Connect(const RawAddress& address) override {
+ DVLOG(2) << __func__ << " address: " << address;
+ do_in_bta_thread(FROM_HERE, Bind(&HearingAid::Connect,
+ Unretained(HearingAid::Get()), address));
+ }
+
+ void Disconnect(const RawAddress& address) override {
+ DVLOG(2) << __func__ << " address: " << address;
+ do_in_bta_thread(FROM_HERE, Bind(&HearingAid::Disconnect,
+ Unretained(HearingAid::Get()), address));
+ do_in_jni_thread(
+ FROM_HERE, Bind(&btif_storage_remove_hearing_aid_white_list, address));
+ }
+
+ void SetVolume(int8_t volume) override {
+ DVLOG(2) << __func__ << " volume: " << +volume;
+ do_in_bta_thread(FROM_HERE, Bind(&HearingAid::SetVolume,
+ Unretained(HearingAid::Get()), volume));
+ }
+
+ void RemoveDevice(const RawAddress& address) override {
+ DVLOG(2) << __func__ << " address: " << address;
+
+ // RemoveDevice can be called on devices that don't have HA enabled
+ if (HearingAid::IsInitialized()) {
+ do_in_bta_thread(FROM_HERE, Bind(&HearingAid::Disconnect,
+ Unretained(HearingAid::Get()), address));
+ }
+
+ do_in_jni_thread(FROM_HERE,
+ Bind(&btif_storage_remove_hearing_aid, address));
+ }
+
+ void Cleanup(void) {
+ DVLOG(2) << __func__;
+ do_in_bta_thread(FROM_HERE, Bind(&HearingAid::CleanUp));
+ }
+
+ private:
+ HearingAidCallbacks* callbacks;
+};
+
+} // namespace
+
+HearingAidInterface* btif_hearing_aid_get_interface() {
+ if (!hearingAidInstance)
+ hearingAidInstance.reset(new HearingAidInterfaceImpl());
+
+ return hearingAidInstance.get();
+}
diff --git a/btif/src/btif_hf.cc b/btif/src/btif_hf.cc
index 9ec6da8..37f9471 100644
--- a/btif/src/btif_hf.cc
+++ b/btif/src/btif_hf.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,11 +27,14 @@
#define LOG_TAG "bt_btif_hf"
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <bta/include/bta_ag_api.h>
#include <hardware/bluetooth.h>
+#include <hardware/bluetooth_headset_callbacks.h>
+#include <hardware/bluetooth_headset_interface.h>
#include <hardware/bt_hf.h>
#include "bta/include/utl.h"
@@ -40,7 +43,10 @@
#include "btif_hf.h"
#include "btif_profile_queue.h"
#include "btif_util.h"
-#include "osi/include/properties.h"
+#include "osi/include/metrics.h"
+
+namespace bluetooth {
+namespace headset {
/*******************************************************************************
* Constants & Macros
@@ -77,74 +83,41 @@
/* HF features supported at runtime */
static uint32_t btif_hf_features = BTIF_HF_FEATURES;
-#define BTIF_HF_CALL_END_TIMEOUT 6
-
#define BTIF_HF_INVALID_IDX (-1)
-/* Number of BTIF-HF control blocks */
-#define BTIF_HF_NUM_CB 2
-
/* Max HF clients supported from App */
-uint16_t btif_max_hf_clients = 1;
-
-/* HF app ids for service registration */
-typedef enum {
- BTIF_HF_ID_1 = 0,
- BTIF_HF_ID_2,
-#if (BTIF_HF_NUM_CB == 3)
- BTIF_HF_ID_3
-#endif
-} bthf_hf_id_t;
-
-uint16_t bthf_hf_id[BTIF_HF_NUM_CB] = {BTIF_HF_ID_1, BTIF_HF_ID_2,
-#if (BTIF_HF_NUM_CB == 3)
- BTIF_HF_ID_3
-#endif
-};
-
-/*******************************************************************************
- * Local type definitions
- ******************************************************************************/
+static int btif_max_hf_clients = 1;
+static RawAddress active_bda = {};
/*******************************************************************************
* Static variables
******************************************************************************/
-static bthf_callbacks_t* bt_hf_callbacks = NULL;
-static int hf_idx = BTIF_HF_INVALID_IDX;
+static Callbacks* bt_hf_callbacks = nullptr;
#define CHECK_BTHF_INIT() \
do { \
- if (bt_hf_callbacks == NULL) { \
+ if (!bt_hf_callbacks) { \
BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __func__); \
return BT_STATUS_NOT_READY; \
} else { \
BTIF_TRACE_EVENT("BTHF: %s", __func__); \
} \
- } while (0)
+ } while (false)
/* BTIF-HF control block to map bdaddr to BTA handle */
-typedef struct _btif_hf_cb {
+struct btif_hf_cb_t {
uint16_t handle;
+ bool is_initiator;
RawAddress connected_bda;
bthf_connection_state_t state;
- bthf_vr_state_t vr_state;
tBTA_AG_PEER_FEAT peer_feat;
int num_active;
int num_held;
- struct timespec call_end_timestamp;
- struct timespec connected_timestamp;
bthf_call_state_t call_setup_state;
-} btif_hf_cb_t;
+};
-static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB];
+static btif_hf_cb_t btif_hf_cb[BTA_AG_MAX_NUM_CLIENTS];
-/*******************************************************************************
- * Static functions
- ******************************************************************************/
-
-/*******************************************************************************
- * Externs
- ******************************************************************************/
/* By default, even though codec negotiation is enabled, we will not use WBS as
* the default
* codec unless this variable is set to true.
@@ -153,24 +126,47 @@
#define BTIF_HF_WBS_PREFERRED false
#endif
-bool btif_conf_hf_force_wbs = BTIF_HF_WBS_PREFERRED;
+static bool btif_conf_hf_force_wbs = BTIF_HF_WBS_PREFERRED;
-/*******************************************************************************
- * Functions
- ******************************************************************************/
+static const char* dump_hf_call_state(bthf_call_state_t call_state) {
+ switch (call_state) {
+ CASE_RETURN_STR(BTHF_CALL_STATE_IDLE)
+ CASE_RETURN_STR(BTHF_CALL_STATE_HELD)
+ CASE_RETURN_STR(BTHF_CALL_STATE_DIALING)
+ CASE_RETURN_STR(BTHF_CALL_STATE_ALERTING)
+ CASE_RETURN_STR(BTHF_CALL_STATE_INCOMING)
+ CASE_RETURN_STR(BTHF_CALL_STATE_WAITING)
+ CASE_RETURN_STR(BTHF_CALL_STATE_ACTIVE)
+ CASE_RETURN_STR(BTHF_CALL_STATE_DISCONNECTED)
+ default:
+ return "UNKNOWN CALL STATE";
+ }
+}
+
+/**
+ * Check if bd_addr is the current active device.
+ *
+ * @param bd_addr target device address
+ * @return True if bd_addr is the current active device, False otherwise or if
+ * no active device is set (i.e. active_device_addr is empty)
+ */
+static bool is_active_device(const RawAddress& bd_addr) {
+ return !active_bda.IsEmpty() && active_bda == bd_addr;
+}
/*******************************************************************************
*
* Function is_connected
*
* Description Internal function to check if HF is connected
+ * is_connected(nullptr) returns TRUE if one of the control
+ * blocks is connected
*
* Returns true if connected
*
******************************************************************************/
static bool is_connected(RawAddress* bd_addr) {
- int i;
- for (i = 0; i < btif_max_hf_clients; ++i) {
+ for (int i = 0; i < btif_max_hf_clients; ++i) {
if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
(btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) &&
(!bd_addr || *bd_addr == btif_hf_cb[i].connected_bda))
@@ -189,8 +185,7 @@
*
******************************************************************************/
static int btif_hf_idx_by_bdaddr(RawAddress* bd_addr) {
- int i;
- for (i = 0; i < btif_max_hf_clients; ++i) {
+ for (int i = 0; i < btif_max_hf_clients; ++i) {
if (*bd_addr == btif_hf_cb[i].connected_bda) return i;
}
return BTIF_HF_INVALID_IDX;
@@ -206,12 +201,16 @@
*
******************************************************************************/
static uint8_t callstate_to_callsetup(bthf_call_state_t call_state) {
- uint8_t call_setup = 0;
- if (call_state == BTHF_CALL_STATE_INCOMING) call_setup = 1;
- if (call_state == BTHF_CALL_STATE_DIALING) call_setup = 2;
- if (call_state == BTHF_CALL_STATE_ALERTING) call_setup = 3;
-
- return call_setup;
+ switch (call_state) {
+ case BTHF_CALL_STATE_INCOMING:
+ return 1;
+ case BTHF_CALL_STATE_DIALING:
+ return 2;
+ case BTHF_CALL_STATE_ALERTING:
+ return 3;
+ default:
+ return 0;
+ }
}
/*******************************************************************************
@@ -224,15 +223,12 @@
*
******************************************************************************/
static void send_at_result(uint8_t ok_flag, uint16_t errcode, int idx) {
- tBTA_AG_RES_DATA ag_res;
- memset(&ag_res, 0, sizeof(ag_res));
-
+ tBTA_AG_RES_DATA ag_res = {};
ag_res.ok_flag = ok_flag;
if (ok_flag == BTA_AG_OK_ERROR) {
ag_res.errcode = errcode;
}
-
- BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
+ BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, ag_res);
}
/*******************************************************************************
@@ -244,86 +240,52 @@
* Returns void
*
******************************************************************************/
-static void send_indicator_update(uint16_t indicator, uint16_t value) {
- tBTA_AG_RES_DATA ag_res;
-
- memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
+static void send_indicator_update(const btif_hf_cb_t& control_block,
+ uint16_t indicator, uint16_t value) {
+ tBTA_AG_RES_DATA ag_res = {};
ag_res.ind.id = indicator;
ag_res.ind.value = value;
-
- BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res);
+ BTA_AgResult(control_block.handle, BTA_AG_IND_RES, ag_res);
}
-void clear_phone_state_multihf(int idx) {
- btif_hf_cb[idx].call_setup_state = BTHF_CALL_STATE_IDLE;
- btif_hf_cb[idx].num_active = btif_hf_cb[idx].num_held = 0;
+static bool is_nth_bit_enabled(uint32_t value, int n) {
+ return (value & (static_cast<uint32_t>(1) << n)) != 0;
}
-/*******************************************************************************
- *
- * Function btif_hf_latest_connected_idx
- *
- * Description Returns idx for latest connected HF
- *
- * Returns int
- *
- ******************************************************************************/
-static int btif_hf_latest_connected_idx() {
- struct timespec now, conn_time_delta;
- int latest_conn_idx = BTIF_HF_INVALID_IDX, i;
+void clear_phone_state_multihf(btif_hf_cb_t* hf_cb) {
+ hf_cb->call_setup_state = BTHF_CALL_STATE_IDLE;
+ hf_cb->num_active = 0;
+ hf_cb->num_held = 0;
+}
- clock_gettime(CLOCK_MONOTONIC, &now);
- conn_time_delta.tv_sec = now.tv_sec;
+static void reset_control_block(btif_hf_cb_t* hf_cb) {
+ hf_cb->state = BTHF_CONNECTION_STATE_DISCONNECTED;
+ hf_cb->is_initiator = false;
+ hf_cb->connected_bda = RawAddress::kEmpty;
+ hf_cb->peer_feat = 0;
+ clear_phone_state_multihf(hf_cb);
+}
- for (i = 0; i < btif_max_hf_clients; i++) {
- if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
- if ((now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec) <
- conn_time_delta.tv_sec) {
- conn_time_delta.tv_sec =
- now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec;
- latest_conn_idx = i;
- }
- }
+/**
+ * Check if Service Level Connection (SLC) is established for bd_addr
+ *
+ * @param bd_addr remote device address
+ * @return true if SLC is established for bd_addr
+ */
+static bool IsSlcConnected(RawAddress* bd_addr) {
+ if (!bd_addr) {
+ LOG(WARNING) << __func__ << ": bd_addr is null";
+ return false;
}
- return latest_conn_idx;
-}
-
-/*******************************************************************************
- *
- * Function btif_hf_check_if_slc_connected
- *
- * Description Returns BT_STATUS_SUCCESS if SLC is up for any HF
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t btif_hf_check_if_slc_connected() {
- if (bt_hf_callbacks == NULL) {
- BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __func__);
- return BT_STATUS_NOT_READY;
- } else {
- int i;
- for (i = 0; i < btif_max_hf_clients; i++) {
- if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
- BTIF_TRACE_EVENT("BTHF: %s: slc connected for idx = %d", __func__, i);
- return BT_STATUS_SUCCESS;
- }
- }
- BTIF_TRACE_WARNING("BTHF: %s: No SLC connection up", __func__);
- return BT_STATUS_NOT_READY;
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+ if (idx < 0 || idx > BTA_AG_MAX_NUM_CLIENTS) {
+ LOG(WARNING) << __func__ << ": invalid index " << idx << " for "
+ << *bd_addr;
+ return false;
}
+ return btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_SLC_CONNECTED;
}
-/*****************************************************************************
- * Section name (Group of functions)
- ****************************************************************************/
-
-/*****************************************************************************
- *
- * btif hf api functions (no context switch)
- *
- ****************************************************************************/
-
/*******************************************************************************
*
* Function btif_hf_upstreams_evt
@@ -334,155 +296,159 @@
*
******************************************************************************/
static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
+ if (event == BTA_AG_ENABLE_EVT || event == BTA_AG_DISABLE_EVT) {
+ LOG(INFO) << __func__ << ": AG enable/disable event " << event;
+ return;
+ }
+ if (p_param == nullptr) {
+ LOG(ERROR) << __func__ << ": parameter is null";
+ return;
+ }
tBTA_AG* p_data = (tBTA_AG*)p_param;
int idx = p_data->hdr.handle - 1;
BTIF_TRACE_DEBUG("%s: event=%s", __func__, dump_hf_event(event));
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
return;
}
+ if (!bt_hf_callbacks) {
+ BTIF_TRACE_ERROR("%s: Headset callback is NULL", __func__);
+ return;
+ }
switch (event) {
- case BTA_AG_ENABLE_EVT:
- case BTA_AG_DISABLE_EVT:
- break;
-
case BTA_AG_REGISTER_EVT:
btif_hf_cb[idx].handle = p_data->reg.hdr.handle;
- BTIF_TRACE_DEBUG(
- "%s: BTA_AG_REGISTER_EVT,"
- "btif_hf_cb.handle = %d",
- __func__, btif_hf_cb[idx].handle);
+ BTIF_TRACE_DEBUG("%s: BTA_AG_REGISTER_EVT, btif_hf_cb.handle = %d",
+ __func__, btif_hf_cb[idx].handle);
break;
-
+ // RFCOMM connected or failed to connect
case BTA_AG_OPEN_EVT:
+ // Check if an outoging connection is pending
+ if (btif_hf_cb[idx].is_initiator) {
+ CHECK_EQ(btif_hf_cb[idx].state, BTHF_CONNECTION_STATE_CONNECTING)
+ << "Control block must be in connecting state when initiating";
+ CHECK(!btif_hf_cb[idx].connected_bda.IsEmpty())
+ << "Remote device address must not be empty when initiating";
+ CHECK_EQ(btif_hf_cb[idx].connected_bda, p_data->open.bd_addr)
+ << "Incoming message's address must match expected one";
+ }
if (p_data->open.status == BTA_AG_SUCCESS) {
+ // In case this is an incoming connection
btif_hf_cb[idx].connected_bda = p_data->open.bd_addr;
btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED;
btif_hf_cb[idx].peer_feat = 0;
- clear_phone_state_multihf(idx);
- } else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING) {
- btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
+ clear_phone_state_multihf(&btif_hf_cb[idx]);
+ system_bt_osi::BluetoothMetricsLogger::GetInstance()
+ ->LogHeadsetProfileRfcConnection(p_data->open.service_id);
+ bt_hf_callbacks->ConnectionStateCallback(
+ btif_hf_cb[idx].state, &btif_hf_cb[idx].connected_bda);
} else {
- BTIF_TRACE_WARNING(
- "%s: AG open failed, but another device connected. status=%d "
- "state=%d connected device=%s",
- __func__, p_data->open.status, btif_hf_cb[idx].state,
- btif_hf_cb[idx].connected_bda.ToString().c_str());
- break;
+ if (!btif_hf_cb[idx].is_initiator) {
+ // Ignore remote initiated open failures
+ LOG(WARNING) << __func__ << ": Unexpected AG open failure "
+ << std::to_string(p_data->open.status) << " for "
+ << p_data->open.bd_addr << " is ignored";
+ break;
+ }
+ LOG(ERROR) << __func__ << ": self initiated AG open failed for "
+ << btif_hf_cb[idx].connected_bda << ", status "
+ << std::to_string(p_data->open.status);
+ RawAddress connected_bda = btif_hf_cb[idx].connected_bda;
+ reset_control_block(&btif_hf_cb[idx]);
+ bt_hf_callbacks->ConnectionStateCallback(btif_hf_cb[idx].state,
+ &connected_bda);
+ btif_queue_advance();
}
-
- HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
- &btif_hf_cb[idx].connected_bda);
-
- if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
- btif_hf_cb[idx].connected_bda = RawAddress::kAny;
-
- if (p_data->open.status != BTA_AG_SUCCESS) btif_queue_advance();
break;
-
- case BTA_AG_CLOSE_EVT:
- btif_hf_cb[idx].connected_timestamp.tv_sec = 0;
- btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
- BTIF_TRACE_DEBUG(
- "%s: BTA_AG_CLOSE_EVT,"
- "idx = %d, btif_hf_cb.handle = %d",
- __func__, idx, btif_hf_cb[idx].handle);
- HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
- &btif_hf_cb[idx].connected_bda);
- btif_hf_cb[idx].connected_bda = RawAddress::kAny;
- btif_hf_cb[idx].peer_feat = 0;
- clear_phone_state_multihf(idx);
- hf_idx = btif_hf_latest_connected_idx();
- /* If AG_OPEN was received but SLC was not setup in a specified time (10
- *seconds),
- ** then AG_CLOSE may be received. We need to advance the queue here
- */
- btif_queue_advance();
+ // SLC and RFCOMM both disconnected
+ case BTA_AG_CLOSE_EVT: {
+ BTIF_TRACE_DEBUG("%s: BTA_AG_CLOSE_EVT, idx = %d, btif_hf_cb.handle = %d",
+ __func__, idx, btif_hf_cb[idx].handle);
+ // If AG_OPEN was received but SLC was not connected in time, then
+ // AG_CLOSE may be received. We need to advance the queue here.
+ bool failed_to_setup_slc =
+ (btif_hf_cb[idx].state != BTHF_CONNECTION_STATE_SLC_CONNECTED) &&
+ btif_hf_cb[idx].is_initiator;
+ RawAddress connected_bda = btif_hf_cb[idx].connected_bda;
+ reset_control_block(&btif_hf_cb[idx]);
+ bt_hf_callbacks->ConnectionStateCallback(btif_hf_cb[idx].state,
+ &connected_bda);
+ if (failed_to_setup_slc) {
+ LOG(ERROR) << __func__ << ": failed to setup SLC for " << connected_bda;
+ btif_queue_advance();
+ }
break;
-
+ }
+ // SLC connected
case BTA_AG_CONN_EVT:
- clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[idx].connected_timestamp);
BTIF_TRACE_DEBUG("%s: BTA_AG_CONN_EVT, idx = %d ", __func__, idx);
btif_hf_cb[idx].peer_feat = p_data->conn.peer_feat;
btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_SLC_CONNECTED;
- hf_idx = btif_hf_latest_connected_idx();
-
- HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
- &btif_hf_cb[idx].connected_bda);
- btif_queue_advance();
+ bt_hf_callbacks->ConnectionStateCallback(btif_hf_cb[idx].state,
+ &btif_hf_cb[idx].connected_bda);
+ if (btif_hf_cb[idx].is_initiator) {
+ btif_queue_advance();
+ }
break;
case BTA_AG_AUDIO_OPEN_EVT:
- hf_idx = idx;
- HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AudioStateCallback(BTHF_AUDIO_STATE_CONNECTED,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AUDIO_CLOSE_EVT:
- HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AudioStateCallback(BTHF_AUDIO_STATE_DISCONNECTED,
+ &btif_hf_cb[idx].connected_bda);
break;
/* BTA auto-responds, silently discard */
case BTA_AG_SPK_EVT:
case BTA_AG_MIC_EVT:
- HAL_CBACK(bt_hf_callbacks, volume_cmd_cb,
- (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK
- : BTHF_VOLUME_TYPE_MIC,
- p_data->val.num, &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->VolumeControlCallback(
+ (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK
+ : BTHF_VOLUME_TYPE_MIC,
+ p_data->val.num, &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_A_EVT:
- if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
- hf_idx = idx;
- else
- BTIF_TRACE_DEBUG("Donot set hf_idx for ATA since already in a call");
-
- HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AnswerCallCallback(&btif_hf_cb[idx].connected_bda);
break;
/* Java needs to send OK/ERROR for these commands */
case BTA_AG_AT_BLDN_EVT:
case BTA_AG_AT_D_EVT:
- if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
- hf_idx = idx;
- else
- BTIF_TRACE_DEBUG("Donot set hf_idx for BLDN/D since already in a call");
-
- HAL_CBACK(bt_hf_callbacks, dial_call_cmd_cb,
- (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->DialCallCallback(
+ (event == BTA_AG_AT_D_EVT) ? p_data->val.str : nullptr,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CHUP_EVT:
- HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->HangupCallCallback(&btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CIND_EVT:
- HAL_CBACK(bt_hf_callbacks, cind_cmd_cb, &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AtCindCallback(&btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_VTS_EVT:
- HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0],
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->DtmfCmdCallback(p_data->val.str[0],
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_BVRA_EVT:
- HAL_CBACK(bt_hf_callbacks, vr_cmd_cb,
- (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED
- : BTHF_VR_STATE_STOPPED,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->VoiceRecognitionCallback((p_data->val.num == 1)
+ ? BTHF_VR_STATE_STARTED
+ : BTHF_VR_STATE_STOPPED,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_NREC_EVT:
- HAL_CBACK(bt_hf_callbacks, nrec_cmd_cb,
- (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->NoiseReductionCallback(
+ (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP,
+ &btif_hf_cb[idx].connected_bda);
break;
/* TODO: Add a callback for CBC */
@@ -490,8 +456,7 @@
break;
case BTA_AG_AT_CKPD_EVT:
- HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->KeyPressedCallback(&btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_WBS_EVT:
@@ -499,39 +464,38 @@
"BTA_AG_WBS_EVT Set codec status %d codec %d 1=CVSD 2=MSBC",
p_data->val.hdr.status, p_data->val.num);
if (p_data->val.num == BTA_AG_CODEC_CVSD) {
- HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NO,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->WbsCallback(BTHF_WBS_NO,
+ &btif_hf_cb[idx].connected_bda);
} else if (p_data->val.num == BTA_AG_CODEC_MSBC) {
- HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_YES,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->WbsCallback(BTHF_WBS_YES,
+ &btif_hf_cb[idx].connected_bda);
} else {
- HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NONE,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->WbsCallback(BTHF_WBS_NONE,
+ &btif_hf_cb[idx].connected_bda);
}
break;
/* Java needs to send OK/ERROR for these commands */
case BTA_AG_AT_CHLD_EVT:
- HAL_CBACK(bt_hf_callbacks, chld_cmd_cb,
- (bthf_chld_type_t)atoi(p_data->val.str),
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AtChldCallback((bthf_chld_type_t)atoi(p_data->val.str),
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CLCC_EVT:
- HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb, &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AtClccCallback(&btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_COPS_EVT:
- HAL_CBACK(bt_hf_callbacks, cops_cmd_cb, &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AtCopsCallback(&btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_UNAT_EVT:
- HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->UnknownAtCallback(p_data->val.str,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CNUM_EVT:
- HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb, &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AtCnumCallback(&btif_hf_cb[idx].connected_bda);
break;
/* TODO: Some of these commands may need to be sent to app. For now respond
@@ -547,8 +511,7 @@
we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC
at the time
of SCO connection establishment */
- if ((btif_conf_hf_force_wbs == true) &&
- (p_data->val.num & BTA_AG_CODEC_MSBC)) {
+ if ((btif_conf_hf_force_wbs) && (p_data->val.num & BTA_AG_CODEC_MSBC)) {
BTIF_TRACE_EVENT("%s: btif_hf override-Preferred Codec to MSBC",
__func__);
BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_MSBC);
@@ -563,28 +526,38 @@
__func__, p_data->val.num);
/* No BTHF_WBS_NONE case, because HF1.6 supported device can send BCS */
/* Only CVSD is considered narrow band speech */
- HAL_CBACK(
- bt_hf_callbacks, wbs_cb,
+ bt_hf_callbacks->WbsCallback(
(p_data->val.num == BTA_AG_CODEC_CVSD) ? BTHF_WBS_NO : BTHF_WBS_YES,
&btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_BIND_EVT:
if (p_data->val.hdr.status == BTA_AG_SUCCESS) {
- HAL_CBACK(bt_hf_callbacks, bind_cb, p_data->val.str,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AtBindCallback(p_data->val.str,
+ &btif_hf_cb[idx].connected_bda);
}
break;
case BTA_AG_AT_BIEV_EVT:
if (p_data->val.hdr.status == BTA_AG_SUCCESS) {
- HAL_CBACK(bt_hf_callbacks, biev_cb,
- (bthf_hf_ind_type_t)p_data->val.lidx, (int)p_data->val.num,
- &btif_hf_cb[idx].connected_bda);
+ bt_hf_callbacks->AtBievCallback((bthf_hf_ind_type_t)p_data->val.lidx,
+ (int)p_data->val.num,
+ &btif_hf_cb[idx].connected_bda);
+ }
+ break;
+ case BTA_AG_AT_BIA_EVT:
+ if (p_data->val.hdr.status == BTA_AG_SUCCESS) {
+ uint32_t bia_mask_out = p_data->val.num;
+ bool service = !is_nth_bit_enabled(bia_mask_out, BTA_AG_IND_SERVICE);
+ bool roam = !is_nth_bit_enabled(bia_mask_out, BTA_AG_IND_ROAM);
+ bool signal = !is_nth_bit_enabled(bia_mask_out, BTA_AG_IND_SIGNAL);
+ bool battery = !is_nth_bit_enabled(bia_mask_out, BTA_AG_IND_BATTCHG);
+ bt_hf_callbacks->AtBiaCallback(service, roam, signal, battery,
+ &btif_hf_cb[idx].connected_bda);
}
break;
default:
- BTIF_TRACE_WARNING("%s: Unhandled event: %d", __func__, event);
+ LOG(WARNING) << __func__ << ": unhandled event " << event;
break;
}
}
@@ -620,7 +593,7 @@
/* switch context to btif task context (copy full union size for convenience)
*/
status = btif_transfer_context(btif_hf_upstreams_evt, (uint16_t)event,
- (char*)p_data, param_len, NULL);
+ (char*)p_data, param_len, nullptr);
/* catch any failed context transfers */
ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
@@ -628,91 +601,6 @@
/*******************************************************************************
*
- * Function btif_in_hf_generic_evt
- *
- * Description Processes generic events to be sent to JNI that are not
- * triggered from the BTA.
- * Always runs in BTIF context
- *
- * Returns void
- *
- ******************************************************************************/
-static void btif_in_hf_generic_evt(uint16_t event, char* p_param) {
- int idx = btif_hf_idx_by_bdaddr((RawAddress*)p_param);
-
- BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
- BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
- return;
- }
-
- switch (event) {
- case BTIF_HFP_CB_AUDIO_CONNECTING: {
- HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTING,
- &btif_hf_cb[idx].connected_bda);
- } break;
- default: {
- BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __func__, event);
- } break;
- }
-}
-
-static bool inband_ringing_property_enabled() {
- char inband_ringing_flag[PROPERTY_VALUE_MAX] = {0};
- osi_property_get("persist.bluetooth.enableinbandringing", inband_ringing_flag,
- "true");
- if (strncmp(inband_ringing_flag, "true", 4) == 0) {
- BTIF_TRACE_DEBUG("%s: In-band ringing enabled by property", __func__);
- return true;
- }
- return false;
-}
-
-/*******************************************************************************
- *
- * Function btif_hf_init
- *
- * Description initializes the hf interface
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t init(bthf_callbacks_t* callbacks, int max_hf_clients,
- bool inband_ringing_supported) {
- bool inband_ringing_property_enable = inband_ringing_property_enabled();
- if (inband_ringing_supported && inband_ringing_property_enable) {
- btif_hf_features |= BTA_AG_FEAT_INBAND;
- } else {
- btif_hf_features &= ~BTA_AG_FEAT_INBAND;
- }
- btif_max_hf_clients = max_hf_clients;
- BTIF_TRACE_DEBUG(
- "%s: btif_hf_features=%zu, max_hf_clients=%d, "
- "inband_ringing=[supported=%d, enabled=%d]",
- __func__, btif_hf_features, btif_max_hf_clients, inband_ringing_supported,
- inband_ringing_property_enable);
- bt_hf_callbacks = callbacks;
- memset(&btif_hf_cb, 0, sizeof(btif_hf_cb));
-
-/* Invoke the enable service API to the core to set the appropriate service_id
- * Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled
- * (phone)
- * othwerwise only HSP is enabled (tablet)
- */
-#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK))
- btif_enable_service(BTA_HFP_SERVICE_ID);
-#else
- btif_enable_service(BTA_HSP_SERVICE_ID);
-#endif
-
- for (int i = 0; i < btif_max_hf_clients; i++) clear_phone_state_multihf(i);
-
- return BT_STATUS_SUCCESS;
-}
-
-/*******************************************************************************
- *
* Function connect
*
* Description connect to headset
@@ -722,559 +610,500 @@
******************************************************************************/
static bt_status_t connect_int(RawAddress* bd_addr, uint16_t uuid) {
CHECK_BTHF_INIT();
- int i;
- for (i = 0; i < btif_max_hf_clients;) {
- if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
- (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)))
- i++;
- else
+ if (is_connected(bd_addr)) {
+ BTIF_TRACE_WARNING("%s: device %s is already connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_BUSY;
+ }
+ btif_hf_cb_t* hf_cb = nullptr;
+ for (int i = 0; i < btif_max_hf_clients; i++) {
+ if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_DISCONNECTED) {
+ hf_cb = &btif_hf_cb[i];
break;
+ }
+ // Due to btif queue implementation, when connect_int is called, no btif
+ // control block should be in connecting state
+ // Crash here to prevent future code changes from breaking this mechanism
+ if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTING) {
+ LOG(FATAL) << __func__ << ": " << btif_hf_cb[i].connected_bda
+ << ", handle " << btif_hf_cb[i].handle
+ << ", is still in connecting state " << btif_hf_cb[i].state;
+ }
}
-
- if (i == btif_max_hf_clients) return BT_STATUS_BUSY;
-
- if (!is_connected(bd_addr)) {
- btif_hf_cb[i].state = BTHF_CONNECTION_STATE_CONNECTING;
- btif_hf_cb[i].connected_bda = *bd_addr;
-
- BTA_AgOpen(btif_hf_cb[i].handle, btif_hf_cb[i].connected_bda,
- BTIF_HF_SECURITY, BTIF_HF_SERVICES);
- return BT_STATUS_SUCCESS;
+ if (hf_cb == nullptr) {
+ BTIF_TRACE_WARNING(
+ "%s: Cannot connect %s: maximum %d clients already connected", __func__,
+ bd_addr->ToString().c_str(), btif_max_hf_clients);
+ return BT_STATUS_BUSY;
}
-
- return BT_STATUS_BUSY;
+ hf_cb->state = BTHF_CONNECTION_STATE_CONNECTING;
+ hf_cb->connected_bda = *bd_addr;
+ hf_cb->is_initiator = true;
+ hf_cb->peer_feat = 0;
+ BTA_AgOpen(hf_cb->handle, hf_cb->connected_bda, BTIF_HF_SECURITY);
+ return BT_STATUS_SUCCESS;
}
-static bt_status_t connect(RawAddress* bd_addr) {
+static void UpdateCallStates(btif_hf_cb_t* control_block, int num_active,
+ int num_held, bthf_call_state_t call_setup_state) {
+ control_block->num_active = num_active;
+ control_block->num_held = num_held;
+ control_block->call_setup_state = call_setup_state;
+}
+
+/*******************************************************************************
+ *
+ * Function btif_hf_is_call_idle
+ *
+ * Description returns true if no call is in progress
+ *
+ * Returns bt_status_t
+ *
+ ******************************************************************************/
+bool IsCallIdle() {
+ if (!bt_hf_callbacks) return true;
+
+ for (int i = 0; i < btif_max_hf_clients; ++i) {
+ if ((btif_hf_cb[i].call_setup_state != BTHF_CALL_STATE_IDLE) ||
+ ((btif_hf_cb[i].num_held + btif_hf_cb[i].num_active) > 0))
+ return false;
+ }
+
+ return true;
+}
+
+class HeadsetInterface : Interface {
+ public:
+ static Interface* GetInstance() {
+ static Interface* instance = new HeadsetInterface();
+ return instance;
+ }
+ bt_status_t Init(Callbacks* callbacks, int max_hf_clients,
+ bool inband_ringing_enabled) override;
+ bt_status_t Connect(RawAddress* bd_addr) override;
+ bt_status_t Disconnect(RawAddress* bd_addr) override;
+ bt_status_t ConnectAudio(RawAddress* bd_addr) override;
+ bt_status_t DisconnectAudio(RawAddress* bd_addr) override;
+ bt_status_t StartVoiceRecognition(RawAddress* bd_addr) override;
+ bt_status_t StopVoiceRecognition(RawAddress* bd_addr) override;
+ bt_status_t VolumeControl(bthf_volume_type_t type, int volume,
+ RawAddress* bd_addr) override;
+ bt_status_t DeviceStatusNotification(bthf_network_state_t ntk_state,
+ bthf_service_type_t svc_type, int signal,
+ int batt_chg,
+ RawAddress* bd_addr) override;
+ bt_status_t CopsResponse(const char* cops, RawAddress* bd_addr) override;
+ bt_status_t CindResponse(int svc, int num_active, int num_held,
+ bthf_call_state_t call_setup_state, int signal,
+ int roam, int batt_chg,
+ RawAddress* bd_addr) override;
+ bt_status_t FormattedAtResponse(const char* rsp,
+ RawAddress* bd_addr) override;
+ bt_status_t AtResponse(bthf_at_response_t response_code, int error_code,
+ RawAddress* bd_addr) override;
+ bt_status_t ClccResponse(int index, bthf_call_direction_t dir,
+ bthf_call_state_t state, bthf_call_mode_t mode,
+ bthf_call_mpty_type_t mpty, const char* number,
+ bthf_call_addrtype_t type,
+ RawAddress* bd_addr) override;
+ bt_status_t PhoneStateChange(int num_active, int num_held,
+ bthf_call_state_t call_setup_state,
+ const char* number, bthf_call_addrtype_t type,
+ RawAddress* bd_addr) override;
+
+ void Cleanup() override;
+ bt_status_t SetScoAllowed(bool value) override;
+ bt_status_t SendBsir(bool value, RawAddress* bd_addr) override;
+ bt_status_t SetActiveDevice(RawAddress* active_device_addr) override;
+};
+
+bt_status_t HeadsetInterface::Init(Callbacks* callbacks, int max_hf_clients,
+ bool inband_ringing_enabled) {
+ if (inband_ringing_enabled) {
+ btif_hf_features |= BTA_AG_FEAT_INBAND;
+ } else {
+ btif_hf_features &= ~BTA_AG_FEAT_INBAND;
+ }
+ CHECK_LE(max_hf_clients, BTA_AG_MAX_NUM_CLIENTS)
+ << __func__
+ << "Too many HF clients,"
+ " maximum is "
+ << BTA_AG_MAX_NUM_CLIENTS << " was given " << max_hf_clients;
+ btif_max_hf_clients = max_hf_clients;
+ BTIF_TRACE_DEBUG(
+ "%s: btif_hf_features=%zu, max_hf_clients=%d, inband_ringing_enabled=%d",
+ __func__, btif_hf_features, btif_max_hf_clients, inband_ringing_enabled);
+ bt_hf_callbacks = callbacks;
+ for (btif_hf_cb_t& hf_cb : btif_hf_cb) {
+ reset_control_block(&hf_cb);
+ }
+
+// Invoke the enable service API to the core to set the appropriate service_id
+// Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled
+// (phone) otherwise only HSP is enabled (tablet)
+#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK))
+ btif_enable_service(BTA_HFP_SERVICE_ID);
+#else
+ btif_enable_service(BTA_HSP_SERVICE_ID);
+#endif
+
+ return BT_STATUS_SUCCESS;
+}
+
+bt_status_t HeadsetInterface::Connect(RawAddress* bd_addr) {
CHECK_BTHF_INIT();
return btif_queue_connect(UUID_SERVCLASS_AG_HANDSFREE, bd_addr, connect_int);
}
-/*******************************************************************************
- *
- * Function disconnect
- *
- * Description disconnect from headset
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t disconnect(RawAddress* bd_addr) {
+bt_status_t HeadsetInterface::Disconnect(RawAddress* bd_addr) {
CHECK_BTHF_INIT();
-
int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
return BT_STATUS_FAIL;
}
-
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- BTA_AgClose(btif_hf_cb[idx].handle);
- return BT_STATUS_SUCCESS;
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
}
-
- return BT_STATUS_FAIL;
+ BTA_AgClose(btif_hf_cb[idx].handle);
+ return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function connect_audio
- *
- * Description create an audio connection
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t connect_audio(RawAddress* bd_addr) {
+bt_status_t HeadsetInterface::ConnectAudio(RawAddress* bd_addr) {
CHECK_BTHF_INIT();
-
int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
return BT_STATUS_FAIL;
}
-
/* Check if SLC is connected */
- if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
+ if (!IsSlcConnected(bd_addr)) {
+ LOG(ERROR) << ": SLC not connected for " << *bd_addr;
return BT_STATUS_NOT_READY;
-
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- BTA_AgAudioOpen(btif_hf_cb[idx].handle);
-
- /* Inform the application that the audio connection has been initiated
- * successfully */
- btif_transfer_context(btif_in_hf_generic_evt, BTIF_HFP_CB_AUDIO_CONNECTING,
- (char*)bd_addr, sizeof(RawAddress), NULL);
- return BT_STATUS_SUCCESS;
}
-
- return BT_STATUS_FAIL;
+ BTA_AgAudioOpen(btif_hf_cb[idx].handle);
+ // Inform the application that the audio connection has been initiated
+ // successfully
+ do_in_jni_thread(base::Bind(&Callbacks::AudioStateCallback,
+ // Manual pointer management for now
+ base::Unretained(bt_hf_callbacks),
+ BTHF_AUDIO_STATE_CONNECTING,
+ &btif_hf_cb[idx].connected_bda));
+ return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function disconnect_audio
- *
- * Description close the audio connection
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t disconnect_audio(RawAddress* bd_addr) {
+bt_status_t HeadsetInterface::DisconnectAudio(RawAddress* bd_addr) {
CHECK_BTHF_INIT();
-
int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
return BT_STATUS_FAIL;
}
-
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- BTA_AgAudioClose(btif_hf_cb[idx].handle);
- return BT_STATUS_SUCCESS;
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
}
-
- return BT_STATUS_FAIL;
+ BTA_AgAudioClose(btif_hf_cb[idx].handle);
+ return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function start_voice_recognition
- *
- * Description start voice recognition
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t start_voice_recognition(RawAddress* bd_addr) {
+bt_status_t HeadsetInterface::StartVoiceRecognition(RawAddress* bd_addr) {
CHECK_BTHF_INIT();
-
int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
return BT_STATUS_FAIL;
}
-
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC) {
- tBTA_AG_RES_DATA ag_res;
- memset(&ag_res, 0, sizeof(ag_res));
- ag_res.state = 1;
- BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
-
- return BT_STATUS_SUCCESS;
- } else {
- return BT_STATUS_UNSUPPORTED;
- }
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_NOT_READY;
}
-
- return BT_STATUS_NOT_READY;
+ if (!(btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)) {
+ BTIF_TRACE_ERROR("%s: voice recognition not supported, features=0x%x",
+ __func__, btif_hf_cb[idx].peer_feat);
+ return BT_STATUS_UNSUPPORTED;
+ }
+ tBTA_AG_RES_DATA ag_res = {};
+ ag_res.state = true;
+ BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, ag_res);
+ return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function stop_voice_recognition
- *
- * Description stop voice recognition
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t stop_voice_recognition(RawAddress* bd_addr) {
+bt_status_t HeadsetInterface::StopVoiceRecognition(RawAddress* bd_addr) {
CHECK_BTHF_INIT();
-
int idx = btif_hf_idx_by_bdaddr(bd_addr);
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
return BT_STATUS_FAIL;
}
-
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC) {
- tBTA_AG_RES_DATA ag_res;
- memset(&ag_res, 0, sizeof(ag_res));
- ag_res.state = 0;
- BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
-
- return BT_STATUS_SUCCESS;
- } else {
- return BT_STATUS_UNSUPPORTED;
- }
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_NOT_READY;
}
-
- return BT_STATUS_NOT_READY;
+ if (!(btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)) {
+ BTIF_TRACE_ERROR("%s: voice recognition not supported, features=0x%x",
+ __func__, btif_hf_cb[idx].peer_feat);
+ return BT_STATUS_UNSUPPORTED;
+ }
+ tBTA_AG_RES_DATA ag_res = {};
+ ag_res.state = false;
+ BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, ag_res);
+ return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function volume_control
- *
- * Description volume control
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t volume_control(bthf_volume_type_t type, int volume,
- RawAddress* bd_addr) {
+bt_status_t HeadsetInterface::VolumeControl(bthf_volume_type_t type, int volume,
+ RawAddress* bd_addr) {
CHECK_BTHF_INIT();
-
int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
return BT_STATUS_FAIL;
}
-
- tBTA_AG_RES_DATA ag_res;
- memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- ag_res.num = volume;
- BTA_AgResult(
- btif_hf_cb[idx].handle,
- (type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES,
- &ag_res);
- return BT_STATUS_SUCCESS;
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
}
-
- return BT_STATUS_FAIL;
+ tBTA_AG_RES_DATA ag_res = {};
+ ag_res.num = static_cast<uint16_t>(volume);
+ BTA_AgResult(btif_hf_cb[idx].handle,
+ (type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES,
+ ag_res);
+ return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function device_status_notification
- *
- * Description Combined device status change notification
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t device_status_notification(bthf_network_state_t ntk_state,
- bthf_service_type_t svc_type,
- int signal, int batt_chg) {
+bt_status_t HeadsetInterface::DeviceStatusNotification(
+ bthf_network_state_t ntk_state, bthf_service_type_t svc_type, int signal,
+ int batt_chg, RawAddress* bd_addr) {
CHECK_BTHF_INIT();
-
- if (is_connected(NULL)) {
- /* send all indicators to BTA.
- ** BTA will make sure no duplicates are sent out
- */
- send_indicator_update(BTA_AG_IND_SERVICE,
+ if (!bd_addr) {
+ BTIF_TRACE_WARNING("%s: bd_addr is null", __func__);
+ return BT_STATUS_FAIL;
+ }
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+ if (idx < 0 || idx > BTA_AG_MAX_NUM_CLIENTS) {
+ BTIF_TRACE_WARNING("%s: invalid index %d for %s", __func__, idx,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
+ }
+ const btif_hf_cb_t& control_block = btif_hf_cb[idx];
+ // ok if no device is connected
+ if (is_connected(nullptr)) {
+ // send all indicators to BTA.
+ // BTA will make sure no duplicates are sent out
+ send_indicator_update(control_block, BTA_AG_IND_SERVICE,
(ntk_state == BTHF_NETWORK_STATE_AVAILABLE) ? 1 : 0);
- send_indicator_update(BTA_AG_IND_ROAM,
+ send_indicator_update(control_block, BTA_AG_IND_ROAM,
(svc_type == BTHF_SERVICE_TYPE_HOME) ? 0 : 1);
- send_indicator_update(BTA_AG_IND_SIGNAL, signal);
- send_indicator_update(BTA_AG_IND_BATTCHG, batt_chg);
- return BT_STATUS_SUCCESS;
+ send_indicator_update(control_block, BTA_AG_IND_SIGNAL, signal);
+ send_indicator_update(control_block, BTA_AG_IND_BATTCHG, batt_chg);
}
-
return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function cops_response
- *
- * Description Response for COPS command
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t cops_response(const char* cops, RawAddress* bd_addr) {
+bt_status_t HeadsetInterface::CopsResponse(const char* cops,
+ RawAddress* bd_addr) {
CHECK_BTHF_INIT();
-
int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
return BT_STATUS_FAIL;
}
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
+ }
+ tBTA_AG_RES_DATA ag_res = {};
+ /* Format the response */
+ snprintf(ag_res.str, sizeof(ag_res.str), "0,0,\"%.16s\"", cops);
+ ag_res.ok_flag = BTA_AG_OK_DONE;
+ BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_COPS_RES, ag_res);
+ return BT_STATUS_SUCCESS;
+}
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- tBTA_AG_RES_DATA ag_res;
+bt_status_t HeadsetInterface::CindResponse(int svc, int num_active,
+ int num_held,
+ bthf_call_state_t call_setup_state,
+ int signal, int roam, int batt_chg,
+ RawAddress* bd_addr) {
+ CHECK_BTHF_INIT();
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
+ BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
+ return BT_STATUS_FAIL;
+ }
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
+ }
+ tBTA_AG_RES_DATA ag_res = {};
+ // per the errata 2043, call=1 implies atleast one call is in progress
+ // (active/held), see:
+ // https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
+ snprintf(ag_res.str, sizeof(ag_res.str), "%d,%d,%d,%d,%d,%d,%d",
+ (num_active + num_held) ? 1 : 0, /* Call state */
+ callstate_to_callsetup(call_setup_state), /* Callsetup state */
+ svc, /* network service */
+ signal, /* Signal strength */
+ roam, /* Roaming indicator */
+ batt_chg, /* Battery level */
+ ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); /* Call held */
+ BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_CIND_RES, ag_res);
+ return BT_STATUS_SUCCESS;
+}
- /* Format the response */
- snprintf(ag_res.str, sizeof(ag_res.str), "0,0,\"%.16s\"", cops);
+bt_status_t HeadsetInterface::FormattedAtResponse(const char* rsp,
+ RawAddress* bd_addr) {
+ CHECK_BTHF_INIT();
+ tBTA_AG_RES_DATA ag_res = {};
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
+ BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
+ return BT_STATUS_FAIL;
+ }
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
+ }
+ /* Format the response and send */
+ strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN);
+ BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, ag_res);
+ return BT_STATUS_SUCCESS;
+}
+
+bt_status_t HeadsetInterface::AtResponse(bthf_at_response_t response_code,
+ int error_code, RawAddress* bd_addr) {
+ CHECK_BTHF_INIT();
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
+ BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
+ return BT_STATUS_FAIL;
+ }
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
+ }
+ send_at_result(
+ (response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE : BTA_AG_OK_ERROR,
+ static_cast<uint16_t>(error_code), idx);
+ return BT_STATUS_SUCCESS;
+}
+
+bt_status_t HeadsetInterface::ClccResponse(
+ int index, bthf_call_direction_t dir, bthf_call_state_t state,
+ bthf_call_mode_t mode, bthf_call_mpty_type_t mpty, const char* number,
+ bthf_call_addrtype_t type, RawAddress* bd_addr) {
+ CHECK_BTHF_INIT();
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
+ BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
+ return BT_STATUS_FAIL;
+ }
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s is not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
+ }
+ tBTA_AG_RES_DATA ag_res = {};
+ /* Format the response */
+ if (index == 0) {
ag_res.ok_flag = BTA_AG_OK_DONE;
-
- BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
- return BT_STATUS_SUCCESS;
- }
- return BT_STATUS_FAIL;
-}
-
-/*******************************************************************************
- *
- * Function cind_response
- *
- * Description Response for CIND command
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t cind_response(int svc, int num_active, int num_held,
- bthf_call_state_t call_setup_state, int signal,
- int roam, int batt_chg, RawAddress* bd_addr) {
- CHECK_BTHF_INIT();
-
- int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
- BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
- return BT_STATUS_FAIL;
- }
-
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- tBTA_AG_RES_DATA ag_res;
-
- memset(&ag_res, 0, sizeof(ag_res));
- /* per the errata 2043, call=1 implies atleast one call is in progress
- *(active/held)
- ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
- **/
- snprintf(
- ag_res.str, sizeof(ag_res.str), "%d,%d,%d,%d,%d,%d,%d",
- (num_active + num_held) ? 1 : 0, /* Call state */
- callstate_to_callsetup(call_setup_state), /* Callsetup state */
- svc, /* network service */
- signal, /* Signal strength */
- roam, /* Roaming indicator */
- batt_chg, /* Battery level */
- ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); /* Call held */
-
- BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res);
-
- return BT_STATUS_SUCCESS;
- }
-
- return BT_STATUS_FAIL;
-}
-
-/*******************************************************************************
- *
- * Function bind_response
- *
- * Description Send +BIND response
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t bind_response(bthf_hf_ind_type_t ind_id,
- bthf_hf_ind_status_t ind_status,
- RawAddress* bd_addr) {
- CHECK_BTHF_INIT();
-
- int index = btif_hf_idx_by_bdaddr(bd_addr);
- if (!is_connected(bd_addr) || index == BTIF_HF_INVALID_IDX)
- return BT_STATUS_FAIL;
-
- tBTA_AG_RES_DATA ag_res;
- memset(&ag_res, 0, sizeof(ag_res));
- ag_res.ind.id = ind_id;
- ag_res.ind.on_demand = (ind_status == BTHF_HF_IND_ENABLED);
-
- BTA_AgResult(btif_hf_cb[index].handle, BTA_AG_BIND_RES, &ag_res);
- return BT_STATUS_SUCCESS;
-}
-
-static bt_status_t set_sco_allowed(bool value) {
- CHECK_BTHF_INIT();
-
- BTA_AgSetScoAllowed(value);
- return BT_STATUS_SUCCESS;
-}
-
-/*******************************************************************************
- *
- * Function formatted_at_response
- *
- * Description Pre-formatted AT response, typically in response to unknown
- * AT cmd
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t formatted_at_response(const char* rsp, RawAddress* bd_addr) {
- CHECK_BTHF_INIT();
- tBTA_AG_RES_DATA ag_res;
- int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
- BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
- return BT_STATUS_FAIL;
- }
-
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- /* Format the response and send */
- memset(&ag_res, 0, sizeof(ag_res));
- strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN);
- BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
-
- return BT_STATUS_SUCCESS;
- }
-
- return BT_STATUS_FAIL;
-}
-
-/*******************************************************************************
- *
- * Function at_response
- *
- * Description ok/error response
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t at_response(bthf_at_response_t response_code, int error_code,
- RawAddress* bd_addr) {
- CHECK_BTHF_INIT();
-
- int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
- BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
- return BT_STATUS_FAIL;
- }
-
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
- : BTA_AG_OK_ERROR,
- error_code, idx);
- return BT_STATUS_SUCCESS;
- }
-
- return BT_STATUS_FAIL;
-}
-
-/*******************************************************************************
- *
- * Function clcc_response
- *
- * Description response for CLCC command
- * Can be iteratively called for each call index. Call index
- * of 0 will be treated as NULL termination (Completes
- * response)
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
- bthf_call_state_t state, bthf_call_mode_t mode,
- bthf_call_mpty_type_t mpty, const char* number,
- bthf_call_addrtype_t type,
- RawAddress* bd_addr) {
- CHECK_BTHF_INIT();
-
- int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
- BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
- return BT_STATUS_FAIL;
- }
-
- if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
- tBTA_AG_RES_DATA ag_res;
- memset(&ag_res, 0, sizeof(ag_res));
-
- /* Format the response */
- if (index == 0) {
- ag_res.ok_flag = BTA_AG_OK_DONE;
- } else {
- BTIF_TRACE_EVENT(
- "clcc_response: [%d] dir %d state %d mode %d number = %s type = %d",
- index, dir, state, mode, number, type);
- int res_strlen =
- snprintf(ag_res.str, sizeof(ag_res.str), "%d,%d,%d,%d,%d", index, dir,
- state, mode, mpty);
-
- if (number) {
- size_t rem_bytes = sizeof(ag_res.str) - res_strlen;
- char dialnum[sizeof(ag_res.str)];
- size_t newidx = 0;
- if (type == BTHF_CALL_ADDRTYPE_INTERNATIONAL && *number != '+') {
- dialnum[newidx++] = '+';
- }
- for (size_t i = 0; number[i] != 0; i++) {
- if (utl_isdialchar(number[i])) {
- dialnum[newidx++] = number[i];
- }
- }
- dialnum[newidx] = 0;
- snprintf(&ag_res.str[res_strlen], rem_bytes, ",\"%s\",%d", dialnum,
- type);
+ } else {
+ BTIF_TRACE_EVENT(
+ "clcc_response: [%d] dir %d state %d mode %d number = %s type = %d",
+ index, dir, state, mode, number, type);
+ int res_strlen = snprintf(ag_res.str, sizeof(ag_res.str), "%d,%d,%d,%d,%d",
+ index, dir, state, mode, mpty);
+ if (number) {
+ size_t rem_bytes = sizeof(ag_res.str) - res_strlen;
+ char dialnum[sizeof(ag_res.str)];
+ size_t newidx = 0;
+ if (type == BTHF_CALL_ADDRTYPE_INTERNATIONAL && *number != '+') {
+ dialnum[newidx++] = '+';
}
+ for (size_t i = 0; number[i] != 0; i++) {
+ if (newidx >= (sizeof(dialnum) - res_strlen - 1)) {
+ android_errorWriteLog(0x534e4554, "79266386");
+ break;
+ }
+ if (utl_isdialchar(number[i])) {
+ dialnum[newidx++] = number[i];
+ }
+ }
+ dialnum[newidx] = 0;
+ // Reserve 5 bytes for ["][,][3_digit_type]
+ snprintf(&ag_res.str[res_strlen], rem_bytes - 5, ",\"%s", dialnum);
+ std::stringstream remaining_string;
+ remaining_string << "\"," << type;
+ strncat(&ag_res.str[res_strlen], remaining_string.str().c_str(), 5);
}
- BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res);
-
- return BT_STATUS_SUCCESS;
}
-
- return BT_STATUS_FAIL;
+ BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, ag_res);
+ return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function phone_state_change
- *
- * Description notify of a call state change
- * number & type: valid only for incoming & waiting call
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-
-static bt_status_t phone_state_change(int num_active, int num_held,
- bthf_call_state_t call_setup_state,
- const char* number,
- bthf_call_addrtype_t type) {
- tBTA_AG_RES res = 0xff;
- tBTA_AG_RES_DATA ag_res;
- bt_status_t status = BT_STATUS_SUCCESS;
- bool activeCallUpdated = false;
- int idx, i;
-
- /* hf_idx is index of connected HS that sent ATA/BLDN,
- otherwise index of latest connected HS */
- if (hf_idx != BTIF_HF_INVALID_IDX)
- idx = hf_idx;
- else
- idx = btif_hf_latest_connected_idx();
-
- BTIF_TRACE_DEBUG("phone_state_change: idx = %d", idx);
-
- /* Check if SLC is connected */
- if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
+bt_status_t HeadsetInterface::PhoneStateChange(
+ int num_active, int num_held, bthf_call_state_t call_setup_state,
+ const char* number, bthf_call_addrtype_t type, RawAddress* bd_addr) {
+ CHECK_BTHF_INIT();
+ if (!bd_addr) {
+ BTIF_TRACE_WARNING("%s: bd_addr is null", __func__);
+ return BT_STATUS_FAIL;
+ }
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+ if (idx < 0 || idx > BTA_AG_MAX_NUM_CLIENTS) {
+ BTIF_TRACE_WARNING("%s: invalid index %d for %s", __func__, idx,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
+ }
+ const btif_hf_cb_t& control_block = btif_hf_cb[idx];
+ if (!IsSlcConnected(bd_addr)) {
+ LOG(WARNING) << ": SLC not connected for " << *bd_addr;
return BT_STATUS_NOT_READY;
-
- BTIF_TRACE_DEBUG(
- "phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"
- " call_setup=%s [prev: %s]",
- num_active, btif_hf_cb[idx].num_active, num_held,
- btif_hf_cb[idx].num_held, dump_hf_call_state(call_setup_state),
- dump_hf_call_state(btif_hf_cb[idx].call_setup_state));
+ }
+ if (call_setup_state == BTHF_CALL_STATE_DISCONNECTED) {
+ // HFP spec does not handle cases when a call is being disconnected.
+ // Since DISCONNECTED state must lead to IDLE state, ignoring it here.s
+ LOG(INFO) << __func__
+ << ": Ignore call state change to DISCONNECTED, idx=" << idx
+ << ", addr=" << *bd_addr << ", num_active=" << num_active
+ << ", num_held=" << num_held;
+ return BT_STATUS_SUCCESS;
+ }
+ LOG(INFO) << __func__ << ": idx=" << idx << ", addr=" << *bd_addr
+ << ", active_bda=" << active_bda << ", num_active=" << num_active
+ << ", prev_num_active" << control_block.num_active
+ << ", num_held=" << num_held
+ << ", prev_num_held=" << control_block.num_held
+ << ", call_state=" << dump_hf_call_state(call_setup_state)
+ << ", prev_call_state="
+ << dump_hf_call_state(control_block.call_setup_state);
+ tBTA_AG_RES res = 0xFF;
+ bt_status_t status = BT_STATUS_SUCCESS;
+ bool active_call_updated = false;
/* if all indicators are 0, send end call and return */
if (num_active == 0 && num_held == 0 &&
call_setup_state == BTHF_CALL_STATE_IDLE) {
- BTIF_TRACE_DEBUG("%s: Phone on hook", __func__);
-
- /* record call termination timestamp if there was an active/held call or
- callsetup state > BTHF_CALL_STATE_IDLE */
- if ((btif_hf_cb[idx].call_setup_state != BTHF_CALL_STATE_IDLE) ||
- (btif_hf_cb[idx].num_active) || (btif_hf_cb[idx].num_held)) {
- BTIF_TRACE_DEBUG("%s: Record call termination timestamp", __func__);
- clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[0].call_end_timestamp);
- }
- BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
- hf_idx = BTIF_HF_INVALID_IDX;
-
+ VLOG(1) << __func__ << ": call ended";
+ BTA_AgResult(control_block.handle, BTA_AG_END_CALL_RES,
+ tBTA_AG_RES_DATA::kEmpty);
/* if held call was present, reset that as well */
- if (btif_hf_cb[idx].num_held) send_indicator_update(BTA_AG_IND_CALLHELD, 0);
-
- goto update_call_states;
+ if (control_block.num_held) {
+ send_indicator_update(control_block, BTA_AG_IND_CALLHELD, 0);
+ }
+ UpdateCallStates(&btif_hf_cb[idx], num_active, num_held, call_setup_state);
+ return status;
}
/* active state can change when:
@@ -1288,57 +1117,60 @@
** force the SCO to be setup. Handle this special case here prior to
** call setup handling
*/
- if (((num_active + num_held) > 0) && (btif_hf_cb[idx].num_active == 0) &&
- (btif_hf_cb[idx].num_held == 0) &&
- (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE)) {
+ if (((num_active + num_held) > 0) && (control_block.num_active == 0) &&
+ (control_block.num_held == 0) &&
+ (control_block.call_setup_state == BTHF_CALL_STATE_IDLE)) {
+ tBTA_AG_RES_DATA ag_res = {};
BTIF_TRACE_DEBUG(
- "%s: Active/Held call notification received without call setup update",
+ "%s: Active/Held call notification received without call setup "
+ "update",
__func__);
- memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
- /* Addition call setup with the Active call
- ** CIND response should have been updated.
- ** just open SCO connection.
- */
- if (call_setup_state != BTHF_CALL_STATE_IDLE)
+ // Addition call setup with the Active call
+ // CIND response should have been updated.
+ // just open SCO connection.
+ if (call_setup_state != BTHF_CALL_STATE_IDLE) {
res = BTA_AG_MULTI_CALL_RES;
- else
+ } else {
res = BTA_AG_OUT_CALL_CONN_RES;
- BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
- activeCallUpdated = true;
+ }
+ BTA_AgResult(control_block.handle, res, ag_res);
+ active_call_updated = true;
}
/* Ringing call changed? */
- if (call_setup_state != btif_hf_cb[idx].call_setup_state) {
+ if (call_setup_state != control_block.call_setup_state) {
+ tBTA_AG_RES_DATA ag_res = {};
+ ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
BTIF_TRACE_DEBUG("%s: Call setup states changed. old: %s new: %s", __func__,
- dump_hf_call_state(btif_hf_cb[idx].call_setup_state),
+ dump_hf_call_state(control_block.call_setup_state),
dump_hf_call_state(call_setup_state));
- memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
-
switch (call_setup_state) {
case BTHF_CALL_STATE_IDLE: {
- switch (btif_hf_cb[idx].call_setup_state) {
+ switch (control_block.call_setup_state) {
case BTHF_CALL_STATE_INCOMING:
- if (num_active > btif_hf_cb[idx].num_active) {
+ if (num_active > control_block.num_active) {
res = BTA_AG_IN_CALL_CONN_RES;
- ag_res.audio_handle = btif_hf_cb[idx].handle;
- } else if (num_held > btif_hf_cb[idx].num_held)
+ if (is_active_device(*bd_addr)) {
+ ag_res.audio_handle = control_block.handle;
+ }
+ } else if (num_held > control_block.num_held)
res = BTA_AG_IN_CALL_HELD_RES;
else
res = BTA_AG_CALL_CANCEL_RES;
break;
case BTHF_CALL_STATE_DIALING:
case BTHF_CALL_STATE_ALERTING:
- if (num_active > btif_hf_cb[idx].num_active) {
- ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
+ if (num_active > control_block.num_active) {
res = BTA_AG_OUT_CALL_CONN_RES;
} else
res = BTA_AG_CALL_CANCEL_RES;
break;
default:
- BTIF_TRACE_ERROR("%s: Incorrect Call setup state transition",
- __func__);
+ BTIF_TRACE_ERROR("%s: Incorrect call state prev=%d, now=%d",
+ __func__, control_block.call_setup_state,
+ call_setup_state);
status = BT_STATUS_PARM_INVALID;
break;
}
@@ -1349,6 +1181,9 @@
res = BTA_AG_CALL_WAIT_RES;
} else {
res = BTA_AG_IN_CALL_RES;
+ if (is_active_device(*bd_addr)) {
+ ag_res.audio_handle = control_block.handle;
+ }
}
if (number) {
int xx = 0;
@@ -1357,141 +1192,114 @@
else
xx = snprintf(ag_res.str, sizeof(ag_res.str), "\"%s\"", number);
ag_res.num = type;
+ // 5 = [,][3_digit_type][null_terminator]
+ if (xx > static_cast<int>(sizeof(ag_res.str) - 5)) {
+ android_errorWriteLog(0x534e4554, "79431031");
+ xx = sizeof(ag_res.str) - 5;
+ // Null terminating the string
+ memset(&ag_res.str[xx], 0, 5);
+ }
if (res == BTA_AG_CALL_WAIT_RES)
snprintf(&ag_res.str[xx], sizeof(ag_res.str) - xx, ",%d", type);
}
break;
case BTHF_CALL_STATE_DIALING:
- if (!(num_active + num_held))
- ag_res.audio_handle = btif_hf_cb[idx].handle;
+ if (!(num_active + num_held) && is_active_device(*bd_addr)) {
+ ag_res.audio_handle = control_block.handle;
+ }
res = BTA_AG_OUT_CALL_ORIG_RES;
break;
case BTHF_CALL_STATE_ALERTING:
/* if we went from idle->alert, force SCO setup here. dialing usually
* triggers it */
- if ((btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) &&
- !(num_active + num_held))
- ag_res.audio_handle = btif_hf_cb[idx].handle;
+ if ((control_block.call_setup_state == BTHF_CALL_STATE_IDLE) &&
+ !(num_active + num_held) && is_active_device(*bd_addr)) {
+ ag_res.audio_handle = control_block.handle;
+ }
res = BTA_AG_OUT_CALL_ALERT_RES;
break;
default:
- BTIF_TRACE_ERROR("%s: Incorrect new ringing call state", __func__);
+ BTIF_TRACE_ERROR("%s: Incorrect call state prev=%d, now=%d", __func__,
+ control_block.call_setup_state, call_setup_state);
status = BT_STATUS_PARM_INVALID;
break;
}
BTIF_TRACE_DEBUG("%s: Call setup state changed. res=%d, audio_handle=%d",
__func__, res, ag_res.audio_handle);
- if (res) BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
+ if (res != 0xFF) {
+ BTA_AgResult(control_block.handle, res, ag_res);
+ }
/* if call setup is idle, we have already updated call indicator, jump out
*/
if (call_setup_state == BTHF_CALL_STATE_IDLE) {
/* check & update callheld */
- if ((num_held > 0) && (num_active > 0))
- send_indicator_update(BTA_AG_IND_CALLHELD, 1);
- goto update_call_states;
+ if ((num_held > 0) && (num_active > 0)) {
+ send_indicator_update(control_block, BTA_AG_IND_CALLHELD, 1);
+ }
+ UpdateCallStates(&btif_hf_cb[idx], num_active, num_held,
+ call_setup_state);
+ return status;
}
}
- memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
-
- /* per the errata 2043, call=1 implies atleast one call is in progress
- *(active/held)
- ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
- ** Handle call indicator change
+ /**
+ * Handle call indicator change
+ *
+ * Per the errata 2043, call=1 implies at least one call is in progress
+ * (active or held)
+ * See: https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
+ *
**/
- if (!activeCallUpdated &&
+ if (!active_call_updated &&
((num_active + num_held) !=
- (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held))) {
- BTIF_TRACE_DEBUG("%s: Active call states changed. old: %d new: %d",
- __func__, btif_hf_cb[idx].num_active, num_active);
- send_indicator_update(BTA_AG_IND_CALL,
- ((num_active + num_held) > 0) ? 1 : 0);
+ (control_block.num_active + control_block.num_held))) {
+ VLOG(1) << __func__ << ": in progress call states changed, active=["
+ << control_block.num_active << "->" << num_active << "], held=["
+ << control_block.num_held << "->" << num_held;
+ send_indicator_update(control_block, BTA_AG_IND_CALL,
+ ((num_active + num_held) > 0) ? BTA_AG_CALL_ACTIVE
+ : BTA_AG_CALL_INACTIVE);
}
/* Held Changed? */
- if (num_held != btif_hf_cb[idx].num_held ||
- ((num_active == 0) && ((num_held + btif_hf_cb[idx].num_held) > 1))) {
+ if (num_held != control_block.num_held ||
+ ((num_active == 0) && ((num_held + control_block.num_held) > 1))) {
BTIF_TRACE_DEBUG("%s: Held call states changed. old: %d new: %d", __func__,
- btif_hf_cb[idx].num_held, num_held);
- send_indicator_update(BTA_AG_IND_CALLHELD,
+ control_block.num_held, num_held);
+ send_indicator_update(control_block, BTA_AG_IND_CALLHELD,
((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
}
/* Calls Swapped? */
- if ((call_setup_state == btif_hf_cb[idx].call_setup_state) &&
- (num_active && num_held) && (num_active == btif_hf_cb[idx].num_active) &&
- (num_held == btif_hf_cb[idx].num_held)) {
+ if ((call_setup_state == control_block.call_setup_state) &&
+ (num_active && num_held) && (num_active == control_block.num_active) &&
+ (num_held == control_block.num_held)) {
BTIF_TRACE_DEBUG("%s: Calls swapped", __func__);
- send_indicator_update(BTA_AG_IND_CALLHELD, 1);
+ send_indicator_update(control_block, BTA_AG_IND_CALLHELD, 1);
}
-update_call_states:
- for (i = 0; i < btif_max_hf_clients; i++) {
- if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
- btif_hf_cb[i].num_active = num_active;
- btif_hf_cb[i].num_held = num_held;
- btif_hf_cb[i].call_setup_state = call_setup_state;
- }
+ /* When call is hung up and still there is another call is in active,
+ * some of the HF cannot acquire the call states by its own. If HF try
+ * to terminate a call, it may not send the command AT+CHUP because the
+ * call states are not updated properly. HF should get informed the call
+ * status forcibly.
+ */
+ if ((control_block.num_active == num_active && num_active != 0) &&
+ (control_block.num_held != num_held && num_held == 0)) {
+ tBTA_AG_RES_DATA ag_res = {};
+ ag_res.ind.id = BTA_AG_IND_CALL;
+ ag_res.ind.value = num_active;
+ BTA_AgResult(control_block.handle, BTA_AG_IND_RES_ON_DEMAND, ag_res);
}
+
+ UpdateCallStates(&btif_hf_cb[idx], num_active, num_held, call_setup_state);
return status;
}
-/*******************************************************************************
- *
- * Function btif_hf_is_call_idle
- *
- * Description returns true if no call is in progress
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-bool btif_hf_is_call_idle(void) {
- if (bt_hf_callbacks == NULL) return true;
-
- for (int i = 0; i < btif_max_hf_clients; ++i) {
- if ((btif_hf_cb[i].call_setup_state != BTHF_CALL_STATE_IDLE) ||
- ((btif_hf_cb[i].num_held + btif_hf_cb[i].num_active) > 0))
- return false;
- }
-
- return true;
-}
-
-/*******************************************************************************
- *
- * Function btif_hf_call_terminated_recently
- *
- * Description Checks if a call has been terminated
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-bool btif_hf_call_terminated_recently() {
- struct timespec now;
-
- clock_gettime(CLOCK_MONOTONIC, &now);
- if (now.tv_sec <
- btif_hf_cb[0].call_end_timestamp.tv_sec + BTIF_HF_CALL_END_TIMEOUT) {
- return true;
- } else {
- btif_hf_cb[0].call_end_timestamp.tv_sec = 0;
- return false;
- }
-}
-
-/*******************************************************************************
- *
- * Function cleanup
- *
- * Description Closes the HF interface
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static void cleanup(void) {
+void HeadsetInterface::Cleanup() {
BTIF_TRACE_EVENT("%s", __func__);
btif_queue_cleanup(UUID_SERVCLASS_AG_HANDSFREE);
@@ -1501,65 +1309,41 @@
#else
btif_disable_service(BTA_HSP_SERVICE_ID);
#endif
- bt_hf_callbacks = NULL;
+ bt_hf_callbacks = nullptr;
}
}
-/*******************************************************************************
- *
- * Function configure_wbs
- *
- * Description set to over-ride the current WBS configuration.
- * It will not send codec setting cmd to the controller now.
- * It just change the configure.
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t configure_wbs(RawAddress* bd_addr,
- bthf_wbs_config_t config) {
+bt_status_t HeadsetInterface::SetScoAllowed(bool value) {
CHECK_BTHF_INIT();
-
- int idx = btif_hf_idx_by_bdaddr(bd_addr);
-
- if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
- BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
- return BT_STATUS_FAIL;
- }
-
- BTIF_TRACE_EVENT("%s config is %d", __func__, config);
- if (config == BTHF_WBS_YES)
- BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_MSBC);
- else if (config == BTHF_WBS_NO)
- BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_CVSD);
- else
- BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_NONE);
-
+ BTA_AgSetScoAllowed(value);
return BT_STATUS_SUCCESS;
}
-static const bthf_interface_t bthfInterface = {
- sizeof(bthfInterface),
- init,
- connect,
- disconnect,
- connect_audio,
- disconnect_audio,
- start_voice_recognition,
- stop_voice_recognition,
- volume_control,
- device_status_notification,
- cops_response,
- cind_response,
- formatted_at_response,
- at_response,
- clcc_response,
- phone_state_change,
- cleanup,
- configure_wbs,
- bind_response,
- set_sco_allowed,
-};
+bt_status_t HeadsetInterface::SendBsir(bool value, RawAddress* bd_addr) {
+ CHECK_BTHF_INIT();
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+ if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
+ BTIF_TRACE_ERROR("%s: Invalid index %d for %s", __func__, idx,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
+ }
+ if (!is_connected(bd_addr)) {
+ BTIF_TRACE_ERROR("%s: %s not connected", __func__,
+ bd_addr->ToString().c_str());
+ return BT_STATUS_FAIL;
+ }
+ tBTA_AG_RES_DATA ag_result = {};
+ ag_result.state = value;
+ BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_INBAND_RING_RES, ag_result);
+ return BT_STATUS_SUCCESS;
+}
+
+bt_status_t HeadsetInterface::SetActiveDevice(RawAddress* active_device_addr) {
+ CHECK_BTHF_INIT();
+ active_bda = *active_device_addr;
+ BTA_AgSetActiveDevice(*active_device_addr);
+ return BT_STATUS_SUCCESS;
+}
/*******************************************************************************
*
@@ -1570,19 +1354,24 @@
* Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
*
******************************************************************************/
-bt_status_t btif_hf_execute_service(bool b_enable) {
- const char* p_service_names[] = BTIF_HF_SERVICE_NAMES;
- int i;
+bt_status_t ExecuteService(bool b_enable) {
+ const char* service_names_raw[] = BTIF_HF_SERVICE_NAMES;
+ std::vector<std::string> service_names;
+ for (const char* service_name_raw : service_names_raw) {
+ if (service_name_raw) {
+ service_names.emplace_back(service_name_raw);
+ }
+ }
if (b_enable) {
/* Enable and register with BTA-AG */
- BTA_AgEnable(BTA_AG_PARSE, bte_hf_evt);
- for (i = 0; i < btif_max_hf_clients; i++) {
+ BTA_AgEnable(bte_hf_evt);
+ for (uint8_t app_id = 0; app_id < btif_max_hf_clients; app_id++) {
BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY, btif_hf_features,
- p_service_names, bthf_hf_id[i]);
+ service_names, app_id);
}
} else {
/* De-register AG */
- for (i = 0; i < btif_max_hf_clients; i++) {
+ for (int i = 0; i < btif_max_hf_clients; i++) {
BTA_AgDeregister(btif_hf_cb[i].handle);
}
/* Disable AG */
@@ -1600,7 +1389,10 @@
* Returns bthf_interface_t
*
******************************************************************************/
-const bthf_interface_t* btif_hf_get_interface() {
- BTIF_TRACE_EVENT("%s", __func__);
- return &bthfInterface;
+Interface* GetInterface() {
+ VLOG(0) << __func__;
+ return HeadsetInterface::GetInstance();
}
+
+} // namespace headset
+} // namespace bluetooth
diff --git a/btif/src/btif_hf_client.cc b/btif/src/btif_hf_client.cc
index c1f3c8b..7c65bf7 100644
--- a/btif/src/btif_hf_client.cc
+++ b/btif/src/btif_hf_client.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -109,6 +109,18 @@
char btif_hf_client_version[PROPERTY_VALUE_MAX];
+static const char* dump_hf_client_conn_state(uint16_t event) {
+ switch (event) {
+ CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED)
+ CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_CONNECTING)
+ CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_CONNECTED)
+ CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED)
+ CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_DISCONNECTING)
+ default:
+ return "UNKNOWN MSG ID";
+ }
+}
+
#define CHECK_BTHF_CLIENT_INIT() \
do { \
if (bt_hf_client_callbacks == NULL) { \
@@ -126,7 +138,7 @@
return BT_STATUS_NOT_READY; \
} else if ((cb)->state != BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) { \
BTIF_TRACE_WARNING("BTHF CLIENT: %s: SLC connection not up. state=%s", \
- __func__, dump_hf_conn_state((cb)->state)); \
+ __func__, dump_hf_client_conn_state((cb)->state)); \
return BT_STATUS_NOT_READY; \
} else { \
BTIF_TRACE_EVENT("BTHF CLIENT: %s", __func__); \
@@ -162,7 +174,7 @@
switch (event) {
case BTIF_HF_CLIENT_CB_AUDIO_CONNECTING: {
HAL_CBACK(bt_hf_client_callbacks, audio_state_cb, &cb->peer_bda,
- (bthf_client_audio_state_t)BTHF_AUDIO_STATE_CONNECTING);
+ (bthf_client_audio_state_t)BTHF_CLIENT_AUDIO_STATE_CONNECTING);
} break;
default: {
BTIF_TRACE_WARNING("%s: : Unknown event 0x%x", __func__, event);
diff --git a/btif/src/btif_hh.cc b/btif/src/btif_hh.cc
index 7c7352e..c5a9021 100644
--- a/btif/src/btif_hh.cc
+++ b/btif/src/btif_hh.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -503,6 +503,7 @@
bool btif_hh_copy_hid_info(tBTA_HH_DEV_DSCP_INFO* dest,
tBTA_HH_DEV_DSCP_INFO* src) {
+ memset(dest, 0, sizeof(tBTA_HH_DEV_DSCP_INFO));
dest->descriptor.dl_len = 0;
if (src->descriptor.dl_len > 0) {
dest->descriptor.dsc_list = (uint8_t*)osi_malloc(src->descriptor.dl_len);
@@ -533,10 +534,6 @@
bt_status_t btif_hh_virtual_unplug(const RawAddress* bd_addr) {
BTIF_TRACE_DEBUG("%s", __func__);
btif_hh_device_t* p_dev;
- char bd_str[18];
- snprintf(bd_str, sizeof(bd_str), "%02X:%02X:%02X:%02X:%02X:%02X",
- bd_addr->address[0], bd_addr->address[1], bd_addr->address[2],
- bd_addr->address[3], bd_addr->address[4], bd_addr->address[5]);
p_dev = btif_hh_find_dev_by_bda(*bd_addr);
if ((p_dev != NULL) && (p_dev->dev_status == BTHH_CONN_STATE_CONNECTED) &&
(p_dev->attr_mask & HID_VIRTUAL_CABLE)) {
@@ -547,7 +544,13 @@
BTA_HhSendCtrl(p_dev->dev_handle, BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG);
return BT_STATUS_SUCCESS;
} else {
- BTIF_TRACE_ERROR("%s: Error, device %s not opened.", __func__, bd_str);
+ BTIF_TRACE_ERROR("%s: Error, device %s not opened, status = %d", __func__,
+ bd_addr->ToString().c_str(), btif_hh_cb.status);
+ if ((btif_hh_cb.pending_conn_address == *bd_addr) &&
+ (btif_hh_cb.status == BTIF_HH_DEV_CONNECTING)) {
+ btif_hh_cb.status = (BTIF_HH_STATUS)BTIF_HH_DEV_DISCONNECTED;
+ btif_hh_cb.pending_conn_address = RawAddress::kEmpty;
+ }
return BT_STATUS_FAIL;
}
}
@@ -602,6 +605,7 @@
pagescan mode, we will do 2 retries to connect before giving up */
tBTA_SEC sec_mask = BTUI_HH_SECURITY;
btif_hh_cb.status = BTIF_HH_DEV_CONNECTING;
+ btif_hh_cb.pending_conn_address = *bd_addr;
BTA_HhOpen(*bd_addr, BTA_HH_PROTO_RPT_MODE, sec_mask);
// TODO(jpawlowski); make cback accept const and remove tmp!
@@ -749,6 +753,7 @@
case BTA_HH_OPEN_EVT:
BTIF_TRACE_WARNING("%s: BTA_HH_OPN_EVT: handle=%d, status =%d", __func__,
p_data->conn.handle, p_data->conn.status);
+ btif_hh_cb.pending_conn_address = RawAddress::kEmpty;
if (p_data->conn.status == BTA_HH_OK) {
p_dev = btif_hh_find_connected_dev_by_handle(p_data->conn.handle);
if (p_dev == NULL) {
@@ -1264,17 +1269,14 @@
CHECK_BTHH_INIT();
BTIF_TRACE_EVENT("BTHH: %s", __func__);
btif_hh_device_t* p_dev;
- char bd_str[18];
- snprintf(bd_str, sizeof(bd_str), "%02X:%02X:%02X:%02X:%02X:%02X",
- bd_addr->address[0], bd_addr->address[1], bd_addr->address[2],
- bd_addr->address[3], bd_addr->address[4], bd_addr->address[5]);
if (btif_hh_cb.status == BTIF_HH_DISABLED) {
BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
return BT_STATUS_FAIL;
}
p_dev = btif_hh_find_dev_by_bda(*bd_addr);
if (!p_dev) {
- BTIF_TRACE_ERROR("%s: Error, device %s not opened.", __func__, bd_str);
+ BTIF_TRACE_ERROR("%s: Error, device %s not opened.", __func__,
+ bd_addr->ToString().c_str());
return BT_STATUS_FAIL;
}
btif_transfer_context(btif_hh_handle_evt, BTIF_HH_VUP_REQ_EVT, (char*)bd_addr,
@@ -1364,6 +1366,7 @@
return BT_STATUS_FAIL;
}
+ memset(&dscp_info, 0, sizeof(dscp_info));
dscp_info.vendor_id = hid_info.vendor_id;
dscp_info.product_id = hid_info.product_id;
dscp_info.version = hid_info.version;
@@ -1480,7 +1483,7 @@
return BT_STATUS_FAIL;
} else if (((int)reportType) <= BTA_HH_RPTT_RESRV ||
((int)reportType) > BTA_HH_RPTT_FEATURE) {
- LOG(ERROR) << " Error, device" << *bd_addr << " not opened";
+ LOG(ERROR) << " Error, report type=" << +reportType << " not supported";
return BT_STATUS_FAIL;
} else {
BTA_HhGetReport(p_dev->dev_handle, reportType, reportId, bufferSize);
@@ -1517,7 +1520,7 @@
return BT_STATUS_FAIL;
} else if (((int)reportType) <= BTA_HH_RPTT_RESRV ||
((int)reportType) > BTA_HH_RPTT_FEATURE) {
- LOG(ERROR) << " Error, device" << *bd_addr << " not opened";
+ LOG(ERROR) << " Error, report type=" << +reportType << " not supported";
return BT_STATUS_FAIL;
} else {
int hex_bytes_filled;
diff --git a/btif/src/btif_hl.cc b/btif/src/btif_hl.cc
index 4f701fb..a317f79 100644
--- a/btif/src/btif_hl.cc
+++ b/btif/src/btif_hl.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/src/btif_mce.cc b/btif/src/btif_mce.cc
index 53102e8..d9326db 100644
--- a/btif/src/btif_mce.cc
+++ b/btif/src/btif_mce.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2014 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +38,6 @@
#include "bta_api.h"
#include "bta_mce_api.h"
#include "btif_common.h"
-#include "btif_profile_queue.h"
#include "btif_util.h"
/*****************************************************************************
diff --git a/btif/src/btif_pan.cc b/btif/src/btif_pan.cc
index 7b2c861..9828c4b 100644
--- a/btif/src/btif_pan.cc
+++ b/btif/src/btif_pan.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
#define LOG_TAG "bt_btif_pan"
+#include <base/bind.h>
#include <base/logging.h>
#include <ctype.h>
#include <errno.h>
@@ -53,6 +54,7 @@
#include "bt_common.h"
#include "bta_api.h"
+#include "bta_closure_api.h"
#include "bta_pan_api.h"
#include "btif_common.h"
#include "btif_pan_internal.h"
@@ -105,13 +107,13 @@
uint32_t user_id);
static void btpan_cleanup_conn(btpan_conn_t* conn);
static void bta_pan_callback(tBTA_PAN_EVT event, tBTA_PAN* p_data);
-static void btu_exec_tap_fd_read(void* p_param);
+static void btu_exec_tap_fd_read(const int fd);
static btpan_interface_t pan_if = {
sizeof(pan_if), btpan_jni_init, btpan_enable, btpan_get_local_role,
btpan_connect, btpan_disconnect, btpan_jni_cleanup};
-btpan_interface_t* btif_pan_get_interface() { return &pan_if; }
+const btpan_interface_t* btif_pan_get_interface() { return &pan_if; }
/*******************************************************************************
**
@@ -286,7 +288,7 @@
// set mac addr
memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, devname, IFNAMSIZ - 1);
+ strlcpy(ifr.ifr_name, devname, IFNAMSIZ);
err = ioctl(sk, SIOCGIFHWADDR, &ifr);
if (err < 0) {
BTIF_TRACE_ERROR(
@@ -296,7 +298,7 @@
return -1;
}
- strncpy(ifr.ifr_name, devname, IFNAMSIZ - 1);
+ strlcpy(ifr.ifr_name, devname, IFNAMSIZ);
memcpy(ifr.ifr_hwaddr.sa_data, addr->address, 6);
/* The IEEE has specified that the most significant bit of the most
@@ -324,7 +326,7 @@
// bring it up
memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1);
+ strlcpy(ifr.ifr_name, devname, IF_NAMESIZE);
ifr.ifr_flags |= IFF_UP;
ifr.ifr_flags |= IFF_MULTICAST;
@@ -350,7 +352,7 @@
if (sk < 0) return -1;
memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1);
+ strlcpy(ifr.ifr_name, devname, IF_NAMESIZE);
ifr.ifr_flags &= ~IFF_UP;
@@ -367,7 +369,8 @@
btpan_cb.flow = enable;
if (enable) {
btsock_thread_add_fd(pan_pth, btpan_cb.tap_fd, 0, SOCK_THREAD_FD_RD, 0);
- bta_dmexecutecallback(btu_exec_tap_fd_read, INT_TO_PTR(btpan_cb.tap_fd));
+ do_in_bta_thread(FROM_HERE,
+ base::Bind(btu_exec_tap_fd_read, btpan_cb.tap_fd));
}
}
@@ -387,7 +390,7 @@
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- strncpy(ifr.ifr_name, TAP_IF_NAME, IFNAMSIZ);
+ strlcpy(ifr.ifr_name, TAP_IF_NAME, IFNAMSIZ);
/* try to create the device */
err = ioctl(fd, TUNSETIFF, (void*)&ifr);
@@ -663,9 +666,8 @@
}
#define IS_EXCEPTION(e) ((e) & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL))
-static void btu_exec_tap_fd_read(void* p_param) {
+static void btu_exec_tap_fd_read(int fd) {
struct pollfd ufd;
- int fd = PTR_TO_INT(p_param);
if (fd == INVALID_FD || fd != btpan_cb.tap_fd) return;
@@ -770,6 +772,7 @@
btpan_cb.tap_fd = INVALID_FD;
btpan_tap_close(fd);
btif_pan_close_all_conns();
- } else if (flags & SOCK_THREAD_FD_RD)
- bta_dmexecutecallback(btu_exec_tap_fd_read, INT_TO_PTR(fd));
+ } else if (flags & SOCK_THREAD_FD_RD) {
+ do_in_bta_thread(FROM_HERE, base::Bind(btu_exec_tap_fd_read, fd));
+ }
}
diff --git a/btif/src/btif_profile_queue.cc b/btif/src/btif_profile_queue.cc
index 152f11d..10acade 100644
--- a/btif/src/btif_profile_queue.cc
+++ b/btif/src/btif_profile_queue.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,129 +28,115 @@
#include "btif_profile_queue.h"
+#include <base/bind.h>
#include <base/logging.h>
+#include <base/strings/stringprintf.h>
#include <string.h>
+#include <list>
#include "bt_common.h"
#include "btif_common.h"
-#include "osi/include/allocator.h"
-#include "osi/include/list.h"
#include "stack_manager.h"
/*******************************************************************************
* Local type definitions
******************************************************************************/
-typedef enum {
- BTIF_QUEUE_CONNECT_EVT,
- BTIF_QUEUE_ADVANCE_EVT,
- BTIF_QUEUE_CLEANUP_EVT
-} btif_queue_event_t;
+// Class to store connect info.
+class ConnectNode {
+ public:
+ ConnectNode(const RawAddress& address, uint16_t uuid,
+ btif_connect_cb_t connect_cb)
+ : address_(address), uuid_(uuid), busy_(false), connect_cb_(connect_cb) {}
-typedef struct {
- RawAddress bda;
- uint16_t uuid;
- bool busy;
- btif_connect_cb_t connect_cb;
-} connect_node_t;
+ std::string ToString() const {
+ return base::StringPrintf("address=%s UUID=%04X busy=%s",
+ address_.ToString().c_str(), uuid_,
+ (busy_) ? "true" : "false");
+ }
+
+ const RawAddress& address() const { return address_; }
+ uint16_t uuid() const { return uuid_; }
+
+ /**
+ * Initiate the connection.
+ *
+ * @return BT_STATUS_SUCCESS on success, othewise the corresponding error
+ * code. Note: if a previous connect request hasn't been completed, the
+ * return value is BT_STATUS_SUCCESS.
+ */
+ bt_status_t connect() {
+ if (busy_) return BT_STATUS_SUCCESS;
+ busy_ = true;
+ return connect_cb_(&address_, uuid_);
+ }
+
+ private:
+ RawAddress address_;
+ uint16_t uuid_;
+ bool busy_;
+ btif_connect_cb_t connect_cb_;
+};
/*******************************************************************************
* Static variables
******************************************************************************/
-static list_t* connect_queue;
+static std::list<ConnectNode> connect_queue;
-static const size_t MAX_REASONABLE_REQUESTS = 10;
+static const size_t MAX_REASONABLE_REQUESTS = 20;
/*******************************************************************************
* Queue helper functions
******************************************************************************/
-static void queue_int_add(connect_node_t* p_param) {
- if (!connect_queue) {
- LOG_INFO(LOG_TAG, "%s: allocating profile queue", __func__);
- connect_queue = list_new(osi_free);
- CHECK(connect_queue != NULL);
- }
-
+static void queue_int_add(uint16_t uuid, const RawAddress& bda,
+ btif_connect_cb_t connect_cb) {
// Sanity check to make sure we're not leaking connection requests
- CHECK(list_length(connect_queue) < MAX_REASONABLE_REQUESTS);
+ CHECK(connect_queue.size() < MAX_REASONABLE_REQUESTS);
- for (const list_node_t* node = list_begin(connect_queue);
- node != list_end(connect_queue); node = list_next(node)) {
- if (((connect_node_t*)list_node(node))->uuid == p_param->uuid) {
- LOG_ERROR(LOG_TAG,
- "%s dropping duplicate connection request UUID=%04X, "
- "bd_addr=%s, busy=%d",
- __func__, p_param->uuid, p_param->bda.ToString().c_str(),
- p_param->busy);
+ ConnectNode param(bda, uuid, connect_cb);
+ for (const auto& node : connect_queue) {
+ if (node.uuid() == param.uuid() && node.address() == param.address()) {
+ LOG_ERROR(LOG_TAG, "%s: dropping duplicate connection request: %s",
+ __func__, param.ToString().c_str());
return;
}
}
- LOG_INFO(
- LOG_TAG, "%s: adding connection request UUID=%04X, bd_addr=%s, busy=%d",
- __func__, p_param->uuid, p_param->bda.ToString().c_str(), p_param->busy);
- connect_node_t* p_node = (connect_node_t*)osi_malloc(sizeof(connect_node_t));
- memcpy(p_node, p_param, sizeof(connect_node_t));
- list_append(connect_queue, p_node);
+ LOG_INFO(LOG_TAG, "%s: adding connection request: %s", __func__,
+ param.ToString().c_str());
+ connect_queue.push_back(param);
+
+ btif_queue_connect_next();
}
static void queue_int_advance() {
- if (connect_queue && !list_is_empty(connect_queue)) {
- connect_node_t* p_head = (connect_node_t*)list_front(connect_queue);
- LOG_INFO(LOG_TAG,
- "%s: removing connection request UUID=%04X, bd_addr=%s, busy=%d",
- __func__, p_head->uuid, p_head->bda.ToString().c_str(),
- p_head->busy);
- list_remove(connect_queue, p_head);
- }
+ if (connect_queue.empty()) return;
+
+ const ConnectNode& head = connect_queue.front();
+ LOG_INFO(LOG_TAG, "%s: removing connection request: %s", __func__,
+ head.ToString().c_str());
+ connect_queue.pop_front();
+
+ btif_queue_connect_next();
}
-static void queue_int_cleanup(uint16_t* p_uuid) {
- if (!p_uuid) {
- LOG_ERROR(LOG_TAG, "%s: UUID is null", __func__);
- return;
- }
- uint16_t uuid = *p_uuid;
+static void queue_int_cleanup(uint16_t uuid) {
LOG_INFO(LOG_TAG, "%s: UUID=%04X", __func__, uuid);
- if (!connect_queue) {
- return;
- }
- connect_node_t* connection_request;
- const list_node_t* node = list_begin(connect_queue);
- while (node && node != list_end(connect_queue)) {
- connection_request = (connect_node_t*)list_node(node);
- node = list_next(node);
- if (connection_request->uuid == uuid) {
- LOG_INFO(LOG_TAG,
- "%s: removing connection request UUID=%04X, bd_addr=%s, busy=%d",
- __func__, connection_request->uuid,
- connection_request->bda.ToString().c_str(),
- connection_request->busy);
- list_remove(connect_queue, connection_request);
+
+ for (auto it = connect_queue.begin(); it != connect_queue.end();) {
+ auto it_prev = it++;
+ const ConnectNode& node = *it_prev;
+ if (node.uuid() == uuid) {
+ LOG_INFO(LOG_TAG, "%s: removing connection request: %s", __func__,
+ node.ToString().c_str());
+ connect_queue.erase(it_prev);
}
}
}
-static void queue_int_handle_evt(uint16_t event, char* p_param) {
- switch (event) {
- case BTIF_QUEUE_CONNECT_EVT:
- queue_int_add((connect_node_t*)p_param);
- break;
-
- case BTIF_QUEUE_ADVANCE_EVT:
- queue_int_advance();
- break;
-
- case BTIF_QUEUE_CLEANUP_EVT:
- queue_int_cleanup((uint16_t*)(p_param));
- return;
- }
-
- if (stack_manager_get_interface()->get_stack_is_running())
- btif_queue_connect_next();
-}
+static void queue_int_release() { connect_queue.clear(); }
/*******************************************************************************
*
@@ -164,14 +150,8 @@
******************************************************************************/
bt_status_t btif_queue_connect(uint16_t uuid, const RawAddress* bda,
btif_connect_cb_t connect_cb) {
- connect_node_t node;
- memset(&node, 0, sizeof(connect_node_t));
- node.bda = *bda;
- node.uuid = uuid;
- node.connect_cb = connect_cb;
-
- return btif_transfer_context(queue_int_handle_evt, BTIF_QUEUE_CONNECT_EVT,
- (char*)&node, sizeof(connect_node_t), NULL);
+ return do_in_jni_thread(FROM_HERE,
+ base::Bind(&queue_int_add, uuid, *bda, connect_cb));
}
/*******************************************************************************
@@ -184,8 +164,7 @@
*
******************************************************************************/
void btif_queue_cleanup(uint16_t uuid) {
- btif_transfer_context(queue_int_handle_evt, BTIF_QUEUE_CLEANUP_EVT,
- (char*)&uuid, sizeof(uint16_t), NULL);
+ do_in_jni_thread(FROM_HERE, base::Bind(&queue_int_cleanup, uuid));
}
/*******************************************************************************
@@ -199,27 +178,23 @@
*
******************************************************************************/
void btif_queue_advance() {
- btif_transfer_context(queue_int_handle_evt, BTIF_QUEUE_ADVANCE_EVT, NULL, 0,
- NULL);
+ do_in_jni_thread(FROM_HERE, base::Bind(&queue_int_advance));
}
-// This function dispatches the next pending connect request. It is called from
-// stack_manager when the stack comes up.
bt_status_t btif_queue_connect_next(void) {
- if (!connect_queue || list_is_empty(connect_queue)) return BT_STATUS_FAIL;
+ // The call must be on the JNI thread, otherwise the access to connect_queue
+ // is not thread-safe.
+ CHECK(is_on_jni_thread());
- connect_node_t* p_head = (connect_node_t*)list_front(connect_queue);
+ if (connect_queue.empty()) return BT_STATUS_FAIL;
+ if (!stack_manager_get_interface()->get_stack_is_running())
+ return BT_STATUS_FAIL;
- LOG_INFO(LOG_TAG,
- "%s: executing connection request UUID=%04X, bd_addr=%s, busy=%d",
- __func__, p_head->uuid, p_head->bda.ToString().c_str(),
- p_head->busy);
- // If the queue is currently busy, we return success anyway,
- // since the connection has been queued...
- if (p_head->busy) return BT_STATUS_SUCCESS;
+ ConnectNode& head = connect_queue.front();
- p_head->busy = true;
- return p_head->connect_cb(&p_head->bda, p_head->uuid);
+ LOG_INFO(LOG_TAG, "%s: executing connection request: %s", __func__,
+ head.ToString().c_str());
+ return head.connect();
}
/*******************************************************************************
@@ -233,6 +208,9 @@
******************************************************************************/
void btif_queue_release() {
LOG_INFO(LOG_TAG, "%s", __func__);
- list_free(connect_queue);
- connect_queue = NULL;
+ if (do_in_jni_thread(FROM_HERE, base::Bind(&queue_int_release)) !=
+ BT_STATUS_SUCCESS) {
+ // Scheduling failed - the thread to schedule on is probably dead
+ queue_int_release();
+ }
}
diff --git a/btif/src/btif_rc.cc b/btif/src/btif_rc.cc
index edd0730..c226b5f 100644
--- a/btif/src/btif_rc.cc
+++ b/btif/src/btif_rc.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@
#include "bta_av_api.h"
#include "btif_av.h"
#include "btif_common.h"
+#include "btif_rc.h"
#include "btif_util.h"
#include "btu.h"
#include "device/include/interop.h"
@@ -49,6 +50,7 @@
#include "osi/include/list.h"
#include "osi/include/osi.h"
#include "osi/include/properties.h"
+
#define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
/*****************************************************************************
@@ -89,7 +91,7 @@
#define CHECK_RC_CONNECTED(p_dev) \
do { \
- if ((p_dev) == NULL || (p_dev)->rc_connected == false) { \
+ if ((p_dev) == NULL || !(p_dev)->rc_connected) { \
BTIF_TRACE_WARNING("%s: called when RC is not connected", __func__); \
return BT_STATUS_NOT_READY; \
} \
@@ -97,7 +99,7 @@
#define CHECK_BR_CONNECTED(p_dev) \
do { \
- if ((p_dev) == NULL || (p_dev)->br_connected == false) { \
+ if ((p_dev) == NULL || !(p_dev)->br_connected) { \
BTIF_TRACE_WARNING("%s: called when BR is not connected", __func__); \
return BT_STATUS_NOT_READY; \
} \
@@ -285,10 +287,14 @@
tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp);
static void handle_app_attr_val_txt_response(tBTA_AV_META_MSG* pmeta_msg,
tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp);
+static void cleanup_app_attr_val_txt_response(
+ btif_rc_player_app_settings_t* p_app_settings);
static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg,
tAVRC_GET_PLAY_STATUS_RSP* p_rsp);
static void handle_set_addressed_player_response(tBTA_AV_META_MSG* pmeta_msg,
tAVRC_RSP* p_rsp);
+static void cleanup_btrc_folder_items(btrc_folder_items_t* btrc_items,
+ uint8_t item_count);
static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,
tAVRC_GET_ATTRS_RSP* p_rsp);
static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg,
@@ -319,8 +325,9 @@
btrc_folder_items_t* btrc_item);
void get_folder_item_type_player(const tAVRC_ITEM* avrc_item,
btrc_folder_items_t* btrc_item);
-static bt_status_t get_folder_items_cmd(RawAddress* bd_addr, uint8_t scope,
- uint8_t start_item, uint8_t num_items);
+static bt_status_t get_folder_items_cmd(const RawAddress& bd_addr,
+ uint8_t scope, uint32_t start_item,
+ uint32_t end_item);
static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* p_param,
uint8_t ctype, uint8_t label,
@@ -348,8 +355,7 @@
/*****************************************************************************
* Externs
*****************************************************************************/
-extern bool btif_hf_call_terminated_recently();
-extern bool check_cod(const RawAddress* remote_bdaddr, uint32_t cod);
+extern bool check_cod(const RawAddress& remote_bdaddr, uint32_t cod);
/*****************************************************************************
* Functions
@@ -392,13 +398,13 @@
return connected_devices;
}
-btif_rc_device_cb_t* btif_rc_get_device_by_bda(const RawAddress* bd_addr) {
- VLOG(1) << __func__ << ": bd_addr: " << *bd_addr;
+btif_rc_device_cb_t* btif_rc_get_device_by_bda(const RawAddress& bd_addr) {
+ VLOG(1) << __func__ << ": bd_addr: " << bd_addr;
for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
if ((btif_rc_cb.rc_multi_cb[idx].rc_state !=
BTRC_CONNECTION_STATE_DISCONNECTED) &&
- btif_rc_cb.rc_multi_cb[idx].rc_addr == *bd_addr) {
+ btif_rc_cb.rc_multi_cb[idx].rc_addr == bd_addr) {
return (&btif_rc_cb.rc_multi_cb[idx]);
}
}
@@ -481,23 +487,30 @@
}
BTIF_TRACE_DEBUG("%s: Update rc features to CTRL: %d", __func__, rc_features);
- RawAddress rc_addr = p_dev->rc_addr;
- HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
+ do_in_jni_thread(FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->getrcfeatures_cb,
+ p_dev->rc_addr, rc_features));
}
void handle_rc_features(btif_rc_device_cb_t* p_dev) {
- RawAddress rc_addr = p_dev->rc_addr;
CHECK(bt_rc_callbacks);
btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
- RawAddress avdtp_addr = btif_av_get_addr();
+ RawAddress avdtp_source_active_peer_addr = btif_av_source_active_peer();
+ RawAddress avdtp_sink_active_peer_addr = btif_av_sink_active_peer();
- BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
- avdtp_addr.ToString().c_str(), rc_addr.ToString().c_str());
+ BTIF_TRACE_DEBUG(
+ "%s: AVDTP Source Active Peer Address: %s "
+ "AVDTP Sink Active Peer Address: %s "
+ "AVCTP address: %s",
+ __func__, avdtp_source_active_peer_addr.ToString().c_str(),
+ avdtp_sink_active_peer_addr.ToString().c_str(),
+ p_dev->rc_addr.ToString().c_str());
- if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr) ||
- absolute_volume_disabled() || avdtp_addr != rc_addr) {
+ if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &p_dev->rc_addr) ||
+ absolute_volume_disabled() ||
+ (avdtp_source_active_peer_addr != p_dev->rc_addr &&
+ avdtp_sink_active_peer_addr != p_dev->rc_addr)) {
p_dev->rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
}
@@ -518,7 +531,7 @@
}
BTIF_TRACE_DEBUG("%s: rc_features: 0x%x", __func__, rc_features);
- HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features);
+ HAL_CBACK(bt_rc_callbacks, remote_features_cb, p_dev->rc_addr, rc_features);
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
BTIF_TRACE_DEBUG(
@@ -572,9 +585,10 @@
* to a browse when not connected to the control channel over AVRCP is
* probably not preferred anyways. */
if (p_rc_br_open->status == BTA_AV_SUCCESS) {
- RawAddress rc_addr = p_dev->rc_addr;
p_dev->br_connected = true;
- HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, true, true, &rc_addr);
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->connection_state_cb, true,
+ true, p_dev->rc_addr));
}
}
@@ -632,8 +646,9 @@
p_dev->rc_playing_uid = RC_INVALID_TRACK_ID;
if (bt_rc_ctrl_callbacks != NULL) {
- RawAddress rc_addr = p_dev->rc_addr;
- HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, true, false, &rc_addr);
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->connection_state_cb, true,
+ false, p_dev->rc_addr));
}
/* report connection state if remote device is AVRCP target */
handle_rc_ctrl_features(p_dev);
@@ -662,7 +677,12 @@
BTIF_TRACE_ERROR("Got disconnect of unknown device");
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
+ /* report connection state if device is AVRCP target */
+ if (bt_rc_ctrl_callbacks != NULL) {
+ do_in_jni_thread(
+ FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->connection_state_cb, false,
+ false, p_dev->rc_addr));
+ }
/* Clean up AVRCP procedure flags */
memset(&p_dev->rc_app_settings, 0, sizeof(btif_rc_player_app_settings_t));
p_dev->rc_features_processed = false;
@@ -694,11 +714,6 @@
}
p_dev->rc_addr = RawAddress::kEmpty;
- /* report connection state if device is AVRCP target */
- if (bt_rc_ctrl_callbacks != NULL) {
- HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, false, false,
- &rc_addr);
- }
}
/***************************************************************************
@@ -724,14 +739,13 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id: %d", __func__,
p_remote_cmd->rc_id);
/* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up
* this PLAY */
- if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected())) {
+ if ((p_remote_cmd->rc_id == AVRC_ID_PLAY) && (!btif_av_is_connected())) {
if (p_remote_cmd->key_state == AVRC_STATE_PRESS) {
APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command",
__func__);
@@ -741,14 +755,14 @@
}
/* If we previously queued a play and we get a PAUSE, clear it. */
- if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (p_dev->rc_pending_play)) {
+ if ((p_remote_cmd->rc_id == AVRC_ID_PAUSE) && (p_dev->rc_pending_play)) {
APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received",
__func__);
p_dev->rc_pending_play = false;
return;
}
- if ((p_remote_cmd->rc_id == BTA_AV_RC_STOP) &&
+ if ((p_remote_cmd->rc_id == AVRC_ID_STOP) &&
(!btif_av_stream_started_ready())) {
APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd", __func__);
return;
@@ -760,7 +774,7 @@
BTIF_TRACE_DEBUG("%s: rc_features: %d, cmd->rc_id: %d, pressed: %d", __func__,
p_dev->rc_features, p_remote_cmd->rc_id, pressed);
HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed,
- &rc_addr);
+ p_dev->rc_addr);
}
/***************************************************************************
@@ -781,7 +795,6 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
if (!(p_dev->rc_features & BTA_AV_FEAT_RCTG)) {
BTIF_TRACE_ERROR("%s: DUT does not support AVRCP controller role",
@@ -795,8 +808,10 @@
release_transaction(p_remote_rsp->label);
if (bt_rc_ctrl_callbacks != NULL) {
- HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, &rc_addr,
- p_remote_rsp->rc_id, p_remote_rsp->key_state);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->passthrough_rsp_cb, p_dev->rc_addr,
+ p_remote_rsp->rc_id, p_remote_rsp->key_state));
}
}
@@ -839,8 +854,9 @@
status);
release_transaction(p_remote_rsp->label);
- HAL_CBACK(bt_rc_ctrl_callbacks, groupnavigation_rsp_cb, vendor_id,
- key_state);
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->groupnavigation_rsp_cb,
+ vendor_id, key_state));
} else {
BTIF_TRACE_ERROR("%s: Remote does not support AVRCP TG role", __func__);
}
@@ -1074,18 +1090,11 @@
}
}
-/***************************************************************************
- **
- ** Function btif_rc_get_connected_peer
- **
- ** Description Fetches the connected headset's address if any
- **
- ***************************************************************************/
-bool btif_rc_get_connected_peer(RawAddress* peer_addr) {
+bool btif_rc_is_connected_peer(const RawAddress& peer_addr) {
for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
btif_rc_device_cb_t* p_dev = get_connected_device(idx);
- if (p_dev != NULL && (p_dev->rc_connected == TRUE)) {
- *peer_addr = p_dev->rc_addr;
+ if (p_dev != NULL && (p_dev->rc_connected == TRUE) &&
+ peer_addr == p_dev->rc_addr) {
return true;
}
}
@@ -1101,7 +1110,7 @@
***************************************************************************/
uint8_t btif_rc_get_connected_peer_handle(const RawAddress& peer_addr) {
btif_rc_device_cb_t* p_dev = NULL;
- p_dev = btif_rc_get_device_by_bda(&peer_addr);
+ p_dev = btif_rc_get_device_by_bda(peer_addr);
if (p_dev == NULL) {
BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
@@ -1123,7 +1132,7 @@
void btif_rc_check_handle_pending_play(const RawAddress& peer_addr,
bool bSendToApp) {
btif_rc_device_cb_t* p_dev = NULL;
- p_dev = btif_rc_get_device_by_bda(&peer_addr);
+ p_dev = btif_rc_get_device_by_bda(peer_addr);
if (p_dev == NULL) {
BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
@@ -1243,7 +1252,7 @@
__func__, p_dev->rc_handle, index, label, code,
dump_rc_pdu(pmetamsg_resp->rsp.pdu));
- if (index >= 0 && p_dev->rc_pdu_info[index].is_rsp_pending == false) {
+ if (index >= 0 && !p_dev->rc_pdu_info[index].is_rsp_pending) {
BTIF_TRACE_ERROR("%s: is_rsp_pending false, returning", __func__);
return;
}
@@ -1414,12 +1423,11 @@
BTIF_TRACE_EVENT("%s: pdu: %s handle: 0x%x ctype: %x label: %x event ID: %x",
__func__, dump_rc_pdu(pavrc_cmd->pdu), p_dev->rc_handle,
ctype, label, pavrc_cmd->reg_notif.event_id);
- RawAddress rc_addr = p_dev->rc_addr;
switch (event) {
case AVRC_PDU_GET_PLAY_STATUS: {
fill_pdu_queue(IDX_GET_PLAY_STATUS_RSP, ctype, label, true, p_dev);
- HAL_CBACK(bt_rc_callbacks, get_play_status_cb, &rc_addr);
+ HAL_CBACK(bt_rc_callbacks, get_play_status_cb, p_dev->rc_addr);
} break;
case AVRC_PDU_LIST_PLAYER_APP_ATTR:
case AVRC_PDU_LIST_PLAYER_APP_VALUES:
@@ -1447,7 +1455,7 @@
}
fill_pdu_queue(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, true, p_dev);
HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs,
- &rc_addr);
+ p_dev->rc_addr);
} break;
case AVRC_PDU_REGISTER_NOTIFICATION: {
if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
@@ -1463,12 +1471,12 @@
}
HAL_CBACK(bt_rc_callbacks, register_notification_cb,
(btrc_event_id_t)pavrc_cmd->reg_notif.event_id,
- pavrc_cmd->reg_notif.param, &rc_addr);
+ pavrc_cmd->reg_notif.param, p_dev->rc_addr);
} break;
case AVRC_PDU_INFORM_DISPLAY_CHARSET: {
tAVRC_RESPONSE avrc_rsp;
BTIF_TRACE_EVENT("%s: AVRC_PDU_INFORM_DISPLAY_CHARSET", __func__);
- if (p_dev->rc_connected == true) {
+ if (p_dev->rc_connected) {
memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
avrc_rsp.inform_charset.opcode =
opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
@@ -1510,19 +1518,20 @@
fill_pdu_queue(IDX_GET_FOLDER_ITEMS_RSP, ctype, label, true, p_dev);
HAL_CBACK(bt_rc_callbacks, get_folder_items_cb,
pavrc_cmd->get_items.scope, pavrc_cmd->get_items.start_item,
- pavrc_cmd->get_items.end_item, num_attr, attr_ids, &rc_addr);
+ pavrc_cmd->get_items.end_item, num_attr, attr_ids,
+ p_dev->rc_addr);
} break;
case AVRC_PDU_SET_ADDRESSED_PLAYER: {
fill_pdu_queue(IDX_SET_ADDR_PLAYER_RSP, ctype, label, true, p_dev);
HAL_CBACK(bt_rc_callbacks, set_addressed_player_cb,
- pavrc_cmd->addr_player.player_id, &rc_addr);
+ pavrc_cmd->addr_player.player_id, p_dev->rc_addr);
} break;
case AVRC_PDU_SET_BROWSED_PLAYER: {
fill_pdu_queue(IDX_SET_BROWSED_PLAYER_RSP, ctype, label, true, p_dev);
HAL_CBACK(bt_rc_callbacks, set_browsed_player_cb,
- pavrc_cmd->br_player.player_id, &rc_addr);
+ pavrc_cmd->br_player.player_id, p_dev->rc_addr);
} break;
case AVRC_PDU_REQUEST_CONTINUATION_RSP: {
@@ -1558,14 +1567,14 @@
case AVRC_PDU_CHANGE_PATH: {
fill_pdu_queue(IDX_CHG_PATH_RSP, ctype, label, true, p_dev);
HAL_CBACK(bt_rc_callbacks, change_path_cb, pavrc_cmd->chg_path.direction,
- pavrc_cmd->chg_path.folder_uid, &rc_addr);
+ pavrc_cmd->chg_path.folder_uid, p_dev->rc_addr);
} break;
case AVRC_PDU_SEARCH: {
fill_pdu_queue(IDX_SEARCH_RSP, ctype, label, true, p_dev);
HAL_CBACK(bt_rc_callbacks, search_cb, pavrc_cmd->search.string.charset_id,
pavrc_cmd->search.string.str_len,
- pavrc_cmd->search.string.p_str, &rc_addr);
+ pavrc_cmd->search.string.p_str, p_dev->rc_addr);
} break;
case AVRC_PDU_GET_ITEM_ATTRIBUTES: {
@@ -1587,27 +1596,27 @@
num_attr);
HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope,
pavrc_cmd->get_attrs.uid, pavrc_cmd->get_attrs.uid_counter,
- num_attr, item_attrs, &rc_addr);
+ num_attr, item_attrs, p_dev->rc_addr);
} break;
case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: {
fill_pdu_queue(IDX_GET_TOTAL_NUM_OF_ITEMS_RSP, ctype, label, true, p_dev);
HAL_CBACK(bt_rc_callbacks, get_total_num_of_items_cb,
- pavrc_cmd->get_num_of_items.scope, &rc_addr);
+ pavrc_cmd->get_num_of_items.scope, p_dev->rc_addr);
} break;
case AVRC_PDU_ADD_TO_NOW_PLAYING: {
fill_pdu_queue(IDX_ADD_TO_NOW_PLAYING_RSP, ctype, label, true, p_dev);
HAL_CBACK(bt_rc_callbacks, add_to_now_playing_cb,
pavrc_cmd->add_to_play.scope, pavrc_cmd->add_to_play.uid,
- pavrc_cmd->add_to_play.uid_counter, &rc_addr);
+ pavrc_cmd->add_to_play.uid_counter, p_dev->rc_addr);
} break;
case AVRC_PDU_PLAY_ITEM: {
fill_pdu_queue(IDX_PLAY_ITEM_RSP, ctype, label, true, p_dev);
HAL_CBACK(bt_rc_callbacks, play_item_cb, pavrc_cmd->play_item.scope,
pavrc_cmd->play_item.uid_counter, pavrc_cmd->play_item.uid,
- &rc_addr);
+ p_dev->rc_addr);
} break;
default: {
@@ -1633,16 +1642,19 @@
btif_rc_device_cb_t* p_dev) {
BTIF_TRACE_DEBUG("%s: pdu: %s: handle: 0x%x", __func__,
dump_rc_pdu(pavrc_cmd->pdu), p_dev->rc_handle);
- RawAddress rc_addr = p_dev->rc_addr;
switch (event) {
case AVRC_PDU_SET_ABSOLUTE_VOLUME:
- HAL_CBACK(bt_rc_ctrl_callbacks, setabsvol_cmd_cb, &rc_addr,
- pavrc_cmd->volume.volume, label);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->setabsvol_cmd_cb, p_dev->rc_addr,
+ pavrc_cmd->volume.volume, label));
break;
case AVRC_PDU_REGISTER_NOTIFICATION:
if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE) {
- HAL_CBACK(bt_rc_ctrl_callbacks, registernotification_absvol_cb,
- &rc_addr, label);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->registernotification_absvol_cb,
+ p_dev->rc_addr, label));
}
break;
}
@@ -1664,14 +1676,13 @@
BTIF_TRACE_EVENT("%s: pdu: %s: handle: 0x%x ctype: %x label: %x", __func__,
dump_rc_pdu(pavrc_resp->pdu), p_dev->rc_handle, ctype,
label);
- RawAddress rc_addr = p_dev->rc_addr;
switch (event) {
case AVRC_PDU_REGISTER_NOTIFICATION: {
if (AVRC_RSP_CHANGED == ctype)
p_dev->rc_volume = pavrc_resp->reg_notif.param.volume;
HAL_CBACK(bt_rc_callbacks, volume_change_cb,
- pavrc_resp->reg_notif.param.volume, ctype, &rc_addr);
+ pavrc_resp->reg_notif.param.volume, ctype, p_dev->rc_addr);
} break;
case AVRC_PDU_SET_ABSOLUTE_VOLUME: {
@@ -1682,7 +1693,7 @@
if (AVRC_RSP_ACCEPT == ctype)
p_dev->rc_volume = pavrc_resp->volume.volume;
HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->volume.volume,
- ctype, &rc_addr);
+ ctype, p_dev->rc_addr);
} break;
default:
@@ -1755,7 +1766,7 @@
return;
}
- if (p_dev->rc_procedure_complete == true) {
+ if (p_dev->rc_procedure_complete) {
return;
}
p_dev->rc_procedure_complete = true;
@@ -1778,7 +1789,7 @@
* Returns bt_status_t
*
**************************************************************************/
-static bt_status_t get_play_status_rsp(RawAddress* bd_addr,
+static bt_status_t get_play_status_rsp(const RawAddress& bd_addr,
btrc_play_status_t play_status,
uint32_t song_len, uint32_t song_pos) {
tAVRC_RESPONSE avrc_rsp;
@@ -1818,7 +1829,8 @@
* Returns bt_status_t
*
**************************************************************************/
-static bt_status_t get_element_attr_rsp(RawAddress* bd_addr, uint8_t num_attr,
+static bt_status_t get_element_attr_rsp(const RawAddress& bd_addr,
+ uint8_t num_attr,
btrc_element_attr_val_t* p_attrs) {
tAVRC_RESPONSE avrc_rsp;
uint32_t i;
@@ -1893,7 +1905,7 @@
continue;
}
- if (btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].bNotify == false) {
+ if (!btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].bNotify) {
BTIF_TRACE_WARNING(
"%s: Avrcp Event id is not registered: event_id: %x, handle: 0x%x",
__func__, event_id, btif_rc_cb.rc_multi_cb[idx].rc_handle);
@@ -1963,7 +1975,7 @@
* get_folder_items_list PDU
*
**************************************************************************/
-static bt_status_t get_folder_items_list_rsp(RawAddress* bd_addr,
+static bt_status_t get_folder_items_list_rsp(const RawAddress& bd_addr,
btrc_status_t rsp_status,
uint16_t uid_counter,
uint8_t num_items,
@@ -1982,7 +1994,7 @@
CHECK_RC_CONNECTED(p_dev);
/* check if rsp to previous cmd was completed */
- if (p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending == false) {
+ if (!p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending) {
BTIF_TRACE_WARNING("%s: Not sending response as no PDU was registered",
__func__);
return BT_STATUS_UNHANDLED;
@@ -2127,7 +2139,7 @@
* BT_STATUS_SUCCESS - always if RC is connected
*
**************************************************************************/
-static bt_status_t set_addressed_player_rsp(RawAddress* bd_addr,
+static bt_status_t set_addressed_player_rsp(const RawAddress& bd_addr,
btrc_status_t rsp_status) {
tAVRC_RESPONSE avrc_rsp;
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
@@ -2165,7 +2177,7 @@
* set_browsed_player PDU
*
**************************************************************************/
-static bt_status_t set_browsed_player_rsp(RawAddress* bd_addr,
+static bt_status_t set_browsed_player_rsp(const RawAddress& bd_addr,
btrc_status_t rsp_status,
uint32_t num_items,
uint16_t charset_id,
@@ -2193,7 +2205,7 @@
__func__, rsp_status, avrc_rsp.br_player.status);
/* check if rsp to previous cmd was completed */
- if (p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending == false) {
+ if (!p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending) {
BTIF_TRACE_WARNING("%s: Not sending response as no PDU was registered",
__func__);
return BT_STATUS_UNHANDLED;
@@ -2283,7 +2295,7 @@
* BT_STATUS_SUCCESS - always if RC is connected
*
**************************************************************************/
-static bt_status_t change_path_rsp(RawAddress* bd_addr,
+static bt_status_t change_path_rsp(const RawAddress& bd_addr,
btrc_status_t rsp_status,
uint32_t num_items) {
tAVRC_RESPONSE avrc_rsp;
@@ -2316,8 +2328,9 @@
* BT_STATUS_SUCCESS - always if RC is connected
*
**************************************************************************/
-static bt_status_t search_rsp(RawAddress* bd_addr, btrc_status_t rsp_status,
- uint32_t uid_counter, uint32_t num_items) {
+static bt_status_t search_rsp(const RawAddress& bd_addr,
+ btrc_status_t rsp_status, uint32_t uid_counter,
+ uint32_t num_items) {
tAVRC_RESPONSE avrc_rsp;
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
@@ -2349,7 +2362,7 @@
* BT_STATUS_SUCCESS - always if RC is connected
*
**************************************************************************/
-static bt_status_t get_item_attr_rsp(RawAddress* bd_addr,
+static bt_status_t get_item_attr_rsp(const RawAddress& bd_addr,
btrc_status_t rsp_status, uint8_t num_attr,
btrc_element_attr_val_t* p_attrs) {
tAVRC_RESPONSE avrc_rsp;
@@ -2391,7 +2404,7 @@
* BT_STATUS_SUCCESS - always if RC is connected
*
**************************************************************************/
-static bt_status_t add_to_now_playing_rsp(RawAddress* bd_addr,
+static bt_status_t add_to_now_playing_rsp(const RawAddress& bd_addr,
btrc_status_t rsp_status) {
tAVRC_RESPONSE avrc_rsp;
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
@@ -2423,7 +2436,7 @@
* BT_STATUS_SUCCESS - always if RC is connected
*
**************************************************************************/
-static bt_status_t play_item_rsp(RawAddress* bd_addr,
+static bt_status_t play_item_rsp(const RawAddress& bd_addr,
btrc_status_t rsp_status) {
tAVRC_RESPONSE avrc_rsp;
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
@@ -2455,7 +2468,7 @@
* BT_STATUS_SUCCESS - always if RC is connected
*
**************************************************************************/
-static bt_status_t get_total_num_of_items_rsp(RawAddress* bd_addr,
+static bt_status_t get_total_num_of_items_rsp(const RawAddress& bd_addr,
btrc_status_t rsp_status,
uint32_t uid_counter,
uint32_t num_items) {
@@ -2498,15 +2511,9 @@
static bt_status_t set_volume(uint8_t volume) {
BTIF_TRACE_DEBUG("%s: volume: %d", __func__, volume);
tAVRC_STS status = BT_STATUS_UNSUPPORTED;
- rc_transaction_t* p_transaction = NULL;
for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
- if (!btif_rc_cb.rc_multi_cb[idx].rc_connected) {
- status = BT_STATUS_NOT_READY;
- BTIF_TRACE_ERROR("%s: RC is not connected for device: 0x%x", __func__,
- btif_rc_cb.rc_multi_cb[idx].rc_addr);
- continue;
- }
+ if (!btif_rc_cb.rc_multi_cb[idx].rc_connected) continue;
if (btif_rc_cb.rc_multi_cb[idx].rc_volume == volume) {
status = BT_STATUS_DONE;
@@ -2515,49 +2522,54 @@
continue;
}
- if ((btif_rc_cb.rc_multi_cb[idx].rc_volume != volume) &&
- btif_rc_cb.rc_multi_cb[idx].rc_state ==
+ if ((btif_rc_cb.rc_multi_cb[idx].rc_volume == volume) ||
+ btif_rc_cb.rc_multi_cb[idx].rc_state !=
BTRC_CONNECTION_STATE_CONNECTED) {
- if ((btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_RCTG) == 0) {
- status = BT_STATUS_NOT_READY;
- continue;
- } else {
- tAVRC_COMMAND avrc_cmd = {0};
- BT_HDR* p_msg = NULL;
-
- if (btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_ADV_CTRL) {
- BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume: %d",
- __func__, volume);
- avrc_cmd.volume.opcode = AVRC_OP_VENDOR;
- avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
- avrc_cmd.volume.status = AVRC_STS_NO_ERROR;
- avrc_cmd.volume.volume = volume;
-
- if (AVRC_BldCommand(&avrc_cmd, &p_msg) == AVRC_STS_NO_ERROR) {
- bt_status_t tran_status = get_transaction(&p_transaction);
-
- if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction) {
- BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d",
- __func__, p_transaction->lbl);
- BTA_AvMetaCmd(btif_rc_cb.rc_multi_cb[idx].rc_handle,
- p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
- status = BT_STATUS_SUCCESS;
- } else {
- osi_free_and_reset((void**)&p_msg);
- BTIF_TRACE_ERROR(
- "%s: failed to obtain transaction details. status: 0x%02x",
- __func__, tran_status);
- status = BT_STATUS_FAIL;
- }
- } else {
- BTIF_TRACE_ERROR(
- "%s: failed to build absolute volume command. status: 0x%02x",
- __func__, status);
- status = BT_STATUS_FAIL;
- }
- }
- }
+ continue;
}
+
+ if ((btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_RCTG) == 0) {
+ status = BT_STATUS_NOT_READY;
+ continue;
+ }
+
+ if (!(btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_ADV_CTRL))
+ continue;
+
+ BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume: %d",
+ __func__, volume);
+
+ tAVRC_COMMAND avrc_cmd = {.volume = {.opcode = AVRC_OP_VENDOR,
+ .pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME,
+ .status = AVRC_STS_NO_ERROR,
+ .volume = volume}};
+
+ BT_HDR* p_msg = NULL;
+ if (AVRC_BldCommand(&avrc_cmd, &p_msg) != AVRC_STS_NO_ERROR) {
+ BTIF_TRACE_ERROR(
+ "%s: failed to build absolute volume command. status: 0x%02x",
+ __func__, status);
+ status = BT_STATUS_FAIL;
+ continue;
+ }
+
+ rc_transaction_t* p_transaction = NULL;
+ bt_status_t tran_status = get_transaction(&p_transaction);
+
+ if (tran_status != BT_STATUS_SUCCESS || !p_transaction) {
+ osi_free_and_reset((void**)&p_msg);
+ BTIF_TRACE_ERROR(
+ "%s: failed to obtain transaction details. status: 0x%02x", __func__,
+ tran_status);
+ status = BT_STATUS_FAIL;
+ continue;
+ }
+
+ BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__,
+ p_transaction->lbl);
+ BTA_AvMetaCmd(btif_rc_cb.rc_multi_cb[idx].rc_handle, p_transaction->lbl,
+ AVRC_CMD_CTRL, p_msg);
+ status = BT_STATUS_SUCCESS;
}
return (bt_status_t)status;
}
@@ -2726,7 +2738,7 @@
bool iterate_supported_event_list_for_timeout(void* data, void* cb_data) {
rc_context_t* cntxt = (rc_context_t*)cb_data;
uint8_t label = cntxt->label & 0xFF;
- btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(&cntxt->rc_addr);
+ btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(cntxt->rc_addr);
btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)data;
if (p_event->label == label) {
@@ -2792,7 +2804,7 @@
p_context = (btif_rc_timer_context_t*)data;
memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
- p_dev = btif_rc_get_device_by_bda(&p_context->rc_addr);
+ p_dev = btif_rc_get_device_by_bda(p_context->rc_addr);
if (p_dev == NULL) {
BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
return;
@@ -2877,7 +2889,7 @@
btif_rc_timer_context_t* p_context = (btif_rc_timer_context_t*)data;
tAVRC_RESPONSE avrc_response = {0};
tBTA_AV_META_MSG meta_msg;
- btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(&p_context->rc_addr);
+ btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(p_context->rc_addr);
if (p_dev == NULL) {
BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
return;
@@ -3112,6 +3124,7 @@
if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE) ||
(p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE) ||
(p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE) ||
+ (p_rsp->param.event_id[xx] == AVRC_EVT_ADDR_PLAYER_CHANGE) ||
(p_rsp->param.event_id[xx] == AVRC_EVT_UIDS_CHANGE)) {
p_event = (btif_rc_supported_event_t*)osi_malloc(
sizeof(btif_rc_supported_event_t));
@@ -3179,7 +3192,6 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
if (pmeta_msg->code == AVRC_RSP_INTERIM) {
btif_rc_supported_event_t* p_event;
@@ -3191,11 +3203,16 @@
/* Start timer to get play status periodically
* if the play state is playing.
*/
- if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING) {
+ if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING ||
+ p_rsp->param.play_status == AVRC_PLAYSTATE_REV_SEEK ||
+ p_rsp->param.play_status == AVRC_PLAYSTATE_FWD_SEEK) {
rc_start_play_status_timer(p_dev);
}
- HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb, &rc_addr,
- (btrc_play_status_t)p_rsp->param.play_status);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->play_status_changed_cb,
+ p_dev->rc_addr,
+ (btrc_play_status_t)p_rsp->param.play_status));
break;
case AVRC_EVT_TRACK_CHANGE:
@@ -3220,6 +3237,9 @@
break;
case AVRC_EVT_ADDR_PLAYER_CHANGE:
+ do_in_jni_thread(
+ FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->set_addressed_player_cb,
+ p_dev->rc_addr, BTRC_STS_ADDR_PLAY_CHGD));
break;
case AVRC_EVT_UIDS_CHANGE:
@@ -3252,7 +3272,7 @@
p_event = NULL;
}
/* Registered for all events, we can request application settings */
- if (p_event == NULL && p_dev->rc_app_settings.query_started == false) {
+ if (p_event == NULL && !p_dev->rc_app_settings.query_started) {
/* we need to do this only if remote TG supports
* player application settings
*/
@@ -3296,8 +3316,11 @@
} else {
rc_stop_play_status_timer(p_dev);
}
- HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb, &rc_addr,
- (btrc_play_status_t)p_rsp->param.play_status);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->play_status_changed_cb,
+ p_dev->rc_addr,
+ (btrc_play_status_t)p_rsp->param.play_status));
break;
@@ -3318,8 +3341,11 @@
app_settings.attr_values[xx] =
p_rsp->param.player_setting.attr_value[xx];
}
- HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
- &rc_addr, &app_settings);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(
+ bt_rc_ctrl_callbacks->playerapplicationsetting_changed_cb,
+ p_dev->rc_addr, app_settings));
} break;
case AVRC_EVT_NOW_PLAYING_CHANGE:
@@ -3421,7 +3447,6 @@
}
p_app_settings = &p_dev->rc_app_settings;
- RawAddress rc_addr = p_dev->rc_addr;
if (p_app_settings->attr_index < p_app_settings->num_attrs) {
attr_index = p_app_settings->attr_index;
@@ -3444,8 +3469,11 @@
attrs[xx] = p_app_settings->attrs[xx].attr_id;
}
get_player_app_setting_cmd(p_app_settings->num_attrs, attrs, p_dev);
- HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
- p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
+ p_dev->rc_addr, p_app_settings->num_attrs,
+ p_app_settings->attrs, 0, nullptr));
}
} else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs) {
attr_index = p_app_settings->ext_attr_index;
@@ -3500,7 +3528,6 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
app_settings.num_attr = p_rsp->num_val;
@@ -3514,8 +3541,10 @@
app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
}
- HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb, &rc_addr,
- &app_settings);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_changed_cb,
+ p_dev->rc_addr, app_settings));
/* Application settings are fetched only once for initial values
* initiate anything that follows after RC procedure.
* Defer it if browsing is supported till players query
@@ -3548,7 +3577,6 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
p_app_settings = &p_dev->rc_app_settings;
/* Todo: Do we need to retry on command timeout */
@@ -3572,8 +3600,11 @@
attrs[xx] = p_app_settings->attrs[xx].attr_id;
}
- HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
- p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
+ p_dev->rc_addr, p_app_settings->num_attrs,
+ p_app_settings->attrs, 0, nullptr));
get_player_app_setting_cmd(xx, attrs, p_dev);
}
return;
@@ -3621,7 +3652,6 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
p_app_settings = &p_dev->rc_app_settings;
/* Todo: Do we need to retry on command timeout */
@@ -3650,8 +3680,10 @@
for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
attrs[xx] = p_app_settings->attrs[xx].attr_id;
}
- HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
- p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
+ do_in_jni_thread(
+ FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
+ p_dev->rc_addr, p_app_settings->num_attrs,
+ p_app_settings->attrs, 0, nullptr));
get_player_app_setting_cmd(xx, attrs, p_dev);
return;
@@ -3687,29 +3719,46 @@
for (x = 0; x < p_app_settings->num_ext_attrs; x++) {
attrs[xx + x] = p_app_settings->ext_attrs[x].attr_id;
}
- HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
- p_app_settings->num_attrs, p_app_settings->attrs,
- p_app_settings->num_ext_attrs, p_app_settings->ext_attrs);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->playerapplicationsetting_cb,
+ p_dev->rc_addr, p_app_settings->num_attrs,
+ p_app_settings->attrs, p_app_settings->num_ext_attrs,
+ p_app_settings->ext_attrs));
get_player_app_setting_cmd(xx + x, attrs, p_dev);
/* Free the application settings information after sending to
* application.
*/
- for (xx = 0; xx < p_app_settings->ext_attr_index; xx++) {
- int x;
- btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx];
-
- for (x = 0; x < p_ext_attr->num_val; x++)
- osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str);
- p_ext_attr->num_val = 0;
- osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
- }
+ do_in_jni_thread(FROM_HERE, base::Bind(cleanup_app_attr_val_txt_response,
+ p_app_settings));
p_app_settings->num_attrs = 0;
}
}
/***************************************************************************
*
+ * Function cleanup_app_attr_val_txt_response
+ *
+ * Description Frees the memory that was allocated for reporting player
+ * application settings.
+ * Returns None
+ **************************************************************************/
+static void cleanup_app_attr_val_txt_response(
+ btif_rc_player_app_settings_t* p_app_settings) {
+ for (uint8_t xx = 0; xx < p_app_settings->ext_attr_index; xx++) {
+ int x;
+ btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx];
+ for (x = 0; x < p_ext_attr->num_val; x++) {
+ osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str);
+ }
+ p_ext_attr->num_val = 0;
+ osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
+ }
+}
+
+/***************************************************************************
+ *
* Function handle_set_app_attr_val_response
*
* Description handles the the set attributes value response, if fails
@@ -3728,7 +3777,6 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
/* For timeout pmeta_msg will be NULL, else we need to
* check if this is accepted by TG
@@ -3736,8 +3784,9 @@
if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT)) {
accepted = 1;
}
- HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr,
- accepted);
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->setplayerappsetting_rsp_cb,
+ p_dev->rc_addr, accepted));
}
/***************************************************************************
@@ -3764,7 +3813,6 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
for (int i = 0; i < p_rsp->num_attrs; i++) {
p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
@@ -3775,9 +3823,10 @@
osi_free_and_reset((void**)&p_rsp->p_attrs[i].name.p_str);
}
}
- HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb, &rc_addr,
- p_rsp->num_attrs, p_attr);
- osi_free(p_attr);
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->track_changed_cb,
+ p_dev->rc_addr, p_rsp->num_attrs, p_attr));
+ do_in_jni_thread(FROM_HERE, base::Bind(osi_free, p_attr));
} else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) {
/* Retry for timeout case, this covers error handling
* for continuation failure also.
@@ -3814,11 +3863,12 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
if (p_rsp->status == AVRC_STS_NO_ERROR) {
- HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb, &rc_addr,
- p_rsp->song_len, p_rsp->song_pos);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->play_position_changed_cb,
+ p_dev->rc_addr, p_rsp->song_len, p_rsp->song_pos));
} else {
BTIF_TRACE_ERROR("%s: Error in get play status procedure: %d", __func__,
p_rsp->status);
@@ -3845,11 +3895,11 @@
return;
}
- RawAddress rc_addr = p_dev->rc_addr;
if (p_rsp->status == AVRC_STS_NO_ERROR) {
- HAL_CBACK(bt_rc_ctrl_callbacks, set_addressed_player_cb, &rc_addr,
- p_rsp->status);
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->set_addressed_player_cb,
+ p_dev->rc_addr, p_rsp->status));
} else {
BTIF_TRACE_ERROR("%s: Error in get play status procedure %d", __func__,
p_rsp->status);
@@ -3869,7 +3919,6 @@
tAVRC_GET_ITEMS_RSP* p_rsp) {
btif_rc_device_cb_t* p_dev =
btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
- RawAddress rc_addr = p_dev->rc_addr;
if (p_rsp->status == AVRC_STS_NO_ERROR) {
/* Convert the internal folder listing into a response that can
@@ -3886,6 +3935,10 @@
switch (avrc_item->item_type) {
case AVRC_ITEM_MEDIA:
BTIF_TRACE_DEBUG("%s setting type to %d", __func__, BTRC_ITEM_MEDIA);
+ /* Allocate Space for Attributes */
+ btrc_item->media.num_attrs = avrc_item->u.media.attr_count;
+ btrc_item->media.p_attrs = (btrc_element_attr_val_t*)osi_malloc(
+ btrc_item->media.num_attrs * sizeof(btrc_element_attr_val_t));
get_folder_item_type_media(avrc_item, btrc_item);
break;
@@ -3905,20 +3958,54 @@
}
}
- HAL_CBACK(bt_rc_ctrl_callbacks, get_folder_items_cb, &rc_addr,
- BTRC_STS_NO_ERROR,
- /* We want to make the ownership explicit in native */
- (const btrc_folder_items_t*)btrc_items, item_count);
- BTIF_TRACE_DEBUG("%s HAL CBACK get_folder_items_cb finished", __func__);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->get_folder_items_cb, p_dev->rc_addr,
+ BTRC_STS_NO_ERROR,
+ /* We want to make the ownership explicit in native */
+ btrc_items, item_count));
- /* Release the memory block for items since we OWN the object */
- osi_free(btrc_items);
+ /* Release the memory block for items and attributes allocated here.
+ * Since the executor for do_in_jni_thread is a Single Thread Task Runner it
+ * is okay to queue up the cleanup of btrc_items */
+ do_in_jni_thread(FROM_HERE, base::Bind(cleanup_btrc_folder_items,
+ btrc_items, item_count));
+
+ BTIF_TRACE_DEBUG("%s get_folder_items_cb sent to JNI thread", __func__);
} else {
BTIF_TRACE_ERROR("%s: Error %d", __func__, p_rsp->status);
- HAL_CBACK(bt_rc_ctrl_callbacks, get_folder_items_cb, &rc_addr,
- (btrc_status_t)p_rsp->status, NULL, 0);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->get_folder_items_cb, p_dev->rc_addr,
+ (btrc_status_t)p_rsp->status, nullptr, 0));
}
}
+/***************************************************************************
+ *
+ * Function cleanup_btrc_folder_items
+ *
+ * Description Frees the memory that was allocated for a list of folder
+ * items.
+ * Returns None
+ **************************************************************************/
+static void cleanup_btrc_folder_items(btrc_folder_items_t* btrc_items,
+ uint8_t item_count) {
+ for (uint8_t i = 0; i < item_count; i++) {
+ btrc_folder_items_t* btrc_item = &(btrc_items[i]);
+ switch (btrc_item->item_type) {
+ case BTRC_ITEM_MEDIA:
+ osi_free(btrc_item->media.p_attrs);
+ break;
+ case BTRC_ITEM_PLAYER:
+ case BTRC_ITEM_FOLDER:
+ /*Nothing to free*/
+ break;
+ default:
+ BTIF_TRACE_WARNING("%s free unspecified type", __func__);
+ }
+ }
+ osi_free(btrc_items);
+}
/***************************************************************************
*
@@ -3959,11 +4046,6 @@
memcpy(btrc_item_media->name, avrc_item_media->name.p_str,
sizeof(uint8_t) * (avrc_item_media->name.str_len));
- /* Copy the parameters */
- btrc_item_media->num_attrs = avrc_item_media->attr_count;
- btrc_item_media->p_attrs = (btrc_element_attr_val_t*)osi_malloc(
- btrc_item_media->num_attrs * sizeof(btrc_element_attr_val_t));
-
/* Extract each attribute */
for (int i = 0; i < avrc_item_media->attr_count; i++) {
btrc_element_attr_val_t* btrc_attr_pair = &(btrc_item_media->p_attrs[i]);
@@ -4084,6 +4166,8 @@
btrc_item_player->major_type = avrc_item_player->major_type;
/* Sub type */
btrc_item_player->sub_type = avrc_item_player->sub_type;
+ /* Play status */
+ btrc_item_player->play_status = avrc_item_player->play_status;
/* Features */
memcpy(btrc_item_player->features, avrc_item_player->features,
BTRC_FEATURE_BIT_MASK_SIZE);
@@ -4106,11 +4190,11 @@
tAVRC_CHG_PATH_RSP* p_rsp) {
btif_rc_device_cb_t* p_dev =
btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
- RawAddress rc_addr = p_dev->rc_addr;
if (p_rsp->status == AVRC_STS_NO_ERROR) {
- HAL_CBACK(bt_rc_ctrl_callbacks, change_folder_path_cb, &rc_addr,
- p_rsp->num_items);
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->change_folder_path_cb,
+ p_dev->rc_addr, p_rsp->num_items));
} else {
BTIF_TRACE_ERROR("%s error in handle_change_path_response %d", __func__,
p_rsp->status);
@@ -4130,11 +4214,12 @@
tAVRC_SET_BR_PLAYER_RSP* p_rsp) {
btif_rc_device_cb_t* p_dev =
btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
- RawAddress rc_addr = p_dev->rc_addr;
if (p_rsp->status == AVRC_STS_NO_ERROR) {
- HAL_CBACK(bt_rc_ctrl_callbacks, set_browsed_player_cb, &rc_addr,
- p_rsp->num_items, p_rsp->folder_depth);
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(bt_rc_ctrl_callbacks->set_browsed_player_cb, p_dev->rc_addr,
+ p_rsp->num_items, p_rsp->folder_depth));
} else {
BTIF_TRACE_ERROR("%s error %d", __func__, p_rsp->status);
}
@@ -4479,7 +4564,7 @@
* BT_STATUS_FAIL.
*
**************************************************************************/
-static bt_status_t get_playback_state_cmd(RawAddress* bd_addr) {
+static bt_status_t get_playback_state_cmd(const RawAddress& bd_addr) {
BTIF_TRACE_DEBUG("%s", __func__);
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
return get_play_status_cmd(p_dev);
@@ -4492,18 +4577,18 @@
* Description Fetch the now playing list
*
* Paramters start_item: First item to fetch (0 to fetch from beganning)
- * end_item: Last item to fetch (0xff to fetch until end)
+ * end_item: Last item to fetch (0xffffffff to fetch until end)
*
* Returns BT_STATUS_SUCCESS if command issued successfully otherwise
* BT_STATUS_FAIL.
*
**************************************************************************/
-static bt_status_t get_now_playing_list_cmd(RawAddress* bd_addr,
- uint8_t start_item,
- uint8_t num_items) {
- BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items);
+static bt_status_t get_now_playing_list_cmd(const RawAddress& bd_addr,
+ uint32_t start_item,
+ uint32_t end_item) {
+ BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
return get_folder_items_cmd(bd_addr, AVRC_SCOPE_NOW_PLAYING, start_item,
- num_items);
+ end_item);
}
/***************************************************************************
@@ -4513,17 +4598,17 @@
* Description Fetch the currently selected folder list
*
* Paramters start_item: First item to fetch (0 to fetch from beganning)
- * end_item: Last item to fetch (0xff to fetch until end)
+ * end_item: Last item to fetch (0xffffffff to fetch until end)
*
* Returns BT_STATUS_SUCCESS if command issued successfully otherwise
* BT_STATUS_FAIL.
*
**************************************************************************/
-static bt_status_t get_folder_list_cmd(RawAddress* bd_addr, uint8_t start_item,
- uint8_t num_items) {
- BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items);
+static bt_status_t get_folder_list_cmd(const RawAddress& bd_addr,
+ uint32_t start_item, uint32_t end_item) {
+ BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
return get_folder_items_cmd(bd_addr, AVRC_SCOPE_FILE_SYSTEM, start_item,
- num_items);
+ end_item);
}
/***************************************************************************
@@ -4533,17 +4618,17 @@
* Description Fetch the player list
*
* Paramters start_item: First item to fetch (0 to fetch from beganning)
- * end_item: Last item to fetch (0xff to fetch until end)
+ * end_item: Last item to fetch (0xffffffff to fetch until end)
*
* Returns BT_STATUS_SUCCESS if command issued successfully otherwise
* BT_STATUS_FAIL.
*
**************************************************************************/
-static bt_status_t get_player_list_cmd(RawAddress* bd_addr, uint8_t start_item,
- uint8_t num_items) {
- BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items);
+static bt_status_t get_player_list_cmd(const RawAddress& bd_addr,
+ uint32_t start_item, uint32_t end_item) {
+ BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
return get_folder_items_cmd(bd_addr, AVRC_SCOPE_PLAYER_LIST, start_item,
- num_items);
+ end_item);
}
/***************************************************************************
@@ -4555,13 +4640,13 @@
* Paramters direction: Direction (Up/Down) to change folder
* uid: The UID of folder to move to
* start_item: First item to fetch (0 to fetch from beganning)
- * end_item: Last item to fetch (0xff to fetch until end)
+ * end_item: Last item to fetch (0xffffffff to fetch until end)
*
* Returns BT_STATUS_SUCCESS if command issued successfully otherwise
* BT_STATUS_FAIL.
*
**************************************************************************/
-static bt_status_t change_folder_path_cmd(RawAddress* bd_addr,
+static bt_status_t change_folder_path_cmd(const RawAddress& bd_addr,
uint8_t direction, uint8_t* uid) {
BTIF_TRACE_DEBUG("%s: direction %d", __func__, direction);
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
@@ -4613,7 +4698,8 @@
* BT_STATUS_FAIL.
*
**************************************************************************/
-static bt_status_t set_browsed_player_cmd(RawAddress* bd_addr, uint16_t id) {
+static bt_status_t set_browsed_player_cmd(const RawAddress& bd_addr,
+ uint16_t id) {
BTIF_TRACE_DEBUG("%s: id %d", __func__, id);
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
CHECK_RC_CONNECTED(p_dev);
@@ -4660,7 +4746,8 @@
** BT_STATUS_FAIL.
**
***************************************************************************/
-static bt_status_t set_addressed_player_cmd(RawAddress* bd_addr, uint16_t id) {
+static bt_status_t set_addressed_player_cmd(const RawAddress& bd_addr,
+ uint16_t id) {
BTIF_TRACE_DEBUG("%s: id %d", __func__, id);
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
@@ -4707,14 +4794,15 @@
* Paramters scope: AVRC_SCOPE_NOW_PLAYING (etc) for various browseable
* content
* start_item: First item to fetch (0 to fetch from beganning)
- * end_item: Last item to fetch (0xff to fetch until end)
+ * end_item: Last item to fetch (0xffff to fetch until end)
*
* Returns BT_STATUS_SUCCESS if command issued successfully otherwise
* BT_STATUS_FAIL.
*
**************************************************************************/
-static bt_status_t get_folder_items_cmd(RawAddress* bd_addr, uint8_t scope,
- uint8_t start_item, uint8_t end_item) {
+static bt_status_t get_folder_items_cmd(const RawAddress& bd_addr,
+ uint8_t scope, uint32_t start_item,
+ uint32_t end_item) {
/* Check that both avrcp and browse channel are connected. */
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
BTIF_TRACE_DEBUG("%s", __func__);
@@ -4764,7 +4852,7 @@
* Returns void
*
**************************************************************************/
-static bt_status_t change_player_app_setting(RawAddress* bd_addr,
+static bt_status_t change_player_app_setting(const RawAddress& bd_addr,
uint8_t num_attrib,
uint8_t* attrib_ids,
uint8_t* attrib_vals) {
@@ -4798,7 +4886,7 @@
* Returns void
*
**************************************************************************/
-static bt_status_t play_item_cmd(RawAddress* bd_addr, uint8_t scope,
+static bt_status_t play_item_cmd(const RawAddress& bd_addr, uint8_t scope,
uint8_t* uid, uint16_t uid_counter) {
BTIF_TRACE_DEBUG("%s: scope %d uid_counter %d", __func__, scope, uid_counter);
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
@@ -4968,7 +5056,7 @@
* Returns void
*
**************************************************************************/
-static bt_status_t set_volume_rsp(RawAddress* bd_addr, uint8_t abs_vol,
+static bt_status_t set_volume_rsp(const RawAddress& bd_addr, uint8_t abs_vol,
uint8_t label) {
tAVRC_STS status = BT_STATUS_UNSUPPORTED;
tAVRC_RESPONSE avrc_rsp;
@@ -4989,7 +5077,7 @@
BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__,
p_dev->rc_vol_label);
if (p_msg != NULL) {
- BTA_AvVendorRsp(p_dev->rc_handle, label, BTA_AV_RSP_ACCEPT, data_start,
+ BTA_AvVendorRsp(p_dev->rc_handle, label, AVRC_RSP_ACCEPT, data_start,
p_msg->len, 0);
status = BT_STATUS_SUCCESS;
}
@@ -5011,8 +5099,8 @@
*
**************************************************************************/
static bt_status_t volume_change_notification_rsp(
- RawAddress* bd_addr, btrc_notification_type_t rsp_type, uint8_t abs_vol,
- uint8_t label) {
+ const RawAddress& bd_addr, btrc_notification_type_t rsp_type,
+ uint8_t abs_vol, uint8_t label) {
tAVRC_STS status = BT_STATUS_UNSUPPORTED;
tAVRC_RESPONSE avrc_rsp;
BT_HDR* p_msg = NULL;
@@ -5057,7 +5145,7 @@
* Returns void
*
**************************************************************************/
-static bt_status_t send_groupnavigation_cmd(RawAddress* bd_addr,
+static bt_status_t send_groupnavigation_cmd(const RawAddress& bd_addr,
uint8_t key_code,
uint8_t key_state) {
tAVRC_STS status = BT_STATUS_UNSUPPORTED;
@@ -5102,8 +5190,8 @@
* Returns void
*
**************************************************************************/
-static bt_status_t send_passthrough_cmd(RawAddress* bd_addr, uint8_t key_code,
- uint8_t key_state) {
+static bt_status_t send_passthrough_cmd(const RawAddress& bd_addr,
+ uint8_t key_code, uint8_t key_state) {
tAVRC_STS status = BT_STATUS_UNSUPPORTED;
btif_rc_device_cb_t* p_dev = NULL;
BTIF_TRACE_ERROR("%s: calling btif_rc_get_device_by_bda", __func__);
@@ -5213,7 +5301,7 @@
* Returns void
******************************************************************************/
static void initialize_transaction(int lbl) {
- std::unique_lock<std::recursive_mutex>(device.lbllock);
+ std::unique_lock<std::recursive_mutex> lock(device.lbllock);
if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) {
clear_cmd_timeout(lbl);
@@ -5266,7 +5354,7 @@
/* Determine if this is a valid label */
if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
- if (false == device.transaction[lbl].in_use) {
+ if (!device.transaction[lbl].in_use) {
transaction = NULL;
} else {
transaction = &(device.transaction[lbl]);
@@ -5291,7 +5379,7 @@
// Check for unused transactions
for (uint8_t i = 0; i < MAX_TRANSACTIONS_PER_SESSION; i++) {
- if (false == device.transaction[i].in_use) {
+ if (!device.transaction[i].in_use) {
BTIF_TRACE_DEBUG("%s: Got transaction.label: %d", __func__,
device.transaction[i].lbl);
device.transaction[i].in_use = true;
diff --git a/btif/src/btif_sdp.cc b/btif/src/btif_sdp.cc
index de39c42..d7c3f67 100644
--- a/btif/src/btif_sdp.cc
+++ b/btif/src/btif_sdp.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Samsung System LSI
+ * Copyright 2014 Samsung System LSI
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,8 @@
#include "btif_profile_queue.h"
#include "btif_util.h"
+using bluetooth::Uuid;
+
/*****************************************************************************
* Functions implemented in sdp_server.c
*****************************************************************************/
@@ -64,16 +66,13 @@
static void btif_sdp_search_comp_evt(uint16_t event, char* p_param) {
tBTA_SDP_SEARCH_COMP* evt_data = (tBTA_SDP_SEARCH_COMP*)p_param;
- RawAddress addr;
BTIF_TRACE_DEBUG("%s: event = %d", __func__, event);
if (event != BTA_SDP_SEARCH_COMP_EVT) return;
- addr = evt_data->remote_addr;
-
HAL_CBACK(bt_sdp_callbacks, sdp_search_cb, (bt_status_t)evt_data->status,
- &addr, (uint8_t*)(evt_data->uuid.uu.uuid128),
- evt_data->record_count, evt_data->records);
+ evt_data->remote_addr, evt_data->uuid, evt_data->record_count,
+ evt_data->records);
}
static void sdp_search_comp_copy_cb(uint16_t event, char* p_dest, char* p_src) {
@@ -137,13 +136,8 @@
return BT_STATUS_SUCCESS;
}
-static bt_status_t search(RawAddress* bd_addr, const uint8_t* uuid) {
- tSDP_UUID sdp_uuid;
- sdp_uuid.len = 16;
- memcpy(sdp_uuid.uu.uuid128, uuid, sizeof(sdp_uuid.uu.uuid128));
-
- BTA_SdpSearch(*bd_addr, &sdp_uuid);
-
+static bt_status_t search(RawAddress* bd_addr, const Uuid& uuid) {
+ BTA_SdpSearch(*bd_addr, uuid);
return BT_STATUS_SUCCESS;
}
diff --git a/btif/src/btif_sdp_server.cc b/btif/src/btif_sdp_server.cc
index b84d694..4738da4 100644
--- a/btif/src/btif_sdp_server.cc
+++ b/btif/src/btif_sdp_server.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Samsung System LSI
+ * Copyright 2014 Samsung System LSI
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -356,7 +356,7 @@
if (handle != -1 && handle != 0) {
bool result;
result = SDP_DeleteRecord(handle);
- if (result == false) {
+ if (!result) {
BTIF_TRACE_ERROR(" Unable to remove handle 0x%08x", handle);
}
}
diff --git a/btif/src/btif_sm.cc b/btif/src/btif_sm.cc
deleted file mode 100644
index 8f7bbb2..0000000
--- a/btif/src/btif_sm.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2009-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/*****************************************************************************
- *
- * Filename: btif_sm.c
- *
- * Description: Generic BTIF state machine API
- *
- *****************************************************************************/
-
-#define LOG_TAG "bt_btif"
-
-#include "btif_sm.h"
-
-#include "bt_common.h"
-#include "btif_common.h"
-#include "osi/include/allocator.h"
-
-/*****************************************************************************
- * Local type definitions
- *****************************************************************************/
-typedef struct {
- btif_sm_state_t state;
- btif_sm_handler_t* p_handlers;
-} btif_sm_cb_t;
-
-/*****************************************************************************
- * Functions
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * Function btif_sm_init
- *
- * Description Initializes the state machine with the state handlers
- * The caller should ensure that the table and the corresponding
- * states match. The location that 'p_handlers' points to shall
- * be available until the btif_sm_shutdown API is invoked.
- *
- * Returns Returns a pointer to the initialized state machine handle.
- *
- *****************************************************************************/
-
-btif_sm_handle_t btif_sm_init(const btif_sm_handler_t* p_handlers,
- btif_sm_state_t initial_state) {
- if (p_handlers == NULL) {
- BTIF_TRACE_ERROR("%s : p_handlers is NULL", __func__);
- return NULL;
- }
-
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)osi_malloc(sizeof(btif_sm_cb_t));
- p_cb->state = initial_state;
- p_cb->p_handlers = (btif_sm_handler_t*)p_handlers;
-
- /* Send BTIF_SM_ENTER_EVT to the initial state */
- p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL);
-
- return (btif_sm_handle_t)p_cb;
-}
-
-/*****************************************************************************
- *
- * Function btif_sm_shutdown
- *
- * Description Tears down the state machine
- *
- * Returns None
- *
- *****************************************************************************/
-void btif_sm_shutdown(btif_sm_handle_t handle) {
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle;
-
- if (p_cb == NULL) {
- BTIF_TRACE_ERROR("%s : Invalid handle", __func__);
- return;
- }
- osi_free(p_cb);
-}
-
-/*****************************************************************************
- *
- * Function btif_sm_get_state
- *
- * Description Fetches the current state of the state machine
- *
- * Returns Current state
- *
- *****************************************************************************/
-btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle) {
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle;
-
- if (p_cb == NULL) {
- BTIF_TRACE_ERROR("%s : Invalid handle", __func__);
- return 0;
- }
-
- return p_cb->state;
-}
-
-/*****************************************************************************
- *
- * Function btif_sm_dispatch
- *
- * Description Dispatches the 'event' along with 'data' to the current state
- * handler
- *
- * Returns BT_STATUS_SUCCESS on success
- * BT_STATUS_UNHANDLED if event was not processed
- * BT_STATUS_FAIL otherwise
- *
- *****************************************************************************/
-bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event,
- void* data) {
- bt_status_t status = BT_STATUS_SUCCESS;
-
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle;
-
- if (p_cb == NULL) {
- BTIF_TRACE_ERROR("%s : Invalid handle", __func__);
- return BT_STATUS_FAIL;
- }
-
- if (p_cb->p_handlers[p_cb->state](event, data) == false)
- return BT_STATUS_UNHANDLED;
-
- return status;
-}
-
-/*****************************************************************************
- *
- * Function btif_sm_change_state
- *
- * Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT'
- * shall be invoked before exiting the current state. The
- * 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new
- * state
- *
- * Returns BT_STATUS_SUCCESS on success
- * BT_STATUS_UNHANDLED if event was not processed
- * BT_STATUS_FAIL otherwise
- *
- *****************************************************************************/
-bt_status_t btif_sm_change_state(btif_sm_handle_t handle,
- btif_sm_state_t state) {
- bt_status_t status = BT_STATUS_SUCCESS;
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle;
-
- if (p_cb == NULL) {
- BTIF_TRACE_ERROR("%s : Invalid handle", __func__);
- return BT_STATUS_FAIL;
- }
-
- /* Send exit event to the current state */
- if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL) == false)
- status = BT_STATUS_UNHANDLED;
-
- /* Change to the new state */
- p_cb->state = state;
-
- /* Send enter event to the new state */
- if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL) == false)
- status = BT_STATUS_UNHANDLED;
-
- return status;
-}
diff --git a/btif/src/btif_sock.cc b/btif/src/btif_sock.cc
index a41ab13..90121b1 100644
--- a/btif/src/btif_sock.cc
+++ b/btif/src/btif_sock.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,23 +34,31 @@
#include "btif_sock_thread.h"
#include "btif_uid.h"
#include "btif_util.h"
+#include "device/include/controller.h"
#include "osi/include/thread.h"
+using bluetooth::Uuid;
+
static bt_status_t btsock_listen(btsock_type_t type, const char* service_name,
- const uint8_t* uuid, int channel, int* sock_fd,
+ const Uuid* uuid, int channel, int* sock_fd,
int flags, int app_uid);
static bt_status_t btsock_connect(const RawAddress* bd_addr, btsock_type_t type,
- const uint8_t* uuid, int channel,
- int* sock_fd, int flags, int app_uid);
+ const Uuid* uuid, int channel, int* sock_fd,
+ int flags, int app_uid);
+
+static void btsock_request_max_tx_data_length(const RawAddress& bd_addr);
static void btsock_signaled(int fd, int type, int flags, uint32_t user_id);
static std::atomic_int thread_handle{-1};
static thread_t* thread;
-btsock_interface_t* btif_sock_get_interface(void) {
- static btsock_interface_t interface = {sizeof(interface), btsock_listen,
- btsock_connect};
+const btsock_interface_t* btif_sock_get_interface(void) {
+ static btsock_interface_t interface = {
+ sizeof(interface), btsock_listen, /* listen */
+ btsock_connect, /* connect */
+ btsock_request_max_tx_data_length /* request_max_tx_data_length */
+ };
return &interface;
}
@@ -120,15 +128,15 @@
}
static bt_status_t btsock_listen(btsock_type_t type, const char* service_name,
- const uint8_t* service_uuid, int channel,
+ const Uuid* service_uuid, int channel,
int* sock_fd, int flags, int app_uid) {
if ((flags & BTSOCK_FLAG_NO_SDP) == 0) {
- CHECK(service_uuid != NULL || channel > 0);
CHECK(sock_fd != NULL);
}
*sock_fd = INVALID_FD;
bt_status_t status = BT_STATUS_FAIL;
+ int original_channel = channel;
switch (type) {
case BTSOCK_RFCOMM:
@@ -139,7 +147,23 @@
status =
btsock_l2cap_listen(service_name, channel, sock_fd, flags, app_uid);
break;
-
+ case BTSOCK_L2CAP_LE:
+ if (flags & BTSOCK_FLAG_NO_SDP) {
+ /* Set channel to zero so that it will be assigned */
+ channel = 0;
+ } else if (channel <= 0) {
+ LOG_ERROR(LOG_TAG, "%s: type BTSOCK_L2CAP_LE: invalid channel=%d",
+ __func__, channel);
+ break;
+ }
+ flags |= BTSOCK_FLAG_LE_COC;
+ LOG_DEBUG(
+ LOG_TAG,
+ "%s: type=BTSOCK_L2CAP_LE, channel=0x%x, original=0x%x, flags=0x%x",
+ __func__, channel, original_channel, flags);
+ status =
+ btsock_l2cap_listen(service_name, channel, sock_fd, flags, app_uid);
+ break;
case BTSOCK_SCO:
status = btsock_sco_listen(sock_fd, flags);
break;
@@ -154,9 +178,8 @@
}
static bt_status_t btsock_connect(const RawAddress* bd_addr, btsock_type_t type,
- const uint8_t* uuid, int channel,
- int* sock_fd, int flags, int app_uid) {
- CHECK(uuid != NULL || channel > 0);
+ const Uuid* uuid, int channel, int* sock_fd,
+ int flags, int app_uid) {
CHECK(bd_addr != NULL);
CHECK(sock_fd != NULL);
@@ -173,6 +196,13 @@
status = btsock_l2cap_connect(bd_addr, channel, sock_fd, flags, app_uid);
break;
+ case BTSOCK_L2CAP_LE:
+ flags |= BTSOCK_FLAG_LE_COC;
+ LOG_DEBUG(LOG_TAG, "%s: type=BTSOCK_L2CAP_LE, channel=0x%x, flags=0x%x",
+ __func__, channel, flags);
+ status = btsock_l2cap_connect(bd_addr, channel, sock_fd, flags, app_uid);
+ break;
+
case BTSOCK_SCO:
status = btsock_sco_connect(bd_addr, sock_fd, flags);
break;
@@ -186,12 +216,24 @@
return status;
}
+static void btsock_request_max_tx_data_length(const RawAddress& remote_device) {
+ const controller_t* controller = controller_get_interface();
+ uint16_t max_len = controller->get_ble_maximum_tx_data_length();
+
+ DVLOG(2) << __func__ << ": max_len=" << max_len;
+
+ BTA_DmBleSetDataLength(remote_device, max_len);
+}
+
static void btsock_signaled(int fd, int type, int flags, uint32_t user_id) {
switch (type) {
case BTSOCK_RFCOMM:
btsock_rfc_signaled(fd, flags, user_id);
break;
case BTSOCK_L2CAP:
+ case BTSOCK_L2CAP_LE:
+ /* Note: The caller may not distinguish between BTSOCK_L2CAP and
+ * BTSOCK_L2CAP_LE correctly */
btsock_l2cap_signaled(fd, flags, user_id);
break;
default:
diff --git a/btif/src/btif_sock_l2cap.cc b/btif/src/btif_sock_l2cap.cc
index 90e3755..43f2372 100644
--- a/btif/src/btif_sock_l2cap.cc
+++ b/btif/src/btif_sock_l2cap.cc
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2014 Samsung System LSI
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright 2014 Samsung System LSI
+ * Copyright 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,23 +15,22 @@
* limitations under the License.
*/
-#define LOG_TAG "bt_btif_sock"
-
#include "btif_sock_l2cap.h"
+#include <base/logging.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
+#include <vector>
#include <mutex>
#include <hardware/bt_sock.h>
#include "osi/include/allocator.h"
-#include "osi/include/log.h"
#include "bt_common.h"
#include "bt_target.h"
@@ -49,6 +48,7 @@
#include "btu.h"
#include "hcimsgs.h"
#include "l2c_api.h"
+#include "l2c_int.h"
#include "l2cdefs.h"
#include "port_api.h"
#include "sdp_api.h"
@@ -76,16 +76,17 @@
struct packet* first_packet; // fist packet to be delivered to app
struct packet* last_packet; // last packet to be delivered to app
- fixed_queue_t* incoming_que; // data that came in but has not yet been read
unsigned fixed_chan : 1; // fixed channel (or psm?)
unsigned server : 1; // is a server? (or connecting?)
unsigned connected : 1; // is connected?
unsigned outgoing_congest : 1; // should we hold?
unsigned server_psm_sent : 1; // The server shall only send PSM once.
bool is_le_coc; // is le connection oriented channel?
+ uint16_t rx_mtu;
+ uint16_t tx_mtu;
} l2cap_socket;
-static bt_status_t btSock_start_l2cap_server_l(l2cap_socket* sock);
+static void btsock_l2cap_server_listen(l2cap_socket* sock);
static std::mutex state_lock;
@@ -172,18 +173,12 @@
/* makes a copy of the data, returns true on success */
static char packet_put_tail_l(l2cap_socket* sock, const void* data,
uint32_t len) {
- struct packet* p = packet_alloc((const uint8_t*)data, len);
-
if (sock->bytes_buffered >= L2CAP_MAX_RX_BUFFER) {
- LOG_ERROR(LOG_TAG, "packet_put_tail_l: buffer overflow");
+ LOG(ERROR) << __func__ << ": buffer overflow";
return false;
}
- if (!p) {
- LOG_ERROR(LOG_TAG, "packet_put_tail_l: unable to allocate packet...");
- return false;
- }
-
+ struct packet* p = packet_alloc((const uint8_t*)data, len);
p->next = NULL;
p->prev = sock->last_packet;
sock->last_packet = p;
@@ -232,7 +227,7 @@
if (sock->app_fd != -1) {
close(sock->app_fd);
} else {
- APPL_TRACE_ERROR("SOCK_LIST: free(id = %d) - NO app_fd!", sock->id);
+ LOG(ERROR) << "SOCK_LIST: free(id = " << sock->id << ") - NO app_fd!";
}
while (packet_get_head_l(sock, &buf, NULL)) osi_free(buf);
@@ -240,35 +235,35 @@
// lower-level close() should be idempotent... so let's call it and see...
if (sock->is_le_coc) {
// Only call if we are non server connections
- if (sock->handle >= 0 && (sock->server == false)) {
+ if (sock->handle >= 0 && (!sock->server)) {
BTA_JvL2capClose(sock->handle);
}
- if ((sock->channel >= 0) && (sock->server == true)) {
- BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP);
+ if ((sock->channel >= 0) && (sock->server)) {
+ BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP_LE);
}
} else {
// Only call if we are non server connections
- if ((sock->handle >= 0) && (sock->server == false)) {
+ if ((sock->handle >= 0) && (!sock->server)) {
if (sock->fixed_chan)
BTA_JvL2capCloseLE(sock->handle);
else
BTA_JvL2capClose(sock->handle);
}
- if ((sock->channel >= 0) && (sock->server == true)) {
+ if ((sock->channel >= 0) && (sock->server)) {
if (sock->fixed_chan)
BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP_LE);
else
BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP);
if (!sock->fixed_chan) {
- APPL_TRACE_DEBUG("%s stopping L2CAP server channel %d", __func__,
- sock->channel);
+ DVLOG(2) << __func__ << ": stopping L2CAP server channel "
+ << sock->channel;
BTA_JvL2capStopServer(sock->channel, sock->id);
}
}
}
- APPL_TRACE_DEBUG("%s: free(id = %d)", __func__, sock->id);
+ DVLOG(2) << __func__ << ": free id:" << sock->id;
osi_free(sock);
}
@@ -289,7 +284,7 @@
security |= BTM_SEC_IN_MIN_16_DIGIT_PIN;
if (socketpair(AF_LOCAL, SOCK_SEQPACKET, 0, fds)) {
- APPL_TRACE_ERROR("socketpair failed, errno:%d", errno);
+ LOG(ERROR) << "socketpair failed, errno:" << errno;
goto fail_sockpair;
}
@@ -308,6 +303,8 @@
sock->first_packet = NULL;
sock->last_packet = NULL;
+ sock->tx_mtu = L2CAP_LE_MIN_MTU;
+
sock->next = socks;
sock->prev = NULL;
if (socks) socks->prev = sock;
@@ -327,7 +324,7 @@
if (!++sock->id) /* no zero IDs allowed */
sock->id++;
}
- APPL_TRACE_DEBUG("SOCK_LIST: alloc(id = %d)", sock->id);
+ DVLOG(2) << __func__ << " SOCK_LIST: alloc id:" << sock->id;
return sock;
fail_sockpair:
@@ -336,7 +333,7 @@
}
bt_status_t btsock_l2cap_init(int handle, uid_set_t* set) {
- APPL_TRACE_DEBUG("%s handle = %d", __func__);
+ DVLOG(2) << __func__ << ": handle: " << handle;
std::unique_lock<std::mutex> lock(state_lock);
pth = handle;
socks = NULL;
@@ -352,25 +349,28 @@
}
static inline bool send_app_psm_or_chan_l(l2cap_socket* sock) {
+ DVLOG(2) << __func__ << ": channel: " << sock->channel;
return sock_send_all(sock->our_fd, (const uint8_t*)&sock->channel,
sizeof(sock->channel)) == sizeof(sock->channel);
}
static bool send_app_connect_signal(int fd, const RawAddress* addr, int channel,
- int status, int send_fd, int tx_mtu) {
+ int status, int send_fd, uint16_t rx_mtu,
+ uint16_t tx_mtu) {
sock_connect_signal_t cs;
cs.size = sizeof(cs);
cs.bd_addr = *addr;
cs.channel = channel;
cs.status = status;
- cs.max_rx_packet_size = L2CAP_MAX_SDU_LENGTH;
+ cs.max_rx_packet_size = rx_mtu;
cs.max_tx_packet_size = tx_mtu;
if (send_fd != -1) {
if (sock_send_fd(fd, (const uint8_t*)&cs, sizeof(cs), send_fd) ==
sizeof(cs))
return true;
else
- APPL_TRACE_ERROR("sock_send_fd failed, fd:%d, send_fd:%d", fd, send_fd);
+ LOG(ERROR) << "sock_send_fd failed, fd: " << fd
+ << ", send_fd:" << send_fd;
} else if (sock_send_all(fd, (const uint8_t*)&cs, sizeof(cs)) == sizeof(cs)) {
return true;
}
@@ -386,20 +386,20 @@
if (!sock) return;
if (p_start->status != BTA_JV_SUCCESS) {
- APPL_TRACE_ERROR("Error starting l2cap_listen - status: 0x%04x",
- p_start->status);
+ LOG(ERROR) << "Error starting l2cap_listen - status: "
+ << loghex(p_start->status);
btsock_l2cap_free_l(sock);
return;
}
sock->handle = p_start->handle;
- APPL_TRACE_DEBUG("on_srv_l2cap_listen_started() sock->handle =%d id:%d",
- sock->handle, sock->id);
+ DVLOG(2) << __func__ << ": sock->handle: " << sock->handle
+ << ", id: " << sock->id;
- if (sock->server_psm_sent == false) {
+ if (!sock->server_psm_sent) {
if (!send_app_psm_or_chan_l(sock)) {
// closed
- APPL_TRACE_DEBUG("send_app_psm() failed, close rs->id:%d", sock->id);
+ DVLOG(2) << "send_app_psm() failed, close rs->id: " << sock->id;
btsock_l2cap_free_l(sock);
} else {
sock->server_psm_sent = true;
@@ -424,16 +424,13 @@
/**
* Here we allocate a new sock instance to mimic the BluetoothSocket. The socket
- * will be a clone
- * of the sock representing the BluetoothServerSocket.
+ * will be a clone of the sock representing the BluetoothServerSocket.
* */
static void on_srv_l2cap_psm_connect_l(tBTA_JV_L2CAP_OPEN* p_open,
l2cap_socket* sock) {
- l2cap_socket* accept_rs;
- uint32_t new_listen_id;
-
// std::mutex locked by caller
- accept_rs = btsock_l2cap_alloc_l(sock->name, &p_open->rem_bda, false, 0);
+ l2cap_socket* accept_rs =
+ btsock_l2cap_alloc_l(sock->name, &p_open->rem_bda, false, 0);
accept_rs->connected = true;
accept_rs->security = sock->security;
accept_rs->fixed_chan = sock->fixed_chan;
@@ -443,121 +440,114 @@
sock->handle =
-1; /* We should no longer associate this handle with the server socket */
accept_rs->is_le_coc = sock->is_le_coc;
+ accept_rs->tx_mtu = sock->tx_mtu = p_open->tx_mtu;
/* Swap IDs to hand over the GAP connection to the accepted socket, and start
- a new server on
- the newly create socket ID. */
- new_listen_id = accept_rs->id;
+ a new server on the newly create socket ID. */
+ uint32_t new_listen_id = accept_rs->id;
accept_rs->id = sock->id;
sock->id = new_listen_id;
- if (accept_rs) {
- // start monitor the socket
- btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
- SOCK_THREAD_FD_EXCEPTION, sock->id);
- btsock_thread_add_fd(pth, accept_rs->our_fd, BTSOCK_L2CAP,
- SOCK_THREAD_FD_RD, accept_rs->id);
- APPL_TRACE_DEBUG(
- "sending connect signal & app fd: %d to app server to accept() the"
- " connection",
- accept_rs->app_fd);
- APPL_TRACE_DEBUG("server fd:%d, scn:%d", sock->our_fd, sock->channel);
- send_app_connect_signal(sock->our_fd, &accept_rs->addr, sock->channel, 0,
- accept_rs->app_fd, p_open->tx_mtu);
- accept_rs->app_fd =
- -1; // The fd is closed after sent to app in send_app_connect_signal()
- // But for some reason we still leak a FD - either the server socket
- // one or the accept socket one.
- if (btSock_start_l2cap_server_l(sock) != BT_STATUS_SUCCESS) {
- btsock_l2cap_free_l(sock);
- }
- }
+ // start monitor the socket
+ btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
+ SOCK_THREAD_FD_EXCEPTION, sock->id);
+ btsock_thread_add_fd(pth, accept_rs->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD,
+ accept_rs->id);
+ DVLOG(2) << "sending connect signal & app fd: " << accept_rs->app_fd
+ << " to app server to accept() the connection";
+ DVLOG(2) << "server fd: << " << sock->our_fd << ", scn:" << sock->channel;
+ send_app_connect_signal(sock->our_fd, &accept_rs->addr, sock->channel, 0,
+ accept_rs->app_fd, sock->rx_mtu, p_open->tx_mtu);
+ accept_rs->app_fd =
+ -1; // The fd is closed after sent to app in send_app_connect_signal()
+ // But for some reason we still leak a FD - either the server socket
+ // one or the accept socket one.
+ btsock_l2cap_server_listen(sock);
}
static void on_srv_l2cap_le_connect_l(tBTA_JV_L2CAP_LE_OPEN* p_open,
l2cap_socket* sock) {
- l2cap_socket* accept_rs;
- uint32_t new_listen_id;
-
// std::mutex locked by caller
- accept_rs = btsock_l2cap_alloc_l(sock->name, &p_open->rem_bda, false, 0);
- if (accept_rs) {
- // swap IDs
- new_listen_id = accept_rs->id;
- accept_rs->id = sock->id;
- sock->id = new_listen_id;
+ l2cap_socket* accept_rs =
+ btsock_l2cap_alloc_l(sock->name, &p_open->rem_bda, false, 0);
+ if (!accept_rs) return;
- accept_rs->handle = p_open->handle;
- accept_rs->connected = true;
- accept_rs->security = sock->security;
- accept_rs->fixed_chan = sock->fixed_chan;
- accept_rs->channel = sock->channel;
- accept_rs->app_uid = sock->app_uid;
+ // swap IDs
+ uint32_t new_listen_id = accept_rs->id;
+ accept_rs->id = sock->id;
+ sock->id = new_listen_id;
- // if we do not set a callback, this socket will be dropped */
- *(p_open->p_p_cback) = (void*)btsock_l2cap_cbk;
- *(p_open->p_user_data) = UINT_TO_PTR(accept_rs->id);
+ accept_rs->handle = p_open->handle;
+ accept_rs->connected = true;
+ accept_rs->security = sock->security;
+ accept_rs->fixed_chan = sock->fixed_chan;
+ accept_rs->channel = sock->channel;
+ accept_rs->app_uid = sock->app_uid;
+ accept_rs->tx_mtu = sock->tx_mtu = p_open->tx_mtu;
- // start monitor the socket
- btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
- SOCK_THREAD_FD_EXCEPTION, sock->id);
- btsock_thread_add_fd(pth, accept_rs->our_fd, BTSOCK_L2CAP,
- SOCK_THREAD_FD_RD, accept_rs->id);
- APPL_TRACE_DEBUG(
- "sending connect signal & app fd:%dto app server to accept() the"
- " connection",
- accept_rs->app_fd);
- APPL_TRACE_DEBUG("server fd:%d, scn:%d", sock->our_fd, sock->channel);
- send_app_connect_signal(sock->our_fd, &accept_rs->addr, sock->channel, 0,
- accept_rs->app_fd, p_open->tx_mtu);
- accept_rs->app_fd = -1; // the fd is closed after sent to app
- }
+ // if we do not set a callback, this socket will be dropped */
+ *(p_open->p_p_cback) = (void*)btsock_l2cap_cbk;
+ *(p_open->p_user_data) = UINT_TO_PTR(accept_rs->id);
+
+ // start monitor the socket
+ btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
+ SOCK_THREAD_FD_EXCEPTION, sock->id);
+ btsock_thread_add_fd(pth, accept_rs->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD,
+ accept_rs->id);
+ DVLOG(2) << "sending connect signal & app fd: " << accept_rs->app_fd
+ << " to app server to accept() the connection";
+ DVLOG(2) << "server fd: << " << sock->our_fd << ", scn:" << sock->channel;
+ send_app_connect_signal(sock->our_fd, &accept_rs->addr, sock->channel, 0,
+ accept_rs->app_fd, sock->rx_mtu, p_open->tx_mtu);
+ accept_rs->app_fd = -1; // the fd is closed after sent to app
}
static void on_cl_l2cap_psm_connect_l(tBTA_JV_L2CAP_OPEN* p_open,
l2cap_socket* sock) {
sock->addr = p_open->rem_bda;
+ sock->tx_mtu = p_open->tx_mtu;
if (!send_app_psm_or_chan_l(sock)) {
- APPL_TRACE_ERROR("send_app_psm_or_chan_l failed");
+ LOG(ERROR) << "send_app_psm_or_chan_l failed";
return;
}
- if (send_app_connect_signal(sock->our_fd, &sock->addr, sock->channel, 0, -1,
- p_open->tx_mtu)) {
- // start monitoring the socketpair to get call back when app writing data
- APPL_TRACE_DEBUG(
- "on_l2cap_connect_ind, connect signal sent, slot id:%d, psm:%d,"
- " server:%d",
- sock->id, sock->channel, sock->server);
- btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD,
- sock->id);
- sock->connected = true;
- } else
- APPL_TRACE_ERROR("send_app_connect_signal failed");
+ if (!send_app_connect_signal(sock->our_fd, &sock->addr, sock->channel, 0, -1,
+ sock->rx_mtu, p_open->tx_mtu)) {
+ LOG(ERROR) << "send_app_connect_signal failed";
+ return;
+ }
+
+ // start monitoring the socketpair to get call back when app writing data
+ DVLOG(2) << " connect signal sent, slot id: " << sock->id
+ << ", chan: " << sock->channel << ", server: " << sock->server;
+ btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD,
+ sock->id);
+ sock->connected = true;
}
static void on_cl_l2cap_le_connect_l(tBTA_JV_L2CAP_LE_OPEN* p_open,
l2cap_socket* sock) {
sock->addr = p_open->rem_bda;
+ sock->tx_mtu = p_open->tx_mtu;
if (!send_app_psm_or_chan_l(sock)) {
- APPL_TRACE_ERROR("send_app_psm_or_chan_l failed");
+ LOG(ERROR) << "send_app_psm_or_chan_l failed";
return;
}
- if (send_app_connect_signal(sock->our_fd, &sock->addr, sock->channel, 0, -1,
- p_open->tx_mtu)) {
- // start monitoring the socketpair to get call back when app writing data
- APPL_TRACE_DEBUG(
- "on_l2cap_connect_ind, connect signal sent, slot id:%d, Chan:%d,"
- " server:%d",
- sock->id, sock->channel, sock->server);
- btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD,
- sock->id);
- sock->connected = true;
- } else
- APPL_TRACE_ERROR("send_app_connect_signal failed");
+ if (!send_app_connect_signal(sock->our_fd, &sock->addr, sock->channel, 0, -1,
+ sock->rx_mtu, p_open->tx_mtu)) {
+ LOG(ERROR) << "send_app_connect_signal failed";
+ return;
+ }
+
+ // start monitoring the socketpair to get call back when app writing data
+ DVLOG(2) << " connect signal sent, slot id: " << sock->id
+ << ", chan: " << sock->channel << ", server: " << sock->server;
+ btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD,
+ sock->id);
+ sock->connected = true;
}
static void on_l2cap_connect(tBTA_JV* p_data, uint32_t id) {
@@ -568,10 +558,11 @@
std::unique_lock<std::mutex> lock(state_lock);
sock = btsock_l2cap_find_by_id_l(id);
if (!sock) {
- APPL_TRACE_ERROR("on_l2cap_connect on unknown socket");
+ LOG(ERROR) << __func__ << ": unknown socket";
return;
}
+ sock->tx_mtu = le_open->tx_mtu;
if (sock->fixed_chan && le_open->status == BTA_JV_SUCCESS) {
if (!sock->server)
on_cl_l2cap_le_connect_l(le_open, sock);
@@ -593,13 +584,12 @@
sock = btsock_l2cap_find_by_id_l(id);
if (!sock) return;
- APPL_TRACE_DEBUG("on_l2cap_close, slot id:%d, fd:%d, %s:%d, server:%d",
- sock->id, sock->our_fd,
- sock->fixed_chan ? "fixed_chan" : "PSM", sock->channel,
- sock->server);
+ DVLOG(2) << __func__ << ": slot id: " << sock->id << ", fd: " << sock->our_fd
+ << (sock->fixed_chan ? ", fixed_chan:" : ", PSM: ") << sock->channel
+ << ", server:" << sock->server;
// TODO: This does not seem to be called...
// I'm not sure if this will be called for non-server sockets?
- if (!sock->fixed_chan && (sock->server == true)) {
+ if (!sock->fixed_chan && (sock->server)) {
BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP);
}
btsock_l2cap_free_l(sock);
@@ -615,30 +605,21 @@
sock->outgoing_congest = p->cong ? 1 : 0;
// mointer the fd for any outgoing data
if (!sock->outgoing_congest) {
- APPL_TRACE_DEBUG(
- "on_l2cap_outgoing_congest: adding fd to btsock_thread...");
+ DVLOG(2) << __func__ << ": adding fd to btsock_thread...";
btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD,
sock->id);
}
}
-static void on_l2cap_write_done(void* req_id, uint16_t len, uint32_t id) {
- l2cap_socket* sock;
-
- if (req_id != NULL) {
- osi_free(req_id); // free the buffer
- }
-
- int app_uid = -1;
-
+static void on_l2cap_write_done(uint16_t len, uint32_t id) {
std::unique_lock<std::mutex> lock(state_lock);
- sock = btsock_l2cap_find_by_id_l(id);
+ l2cap_socket* sock = btsock_l2cap_find_by_id_l(id);
if (!sock) return;
- app_uid = sock->app_uid;
+ int app_uid = sock->app_uid;
if (!sock->outgoing_congest) {
// monitor the fd for any outgoing data
- APPL_TRACE_DEBUG("on_l2cap_write_done: adding fd to btsock_thread...");
+ DVLOG(2) << __func__ << ": adding fd to btsock_thread...";
btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD,
sock->id);
}
@@ -646,27 +627,6 @@
uid_set_add_tx(uid_set, app_uid, len);
}
-static void on_l2cap_write_fixed_done(void* req_id, uint16_t len, uint32_t id) {
- l2cap_socket* sock;
-
- if (req_id != NULL) {
- osi_free(req_id); // free the buffer
- }
-
- int app_uid = -1;
- std::unique_lock<std::mutex> lock(state_lock);
- sock = btsock_l2cap_find_by_id_l(id);
- if (!sock) return;
-
- app_uid = sock->app_uid;
- if (!sock->outgoing_congest) {
- // monitor the fd for any outgoing data
- btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD,
- sock->id);
- }
- uid_set_add_tx(uid_set, app_uid, len);
-}
-
static void on_l2cap_data_ind(tBTA_JV* evt, uint32_t id) {
l2cap_socket* sock;
@@ -690,28 +650,26 @@
btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_WR,
sock->id);
} else { // connection must be dropped
- APPL_TRACE_DEBUG(
- "on_l2cap_data_ind() unable to push data to socket - closing"
- " fixed channel");
+ DVLOG(2) << __func__
+ << ": unable to push data to socket - closing fixed channel";
BTA_JvL2capCloseLE(sock->handle);
btsock_l2cap_free_l(sock);
}
} else {
- uint8_t buffer[L2CAP_MAX_SDU_LENGTH];
uint32_t count;
if (BTA_JvL2capReady(sock->handle, &count) == BTA_JV_SUCCESS) {
- if (BTA_JvL2capRead(sock->handle, sock->id, buffer, count) ==
+ std::vector<uint8_t> buffer(count);
+ if (BTA_JvL2capRead(sock->handle, sock->id, buffer.data(), count) ==
BTA_JV_SUCCESS) {
- if (packet_put_tail_l(sock, buffer, count)) {
+ if (packet_put_tail_l(sock, buffer.data(), count)) {
bytes_read = count;
btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
SOCK_THREAD_FD_WR, sock->id);
} else { // connection must be dropped
- APPL_TRACE_DEBUG(
- "on_l2cap_data_ind() unable to push data to socket"
- " - closing channel");
+ DVLOG(2) << __func__
+ << ": unable to push data to socket - closing channel";
BTA_JvL2capClose(sock->handle);
btsock_l2cap_free_l(sock);
}
@@ -740,29 +698,27 @@
break;
case BTA_JV_L2CAP_CLOSE_EVT:
- APPL_TRACE_DEBUG("BTA_JV_L2CAP_CLOSE_EVT: id: %u", l2cap_socket_id);
+ DVLOG(2) << "BTA_JV_L2CAP_CLOSE_EVT: id: " << l2cap_socket_id;
on_l2cap_close(&p_data->l2c_close, l2cap_socket_id);
break;
case BTA_JV_L2CAP_DATA_IND_EVT:
on_l2cap_data_ind(p_data, l2cap_socket_id);
- APPL_TRACE_DEBUG("BTA_JV_L2CAP_DATA_IND_EVT");
+ DVLOG(2) << "BTA_JV_L2CAP_DATA_IND_EVT";
break;
case BTA_JV_L2CAP_READ_EVT:
- APPL_TRACE_DEBUG("BTA_JV_L2CAP_READ_EVT not used");
+ DVLOG(2) << "BTA_JV_L2CAP_READ_EVT not used";
break;
case BTA_JV_L2CAP_WRITE_EVT:
- APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_EVT: id: %u", l2cap_socket_id);
- on_l2cap_write_done(p_data->l2c_write.p_data, p_data->l2c_write.len,
- l2cap_socket_id);
+ DVLOG(2) << "BTA_JV_L2CAP_WRITE_EVT: id: " << l2cap_socket_id;
+ on_l2cap_write_done(p_data->l2c_write.len, l2cap_socket_id);
break;
case BTA_JV_L2CAP_WRITE_FIXED_EVT:
- APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_FIXED_EVT: id: %u", l2cap_socket_id);
- on_l2cap_write_fixed_done(p_data->l2c_write_fixed.p_data,
- p_data->l2c_write.len, l2cap_socket_id);
+ DVLOG(2) << "BTA_JV_L2CAP_WRITE_FIXED_EVT: id: " << l2cap_socket_id;
+ on_l2cap_write_done(p_data->l2c_write.len, l2cap_socket_id);
break;
case BTA_JV_L2CAP_CONG_EVT:
@@ -770,8 +726,8 @@
break;
default:
- APPL_TRACE_ERROR("unhandled event %d, slot id: %u", event,
- l2cap_socket_id);
+ LOG(ERROR) << "unhandled event: " << event
+ << ", slot id: " << l2cap_socket_id;
break;
}
}
@@ -805,62 +761,47 @@
std::unique_lock<std::mutex> lock(state_lock);
l2cap_socket* sock = btsock_l2cap_find_by_id_l(id);
if (!sock) {
- APPL_TRACE_ERROR("%s: Error: sock is null", __func__);
+ LOG(ERROR) << __func__ << ": sock is null";
return;
}
sock->channel = psm;
- if (btSock_start_l2cap_server_l(sock) != BT_STATUS_SUCCESS)
- btsock_l2cap_free_l(sock);
+ btsock_l2cap_server_listen(sock);
}
-static bt_status_t btSock_start_l2cap_server_l(l2cap_socket* sock) {
- tL2CAP_CFG_INFO cfg;
- bt_status_t stat = BT_STATUS_SUCCESS;
- /* Setup ETM settings:
- * mtu will be set below */
- memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
-
- cfg.fcr_present = true;
- cfg.fcr = obex_l2c_fcr_opts_def;
+static void btsock_l2cap_server_listen(l2cap_socket* sock) {
+ DVLOG(2) << __func__ << ": fixed_chan: " << sock->fixed_chan
+ << ", channel: " << sock->channel
+ << ", is_le_coc: " << sock->is_le_coc;
if (sock->fixed_chan) {
- if (BTA_JvL2capStartServerLE(sock->security, 0, NULL, sock->channel,
- L2CAP_DEFAULT_MTU, NULL, btsock_l2cap_cbk,
- sock->id) != BTA_JV_SUCCESS)
- stat = BT_STATUS_FAIL;
-
- } else {
- /* If we have a channel specified in the request, just start the server,
- * else we request a PSM and start the server after we receive a PSM. */
- if (sock->channel < 0) {
- if (sock->is_le_coc) {
- if (BTA_JvGetChannelId(BTA_JV_CONN_TYPE_L2CAP_LE, sock->id, 0) !=
- BTA_JV_SUCCESS)
- stat = BT_STATUS_FAIL;
- } else {
- if (BTA_JvGetChannelId(BTA_JV_CONN_TYPE_L2CAP, sock->id, 0) !=
- BTA_JV_SUCCESS)
- stat = BT_STATUS_FAIL;
- }
- } else {
- if (sock->is_le_coc) {
- if (BTA_JvL2capStartServer(BTA_JV_CONN_TYPE_L2CAP_LE, sock->security, 0,
- NULL, sock->channel, L2CAP_MAX_SDU_LENGTH,
- &cfg, btsock_l2cap_cbk,
- sock->id) != BTA_JV_SUCCESS)
- stat = BT_STATUS_FAIL;
- } else {
- if (BTA_JvL2capStartServer(BTA_JV_CONN_TYPE_L2CAP, sock->security, 0,
- &obex_l2c_etm_opt, sock->channel,
- L2CAP_MAX_SDU_LENGTH, &cfg, btsock_l2cap_cbk,
- sock->id) != BTA_JV_SUCCESS)
- stat = BT_STATUS_FAIL;
- }
- }
+ BTA_JvL2capStartServerLE(sock->channel, btsock_l2cap_cbk, sock->id);
+ return;
}
- return stat;
+
+ int connection_type =
+ sock->is_le_coc ? BTA_JV_CONN_TYPE_L2CAP_LE : BTA_JV_CONN_TYPE_L2CAP;
+
+ /* If we have a channel specified in the request, just start the server,
+ * else we request a PSM and start the server after we receive a PSM. */
+ if (sock->channel <= 0) {
+ BTA_JvGetChannelId(connection_type, sock->id, 0);
+ return;
+ }
+
+ /* Setup ETM settings: mtu will be set below */
+ std::unique_ptr<tL2CAP_CFG_INFO> cfg = std::make_unique<tL2CAP_CFG_INFO>(
+ tL2CAP_CFG_INFO{.fcr_present = true, .fcr = obex_l2c_fcr_opts_def});
+
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info;
+ if (!sock->is_le_coc) {
+ ertm_info.reset(new tL2CAP_ERTM_INFO(obex_l2c_etm_opt));
+ }
+
+ BTA_JvL2capStartServer(connection_type, sock->security, 0,
+ std::move(ertm_info), sock->channel, sock->rx_mtu,
+ std::move(cfg), btsock_l2cap_cbk, sock->id);
}
static bt_status_t btsock_l2cap_listen_or_connect(const char* name,
@@ -868,10 +809,7 @@
int channel, int* sock_fd,
int flags, char listen,
int app_uid) {
- bt_status_t stat;
int fixed_chan = 1;
- l2cap_socket* sock;
- tL2CAP_CFG_INFO cfg;
bool is_le_coc = false;
if (!sock_fd) return BT_STATUS_PARM_INVALID;
@@ -880,9 +818,9 @@
// We need to auto assign a PSM
fixed_chan = 0;
} else {
+ is_le_coc = (flags & BTSOCK_FLAG_LE_COC) != 0;
fixed_chan = (channel & L2CAP_MASK_FIXED_CHANNEL) != 0;
- is_le_coc = (channel & L2CAP_MASK_LE_COC_CHANNEL) != 0;
- channel &= ~(L2CAP_MASK_FIXED_CHANNEL | L2CAP_MASK_LE_COC_CHANNEL);
+ channel &= ~L2CAP_MASK_FIXED_CHANNEL;
}
if (!is_inited()) return BT_STATUS_NOT_READY;
@@ -890,7 +828,7 @@
// TODO: This is kind of bad to lock here, but it is needed for the current
// design.
std::unique_lock<std::mutex> lock(state_lock);
- sock = btsock_l2cap_alloc_l(name, addr, listen, flags);
+ l2cap_socket* sock = btsock_l2cap_alloc_l(name, addr, listen, flags);
if (!sock) {
return BT_STATUS_NOMEM;
}
@@ -899,60 +837,44 @@
sock->channel = channel;
sock->app_uid = app_uid;
sock->is_le_coc = is_le_coc;
-
- stat = BT_STATUS_SUCCESS;
-
- /* Setup ETM settings:
- * mtu will be set below */
- memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
-
- cfg.fcr_present = true;
- cfg.fcr = obex_l2c_fcr_opts_def;
+ sock->rx_mtu = is_le_coc ? L2CAP_SDU_LENGTH_LE_MAX : L2CAP_SDU_LENGTH_MAX;
/* "role" is never initialized in rfcomm code */
if (listen) {
- stat = btSock_start_l2cap_server_l(sock);
+ btsock_l2cap_server_listen(sock);
} else {
if (fixed_chan) {
- if (BTA_JvL2capConnectLE(sock->security, 0, NULL, channel,
- L2CAP_DEFAULT_MTU, NULL, sock->addr,
- btsock_l2cap_cbk, sock->id) != BTA_JV_SUCCESS)
- stat = BT_STATUS_FAIL;
-
+ BTA_JvL2capConnectLE(channel, sock->addr, btsock_l2cap_cbk, sock->id);
} else {
- if (sock->is_le_coc) {
- if (BTA_JvL2capConnect(BTA_JV_CONN_TYPE_L2CAP_LE, sock->security, 0,
- NULL, channel, L2CAP_MAX_SDU_LENGTH, &cfg,
- sock->addr, btsock_l2cap_cbk,
- sock->id) != BTA_JV_SUCCESS)
- stat = BT_STATUS_FAIL;
- } else {
- if (BTA_JvL2capConnect(BTA_JV_CONN_TYPE_L2CAP, sock->security, 0,
- &obex_l2c_etm_opt, channel, L2CAP_MAX_SDU_LENGTH,
- &cfg, sock->addr, btsock_l2cap_cbk,
- sock->id) != BTA_JV_SUCCESS)
- stat = BT_STATUS_FAIL;
+ int connection_type =
+ sock->is_le_coc ? BTA_JV_CONN_TYPE_L2CAP_LE : BTA_JV_CONN_TYPE_L2CAP;
+
+ /* Setup ETM settings: mtu will be set below */
+ std::unique_ptr<tL2CAP_CFG_INFO> cfg = std::make_unique<tL2CAP_CFG_INFO>(
+ tL2CAP_CFG_INFO{.fcr_present = true, .fcr = obex_l2c_fcr_opts_def});
+
+ std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info;
+ if (!sock->is_le_coc) {
+ ertm_info.reset(new tL2CAP_ERTM_INFO(obex_l2c_etm_opt));
}
+
+ BTA_JvL2capConnect(
+ connection_type, sock->security, 0, std::move(ertm_info), channel,
+ sock->rx_mtu, std::move(cfg), sock->addr, btsock_l2cap_cbk, sock->id);
}
}
- if (stat == BT_STATUS_SUCCESS) {
- *sock_fd = sock->app_fd;
- /* We pass the FD to JAVA, but since it runs in another process, we need to
- * also close
- * it in native, either straight away, as done when accepting an incoming
- * connection,
- * or when doing cleanup after this socket */
- sock->app_fd =
- -1; /*This leaks the file descriptor. The FD should be closed in
- JAVA but it apparently do not work */
- btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
- SOCK_THREAD_FD_EXCEPTION, sock->id);
- } else {
- btsock_l2cap_free_l(sock);
- }
+ *sock_fd = sock->app_fd;
+ /* We pass the FD to JAVA, but since it runs in another process, we need to
+ * also close it in native, either straight away, as done when accepting an
+ * incoming connection, or when doing cleanup after this socket */
+ sock->app_fd = -1;
+ /*This leaks the file descriptor. The FD should be closed in JAVA but it
+ * apparently do not work */
+ btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
+ SOCK_THREAD_FD_EXCEPTION, sock->id);
- return stat;
+ return BT_STATUS_SUCCESS;
}
bt_status_t btsock_l2cap_listen(const char* name, int channel, int* sock_fd,
@@ -997,60 +919,69 @@
return false;
}
+inline BT_HDR* malloc_l2cap_buf(uint16_t len) {
+ // We need FCS only for L2CAP_FCR_ERTM_MODE, but it's just 2 bytes so it's ok
+ BT_HDR* msg = (BT_HDR*)osi_malloc(BT_HDR_SIZE + L2CAP_MIN_OFFSET + len +
+ L2CAP_FCS_LENGTH);
+ msg->offset = L2CAP_MIN_OFFSET;
+ msg->len = len;
+ return msg;
+}
+
+inline uint8_t* get_l2cap_sdu_start_ptr(BT_HDR* msg) {
+ return (uint8_t*)(msg) + BT_HDR_SIZE + msg->offset;
+}
+
void btsock_l2cap_signaled(int fd, int flags, uint32_t user_id) {
- l2cap_socket* sock;
char drop_it = false;
/* We use MSG_DONTWAIT when sending data to JAVA, hence it can be accepted to
* hold the lock. */
std::unique_lock<std::mutex> lock(state_lock);
- sock = btsock_l2cap_find_by_id_l(user_id);
+ l2cap_socket* sock = btsock_l2cap_find_by_id_l(user_id);
if (!sock) return;
if ((flags & SOCK_THREAD_FD_RD) && !sock->server) {
// app sending data
if (sock->connected) {
int size = 0;
+ bool ioctl_success = ioctl(sock->our_fd, FIONREAD, &size) == 0;
+ if (!(flags & SOCK_THREAD_FD_EXCEPTION) || (ioctl_success && size)) {
+ /* FIONREAD return number of bytes that are immediately available for
+ reading, might be bigger than awaiting packet.
- if (!(flags & SOCK_THREAD_FD_EXCEPTION) ||
- (ioctl(sock->our_fd, FIONREAD, &size) == 0 && size)) {
- uint8_t* buffer = (uint8_t*)osi_malloc(L2CAP_MAX_SDU_LENGTH);
+ BluetoothSocket.write(...) guarantees that any packet send to this
+ socket is broken into pieces no bigger than MTU bytes (as requested
+ by BT spec). */
+ size = std::min(size, (int)sock->tx_mtu);
+
+ BT_HDR* buffer = malloc_l2cap_buf(size);
/* The socket is created with SOCK_SEQPACKET, hence we read one message
- * at the time. The maximum size of a message is allocated to ensure
- * data is not lost. This is okay to do as Android uses virtual memory,
- * hence even if we only use a fraction of the memory it should not
- * block for others to use the memory. As the definition of
- * ioctl(FIONREAD) do not clearly define what value will be returned if
- * multiple messages are written to the socket before any message is
- * read from the socket, we could potentially risk to allocate way more
- * memory than needed. One of the use cases for this socket is obex
- * where multiple 64kbyte messages are typically written to the socket
- * in a tight loop, hence we risk the ioctl will return the total amount
- * of data in the buffer, which could be multiple 64kbyte chunks.
- * UPDATE: As the stack cannot handle 64kbyte buffers, the size is
- * reduced to around 8kbyte - and using malloc for buffer allocation
- * here seems to be wrong
- * UPDATE: Since we are responsible for freeing the buffer in the
- * write_complete_ind, it is OK to use malloc. */
+ * at the time. */
ssize_t count;
- OSI_NO_INTR(count = recv(fd, buffer, L2CAP_MAX_SDU_LENGTH,
- MSG_NOSIGNAL | MSG_DONTWAIT));
- APPL_TRACE_DEBUG(
- "btsock_l2cap_signaled - %d bytes received from socket", count);
+ OSI_NO_INTR(count = recv(fd, get_l2cap_sdu_start_ptr(buffer), size,
+ MSG_NOSIGNAL | MSG_DONTWAIT | MSG_TRUNC));
+ if (count > sock->tx_mtu) {
+ /* This can't happen thanks to check in BluetoothSocket.java but leave
+ * this in case this socket is ever used anywhere else*/
+ LOG(ERROR) << "recv more than MTU. Data will be lost: " << count;
+ count = sock->tx_mtu;
+ }
+
+ /* When multiple packets smaller than MTU are flushed to the socket, the
+ size of the single packet read could be smaller than the ioctl
+ reported total size of awaiting packets. Hence, we adjust the buffer
+ length. */
+ buffer->len = count;
+ DVLOG(2) << __func__ << ": bytes received from socket: " << count;
if (sock->fixed_chan) {
- if (BTA_JvL2capWriteFixed(sock->channel, sock->addr,
- PTR_TO_UINT(buffer), btsock_l2cap_cbk,
- buffer, count, user_id) != BTA_JV_SUCCESS) {
- // On fail, free the buffer
- on_l2cap_write_fixed_done(buffer, count, user_id);
- }
+ // will take care of freeing buffer
+ BTA_JvL2capWriteFixed(sock->channel, sock->addr, PTR_TO_UINT(buffer),
+ btsock_l2cap_cbk, buffer, user_id);
} else {
- if (BTA_JvL2capWrite(sock->handle, PTR_TO_UINT(buffer), buffer, count,
- user_id) != BTA_JV_SUCCESS) {
- // On fail, free the buffer
- on_l2cap_write_done(buffer, count, user_id);
- }
+ // will take care of freeing buffer
+ BTA_JvL2capWrite(sock->handle, PTR_TO_UINT(buffer), buffer, user_id);
}
}
} else
diff --git a/btif/src/btif_sock_rfc.cc b/btif/src/btif_sock_rfc.cc
index 2ea2a15..4b490a0 100644
--- a/btif/src/btif_sock_rfc.cc
+++ b/btif/src/btif_sock_rfc.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,6 +59,8 @@
* L2CAP functions from this file. */
#include "btif_sock_l2cap.h"
+using bluetooth::Uuid;
+
// Maximum number of RFCOMM channels (1-30 inclusive).
#define MAX_RFC_CHANNEL 30
@@ -82,7 +84,7 @@
int scn_notified;
RawAddress addr;
int is_service_uuid_valid;
- uint8_t service_uuid[16];
+ Uuid service_uuid;
char service_name[256];
int fd;
int app_fd; // Temporary storage for the half of the socketpair that's sent
@@ -157,7 +159,7 @@
for (size_t i = 0; i < ARRAY_SIZE(rfc_slots); ++i)
if (rfc_slots[i].id == id) return &rfc_slots[i];
- LOG_ERROR(LOG_TAG, "%s unable to find RFCOMM slot id: %d", __func__, id);
+ LOG_ERROR(LOG_TAG, "%s unable to find RFCOMM slot id: %u", __func__, id);
return NULL;
}
@@ -181,7 +183,7 @@
}
static rfc_slot_t* alloc_rfc_slot(const RawAddress* addr, const char* name,
- const uint8_t* uuid, int channel, int flags,
+ const Uuid& uuid, int channel, int flags,
bool server) {
int security = 0;
if (flags & BTSOCK_FLAG_ENCRYPT)
@@ -215,13 +217,9 @@
slot->scn = channel;
slot->app_uid = -1;
- if (!is_uuid_empty(uuid)) {
- memcpy(slot->service_uuid, uuid, sizeof(slot->service_uuid));
- slot->is_service_uuid_valid = true;
- } else {
- memset(slot->service_uuid, 0, sizeof(slot->service_uuid));
- slot->is_service_uuid_valid = false;
- }
+ slot->is_service_uuid_valid = !uuid.IsEmpty();
+ slot->service_uuid = uuid;
+
if (name && *name) {
strlcpy(slot->service_name, name, sizeof(slot->service_name));
} else {
@@ -269,7 +267,7 @@
}
bt_status_t btsock_rfc_listen(const char* service_name,
- const uint8_t* service_uuid, int channel,
+ const Uuid* service_uuid, int channel,
int* sock_fd, int flags, int app_uid) {
CHECK(sock_fd != NULL);
CHECK((service_uuid != NULL) ||
@@ -285,15 +283,16 @@
if (!is_init_done()) return BT_STATUS_NOT_READY;
if ((flags & BTSOCK_FLAG_NO_SDP) == 0) {
- if (is_uuid_empty(service_uuid)) {
+ if (!service_uuid || service_uuid->IsEmpty()) {
APPL_TRACE_DEBUG(
- "BTA_JvGetChannelId: service_uuid not set AND "
- "BTSOCK_FLAG_NO_SDP is not set - changing to SPP");
- service_uuid =
- UUID_SPP; // Use serial port profile to listen to specified channel
+ "%s: service_uuid not set AND BTSOCK_FLAG_NO_SDP is not set - "
+ "changing to SPP",
+ __func__);
+ // Use serial port profile to listen to specified channel
+ service_uuid = &UUID_SPP;
} else {
// Check the service_uuid. overwrite the channel # if reserved
- int reserved_channel = get_reserved_rfc_channel(service_uuid);
+ int reserved_channel = get_reserved_rfc_channel(*service_uuid);
if (reserved_channel > 0) {
channel = reserved_channel;
}
@@ -303,7 +302,7 @@
std::unique_lock<std::recursive_mutex> lock(slot_lock);
rfc_slot_t* slot =
- alloc_rfc_slot(NULL, service_name, service_uuid, channel, flags, true);
+ alloc_rfc_slot(NULL, service_name, *service_uuid, channel, flags, true);
if (!slot) {
LOG_ERROR(LOG_TAG, "%s unable to allocate RFCOMM slot.", __func__);
return BT_STATUS_FAIL;
@@ -329,10 +328,10 @@
}
bt_status_t btsock_rfc_connect(const RawAddress* bd_addr,
- const uint8_t* service_uuid, int channel,
+ const Uuid* service_uuid, int channel,
int* sock_fd, int flags, int app_uid) {
CHECK(sock_fd != NULL);
- CHECK(service_uuid != NULL || (channel >= 1 && channel <= MAX_RFC_CHANNEL));
+ CHECK((service_uuid != NULL) || (channel >= 1 && channel <= MAX_RFC_CHANNEL));
*sock_fd = INVALID_FD;
@@ -345,13 +344,13 @@
std::unique_lock<std::recursive_mutex> lock(slot_lock);
rfc_slot_t* slot =
- alloc_rfc_slot(bd_addr, NULL, service_uuid, channel, flags, false);
+ alloc_rfc_slot(bd_addr, NULL, *service_uuid, channel, flags, false);
if (!slot) {
LOG_ERROR(LOG_TAG, "%s unable to allocate RFCOMM slot.", __func__);
return BT_STATUS_FAIL;
}
- if (is_uuid_empty(service_uuid)) {
+ if (!service_uuid || service_uuid->IsEmpty()) {
tBTA_JV_STATUS ret =
BTA_JvRfcommConnect(slot->security, slot->role, slot->scn, slot->addr,
rfcomm_cback, slot->id);
@@ -368,12 +367,8 @@
return BT_STATUS_FAIL;
}
} else {
- tSDP_UUID sdp_uuid;
- sdp_uuid.len = 16;
- memcpy(sdp_uuid.uu.uuid128, service_uuid, sizeof(sdp_uuid.uu.uuid128));
-
if (!is_requesting_sdp()) {
- BTA_JvStartDiscovery(*bd_addr, 1, &sdp_uuid, slot->id);
+ BTA_JvStartDiscovery(*bd_addr, 1, service_uuid, slot->id);
slot->f.pending_sdp_request = false;
slot->f.doing_sdp_request = true;
} else {
@@ -444,7 +439,7 @@
}
static bool send_app_scn(rfc_slot_t* slot) {
- if (slot->scn_notified == true) {
+ if (slot->scn_notified) {
// already send, just return success.
return true;
}
@@ -625,7 +620,7 @@
break;
default:
- LOG_ERROR(LOG_TAG, "%s unhandled event %d, slot id: %zi", __func__, event,
+ LOG_ERROR(LOG_TAG, "%s unhandled event %d, slot id: %u", __func__, event,
rfcomm_slot_id);
break;
}
@@ -658,7 +653,7 @@
APPL_TRACE_DEBUG("send_app_scn() failed, close rs->id:%d", rs->id);
cleanup_rfc_slot(rs);
} else {
- if (rs->is_service_uuid_valid == true) {
+ if (rs->is_service_uuid_valid) {
// We already have data for SDP record, create it (RFC-only
// profiles)
BTA_JvCreateRecordByUser(rs->id);
@@ -732,11 +727,7 @@
// Find the next slot that needs to perform an SDP request and service it.
slot = find_rfc_slot_by_pending_sdp();
if (slot) {
- tSDP_UUID sdp_uuid;
- sdp_uuid.len = 16;
- memcpy(sdp_uuid.uu.uuid128, slot->service_uuid,
- sizeof(sdp_uuid.uu.uuid128));
- BTA_JvStartDiscovery(slot->addr, 1, &sdp_uuid, slot->id);
+ BTA_JvStartDiscovery(slot->addr, 1, &slot->service_uuid, slot->id);
slot->f.pending_sdp_request = false;
slot->f.doing_sdp_request = true;
}
diff --git a/btif/src/btif_sock_sco.cc b/btif/src/btif_sock_sco.cc
index f3e2bb9..6283196 100644
--- a/btif/src/btif_sock_sco.cc
+++ b/btif/src/btif_sock_sco.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/src/btif_sock_sdp.cc b/btif/src/btif_sock_sdp.cc
index afbfab4..d7993e5 100644
--- a/btif/src/btif_sock_sdp.cc
+++ b/btif/src/btif_sock_sdp.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,6 +43,8 @@
#include "sdp_api.h"
#include "utl.h"
+using bluetooth::Uuid;
+
// This module provides an abstraction on top of the lower-level SDP database
// code for registration and discovery of various bluetooth sockets.
//
@@ -85,7 +87,8 @@
#define RESERVED_SCN_OPS 12
#define UUID_MAX_LENGTH 16
-#define UUID_MATCHES(u1, u2) !memcmp(u1, u2, UUID_MAX_LENGTH)
+
+#define SPP_PROFILE_VERSION 0x0102
// Adds a protocol list and service name (if provided) to an SDP record given by
// |sdp_handle|, and marks it as browseable. This is a shortcut for defining a
@@ -111,7 +114,7 @@
proto_list[1].num_params = 1;
proto_list[1].params[0] = channel;
- if (with_obex == true) {
+ if (with_obex) {
proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX;
proto_list[2].num_params = 0;
}
@@ -152,15 +155,15 @@
// Registers a service with the given |name|, |uuid|, and |channel| in the SDP
// database as a generic L2CAP RFCOMM protocol, storing its |uuid| as a service
// class sequence.
-static int add_sdp_by_uuid(const char* name, const uint8_t* uuid,
+static int add_sdp_by_uuid(const char* name, const Uuid& uuid,
const uint16_t channel) {
- APPL_TRACE_DEBUG("add_sdp_by_uuid: scn: %d, service_name: %s", channel, name);
+ APPL_TRACE_DEBUG("%s: uuid: %s, scn: %d, service_name: %s", __func__,
+ uuid.ToString().c_str(), channel, name);
uint32_t handle = SDP_CreateRecord();
if (handle == 0) {
APPL_TRACE_ERROR(
- "add_sdp_by_uuid: failed to create sdp record, "
- "scn: %d, service_name: %s",
+ "%s: failed to create sdp record, scn: %d, service_name: %s", __func__,
channel, name);
return 0;
}
@@ -183,7 +186,8 @@
// Do the conversion to big-endian -- tmp is only used to iterate through the
// UUID array in the macro and serves no other purpose as the conversion
// macros are not hygenic.
- { ARRAY_TO_BE_STREAM(tmp, uuid, UUID_MAX_LENGTH); }
+
+ { ARRAY_TO_BE_STREAM(tmp, uuid.To128BitBE().data(), UUID_MAX_LENGTH); }
stage = "service_class_sequence";
if (!SDP_AddSequence(handle, (uint16_t)ATTR_ID_SERVICE_CLASS_ID_LIST, 1,
@@ -191,17 +195,14 @@
goto error;
APPL_TRACE_DEBUG(
- "add_sdp_by_uuid: service registered successfully, "
- "service_name: %s, handle: 0x%08x",
- name, handle);
+ "%s: service registered successfully, service_name: %s, handle: 0x%08x",
+ __func__, name, handle);
return handle;
error:
SDP_DeleteRecord(handle);
- APPL_TRACE_ERROR(
- "add_sdp_by_uuid: failed to register service "
- "stage: %s, service_name: %s",
- stage, name);
+ APPL_TRACE_ERROR("%s: failed to register service stage: %s, service_name: %s",
+ __func__, stage, name);
return 0;
}
@@ -357,6 +358,11 @@
stage = "service_class";
if (!SDP_AddServiceClassIdList(handle, 1, &service)) goto error;
+ stage = "profile_descriptor_list";
+ if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_SERIAL_PORT,
+ SPP_PROFILE_VERSION))
+ goto error;
+
APPL_TRACE_DEBUG(
"add_spp_sdp: service registered successfully, "
"service_name: %s, handle 0x%08x)",
@@ -377,10 +383,10 @@
// |channel|. This function attempts to identify the type of the service based
// upon its |uuid|, and will override the |channel| with a reserved channel
// number if the |uuid| matches one of the preregistered bluez SDP records.
-static int add_rfc_sdp_by_uuid(const char* name, const uint8_t* uuid,
+static int add_rfc_sdp_by_uuid(const char* name, const Uuid& uuid,
const int channel) {
- APPL_TRACE_DEBUG("add_rfc_sdp_by_uuid: service_name: %s, channel: %d", name,
- channel);
+ APPL_TRACE_DEBUG("%s: uuid: %s, service_name: %s, channel: %d", __func__,
+ uuid.ToString().c_str(), name, channel);
/*
* Bluetooth Socket API relies on having preregistered bluez sdp records for
@@ -402,14 +408,14 @@
int handle = 0;
- if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
+ if (uuid == UUID_OBEX_OBJECT_PUSH) {
handle = add_ops_sdp(name, final_channel);
- } else if (UUID_MATCHES(UUID_PBAP_PSE, uuid)) {
+ } else if (uuid == UUID_PBAP_PSE) {
// PBAP Server is always channel 19
handle = add_pbap_sdp(name, final_channel);
- } else if (UUID_MATCHES(UUID_SPP, uuid)) {
+ } else if (uuid == UUID_SPP) {
handle = add_spp_sdp(name, final_channel);
- } else if (UUID_MATCHES(UUID_MAP_MAS, uuid)) {
+ } else if (uuid == UUID_MAP_MAS) {
// Record created by new SDP create record interface
handle = 0xff;
} else {
@@ -429,10 +435,10 @@
return false;
}
-int get_reserved_rfc_channel(const uint8_t* uuid) {
- if (UUID_MATCHES(UUID_PBAP_PSE, uuid)) {
+int get_reserved_rfc_channel(const bluetooth::Uuid& uuid) {
+ if (uuid == UUID_PBAP_PSE) {
return RESERVED_SCN_PBS;
- } else if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
+ } else if (uuid == UUID_OBEX_OBJECT_PUSH) {
return RESERVED_SCN_OPS;
}
@@ -442,8 +448,8 @@
// Adds an SDP record to the SDP database using the given |name|, |uuid|, and
// |channel|. Note that if the |uuid| is empty, the |uuid| will be set based
// upon the |channel| passed in.
-int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, const int channel) {
- if (is_uuid_empty(uuid)) {
+int add_rfc_sdp_rec(const char* name, Uuid uuid, const int channel) {
+ if (uuid.IsEmpty()) {
switch (channel) {
case RESERVED_SCN_PBS: // PBAP Reserved port
uuid = UUID_PBAP_PSE;
diff --git a/btif/src/btif_sock_thread.cc b/btif/src/btif_sock_thread.cc
index b206892..a49568b 100644
--- a/btif/src/btif_sock_thread.cc
+++ b/btif/src/btif_sock_thread.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/btif/src/btif_sock_util.cc b/btif/src/btif_sock_util.cc
index bf76100..68afa2a 100644
--- a/btif/src/btif_sock_util.cc
+++ b/btif/src/btif_sock_util.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -145,89 +145,3 @@
close(send_fd);
return ret_len;
}
-
-static const char* hex_table = "0123456789abcdef";
-static inline void byte2hex(const char* data, char** str) {
- **str = hex_table[(*data >> 4) & 0xf];
- ++*str;
- **str = hex_table[*data & 0xf];
- ++*str;
-}
-static inline void byte2char(const char* data, char** str) {
- **str = *data < ' ' ? '.' : *data > '~' ? '.' : *data;
- ++(*str);
-}
-static inline void word2hex(const char* data, char** hex) {
- byte2hex(&data[1], hex);
- byte2hex(&data[0], hex);
-}
-void dump_bin(const char* title, const char* data, int size) {
- char line_buff[256];
- char* line;
- int i, j, addr;
- const int width = 16;
- LOG_DEBUG(LOG_TAG, "%s, size:%d, dump started {", title, size);
- if (size <= 0) return;
- // write offset
- line = line_buff;
- *line++ = ' ';
- *line++ = ' ';
- *line++ = ' ';
- *line++ = ' ';
- *line++ = ' ';
- *line++ = ' ';
- for (j = 0; j < width; j++) {
- byte2hex((const char*)&j, &line);
- *line++ = ' ';
- }
- *line = 0;
- LOG_DEBUG(LOG_TAG, "%s", line_buff);
-
- for (i = 0; i < size / width; i++) {
- line = line_buff;
- // write address:
- addr = i * width;
- word2hex((const char*)&addr, &line);
- *line++ = ':';
- *line++ = ' ';
- // write hex of data
- for (j = 0; j < width; j++) {
- byte2hex(&data[j], &line);
- *line++ = ' ';
- }
- // write char of data
- for (j = 0; j < width; j++) byte2char(data++, &line);
- // wirte the end of line
- *line = 0;
- // output the line
- LOG_DEBUG(LOG_TAG, "%s", line_buff);
- }
- // last line of left over if any
- int leftover = size % width;
- if (leftover > 0) {
- line = line_buff;
- // write address:
- addr = i * width;
- word2hex((const char*)&addr, &line);
- *line++ = ':';
- *line++ = ' ';
- // write hex of data
- for (j = 0; j < leftover; j++) {
- byte2hex(&data[j], &line);
- *line++ = ' ';
- }
- // write hex padding
- for (; j < width; j++) {
- *line++ = ' ';
- *line++ = ' ';
- *line++ = ' ';
- }
- // write char of data
- for (j = 0; j < leftover; j++) byte2char(data++, &line);
- // write the end of line
- *line = 0;
- // output the line
- LOG_DEBUG(LOG_TAG, "%s", line_buff);
- }
- LOG_DEBUG(LOG_TAG, "%s, size:%d, dump ended }", title, size);
-}
diff --git a/btif/src/btif_storage.cc b/btif/src/btif_storage.cc
index 1c34787..fe00a2b 100644
--- a/btif/src/btif_storage.cc
+++ b/btif/src/btif_storage.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +40,9 @@
#include <time.h>
#include "bt_common.h"
+#include "bta_closure_api.h"
#include "bta_hd_api.h"
+#include "bta_hearing_aid_api.h"
#include "bta_hh_api.h"
#include "btif_api.h"
#include "btif_config.h"
@@ -54,6 +56,9 @@
#include "osi/include/log.h"
#include "osi/include/osi.h"
+using base::Bind;
+using bluetooth::Uuid;
+
/*******************************************************************************
* Constants & Macros
******************************************************************************/
@@ -88,7 +93,7 @@
(p).type = (t); \
(p).val = (v); \
(p).len = (l); \
- s = btif_storage_get_adapter_property(&(p)); \
+ (s) = btif_storage_get_adapter_property(&(p)); \
} while (0)
// TODO: This macro should be converted to a function
@@ -167,26 +172,24 @@
******************************************************************************/
static bt_status_t btif_in_fetch_bonded_ble_device(
- const char* remote_bd_addr, int add,
+ const std::string& remote_bd_addr, int add,
btif_bonded_devices_t* p_bonded_devices);
-static bt_status_t btif_in_fetch_bonded_device(const char* bdstr);
+static bt_status_t btif_in_fetch_bonded_device(const std::string& bdstr);
-static bool btif_has_ble_keys(const char* bdstr);
+static bool btif_has_ble_keys(const std::string& bdstr);
/*******************************************************************************
* Static functions
******************************************************************************/
static int prop2cfg(const RawAddress* remote_bd_addr, bt_property_t* prop) {
- std::string addrstr;
- const char* bdstr = addrstr.c_str();
+ std::string bdstr;
if (remote_bd_addr) {
- addrstr = remote_bd_addr->ToString();
- bdstr = addrstr.c_str();
+ bdstr = remote_bd_addr->ToString();
}
- BTIF_TRACE_DEBUG("in, bd addr:%s, prop type:%d, len:%d", bdstr, prop->type,
- prop->len);
+ BTIF_TRACE_DEBUG("in, bd addr:%s, prop type:%d, len:%d", bdstr.c_str(),
+ prop->type, prop->len);
char value[1024];
if (prop->len <= 0 || prop->len > (int)sizeof(value) - 1) {
BTIF_TRACE_ERROR("property type:%d, len:%d is invalid", prop->type,
@@ -198,14 +201,18 @@
btif_config_set_int(bdstr, BTIF_STORAGE_PATH_REMOTE_DEVTIME,
(int)time(NULL));
break;
- case BT_PROPERTY_BDNAME:
- strncpy(value, (char*)prop->val, prop->len);
- value[prop->len] = '\0';
+ case BT_PROPERTY_BDNAME: {
+ int name_length = prop->len > BTM_MAX_LOC_BD_NAME_LEN
+ ? BTM_MAX_LOC_BD_NAME_LEN
+ : prop->len;
+ strncpy(value, (char*)prop->val, name_length);
+ value[name_length] = '\0';
if (remote_bd_addr)
btif_config_set_str(bdstr, BTIF_STORAGE_PATH_REMOTE_NAME, value);
else
btif_config_set_str("Adapter", BTIF_STORAGE_KEY_ADAPTER_NAME, value);
break;
+ }
case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
strncpy(value, (char*)prop->val, prop->len);
value[prop->len] = '\0';
@@ -228,22 +235,12 @@
*(int*)prop->val);
break;
case BT_PROPERTY_UUIDS: {
- uint32_t i;
- char buf[64];
- value[0] = 0;
- for (i = 0; i < (prop->len) / sizeof(bt_uuid_t); i++) {
- bt_uuid_t* p_uuid = (bt_uuid_t*)prop->val + i;
- memset(buf, 0, sizeof(buf));
- uuid_to_string_legacy(p_uuid, buf, sizeof(buf));
- if (strlen(value) + strlen(buf) + 1 > (int) sizeof(value) - 1) {
- android_errorWriteLog(0x534e4554, "73963551");
- return false;
- }
- strcat(value, buf);
- // strcat(value, ";");
- strcat(value, " ");
+ std::string val;
+ size_t cnt = (prop->len) / sizeof(Uuid);
+ for (size_t i = 0; i < cnt; i++) {
+ val += (reinterpret_cast<Uuid*>(prop->val) + i)->ToString() + " ";
}
- btif_config_set_str(bdstr, BTIF_STORAGE_PATH_REMOTE_SERVICE, value);
+ btif_config_set_str(bdstr, BTIF_STORAGE_PATH_REMOTE_SERVICE, val);
break;
}
case BT_PROPERTY_REMOTE_VERSION_INFO: {
@@ -264,8 +261,10 @@
return false;
}
- /* save changes if the device was bonded */
- if (btif_in_fetch_bonded_device(bdstr) == BT_STATUS_SUCCESS) {
+ /* No need to look for bonded device with address of NULL */
+ if (remote_bd_addr &&
+ btif_in_fetch_bonded_device(bdstr) == BT_STATUS_SUCCESS) {
+ /* save changes if the device was bonded */
btif_config_flush();
}
@@ -273,14 +272,12 @@
}
static int cfg2prop(const RawAddress* remote_bd_addr, bt_property_t* prop) {
- std::string addrstr;
- const char* bdstr = addrstr.c_str();
+ std::string bdstr;
if (remote_bd_addr) {
- addrstr = remote_bd_addr->ToString();
- bdstr = addrstr.c_str();
+ bdstr = remote_bd_addr->ToString();
}
- BTIF_TRACE_DEBUG("in, bd addr:%s, prop type:%d, len:%d", bdstr, prop->type,
- prop->len);
+ BTIF_TRACE_DEBUG("in, bd addr:%s, prop type:%d, len:%d", bdstr.c_str(),
+ prop->type, prop->len);
if (prop->len <= 0) {
BTIF_TRACE_ERROR("property type:%d, len:%d is invalid", prop->type,
prop->len);
@@ -346,10 +343,10 @@
int size = sizeof(value);
if (btif_config_get_str(bdstr, BTIF_STORAGE_PATH_REMOTE_SERVICE, value,
&size)) {
- bt_uuid_t* p_uuid = (bt_uuid_t*)prop->val;
+ Uuid* p_uuid = reinterpret_cast<Uuid*>(prop->val);
size_t num_uuids =
btif_split_uuids_string(value, p_uuid, BT_MAX_NUM_UUIDS);
- prop->len = num_uuids * sizeof(bt_uuid_t);
+ prop->len = num_uuids * sizeof(Uuid);
ret = true;
} else {
prop->val = NULL;
@@ -364,11 +361,11 @@
ret = btif_config_get_int(bdstr, BTIF_STORAGE_PATH_REMOTE_VER_MFCT,
&info->manufacturer);
- if (ret == true)
+ if (ret)
ret = btif_config_get_int(bdstr, BTIF_STORAGE_PATH_REMOTE_VER_VER,
&info->version);
- if (ret == true)
+ if (ret)
ret = btif_config_get_int(bdstr, BTIF_STORAGE_PATH_REMOTE_VER_SUBVER,
&info->sub_ver);
}
@@ -391,7 +388,7 @@
* Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
*
******************************************************************************/
-static bt_status_t btif_in_fetch_bonded_device(const char* bdstr) {
+static bt_status_t btif_in_fetch_bonded_device(const std::string& bdstr) {
bool bt_linkkey_file_found = false;
LINK_KEY link_key;
@@ -407,7 +404,8 @@
if ((btif_in_fetch_bonded_ble_device(bdstr, false, NULL) !=
BT_STATUS_SUCCESS) &&
(!bt_linkkey_file_found)) {
- BTIF_TRACE_DEBUG("Remote device:%s, no link key or ble key found", bdstr);
+ BTIF_TRACE_DEBUG("Remote device:%s, no link key or ble key found",
+ bdstr.c_str());
return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
@@ -430,13 +428,13 @@
bool bt_linkkey_file_found = false;
int device_type;
- for (const btif_config_section_iter_t* iter = btif_config_section_begin();
- iter != btif_config_section_end();
- iter = btif_config_section_next(iter)) {
- const char* name = btif_config_section_name(iter);
+ // TODO: this code is not thread safe, it can corrupt config content.
+ // b/67595284
+ for (const section_t& section : btif_config_sections()) {
+ const std::string& name = section.name;
if (!RawAddress::IsValidAddress(name)) continue;
- BTIF_TRACE_DEBUG("Remote device:%s", name);
+ BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
LINK_KEY link_key;
size_t size = sizeof(link_key);
if (btif_config_get_bin(name, "LinkKey", link_key, &size)) {
@@ -465,9 +463,10 @@
bt_linkkey_file_found = false;
}
}
- if (!btif_in_fetch_bonded_ble_device(name, add, p_bonded_devices) &&
+ if (!btif_in_fetch_bonded_ble_device(name.c_str(), add, p_bonded_devices) &&
!bt_linkkey_file_found) {
- BTIF_TRACE_DEBUG("Remote device:%s, no link key or ble key found", name);
+ BTIF_TRACE_DEBUG("Remote device:%s, no link key or ble key found",
+ name.c_str());
}
}
return BT_STATUS_SUCCESS;
@@ -480,11 +479,11 @@
CHECK(device_added);
CHECK(key_found);
- char buffer[100];
- memset(buffer, 0, sizeof(buffer));
+ tBTA_LE_KEY_VALUE key;
+ memset(&key, 0, sizeof(key));
- if (btif_storage_get_ble_bonding_key(&bd_addr, key_type, buffer, key_len) ==
- BT_STATUS_SUCCESS) {
+ if (btif_storage_get_ble_bonding_key(&bd_addr, key_type, (uint8_t*)&key,
+ key_len) == BT_STATUS_SUCCESS) {
if (add_key) {
if (!*device_added) {
BTA_DmAddBleDevice(bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
@@ -493,7 +492,7 @@
BTIF_TRACE_DEBUG("%s() Adding key type %d for %s", __func__, key_type,
bd_addr.ToString().c_str());
- BTA_DmAddBleKey(bd_addr, (tBTA_LE_KEY_VALUE*)buffer, key_type);
+ BTA_DmAddBleKey(bd_addr, &key, key_type);
}
*key_found = true;
@@ -520,15 +519,21 @@
* Returns Number of UUIDs parsed from the supplied string
*
******************************************************************************/
-size_t btif_split_uuids_string(const char* str, bt_uuid_t* p_uuid,
+size_t btif_split_uuids_string(const char* str, bluetooth::Uuid* p_uuid,
size_t max_uuids) {
CHECK(str);
CHECK(p_uuid);
size_t num_uuids = 0;
while (str && num_uuids < max_uuids) {
- bool rc = string_to_uuid(str, p_uuid++);
- if (!rc) break;
+ bool is_valid;
+ bluetooth::Uuid tmp =
+ Uuid::FromString(std::string(str, Uuid::kString128BitLen), &is_valid);
+ if (!is_valid) break;
+
+ *p_uuid = tmp;
+ p_uuid++;
+
num_uuids++;
str = strchr(str, ' ');
if (str) str++;
@@ -556,7 +561,7 @@
RawAddress* bd_addr = (RawAddress*)property->val;
/* Fetch the local BD ADDR */
const controller_t* controller = controller_get_interface();
- if (controller->get_is_ready() == false) {
+ if (!controller->get_is_ready()) {
LOG_ERROR(LOG_TAG,
"%s: Controller not ready! Unable to return Bluetooth Address",
__func__);
@@ -587,7 +592,7 @@
return BT_STATUS_SUCCESS;
} else if (property->type == BT_PROPERTY_UUIDS) {
/* publish list of local supported services */
- bt_uuid_t* p_uuid = (bt_uuid_t*)property->val;
+ Uuid* p_uuid = reinterpret_cast<Uuid*>(property->val);
uint32_t num_uuids = 0;
uint32_t i;
@@ -599,32 +604,35 @@
if (service_mask & (tBTA_SERVICE_MASK)(1 << i)) {
switch (i) {
case BTA_HFP_SERVICE_ID: {
- uuid16_to_uuid128(UUID_SERVCLASS_AG_HANDSFREE, p_uuid + num_uuids);
+ *(p_uuid + num_uuids) =
+ Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
num_uuids++;
}
/* intentional fall through: Send both BFP & HSP UUIDs if HFP is
* enabled */
case BTA_HSP_SERVICE_ID: {
- uuid16_to_uuid128(UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
- p_uuid + num_uuids);
+ *(p_uuid + num_uuids) =
+ Uuid::From16Bit(UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY);
num_uuids++;
} break;
case BTA_A2DP_SOURCE_SERVICE_ID: {
- uuid16_to_uuid128(UUID_SERVCLASS_AUDIO_SOURCE, p_uuid + num_uuids);
+ *(p_uuid + num_uuids) =
+ Uuid::From16Bit(UUID_SERVCLASS_AUDIO_SOURCE);
num_uuids++;
} break;
case BTA_A2DP_SINK_SERVICE_ID: {
- uuid16_to_uuid128(UUID_SERVCLASS_AUDIO_SINK, p_uuid + num_uuids);
+ *(p_uuid + num_uuids) = Uuid::From16Bit(UUID_SERVCLASS_AUDIO_SINK);
num_uuids++;
} break;
case BTA_HFP_HS_SERVICE_ID: {
- uuid16_to_uuid128(UUID_SERVCLASS_HF_HANDSFREE, p_uuid + num_uuids);
+ *(p_uuid + num_uuids) =
+ Uuid::From16Bit(UUID_SERVCLASS_HF_HANDSFREE);
num_uuids++;
} break;
}
}
}
- property->len = (num_uuids) * sizeof(bt_uuid_t);
+ property->len = (num_uuids) * sizeof(Uuid);
return BT_STATUS_SUCCESS;
}
@@ -736,15 +744,14 @@
bt_status_t btif_storage_add_bonded_device(RawAddress* remote_bd_addr,
LINK_KEY link_key, uint8_t key_type,
uint8_t pin_length) {
- std::string addrstr = remote_bd_addr->ToString();
- const char* bdstr = addrstr.c_str();
+ std::string bdstr = remote_bd_addr->ToString();
int ret = btif_config_set_int(bdstr, "LinkKeyType", (int)key_type);
ret &= btif_config_set_int(bdstr, "PinLength", (int)pin_length);
ret &= btif_config_set_bin(bdstr, "LinkKey", link_key, sizeof(LINK_KEY));
if (is_restricted_mode()) {
BTIF_TRACE_WARNING("%s: '%s' pairing will be removed if unrestricted",
- __func__, bdstr);
+ __func__, bdstr.c_str());
btif_config_set_int(bdstr, "Restricted", 1);
}
@@ -765,9 +772,8 @@
******************************************************************************/
bt_status_t btif_storage_remove_bonded_device(
const RawAddress* remote_bd_addr) {
- std::string addrstr = remote_bd_addr->ToString();
- const char* bdstr = addrstr.c_str();
- BTIF_TRACE_DEBUG("in bd addr:%s", bdstr);
+ std::string bdstr = remote_bd_addr->ToString();
+ BTIF_TRACE_DEBUG("in bd addr:%s", bdstr.c_str());
btif_storage_remove_ble_bonding_keys(remote_bd_addr);
@@ -778,6 +784,9 @@
ret &= btif_config_remove(bdstr, "PinLength");
if (btif_config_exist(bdstr, "LinkKey"))
ret &= btif_config_remove(bdstr, "LinkKey");
+ if (btif_config_exist(bdstr, BTIF_STORAGE_PATH_REMOTE_ALIASE)) {
+ ret &= btif_config_remove(bdstr, BTIF_STORAGE_PATH_REMOTE_ALIASE);
+ }
/* write bonded info immediately */
btif_config_flush();
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
@@ -806,8 +815,8 @@
bt_bdname_t name, alias;
bt_scan_mode_t mode;
uint32_t disc_timeout;
- bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS];
- bt_uuid_t remote_uuids[BT_MAX_NUM_UUIDS];
+ Uuid local_uuids[BT_MAX_NUM_UUIDS];
+ Uuid remote_uuids[BT_MAX_NUM_UUIDS];
bt_status_t status;
btif_in_fetch_bonded_devices(&bonded_devices, 1);
@@ -930,7 +939,8 @@
******************************************************************************/
bt_status_t btif_storage_add_ble_bonding_key(RawAddress* remote_bd_addr,
- char* key, uint8_t key_type,
+ const uint8_t* key,
+ uint8_t key_type,
uint8_t key_length) {
const char* name;
switch (key_type) {
@@ -955,8 +965,8 @@
default:
return BT_STATUS_FAIL;
}
- int ret = btif_config_set_bin(remote_bd_addr->ToString().c_str(), name,
- (const uint8_t*)key, key_length);
+ int ret =
+ btif_config_set_bin(remote_bd_addr->ToString(), name, key, key_length);
btif_config_save();
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
@@ -972,7 +982,8 @@
*
******************************************************************************/
bt_status_t btif_storage_get_ble_bonding_key(RawAddress* remote_bd_addr,
- uint8_t key_type, char* key_value,
+ uint8_t key_type,
+ uint8_t* key_value,
int key_length) {
const char* name;
switch (key_type) {
@@ -997,8 +1008,8 @@
return BT_STATUS_FAIL;
}
size_t length = key_length;
- int ret = btif_config_get_bin(remote_bd_addr->ToString().c_str(), name,
- (uint8_t*)key_value, &length);
+ int ret =
+ btif_config_get_bin(remote_bd_addr->ToString(), name, key_value, &length);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
@@ -1014,9 +1025,8 @@
******************************************************************************/
bt_status_t btif_storage_remove_ble_bonding_keys(
const RawAddress* remote_bd_addr) {
- std::string addrstr = remote_bd_addr->ToString();
- const char* bdstr = addrstr.c_str();
- BTIF_TRACE_DEBUG(" %s in bd addr:%s", __func__, bdstr);
+ std::string bdstr = remote_bd_addr->ToString();
+ BTIF_TRACE_DEBUG(" %s in bd addr:%s", __func__, bdstr.c_str());
int ret = 1;
if (btif_config_exist(bdstr, "LE_KEY_PENC"))
ret &= btif_config_remove(bdstr, "LE_KEY_PENC");
@@ -1126,7 +1136,7 @@
}
static bt_status_t btif_in_fetch_bonded_ble_device(
- const char* remote_bd_addr, int add,
+ const std::string& remote_bd_addr, int add,
btif_bonded_devices_t* p_bonded_devices) {
int device_type;
int addr_type;
@@ -1138,7 +1148,8 @@
if ((device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE ||
btif_has_ble_keys(remote_bd_addr)) {
- BTIF_TRACE_DEBUG("%s Found a LE device: %s", __func__, remote_bd_addr);
+ BTIF_TRACE_DEBUG("%s Found a LE device: %s", __func__,
+ remote_bd_addr.c_str());
RawAddress bd_addr;
RawAddress::FromString(remote_bd_addr, bd_addr);
@@ -1180,12 +1191,12 @@
bt_status_t btif_storage_set_remote_addr_type(const RawAddress* remote_bd_addr,
uint8_t addr_type) {
- int ret = btif_config_set_int(remote_bd_addr->ToString().c_str(), "AddrType",
+ int ret = btif_config_set_int(remote_bd_addr->ToString(), "AddrType",
(int)addr_type);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
-bool btif_has_ble_keys(const char* bdstr) {
+bool btif_has_ble_keys(const std::string& bdstr) {
return btif_config_exist(bdstr, "LE_KEY_PENC");
}
@@ -1201,8 +1212,8 @@
******************************************************************************/
bt_status_t btif_storage_get_remote_addr_type(const RawAddress* remote_bd_addr,
int* addr_type) {
- int ret = btif_config_get_int(remote_bd_addr->ToString().c_str(), "AddrType",
- addr_type);
+ int ret =
+ btif_config_get_int(remote_bd_addr->ToString(), "AddrType", addr_type);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
/*******************************************************************************
@@ -1223,8 +1234,7 @@
uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout,
uint16_t dl_len, uint8_t* dsc_list) {
BTIF_TRACE_DEBUG("btif_storage_add_hid_device_info:");
- std::string addrstr = remote_bd_addr->ToString();
- const char* bdstr = addrstr.c_str();
+ std::string bdstr = remote_bd_addr->ToString();
btif_config_set_int(bdstr, "HidAttrMask", attr_mask);
btif_config_set_int(bdstr, "HidSubClass", sub_class);
btif_config_set_int(bdstr, "HidAppId", app_id);
@@ -1250,69 +1260,67 @@
*
******************************************************************************/
bt_status_t btif_storage_load_bonded_hid_info(void) {
- RawAddress bd_addr;
- tBTA_HH_DEV_DSCP_INFO dscp_info;
- uint16_t attr_mask;
- uint8_t sub_class;
- uint8_t app_id;
-
- memset(&dscp_info, 0, sizeof(dscp_info));
- for (const btif_config_section_iter_t* iter = btif_config_section_begin();
- iter != btif_config_section_end();
- iter = btif_config_section_next(iter)) {
- const char* name = btif_config_section_name(iter);
+ // TODO: this code is not thread safe, it can corrupt config content.
+ // b/67595284
+ for (const section_t& section : btif_config_sections()) {
+ const std::string& name = section.name;
if (!RawAddress::IsValidAddress(name)) continue;
- BTIF_TRACE_DEBUG("Remote device:%s", name);
+ BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
+
int value;
- if (btif_in_fetch_bonded_device(name) == BT_STATUS_SUCCESS) {
- if (btif_config_get_int(name, "HidAttrMask", &value)) {
- attr_mask = (uint16_t)value;
+ if (!btif_config_get_int(name, "HidAttrMask", &value)) continue;
+ uint16_t attr_mask = (uint16_t)value;
- btif_config_get_int(name, "HidSubClass", &value);
- sub_class = (uint8_t)value;
+ if (btif_in_fetch_bonded_device(name) != BT_STATUS_SUCCESS) {
+ RawAddress bd_addr;
+ RawAddress::FromString(name, bd_addr);
+ btif_storage_remove_hid_info(&bd_addr);
+ continue;
+ }
- btif_config_get_int(name, "HidAppId", &value);
- app_id = (uint8_t)value;
+ tBTA_HH_DEV_DSCP_INFO dscp_info;
+ memset(&dscp_info, 0, sizeof(dscp_info));
- btif_config_get_int(name, "HidVendorId", &value);
- dscp_info.vendor_id = (uint16_t)value;
+ btif_config_get_int(name, "HidSubClass", &value);
+ uint8_t sub_class = (uint8_t)value;
- btif_config_get_int(name, "HidProductId", &value);
- dscp_info.product_id = (uint16_t)value;
+ btif_config_get_int(name, "HidAppId", &value);
+ uint8_t app_id = (uint8_t)value;
- btif_config_get_int(name, "HidVersion", &value);
- dscp_info.version = (uint8_t)value;
+ btif_config_get_int(name, "HidVendorId", &value);
+ dscp_info.vendor_id = (uint16_t)value;
- btif_config_get_int(name, "HidCountryCode", &value);
- dscp_info.ctry_code = (uint8_t)value;
+ btif_config_get_int(name, "HidProductId", &value);
+ dscp_info.product_id = (uint16_t)value;
- value = 0;
- btif_config_get_int(name, "HidSSRMaxLatency", &value);
- dscp_info.ssr_max_latency = (uint16_t)value;
+ btif_config_get_int(name, "HidVersion", &value);
+ dscp_info.version = (uint8_t)value;
- value = 0;
- btif_config_get_int(name, "HidSSRMinTimeout", &value);
- dscp_info.ssr_min_tout = (uint16_t)value;
+ btif_config_get_int(name, "HidCountryCode", &value);
+ dscp_info.ctry_code = (uint8_t)value;
- size_t len = btif_config_get_bin_length(name, "HidDescriptor");
- if (len > 0) {
- dscp_info.descriptor.dl_len = (uint16_t)len;
- dscp_info.descriptor.dsc_list = (uint8_t*)alloca(len);
- btif_config_get_bin(name, "HidDescriptor",
- (uint8_t*)dscp_info.descriptor.dsc_list, &len);
- }
- RawAddress::FromString(name, bd_addr);
- // add extracted information to BTA HH
- if (btif_hh_add_added_dev(bd_addr, attr_mask)) {
- BTA_HhAddDev(bd_addr, attr_mask, sub_class, app_id, dscp_info);
- }
- }
- } else {
- if (btif_config_get_int(name, "HidAttrMask", &value)) {
- btif_storage_remove_hid_info(&bd_addr);
- RawAddress::FromString(name, bd_addr);
- }
+ value = 0;
+ btif_config_get_int(name, "HidSSRMaxLatency", &value);
+ dscp_info.ssr_max_latency = (uint16_t)value;
+
+ value = 0;
+ btif_config_get_int(name, "HidSSRMinTimeout", &value);
+ dscp_info.ssr_min_tout = (uint16_t)value;
+
+ size_t len = btif_config_get_bin_length(name, "HidDescriptor");
+ if (len > 0) {
+ dscp_info.descriptor.dl_len = (uint16_t)len;
+ dscp_info.descriptor.dsc_list = (uint8_t*)alloca(len);
+ btif_config_get_bin(name, "HidDescriptor",
+ (uint8_t*)dscp_info.descriptor.dsc_list, &len);
+ }
+
+ RawAddress bd_addr;
+ RawAddress::FromString(name, bd_addr);
+ // add extracted information to BTA HH
+ if (btif_hh_add_added_dev(bd_addr, attr_mask)) {
+ BTA_HhAddDev(bd_addr, attr_mask, sub_class, app_id, dscp_info);
}
}
@@ -1331,8 +1339,7 @@
*
******************************************************************************/
bt_status_t btif_storage_remove_hid_info(RawAddress* remote_bd_addr) {
- std::string addrstr = remote_bd_addr->ToString();
- const char* bdstr = addrstr.c_str();
+ std::string bdstr = remote_bd_addr->ToString();
btif_config_remove(bdstr, "HidAttrMask");
btif_config_remove(bdstr, "HidSubClass");
@@ -1348,6 +1355,135 @@
return BT_STATUS_SUCCESS;
}
+constexpr char HEARING_AID_PSM[] = "HearingAidPsm";
+constexpr char HEARING_AID_CAPABILITIES[] = "HearingAidCapabilities";
+constexpr char HEARING_AID_CODECS[] = "HearingAidCodecs";
+constexpr char HEARING_AID_AUDIO_CONTROL_POINT[] =
+ "HearingAidAudioControlPoint";
+constexpr char HEARING_AID_VOLUME_HANDLE[] = "HearingAidVolumeHandle";
+constexpr char HEARING_AID_SYNC_ID[] = "HearingAidSyncId";
+constexpr char HEARING_AID_RENDER_DELAY[] = "HearingAidRenderDelay";
+constexpr char HEARING_AID_PREPARATION_DELAY[] = "HearingAidPreparationDelay";
+constexpr char HEARING_AID_IS_WHITE_LISTED[] = "HearingAidIsWhiteListed";
+
+void btif_storage_add_hearing_aid(const RawAddress& address, uint16_t psm,
+ uint8_t capabilities, uint16_t codecs,
+ uint16_t audio_control_point_handle,
+ uint16_t volume_handle, uint64_t hi_sync_id,
+ uint16_t render_delay,
+ uint16_t preparation_delay) {
+ do_in_jni_thread(
+ FROM_HERE,
+ Bind(
+ [](const RawAddress& address, uint16_t psm, uint8_t capabilities,
+ uint16_t codecs, uint16_t audio_control_point_handle,
+ uint16_t volume_handle, uint64_t hi_sync_id, uint16_t render_delay,
+ uint16_t preparation_delay) {
+ std::string bdstr = address.ToString();
+ VLOG(2) << "saving hearing aid device: " << bdstr;
+ btif_config_set_int(bdstr, HEARING_AID_PSM, psm);
+ btif_config_set_int(bdstr, HEARING_AID_CAPABILITIES, capabilities);
+ btif_config_set_int(bdstr, HEARING_AID_CODECS, codecs);
+ btif_config_set_int(bdstr, HEARING_AID_AUDIO_CONTROL_POINT,
+ audio_control_point_handle);
+ btif_config_set_int(bdstr, HEARING_AID_VOLUME_HANDLE,
+ volume_handle);
+ btif_config_set_uint64(bdstr, HEARING_AID_SYNC_ID, hi_sync_id);
+ btif_config_set_int(bdstr, HEARING_AID_RENDER_DELAY, render_delay);
+ btif_config_set_int(bdstr, HEARING_AID_PREPARATION_DELAY,
+ preparation_delay);
+ btif_config_set_int(bdstr, HEARING_AID_IS_WHITE_LISTED, true);
+ btif_config_save();
+ },
+ address, psm, capabilities, codecs, audio_control_point_handle,
+ volume_handle, hi_sync_id, render_delay, preparation_delay));
+}
+
+/** Loads information about bonded hearing aid devices */
+void btif_storage_load_bonded_hearing_aids() {
+ // TODO: this code is not thread safe, it can corrupt config content.
+ // b/67595284
+ for (const section_t& section : btif_config_sections()) {
+ const std::string& name = section.name;
+ if (!RawAddress::IsValidAddress(name)) continue;
+
+ BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
+
+ int value;
+ if (!btif_config_get_int(name, HEARING_AID_PSM, &value)) continue;
+ uint16_t psm = value;
+
+ if (btif_in_fetch_bonded_device(name.c_str()) != BT_STATUS_SUCCESS) {
+ RawAddress bd_addr;
+ RawAddress::FromString(name, bd_addr);
+ btif_storage_remove_hearing_aid(bd_addr);
+ continue;
+ }
+
+ uint8_t capabilities = 0;
+ if (btif_config_get_int(name, HEARING_AID_CAPABILITIES, &value))
+ capabilities = value;
+
+ uint16_t codecs = 0;
+ if (btif_config_get_int(name, HEARING_AID_CODECS, &value)) codecs = value;
+
+ uint16_t audio_control_point_handle = 0;
+ if (btif_config_get_int(name, HEARING_AID_AUDIO_CONTROL_POINT, &value))
+ audio_control_point_handle = value;
+
+ uint16_t volume_handle = 0;
+ if (btif_config_get_int(name, HEARING_AID_VOLUME_HANDLE, &value))
+ volume_handle = value;
+
+ uint64_t lvalue;
+ uint64_t hi_sync_id = 0;
+ if (btif_config_get_uint64(name, HEARING_AID_SYNC_ID, &lvalue))
+ hi_sync_id = lvalue;
+
+ uint16_t render_delay = 0;
+ if (btif_config_get_int(name, HEARING_AID_RENDER_DELAY, &value))
+ render_delay = value;
+
+ uint16_t preparation_delay = 0;
+ if (btif_config_get_int(name, HEARING_AID_PREPARATION_DELAY, &value))
+ preparation_delay = value;
+
+ uint16_t is_white_listed = 0;
+ if (btif_config_get_int(name, HEARING_AID_IS_WHITE_LISTED, &value))
+ is_white_listed = value;
+
+ RawAddress bd_addr;
+ RawAddress::FromString(name, bd_addr);
+ // add extracted information to BTA Hearing Aid
+ do_in_bta_thread(
+ FROM_HERE,
+ Bind(&HearingAid::AddFromStorage, bd_addr, psm, capabilities, codecs,
+ audio_control_point_handle, volume_handle, hi_sync_id,
+ render_delay, preparation_delay, is_white_listed));
+ }
+}
+
+/** Deletes the bonded hearing aid device info from NVRAM */
+void btif_storage_remove_hearing_aid(const RawAddress& address) {
+ std::string addrstr = address.ToString();
+
+ btif_config_remove(addrstr, HEARING_AID_PSM);
+ btif_config_remove(addrstr, HEARING_AID_CAPABILITIES);
+ btif_config_remove(addrstr, HEARING_AID_CODECS);
+ btif_config_remove(addrstr, HEARING_AID_AUDIO_CONTROL_POINT);
+ btif_config_remove(addrstr, HEARING_AID_VOLUME_HANDLE);
+ btif_config_remove(addrstr, HEARING_AID_SYNC_ID);
+ btif_config_remove(addrstr, HEARING_AID_IS_WHITE_LISTED);
+ btif_config_save();
+}
+
+/** Remove the hearing aid device from white list */
+void btif_storage_remove_hearing_aid_white_list(const RawAddress& address) {
+ std::string addrstr = address.ToString();
+
+ btif_config_set_int(addrstr, HEARING_AID_IS_WHITE_LISTED, false);
+}
+
/*******************************************************************************
*
* Function btif_storage_is_restricted_device
@@ -1360,7 +1496,7 @@
*
******************************************************************************/
bool btif_storage_is_restricted_device(const RawAddress* remote_bd_addr) {
- return btif_config_exist(remote_bd_addr->ToString().c_str(), "Restricted");
+ return btif_config_exist(remote_bd_addr->ToString(), "Restricted");
}
/*******************************************************************************
@@ -1372,14 +1508,13 @@
*
******************************************************************************/
bt_status_t btif_storage_load_hidd(void) {
-
- for (const btif_config_section_iter_t* iter = btif_config_section_begin();
- iter != btif_config_section_end();
- iter = btif_config_section_next(iter)) {
- const char* name = btif_config_section_name(iter);
+ // TODO: this code is not thread safe, it can corrupt config content.
+ // b/67595284
+ for (const section_t& section : btif_config_sections()) {
+ const std::string& name = section.name;
if (!RawAddress::IsValidAddress(name)) continue;
- BTIF_TRACE_DEBUG("Remote device:%s", name);
+ BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
int value;
if (btif_in_fetch_bonded_device(name) == BT_STATUS_SUCCESS) {
if (btif_config_get_int(name, "HidDeviceCabled", &value)) {
@@ -1398,13 +1533,23 @@
*
* Function btif_storage_set_hidd
*
- * Description Stores hidd bonded device info in nvram.
+ * Description Stores currently used HIDD device info in nvram and remove
+ * the "HidDeviceCabled" flag from unused devices
*
* Returns BT_STATUS_SUCCESS
*
******************************************************************************/
bt_status_t btif_storage_set_hidd(RawAddress* remote_bd_addr) {
- btif_config_set_int(remote_bd_addr->ToString().c_str(), "HidDeviceCabled", 1);
+ std::string remote_device_address_string = remote_bd_addr->ToString();
+ for (const section_t& section : btif_config_sections()) {
+ if (!RawAddress::IsValidAddress(section.name)) continue;
+ if (section.name == remote_device_address_string) continue;
+ if (btif_in_fetch_bonded_device(section.name) == BT_STATUS_SUCCESS) {
+ btif_config_remove(section.name, "HidDeviceCabled");
+ }
+ }
+
+ btif_config_set_int(remote_device_address_string, "HidDeviceCabled", 1);
btif_config_save();
return BT_STATUS_SUCCESS;
}
@@ -1419,7 +1564,7 @@
*
******************************************************************************/
bt_status_t btif_storage_remove_hidd(RawAddress* remote_bd_addr) {
- btif_config_remove(remote_bd_addr->ToString().c_str(), "HidDeviceCabled");
+ btif_config_remove(remote_bd_addr->ToString(), "HidDeviceCabled");
btif_config_save();
return BT_STATUS_SUCCESS;
diff --git a/btif/src/btif_uid.cc b/btif/src/btif_uid.cc
index 45e3456..4ee5fe8 100644
--- a/btif/src/btif_uid.cc
+++ b/btif/src/btif_uid.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,13 +27,14 @@
#include "bt_common.h"
#include "btif_uid.h"
+static std::mutex set_lock;
+
typedef struct uid_set_node_t {
struct uid_set_node_t* next;
bt_uid_traffic_t data;
} uid_set_node_t;
typedef struct uid_set_t {
- std::mutex lock;
uid_set_node_t* head;
} uid_set_t;
@@ -43,7 +44,7 @@
}
void uid_set_destroy(uid_set_t* set) {
- std::unique_lock<std::mutex> lock(set->lock);
+ std::unique_lock<std::mutex> guard(set_lock);
uid_set_node_t* node = set->head;
while (node) {
uid_set_node_t* temp = node;
@@ -74,7 +75,7 @@
void uid_set_add_tx(uid_set_t* set, int32_t app_uid, uint64_t bytes) {
if (app_uid == -1 || bytes == 0) return;
- std::unique_lock<std::mutex> lock(set->lock);
+ std::unique_lock<std::mutex> guard(set_lock);
uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid);
node->data.tx_bytes += bytes;
}
@@ -82,13 +83,13 @@
void uid_set_add_rx(uid_set_t* set, int32_t app_uid, uint64_t bytes) {
if (app_uid == -1 || bytes == 0) return;
- std::unique_lock<std::mutex> lock(set->lock);
+ std::unique_lock<std::mutex> guard(set_lock);
uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid);
node->data.rx_bytes += bytes;
}
bt_uid_traffic_t* uid_set_read_and_clear(uid_set_t* set) {
- std::unique_lock<std::mutex> lock(set->lock);
+ std::unique_lock<std::mutex> guard(set_lock);
// Find the length
size_t len = 0;
diff --git a/btif/src/btif_util.cc b/btif/src/btif_util.cc
index 932c55a..26d84fd 100644
--- a/btif/src/btif_util.cc
+++ b/btif/src/btif_util.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 2009-2016 Broadcom Corporation
+ * Copyright 2009-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,29 +56,6 @@
* Constants & Macros
******************************************************************************/
#define ISDIGIT(a) (((a) >= '0') && ((a) <= '9'))
-#define ISXDIGIT(a) \
- ((((a) >= '0') && ((a) <= '9')) || (((a) >= 'A') && ((a) <= 'F')) || \
- (((a) >= 'a') && ((a) <= 'f')))
-
-/*******************************************************************************
- * Local type definitions
- ******************************************************************************/
-
-/*******************************************************************************
- * Static variables
- ******************************************************************************/
-
-/*******************************************************************************
- * Static functions
- ******************************************************************************/
-
-/*******************************************************************************
- * Externs
- ******************************************************************************/
-
-/*******************************************************************************
- * Functions
- ******************************************************************************/
/*****************************************************************************
* Logging helper functions
@@ -100,64 +77,6 @@
dev_class[0] = (uint8_t)(cod >> 16);
}
-static const uint8_t sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB};
-
-void uuid16_to_uuid128(uint16_t uuid16, bt_uuid_t* uuid128) {
- uint16_t uuid16_bo;
- memset(uuid128, 0, sizeof(bt_uuid_t));
-
- memcpy(uuid128->uu, sdp_base_uuid, MAX_UUID_SIZE);
- uuid16_bo = ntohs(uuid16);
- memcpy(uuid128->uu + 2, &uuid16_bo, sizeof(uint16_t));
-}
-
-bool string_to_uuid(const char* str, bt_uuid_t* p_uuid) {
- CHECK(p_uuid);
- if (str == NULL) return false;
-
- uint32_t uuid0, uuid4;
- uint16_t uuid1, uuid2, uuid3, uuid5;
-
- int rc = sscanf(str, "%08x-%04hx-%04hx-%04hx-%08x%04hx", &uuid0, &uuid1,
- &uuid2, &uuid3, &uuid4, &uuid5);
- if (rc != 6) return false;
-
- uuid0 = htonl(uuid0);
- uuid1 = htons(uuid1);
- uuid2 = htons(uuid2);
- uuid3 = htons(uuid3);
- uuid4 = htonl(uuid4);
- uuid5 = htons(uuid5);
-
- memcpy(&(p_uuid->uu[0]), &uuid0, 4);
- memcpy(&(p_uuid->uu[4]), &uuid1, 2);
- memcpy(&(p_uuid->uu[6]), &uuid2, 2);
- memcpy(&(p_uuid->uu[8]), &uuid3, 2);
- memcpy(&(p_uuid->uu[10]), &uuid4, 4);
- memcpy(&(p_uuid->uu[14]), &uuid5, 2);
-
- return true;
-}
-
-void uuid_to_string_legacy(bt_uuid_t* p_uuid, char* str, size_t str_len) {
- uint32_t uuid0, uuid4;
- uint16_t uuid1, uuid2, uuid3, uuid5;
-
- memcpy(&uuid0, &(p_uuid->uu[0]), 4);
- memcpy(&uuid1, &(p_uuid->uu[4]), 2);
- memcpy(&uuid2, &(p_uuid->uu[6]), 2);
- memcpy(&uuid3, &(p_uuid->uu[8]), 2);
- memcpy(&uuid4, &(p_uuid->uu[10]), 4);
- memcpy(&uuid5, &(p_uuid->uu[14]), 2);
-
- snprintf(str, str_len, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", ntohl(uuid0),
- ntohs(uuid1), ntohs(uuid2), ntohs(uuid3), ntohl(uuid4),
- ntohs(uuid5));
- return;
-}
-
/*****************************************************************************
* Function ascii_2_hex
*
@@ -291,6 +210,7 @@
CASE_RETURN_STR(BTA_AG_AT_BCS_EVT)
CASE_RETURN_STR(BTA_AG_AT_BIND_EVT)
CASE_RETURN_STR(BTA_AG_AT_BIEV_EVT)
+ CASE_RETURN_STR(BTA_AG_AT_BIA_EVT)
default:
return "UNKNOWN MSG ID";
@@ -349,18 +269,6 @@
}
}
-const char* dump_hf_conn_state(uint16_t event) {
- switch (event) {
- CASE_RETURN_STR(BTHF_CONNECTION_STATE_DISCONNECTED)
- CASE_RETURN_STR(BTHF_CONNECTION_STATE_CONNECTING)
- CASE_RETURN_STR(BTHF_CONNECTION_STATE_CONNECTED)
- CASE_RETURN_STR(BTHF_CONNECTION_STATE_SLC_CONNECTED)
- CASE_RETURN_STR(BTHF_CONNECTION_STATE_DISCONNECTING)
- default:
- return "UNKNOWN MSG ID";
- }
-}
-
const char* dump_hd_event(uint16_t event) {
switch (event) {
CASE_RETURN_STR(BTA_HD_ENABLE_EVT)
@@ -381,20 +289,6 @@
}
}
-const char* dump_hf_call_state(bthf_call_state_t call_state) {
- switch (call_state) {
- CASE_RETURN_STR(BTHF_CALL_STATE_IDLE)
- CASE_RETURN_STR(BTHF_CALL_STATE_HELD)
- CASE_RETURN_STR(BTHF_CALL_STATE_DIALING)
- CASE_RETURN_STR(BTHF_CALL_STATE_ALERTING)
- CASE_RETURN_STR(BTHF_CALL_STATE_INCOMING)
- CASE_RETURN_STR(BTHF_CALL_STATE_WAITING)
- CASE_RETURN_STR(BTHF_CALL_STATE_ACTIVE)
- default:
- return "UNKNOWN CALL STATE";
- }
-}
-
const char* dump_thread_evt(bt_cb_thread_evt evt) {
switch (evt) {
CASE_RETURN_STR(ASSOCIATE_JVM)
@@ -405,17 +299,6 @@
}
}
-const char* dump_hf_audio_state(uint16_t event) {
- switch (event) {
- CASE_RETURN_STR(BTHF_AUDIO_STATE_DISCONNECTED)
- CASE_RETURN_STR(BTHF_AUDIO_STATE_CONNECTING)
- CASE_RETURN_STR(BTHF_AUDIO_STATE_CONNECTED)
- CASE_RETURN_STR(BTHF_AUDIO_STATE_DISCONNECTING)
- default:
- return "UNKNOWN MSG ID";
- }
-}
-
const char* dump_av_conn_state(uint16_t event) {
switch (event) {
CASE_RETURN_STR(BTAV_CONNECTION_STATE_DISCONNECTED)
diff --git a/btif/src/stack_manager.cc b/btif/src/stack_manager.cc
index eb0ac22..e37db87 100644
--- a/btif/src/stack_manager.cc
+++ b/btif/src/stack_manager.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -194,8 +194,6 @@
// Synchronous function to clean up the stack
static void event_clean_up_stack(void* context) {
- future_t* local_hack_future;
-
if (!stack_is_initialized) {
LOG_INFO(LOG_TAG, "%s found the stack already in a clean state", __func__);
goto cleanup;
@@ -204,8 +202,6 @@
ensure_stack_is_not_running();
LOG_INFO(LOG_TAG, "%s is cleaning up the stack", __func__);
- local_hack_future = future_new();
- hack_future = local_hack_future;
stack_is_initialized = false;
btif_cleanup_bluetooth();
diff --git a/btif/test/btif_profile_queue_test.cc b/btif/test/btif_profile_queue_test.cc
index 79a283f..f7bce86 100644
--- a/btif/test/btif_profile_queue_test.cc
+++ b/btif/test/btif_profile_queue_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 Google, Inc.
+ * Copyright 2017 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,27 +17,28 @@
******************************************************************************/
#include <gtest/gtest.h>
+#include <base/bind.h>
+
+#include "base/location.h"
#include "btif/include/btif_profile_queue.h"
#include "stack_manager.h"
#include "types/raw_address.h"
-static bool sStackRunning;
-
-bool get_stack_is_running(void) { return sStackRunning; }
-
-static stack_manager_t sStackManager = {nullptr, nullptr, nullptr, nullptr,
- get_stack_is_running};
-
-const stack_manager_t* stack_manager_get_interface() { return &sStackManager; }
-
typedef void(tBTIF_CBACK)(uint16_t event, char* p_param);
typedef void(tBTIF_COPY_CBACK)(uint16_t event, char* p_dest, char* p_src);
-bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event,
- char* p_params, int param_len,
- tBTIF_COPY_CBACK* p_copy_cback) {
- p_cback(event, p_params);
+
+// NOTE: Local re-implementation of functions to avoid thread context switching
+static bool sStackRunning;
+bool get_stack_is_running(void) { return sStackRunning; }
+static stack_manager_t sStackManager = {nullptr, nullptr, nullptr, nullptr,
+ get_stack_is_running};
+const stack_manager_t* stack_manager_get_interface() { return &sStackManager; }
+bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ task.Run();
return BT_STATUS_SUCCESS;
}
+bool is_on_jni_thread() { return true; }
enum ResultType {
NOT_SET = 0,
@@ -130,14 +131,30 @@
sResult = NOT_SET;
btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
EXPECT_EQ(sResult, NOT_SET);
+ // Third item for same UUID1, but different address ADDR2
sResult = NOT_SET;
+ btif_queue_connect(kTestUuid1, &kTestAddr2, test_connect_cb);
+ EXPECT_EQ(sResult, NOT_SET);
+ // Fourth item for same UUID2, but different address ADDR2
+ sResult = NOT_SET;
+ btif_queue_connect(kTestUuid2, &kTestAddr2, test_connect_cb);
+ EXPECT_EQ(sResult, NOT_SET);
// Connect next doesn't work
+ sResult = NOT_SET;
btif_queue_connect_next();
EXPECT_EQ(sResult, NOT_SET);
- // Advance moves queue to execute next item
+ // Advance moves queue to execute second item
sResult = NOT_SET;
btif_queue_advance();
EXPECT_EQ(sResult, UUID2_ADDR1);
+ // Advance moves queue to execute third item
+ sResult = NOT_SET;
+ btif_queue_advance();
+ EXPECT_EQ(sResult, UUID1_ADDR2);
+ // Advance moves queue to execute fourth item
+ sResult = NOT_SET;
+ btif_queue_advance();
+ EXPECT_EQ(sResult, UUID2_ADDR2);
}
TEST_F(BtifProfileQueueTest, test_cleanup_first_allow_second) {
diff --git a/btif/test/btif_state_machine_test.cc b/btif/test/btif_state_machine_test.cc
new file mode 100644
index 0000000..d413a4a
--- /dev/null
+++ b/btif/test/btif_state_machine_test.cc
@@ -0,0 +1,261 @@
+/******************************************************************************
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "btif/include/btif_state_machine.h"
+
+namespace {
+static constexpr uint32_t kInvalidEvent = 0xffffffff;
+static constexpr uint32_t kEventZero = 0;
+static constexpr uint32_t kEventOne = 1;
+static constexpr uint32_t kEventTwo = 2;
+
+static char dataZero = 0;
+static char dataOne = 1;
+static char dataTwo = 2;
+} // namespace
+
+class BtifStateMachineImpl : public BtifStateMachine {
+ public:
+ enum {
+ kStateZero,
+ kStateOne,
+ kStateTwo,
+ };
+
+ class StateZero : public State {
+ public:
+ StateZero(BtifStateMachine& sm)
+ : State(sm, kStateZero),
+ on_enter_(false),
+ on_exit_(false),
+ event_(kInvalidEvent),
+ data_(nullptr) {}
+ void OnEnter() override {
+ on_enter_ = true;
+ on_exit_ = false;
+ }
+ void OnExit() override {
+ on_exit_ = true;
+ on_enter_ = false;
+ }
+ bool ProcessEvent(uint32_t event, void* p_data) override {
+ event_ = event;
+ data_ = p_data;
+ TransitionTo(kStateOne);
+ return true;
+ }
+
+ bool on_enter_;
+ bool on_exit_;
+ uint32_t event_;
+ void* data_;
+ };
+
+ class StateOne : public State {
+ public:
+ StateOne(BtifStateMachine& sm)
+ : State(sm, kStateOne),
+ on_enter_(false),
+ on_exit_(false),
+ event_(kInvalidEvent),
+ data_(nullptr) {}
+ void OnEnter() override {
+ on_enter_ = true;
+ on_exit_ = false;
+ }
+ void OnExit() override {
+ on_exit_ = true;
+ on_enter_ = false;
+ }
+ bool ProcessEvent(uint32_t event, void* p_data) override {
+ event_ = event;
+ data_ = p_data;
+ TransitionTo(kStateTwo);
+ return true;
+ }
+
+ bool on_enter_;
+ bool on_exit_;
+ uint32_t event_;
+ void* data_;
+ };
+
+ class StateTwo : public State {
+ public:
+ StateTwo(BtifStateMachine& sm)
+ : State(sm, kStateTwo),
+ on_enter_(false),
+ on_exit_(false),
+ event_(kInvalidEvent),
+ data_(nullptr) {}
+ void OnEnter() override {
+ on_enter_ = true;
+ on_exit_ = false;
+ }
+ void OnExit() override {
+ on_exit_ = true;
+ on_enter_ = false;
+ }
+ bool ProcessEvent(uint32_t event, void* p_data) override {
+ event_ = event;
+ data_ = p_data;
+ TransitionTo(kStateZero);
+ return true;
+ }
+
+ bool on_enter_;
+ bool on_exit_;
+ uint32_t event_;
+ void* data_;
+ };
+
+ BtifStateMachineImpl() {
+ state_zero_ = new StateZero(*this);
+ state_one_ = new StateOne(*this);
+ state_two_ = new StateTwo(*this);
+
+ AddState(state_zero_);
+ AddState(state_one_);
+ AddState(state_two_);
+ SetInitialState(state_zero_);
+ }
+
+ StateZero* state_zero_;
+ StateOne* state_one_;
+ StateTwo* state_two_;
+};
+
+class BtifStateMachineTest : public ::testing::Test {
+ protected:
+ BtifStateMachineTest() {}
+
+ void SetUp() override { sm_.Start(); }
+
+ void TearDown() override { sm_.Quit(); }
+
+ BtifStateMachineImpl sm_;
+};
+
+TEST_F(BtifStateMachineTest, test_initial_state) {
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+}
+
+TEST_F(BtifStateMachineTest, test_invalid_state) {
+ sm_.Quit();
+ ASSERT_EQ(sm_.kStateInvalid, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+ sm_.Start();
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+}
+
+TEST_F(BtifStateMachineTest, test_transition_to) {
+ // Initial state: StateZero
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+ ASSERT_TRUE(sm_.state_zero_->on_enter_);
+ ASSERT_FALSE(sm_.state_zero_->on_exit_);
+
+ // Transition to StateOne
+ ASSERT_FALSE(sm_.state_one_->on_enter_);
+ ASSERT_FALSE(sm_.state_one_->on_exit_);
+ sm_.TransitionTo(sm_.kStateOne);
+ ASSERT_EQ(sm_.kStateOne, sm_.StateId());
+ ASSERT_EQ(sm_.kStateZero, sm_.PreviousStateId());
+ ASSERT_TRUE(sm_.state_zero_->on_exit_);
+ ASSERT_TRUE(sm_.state_one_->on_enter_);
+ ASSERT_FALSE(sm_.state_one_->on_exit_);
+
+ // Transition to StateTwo
+ ASSERT_FALSE(sm_.state_two_->on_enter_);
+ ASSERT_FALSE(sm_.state_two_->on_exit_);
+ sm_.TransitionTo(sm_.kStateTwo);
+ ASSERT_EQ(sm_.kStateTwo, sm_.StateId());
+ ASSERT_EQ(sm_.kStateOne, sm_.PreviousStateId());
+ ASSERT_TRUE(sm_.state_one_->on_exit_);
+ ASSERT_TRUE(sm_.state_two_->on_enter_);
+ ASSERT_FALSE(sm_.state_two_->on_exit_);
+}
+
+TEST_F(BtifStateMachineTest, test_process_event) {
+ // Initial state: StateZero
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+ ASSERT_TRUE(sm_.state_zero_->on_enter_);
+ ASSERT_FALSE(sm_.state_zero_->on_exit_);
+ ASSERT_EQ(sm_.state_zero_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_zero_->data_, nullptr);
+
+ // Process an event and transition to StateOne
+ ASSERT_FALSE(sm_.state_one_->on_enter_);
+ ASSERT_FALSE(sm_.state_one_->on_exit_);
+ ASSERT_EQ(sm_.state_one_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_one_->data_, nullptr);
+ ASSERT_TRUE(sm_.ProcessEvent(kEventZero, &dataZero));
+ ASSERT_EQ(sm_.kStateOne, sm_.StateId());
+ ASSERT_EQ(sm_.kStateZero, sm_.PreviousStateId());
+ // Check StateZero
+ ASSERT_EQ(sm_.state_zero_->event_, kEventZero);
+ ASSERT_EQ(sm_.state_zero_->data_, &dataZero);
+ ASSERT_TRUE(sm_.state_zero_->on_exit_);
+ // Check StateOne
+ ASSERT_TRUE(sm_.state_one_->on_enter_);
+ ASSERT_FALSE(sm_.state_one_->on_exit_);
+ ASSERT_EQ(sm_.state_one_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_one_->data_, nullptr);
+
+ // Process an event and transition to StateTwo
+ ASSERT_FALSE(sm_.state_two_->on_enter_);
+ ASSERT_FALSE(sm_.state_two_->on_exit_);
+ ASSERT_EQ(sm_.state_two_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_two_->data_, nullptr);
+ ASSERT_TRUE(sm_.ProcessEvent(kEventOne, &dataOne));
+ ASSERT_EQ(sm_.kStateTwo, sm_.StateId());
+ ASSERT_EQ(sm_.kStateOne, sm_.PreviousStateId());
+ // Check StateOne
+ ASSERT_EQ(sm_.state_one_->event_, kEventOne);
+ ASSERT_EQ(sm_.state_one_->data_, &dataOne);
+ ASSERT_TRUE(sm_.state_one_->on_exit_);
+ // Check StateTwo
+ ASSERT_TRUE(sm_.state_two_->on_enter_);
+ ASSERT_FALSE(sm_.state_two_->on_exit_);
+ ASSERT_EQ(sm_.state_two_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_two_->data_, nullptr);
+
+ // Process an event and transition to StateZero
+ // NOTE: StateZero was exited before and has local state
+ ASSERT_FALSE(sm_.state_zero_->on_enter_);
+ ASSERT_TRUE(sm_.state_zero_->on_exit_); // NOTE: already exited before
+ ASSERT_EQ(sm_.state_zero_->event_, kEventZero); // NOTE: state from before
+ ASSERT_EQ(sm_.state_zero_->data_, &dataZero); // NOTE: state from before
+ ASSERT_TRUE(sm_.ProcessEvent(kEventTwo, &dataTwo));
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateTwo, sm_.PreviousStateId());
+ // Check StateTwo
+ ASSERT_EQ(sm_.state_two_->event_, kEventTwo);
+ ASSERT_EQ(sm_.state_two_->data_, &dataTwo);
+ ASSERT_TRUE(sm_.state_two_->on_exit_);
+ // Check StateZero
+ ASSERT_TRUE(sm_.state_zero_->on_enter_);
+ ASSERT_FALSE(sm_.state_zero_->on_exit_);
+ ASSERT_EQ(sm_.state_zero_->event_, kEventZero); // NOTE: state from before
+ ASSERT_EQ(sm_.state_zero_->data_, &dataZero); // NOTE: state from before
+}
diff --git a/btif/test/btif_storage_test.cc b/btif/test/btif_storage_test.cc
index 988e23f..f98776d 100644
--- a/btif/test/btif_storage_test.cc
+++ b/btif/test/btif_storage_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,25 +21,7 @@
#include "btif/include/btif_storage.h"
#include "btif/include/btif_util.h"
-TEST(BtifStorageTest, test_string_to_uuid) {
- const char* s1 = "e39c6285-867f-4b1d-9db0-35fbd9aebf22";
- const uint8_t u1[] = {0xe3, 0x9c, 0x62, 0x85, 0x86, 0x7f, 0x4b, 0x1d,
- 0x9d, 0xb0, 0x35, 0xfb, 0xd9, 0xae, 0xbf, 0x22};
-
- bt_uuid_t uuid;
- memset(&uuid, 0, sizeof(uuid));
- EXPECT_FALSE(memcmp(&uuid, u1, sizeof(u1)) == 0);
-
- bool rc = string_to_uuid(s1, &uuid);
- EXPECT_TRUE(rc);
- EXPECT_TRUE(memcmp(&uuid, u1, sizeof(u1)) == 0);
-}
-
-TEST(BtifStorageTest, test_string_to_uuid_invalid) {
- bt_uuid_t uuid;
- bool rc = string_to_uuid("This is not a UUID", &uuid);
- EXPECT_FALSE(rc);
-}
+using bluetooth::Uuid;
TEST(BtifStorageTest, test_uuid_split_multiple) {
const char* s1 =
@@ -50,11 +32,11 @@
const uint8_t u2[] = {0xe3, 0x9c, 0x62, 0x85, 0x86, 0x7f, 0x4b, 0x1d,
0x9d, 0xb0, 0x35, 0xfb, 0xd9, 0xae, 0xbf, 0x23};
- bt_uuid_t uuids[2];
+ Uuid uuids[2];
size_t num_uuids = btif_split_uuids_string(s1, uuids, 2);
EXPECT_EQ(num_uuids, 2u);
- EXPECT_TRUE(memcmp(&uuids[0], u1, sizeof(u1)) == 0);
- EXPECT_TRUE(memcmp(&uuids[1], u2, sizeof(u2)) == 0);
+ EXPECT_TRUE(memcmp(uuids[0].To128BitBE().data(), u1, sizeof(u1)) == 0);
+ EXPECT_TRUE(memcmp(uuids[1].To128BitBE().data(), u2, sizeof(u2)) == 0);
}
TEST(BtifStorageTest, test_uuid_split_partial) {
@@ -62,7 +44,7 @@
"e39c6285-867f-4b1d-9db0-35fbd9aebf22 "
"e39c6285-867f-4b1d-9db0-35fbd9aebf23";
- bt_uuid_t uuids[2];
+ Uuid uuids[2];
size_t num_uuids = btif_split_uuids_string(s1, uuids, 1);
EXPECT_EQ(num_uuids, 1u);
}
diff --git a/build/Android.bp b/build/Android.bp
index fc6eae8..b8abb0f 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -15,18 +15,28 @@
}
fluoride_defaults {
- name: "fluoride_types_defaults",
+ name: "libchrome_support_defaults",
+ shared_libs: ["libchrome"],
cflags: [
- "-DEXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
- "-fvisibility=hidden",
"-Wall",
"-Wextra",
"-Werror",
+ ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+fluoride_defaults {
+ name: "fluoride_types_defaults",
+ defaults: ["libchrome_support_defaults"],
+ cflags: [
+ "-DEXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
+ "-fvisibility=hidden",
// struct BT_HDR is defined as a variable-size header in a struct.
"-Wno-gnu-variable-sized-type-not-at-end",
- // needed because of the way the struct typedef is done in osi/include
- // header files. This issue can be obsoleted by switching to C11 or C++.
- "-Wno-typedef-redefinition",
// there are too many unused parameters in all the code.
"-Wno-unused-parameter",
"-DLOG_NDEBUG=1",
@@ -38,17 +48,15 @@
debuggable: {
cflags: [
"-DBLUEDROID_DEBUG",
- "-DDCHECK_ALWAYS_ON"
],
},
},
- shared_libs: [ "libchrome" ]
- // Setup Bluetooth local make variables for handling configuration
}
fluoride_defaults {
name: "fluoride_defaults",
defaults: ["fluoride_types_defaults"],
+ header_libs: ["libbluetooth_headers"],
static_libs: [
"libbluetooth-types",
],
diff --git a/build/BUILD.gn b/build/BUILD.gn
index af7d5d8..f09a274 100644
--- a/build/BUILD.gn
+++ b/build/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
config("default_include_dirs") {
include_dirs = [
- "//third_party/libhardware/include/",
+ "//include/",
"//types/",
]
}
@@ -28,6 +28,7 @@
#TODO(jpawlowski): uncomment once we have no warnings on linux build
# "-Wall",
# "-Werror",
+ "-Wno-gnu-variable-sized-type-not-at-end",
"-g",
"-O0",
"-fpic",
@@ -54,11 +55,6 @@
"EXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
"KERNEL_MISSING_CLOCK_BOOTTIME_ALARM=TRUE",
- # This is a macro to that can be used by android hardware/libhardware
- # to not include dependencies on core project. This is a temporary
- # workaround until we get rid of dependency on hardware.
- "_HW_DONT_INCLUDE_CORE_=1",
-
# This is a macro to that can be used by source code to detect if the
# current build is done by GN or via Android.mk. This is a temporary
# workaround until we can remove all Android-specific dependencies.
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 148230b..765b21e 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/build/fluoride.go b/build/fluoride.go
index 7b9ac97..6a511a5 100644
--- a/build/fluoride.go
+++ b/build/fluoride.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/build/secondary/third_party/aac/BUILD.gn b/build/secondary/third_party/aac/BUILD.gn
index 183e2a2..d9e79a7 100644
--- a/build/secondary/third_party/aac/BUILD.gn
+++ b/build/secondary/third_party/aac/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2017 Google, Inc.
+# Copyright 2017 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/build/secondary/third_party/googletest/BUILD.gn b/build/secondary/third_party/googletest/BUILD.gn
index 0122adc..54c53d7 100644
--- a/build/secondary/third_party/googletest/BUILD.gn
+++ b/build/secondary/third_party/googletest/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2016 Google, Inc.
+# Copyright 2016 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/build/secondary/third_party/libchrome/BUILD.gn b/build/secondary/third_party/libchrome/BUILD.gn
index d0d94b2..c84b293 100644
--- a/build/secondary/third_party/libchrome/BUILD.gn
+++ b/build/secondary/third_party/libchrome/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/build/secondary/third_party/libldac/BUILD.gn b/build/secondary/third_party/libldac/BUILD.gn
index faf85a2..23b191d 100644
--- a/build/secondary/third_party/libldac/BUILD.gn
+++ b/build/secondary/third_party/libldac/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2017 Google, Inc.
+# Copyright 2017 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/build/secondary/third_party/tinyxml2/BUILD.gn b/build/secondary/third_party/tinyxml2/BUILD.gn
index 335960b..aeb66a1 100644
--- a/build/secondary/third_party/tinyxml2/BUILD.gn
+++ b/build/secondary/third_party/tinyxml2/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/build/toolchain/clang/BUILD.gn b/build/toolchain/clang/BUILD.gn
index fcd6d56..ee86e27 100644
--- a/build/toolchain/clang/BUILD.gn
+++ b/build/toolchain/clang/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2016 Android Open Source Project
+# Copyright 2016 Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/build/toolchain/gcc/BUILD.gn b/build/toolchain/gcc/BUILD.gn
index 888b015..1c92d0a 100644
--- a/build/toolchain/gcc/BUILD.gn
+++ b/build/toolchain/gcc/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/conf/bt_stack.conf b/conf/bt_stack.conf
index f1557b1..d1e7756 100644
--- a/conf/bt_stack.conf
+++ b/conf/bt_stack.conf
@@ -50,6 +50,9 @@
# SMP Pair options (formatted as hex bytes) auth, io, ikey, rkey, ksize
#PTS_SmpOptions=0xD,0x4,0xf,0xf,0x10
+# PTS AVRCP Test mode
+#PTS_AvrcpTest=true
+
# SMP Certification Failure Cases
# Set any of the following SMP error values (from smp_api_types.h)
# to induce pairing failues for various PTS SMP test cases.
diff --git a/device/Android.bp b/device/Android.bp
index c113113..f72a16b 100644
--- a/device/Android.bp
+++ b/device/Android.bp
@@ -10,7 +10,7 @@
"system/bt",
"system/bt/btcore/include",
"system/bt/hci/include",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/stack/include",
],
srcs: [
diff --git a/device/AndroidTest.xml b/device/AndroidTest.xml
index 45a7e51..0960fb4 100644
--- a/device/AndroidTest.xml
+++ b/device/AndroidTest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/device/BUILD.gn b/device/BUILD.gn
index f93b70d..5de439d 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
"//",
"//btcore/include",
"//hci/include",
- "//include",
+ "//internal_include",
"//stack/include",
]
diff --git a/device/include/controller.h b/device/include/controller.h
index 135cdcd..c1fe337 100644
--- a/device/include/controller.h
+++ b/device/include/controller.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -72,6 +72,7 @@
uint16_t (*get_acl_packet_size_ble)(void);
uint16_t (*get_ble_default_data_packet_length)(void);
+ uint16_t (*get_ble_maximum_tx_data_length)(void);
uint16_t (*get_ble_maxium_advertising_data_length)(void);
uint8_t (*get_ble_number_of_supported_advertising_sets)(void);
diff --git a/device/include/esco_parameters.h b/device/include/esco_parameters.h
index f906c8d..b79948d 100644
--- a/device/include/esco_parameters.h
+++ b/device/include/esco_parameters.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Broadcom Corporation
+ * Copyright 2015 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/device/include/interop.h b/device/include/interop.h
index 96a3b9a..b31efc3 100644
--- a/device/include/interop.h
+++ b/device/include/interop.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -113,7 +113,7 @@
// |length| must be greater than 0 and less than RawAddress::kLength.
// As |interop_feature_t| is not exposed in the public API, feature must be a
// valid integer representing an option in the enum.
-void interop_database_add(const uint16_t feature, const RawAddress* addr,
+void interop_database_add(uint16_t feature, const RawAddress* addr,
size_t length);
// Clear the dynamic portion of the interoperability workaround database.
diff --git a/device/include/interop_database.h b/device/include/interop_database.h
index 38c3a24..ad1bb5a 100644
--- a/device/include/interop_database.h
+++ b/device/include/interop_database.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/device/src/controller.cc b/device/src/controller.cc
index 8e1d887..a07e54b 100644
--- a/device/src/controller.cc
+++ b/device/src/controller.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,6 +65,11 @@
static uint8_t ble_supported_states[BLE_SUPPORTED_STATES_SIZE];
static bt_device_features_t features_ble;
static uint16_t ble_suggested_default_data_length;
+static uint16_t ble_supported_max_tx_octets;
+static uint16_t ble_supported_max_tx_time;
+static uint16_t ble_supported_max_rx_octets;
+static uint16_t ble_supported_max_rx_time;
+
static uint16_t ble_maxium_advertising_data_length;
static uint8_t ble_number_of_supported_advertising_sets;
static uint8_t local_supported_codecs[MAX_LOCAL_SUPPORTED_CODECS_SIZE];
@@ -212,6 +217,12 @@
}
if (HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array)) {
+ response =
+ AWAIT_COMMAND(packet_factory->make_ble_read_maximum_data_length());
+ packet_parser->parse_ble_read_maximum_data_length_response(
+ response, &ble_supported_max_tx_octets, &ble_supported_max_tx_time,
+ &ble_supported_max_rx_octets, &ble_supported_max_rx_time);
+
response = AWAIT_COMMAND(
packet_factory->make_ble_read_suggested_default_data_length());
packet_parser->parse_ble_read_suggested_default_data_length_response(
@@ -448,6 +459,12 @@
return ble_suggested_default_data_length;
}
+static uint16_t get_ble_maximum_tx_data_length(void) {
+ CHECK(readable);
+ CHECK(ble_supported);
+ return ble_supported_max_tx_octets;
+}
+
static uint16_t get_ble_maxium_advertising_data_length(void) {
CHECK(readable);
CHECK(ble_supported);
@@ -540,6 +557,7 @@
get_acl_packet_size_classic,
get_acl_packet_size_ble,
get_ble_suggested_default_data_length,
+ get_ble_maximum_tx_data_length,
get_ble_maxium_advertising_data_length,
get_ble_number_of_supported_advertising_sets,
diff --git a/device/src/esco_parameters.cc b/device/src/esco_parameters.cc
index 80f5e76..7f550a1 100644
--- a/device/src/esco_parameters.cc
+++ b/device/src/esco_parameters.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Broadcom Corporation
+ * Copyright 2015 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/device/src/interop.cc b/device/src/interop.cc
index 7b1fe59..c2ed2a8 100644
--- a/device/src/interop.cc
+++ b/device/src/interop.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -76,7 +76,7 @@
return false;
}
-void interop_database_add(const uint16_t feature, const RawAddress* addr,
+void interop_database_add(uint16_t feature, const RawAddress* addr,
size_t length) {
CHECK(addr);
CHECK(length > 0);
diff --git a/device/test/interop_test.cc b/device/test/interop_test.cc
index e82a3b5..71cc8cb 100644
--- a/device/test/interop_test.cc
+++ b/device/test/interop_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/doc/style_guide.md b/doc/style_guide.md
index 8490fd2..5fc786e 100644
--- a/doc/style_guide.md
+++ b/doc/style_guide.md
@@ -235,7 +235,7 @@
```
/******************************************************************************
*
- * Copyright (C) <year> <owner>
+ * Copyright <year> <owner>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/Android.bp b/embdrv/Android.bp
deleted file mode 100644
index 7c6328e..0000000
--- a/embdrv/Android.bp
+++ /dev/null
@@ -1,3 +0,0 @@
-subdirs = [
- "sbc",
-]
diff --git a/embdrv/g722/Android.bp b/embdrv/g722/Android.bp
new file mode 100644
index 0000000..cc635d8
--- /dev/null
+++ b/embdrv/g722/Android.bp
@@ -0,0 +1,12 @@
+
+cc_library_static {
+ name: "libg722codec",
+ defaults: ["fluoride_defaults"],
+ cflags: [
+ "-DG722_SUPPORT_MALLOC"
+ ],
+ srcs: [
+ "g722_decode.cc",
+ "g722_encode.cc",
+ ],
+}
\ No newline at end of file
diff --git a/embdrv/g722/g722_decode.cc b/embdrv/g722/g722_decode.cc
new file mode 100644
index 0000000..4d812ac
--- /dev/null
+++ b/embdrv/g722/g722_decode.cc
@@ -0,0 +1,422 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g722_decode.c - The ITU G.722 codec, decode part.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ * Despite my general liking of the GPL, I place my own contributions
+ * to this code in the public domain for the benefit of all mankind -
+ * even the slimy ones who might try to proprietize my work and use it
+ * to my detriment.
+ *
+ * Based in part on a single channel G.722 codec which is:
+ *
+ * Copyright (c) CMU 1993
+ * Computer Science, Speech Group
+ * Chengxiang Lu and Alex Hauptmann
+ *
+ * $Id: g722_decode.c 194722 2009-05-15 17:59:08Z russell $
+ */
+
+/*! \file */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include "g722_typedefs.h"
+#include "g722_enc_dec.h"
+
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+#if !defined(TRUE)
+#define TRUE (!FALSE)
+#endif
+
+#define PACKED_INPUT (0)
+#define BITS_PER_SAMPLE (8)
+
+#ifndef BUILD_FEATURE_G722_USE_INTRINSIC_SAT
+static __inline int16_t __ssat16(int32_t amp)
+{
+ int16_t amp16;
+
+ /* Hopefully this is optimised for the common case - not clipping */
+ amp16 = (int16_t) amp;
+ if (amp == amp16)
+ return amp16;
+ if (amp > 0x7fff)
+ return 0x7fff;
+ return 0x8000;
+}
+/*- End of function --------------------------------------------------------*/
+#else
+static __inline int16_t __ssat16( int32_t val)
+{
+ register int32_t res;
+ __asm volatile (
+ "SSAT %0, #16, %1\n\t"
+ :"=r"(res)
+ :"r"(val)
+ :);
+ return (int16_t)res;
+}
+#endif
+
+/*- End of function --------------------------------------------------------*/
+
+static void block4(g722_band_t *band, int d);
+
+static void block4(g722_band_t *band, int d)
+{
+ int wd1;
+ int wd2;
+ int wd3;
+ int i;
+ int sg[7];
+ int ap1, ap2;
+ int sg0, sgi;
+ int sz;
+
+ /* Block 4, RECONS */
+ band->d[0] = d;
+ band->r[0] = __ssat16(band->s + d);
+
+ /* Block 4, PARREC */
+ band->p[0] = __ssat16(band->sz + d);
+
+ /* Block 4, UPPOL2 */
+ for (i = 0; i < 3; i++)
+ {
+ sg[i] = band->p[i] >> 15;
+ }
+ wd1 = __ssat16(band->a[1] << 2);
+
+ wd2 = (sg[0] == sg[1]) ? -wd1 : wd1;
+ if (wd2 > 32767)
+ wd2 = 32767;
+
+ ap2 = (sg[0] == sg[2]) ? 128 : -128;
+ ap2 += (wd2 >> 7);
+ ap2 += (band->a[2]*32512) >> 15;
+ if (ap2 > 12288)
+ ap2 = 12288;
+ else if (ap2 < -12288)
+ ap2 = -12288;
+ band->ap[2] = ap2;
+
+ /* Block 4, UPPOL1 */
+ sg[0] = band->p[0] >> 15;
+ sg[1] = band->p[1] >> 15;
+ wd1 = (sg[0] == sg[1]) ? 192 : -192;
+ wd2 = (band->a[1]*32640) >> 15;
+
+ ap1 = __ssat16(wd1 + wd2);
+ wd3 = __ssat16(15360 - band->ap[2]);
+ if (ap1 > wd3)
+ ap1 = wd3;
+ else if (ap1 < -wd3)
+ ap1 = -wd3;
+ band->ap[1] = ap1;
+
+ /* Block 4, UPZERO */
+ /* Block 4, FILTEZ */
+ wd1 = (d == 0) ? 0 : 128;
+
+ sg0 = sg[0] = d >> 15;
+ for (i = 1; i < 7; i++)
+ {
+ sgi = band->d[i] >> 15;
+ wd2 = (sgi == sg0) ? wd1 : -wd1;
+ wd3 = (band->b[i]*32640) >> 15;
+ band->bp[i] = __ssat16(wd2 + wd3);
+ }
+
+ /* Block 4, DELAYA */
+ sz = 0;
+ for (i = 6; i > 0; i--)
+ {
+ int bi;
+
+ band->d[i] = band->d[i - 1];
+ bi = band->b[i] = band->bp[i];
+ wd1 = __ssat16(band->d[i] + band->d[i]);
+ sz += (bi*wd1) >> 15;
+ }
+ band->sz = sz;
+
+ for (i = 2; i > 0; i--)
+ {
+ band->r[i] = band->r[i - 1];
+ band->p[i] = band->p[i - 1];
+ band->a[i] = band->ap[i];
+ }
+
+ /* Block 4, FILTEP */
+ wd1 = __ssat16(band->r[1] + band->r[1]);
+ wd1 = (band->a[1]*wd1) >> 15;
+ wd2 = __ssat16(band->r[2] + band->r[2]);
+ wd2 = (band->a[2]*wd2) >> 15;
+ band->sp = __ssat16(wd1 + wd2);
+
+ /* Block 4, PREDIC */
+ band->s = __ssat16(band->sp + band->sz);
+}
+/*- End of function --------------------------------------------------------*/
+
+g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, unsigned int rate, int options)
+{
+ if (s == NULL)
+ {
+#ifdef G722_SUPPORT_MALLOC
+ if ((s = (g722_decode_state_t *) malloc(sizeof(*s))) == NULL)
+#endif
+ return NULL;
+ }
+ memset(s, 0, sizeof(*s));
+ if (rate == 48000)
+ s->bits_per_sample = 6;
+ else if (rate == 56000)
+ s->bits_per_sample = 7;
+ else
+ s->bits_per_sample = 8;
+ s->dac_pcm = options & G722_FORMAT_DAC12;
+ s->band[0].det = 32;
+ s->band[1].det = 8;
+ return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+int g722_decode_release(g722_decode_state_t *s)
+{
+ free(s);
+ return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int16_t wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042 };
+static int16_t rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 };
+static int16_t ilb[32] =
+{
+ 2048, 2093, 2139, 2186, 2233, 2282, 2332,
+ 2383, 2435, 2489, 2543, 2599, 2656, 2714,
+ 2774, 2834, 2896, 2960, 3025, 3091, 3158,
+ 3228, 3298, 3371, 3444, 3520, 3597, 3676,
+ 3756, 3838, 3922, 4008
+};
+
+static int16_t wh[3] = {0, -214, 798};
+static int16_t rh2[4] = {2, 1, 2, 1};
+static int16_t qm2[4] = {-7408, -1616, 7408, 1616};
+static int16_t qm4[16] =
+{
+ 0, -20456, -12896, -8968,
+ -6288, -4240, -2584, -1200,
+ 20456, 12896, 8968, 6288,
+ 4240, 2584, 1200, 0
+};
+#if 0
+static const int qm5[32] =
+{
+ -280, -280, -23352, -17560,
+ -14120, -11664, -9752, -8184,
+ -6864, -5712, -4696, -3784,
+ -2960, -2208, -1520, -880,
+ 23352, 17560, 14120, 11664,
+ 9752, 8184, 6864, 5712,
+ 4696, 3784, 2960, 2208,
+ 1520, 880, 280, -280
+};
+#endif
+static int16_t qm6[64] =
+{
+ -136, -136, -136, -136,
+ -24808, -21904, -19008, -16704,
+ -14984, -13512, -12280, -11192,
+ -10232, -9360, -8576, -7856,
+ -7192, -6576, -6000, -5456,
+ -4944, -4464, -4008, -3576,
+ -3168, -2776, -2400, -2032,
+ -1688, -1360, -1040, -728,
+ 24808, 21904, 19008, 16704,
+ 14984, 13512, 12280, 11192,
+ 10232, 9360, 8576, 7856,
+ 7192, 6576, 6000, 5456,
+ 4944, 4464, 4008, 3576,
+ 3168, 2776, 2400, 2032,
+ 1688, 1360, 1040, 728,
+ 432, 136, -432, -136
+};
+static int16_t qmf_coeffs_even[12] =
+{
+ 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11,
+};
+static int16_t qmf_coeffs_odd[12] =
+{
+ -11, 53, -156, 362, -805, 3876, 951, -210, 32, 12, -11, 3
+};
+
+uint32_t g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len, uint16_t gain)
+{
+
+ int dlowt;
+ int rlow;
+ int ihigh;
+ int dhigh;
+ int rhigh;
+ int xout1;
+ int xout2;
+ int wd1;
+ int wd2;
+ int wd3;
+ int code;
+ uint32_t outlen;
+ int i;
+ int j;
+
+ outlen = 0;
+ rhigh = 0;
+
+ for (j = 0; j < len; )
+ {
+#if PACKED_INPUT == 1
+ /* Unpack the code bits */
+ if (s->in_bits < s->bits_per_sample)
+ {
+ s->in_buffer |= (g722_data[j++] << s->in_bits);
+ s->in_bits += 8;
+ }
+ code = s->in_buffer & ((1 << s->bits_per_sample) - 1);
+ s->in_buffer >>= s->bits_per_sample;
+ s->in_bits -= s->bits_per_sample;
+#else
+ code = g722_data[j++];
+#endif
+
+#if BITS_PER_SAMPLE == 8
+ wd1 = code & 0x3F;
+ ihigh = (code >> 6) & 0x03;
+ wd2 = qm6[wd1];
+ wd1 >>= 2;
+#elif BITS_PER_SAMPLE == 7
+ wd1 = code & 0x1F;
+ ihigh = (code >> 5) & 0x03;
+ wd2 = qm5[wd1];
+ wd1 >>= 1;
+#elif BITS_PER_SAMPLE == 6
+ wd1 = code & 0x0F;
+ ihigh = (code >> 4) & 0x03;
+ wd2 = qm4[wd1];
+#endif
+ /* Block 5L, LOW BAND INVQBL */
+ wd2 = (s->band[0].det*wd2) >> 15;
+ /* Block 5L, RECONS */
+ rlow = s->band[0].s + wd2;
+ /* Block 6L, LIMIT */
+
+ // ANDREA
+ // rlow=ssat(rlow,2<<14)
+ if (rlow > 16383)
+ {
+ rlow = 16383;
+ }
+ else if (rlow < -16384)
+ {
+ rlow = -16384;
+ }
+
+ /* Block 2L, INVQAL */
+ wd2 = qm4[wd1];
+ dlowt = (s->band[0].det*wd2) >> 15;
+
+ /* Block 3L, LOGSCL */
+ wd2 = rl42[wd1];
+ wd1 = (s->band[0].nb*127) >> 7;
+ wd1 += wl[wd2];
+ if (wd1 < 0)
+ {
+ wd1 = 0;
+ }
+ else if (wd1 > 18432)
+ {
+ wd1 = 18432;
+ }
+ s->band[0].nb = wd1;
+
+ /* Block 3L, SCALEL */
+ wd1 = (s->band[0].nb >> 6) & 31;
+ wd2 = 8 - (s->band[0].nb >> 11);
+ wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2);
+ s->band[0].det = wd3 << 2;
+
+ block4(&s->band[0], dlowt);
+
+ /* Block 2H, INVQAH */
+ wd2 = qm2[ihigh];
+ dhigh = (s->band[1].det*wd2) >> 15;
+ /* Block 5H, RECONS */
+ rhigh = dhigh + s->band[1].s;
+ /* Block 6H, LIMIT */
+
+ // ANDREA
+ // rhigh=ssat(rhigh,2<<14)
+
+ if (rhigh > 16383)
+ rhigh = 16383;
+ else if (rhigh < -16384)
+ rhigh = -16384;
+
+ /* Block 2H, INVQAH */
+ wd2 = rh2[ihigh];
+ wd1 = (s->band[1].nb*127) >> 7;
+ wd1 += wh[wd2];
+ if (wd1 < 0)
+ wd1 = 0;
+ else if (wd1 > 22528)
+ wd1 = 22528;
+ s->band[1].nb = wd1;
+
+ /* Block 3H, SCALEH */
+ wd1 = (s->band[1].nb >> 6) & 31;
+ wd2 = 10 - (s->band[1].nb >> 11);
+ wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2);
+ s->band[1].det = wd3 << 2;
+
+ block4(&s->band[1], dhigh);
+
+ /* Apply the receive QMF */
+ for (i = 0; i < 22; i++)
+ s->x[i] = s->x[i + 2];
+ s->x[22] = rlow + rhigh;
+ s->x[23] = rlow - rhigh;
+
+ // we should get PERF numbers for the following loop
+ xout1 = 0;
+ xout2 = 0;
+ for (i = 0; i < 12; i++)
+ {
+ xout2 += s->x[2*i] * qmf_coeffs_even[i];
+ xout1 += s->x[2*i+1] * qmf_coeffs_odd[i];
+ }
+ xout1 = NLDECOMPRESS_PREPROCESS_SAMPLE_WITH_GAIN((int16_t) __ssat16(xout1 >> 11), gain);
+ xout2 = NLDECOMPRESS_PREPROCESS_SAMPLE_WITH_GAIN((int16_t) __ssat16(xout2 >> 11), gain);
+ if (s->dac_pcm)
+ {
+ amp[outlen++] = ((int16_t) (xout1 >> 4) + 2048);
+ amp[outlen++] = ((int16_t) (xout2 >> 4) + 2048);
+ }
+ else
+ {
+ amp[outlen++] = xout1;
+ amp[outlen++] = xout2;
+ }
+ }
+ return outlen;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
diff --git a/embdrv/g722/g722_enc_dec.h b/embdrv/g722/g722_enc_dec.h
new file mode 100644
index 0000000..f06cd20
--- /dev/null
+++ b/embdrv/g722/g722_enc_dec.h
@@ -0,0 +1,148 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g722.h - The ITU G.722 codec.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ * Despite my general liking of the GPL, I place my own contributions
+ * to this code in the public domain for the benefit of all mankind -
+ * even the slimy ones who might try to proprietize my work and use it
+ * to my detriment.
+ *
+ * Based on a single channel G.722 codec which is:
+ *
+ ***** Copyright (c) CMU 1993 *****
+ * Computer Science, Speech Group
+ * Chengxiang Lu and Alex Hauptmann
+ *
+ * $Id: g722.h 48959 2006-12-25 06:42:15Z rizzo $
+ */
+
+
+/*! \file */
+
+#if !defined(_G722_H_)
+#define _G722_H_
+
+/*! \page g722_page G.722 encoding and decoding
+\section g722_page_sec_1 What does it do?
+The G.722 module is a bit exact implementation of the ITU G.722 specification for all three
+specified bit rates - 64000bps, 56000bps and 48000bps. It passes the ITU tests.
+
+To allow fast and flexible interworking with narrow band telephony, the encoder and decoder
+support an option for the linear audio to be an 8k samples/second stream. In this mode the
+codec is considerably faster, and still fully compatible with wideband terminals using G.722.
+
+\section g722_page_sec_2 How does it work?
+???.
+*/
+
+/* Format DAC12 is added to decode directly into samples suitable for
+ a 12-bit DAC using offset binary representation. */
+
+enum
+{
+ G722_SAMPLE_RATE_8000 = 0x0001,
+ G722_PACKED = 0x0002,
+ G722_FORMAT_DAC12 = 0x0004,
+};
+
+#ifdef BUILD_FEATURE_DAC
+#define NLDECOMPRESS_APPLY_GAIN(s,g) (((s) * (int32_t)(g)) >> 16)
+// Equivalent to shift 16, add 0x8000, shift 4
+#define NLDECOMPRESS_APPLY_GAIN_CONVERTED_DAC(s,g) (uint16_t)((uint16_t)(((s) * (int32_t)(g)) >> 20) + 0x800)
+#else
+#define NLDECOMPRESS_APPLY_GAIN(s,g) (((int32_t)(s) * (int32_t)(g)) >> 16)
+#endif
+
+#ifdef BUILD_FEATURE_DAC
+#define NLDECOMPRESS_PREPROCESS_PCM_SAMPLE_WITH_GAIN(s,g) NLDECOMPRESS_APPLY_GAIN_CONVERTED_DAC((s),(g))
+#define NLDECOMPRESS_PREPROCESS_SAMPLE_WITH_GAIN(s,g) ((int16_t)NLDECOMPRESS_APPLY_GAIN((s),(g)))
+#else
+#define NLDECOMPRESS_PREPROCESS_PCM_SAMPLE_WITH_GAIN NLDECOMPRESS_PREPROCESS_SAMPLE_WITH_GAIN
+#define NLDECOMPRESS_PREPROCESS_SAMPLE_WITH_GAIN(s,g) ((int16_t)(NLDECOMPRESS_APPLY_GAIN((s),(g))))
+#endif
+
+typedef struct {
+ int s;
+ int sp;
+ int sz;
+ int r[3];
+ int a[3];
+ int ap[3];
+ int p[3];
+ int d[7];
+ int b[7];
+ int bp[7];
+ int nb;
+ int det;
+} g722_band_t;
+
+typedef struct
+{
+ /*! TRUE if the operating in the special ITU test mode, with the band split filters
+ disabled. */
+ int itu_test_mode;
+ /*! TRUE if the G.722 data is packed */
+ int packed;
+ /*! TRUE if encode from 8k samples/second */
+ int eight_k;
+ /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */
+ int bits_per_sample;
+
+ /*! Signal history for the QMF */
+ int x[24];
+
+ g722_band_t band[2];
+
+ unsigned int in_buffer;
+ int in_bits;
+ unsigned int out_buffer;
+ int out_bits;
+} g722_encode_state_t;
+
+typedef struct
+{
+ /*! TRUE if the operating in the special ITU test mode, with the band split filters
+ disabled. */
+ int itu_test_mode;
+ /*! TRUE if the G.722 data is packed */
+ int packed;
+ /*! TRUE if decode to 8k samples/second */
+ int eight_k;
+ /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */
+ int bits_per_sample;
+ /*! TRUE if offset binary for a 12-bit DAC */
+ int dac_pcm;
+
+ /*! Signal history for the QMF */
+ int x[24];
+
+ g722_band_t band[2];
+
+ unsigned int in_buffer;
+ int in_bits;
+ unsigned int out_buffer;
+ int out_bits;
+} g722_decode_state_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, unsigned int rate, int options);
+int g722_encode_release(g722_encode_state_t *s);
+int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len);
+
+g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, unsigned int rate, int options);
+int g722_decode_release(g722_decode_state_t *s);
+uint32_t g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len, uint16_t aGain);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/embdrv/g722/g722_encode.cc b/embdrv/g722/g722_encode.cc
new file mode 100644
index 0000000..817f5c0
--- /dev/null
+++ b/embdrv/g722/g722_encode.cc
@@ -0,0 +1,438 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g722_encode.c - The ITU G.722 codec, encode part.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * Despite my general liking of the GPL, I place my own contributions
+ * to this code in the public domain for the benefit of all mankind -
+ * even the slimy ones who might try to proprietize my work and use it
+ * to my detriment.
+ *
+ * Based on a single channel 64kbps only G.722 codec which is:
+ *
+ ***** Copyright (c) CMU 1993 *****
+ * Computer Science, Speech Group
+ * Chengxiang Lu and Alex Hauptmann
+ *
+ * $Id: g722_encode.c,v 1.14 2006/07/07 16:37:49 steveu Exp $
+ */
+
+/*! \file */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "g722_typedefs.h"
+#include "g722_enc_dec.h"
+
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+#if !defined(TRUE)
+#define TRUE (!FALSE)
+#endif
+
+#define PACKED_OUTPUT (0)
+#define BITS_PER_SAMPLE (8)
+
+#ifndef BUILD_FEATURE_G722_USE_INTRINSIC_SAT
+static __inline int16_t saturate(int32_t amp)
+{
+ int16_t amp16;
+
+ /* Hopefully this is optimised for the common case - not clipping */
+ amp16 = (int16_t) amp;
+ if (amp == amp16)
+ return amp16;
+ if (amp > 0x7FFF)
+ return 0x7FFF;
+ return 0x8000;
+}
+#else
+static __inline int16_t saturate(int32_t val)
+{
+ register int32_t res;
+ __asm volatile (
+ "SSAT %0, #16, %1\n\t"
+ :"=r"(res)
+ :"r"(val)
+ :);
+ return (int16_t)res;
+}
+#endif
+/*- End of function --------------------------------------------------------*/
+
+static void block4(g722_band_t *band, int d)
+{
+ int wd1;
+ int wd2;
+ int wd3;
+ int i;
+ int sg[7];
+ int ap1, ap2;
+ int sg0, sgi;
+ int sz;
+
+ /* Block 4, RECONS */
+ band->d[0] = d;
+ band->r[0] = saturate(band->s + d);
+
+ /* Block 4, PARREC */
+ band->p[0] = saturate(band->sz + d);
+
+ /* Block 4, UPPOL2 */
+ for (i = 0; i < 3; i++)
+ sg[i] = band->p[i] >> 15;
+ wd1 = saturate(band->a[1] << 2);
+
+ wd2 = (sg[0] == sg[1]) ? -wd1 : wd1;
+ if (wd2 > 32767)
+ wd2 = 32767;
+
+ ap2 = (wd2 >> 7) + ((sg[0] == sg[2]) ? 128 : -128);
+ ap2 += (band->a[2]*32512) >> 15;
+ if (ap2 > 12288)
+ ap2 = 12288;
+ else if (ap2 < -12288)
+ ap2 = -12288;
+ band->ap[2] = ap2;
+
+ /* Block 4, UPPOL1 */
+ sg[0] = band->p[0] >> 15;
+ sg[1] = band->p[1] >> 15;
+ wd1 = (sg[0] == sg[1]) ? 192 : -192;
+ wd2 = (band->a[1]*32640) >> 15;
+
+ ap1 = saturate(wd1 + wd2);
+ wd3 = saturate(15360 - band->ap[2]);
+ if (ap1 > wd3)
+ ap1 = wd3;
+ else if (ap1 < -wd3)
+ ap1 = -wd3;
+ band->ap[1] = ap1;
+
+ /* Block 4, UPZERO */
+ /* Block 4, FILTEZ */
+ wd1 = (d == 0) ? 0 : 128;
+
+ sg0 = sg[0] = d >> 15;
+ for (i = 1; i < 7; i++)
+ {
+ sgi = band->d[i] >> 15;
+ wd2 = (sgi == sg0) ? wd1 : -wd1;
+ wd3 = (band->b[i]*32640) >> 15;
+ band->bp[i] = saturate(wd2 + wd3);
+ }
+
+ /* Block 4, DELAYA */
+ sz = 0;
+ for (i = 6; i > 0; i--)
+ {
+ int bi;
+
+ band->d[i] = band->d[i - 1];
+ bi = band->b[i] = band->bp[i];
+ wd1 = saturate(band->d[i] + band->d[i]);
+ sz += (bi*wd1) >> 15;
+ }
+ band->sz = sz;
+
+ for (i = 2; i > 0; i--)
+ {
+ band->r[i] = band->r[i - 1];
+ band->p[i] = band->p[i - 1];
+ band->a[i] = band->ap[i];
+ }
+
+ /* Block 4, FILTEP */
+ wd1 = saturate(band->r[1] + band->r[1]);
+ wd1 = (band->a[1]*wd1) >> 15;
+ wd2 = saturate(band->r[2] + band->r[2]);
+ wd2 = (band->a[2]*wd2) >> 15;
+ band->sp = saturate(wd1 + wd2);
+
+ /* Block 4, PREDIC */
+ band->s = saturate(band->sp + band->sz);
+}
+/*- End of function --------------------------------------------------------*/
+
+g722_encode_state_t *g722_encode_init(g722_encode_state_t *s,
+ unsigned int rate, int options)
+{
+ if (s == NULL)
+ {
+#ifdef G722_SUPPORT_MALLOC
+ if ((s = (g722_encode_state_t *) malloc(sizeof(*s))) == NULL)
+#endif
+ return NULL;
+ }
+ memset(s, 0, sizeof(*s));
+ if (rate == 48000)
+ s->bits_per_sample = 6;
+ else if (rate == 56000)
+ s->bits_per_sample = 7;
+ else
+ s->bits_per_sample = 8;
+ s->band[0].det = 32;
+ s->band[1].det = 8;
+ return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+int g722_encode_release(g722_encode_state_t *s)
+{
+ free(s);
+ return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+/* WebRtc, tlegrand:
+ * Only define the following if bit-exactness with reference implementation
+ * is needed. Will only have any effect if input signal is saturated.
+ */
+//#define RUN_LIKE_REFERENCE_G722
+#ifdef RUN_LIKE_REFERENCE_G722
+int16_t limitValues (int16_t rl)
+{
+
+ int16_t yl;
+
+ yl = (rl > 16383) ? 16383 : ((rl < -16384) ? -16384 : rl);
+
+ return (yl);
+}
+/*- End of function --------------------------------------------------------*/
+#endif
+
+static int16_t q6[32] =
+{
+ 0, 35, 72, 110, 150, 190, 233, 276,
+ 323, 370, 422, 473, 530, 587, 650, 714,
+ 786, 858, 940, 1023, 1121, 1219, 1339, 1458,
+ 1612, 1765, 1980, 2195, 2557, 2919, 0, 0
+};
+static int16_t iln[32] =
+{
+ 0, 63, 62, 31, 30, 29, 28, 27,
+ 26, 25, 24, 23, 22, 21, 20, 19,
+ 18, 17, 16, 15, 14, 13, 12, 11,
+ 10, 9, 8, 7, 6, 5, 4, 0
+};
+static int16_t ilp[32] =
+{
+ 0, 61, 60, 59, 58, 57, 56, 55,
+ 54, 53, 52, 51, 50, 49, 48, 47,
+ 46, 45, 44, 43, 42, 41, 40, 39,
+ 38, 37, 36, 35, 34, 33, 32, 0
+};
+static int16_t wl[8] =
+{
+ -60, -30, 58, 172, 334, 538, 1198, 3042
+};
+static int16_t rl42[16] =
+{
+ 0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0
+};
+static int16_t ilb[32] =
+{
+ 2048, 2093, 2139, 2186, 2233, 2282, 2332,
+ 2383, 2435, 2489, 2543, 2599, 2656, 2714,
+ 2774, 2834, 2896, 2960, 3025, 3091, 3158,
+ 3228, 3298, 3371, 3444, 3520, 3597, 3676,
+ 3756, 3838, 3922, 4008
+};
+static int16_t qm4[16] =
+{
+ 0, -20456, -12896, -8968,
+ -6288, -4240, -2584, -1200,
+ 20456, 12896, 8968, 6288,
+ 4240, 2584, 1200, 0
+};
+static int16_t qm2[4] =
+{
+ -7408, -1616, 7408, 1616
+};
+static int16_t qmf_coeffs[12] =
+{
+ 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11,
+};
+static int16_t ihn[3] = {0, 1, 0};
+static int16_t ihp[3] = {0, 3, 2};
+static int16_t wh[3] = {0, -214, 798};
+static int16_t rh2[4] = {2, 1, 2, 1};
+
+int g722_encode(g722_encode_state_t *s, uint8_t g722_data[],
+ const int16_t amp[], int len)
+{
+ int dlow;
+ int dhigh;
+ int el;
+ int wd;
+ int wd1;
+ int ril;
+ int wd2;
+ int il4;
+ int ih2;
+ int wd3;
+ int eh;
+ int mih;
+ int i;
+ int j;
+ /* Low and high band PCM from the QMF */
+ int xlow;
+ int xhigh;
+ int g722_bytes;
+ /* Even and odd tap accumulators */
+ int sumeven;
+ int sumodd;
+ int ihigh;
+ int ilow;
+ int code;
+
+ g722_bytes = 0;
+ xhigh = 0;
+ for (j = 0; j < len; )
+ {
+ if (s->itu_test_mode)
+ {
+ xlow =
+ xhigh = amp[j++] >> 1;
+ }
+ else
+ {
+ {
+ /* Apply the transmit QMF */
+ /* Shuffle the buffer down */
+ for (i = 0; i < 22; i++)
+ s->x[i] = s->x[i + 2];
+ //TODO: if len is odd, then this can be a buffer overrun
+ s->x[22] = amp[j++];
+ s->x[23] = amp[j++];
+
+ /* Discard every other QMF output */
+ sumeven = 0;
+ sumodd = 0;
+ for (i = 0; i < 12; i++)
+ {
+ sumodd += s->x[2*i]*qmf_coeffs[i];
+ sumeven += s->x[2*i + 1]*qmf_coeffs[11 - i];
+ }
+ /* We shift by 12 to allow for the QMF filters (DC gain = 4096), plus 1
+ to allow for us summing two filters, plus 1 to allow for the 15 bit
+ input to the G.722 algorithm. */
+ xlow = (sumeven + sumodd) >> 14;
+ xhigh = (sumeven - sumodd) >> 14;
+
+#ifdef RUN_LIKE_REFERENCE_G722
+ /* The following lines are only used to verify bit-exactness
+ * with reference implementation of G.722. Higher precision
+ * is achieved without limiting the values.
+ */
+ xlow = limitValues(xlow);
+ xhigh = limitValues(xhigh);
+#endif
+ }
+ }
+ /* Block 1L, SUBTRA */
+ el = saturate(xlow - s->band[0].s);
+
+ /* Block 1L, QUANTL */
+ wd = (el >= 0) ? el : -(el + 1);
+
+ for (i = 1; i < 30; i++)
+ {
+ wd1 = (q6[i]*s->band[0].det) >> 12;
+ if (wd < wd1)
+ break;
+ }
+ ilow = (el < 0) ? iln[i] : ilp[i];
+
+ /* Block 2L, INVQAL */
+ ril = ilow >> 2;
+ wd2 = qm4[ril];
+ dlow = (s->band[0].det*wd2) >> 15;
+
+ /* Block 3L, LOGSCL */
+ il4 = rl42[ril];
+ wd = (s->band[0].nb*127) >> 7;
+ s->band[0].nb = wd + wl[il4];
+ if (s->band[0].nb < 0)
+ s->band[0].nb = 0;
+ else if (s->band[0].nb > 18432)
+ s->band[0].nb = 18432;
+
+ /* Block 3L, SCALEL */
+ wd1 = (s->band[0].nb >> 6) & 31;
+ wd2 = 8 - (s->band[0].nb >> 11);
+ wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2);
+ s->band[0].det = wd3 << 2;
+
+ block4(&s->band[0], dlow);
+ {
+ int nb;
+
+ /* Block 1H, SUBTRA */
+ eh = saturate(xhigh - s->band[1].s);
+
+ /* Block 1H, QUANTH */
+ wd = (eh >= 0) ? eh : -(eh + 1);
+ wd1 = (564*s->band[1].det) >> 12;
+ mih = (wd >= wd1) ? 2 : 1;
+ ihigh = (eh < 0) ? ihn[mih] : ihp[mih];
+
+ /* Block 2H, INVQAH */
+ wd2 = qm2[ihigh];
+ dhigh = (s->band[1].det*wd2) >> 15;
+
+ /* Block 3H, LOGSCH */
+ ih2 = rh2[ihigh];
+ wd = (s->band[1].nb*127) >> 7;
+
+ nb = wd + wh[ih2];
+ if (nb < 0)
+ nb = 0;
+ else if (nb > 22528)
+ nb = 22528;
+ s->band[1].nb = nb;
+
+ /* Block 3H, SCALEH */
+ wd1 = (s->band[1].nb >> 6) & 31;
+ wd2 = 10 - (s->band[1].nb >> 11);
+ wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2);
+ s->band[1].det = wd3 << 2;
+
+ block4(&s->band[1], dhigh);
+#if BITS_PER_SAMPLE == 8
+ code = ((ihigh << 6) | ilow);
+#elif BITS_PER_SAMPLE == 7
+ code = ((ihigh << 6) | ilow) >> 1;
+#elif BITS_PER_SAMPLE == 6
+ code = ((ihigh << 6) | ilow) >> 2;
+#endif
+ }
+
+#if PACKED_OUTPUT == 1
+ /* Pack the code bits */
+ s->out_buffer |= (code << s->out_bits);
+ s->out_bits += s->bits_per_sample;
+ if (s->out_bits >= 8)
+ {
+ g722_data[g722_bytes++] = (uint8_t) (s->out_buffer & 0xFF);
+ s->out_bits -= 8;
+ s->out_buffer >>= 8;
+ }
+#else
+ g722_data[g722_bytes++] = (uint8_t) code;
+#endif
+ }
+ return g722_bytes;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
diff --git a/embdrv/g722/g722_typedefs.h b/embdrv/g722/g722_typedefs.h
new file mode 100644
index 0000000..d8977ff
--- /dev/null
+++ b/embdrv/g722/g722_typedefs.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// This file contains platform-specific typedefs and defines.
+// Much of it is derived from Chromium's build/build_config.h.
+
+#ifndef WEBRTC_TYPEDEFS_H_
+#define WEBRTC_TYPEDEFS_H_
+
+// Processor architecture detection. For more info on what's defined, see:
+// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+// http://www.agner.org/optimize/calling_conventions.pdf
+// or with gcc, run: "echo | gcc -E -dM -"
+#if defined(_M_X64) || defined(__x86_64__)
+#define WEBRTC_ARCH_X86_FAMILY
+#define WEBRTC_ARCH_X86_64
+#define WEBRTC_ARCH_64_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#elif defined(__aarch64__)
+#define WEBRTC_ARCH_64_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#elif defined(_M_IX86) || defined(__i386__)
+#define WEBRTC_ARCH_X86_FAMILY
+#define WEBRTC_ARCH_X86
+#define WEBRTC_ARCH_32_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#elif defined(__ARMEL__)
+// TODO(ajm): We'd prefer to control platform defines here, but this is
+// currently provided by the Android makefiles. Commented to avoid duplicate
+// definition warnings.
+//#define WEBRTC_ARCH_ARM
+// TODO(ajm): Chromium uses the following two defines. Should we switch?
+//#define WEBRTC_ARCH_ARM_FAMILY
+//#define WEBRTC_ARCH_ARMEL
+#define WEBRTC_ARCH_32_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#elif defined(__MIPSEL__)
+#define WEBRTC_ARCH_32_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#elif defined(__pnacl__)
+#define WEBRTC_ARCH_32_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#else
+#error Please add support for your architecture in typedefs.h
+#endif
+
+#if !(defined(WEBRTC_ARCH_LITTLE_ENDIAN) ^ defined(WEBRTC_ARCH_BIG_ENDIAN))
+#error Define either WEBRTC_ARCH_LITTLE_ENDIAN or WEBRTC_ARCH_BIG_ENDIAN
+#endif
+
+#if (defined(WEBRTC_ARCH_X86_FAMILY) && !defined(__SSE2__)) || \
+ (defined(WEBRTC_ARCH_ARM_V7) && !defined(WEBRTC_ARCH_ARM_NEON))
+#define WEBRTC_CPU_DETECTION
+#endif
+
+#if !defined(_MSC_VER)
+#include <stdint.h>
+#else
+// Define C99 equivalent types, since pre-2010 MSVC doesn't provide stdint.h.
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef __int64 int64_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned __int64 uint64_t;
+#endif
+
+// Borrowed from Chromium's base/compiler_specific.h.
+// Annotate a virtual method indicating it must be overriding a virtual
+// method in the parent class.
+// Use like:
+// virtual void foo() OVERRIDE;
+#if defined(_MSC_VER)
+#define OVERRIDE override
+#elif defined(__clang__)
+// Clang defaults to C++03 and warns about using override. Squelch that.
+// Intentionally no push/pop here so all users of OVERRIDE ignore the warning
+// too. This is like passing -Wno-c++11-extensions, except that GCC won't die
+// (because it won't see this pragma).
+#pragma clang diagnostic ignored "-Wc++11-extensions"
+#define OVERRIDE override
+#elif defined(__GNUC__) && __cplusplus >= 201103 && \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700
+// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled.
+#define OVERRIDE override
+#else
+#define OVERRIDE
+#endif
+
+// Annotate a function indicating the caller must examine the return value.
+// Use like:
+// int foo() WARN_UNUSED_RESULT;
+// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and
+// libjingle are merged.
+#if !defined(WARN_UNUSED_RESULT)
+#if defined(__GNUC__)
+#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+#define WARN_UNUSED_RESULT
+#endif
+#endif // WARN_UNUSED_RESULT
+
+#endif // WEBRTC_TYPEDEFS_H_
diff --git a/embdrv/sbc/BUILD.gn b/embdrv/sbc/BUILD.gn
index 7e75633..696080a 100644
--- a/embdrv/sbc/BUILD.gn
+++ b/embdrv/sbc/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@
include_dirs = [
"encoder/include",
- "//include",
+ "//internal_include",
"//stack/include",
]
}
diff --git a/embdrv/sbc/decoder/include/oi_assert.h b/embdrv/sbc/decoder/include/oi_assert.h
index 1d18f12..4a429e1 100644
--- a/embdrv/sbc/decoder/include/oi_assert.h
+++ b/embdrv/sbc/decoder/include/oi_assert.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_bitstream.h b/embdrv/sbc/decoder/include/oi_bitstream.h
index 1fb075e..0d2aff2 100644
--- a/embdrv/sbc/decoder/include/oi_bitstream.h
+++ b/embdrv/sbc/decoder/include/oi_bitstream.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_bt_spec.h b/embdrv/sbc/decoder/include/oi_bt_spec.h
index 077befd..67d5217 100644
--- a/embdrv/sbc/decoder/include/oi_bt_spec.h
+++ b/embdrv/sbc/decoder/include/oi_bt_spec.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_codec_sbc.h b/embdrv/sbc/decoder/include/oi_codec_sbc.h
index 61fe510..ee761db 100644
--- a/embdrv/sbc/decoder/include/oi_codec_sbc.h
+++ b/embdrv/sbc/decoder/include/oi_codec_sbc.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_codec_sbc_private.h b/embdrv/sbc/decoder/include/oi_codec_sbc_private.h
index 91d80f1..080fe5d 100644
--- a/embdrv/sbc/decoder/include/oi_codec_sbc_private.h
+++ b/embdrv/sbc/decoder/include/oi_codec_sbc_private.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_common.h b/embdrv/sbc/decoder/include/oi_common.h
index a4cf20b..67a69a5 100644
--- a/embdrv/sbc/decoder/include/oi_common.h
+++ b/embdrv/sbc/decoder/include/oi_common.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_cpu_dep.h b/embdrv/sbc/decoder/include/oi_cpu_dep.h
index 21faf5e..b628b4a 100644
--- a/embdrv/sbc/decoder/include/oi_cpu_dep.h
+++ b/embdrv/sbc/decoder/include/oi_cpu_dep.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_modules.h b/embdrv/sbc/decoder/include/oi_modules.h
index 3c20285..272a31a 100644
--- a/embdrv/sbc/decoder/include/oi_modules.h
+++ b/embdrv/sbc/decoder/include/oi_modules.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_osinterface.h b/embdrv/sbc/decoder/include/oi_osinterface.h
index c0a3ff1..8460ca7 100644
--- a/embdrv/sbc/decoder/include/oi_osinterface.h
+++ b/embdrv/sbc/decoder/include/oi_osinterface.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_status.h b/embdrv/sbc/decoder/include/oi_status.h
index 13a5815..8e6d20a 100644
--- a/embdrv/sbc/decoder/include/oi_status.h
+++ b/embdrv/sbc/decoder/include/oi_status.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_stddefs.h b/embdrv/sbc/decoder/include/oi_stddefs.h
index ade040d..e619635 100644
--- a/embdrv/sbc/decoder/include/oi_stddefs.h
+++ b/embdrv/sbc/decoder/include/oi_stddefs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_string.h b/embdrv/sbc/decoder/include/oi_string.h
index fe1e4c1..0d53761 100644
--- a/embdrv/sbc/decoder/include/oi_string.h
+++ b/embdrv/sbc/decoder/include/oi_string.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_time.h b/embdrv/sbc/decoder/include/oi_time.h
index 9b189af..d183ccb 100644
--- a/embdrv/sbc/decoder/include/oi_time.h
+++ b/embdrv/sbc/decoder/include/oi_time.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/include/oi_utils.h b/embdrv/sbc/decoder/include/oi_utils.h
index 9579d78..269114f 100644
--- a/embdrv/sbc/decoder/include/oi_utils.h
+++ b/embdrv/sbc/decoder/include/oi_utils.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/alloc.c b/embdrv/sbc/decoder/srce/alloc.c
index db0d7f0..bc6e543 100644
--- a/embdrv/sbc/decoder/srce/alloc.c
+++ b/embdrv/sbc/decoder/srce/alloc.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/bitalloc-sbc.c b/embdrv/sbc/decoder/srce/bitalloc-sbc.c
index 3e7e6f4..caf6bdf 100644
--- a/embdrv/sbc/decoder/srce/bitalloc-sbc.c
+++ b/embdrv/sbc/decoder/srce/bitalloc-sbc.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/bitalloc.c b/embdrv/sbc/decoder/srce/bitalloc.c
index 75e914a..db8a3b5 100644
--- a/embdrv/sbc/decoder/srce/bitalloc.c
+++ b/embdrv/sbc/decoder/srce/bitalloc.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/bitstream-decode.c b/embdrv/sbc/decoder/srce/bitstream-decode.c
index 5c8b664..913c064 100644
--- a/embdrv/sbc/decoder/srce/bitstream-decode.c
+++ b/embdrv/sbc/decoder/srce/bitstream-decode.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/decoder-oina.c b/embdrv/sbc/decoder/srce/decoder-oina.c
index 5811584..3553d06 100644
--- a/embdrv/sbc/decoder/srce/decoder-oina.c
+++ b/embdrv/sbc/decoder/srce/decoder-oina.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2006 Open Interface North America, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/embdrv/sbc/decoder/srce/decoder-private.c b/embdrv/sbc/decoder/srce/decoder-private.c
index 686dd6a..2b10cde 100644
--- a/embdrv/sbc/decoder/srce/decoder-private.c
+++ b/embdrv/sbc/decoder/srce/decoder-private.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/decoder-sbc.c b/embdrv/sbc/decoder/srce/decoder-sbc.c
index 85c37d6..20c5b67 100644
--- a/embdrv/sbc/decoder/srce/decoder-sbc.c
+++ b/embdrv/sbc/decoder/srce/decoder-sbc.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2006 Open Interface North America, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/embdrv/sbc/decoder/srce/dequant.c b/embdrv/sbc/decoder/srce/dequant.c
index 5243477..e2bce9e 100644
--- a/embdrv/sbc/decoder/srce/dequant.c
+++ b/embdrv/sbc/decoder/srce/dequant.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/framing-sbc.c b/embdrv/sbc/decoder/srce/framing-sbc.c
index e3b1000..9aea461 100644
--- a/embdrv/sbc/decoder/srce/framing-sbc.c
+++ b/embdrv/sbc/decoder/srce/framing-sbc.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/framing.c b/embdrv/sbc/decoder/srce/framing.c
index f6f762c..f835b52 100644
--- a/embdrv/sbc/decoder/srce/framing.c
+++ b/embdrv/sbc/decoder/srce/framing.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/oi_codec_version.c b/embdrv/sbc/decoder/srce/oi_codec_version.c
index 4b69183..70c005f 100644
--- a/embdrv/sbc/decoder/srce/oi_codec_version.c
+++ b/embdrv/sbc/decoder/srce/oi_codec_version.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/readsamplesjoint.inc b/embdrv/sbc/decoder/srce/readsamplesjoint.inc
index 79151ff..5c9613e 100644
--- a/embdrv/sbc/decoder/srce/readsamplesjoint.inc
+++ b/embdrv/sbc/decoder/srce/readsamplesjoint.inc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/synthesis-8-generated.c b/embdrv/sbc/decoder/srce/synthesis-8-generated.c
index d852c74..1656dc4 100644
--- a/embdrv/sbc/decoder/srce/synthesis-8-generated.c
+++ b/embdrv/sbc/decoder/srce/synthesis-8-generated.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/synthesis-dct8.c b/embdrv/sbc/decoder/srce/synthesis-dct8.c
index 514c900..2dfe753 100644
--- a/embdrv/sbc/decoder/srce/synthesis-dct8.c
+++ b/embdrv/sbc/decoder/srce/synthesis-dct8.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/decoder/srce/synthesis-sbc.c b/embdrv/sbc/decoder/srce/synthesis-sbc.c
index 12950c3..a5111ae 100644
--- a/embdrv/sbc/decoder/srce/synthesis-sbc.c
+++ b/embdrv/sbc/decoder/srce/synthesis-sbc.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights
* reserved.
*
diff --git a/embdrv/sbc/encoder/Android.bp b/embdrv/sbc/encoder/Android.bp
index 6e22f89..8ca44de 100644
--- a/embdrv/sbc/encoder/Android.bp
+++ b/embdrv/sbc/encoder/Android.bp
@@ -17,7 +17,7 @@
],
include_dirs: [
"system/bt",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/stack/include",
],
}
diff --git a/embdrv/sbc/encoder/include/sbc_dct.h b/embdrv/sbc/encoder/include/sbc_dct.h
index 10123e5..86130b7 100644
--- a/embdrv/sbc/encoder/include/sbc_dct.h
+++ b/embdrv/sbc/encoder/include/sbc_dct.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/include/sbc_enc_func_declare.h b/embdrv/sbc/encoder/include/sbc_enc_func_declare.h
index 3fbe06a..081f8ab 100644
--- a/embdrv/sbc/encoder/include/sbc_enc_func_declare.h
+++ b/embdrv/sbc/encoder/include/sbc_enc_func_declare.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/include/sbc_encoder.h b/embdrv/sbc/encoder/include/sbc_encoder.h
index e53a08a..53a04a2 100644
--- a/embdrv/sbc/encoder/include/sbc_encoder.h
+++ b/embdrv/sbc/encoder/include/sbc_encoder.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -150,10 +150,6 @@
/*#define ENC_VX_BUFFER_SIZE MINIMUM_ENC_VX_BUFFER_SIZE + 1024*/
#endif
-#ifndef SBC_FOR_EMBEDDED_LINUX
-#define SBC_FOR_EMBEDDED_LINUX FALSE
-#endif
-
/*constants used for index calculation*/
#define SBC_BLK (SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS)
diff --git a/embdrv/sbc/encoder/include/sbc_if.h b/embdrv/sbc/encoder/include/sbc_if.h
index 19706d2..5679383 100644
--- a/embdrv/sbc/encoder/include/sbc_if.h
+++ b/embdrv/sbc/encoder/include/sbc_if.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/include/sbc_types.h b/embdrv/sbc/encoder/include/sbc_types.h
index 0069a2a..211c693 100644
--- a/embdrv/sbc/encoder/include/sbc_types.h
+++ b/embdrv/sbc/encoder/include/sbc_types.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/srce/sbc_analysis.c b/embdrv/sbc/encoder/srce/sbc_analysis.c
index ddc9978..b9a9a5c 100644
--- a/embdrv/sbc/encoder/srce/sbc_analysis.c
+++ b/embdrv/sbc/encoder/srce/sbc_analysis.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/srce/sbc_dct.c b/embdrv/sbc/encoder/srce/sbc_dct.c
index 4ef5572..9f0efe4 100644
--- a/embdrv/sbc/encoder/srce/sbc_dct.c
+++ b/embdrv/sbc/encoder/srce/sbc_dct.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/srce/sbc_dct_coeffs.c b/embdrv/sbc/encoder/srce/sbc_dct_coeffs.c
index 287ad4c..fd7e9cd 100644
--- a/embdrv/sbc/encoder/srce/sbc_dct_coeffs.c
+++ b/embdrv/sbc/encoder/srce/sbc_dct_coeffs.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c b/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c
index f849340..868ce6f 100644
--- a/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c
+++ b/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c b/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c
index 4e205e2..00ee65b 100644
--- a/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c
+++ b/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/srce/sbc_enc_coeffs.c b/embdrv/sbc/encoder/srce/sbc_enc_coeffs.c
index 2129fba..2536b79 100644
--- a/embdrv/sbc/encoder/srce/sbc_enc_coeffs.c
+++ b/embdrv/sbc/encoder/srce/sbc_enc_coeffs.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/srce/sbc_encoder.c b/embdrv/sbc/encoder/srce/sbc_encoder.c
index 978fa71..54212ad 100644
--- a/embdrv/sbc/encoder/srce/sbc_encoder.c
+++ b/embdrv/sbc/encoder/srce/sbc_encoder.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/embdrv/sbc/encoder/srce/sbc_packing.c b/embdrv/sbc/encoder/srce/sbc_packing.c
index 5f36ab8..b478a80 100644
--- a/embdrv/sbc/encoder/srce/sbc_packing.c
+++ b/embdrv/sbc/encoder/srce/sbc_packing.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/Android.bp b/hci/Android.bp
index 4edcfee..635d939 100644
--- a/hci/Android.bp
+++ b/hci/Android.bp
@@ -31,7 +31,7 @@
],
include_dirs: [
"system/bt",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/btcore/include",
"system/bt/stack/include",
"system/bt/utils/include",
@@ -51,7 +51,7 @@
],
include_dirs: [
"system/bt",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/btcore/include",
"system/bt/osi/test",
"system/bt/stack/include",
@@ -73,6 +73,6 @@
"libosi-AllocationTestHarness",
"libcutils",
"libbtcore",
- "libbt-protos",
+ "libbt-protos-lite",
],
}
diff --git a/hci/AndroidTest.xml b/hci/AndroidTest.xml
index b7c1e64..944b454 100644
--- a/hci/AndroidTest.xml
+++ b/hci/AndroidTest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/hci/BUILD.gn b/hci/BUILD.gn
index ba38134..fc9c2ce 100644
--- a/hci/BUILD.gn
+++ b/hci/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
include_dirs = [
"include",
"//",
- "//include",
+ "//internal_include",
"//bta/include",
"//btcore/include",
"//stack/include",
@@ -52,7 +52,7 @@
include_dirs = [
"//",
- "//include",
+ "//internal_include",
"//btcore/include",
"//hci/include",
"//osi/test",
diff --git a/hci/include/bt_hci_bdroid.h b/hci/include/bt_hci_bdroid.h
index aa193d0..cf2c113 100644
--- a/hci/include/bt_hci_bdroid.h
+++ b/hci/include/bt_hci_bdroid.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/bt_vendor_lib.h b/hci/include/bt_vendor_lib.h
index 3c056ab..a274af7 100644
--- a/hci/include/bt_vendor_lib.h
+++ b/hci/include/bt_vendor_lib.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/btsnoop.h b/hci/include/btsnoop.h
index 1cd35dc..e897a96 100644
--- a/hci/include/btsnoop.h
+++ b/hci/include/btsnoop.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/btsnoop_mem.h b/hci/include/btsnoop_mem.h
index cf42ff7..42c3229 100644
--- a/hci/include/btsnoop_mem.h
+++ b/hci/include/btsnoop_mem.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/buffer_allocator.h b/hci/include/buffer_allocator.h
index 63fb217..3bfa2e44 100644
--- a/hci/include/buffer_allocator.h
+++ b/hci/include/buffer_allocator.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/hci_hal.h b/hci/include/hci_hal.h
index 53595c0..f73e116 100644
--- a/hci/include/hci_hal.h
+++ b/hci/include/hci_hal.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/hci_inject.h b/hci/include/hci_inject.h
index 12870d5..62ec518 100644
--- a/hci/include/hci_inject.h
+++ b/hci/include/hci_inject.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/hci_internals.h b/hci/include/hci_internals.h
index 6b9fb01..8fe0041 100644
--- a/hci/include/hci_internals.h
+++ b/hci/include/hci_internals.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/hci_layer.h b/hci/include/hci_layer.h
index acb86de..59ee443 100644
--- a/hci/include/hci_layer.h
+++ b/hci/include/hci_layer.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/hci_packet_factory.h b/hci/include/hci_packet_factory.h
index ed189d6..e7cb47b 100644
--- a/hci/include/hci_packet_factory.h
+++ b/hci/include/hci_packet_factory.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,6 +41,7 @@
BT_HDR* (*make_ble_read_local_supported_features)(void);
BT_HDR* (*make_ble_read_resolving_list_size)(void);
BT_HDR* (*make_ble_read_suggested_default_data_length)(void);
+ BT_HDR* (*make_ble_read_maximum_data_length)(void);
BT_HDR* (*make_ble_read_maximum_advertising_data_length)(void);
BT_HDR* (*make_ble_read_number_of_supported_advertising_sets)(void);
BT_HDR* (*make_ble_set_event_mask)(const bt_event_mask_t* event_mask);
diff --git a/hci/include/hci_packet_parser.h b/hci/include/hci_packet_parser.h
index 0e74c29..8878cb9 100644
--- a/hci/include/hci_packet_parser.h
+++ b/hci/include/hci_packet_parser.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -67,6 +67,12 @@
void (*parse_ble_read_suggested_default_data_length_response)(
BT_HDR* response, uint16_t* ble_default_packet_length_ptr);
+ void (*parse_ble_read_maximum_data_length_response)(
+ BT_HDR* response, uint16_t* ble_supported_max_tx_octets,
+ uint16_t* ble_supported_max_tx_time,
+ uint16_t* ble_supported_max_rx_octets,
+ uint16_t* ble_supported_max_rx_time);
+
void (*parse_ble_read_maximum_advertising_data_length)(
BT_HDR* response, uint16_t* ble_maximum_advertising_data_length_ptr);
diff --git a/hci/include/low_power_manager.h b/hci/include/low_power_manager.h
index 47e3b6d..8b8bd8f 100644
--- a/hci/include/low_power_manager.h
+++ b/hci/include/low_power_manager.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/packet_fragmenter.h b/hci/include/packet_fragmenter.h
index 935ea94..9b252b8 100644
--- a/hci/include/packet_fragmenter.h
+++ b/hci/include/packet_fragmenter.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/userial.h b/hci/include/userial.h
index becb407..2d1424f 100644
--- a/hci/include/userial.h
+++ b/hci/include/userial.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/include/vendor.h b/hci/include/vendor.h
index 70a2cef..ca9f153 100644
--- a/hci/include/vendor.h
+++ b/hci/include/vendor.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/src/btsnoop.cc b/hci/src/btsnoop.cc
index a109ad0..9812b61 100644
--- a/hci/src/btsnoop.cc
+++ b/hci/src/btsnoop.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/uio.h>
#include <unistd.h>
#include "bt_types.h"
@@ -199,7 +200,7 @@
get_btsnoop_log_path(log_path);
get_btsnoop_last_log_path(last_log_path, log_path);
- if (!rename(log_path, last_log_path) && errno != ENOENT)
+ if (rename(log_path, last_log_path) != 0 && errno != ENOENT)
LOG_ERROR(LOG_TAG, "%s unable to rename '%s' to '%s': %s", __func__,
log_path, last_log_path, strerror(errno));
diff --git a/hci/src/btsnoop_mem.cc b/hci/src/btsnoop_mem.cc
index ad135e0..17ce248 100644
--- a/hci/src/btsnoop_mem.cc
+++ b/hci/src/btsnoop_mem.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/src/btsnoop_net.cc b/hci/src/btsnoop_net.cc
index 1d49692..a549205 100644
--- a/hci/src/btsnoop_net.cc
+++ b/hci/src/btsnoop_net.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2013 Google, Inc.
+ * Copyright 2013 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/src/buffer_allocator.cc b/hci/src/buffer_allocator.cc
index d231abe..19a3940 100644
--- a/hci/src/buffer_allocator.cc
+++ b/hci/src/buffer_allocator.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/src/hci_inject.cc b/hci/src/hci_inject.cc
index 70194a5..01b8cfd 100644
--- a/hci/src/hci_inject.cc
+++ b/hci/src/hci_inject.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/src/hci_layer.cc b/hci/src/hci_layer.cc
index d1fa920..f1e0e7a 100644
--- a/hci/src/hci_layer.cc
+++ b/hci/src/hci_layer.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -78,7 +78,9 @@
// Abort if there is no response to an HCI command.
static const uint32_t COMMAND_PENDING_TIMEOUT_MS = 2000;
-static const uint32_t COMMAND_TIMEOUT_RESTART_US = 5000000;
+static const uint32_t COMMAND_PENDING_MUTEX_ACQUIRE_TIMEOUT_MS = 500;
+static const uint32_t COMMAND_TIMEOUT_RESTART_MS = 5000;
+static const int HCI_UNKNOWN_COMMAND_TIMED_OUT = 0x00ffffff;
// Our interface
static bool interface_created;
@@ -105,7 +107,8 @@
// Inbound-related
static alarm_t* command_response_timer;
static list_t* commands_pending_response;
-static std::recursive_mutex commands_pending_response_mutex;
+static std::recursive_timed_mutex commands_pending_response_mutex;
+static alarm_t* hci_timeout_abort_timer;
// The hand-off point for data going to a higher layer, set by the higher layer
static base::Callback<void(const tracked_objects::Location&, BT_HDR*)>
@@ -254,7 +257,8 @@
// Free the timers
{
- std::lock_guard<std::recursive_mutex> lock(commands_pending_response_mutex);
+ std::lock_guard<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex);
alarm_free(command_response_timer);
command_response_timer = NULL;
alarm_free(startup_timer);
@@ -276,7 +280,8 @@
hci_close();
{
- std::lock_guard<std::recursive_mutex> lock(commands_pending_response_mutex);
+ std::lock_guard<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex);
list_free(commands_pending_response);
commands_pending_response = NULL;
}
@@ -286,6 +291,17 @@
thread_free(thread);
thread = NULL;
+ // Clean up abort timer, if it exists.
+ if (hci_timeout_abort_timer != NULL) {
+ alarm_free(hci_timeout_abort_timer);
+ hci_timeout_abort_timer = NULL;
+ }
+
+ if (hci_firmware_log_fd != INVALID_FD) {
+ hci_close_firmware_log_file(hci_firmware_log_fd);
+ hci_firmware_log_fd = INVALID_FD;
+ }
+
return NULL;
}
@@ -359,7 +375,8 @@
static void event_finish_startup(UNUSED_ATTR void* context) {
LOG_INFO(LOG_TAG, "%s", __func__);
- std::lock_guard<std::recursive_mutex> lock(commands_pending_response_mutex);
+ std::lock_guard<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex);
alarm_cancel(startup_timer);
future_ready(startup_future, FUTURE_SUCCESS);
startup_future = NULL;
@@ -368,9 +385,18 @@
static void startup_timer_expired(UNUSED_ATTR void* context) {
LOG_ERROR(LOG_TAG, "%s", __func__);
- std::lock_guard<std::recursive_mutex> lock(commands_pending_response_mutex);
+ std::unique_lock<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex, std::defer_lock);
+ if (!lock.try_lock_for(std::chrono::milliseconds(
+ COMMAND_PENDING_MUTEX_ACQUIRE_TIMEOUT_MS))) {
+ LOG_ERROR(LOG_TAG, "%s: Cannot obtain the mutex", __func__);
+ // We cannot recover if the startup timer expired and we are deadlock,
+ // hence abort.
+ abort();
+ }
future_ready(startup_future, FUTURE_FAIL);
startup_future = NULL;
+ lock.unlock();
}
// Command/packet transmitting functions
@@ -394,11 +420,13 @@
}
static void event_command_ready(waiting_command_t* wait_entry) {
- /// Move it to the list of commands awaiting response
- std::lock_guard<std::recursive_mutex> lock(commands_pending_response_mutex);
- wait_entry->timestamp = std::chrono::steady_clock::now();
- list_append(commands_pending_response, wait_entry);
-
+ {
+ /// Move it to the list of commands awaiting response
+ std::lock_guard<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex);
+ wait_entry->timestamp = std::chrono::steady_clock::now();
+ list_append(commands_pending_response, wait_entry);
+ }
// Send it off
packet_fragmenter->fragment_and_dispatch(wait_entry->command);
@@ -426,11 +454,17 @@
static void transmit_fragment(BT_HDR* packet, bool send_transmit_finished) {
btsnoop->capture(packet, false);
+ // HCI command packets are freed on a different thread when the matching
+ // event is received. Check packet->event before sending to avoid a race.
+ bool free_after_transmit =
+ (packet->event & MSG_EVT_MASK) != MSG_STACK_TO_HC_HCI_CMD &&
+ send_transmit_finished;
+
hci_transmit(packet);
- uint16_t event = packet->event & MSG_EVT_MASK;
- if (event != MSG_STACK_TO_HC_HCI_CMD && send_transmit_finished)
+ if (free_after_transmit) {
buffer_allocator->free(packet);
+ }
}
static void fragmenter_transmit_finished(BT_HDR* packet,
@@ -446,10 +480,17 @@
}
}
-// Print debugging information and quit. Don't dereference original_wait_entry.
-static void command_timed_out(void* original_wait_entry) {
- std::unique_lock<std::recursive_mutex> lock(commands_pending_response_mutex);
+// Abort. The chip has had time to write any debugging information.
+static void hci_timeout_abort(void* unused_data) {
+ LOG_ERROR(LOG_TAG, "%s restarting the Bluetooth process.", __func__);
+ hci_close_firmware_log_file(hci_firmware_log_fd);
+ // We shouldn't try to recover the stack from this command timeout.
+ // If it's caused by a software bug, fix it. If it's a hardware bug, fix it.
+ abort();
+}
+
+static void command_timed_out_log_info(void* original_wait_entry) {
LOG_ERROR(LOG_TAG, "%s: %d commands pending response", __func__,
get_num_waiting_commands());
@@ -479,7 +520,26 @@
LOG_EVENT_INT(BT_HCI_TIMEOUT_TAG_NUM, wait_entry->opcode);
}
- lock.unlock();
+}
+
+// Print debugging information and quit. Don't dereference original_wait_entry.
+static void command_timed_out(void* original_wait_entry) {
+ LOG_ERROR(LOG_TAG, "%s", __func__);
+ std::unique_lock<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex, std::defer_lock);
+ if (!lock.try_lock_for(std::chrono::milliseconds(
+ COMMAND_PENDING_MUTEX_ACQUIRE_TIMEOUT_MS))) {
+ LOG_ERROR(LOG_TAG, "%s: Cannot obtain the mutex", __func__);
+ LOG_EVENT_INT(BT_HCI_TIMEOUT_TAG_NUM, HCI_UNKNOWN_COMMAND_TIMED_OUT);
+ } else {
+ command_timed_out_log_info(original_wait_entry);
+ lock.unlock();
+ }
+
+ // Don't request a firmware dump for multiple hci timeouts
+ if (hci_timeout_abort_timer != NULL || hci_firmware_log_fd != INVALID_FD) {
+ return;
+ }
LOG_ERROR(LOG_TAG, "%s: requesting a firmware dump.", __func__);
@@ -502,14 +562,15 @@
transmit_fragment(bt_hdr, true);
osi_free(bt_hdr);
+ LOG_ERROR(LOG_TAG, "%s: Setting a timer to restart.", __func__);
- LOG_ERROR(LOG_TAG, "%s restarting the Bluetooth process.", __func__);
- usleep(COMMAND_TIMEOUT_RESTART_US);
- hci_close_firmware_log_file(hci_firmware_log_fd);
-
- // We shouldn't try to recover the stack from this command timeout.
- // If it's caused by a software bug, fix it. If it's a hardware bug, fix it.
- abort();
+ hci_timeout_abort_timer = alarm_new("hci.hci_timeout_aborter");
+ if (!hci_timeout_abort_timer) {
+ LOG_ERROR(LOG_TAG, "%s unable to create an abort timer.", __func__);
+ abort();
+ }
+ alarm_set(hci_timeout_abort_timer, COMMAND_TIMEOUT_RESTART_MS,
+ hci_timeout_abort, nullptr);
}
// Event/packet receiving functions
@@ -640,7 +701,8 @@
// Misc internal functions
static waiting_command_t* get_waiting_command(command_opcode_t opcode) {
- std::lock_guard<std::recursive_mutex> lock(commands_pending_response_mutex);
+ std::lock_guard<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex);
for (const list_node_t* node = list_begin(commands_pending_response);
node != list_end(commands_pending_response); node = list_next(node)) {
@@ -658,12 +720,14 @@
}
static int get_num_waiting_commands() {
- std::lock_guard<std::recursive_mutex> lock(commands_pending_response_mutex);
+ std::lock_guard<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex);
return list_length(commands_pending_response);
}
static void update_command_response_timer(void) {
- std::lock_guard<std::recursive_mutex> lock(commands_pending_response_mutex);
+ std::lock_guard<std::recursive_timed_mutex> lock(
+ commands_pending_response_mutex);
if (command_response_timer == NULL) return;
if (list_is_empty(commands_pending_response)) {
diff --git a/hci/src/hci_layer_android.cc b/hci/src/hci_layer_android.cc
index 0598ca1..183b74e 100644
--- a/hci/src/hci_layer_android.cc
+++ b/hci/src/hci_layer_android.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 Google, Inc.
+ * Copyright 2017 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/src/hci_layer_linux.cc b/hci/src/hci_layer_linux.cc
index aa37f78..e32b5ef 100644
--- a/hci/src/hci_layer_linux.cc
+++ b/hci/src/hci_layer_linux.cc
@@ -1,7 +1,7 @@
/**********************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
- * Copyright (C) 2015 Intel Corporation
+ * Copyright 2017 The Android Open Source Project
+ * Copyright 2015 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hci/src/hci_packet_factory.cc b/hci/src/hci_packet_factory.cc
index c3c4a60..ca0fb5f 100644
--- a/hci/src/hci_packet_factory.cc
+++ b/hci/src/hci_packet_factory.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -142,6 +142,10 @@
return make_command_no_params(HCI_BLE_READ_DEFAULT_DATA_LENGTH);
}
+static BT_HDR* make_ble_read_maximum_data_length(void) {
+ return make_command_no_params(HCI_BLE_READ_MAXIMUM_DATA_LENGTH);
+}
+
static BT_HDR* make_ble_read_maximum_advertising_data_length(void) {
return make_command_no_params(HCI_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH);
}
@@ -212,6 +216,7 @@
make_ble_read_local_supported_features,
make_ble_read_resolving_list_size,
make_ble_read_suggested_default_data_length,
+ make_ble_read_maximum_data_length,
make_ble_read_maximum_advertising_data_length,
make_ble_read_number_of_supported_advertising_sets,
make_ble_set_event_mask,
diff --git a/hci/src/hci_packet_parser.cc b/hci/src/hci_packet_parser.cc
index e7ace27..b1efd44 100644
--- a/hci/src/hci_packet_parser.cc
+++ b/hci/src/hci_packet_parser.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -184,7 +184,23 @@
BT_HDR* response, uint16_t* ble_default_packet_length_ptr) {
uint8_t* stream = read_command_complete_header(
response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
- STREAM_TO_UINT8(*ble_default_packet_length_ptr, stream);
+ STREAM_TO_UINT16(*ble_default_packet_length_ptr, stream);
+
+ buffer_allocator->free(response);
+}
+
+static void parse_ble_read_maximum_data_length_response(
+ BT_HDR* response, uint16_t* ble_supported_max_tx_octets,
+ uint16_t* ble_supported_max_tx_time, uint16_t* ble_supported_max_rx_octets,
+ uint16_t* ble_supported_max_rx_time) {
+ uint8_t* stream = read_command_complete_header(
+ response, HCI_BLE_READ_MAXIMUM_DATA_LENGTH, 8 /* bytes after */);
+ STREAM_TO_UINT16(*ble_supported_max_tx_octets, stream);
+ STREAM_TO_UINT16(*ble_supported_max_tx_time, stream);
+ STREAM_TO_UINT16(*ble_supported_max_rx_octets, stream);
+ STREAM_TO_UINT16(*ble_supported_max_rx_time, stream);
+
+ buffer_allocator->free(response);
}
static void parse_ble_read_maximum_advertising_data_length(
@@ -262,6 +278,7 @@
parse_ble_read_local_supported_features_response,
parse_ble_read_resolving_list_size_response,
parse_ble_read_suggested_default_data_length_response,
+ parse_ble_read_maximum_data_length_response,
parse_ble_read_maximum_advertising_data_length,
parse_ble_read_number_of_supported_advertising_sets,
parse_read_local_supported_codecs_response};
diff --git a/hci/src/packet_fragmenter.cc b/hci/src/packet_fragmenter.cc
index 7ac4850..921ac82 100644
--- a/hci/src/packet_fragmenter.cc
+++ b/hci/src/packet_fragmenter.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,9 @@
#define HANDLE_MASK 0x0FFF
#define START_PACKET_BOUNDARY 2
#define CONTINUATION_PACKET_BOUNDARY 1
-#define L2CAP_HEADER_SIZE 4
+#define L2CAP_HEADER_PDU_LEN_SIZE 2
+#define L2CAP_HEADER_CID_SIZE 2
+#define L2CAP_HEADER_SIZE (L2CAP_HEADER_PDU_LEN_SIZE + L2CAP_HEADER_CID_SIZE)
// Our interface and callbacks
@@ -146,9 +148,9 @@
buffer_allocator->free(hdl);
}
- if (acl_length < L2CAP_HEADER_SIZE) {
+ if (acl_length < L2CAP_HEADER_PDU_LEN_SIZE) {
LOG_WARN(LOG_TAG, "%s L2CAP packet too small (%d < %d). Dropping it.",
- __func__, packet->len, L2CAP_HEADER_SIZE);
+ __func__, packet->len, L2CAP_HEADER_PDU_LEN_SIZE);
buffer_allocator->free(packet);
return;
}
diff --git a/hci/test/packet_fragmenter_test.cc b/hci/test/packet_fragmenter_test.cc
index 29c130d..483a66d 100644
--- a/hci/test/packet_fragmenter_test.cc
+++ b/hci/test/packet_fragmenter_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/include/Android.bp b/include/Android.bp
new file mode 100644
index 0000000..01a01b5
--- /dev/null
+++ b/include/Android.bp
@@ -0,0 +1,31 @@
+cc_library_headers {
+ name: "avrcp_headers",
+ defaults: ["libchrome_support_defaults"],
+ include_dirs: ["system/bt/internal_include"],
+ export_include_dirs: ["./hardware/avrcp/"],
+ header_libs: ["internal_include_headers"],
+ export_header_lib_headers: ["internal_include_headers"],
+
+ // We need this in case some file outside of the Bluetooth project includes
+ // bluetooth.h but doesn't include libchrome which avrcp.h depends on.
+ export_shared_lib_headers: ["libchrome"],
+
+ vendor_available: true,
+ host_supported: true,
+}
+
+cc_library_headers {
+ name: "libbluetooth_headers",
+ defaults: ["libchrome_support_defaults"],
+ header_libs: [
+ "avrcp_headers",
+ "libbluetooth-types-header",
+ ],
+ export_header_lib_headers: [
+ "avrcp_headers",
+ "libbluetooth-types-header",
+ ],
+ export_include_dirs: ["./"],
+ vendor_available: true,
+ host_supported: true,
+}
diff --git a/include/hardware/avrcp/avrcp.h b/include/hardware/avrcp/avrcp.h
new file mode 100644
index 0000000..8adba47
--- /dev/null
+++ b/include/hardware/avrcp/avrcp.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <set>
+#include <string>
+
+#include <base/bind.h>
+
+#include "avrcp_common.h"
+#include "raw_address.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+struct SongInfo {
+ std::string media_id; // This gets converted to a UID in the native service
+ std::set<AttributeEntry> attributes;
+};
+
+enum PlayState : uint8_t {
+ STOPPED = 0x00,
+ PLAYING,
+ PAUSED,
+ FWD_SEEK,
+ REV_SEEK,
+ ERROR = 0xFF,
+};
+
+struct PlayStatus {
+ uint32_t position;
+ uint32_t duration;
+ PlayState state;
+};
+
+struct MediaPlayerInfo {
+ uint16_t id;
+ std::string name;
+ bool browsing_supported;
+};
+
+struct FolderInfo {
+ std::string media_id;
+ bool is_playable;
+ std::string name;
+};
+
+// TODO (apanicke): Convert this to a union
+struct ListItem {
+ enum : uint8_t {
+ FOLDER,
+ SONG,
+ } type;
+
+ FolderInfo folder;
+ SongInfo song;
+};
+
+class MediaCallbacks {
+ public:
+ virtual void SendMediaUpdate(bool track_changed, bool play_state, bool queue);
+ virtual void SendFolderUpdate(bool available_players, bool addressed_players,
+ bool uids_changed);
+ virtual void SendActiveDeviceChanged(const RawAddress& address);
+ virtual ~MediaCallbacks() = default;
+};
+
+// The classes below are used by the JNI and are loaded dynamically with the
+// Bluetooth library. All classes must be pure virtual otherwise a compiler
+// error occurs when trying to link the function implementation.
+
+// MediaInterface defines the class that the AVRCP Service uses in order
+// communicate with the media layer. The media layer will define its own
+// implementation of this object and register it with the service using
+// Avrcp::ServiceInterface::Init(). At this point the AVRCP Service will
+// call RegisterUpdateCallbacks() to provide an handle to use to send
+// notifications about changes in the Media Interface.
+//
+// NOTES: The current implementation has the native service handle all the
+// thread switching. It will call the interface functions on the btif/jni
+// thread and the callback will post its results to the bta thread.
+// In the future the interface the JNI registered with the
+// service should post all its tasks to the JNI thread itself so that the native
+// service isn't aware of the thread the interface functions need to be called
+// on. It can then supply callbacks that post results to the correct thread
+// allowing the threading model to be totally encapsulated and allow correct
+// behavior in case the threading model changes on either side.
+class MediaInterface {
+ public:
+ virtual void SendKeyEvent(uint8_t key, KeyState state) = 0;
+
+ using SongInfoCallback = base::Callback<void(SongInfo)>;
+ virtual void GetSongInfo(SongInfoCallback info_cb) = 0;
+
+ using PlayStatusCallback = base::Callback<void(PlayStatus)>;
+ virtual void GetPlayStatus(PlayStatusCallback status_cb) = 0;
+
+ // Contains the current queue and the media ID of the currently playing item
+ // in the queue
+ using NowPlayingCallback =
+ base::Callback<void(std::string, std::vector<SongInfo>)>;
+ virtual void GetNowPlayingList(NowPlayingCallback now_playing_cb) = 0;
+
+ // TODO (apanicke): Use a map with the ID as the key instead of vector
+ // in follow up cleanup patches. This allows simplification of the
+ // MediaPlayerInfo object
+ using MediaListCallback =
+ base::Callback<void(uint16_t curr_player, std::vector<MediaPlayerInfo>)>;
+ virtual void GetMediaPlayerList(MediaListCallback list_cb) = 0;
+
+ using FolderItemsCallback = base::Callback<void(std::vector<ListItem>)>;
+ virtual void GetFolderItems(uint16_t player_id, std::string media_id,
+ FolderItemsCallback folder_cb) = 0;
+
+ using SetBrowsedPlayerCallback = base::Callback<void(
+ bool success, std::string root_id, uint32_t num_items)>;
+ virtual void SetBrowsedPlayer(uint16_t player_id,
+ SetBrowsedPlayerCallback browse_cb) = 0;
+
+ virtual void PlayItem(uint16_t player_id, bool now_playing,
+ std::string media_id) = 0;
+
+ virtual void SetActiveDevice(const RawAddress& address) = 0;
+
+ virtual void RegisterUpdateCallback(MediaCallbacks* callback) = 0;
+
+ virtual void UnregisterUpdateCallback(MediaCallbacks* callback) = 0;
+
+ MediaInterface() = default;
+ virtual ~MediaInterface() = default;
+};
+
+class VolumeInterface {
+ public:
+ // TODO (apanicke): Investigate the best value type for volume. Right now it
+ // is a value from 0-127 because thats what AVRCP uses.
+ using VolumeChangedCb = base::Callback<void(int8_t volume)>;
+
+ // Indicate that a device has been connected that does not support absolute
+ // volume.
+ virtual void DeviceConnected(const RawAddress& bdaddr) = 0;
+
+ // Indicate that a device has been connected that does support absolute
+ // volume. The callback will be immediately called with the current volume
+ // which will be sent to the device.
+ virtual void DeviceConnected(const RawAddress& bdaddr,
+ VolumeChangedCb cb) = 0;
+
+ // Indicate that a device has been disconnected from AVRCP. Will unregister
+ // any callbacks if absolute volume is supported.
+ virtual void DeviceDisconnected(const RawAddress& bdaddr) = 0;
+
+ virtual void SetVolume(int8_t volume) = 0;
+
+ virtual ~VolumeInterface() = default;
+};
+
+class ServiceInterface {
+ public:
+ // mediaInterface can not be null. If volumeInterface is null then Absolute
+ // Volume is disabled.
+ virtual void Init(MediaInterface* mediaInterface,
+ VolumeInterface* volumeInterface) = 0;
+ virtual bool ConnectDevice(const RawAddress& bdaddr) = 0;
+ virtual bool DisconnectDevice(const RawAddress& bdaddr) = 0;
+ virtual bool Cleanup() = 0;
+
+ protected:
+ virtual ~ServiceInterface() = default;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/include/hardware/avrcp/avrcp_common.h b/include/hardware/avrcp/avrcp_common.h
new file mode 100644
index 0000000..702f95d
--- /dev/null
+++ b/include/hardware/avrcp/avrcp_common.h
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <set>
+
+#include <base/sys_byteorder.h>
+
+namespace bluetooth {
+namespace avrcp {
+
+constexpr uint32_t BLUETOOTH_COMPANY_ID = 0x001958;
+
+constexpr uint8_t MAX_TRANSACTION_LABEL = 0xF;
+
+enum class CType : uint8_t {
+ CONTROL = 0x0,
+ STATUS = 0x1,
+ NOTIFY = 0x3,
+ NOT_IMPLEMENTED = 0x8,
+ ACCEPTED = 0x9,
+ REJECTED = 0xa,
+ STABLE = 0xc,
+ CHANGED = 0xd,
+ INTERIM = 0xf,
+};
+
+enum class Opcode : uint8_t {
+ VENDOR = 0x00,
+ UNIT_INFO = 0x30,
+ SUBUNIT_INFO = 0x31,
+ PASS_THROUGH = 0x7c,
+};
+
+// Found in AVRCP_v1.6.1 Section 4.5 Table 4.5
+// Searching can be done in the spec by Camel Casing the constant name
+enum class CommandPdu : uint8_t {
+ GET_CAPABILITIES = 0x10,
+ LIST_APPLICATION_SETTING_ATTRIBUTES = 0x11,
+ GET_ELEMENT_ATTRIBUTES = 0x20,
+ GET_PLAY_STATUS = 0x30,
+ REGISTER_NOTIFICATION = 0x31,
+ SET_ABSOLUTE_VOLUME = 0x50,
+ SET_ADDRESSED_PLAYER = 0x60,
+ PLAY_ITEM = 0x74,
+};
+
+enum class PacketType : uint8_t {
+ SINGLE = 0x00,
+};
+
+enum class Capability : uint8_t {
+ COMPANY_ID = 0x02,
+ EVENTS_SUPPORTED = 0x03,
+};
+
+// Found in AVRCP_v1.6.1 Section 28 Appendix H
+enum class Event : uint8_t {
+ PLAYBACK_STATUS_CHANGED = 0x01,
+ TRACK_CHANGED = 0x02,
+ PLAYBACK_POS_CHANGED = 0x05,
+ PLAYER_APPLICATION_SETTING_CHANGED = 0x08,
+ NOW_PLAYING_CONTENT_CHANGED = 0x09,
+ AVAILABLE_PLAYERS_CHANGED = 0x0a,
+ ADDRESSED_PLAYER_CHANGED = 0x0b,
+ UIDS_CHANGED = 0x0c,
+ VOLUME_CHANGED = 0x0d,
+};
+
+enum class Attribute : uint32_t {
+ TITLE = 0x01,
+ ARTIST_NAME = 0x02,
+ ALBUM_NAME = 0x03,
+ TRACK_NUMBER = 0x04,
+ TOTAL_NUMBER_OF_TRACKS = 0x05,
+ GENRE = 0x06,
+ PLAYING_TIME = 0x07,
+ DEFAULT_COVER_ART = 0x08,
+};
+
+enum class Status : uint8_t {
+ INVALID_COMMAND = 0x00,
+ INVALID_PARAMETER = 0x01,
+ PARAMETER_CONTENT_ERROR = 0x02,
+ INTERNAL_ERROR = 0x03,
+ NO_ERROR = 0x04,
+ UIDS_CHANGED = 0x05,
+ RESERVED = 0x06,
+ INVALID_DIRECTION = 0x07,
+ NOT_A_DIRECTORY = 0x08,
+ DOES_NOT_EXIST = 0x09,
+ INVALID_SCOPE = 0x0a,
+ RANGE_OUT_OF_BOUNDS = 0xb,
+ FOLDER_ITEM_NOT_PLAYABLE = 0x0c,
+ MEDIA_IN_USE = 0x0d,
+ NOW_PLAYING_LIST_FULL = 0x0e,
+ SEARCH_NOT_SUPPORTED = 0x0f,
+ SEARCH_IN_PROGRESS = 0x10,
+ INVALID_PLAYER_ID = 0x11,
+ PLAYER_NOT_BROWSABLE = 0x12,
+ PLAYER_NOT_ADDRESSED = 0x13,
+ NO_VALID_SEARCH_RESULTS = 0x14,
+ NO_AVAILABLE_PLAYERS = 0x15,
+ ADDRESSED_PLAYER_CHANGED = 0x16,
+};
+
+enum class BrowsePdu : uint8_t {
+ SET_BROWSED_PLAYER = 0x70,
+ GET_FOLDER_ITEMS = 0x71,
+ CHANGE_PATH = 0x72,
+ GET_ITEM_ATTRIBUTES = 0x73,
+ GET_TOTAL_NUMBER_OF_ITEMS = 0x75,
+ GENERAL_REJECT = 0xa0,
+};
+
+enum class Scope : uint8_t {
+ MEDIA_PLAYER_LIST = 0x00,
+ VFS = 0x01,
+ SEARCH = 0x02,
+ NOW_PLAYING = 0x03,
+};
+
+enum class Direction : uint8_t {
+ UP = 0x00,
+ DOWN = 0x01,
+};
+
+enum class KeyState : uint8_t {
+ PUSHED = 0x00,
+ RELEASED = 0x01,
+};
+
+class AttributeEntry {
+ public:
+ AttributeEntry(const Attribute& attribute, const std::string& value)
+ : attribute_(attribute), value_(value) {}
+
+ AttributeEntry(const Attribute& attribute) : attribute_(attribute) {}
+
+ AttributeEntry(const AttributeEntry&) = default;
+
+ Attribute attribute() const { return attribute_; }
+
+ std::string value() const { return value_; }
+
+ static constexpr size_t kHeaderSize() {
+ size_t ret = 0;
+ ret += 4; // Size of attribute field
+ ret += 2; // Size of length field
+ ret += 2; // Size of character encoding field
+ return ret;
+ }
+
+ size_t size() const { return kHeaderSize() + value_.size(); }
+
+ void resize(size_t new_size) {
+ new_size = new_size < kHeaderSize() ? 0 : new_size - kHeaderSize();
+ if (value_.size() > new_size) {
+ value_.resize(new_size);
+ }
+ }
+
+ bool empty() { return value_.empty(); }
+
+ bool operator<(const AttributeEntry& rhs) const {
+ return attribute_ < rhs.attribute_;
+ }
+
+ private:
+ Attribute attribute_;
+ std::string value_;
+};
+
+constexpr size_t MAX_FIELD_LEN = 100;
+
+struct MediaPlayerItem {
+ uint16_t id_;
+ std::string name_;
+ bool browsable_;
+
+ MediaPlayerItem(uint16_t id, const std::string& name, bool browsable)
+ : id_(id), name_(name), browsable_(browsable) {
+ if (name_.size() > MAX_FIELD_LEN) {
+ name_.resize(MAX_FIELD_LEN);
+ }
+ }
+
+ MediaPlayerItem(const MediaPlayerItem&) = default;
+
+ static constexpr size_t kHeaderSize() {
+ size_t ret = 0;
+ ret += 1; // Media Player Type
+ ret += 2; // Item Length
+ ret += 2; // Player Id
+ ret += 1; // Player Type
+ ret += 4; // Player Subtype
+ ret += 1; // Play Status
+ ret += 16; // Features
+ ret += 2; // UTF-8 character set
+ ret += 2; // Name Length
+ return ret;
+ }
+
+ size_t size() const { return kHeaderSize() + name_.size(); }
+};
+
+struct FolderItem {
+ uint64_t uid_;
+ uint8_t folder_type_;
+ bool is_playable_;
+ std::string name_;
+
+ FolderItem(uint64_t uid, uint8_t folder_type, bool is_playable,
+ const std::string& name)
+ : uid_(uid),
+ folder_type_(folder_type),
+ is_playable_(is_playable),
+ name_(name) {
+ if (name_.size() > MAX_FIELD_LEN) {
+ name_.resize(MAX_FIELD_LEN);
+ }
+ }
+
+ FolderItem(const FolderItem&) = default;
+
+ static constexpr size_t kHeaderSize() {
+ size_t ret = 0;
+ ret += 1; // Folder Item Type
+ ret += 2; // Item Length
+ ret += 8; // Folder UID
+ ret += 1; // Folder Type
+ ret += 1; // Is Playable byte
+ ret += 2; // UTF-8 Character Set
+ ret += 2; // Name Length
+ return ret;
+ }
+
+ size_t size() const { return kHeaderSize() + name_.size(); }
+};
+
+// NOTE: We never use media type field because we only support audio types
+struct MediaElementItem {
+ uint64_t uid_ = 0;
+ std::string name_;
+ std::set<AttributeEntry> attributes_;
+
+ // Truncate the name and attribute fields so that we don't have a single item
+ // that can exceed the Browsing MTU
+ MediaElementItem(uint64_t uid, const std::string& name,
+ std::set<AttributeEntry> attributes)
+ : uid_(uid), name_(name) {
+ if (name_.size() > MAX_FIELD_LEN) {
+ name_.resize(MAX_FIELD_LEN);
+ }
+
+ for (AttributeEntry val : attributes) {
+ val.resize(MAX_FIELD_LEN);
+ attributes_.insert(val);
+ }
+ }
+
+ MediaElementItem(const MediaElementItem&) = default;
+
+ size_t size() const {
+ size_t ret = 0;
+ ret += 1; // Media Element Item Type
+ ret += 2; // Item Length
+ ret += 8; // Item UID
+ ret += 1; // Media Type
+ ret += 2; // UTF-8 Character Set
+ ret += 2; // Name Length
+ ret += name_.size();
+ ret += 1; // Number of Attributes
+ for (const auto& entry : attributes_) {
+ ret += entry.size();
+ }
+
+ return ret;
+ }
+};
+
+struct MediaListItem {
+ enum : uint8_t { PLAYER = 0x01, FOLDER = 0x02, SONG = 0x03 } type_;
+
+ union {
+ MediaPlayerItem player_;
+ FolderItem folder_;
+ MediaElementItem song_;
+ };
+
+ MediaListItem(MediaPlayerItem item) : type_(PLAYER), player_(item) {}
+
+ MediaListItem(FolderItem item) : type_(FOLDER), folder_(item) {}
+
+ MediaListItem(MediaElementItem item) : type_(SONG), song_(item) {}
+
+ MediaListItem(const MediaListItem& item) {
+ type_ = item.type_;
+ switch (item.type_) {
+ case PLAYER:
+ new (&player_) MediaPlayerItem(item.player_);
+ return;
+ case FOLDER:
+ new (&folder_) FolderItem(item.folder_);
+ return;
+ case SONG:
+ new (&song_) MediaElementItem(item.song_);
+ return;
+ }
+ }
+
+ ~MediaListItem() {
+ switch (type_) {
+ case PLAYER:
+ player_.~MediaPlayerItem();
+ return;
+ case FOLDER:
+ folder_.~FolderItem();
+ return;
+ case SONG:
+ song_.~MediaElementItem();
+ return;
+ }
+ }
+
+ size_t size() const {
+ switch (type_) {
+ case PLAYER:
+ return player_.size();
+ case FOLDER:
+ return folder_.size();
+ case SONG:
+ return song_.size();
+ }
+ }
+};
+
+constexpr size_t AVCT_HDR_LEN = 3;
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/include/hardware/avrcp/avrcp_logging_helper.h b/include/hardware/avrcp/avrcp_logging_helper.h
new file mode 100644
index 0000000..ce95337
--- /dev/null
+++ b/include/hardware/avrcp/avrcp_logging_helper.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#include "avrcp_common.h"
+#include "bt_trace.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+#define CASE_RETURN_TEXT(code) \
+ case code: \
+ return #code
+
+inline std::string CTypeText(const CType& type) {
+ switch (type) {
+ CASE_RETURN_TEXT(CType::CONTROL);
+ CASE_RETURN_TEXT(CType::STATUS);
+ CASE_RETURN_TEXT(CType::NOTIFY);
+ CASE_RETURN_TEXT(CType::ACCEPTED);
+ CASE_RETURN_TEXT(CType::REJECTED);
+ CASE_RETURN_TEXT(CType::STABLE);
+ CASE_RETURN_TEXT(CType::CHANGED);
+ CASE_RETURN_TEXT(CType::INTERIM);
+ default:
+ return "Unknown CType: " + loghex((uint8_t)type);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const CType& type) {
+ return os << CTypeText(type);
+}
+
+inline std::string OpcodeText(const Opcode& opcode) {
+ switch (opcode) {
+ CASE_RETURN_TEXT(Opcode::VENDOR);
+ CASE_RETURN_TEXT(Opcode::UNIT_INFO);
+ CASE_RETURN_TEXT(Opcode::SUBUNIT_INFO);
+ CASE_RETURN_TEXT(Opcode::PASS_THROUGH);
+ default:
+ return "Unknown Opcode: " + loghex((uint8_t)opcode);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const Opcode& opcode) {
+ return os << OpcodeText(opcode);
+}
+
+inline std::string CommandPduText(const CommandPdu& pdu) {
+ switch (pdu) {
+ CASE_RETURN_TEXT(CommandPdu::GET_CAPABILITIES);
+ CASE_RETURN_TEXT(CommandPdu::LIST_APPLICATION_SETTING_ATTRIBUTES);
+ CASE_RETURN_TEXT(CommandPdu::GET_ELEMENT_ATTRIBUTES);
+ CASE_RETURN_TEXT(CommandPdu::GET_PLAY_STATUS);
+ CASE_RETURN_TEXT(CommandPdu::REGISTER_NOTIFICATION);
+ CASE_RETURN_TEXT(CommandPdu::SET_ABSOLUTE_VOLUME);
+ CASE_RETURN_TEXT(CommandPdu::SET_ADDRESSED_PLAYER);
+ CASE_RETURN_TEXT(CommandPdu::PLAY_ITEM);
+ default:
+ return "Unknown Command PDU: " + loghex((uint8_t)pdu);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const CommandPdu& pdu) {
+ return os << CommandPduText(pdu);
+}
+
+inline std::string PacketTypeText(const PacketType& type) {
+ switch (type) {
+ CASE_RETURN_TEXT(PacketType::SINGLE);
+ default:
+ return "Unknown Packet Type: " + loghex((uint8_t)type);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const PacketType& type) {
+ return os << PacketTypeText(type);
+}
+
+inline std::string CapabilityText(const Capability& cap) {
+ switch (cap) {
+ CASE_RETURN_TEXT(Capability::COMPANY_ID);
+ CASE_RETURN_TEXT(Capability::EVENTS_SUPPORTED);
+ default:
+ return "Unknown Capability: " + loghex((uint8_t)cap);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const Capability& cap) {
+ return os << CapabilityText(cap);
+}
+
+inline std::string EventText(const Event& event) {
+ switch (event) {
+ CASE_RETURN_TEXT(Event::PLAYBACK_STATUS_CHANGED);
+ CASE_RETURN_TEXT(Event::TRACK_CHANGED);
+ CASE_RETURN_TEXT(Event::PLAYBACK_POS_CHANGED);
+ CASE_RETURN_TEXT(Event::PLAYER_APPLICATION_SETTING_CHANGED);
+ CASE_RETURN_TEXT(Event::NOW_PLAYING_CONTENT_CHANGED);
+ CASE_RETURN_TEXT(Event::AVAILABLE_PLAYERS_CHANGED);
+ CASE_RETURN_TEXT(Event::ADDRESSED_PLAYER_CHANGED);
+ CASE_RETURN_TEXT(Event::UIDS_CHANGED);
+ CASE_RETURN_TEXT(Event::VOLUME_CHANGED);
+ default:
+ return "Unknown Event: " + loghex((uint8_t)event);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const Event& event) {
+ return os << EventText(event);
+}
+
+inline std::string AttributeText(const Attribute& attr) {
+ switch (attr) {
+ CASE_RETURN_TEXT(Attribute::TITLE);
+ CASE_RETURN_TEXT(Attribute::ARTIST_NAME);
+ CASE_RETURN_TEXT(Attribute::ALBUM_NAME);
+ CASE_RETURN_TEXT(Attribute::TRACK_NUMBER);
+ CASE_RETURN_TEXT(Attribute::TOTAL_NUMBER_OF_TRACKS);
+ CASE_RETURN_TEXT(Attribute::GENRE);
+ CASE_RETURN_TEXT(Attribute::PLAYING_TIME);
+ CASE_RETURN_TEXT(Attribute::DEFAULT_COVER_ART);
+ default:
+ return "Unknown Attribute Value: " + loghex((uint32_t)attr);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const Attribute& attr) {
+ return os << AttributeText(attr);
+}
+
+inline std::string StatusText(const Status& status) {
+ switch (status) {
+ CASE_RETURN_TEXT(Status::INVALID_COMMAND);
+ CASE_RETURN_TEXT(Status::INVALID_PARAMETER);
+ CASE_RETURN_TEXT(Status::PARAMETER_CONTENT_ERROR);
+ CASE_RETURN_TEXT(Status::INTERNAL_ERROR);
+ CASE_RETURN_TEXT(Status::NO_ERROR);
+ CASE_RETURN_TEXT(Status::UIDS_CHANGED);
+ CASE_RETURN_TEXT(Status::RESERVED);
+ CASE_RETURN_TEXT(Status::INVALID_DIRECTION);
+ CASE_RETURN_TEXT(Status::NOT_A_DIRECTORY);
+ CASE_RETURN_TEXT(Status::DOES_NOT_EXIST);
+ CASE_RETURN_TEXT(Status::INVALID_SCOPE);
+ CASE_RETURN_TEXT(Status::RANGE_OUT_OF_BOUNDS);
+ CASE_RETURN_TEXT(Status::FOLDER_ITEM_NOT_PLAYABLE);
+ CASE_RETURN_TEXT(Status::MEDIA_IN_USE);
+ CASE_RETURN_TEXT(Status::NOW_PLAYING_LIST_FULL);
+ CASE_RETURN_TEXT(Status::SEARCH_NOT_SUPPORTED);
+ CASE_RETURN_TEXT(Status::SEARCH_IN_PROGRESS);
+ CASE_RETURN_TEXT(Status::INVALID_PLAYER_ID);
+ CASE_RETURN_TEXT(Status::PLAYER_NOT_BROWSABLE);
+ CASE_RETURN_TEXT(Status::PLAYER_NOT_ADDRESSED);
+ CASE_RETURN_TEXT(Status::NO_VALID_SEARCH_RESULTS);
+ CASE_RETURN_TEXT(Status::NO_AVAILABLE_PLAYERS);
+ CASE_RETURN_TEXT(Status::ADDRESSED_PLAYER_CHANGED);
+ default:
+ return "Unknown Status: " + loghex((uint8_t)status);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const Status& status) {
+ return os << StatusText(status);
+}
+
+inline std::string BrowsePduText(const BrowsePdu& pdu) {
+ switch (pdu) {
+ CASE_RETURN_TEXT(BrowsePdu::SET_BROWSED_PLAYER);
+ CASE_RETURN_TEXT(BrowsePdu::GET_FOLDER_ITEMS);
+ CASE_RETURN_TEXT(BrowsePdu::CHANGE_PATH);
+ CASE_RETURN_TEXT(BrowsePdu::GET_ITEM_ATTRIBUTES);
+ default:
+ return "Unknown Browse PDU: " + loghex((uint8_t)pdu);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const BrowsePdu& pdu) {
+ return os << BrowsePduText(pdu);
+}
+
+inline std::string ScopeText(const Scope& scope) {
+ switch (scope) {
+ CASE_RETURN_TEXT(Scope::MEDIA_PLAYER_LIST);
+ CASE_RETURN_TEXT(Scope::VFS);
+ CASE_RETURN_TEXT(Scope::SEARCH);
+ CASE_RETURN_TEXT(Scope::NOW_PLAYING);
+ default:
+ return "Unknown Scope: " + loghex((uint8_t)scope);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const Scope& pdu) {
+ return os << ScopeText(pdu);
+}
+
+inline std::string DirectionText(const Direction& dir) {
+ switch (dir) {
+ CASE_RETURN_TEXT(Direction::UP);
+ CASE_RETURN_TEXT(Direction::DOWN);
+ default:
+ return "Unknown Direction: " + loghex((uint8_t)dir);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const Direction& dir) {
+ return os << DirectionText(dir);
+}
+
+inline std::string KeyStateText(const KeyState& state) {
+ switch (state) {
+ CASE_RETURN_TEXT(KeyState::PUSHED);
+ CASE_RETURN_TEXT(KeyState::RELEASED);
+ default:
+ return "Unknown KeyState: " + loghex((uint8_t)state);
+ }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const KeyState& dir) {
+ return os << KeyStateText(dir);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/include/hardware/ble_advertiser.h b/include/hardware/ble_advertiser.h
new file mode 100644
index 0000000..6055d89
--- /dev/null
+++ b/include/hardware/ble_advertiser.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BLE_ADVERTISER_H
+#define ANDROID_INCLUDE_BLE_ADVERTISER_H
+
+#include <base/callback_forward.h>
+#include <stdint.h>
+#include <vector>
+#include "bt_common_types.h"
+#include "bt_gatt_types.h"
+
+struct AdvertiseParameters {
+ uint16_t advertising_event_properties;
+ uint32_t min_interval;
+ uint32_t max_interval;
+ uint8_t channel_map;
+ int8_t tx_power;
+ uint8_t primary_advertising_phy;
+ uint8_t secondary_advertising_phy;
+ uint8_t scan_request_notification_enable;
+};
+
+struct PeriodicAdvertisingParameters {
+ uint8_t enable;
+ uint16_t min_interval;
+ uint16_t max_interval;
+ uint16_t periodic_advertising_properties;
+};
+
+class BleAdvertiserInterface {
+ public:
+ virtual ~BleAdvertiserInterface() = default;
+
+ /** Callback invoked when multi-adv operation has completed */
+ using StatusCallback = base::Callback<void(uint8_t /* status */)>;
+ using IdStatusCallback =
+ base::Callback<void(uint8_t /* advertiser_id */, uint8_t /* status */)>;
+ using IdTxPowerStatusCallback =
+ base::Callback<void(uint8_t /* advertiser_id */, int8_t /* tx_power */,
+ uint8_t /* status */)>;
+ using ParametersCallback =
+ base::Callback<void(uint8_t /* status */, int8_t /* tx_power */)>;
+
+ /** Registers an advertiser with the stack */
+ virtual void RegisterAdvertiser(IdStatusCallback) = 0;
+
+ using GetAddressCallback =
+ base::Callback<void(uint8_t /* address_type*/, RawAddress /*address*/)>;
+ virtual void GetOwnAddress(uint8_t advertiser_id, GetAddressCallback cb) = 0;
+
+ /* Set the parameters as per spec, user manual specified values */
+ virtual void SetParameters(uint8_t advertiser_id, AdvertiseParameters params,
+ ParametersCallback cb) = 0;
+
+ /* Setup the data */
+ virtual void SetData(int advertiser_id, bool set_scan_rsp,
+ std::vector<uint8_t> data, StatusCallback cb) = 0;
+
+ /* Enable the advertising instance */
+ virtual void Enable(uint8_t advertiser_id, bool enable, StatusCallback cb,
+ uint16_t duration, uint8_t maxExtAdvEvents,
+ StatusCallback timeout_cb) = 0;
+
+ /* Unregisters an advertiser */
+ virtual void Unregister(uint8_t advertiser_id) = 0;
+
+ virtual void StartAdvertising(uint8_t advertiser_id, StatusCallback cb,
+ AdvertiseParameters params,
+ std::vector<uint8_t> advertise_data,
+ std::vector<uint8_t> scan_response_data,
+ int timeout_s, StatusCallback timeout_cb) = 0;
+
+ /** Start the advertising set. This include registering, setting all
+ * parameters and data, and enabling it. |register_cb| is called when the set
+ * is advertising. |timeout_cb| is called when the timeout_s have passed */
+ virtual void StartAdvertisingSet(
+ IdTxPowerStatusCallback register_cb, AdvertiseParameters params,
+ std::vector<uint8_t> advertise_data,
+ std::vector<uint8_t> scan_response_data,
+ PeriodicAdvertisingParameters periodic_params,
+ std::vector<uint8_t> periodic_data, uint16_t duration,
+ uint8_t maxExtAdvEvents, IdStatusCallback timeout_cb) = 0;
+
+ virtual void SetPeriodicAdvertisingParameters(
+ int advertiser_id, PeriodicAdvertisingParameters parameters,
+ StatusCallback cb) = 0;
+
+ virtual void SetPeriodicAdvertisingData(int advertiser_id,
+ std::vector<uint8_t> data,
+ StatusCallback cb) = 0;
+
+ virtual void SetPeriodicAdvertisingEnable(int advertiser_id, bool enable,
+ StatusCallback cb) = 0;
+};
+
+#endif /* ANDROID_INCLUDE_BLE_ADVERTISER_H */
diff --git a/include/hardware/ble_scanner.h b/include/hardware/ble_scanner.h
new file mode 100644
index 0000000..efa9662
--- /dev/null
+++ b/include/hardware/ble_scanner.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BLE_SCANNER_H
+#define ANDROID_INCLUDE_BLE_SCANNER_H
+
+#include <stdint.h>
+#include <vector>
+#include "bt_common_types.h"
+#include "bt_gatt_client.h"
+#include "bt_gatt_types.h"
+
+/** Callback invoked when batchscan reports are obtained */
+typedef void (*batchscan_reports_callback)(int client_if, int status,
+ int report_format, int num_records,
+ std::vector<uint8_t> data);
+
+/** Callback invoked when batchscan storage threshold limit is crossed */
+typedef void (*batchscan_threshold_callback)(int client_if);
+
+/** Track ADV VSE callback invoked when tracked device is found or lost */
+typedef void (*track_adv_event_callback)(
+ btgatt_track_adv_info_t* p_track_adv_info);
+
+/** Callback for scan results */
+typedef void (*scan_result_callback)(uint16_t event_type, uint8_t addr_type,
+ RawAddress* bda, uint8_t primary_phy,
+ uint8_t secondary_phy,
+ uint8_t advertising_sid, int8_t tx_power,
+ int8_t rssi, uint16_t periodic_adv_int,
+ std::vector<uint8_t> adv_data);
+
+typedef struct {
+ scan_result_callback scan_result_cb;
+ batchscan_reports_callback batchscan_reports_cb;
+ batchscan_threshold_callback batchscan_threshold_cb;
+ track_adv_event_callback track_adv_event_cb;
+} btgatt_scanner_callbacks_t;
+
+class BleScannerInterface {
+ public:
+ virtual ~BleScannerInterface() = default;
+
+ using RegisterCallback =
+ base::Callback<void(uint8_t /* scanner_id */, uint8_t /* status */)>;
+
+ using Callback = base::Callback<void(uint8_t /* status */)>;
+
+ using EnableCallback =
+ base::Callback<void(uint8_t /* action */, uint8_t /* status */)>;
+
+ using FilterParamSetupCallback =
+ base::Callback<void(uint8_t /* avbl_space */, uint8_t /* action_type */,
+ uint8_t /* status */)>;
+
+ using FilterConfigCallback =
+ base::Callback<void(uint8_t /* filt_type */, uint8_t /* avbl_space */,
+ uint8_t /* action */, uint8_t /* status */)>;
+
+ /** Registers a scanner with the stack */
+ virtual void RegisterScanner(RegisterCallback) = 0;
+
+ /** Unregister a scanner from the stack */
+ virtual void Unregister(int scanner_id) = 0;
+
+ /** Start or stop LE device scanning */
+ virtual void Scan(bool start) = 0;
+
+ /** Setup scan filter params */
+ virtual void ScanFilterParamSetup(
+ uint8_t client_if, uint8_t action, uint8_t filt_index,
+ std::unique_ptr<btgatt_filt_param_setup_t> filt_param,
+ FilterParamSetupCallback cb) = 0;
+
+ /** Configure a scan filter condition */
+ virtual void ScanFilterAdd(int filter_index, std::vector<ApcfCommand> filters,
+ FilterConfigCallback cb) = 0;
+
+ /** Clear all scan filter conditions for specific filter index*/
+ virtual void ScanFilterClear(int filt_index, FilterConfigCallback cb) = 0;
+
+ /** Enable / disable scan filter feature*/
+ virtual void ScanFilterEnable(bool enable, EnableCallback cb) = 0;
+
+ /** Sets the LE scan interval and window in units of N*0.625 msec */
+ virtual void SetScanParameters(int scan_interval, int scan_window,
+ Callback cb) = 0;
+
+ /* Configure the batchscan storage */
+ virtual void BatchscanConfigStorage(int client_if, int batch_scan_full_max,
+ int batch_scan_trunc_max,
+ int batch_scan_notify_threshold,
+ Callback cb) = 0;
+
+ /* Enable batchscan */
+ virtual void BatchscanEnable(int scan_mode, int scan_interval,
+ int scan_window, int addr_type, int discard_rule,
+ Callback cb) = 0;
+
+ /* Disable batchscan */
+ virtual void BatchscanDisable(Callback cb) = 0;
+
+ /* Read out batchscan reports */
+ virtual void BatchscanReadReports(int client_if, int scan_mode) = 0;
+
+ using StartSyncCb =
+ base::Callback<void(uint8_t status, uint16_t sync_handle,
+ uint8_t advertising_sid, uint8_t address_type,
+ RawAddress address, uint8_t phy, uint16_t interval)>;
+ using SyncReportCb =
+ base::Callback<void(uint16_t sync_handle, int8_t tx_power, int8_t rssi,
+ uint8_t status, std::vector<uint8_t> data)>;
+ using SyncLostCb = base::Callback<void(uint16_t sync_handle)>;
+ virtual void StartSync(uint8_t sid, RawAddress address, uint16_t skip,
+ uint16_t timeout, StartSyncCb start_cb,
+ SyncReportCb report_cb, SyncLostCb lost_cb) = 0;
+ virtual void StopSync(uint16_t handle) = 0;
+};
+
+#endif /* ANDROID_INCLUDE_BLE_SCANNER_H */
\ No newline at end of file
diff --git a/include/hardware/bluetooth.h b/include/hardware/bluetooth.h
new file mode 100644
index 0000000..36680bf
--- /dev/null
+++ b/include/hardware/bluetooth.h
@@ -0,0 +1,597 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BLUETOOTH_H
+#define ANDROID_INCLUDE_BLUETOOTH_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "avrcp/avrcp.h"
+#include "bluetooth/uuid.h"
+#include "raw_address.h"
+
+/**
+ * The Bluetooth Hardware Module ID
+ */
+
+#define BT_HARDWARE_MODULE_ID "bluetooth"
+#define BT_STACK_MODULE_ID "bluetooth"
+
+/** Bluetooth profile interface IDs */
+#define BT_PROFILE_HANDSFREE_ID "handsfree"
+#define BT_PROFILE_HANDSFREE_CLIENT_ID "handsfree_client"
+#define BT_PROFILE_ADVANCED_AUDIO_ID "a2dp"
+#define BT_PROFILE_ADVANCED_AUDIO_SINK_ID "a2dp_sink"
+#define BT_PROFILE_HEALTH_ID "health"
+#define BT_PROFILE_SOCKETS_ID "socket"
+#define BT_PROFILE_HIDHOST_ID "hidhost"
+#define BT_PROFILE_HIDDEV_ID "hiddev"
+#define BT_PROFILE_PAN_ID "pan"
+#define BT_PROFILE_MAP_CLIENT_ID "map_client"
+#define BT_PROFILE_SDP_CLIENT_ID "sdp"
+#define BT_PROFILE_GATT_ID "gatt"
+#define BT_PROFILE_AV_RC_ID "avrcp"
+#define BT_PROFILE_AV_RC_CTRL_ID "avrcp_ctrl"
+#define BT_PROFILE_HEARING_AID_ID "hearing_aid"
+
+/** Bluetooth test interface IDs */
+#define BT_TEST_INTERFACE_MCAP_ID "mcap_test"
+
+/** Bluetooth Device Name */
+typedef struct { uint8_t name[249]; } __attribute__((packed)) bt_bdname_t;
+
+/** Bluetooth Adapter Visibility Modes*/
+typedef enum {
+ BT_SCAN_MODE_NONE,
+ BT_SCAN_MODE_CONNECTABLE,
+ BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE
+} bt_scan_mode_t;
+
+/** Bluetooth Adapter State */
+typedef enum { BT_STATE_OFF, BT_STATE_ON } bt_state_t;
+
+/** Bluetooth Error Status */
+/** We need to build on this */
+
+typedef enum {
+ BT_STATUS_SUCCESS,
+ BT_STATUS_FAIL,
+ BT_STATUS_NOT_READY,
+ BT_STATUS_NOMEM,
+ BT_STATUS_BUSY,
+ BT_STATUS_DONE, /* request already completed */
+ BT_STATUS_UNSUPPORTED,
+ BT_STATUS_PARM_INVALID,
+ BT_STATUS_UNHANDLED,
+ BT_STATUS_AUTH_FAILURE,
+ BT_STATUS_RMT_DEV_DOWN,
+ BT_STATUS_AUTH_REJECTED,
+ BT_STATUS_JNI_ENVIRONMENT_ERROR,
+ BT_STATUS_JNI_THREAD_ATTACH_ERROR,
+ BT_STATUS_WAKELOCK_ERROR
+} bt_status_t;
+
+/** Bluetooth PinKey Code */
+typedef struct { uint8_t pin[16]; } __attribute__((packed)) bt_pin_code_t;
+
+typedef struct {
+ uint8_t status;
+ uint8_t ctrl_state; /* stack reported state */
+ uint64_t tx_time; /* in ms */
+ uint64_t rx_time; /* in ms */
+ uint64_t idle_time; /* in ms */
+ uint64_t energy_used; /* a product of mA, V and ms */
+} __attribute__((packed)) bt_activity_energy_info;
+
+typedef struct {
+ int32_t app_uid;
+ uint64_t tx_bytes;
+ uint64_t rx_bytes;
+} __attribute__((packed)) bt_uid_traffic_t;
+
+/** Bluetooth Adapter Discovery state */
+typedef enum {
+ BT_DISCOVERY_STOPPED,
+ BT_DISCOVERY_STARTED
+} bt_discovery_state_t;
+
+/** Bluetooth ACL connection state */
+typedef enum {
+ BT_ACL_STATE_CONNECTED,
+ BT_ACL_STATE_DISCONNECTED
+} bt_acl_state_t;
+
+/** Bluetooth SDP service record */
+typedef struct {
+ bluetooth::Uuid uuid;
+ uint16_t channel;
+ char name[256]; // what's the maximum length
+} bt_service_record_t;
+
+/** Bluetooth Remote Version info */
+typedef struct {
+ int version;
+ int sub_ver;
+ int manufacturer;
+} bt_remote_version_t;
+
+typedef struct {
+ uint16_t version_supported;
+ uint8_t local_privacy_enabled;
+ uint8_t max_adv_instance;
+ uint8_t rpa_offload_supported;
+ uint8_t max_irk_list_size;
+ uint8_t max_adv_filter_supported;
+ uint8_t activity_energy_info_supported;
+ uint16_t scan_result_storage_size;
+ uint16_t total_trackable_advertisers;
+ bool extended_scan_support;
+ bool debug_logging_supported;
+ bool le_2m_phy_supported;
+ bool le_coded_phy_supported;
+ bool le_extended_advertising_supported;
+ bool le_periodic_advertising_supported;
+ uint16_t le_maximum_advertising_data_length;
+} bt_local_le_features_t;
+
+/* Bluetooth Adapter and Remote Device property types */
+typedef enum {
+ /* Properties common to both adapter and remote device */
+ /**
+ * Description - Bluetooth Device Name
+ * Access mode - Adapter name can be GET/SET. Remote device can be GET
+ * Data type - bt_bdname_t
+ */
+ BT_PROPERTY_BDNAME = 0x1,
+ /**
+ * Description - Bluetooth Device Address
+ * Access mode - Only GET.
+ * Data type - RawAddress
+ */
+ BT_PROPERTY_BDADDR,
+ /**
+ * Description - Bluetooth Service 128-bit UUIDs
+ * Access mode - Only GET.
+ * Data type - Array of bluetooth::Uuid (Array size inferred from property
+ * length).
+ */
+ BT_PROPERTY_UUIDS,
+ /**
+ * Description - Bluetooth Class of Device as found in Assigned Numbers
+ * Access mode - Only GET.
+ * Data type - uint32_t.
+ */
+ BT_PROPERTY_CLASS_OF_DEVICE,
+ /**
+ * Description - Device Type - BREDR, BLE or DUAL Mode
+ * Access mode - Only GET.
+ * Data type - bt_device_type_t
+ */
+ BT_PROPERTY_TYPE_OF_DEVICE,
+ /**
+ * Description - Bluetooth Service Record
+ * Access mode - Only GET.
+ * Data type - bt_service_record_t
+ */
+ BT_PROPERTY_SERVICE_RECORD,
+
+ /* Properties unique to adapter */
+ /**
+ * Description - Bluetooth Adapter scan mode
+ * Access mode - GET and SET
+ * Data type - bt_scan_mode_t.
+ */
+ BT_PROPERTY_ADAPTER_SCAN_MODE,
+ /**
+ * Description - List of bonded devices
+ * Access mode - Only GET.
+ * Data type - Array of RawAddress of the bonded remote devices
+ * (Array size inferred from property length).
+ */
+ BT_PROPERTY_ADAPTER_BONDED_DEVICES,
+ /**
+ * Description - Bluetooth Adapter Discovery timeout (in seconds)
+ * Access mode - GET and SET
+ * Data type - uint32_t
+ */
+ BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+
+ /* Properties unique to remote device */
+ /**
+ * Description - User defined friendly name of the remote device
+ * Access mode - GET and SET
+ * Data type - bt_bdname_t.
+ */
+ BT_PROPERTY_REMOTE_FRIENDLY_NAME,
+ /**
+ * Description - RSSI value of the inquired remote device
+ * Access mode - Only GET.
+ * Data type - int8_t.
+ */
+ BT_PROPERTY_REMOTE_RSSI,
+ /**
+ * Description - Remote version info
+ * Access mode - SET/GET.
+ * Data type - bt_remote_version_t.
+ */
+
+ BT_PROPERTY_REMOTE_VERSION_INFO,
+
+ /**
+ * Description - Local LE features
+ * Access mode - GET.
+ * Data type - bt_local_le_features_t.
+ */
+ BT_PROPERTY_LOCAL_LE_FEATURES,
+
+ BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP = 0xFF,
+} bt_property_type_t;
+
+/** Bluetooth Adapter Property data structure */
+typedef struct {
+ bt_property_type_t type;
+ int len;
+ void* val;
+} bt_property_t;
+
+/** Bluetooth Out Of Band data for bonding */
+typedef struct {
+ uint8_t le_bt_dev_addr[7]; /* LE Bluetooth Device Address */
+ uint8_t c192[16]; /* Simple Pairing Hash C-192 */
+ uint8_t r192[16]; /* Simple Pairing Randomizer R-192 */
+ uint8_t c256[16]; /* Simple Pairing Hash C-256 */
+ uint8_t r256[16]; /* Simple Pairing Randomizer R-256 */
+ uint8_t sm_tk[16]; /* Security Manager TK Value */
+ uint8_t le_sc_c[16]; /* LE Secure Connections Confirmation Value */
+ uint8_t le_sc_r[16]; /* LE Secure Connections Random Value */
+} bt_out_of_band_data_t;
+
+/** Bluetooth Device Type */
+typedef enum {
+ BT_DEVICE_DEVTYPE_BREDR = 0x1,
+ BT_DEVICE_DEVTYPE_BLE,
+ BT_DEVICE_DEVTYPE_DUAL
+} bt_device_type_t;
+/** Bluetooth Bond state */
+typedef enum {
+ BT_BOND_STATE_NONE,
+ BT_BOND_STATE_BONDING,
+ BT_BOND_STATE_BONDED
+} bt_bond_state_t;
+
+/** Bluetooth SSP Bonding Variant */
+typedef enum {
+ BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
+ BT_SSP_VARIANT_PASSKEY_ENTRY,
+ BT_SSP_VARIANT_CONSENT,
+ BT_SSP_VARIANT_PASSKEY_NOTIFICATION
+} bt_ssp_variant_t;
+
+#define BT_MAX_NUM_UUIDS 32
+
+/** Bluetooth Interface callbacks */
+
+/** Bluetooth Enable/Disable Callback. */
+typedef void (*adapter_state_changed_callback)(bt_state_t state);
+
+/** GET/SET Adapter Properties callback */
+/* TODO: For the GET/SET property APIs/callbacks, we may need a session
+ * identifier to associate the call with the callback. This would be needed
+ * whenever more than one simultaneous instance of the same adapter_type
+ * is get/set.
+ *
+ * If this is going to be handled in the Java framework, then we do not need
+ * to manage sessions here.
+ */
+typedef void (*adapter_properties_callback)(bt_status_t status,
+ int num_properties,
+ bt_property_t* properties);
+
+/** GET/SET Remote Device Properties callback */
+/** TODO: For remote device properties, do not see a need to get/set
+ * multiple properties - num_properties shall be 1
+ */
+typedef void (*remote_device_properties_callback)(bt_status_t status,
+ RawAddress* bd_addr,
+ int num_properties,
+ bt_property_t* properties);
+
+/** New device discovered callback */
+/** If EIR data is not present, then BD_NAME and RSSI shall be NULL and -1
+ * respectively */
+typedef void (*device_found_callback)(int num_properties,
+ bt_property_t* properties);
+
+/** Discovery state changed callback */
+typedef void (*discovery_state_changed_callback)(bt_discovery_state_t state);
+
+/** Bluetooth Legacy PinKey Request callback */
+typedef void (*pin_request_callback)(RawAddress* remote_bd_addr,
+ bt_bdname_t* bd_name, uint32_t cod,
+ bool min_16_digit);
+
+/** Bluetooth SSP Request callback - Just Works & Numeric Comparison*/
+/** pass_key - Shall be 0 for BT_SSP_PAIRING_VARIANT_CONSENT &
+ * BT_SSP_PAIRING_PASSKEY_ENTRY */
+/* TODO: Passkey request callback shall not be needed for devices with display
+ * capability. We still need support this in the stack for completeness */
+typedef void (*ssp_request_callback)(RawAddress* remote_bd_addr,
+ bt_bdname_t* bd_name, uint32_t cod,
+ bt_ssp_variant_t pairing_variant,
+ uint32_t pass_key);
+
+/** Bluetooth Bond state changed callback */
+/* Invoked in response to create_bond, cancel_bond or remove_bond */
+typedef void (*bond_state_changed_callback)(bt_status_t status,
+ RawAddress* remote_bd_addr,
+ bt_bond_state_t state);
+
+/** Bluetooth ACL connection state changed callback */
+typedef void (*acl_state_changed_callback)(bt_status_t status,
+ RawAddress* remote_bd_addr,
+ bt_acl_state_t state);
+
+typedef enum { ASSOCIATE_JVM, DISASSOCIATE_JVM } bt_cb_thread_evt;
+
+/** Thread Associate/Disassociate JVM Callback */
+/* Callback that is invoked by the callback thread to allow upper layer to
+ * attach/detach to/from the JVM */
+typedef void (*callback_thread_event)(bt_cb_thread_evt evt);
+
+/** Bluetooth Test Mode Callback */
+/* Receive any HCI event from controller. Must be in DUT Mode for this callback
+ * to be received */
+typedef void (*dut_mode_recv_callback)(uint16_t opcode, uint8_t* buf,
+ uint8_t len);
+
+/* LE Test mode callbacks
+ * This callback shall be invoked whenever the le_tx_test, le_rx_test or
+ * le_test_end is invoked The num_packets is valid only for le_test_end command
+ */
+typedef void (*le_test_mode_callback)(bt_status_t status, uint16_t num_packets);
+
+/** Callback invoked when energy details are obtained */
+/* Ctrl_state-Current controller state-Active-1,scan-2,or idle-3 state as
+ * defined by HCI spec. If the ctrl_state value is 0, it means the API call
+ * failed Time values-In milliseconds as returned by the controller Energy
+ * used-Value as returned by the controller Status-Provides the status of the
+ * read_energy_info API call uid_data provides an array of bt_uid_traffic_t,
+ * where the array is terminated by an element with app_uid set to -1.
+ */
+typedef void (*energy_info_callback)(bt_activity_energy_info* energy_info,
+ bt_uid_traffic_t* uid_data);
+
+/** TODO: Add callbacks for Link Up/Down and other generic
+ * notifications/callbacks */
+
+/** Bluetooth DM callback structure. */
+typedef struct {
+ /** set to sizeof(bt_callbacks_t) */
+ size_t size;
+ adapter_state_changed_callback adapter_state_changed_cb;
+ adapter_properties_callback adapter_properties_cb;
+ remote_device_properties_callback remote_device_properties_cb;
+ device_found_callback device_found_cb;
+ discovery_state_changed_callback discovery_state_changed_cb;
+ pin_request_callback pin_request_cb;
+ ssp_request_callback ssp_request_cb;
+ bond_state_changed_callback bond_state_changed_cb;
+ acl_state_changed_callback acl_state_changed_cb;
+ callback_thread_event thread_evt_cb;
+ dut_mode_recv_callback dut_mode_recv_cb;
+ le_test_mode_callback le_test_mode_cb;
+ energy_info_callback energy_info_cb;
+} bt_callbacks_t;
+
+typedef void (*alarm_cb)(void* data);
+typedef bool (*set_wake_alarm_callout)(uint64_t delay_millis, bool should_wake,
+ alarm_cb cb, void* data);
+typedef int (*acquire_wake_lock_callout)(const char* lock_name);
+typedef int (*release_wake_lock_callout)(const char* lock_name);
+
+/** The set of functions required by bluedroid to set wake alarms and
+ * grab wake locks. This struct is passed into the stack through the
+ * |set_os_callouts| function on |bt_interface_t|.
+ */
+typedef struct {
+ /* set to sizeof(bt_os_callouts_t) */
+ size_t size;
+
+ set_wake_alarm_callout set_wake_alarm;
+ acquire_wake_lock_callout acquire_wake_lock;
+ release_wake_lock_callout release_wake_lock;
+} bt_os_callouts_t;
+
+/** NOTE: By default, no profiles are initialized at the time of init/enable.
+ * Whenever the application invokes the 'init' API of a profile, then one of
+ * the following shall occur:
+ *
+ * 1.) If Bluetooth is not enabled, then the Bluetooth core shall mark the
+ * profile as enabled. Subsequently, when the application invokes the
+ * Bluetooth 'enable', as part of the enable sequence the profile that
+ * were marked shall be enabled by calling appropriate stack APIs. The
+ * 'adapter_properties_cb' shall return the list of UUIDs of the
+ * enabled profiles.
+ *
+ * 2.) If Bluetooth is enabled, then the Bluetooth core shall invoke the
+ * stack profile API to initialize the profile and trigger a
+ * 'adapter_properties_cb' with the current list of UUIDs including the
+ * newly added profile's UUID.
+ *
+ * The reverse shall occur whenever the profile 'cleanup' APIs are invoked
+ */
+
+/** Represents the standard Bluetooth DM interface. */
+typedef struct {
+ /** set to sizeof(bt_interface_t) */
+ size_t size;
+ /**
+ * Opens the interface and provides the callback routines
+ * to the implemenation of this interface.
+ */
+ int (*init)(bt_callbacks_t* callbacks);
+
+ /** Enable Bluetooth. */
+ int (*enable)(bool guest_mode);
+
+ /** Disable Bluetooth. */
+ int (*disable)(void);
+
+ /** Closes the interface. */
+ void (*cleanup)(void);
+
+ /** Get all Bluetooth Adapter properties at init */
+ int (*get_adapter_properties)(void);
+
+ /** Get Bluetooth Adapter property of 'type' */
+ int (*get_adapter_property)(bt_property_type_t type);
+
+ /** Set Bluetooth Adapter property of 'type' */
+ /* Based on the type, val shall be one of
+ * RawAddress or bt_bdname_t or bt_scanmode_t etc
+ */
+ int (*set_adapter_property)(const bt_property_t* property);
+
+ /** Get all Remote Device properties */
+ int (*get_remote_device_properties)(RawAddress* remote_addr);
+
+ /** Get Remote Device property of 'type' */
+ int (*get_remote_device_property)(RawAddress* remote_addr,
+ bt_property_type_t type);
+
+ /** Set Remote Device property of 'type' */
+ int (*set_remote_device_property)(RawAddress* remote_addr,
+ const bt_property_t* property);
+
+ /** Get Remote Device's service record for the given UUID */
+ int (*get_remote_service_record)(const RawAddress& remote_addr,
+ const bluetooth::Uuid& uuid);
+
+ /** Start SDP to get remote services */
+ int (*get_remote_services)(RawAddress* remote_addr);
+
+ /** Start Discovery */
+ int (*start_discovery)(void);
+
+ /** Cancel Discovery */
+ int (*cancel_discovery)(void);
+
+ /** Create Bluetooth Bonding */
+ int (*create_bond)(const RawAddress* bd_addr, int transport);
+
+ /** Create Bluetooth Bond using out of band data */
+ int (*create_bond_out_of_band)(const RawAddress* bd_addr, int transport,
+ const bt_out_of_band_data_t* oob_data);
+
+ /** Remove Bond */
+ int (*remove_bond)(const RawAddress* bd_addr);
+
+ /** Cancel Bond */
+ int (*cancel_bond)(const RawAddress* bd_addr);
+
+ /**
+ * Get the connection status for a given remote device.
+ * return value of 0 means the device is not connected,
+ * non-zero return status indicates an active connection.
+ */
+ int (*get_connection_state)(const RawAddress* bd_addr);
+
+ /** BT Legacy PinKey Reply */
+ /** If accept==FALSE, then pin_len and pin_code shall be 0x0 */
+ int (*pin_reply)(const RawAddress* bd_addr, uint8_t accept, uint8_t pin_len,
+ bt_pin_code_t* pin_code);
+
+ /** BT SSP Reply - Just Works, Numeric Comparison and Passkey
+ * passkey shall be zero for BT_SSP_VARIANT_PASSKEY_COMPARISON &
+ * BT_SSP_VARIANT_CONSENT
+ * For BT_SSP_VARIANT_PASSKEY_ENTRY, if accept==FALSE, then passkey
+ * shall be zero */
+ int (*ssp_reply)(const RawAddress* bd_addr, bt_ssp_variant_t variant,
+ uint8_t accept, uint32_t passkey);
+
+ /** Get Bluetooth profile interface */
+ const void* (*get_profile_interface)(const char* profile_id);
+
+ /** Bluetooth Test Mode APIs - Bluetooth must be enabled for these APIs */
+ /* Configure DUT Mode - Use this mode to enter/exit DUT mode */
+ int (*dut_mode_configure)(uint8_t enable);
+
+ /* Send any test HCI (vendor-specific) command to the controller. Must be in
+ * DUT Mode */
+ int (*dut_mode_send)(uint16_t opcode, uint8_t* buf, uint8_t len);
+ /** BLE Test Mode APIs */
+ /* opcode MUST be one of: LE_Receiver_Test, LE_Transmitter_Test, LE_Test_End
+ */
+ int (*le_test_mode)(uint16_t opcode, uint8_t* buf, uint8_t len);
+
+ /** Sets the OS call-out functions that bluedroid needs for alarms and wake
+ * locks. This should be called immediately after a successful |init|.
+ */
+ int (*set_os_callouts)(bt_os_callouts_t* callouts);
+
+ /** Read Energy info details - return value indicates BT_STATUS_SUCCESS or
+ * BT_STATUS_NOT_READY Success indicates that the VSC command was sent to
+ * controller
+ */
+ int (*read_energy_info)();
+
+ /**
+ * Native support for dumpsys function
+ * Function is synchronous and |fd| is owned by caller.
+ * |arguments| are arguments which may affect the output, encoded as
+ * UTF-8 strings.
+ */
+ void (*dump)(int fd, const char** arguments);
+
+ /**
+ * Native support for metrics protobuf dumping. The dumping format will be
+ * raw byte array
+ *
+ * @param output an externally allocated string to dump serialized protobuf
+ */
+ void (*dumpMetrics)(std::string* output);
+
+ /**
+ * Clear /data/misc/bt_config.conf and erase all stored connections
+ */
+ int (*config_clear)(void);
+
+ /**
+ * Clear (reset) the dynamic portion of the device interoperability database.
+ */
+ void (*interop_database_clear)(void);
+
+ /**
+ * Add a new device interoperability workaround for a remote device whose
+ * first |len| bytes of the its device address match |addr|.
+ * NOTE: |feature| has to match an item defined in interop_feature_t
+ * (interop.h).
+ */
+ void (*interop_database_add)(uint16_t feature, const RawAddress* addr,
+ size_t len);
+
+ /**
+ * Get the AvrcpTarget Service interface to interact with the Avrcp Service
+ */
+ bluetooth::avrcp::ServiceInterface* (*get_avrcp_service)(void);
+} bt_interface_t;
+
+#define BLUETOOTH_INTERFACE_STRING "bluetoothInterface"
+
+#endif /* ANDROID_INCLUDE_BLUETOOTH_H */
diff --git a/include/hardware/bluetooth_headset_callbacks.h b/include/hardware/bluetooth_headset_callbacks.h
new file mode 100644
index 0000000..e115a15
--- /dev/null
+++ b/include/hardware/bluetooth_headset_callbacks.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "bt_hf.h"
+
+namespace bluetooth {
+namespace headset {
+
+/**
+ * Headset related callbacks invoked from from the Bluetooth native stack
+ * All callbacks are invoked on the JNI thread
+ */
+class Callbacks {
+ public:
+ virtual ~Callbacks() = default;
+ /**
+ * Callback for connection state change.
+ *
+ * @param state one of the values from bthf_connection_state_t
+ * @param bd_addr remote device address
+ */
+ virtual void ConnectionStateCallback(bthf_connection_state_t state,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for audio connection state change.
+ *
+ * @param state one of the values from bthf_audio_state_t
+ * @param bd_addr remote device address
+ */
+ virtual void AudioStateCallback(bthf_audio_state_t state,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for VR connection state change.
+ *
+ * @param state one of the values from bthf_vr_state_t
+ * @param bd_addr
+ */
+ virtual void VoiceRecognitionCallback(bthf_vr_state_t state,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for answer incoming call (ATA)
+ *
+ * @param bd_addr remote device address
+ */
+ virtual void AnswerCallCallback(RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for disconnect call (AT+CHUP)
+ *
+ * @param bd_addr remote device address
+ */
+ virtual void HangupCallCallback(RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for disconnect call (AT+CHUP)
+ *
+ * @param type denote Speaker/Mic gain bthf_volume_type_t
+ * @param volume volume value 0 to 15, p69, HFP 1.7.1 spec
+ * @param bd_addr remote device address
+ */
+ virtual void VolumeControlCallback(bthf_volume_type_t type, int volume,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for dialing an outgoing call
+ *
+ * @param number intended phone number, if number is NULL, redial
+ * @param bd_addr remote device address
+ */
+ virtual void DialCallCallback(char* number, RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for sending DTMF tones
+ *
+ * @param tone contains the dtmf character to be sent
+ * @param bd_addr remote device address
+ */
+ virtual void DtmfCmdCallback(char tone, RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for enabling/disabling noise reduction/echo cancellation
+ *
+ * @param nrec 1 to enable, 0 to disable
+ * @param bd_addr remote device address
+ */
+ virtual void NoiseReductionCallback(bthf_nrec_t nrec,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for AT+BCS and event from BAC
+ *
+ * @param wbs WBS enable, WBS disable
+ * @param bd_addr remote device address
+ */
+ virtual void WbsCallback(bthf_wbs_config_t wbs, RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for call hold handling (AT+CHLD)
+ *
+ * @param chld the call hold command (0, 1, 2, 3)
+ * @param bd_addr remote device address
+ */
+ virtual void AtChldCallback(bthf_chld_type_t chld, RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for CNUM (subscriber number)
+ *
+ * @param bd_addr remote device address
+ */
+ virtual void AtCnumCallback(RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for indicators (CIND)
+ *
+ * @param bd_addr remote device address
+ */
+ virtual void AtCindCallback(RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for operator selection (COPS)
+ *
+ * @param bd_addr remote device address
+ */
+ virtual void AtCopsCallback(RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for call list (AT+CLCC)
+ *
+ * @param bd_addr remote device address
+ */
+ virtual void AtClccCallback(RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for unknown AT command recd from HF
+ *
+ * @param at_string he unparsed AT string
+ * @param bd_addr remote device address
+ */
+ virtual void UnknownAtCallback(char* at_string, RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for keypressed (HSP) event.
+ *
+ * @param bd_addr remote device address
+ */
+ virtual void KeyPressedCallback(RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for BIND. Pass the remote HF Indicators supported.
+ *
+ * @param at_string unparsed AT command string
+ * @param bd_addr remote device address
+ */
+ virtual void AtBindCallback(char* at_string, RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for BIEV. Pass the change in the Remote HF indicator values
+ *
+ * @param ind_id HF indicator id
+ * @param ind_value HF indicator value
+ * @param bd_addr remote device address
+ */
+ virtual void AtBievCallback(bthf_hf_ind_type_t ind_id, int ind_value,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Callback for BIA. Pass the change in AG indicator activation.
+ * NOTE: Call, Call Setup and Call Held indicators are mandatory and cannot
+ * be disabled. Thus, they are not included here.
+ *
+ * @param service whether HF should receive network service state update
+ * @param roam whether HF should receive roaming state update
+ * @param signal whether HF should receive signal strength update
+ * @param battery whether HF should receive AG battery level update
+ * @param bd_addr remote HF device address
+ */
+ virtual void AtBiaCallback(bool service, bool roam, bool signal, bool battery,
+ RawAddress* bd_addr) = 0;
+};
+
+} // namespace headset
+} // namespace bluetooth
\ No newline at end of file
diff --git a/include/hardware/bluetooth_headset_interface.h b/include/hardware/bluetooth_headset_interface.h
new file mode 100644
index 0000000..a3e0e37
--- /dev/null
+++ b/include/hardware/bluetooth_headset_interface.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "bluetooth_headset_callbacks.h"
+#include "bt_hf.h"
+
+namespace bluetooth {
+namespace headset {
+
+/**
+ * Programming interface for Headset profiles in the Fluoride stack
+ * Thread-safe
+ */
+class Interface {
+ public:
+ virtual ~Interface() = default;
+ /**
+ * Register the BtHf callbacks
+ *
+ * @param callbacks callbacks for the user of the native stack
+ * @param max_hf_clients maximum number of headset clients
+ * @param inband_ringing_enabled whether inband ringtone is enabled
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t Init(Callbacks* callbacks, int max_hf_clients,
+ bool inband_ringing_enabled) = 0;
+
+ /**
+ * Connect to headset
+ *
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t Connect(RawAddress* bd_addr) = 0;
+
+ /**
+ * Disconnect from headset
+ *
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t Disconnect(RawAddress* bd_addr) = 0;
+
+ /**
+ * Create an audio connection
+ *
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t ConnectAudio(RawAddress* bd_addr) = 0;
+
+ /**
+ * Close the audio connection
+ *
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t DisconnectAudio(RawAddress* bd_addr) = 0;
+
+ /** start voice recognition */
+ /**
+ * Start voice recognition
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t StartVoiceRecognition(RawAddress* bd_addr) = 0;
+
+ /**
+ * Stop voice recognition
+ *
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t StopVoiceRecognition(RawAddress* bd_addr) = 0;
+
+ /**
+ * Change HFP related volume on remote headset
+ *
+ * @param type Speaker (+VGS) or Mic (+VGM)
+ * @param volume volume level on scale from 0 to 15, p69, HFP 1.7.1 spec
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t VolumeControl(bthf_volume_type_t type, int volume,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Combined device status change notification
+ *
+ * @param ntk_state Network state, available or not available
+ * @param svc_type Service type, roaming or home
+ * @param signal Signal strength, 0 to 5, p86, HFP 1.7.1 spec
+ * @param batt_chg Battery level of the phone, 0 to 5, p87, HFP 1.7.1 spec
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t DeviceStatusNotification(bthf_network_state_t ntk_state,
+ bthf_service_type_t svc_type,
+ int signal, int batt_chg,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Response for COPS (Query Operator Selection) command
+ *
+ * @param cops Operator Name, max length 16 char, p32 HFP 1.7.1 spec
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t CopsResponse(const char* cops, RawAddress* bd_addr) = 0;
+
+ /**
+ * Response for CIND (Stanford Indicator Update) command
+ *
+ * @param svc service availability, available or not available
+ * @param num_active number of active calls
+ * @param num_held number of held calls
+ * @param call_setup_state call setup state
+ * @param signal signal strength, 0 to 5, p86 HFP 1.7.1 spec
+ * @param roam roaming state, 1 for roaming, 0 for home, p86 HFP 1.7.1 spec
+ * @param batt_chg AG battery charge, 0 to 5, p87 HFP 1.7.1 spec
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t CindResponse(int svc, int num_active, int num_held,
+ bthf_call_state_t call_setup_state,
+ int signal, int roam, int batt_chg,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Pre-formatted AT response, typically in response to unknown AT cmd
+ *
+ * @param rsp formatted AT response
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t FormattedAtResponse(const char* rsp,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * ok/error response to AT commands
+ *
+ * @param response_code OK or ERROR
+ * @param error_code actual error code depend on use case
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t AtResponse(bthf_at_response_t response_code,
+ int error_code, RawAddress* bd_addr) = 0;
+
+ /**
+ * Response for CLCC (Current List of Calls) command.
+ * Can be iteratively called for each call index
+ * Call index of 0 will be treated as NULL termination (Completes response)
+ *
+ * @param index index of the call
+ * @param dir direction of the call
+ * @param state state of the call
+ * @param mode mode of the call
+ * @param mpty whether the call is multi party
+ * @param number phone number of the call
+ * @param type type of the call
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t ClccResponse(
+ int index, bthf_call_direction_t dir, bthf_call_state_t state,
+ bthf_call_mode_t mode, bthf_call_mpty_type_t mpty, const char* number,
+ bthf_call_addrtype_t type, RawAddress* bd_addr) = 0;
+
+ /**
+ * Notify of a call state change
+ * Each update notifies
+ * 1. Number of active/held/ringing calls
+ * 2. call_state: This denotes the state change that triggered this msg
+ * This will take one of the values from BtHfCallState
+ * 3. number & type: valid only for incoming & waiting call
+ *
+ * @param num_active number of active calls
+ * @param num_held number of held calls
+ * @param call_setup_state current call setup state
+ * @param number phone number of the call
+ * @param type type of the call
+ * @param bd_addr remote device address
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t PhoneStateChange(int num_active, int num_held,
+ bthf_call_state_t call_setup_state,
+ const char* number,
+ bthf_call_addrtype_t type,
+ RawAddress* bd_addr) = 0;
+
+ /**
+ * Closes the interface.
+ */
+ virtual void Cleanup() = 0;
+
+ /**
+ * Whether we are allowed to initiate SCO
+ *
+ * @param value true to allow, false to disallow
+ * @return BT_STATUS_SUCCESS on success
+ */
+ virtual bt_status_t SetScoAllowed(bool value) = 0;
+
+ /**
+ * Send +BSIR response code to enable/disable in-band ringtone in an active
+ * HFP service level connection
+ *
+ * @param value true for enabled, false for disable
+ * @param bd_addr remote device address
+ */
+ virtual bt_status_t SendBsir(bool value, RawAddress* bd_addr) = 0;
+
+ /**
+ * Set the current active headset device for SCO audio
+ *
+ * @param active_device_addr remote device address
+ */
+ virtual bt_status_t SetActiveDevice(RawAddress* active_device_addr) = 0;
+};
+
+} // namespace headset
+} // namespace bluetooth
diff --git a/include/hardware/bt_av.h b/include/hardware/bt_av.h
new file mode 100644
index 0000000..bdb1285
--- /dev/null
+++ b/include/hardware/bt_av.h
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_AV_H
+#define ANDROID_INCLUDE_BT_AV_H
+
+#include <vector>
+
+#include <hardware/bluetooth.h>
+
+__BEGIN_DECLS
+
+/* Bluetooth AV connection states */
+typedef enum {
+ BTAV_CONNECTION_STATE_DISCONNECTED = 0,
+ BTAV_CONNECTION_STATE_CONNECTING,
+ BTAV_CONNECTION_STATE_CONNECTED,
+ BTAV_CONNECTION_STATE_DISCONNECTING
+} btav_connection_state_t;
+
+/* Bluetooth AV datapath states */
+typedef enum {
+ BTAV_AUDIO_STATE_REMOTE_SUSPEND = 0,
+ BTAV_AUDIO_STATE_STOPPED,
+ BTAV_AUDIO_STATE_STARTED,
+} btav_audio_state_t;
+
+/*
+ * Enum values for each A2DP supported codec.
+ * There should be a separate entry for each A2DP codec that is supported
+ * for encoding (SRC), and for decoding purpose (SINK).
+ */
+typedef enum {
+ BTAV_A2DP_CODEC_INDEX_SOURCE_MIN = 0,
+
+ // Add an entry for each source codec here.
+ // NOTE: The values should be same as those listed in the following file:
+ // BluetoothCodecConfig.java
+ BTAV_A2DP_CODEC_INDEX_SOURCE_SBC = 0,
+ BTAV_A2DP_CODEC_INDEX_SOURCE_AAC,
+ BTAV_A2DP_CODEC_INDEX_SOURCE_APTX,
+ BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD,
+ BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC,
+
+ BTAV_A2DP_CODEC_INDEX_SOURCE_MAX,
+
+ BTAV_A2DP_CODEC_INDEX_SINK_MIN = BTAV_A2DP_CODEC_INDEX_SOURCE_MAX,
+
+ // Add an entry for each sink codec here
+ BTAV_A2DP_CODEC_INDEX_SINK_SBC = BTAV_A2DP_CODEC_INDEX_SINK_MIN,
+ BTAV_A2DP_CODEC_INDEX_SINK_AAC,
+
+ BTAV_A2DP_CODEC_INDEX_SINK_MAX,
+
+ BTAV_A2DP_CODEC_INDEX_MIN = BTAV_A2DP_CODEC_INDEX_SOURCE_MIN,
+ BTAV_A2DP_CODEC_INDEX_MAX = BTAV_A2DP_CODEC_INDEX_SINK_MAX
+} btav_a2dp_codec_index_t;
+
+typedef enum {
+ // Disable the codec.
+ // NOTE: This value can be used only during initialization when
+ // function btav_source_interface_t::init() is called.
+ BTAV_A2DP_CODEC_PRIORITY_DISABLED = -1,
+
+ // Reset the codec priority to its default value.
+ BTAV_A2DP_CODEC_PRIORITY_DEFAULT = 0,
+
+ // Highest codec priority.
+ BTAV_A2DP_CODEC_PRIORITY_HIGHEST = 1000 * 1000
+} btav_a2dp_codec_priority_t;
+
+typedef enum {
+ BTAV_A2DP_CODEC_SAMPLE_RATE_NONE = 0x0,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_44100 = 0x1 << 0,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_48000 = 0x1 << 1,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_88200 = 0x1 << 2,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_96000 = 0x1 << 3,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_176400 = 0x1 << 4,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_192000 = 0x1 << 5,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_16000 = 0x1 << 6,
+ BTAV_A2DP_CODEC_SAMPLE_RATE_24000 = 0x1 << 7
+} btav_a2dp_codec_sample_rate_t;
+
+typedef enum {
+ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE = 0x0,
+ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 = 0x1 << 0,
+ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24 = 0x1 << 1,
+ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32 = 0x1 << 2
+} btav_a2dp_codec_bits_per_sample_t;
+
+typedef enum {
+ BTAV_A2DP_CODEC_CHANNEL_MODE_NONE = 0x0,
+ BTAV_A2DP_CODEC_CHANNEL_MODE_MONO = 0x1 << 0,
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO = 0x1 << 1
+} btav_a2dp_codec_channel_mode_t;
+
+/*
+ * Structure for representing codec capability or configuration.
+ * It is used for configuring A2DP codec preference, and for reporting back
+ * current configuration or codec capability.
+ * For codec capability, fields "sample_rate", "bits_per_sample" and
+ * "channel_mode" can contain bit-masks with all supported features.
+ */
+typedef struct {
+ btav_a2dp_codec_index_t codec_type;
+ btav_a2dp_codec_priority_t
+ codec_priority; // Codec selection priority
+ // relative to other codecs: larger value
+ // means higher priority. If 0, reset to
+ // default.
+ btav_a2dp_codec_sample_rate_t sample_rate;
+ btav_a2dp_codec_bits_per_sample_t bits_per_sample;
+ btav_a2dp_codec_channel_mode_t channel_mode;
+ int64_t codec_specific_1; // Codec-specific value 1
+ int64_t codec_specific_2; // Codec-specific value 2
+ int64_t codec_specific_3; // Codec-specific value 3
+ int64_t codec_specific_4; // Codec-specific value 4
+
+ std::string ToString() const {
+ std::string codec_name_str;
+
+ switch (codec_type) {
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
+ codec_name_str = "SBC";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
+ codec_name_str = "AAC";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
+ codec_name_str = "aptX";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
+ codec_name_str = "aptX HD";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
+ codec_name_str = "LDAC";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
+ codec_name_str = "SBC (Sink)";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
+ codec_name_str = "AAC (Sink)";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_MAX:
+ codec_name_str = "Unknown(CODEC_INDEX_MAX)";
+ break;
+ }
+
+ std::string sample_rate_str;
+ AppendCapability(sample_rate_str,
+ (sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE), "NONE");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_44100),
+ "44100");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_48000),
+ "48000");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_88200),
+ "88200");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_96000),
+ "96000");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_176400),
+ "176400");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_192000),
+ "192000");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_16000),
+ "16000");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_24000),
+ "24000");
+
+ std::string bits_per_sample_str;
+ AppendCapability(bits_per_sample_str,
+ (bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE),
+ "NONE");
+ AppendCapability(bits_per_sample_str,
+ (bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16),
+ "16");
+ AppendCapability(bits_per_sample_str,
+ (bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24),
+ "24");
+ AppendCapability(bits_per_sample_str,
+ (bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32),
+ "32");
+
+ std::string channel_mode_str;
+ AppendCapability(channel_mode_str,
+ (channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE),
+ "NONE");
+ AppendCapability(channel_mode_str,
+ (channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_MONO),
+ "MONO");
+ AppendCapability(channel_mode_str,
+ (channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO),
+ "STEREO");
+
+ return "codec: " + codec_name_str +
+ " priority: " + std::to_string(codec_priority) +
+ " sample_rate: " + sample_rate_str +
+ " bits_per_sample: " + bits_per_sample_str +
+ " channel_mode: " + channel_mode_str +
+ " codec_specific_1: " + std::to_string(codec_specific_1) +
+ " codec_specific_2: " + std::to_string(codec_specific_2) +
+ " codec_specific_3: " + std::to_string(codec_specific_3) +
+ " codec_specific_4: " + std::to_string(codec_specific_4);
+ }
+
+ private:
+ static std::string AppendCapability(std::string& result, bool append,
+ const std::string& name) {
+ if (!append) return result;
+ if (!result.empty()) result += "|";
+ result += name;
+ return result;
+ }
+} btav_a2dp_codec_config_t;
+
+/** Callback for connection state change.
+ * state will have one of the values from btav_connection_state_t
+ */
+typedef void (*btav_connection_state_callback)(const RawAddress& bd_addr,
+ btav_connection_state_t state);
+
+/** Callback for audiopath state change.
+ * state will have one of the values from btav_audio_state_t
+ */
+typedef void (*btav_audio_state_callback)(const RawAddress& bd_addr,
+ btav_audio_state_t state);
+
+/** Callback for audio configuration change.
+ * Used only for the A2DP Source interface.
+ */
+typedef void (*btav_audio_source_config_callback)(
+ const RawAddress& bd_addr, btav_a2dp_codec_config_t codec_config,
+ std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities,
+ std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities);
+
+/** Callback for audio configuration change.
+ * Used only for the A2DP Sink interface.
+ * sample_rate: sample rate in Hz
+ * channel_count: number of channels (1 for mono, 2 for stereo)
+ */
+typedef void (*btav_audio_sink_config_callback)(const RawAddress& bd_addr,
+ uint32_t sample_rate,
+ uint8_t channel_count);
+
+/** BT-AV A2DP Source callback structure. */
+typedef struct {
+ /** set to sizeof(btav_source_callbacks_t) */
+ size_t size;
+ btav_connection_state_callback connection_state_cb;
+ btav_audio_state_callback audio_state_cb;
+ btav_audio_source_config_callback audio_config_cb;
+} btav_source_callbacks_t;
+
+/** BT-AV A2DP Sink callback structure. */
+typedef struct {
+ /** set to sizeof(btav_sink_callbacks_t) */
+ size_t size;
+ btav_connection_state_callback connection_state_cb;
+ btav_audio_state_callback audio_state_cb;
+ btav_audio_sink_config_callback audio_config_cb;
+} btav_sink_callbacks_t;
+
+/**
+ * NOTE:
+ *
+ * 1. AVRCP 1.0 shall be supported initially. AVRCP passthrough commands
+ * shall be handled internally via uinput
+ *
+ * 2. A2DP data path shall be handled via a socket pipe between the AudioFlinger
+ * android_audio_hw library and the Bluetooth stack.
+ *
+ */
+
+/** Represents the standard BT-AV A2DP Source interface.
+ */
+typedef struct {
+ /** set to sizeof(btav_source_interface_t) */
+ size_t size;
+ /**
+ * Register the BtAv callbacks.
+ */
+ bt_status_t (*init)(btav_source_callbacks_t* callbacks,
+ int max_connected_audio_devices,
+ std::vector<btav_a2dp_codec_config_t> codec_priorities);
+
+ /** connect to headset */
+ bt_status_t (*connect)(const RawAddress& bd_addr);
+
+ /** dis-connect from headset */
+ bt_status_t (*disconnect)(const RawAddress& bd_addr);
+
+ /** sets the connected device as active */
+ bt_status_t (*set_active_device)(const RawAddress& bd_addr);
+
+ /** configure the codecs settings preferences */
+ bt_status_t (*config_codec)(
+ const RawAddress& bd_addr,
+ std::vector<btav_a2dp_codec_config_t> codec_preferences);
+
+ /** Closes the interface. */
+ void (*cleanup)(void);
+
+} btav_source_interface_t;
+
+/** Represents the standard BT-AV A2DP Sink interface.
+ */
+typedef struct {
+ /** set to sizeof(btav_sink_interface_t) */
+ size_t size;
+ /**
+ * Register the BtAv callbacks
+ */
+ bt_status_t (*init)(btav_sink_callbacks_t* callbacks);
+
+ /** connect to headset */
+ bt_status_t (*connect)(const RawAddress& bd_addr);
+
+ /** dis-connect from headset */
+ bt_status_t (*disconnect)(const RawAddress& bd_addr);
+
+ /** Closes the interface. */
+ void (*cleanup)(void);
+
+ /** Sends Audio Focus State. */
+ void (*set_audio_focus_state)(int focus_state);
+
+ /** Sets the audio track gain. */
+ void (*set_audio_track_gain)(float gain);
+} btav_sink_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_AV_H */
diff --git a/include/hardware/bt_common_types.h b/include/hardware/bt_common_types.h
new file mode 100644
index 0000000..0a315fe
--- /dev/null
+++ b/include/hardware/bt_common_types.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************************
+ *
+ * This file contains constants and definitions that can be used commonly
+ * between JNI and stack layer
+ *
+ ******************************************************************************/
+#ifndef ANDROID_INCLUDE_BT_COMMON_TYPES_H
+#define ANDROID_INCLUDE_BT_COMMON_TYPES_H
+
+#include "bluetooth.h"
+
+#include <bluetooth/uuid.h>
+#include <vector>
+
+typedef struct {
+ uint8_t client_if;
+ uint8_t filt_index;
+ uint8_t advertiser_state;
+ uint8_t advertiser_info_present;
+ uint8_t addr_type;
+ uint8_t tx_power;
+ int8_t rssi_value;
+ uint16_t time_stamp;
+ RawAddress bd_addr;
+ uint8_t adv_pkt_len;
+ uint8_t* p_adv_pkt_data;
+ uint8_t scan_rsp_len;
+ uint8_t* p_scan_rsp_data;
+} btgatt_track_adv_info_t;
+
+typedef enum {
+ BTGATT_DB_PRIMARY_SERVICE,
+ BTGATT_DB_SECONDARY_SERVICE,
+ BTGATT_DB_INCLUDED_SERVICE,
+ BTGATT_DB_CHARACTERISTIC,
+ BTGATT_DB_DESCRIPTOR,
+} bt_gatt_db_attribute_type_t;
+
+typedef struct {
+ uint16_t id;
+ bluetooth::Uuid uuid;
+ bt_gatt_db_attribute_type_t type;
+ uint16_t attribute_handle;
+
+ /*
+ * If |type| is |BTGATT_DB_PRIMARY_SERVICE|, or
+ * |BTGATT_DB_SECONDARY_SERVICE|, this contains the start and end attribute
+ * handles.
+ */
+ uint16_t start_handle;
+ uint16_t end_handle;
+
+ /*
+ * If |type| is |BTGATT_DB_CHARACTERISTIC|, this contains the properties of
+ * the characteristic.
+ */
+ uint8_t properties;
+ uint16_t permissions;
+} btgatt_db_element_t;
+
+typedef struct {
+ uint16_t feat_seln;
+ uint16_t list_logic_type;
+ uint8_t filt_logic_type;
+ uint8_t rssi_high_thres;
+ uint8_t rssi_low_thres;
+ uint8_t dely_mode;
+ uint16_t found_timeout;
+ uint16_t lost_timeout;
+ uint8_t found_timeout_cnt;
+ uint16_t num_of_tracking_entries;
+} btgatt_filt_param_setup_t;
+
+// Advertising Packet Content Filter
+struct ApcfCommand {
+ uint8_t type;
+ RawAddress address;
+ uint8_t addr_type;
+ bluetooth::Uuid uuid;
+ bluetooth::Uuid uuid_mask;
+ std::vector<uint8_t> name;
+ uint16_t company;
+ uint16_t company_mask;
+ std::vector<uint8_t> data;
+ std::vector<uint8_t> data_mask;
+};
+
+#endif /* ANDROID_INCLUDE_BT_COMMON_TYPES_H */
diff --git a/include/hardware/bt_gatt.h b/include/hardware/bt_gatt.h
new file mode 100644
index 0000000..6f8c408
--- /dev/null
+++ b/include/hardware/bt_gatt.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_GATT_H
+#define ANDROID_INCLUDE_BT_GATT_H
+
+#include <stdint.h>
+#include "ble_advertiser.h"
+#include "ble_scanner.h"
+#include "bt_gatt_client.h"
+#include "bt_gatt_server.h"
+
+__BEGIN_DECLS
+
+/** BT-GATT callbacks */
+typedef struct {
+ /** Set to sizeof(btgatt_callbacks_t) */
+ size_t size;
+
+ /** GATT Client callbacks */
+ const btgatt_client_callbacks_t* client;
+
+ /** GATT Server callbacks */
+ const btgatt_server_callbacks_t* server;
+
+ /** LE scanner callbacks */
+ const btgatt_scanner_callbacks_t* scanner;
+} btgatt_callbacks_t;
+
+/** Represents the standard Bluetooth GATT interface. */
+typedef struct {
+ /** Set to sizeof(btgatt_interface_t) */
+ size_t size;
+
+ /**
+ * Initializes the interface and provides callback routines
+ */
+ bt_status_t (*init)(const btgatt_callbacks_t* callbacks);
+
+ /** Closes the interface */
+ void (*cleanup)(void);
+
+ /** Pointer to the GATT client interface methods.*/
+ const btgatt_client_interface_t* client;
+
+ /** Pointer to the GATT server interface methods.*/
+ const btgatt_server_interface_t* server;
+
+ /** Pointer to the LE scanner interface methods.*/
+ BleScannerInterface* scanner;
+
+ /** Pointer to the advertiser interface methods.*/
+ BleAdvertiserInterface* advertiser;
+} btgatt_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_GATT_H */
diff --git a/include/hardware/bt_gatt_client.h b/include/hardware/bt_gatt_client.h
new file mode 100644
index 0000000..6ea1c89
--- /dev/null
+++ b/include/hardware/bt_gatt_client.h
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_GATT_CLIENT_H
+#define ANDROID_INCLUDE_BT_GATT_CLIENT_H
+
+#include <stdint.h>
+#include <vector>
+#include "bt_common_types.h"
+#include "bt_gatt_types.h"
+
+#include <bluetooth/uuid.h>
+
+__BEGIN_DECLS
+
+/**
+ * Buffer sizes for maximum attribute length and maximum read/write
+ * operation buffer size.
+ */
+#define BTGATT_MAX_ATTR_LEN 600
+
+/** Buffer type for unformatted reads/writes */
+typedef struct {
+ uint8_t value[BTGATT_MAX_ATTR_LEN];
+ uint16_t len;
+} btgatt_unformatted_value_t;
+
+/** Parameters for GATT read operations */
+typedef struct {
+ uint16_t handle;
+ btgatt_unformatted_value_t value;
+ uint16_t value_type;
+ uint8_t status;
+} btgatt_read_params_t;
+
+/** Parameters for GATT write operations */
+typedef struct {
+ btgatt_srvc_id_t srvc_id;
+ btgatt_gatt_id_t char_id;
+ btgatt_gatt_id_t descr_id;
+ uint8_t status;
+} btgatt_write_params_t;
+
+/** Attribute change notification parameters */
+typedef struct {
+ uint8_t value[BTGATT_MAX_ATTR_LEN];
+ RawAddress bda;
+ uint16_t handle;
+ uint16_t len;
+ uint8_t is_notify;
+} btgatt_notify_params_t;
+
+typedef struct {
+ RawAddress* bda1;
+ bluetooth::Uuid* uuid1;
+ uint16_t u1;
+ uint16_t u2;
+ uint16_t u3;
+ uint16_t u4;
+ uint16_t u5;
+} btgatt_test_params_t;
+
+/* BT GATT client error codes */
+typedef enum {
+ BT_GATTC_COMMAND_SUCCESS = 0, /* 0 Command succeeded */
+ BT_GATTC_COMMAND_STARTED, /* 1 Command started OK. */
+ BT_GATTC_COMMAND_BUSY, /* 2 Device busy with another command */
+ BT_GATTC_COMMAND_STORED, /* 3 request is stored in control block */
+ BT_GATTC_NO_RESOURCES, /* 4 No resources to issue command */
+ BT_GATTC_MODE_UNSUPPORTED, /* 5 Request for 1 or more unsupported modes */
+ BT_GATTC_ILLEGAL_VALUE, /* 6 Illegal command /parameter value */
+ BT_GATTC_INCORRECT_STATE, /* 7 Device in wrong state for request */
+ BT_GATTC_UNKNOWN_ADDR, /* 8 Unknown remote BD address */
+ BT_GATTC_DEVICE_TIMEOUT, /* 9 Device timeout */
+ BT_GATTC_INVALID_CONTROLLER_OUTPUT, /* 10 An incorrect value was received
+ from HCI */
+ BT_GATTC_SECURITY_ERROR, /* 11 Authorization or security failure or not
+ authorized */
+ BT_GATTC_DELAYED_ENCRYPTION_CHECK, /*12 Delayed encryption check */
+ BT_GATTC_ERR_PROCESSING /* 12 Generic error */
+} btgattc_error_t;
+
+/** BT-GATT Client callback structure. */
+
+/** Callback invoked in response to register_client */
+typedef void (*register_client_callback)(int status, int client_if,
+ const bluetooth::Uuid& app_uuid);
+
+/** GATT open callback invoked in response to open */
+typedef void (*connect_callback)(int conn_id, int status, int client_if,
+ const RawAddress& bda);
+
+/** Callback invoked in response to close */
+typedef void (*disconnect_callback)(int conn_id, int status, int client_if,
+ const RawAddress& bda);
+
+/**
+ * Invoked in response to search_service when the GATT service search
+ * has been completed.
+ */
+typedef void (*search_complete_callback)(int conn_id, int status);
+
+/** Callback invoked in response to [de]register_for_notification */
+typedef void (*register_for_notification_callback)(int conn_id, int registered,
+ int status, uint16_t handle);
+
+/**
+ * Remote device notification callback, invoked when a remote device sends
+ * a notification or indication that a client has registered for.
+ */
+typedef void (*notify_callback)(int conn_id,
+ const btgatt_notify_params_t& p_data);
+
+/** Reports result of a GATT read operation */
+typedef void (*read_characteristic_callback)(int conn_id, int status,
+ btgatt_read_params_t* p_data);
+
+/** GATT write characteristic operation callback */
+typedef void (*write_characteristic_callback)(int conn_id, int status,
+ uint16_t handle);
+
+/** GATT execute prepared write callback */
+typedef void (*execute_write_callback)(int conn_id, int status);
+
+/** Callback invoked in response to read_descriptor */
+typedef void (*read_descriptor_callback)(int conn_id, int status,
+ const btgatt_read_params_t& p_data);
+
+/** Callback invoked in response to write_descriptor */
+typedef void (*write_descriptor_callback)(int conn_id, int status,
+ uint16_t handle);
+
+/** Callback triggered in response to read_remote_rssi */
+typedef void (*read_remote_rssi_callback)(int client_if, const RawAddress& bda,
+ int rssi, int status);
+
+/** Callback invoked when the MTU for a given connection changes */
+typedef void (*configure_mtu_callback)(int conn_id, int status, int mtu);
+
+/**
+ * Callback notifying an application that a remote device connection is
+ * currently congested and cannot receive any more data. An application should
+ * avoid sending more data until a further callback is received indicating the
+ * congestion status has been cleared.
+ */
+typedef void (*congestion_callback)(int conn_id, bool congested);
+
+/** GATT get database callback */
+typedef void (*get_gatt_db_callback)(int conn_id, const btgatt_db_element_t* db,
+ int count);
+
+/** GATT services between start_handle and end_handle were removed */
+typedef void (*services_removed_callback)(int conn_id, uint16_t start_handle,
+ uint16_t end_handle);
+
+/** GATT services were added */
+typedef void (*services_added_callback)(int conn_id,
+ const btgatt_db_element_t& added,
+ int added_count);
+
+/** Callback invoked when the PHY for a given connection changes */
+typedef void (*phy_updated_callback)(int conn_id, uint8_t tx_phy,
+ uint8_t rx_phy, uint8_t status);
+
+/** Callback invoked when the connection parameters for a given connection
+ * changes */
+typedef void (*conn_updated_callback)(int conn_id, uint16_t interval,
+ uint16_t latency, uint16_t timeout,
+ uint8_t status);
+
+typedef struct {
+ register_client_callback register_client_cb;
+ connect_callback open_cb;
+ disconnect_callback close_cb;
+ search_complete_callback search_complete_cb;
+ register_for_notification_callback register_for_notification_cb;
+ notify_callback notify_cb;
+ read_characteristic_callback read_characteristic_cb;
+ write_characteristic_callback write_characteristic_cb;
+ read_descriptor_callback read_descriptor_cb;
+ write_descriptor_callback write_descriptor_cb;
+ execute_write_callback execute_write_cb;
+ read_remote_rssi_callback read_remote_rssi_cb;
+ configure_mtu_callback configure_mtu_cb;
+ congestion_callback congestion_cb;
+ get_gatt_db_callback get_gatt_db_cb;
+ services_removed_callback services_removed_cb;
+ services_added_callback services_added_cb;
+ phy_updated_callback phy_updated_cb;
+ conn_updated_callback conn_updated_cb;
+} btgatt_client_callbacks_t;
+
+/** Represents the standard BT-GATT client interface. */
+
+typedef struct {
+ /** Registers a GATT client application with the stack */
+ bt_status_t (*register_client)(const bluetooth::Uuid& uuid);
+
+ /** Unregister a client application from the stack */
+ bt_status_t (*unregister_client)(int client_if);
+
+ /** Create a connection to a remote LE or dual-mode device */
+ bt_status_t (*connect)(int client_if, const RawAddress& bd_addr,
+ bool is_direct, int transport, bool opportunistic,
+ int initiating_phys);
+
+ /** Disconnect a remote device or cancel a pending connection */
+ bt_status_t (*disconnect)(int client_if, const RawAddress& bd_addr,
+ int conn_id);
+
+ /** Clear the attribute cache for a given device */
+ bt_status_t (*refresh)(int client_if, const RawAddress& bd_addr);
+
+ /**
+ * Enumerate all GATT services on a connected device.
+ * Optionally, the results can be filtered for a given UUID.
+ */
+ bt_status_t (*search_service)(int conn_id,
+ const bluetooth::Uuid* filter_uuid);
+
+ /**
+ * Sead "Find service by UUID" request. Used only for PTS tests.
+ */
+ void (*btif_gattc_discover_service_by_uuid)(int conn_id,
+ const bluetooth::Uuid& uuid);
+
+ /** Read a characteristic on a remote device */
+ bt_status_t (*read_characteristic)(int conn_id, uint16_t handle,
+ int auth_req);
+
+ /** Read a characteristic on a remote device */
+ bt_status_t (*read_using_characteristic_uuid)(int conn_id,
+ const bluetooth::Uuid& uuid,
+ uint16_t s_handle,
+ uint16_t e_handle,
+ int auth_req);
+
+ /** Write a remote characteristic */
+ bt_status_t (*write_characteristic)(int conn_id, uint16_t handle,
+ int write_type, int auth_req,
+ std::vector<uint8_t> value);
+
+ /** Read the descriptor for a given characteristic */
+ bt_status_t (*read_descriptor)(int conn_id, uint16_t handle, int auth_req);
+
+ /** Write a remote descriptor for a given characteristic */
+ bt_status_t (*write_descriptor)(int conn_id, uint16_t handle, int auth_req,
+ std::vector<uint8_t> value);
+
+ /** Execute a prepared write operation */
+ bt_status_t (*execute_write)(int conn_id, int execute);
+
+ /**
+ * Register to receive notifications or indications for a given
+ * characteristic
+ */
+ bt_status_t (*register_for_notification)(int client_if,
+ const RawAddress& bd_addr,
+ uint16_t handle);
+
+ /** Deregister a previous request for notifications/indications */
+ bt_status_t (*deregister_for_notification)(int client_if,
+ const RawAddress& bd_addr,
+ uint16_t handle);
+
+ /** Request RSSI for a given remote device */
+ bt_status_t (*read_remote_rssi)(int client_if, const RawAddress& bd_addr);
+
+ /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
+ int (*get_device_type)(const RawAddress& bd_addr);
+
+ /** Configure the MTU for a given connection */
+ bt_status_t (*configure_mtu)(int conn_id, int mtu);
+
+ /** Request a connection parameter update */
+ bt_status_t (*conn_parameter_update)(const RawAddress& bd_addr,
+ int min_interval, int max_interval,
+ int latency, int timeout,
+ uint16_t min_ce_len,
+ uint16_t max_ce_len);
+
+ bt_status_t (*set_preferred_phy)(const RawAddress& bd_addr, uint8_t tx_phy,
+ uint8_t rx_phy, uint16_t phy_options);
+
+ bt_status_t (*read_phy)(
+ const RawAddress& bd_addr,
+ base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb);
+
+ /** Test mode interface */
+ bt_status_t (*test_command)(int command, const btgatt_test_params_t& params);
+
+ /** Get gatt db content */
+ bt_status_t (*get_gatt_db)(int conn_id);
+
+} btgatt_client_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_GATT_CLIENT_H */
diff --git a/include/hardware/bt_gatt_server.h b/include/hardware/bt_gatt_server.h
new file mode 100644
index 0000000..1b1db37
--- /dev/null
+++ b/include/hardware/bt_gatt_server.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_GATT_SERVER_H
+#define ANDROID_INCLUDE_BT_GATT_SERVER_H
+
+#include <stdint.h>
+#include <vector>
+
+#include "bt_gatt_types.h"
+
+__BEGIN_DECLS
+
+/** GATT value type used in response to remote read requests */
+typedef struct {
+ uint8_t value[BTGATT_MAX_ATTR_LEN];
+ uint16_t handle;
+ uint16_t offset;
+ uint16_t len;
+ uint8_t auth_req;
+} btgatt_value_t;
+
+/** GATT remote read request response type */
+typedef union {
+ btgatt_value_t attr_value;
+ uint16_t handle;
+} btgatt_response_t;
+
+/** BT-GATT Server callback structure. */
+
+/** Callback invoked in response to register_server */
+typedef void (*register_server_callback)(int status, int server_if,
+ const bluetooth::Uuid& app_uuid);
+
+/** Callback indicating that a remote device has connected or been disconnected
+ */
+typedef void (*connection_callback)(int conn_id, int server_if, int connected,
+ const RawAddress& bda);
+
+/** Callback invoked in response to create_service */
+typedef void (*service_added_callback)(
+ int status, int server_if, std::vector<btgatt_db_element_t> service);
+
+/** Callback invoked in response to stop_service */
+typedef void (*service_stopped_callback)(int status, int server_if,
+ int srvc_handle);
+
+/** Callback triggered when a service has been deleted */
+typedef void (*service_deleted_callback)(int status, int server_if,
+ int srvc_handle);
+
+/**
+ * Callback invoked when a remote device has requested to read a characteristic
+ * or descriptor. The application must respond by calling send_response
+ */
+typedef void (*request_read_callback)(int conn_id, int trans_id,
+ const RawAddress& bda, int attr_handle,
+ int offset, bool is_long);
+
+/**
+ * Callback invoked when a remote device has requested to write to a
+ * characteristic or descriptor.
+ */
+typedef void (*request_write_callback)(int conn_id, int trans_id,
+ const RawAddress& bda, int attr_handle,
+ int offset, bool need_rsp, bool is_prep,
+ std::vector<uint8_t> value);
+
+/** Callback invoked when a previously prepared write is to be executed */
+typedef void (*request_exec_write_callback)(int conn_id, int trans_id,
+ const RawAddress& bda,
+ int exec_write);
+
+/**
+ * Callback triggered in response to send_response if the remote device
+ * sends a confirmation.
+ */
+typedef void (*response_confirmation_callback)(int status, int handle);
+
+/**
+ * Callback confirming that a notification or indication has been sent
+ * to a remote device.
+ */
+typedef void (*indication_sent_callback)(int conn_id, int status);
+
+/**
+ * Callback notifying an application that a remote device connection is
+ * currently congested and cannot receive any more data. An application should
+ * avoid sending more data until a further callback is received indicating the
+ * congestion status has been cleared.
+ */
+typedef void (*congestion_callback)(int conn_id, bool congested);
+
+/** Callback invoked when the MTU for a given connection changes */
+typedef void (*mtu_changed_callback)(int conn_id, int mtu);
+
+/** Callback invoked when the PHY for a given connection changes */
+typedef void (*phy_updated_callback)(int conn_id, uint8_t tx_phy,
+ uint8_t rx_phy, uint8_t status);
+
+/** Callback invoked when the connection parameters for a given connection
+ * changes */
+typedef void (*conn_updated_callback)(int conn_id, uint16_t interval,
+ uint16_t latency, uint16_t timeout,
+ uint8_t status);
+typedef struct {
+ register_server_callback register_server_cb;
+ connection_callback connection_cb;
+ service_added_callback service_added_cb;
+ service_stopped_callback service_stopped_cb;
+ service_deleted_callback service_deleted_cb;
+ request_read_callback request_read_characteristic_cb;
+ request_read_callback request_read_descriptor_cb;
+ request_write_callback request_write_characteristic_cb;
+ request_write_callback request_write_descriptor_cb;
+ request_exec_write_callback request_exec_write_cb;
+ response_confirmation_callback response_confirmation_cb;
+ indication_sent_callback indication_sent_cb;
+ congestion_callback congestion_cb;
+ mtu_changed_callback mtu_changed_cb;
+ phy_updated_callback phy_updated_cb;
+ conn_updated_callback conn_updated_cb;
+} btgatt_server_callbacks_t;
+
+/** Represents the standard BT-GATT server interface. */
+typedef struct {
+ /** Registers a GATT server application with the stack */
+ bt_status_t (*register_server)(const bluetooth::Uuid& uuid);
+
+ /** Unregister a server application from the stack */
+ bt_status_t (*unregister_server)(int server_if);
+
+ /** Create a connection to a remote peripheral */
+ bt_status_t (*connect)(int server_if, const RawAddress& bd_addr,
+ bool is_direct, int transport);
+
+ /** Disconnect an established connection or cancel a pending one */
+ bt_status_t (*disconnect)(int server_if, const RawAddress& bd_addr,
+ int conn_id);
+
+ /** Create a new service */
+ bt_status_t (*add_service)(int server_if,
+ std::vector<btgatt_db_element_t> service);
+
+ /** Stops a local service */
+ bt_status_t (*stop_service)(int server_if, int service_handle);
+
+ /** Delete a local service */
+ bt_status_t (*delete_service)(int server_if, int service_handle);
+
+ /** Send value indication to a remote device */
+ bt_status_t (*send_indication)(int server_if, int attribute_handle,
+ int conn_id, int confirm,
+ std::vector<uint8_t> value);
+
+ /** Send a response to a read/write operation */
+ bt_status_t (*send_response)(int conn_id, int trans_id, int status,
+ const btgatt_response_t& response);
+
+ bt_status_t (*set_preferred_phy)(const RawAddress& bd_addr, uint8_t tx_phy,
+ uint8_t rx_phy, uint16_t phy_options);
+
+ bt_status_t (*read_phy)(
+ const RawAddress& bd_addr,
+ base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb);
+
+} btgatt_server_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_GATT_CLIENT_H */
diff --git a/include/hardware/bt_gatt_types.h b/include/hardware/bt_gatt_types.h
new file mode 100644
index 0000000..e41cca6
--- /dev/null
+++ b/include/hardware/bt_gatt_types.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_GATT_TYPES_H
+#define ANDROID_INCLUDE_BT_GATT_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <bluetooth/uuid.h>
+
+__BEGIN_DECLS
+
+/**
+ * GATT Service types
+ */
+#define BTGATT_SERVICE_TYPE_PRIMARY 0
+#define BTGATT_SERVICE_TYPE_SECONDARY 1
+
+/** GATT ID adding instance id tracking to the UUID */
+typedef struct {
+ bluetooth::Uuid uuid;
+ uint8_t inst_id;
+} btgatt_gatt_id_t;
+
+/** GATT Service ID also identifies the service type (primary/secondary) */
+typedef struct {
+ btgatt_gatt_id_t id;
+ uint8_t is_primary;
+} btgatt_srvc_id_t;
+
+/** Preferred physical Transport for GATT connection */
+typedef enum {
+ GATT_TRANSPORT_AUTO,
+ GATT_TRANSPORT_BREDR,
+ GATT_TRANSPORT_LE
+} btgatt_transport_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_GATT_TYPES_H */
diff --git a/include/hardware/bt_hd.h b/include/hardware/bt_hd.h
new file mode 100644
index 0000000..be93709
--- /dev/null
+++ b/include/hardware/bt_hd.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_HD_H
+#define ANDROID_INCLUDE_BT_HD_H
+
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+typedef enum {
+ BTHD_REPORT_TYPE_OTHER = 0,
+ BTHD_REPORT_TYPE_INPUT,
+ BTHD_REPORT_TYPE_OUTPUT,
+ BTHD_REPORT_TYPE_FEATURE,
+ // special value for reports to be sent on INTR(INPUT is assumed)
+ BTHD_REPORT_TYPE_INTRDATA
+} bthd_report_type_t;
+
+typedef enum {
+ BTHD_APP_STATE_NOT_REGISTERED,
+ BTHD_APP_STATE_REGISTERED
+} bthd_application_state_t;
+
+typedef enum {
+ BTHD_CONN_STATE_CONNECTED,
+ BTHD_CONN_STATE_CONNECTING,
+ BTHD_CONN_STATE_DISCONNECTED,
+ BTHD_CONN_STATE_DISCONNECTING,
+ BTHD_CONN_STATE_UNKNOWN
+} bthd_connection_state_t;
+
+typedef struct {
+ const char* name;
+ const char* description;
+ const char* provider;
+ uint8_t subclass;
+ uint8_t* desc_list;
+ int desc_list_len;
+} bthd_app_param_t;
+
+typedef struct {
+ uint8_t service_type;
+ uint32_t token_rate;
+ uint32_t token_bucket_size;
+ uint32_t peak_bandwidth;
+ uint32_t access_latency;
+ uint32_t delay_variation;
+} bthd_qos_param_t;
+
+typedef void (*bthd_application_state_callback)(RawAddress* bd_addr,
+ bthd_application_state_t state);
+typedef void (*bthd_connection_state_callback)(RawAddress* bd_addr,
+ bthd_connection_state_t state);
+typedef void (*bthd_get_report_callback)(uint8_t type, uint8_t id,
+ uint16_t buffer_size);
+typedef void (*bthd_set_report_callback)(uint8_t type, uint8_t id, uint16_t len,
+ uint8_t* p_data);
+typedef void (*bthd_set_protocol_callback)(uint8_t protocol);
+typedef void (*bthd_intr_data_callback)(uint8_t report_id, uint16_t len,
+ uint8_t* p_data);
+typedef void (*bthd_vc_unplug_callback)(void);
+
+/** BT-HD callbacks */
+typedef struct {
+ size_t size;
+
+ bthd_application_state_callback application_state_cb;
+ bthd_connection_state_callback connection_state_cb;
+ bthd_get_report_callback get_report_cb;
+ bthd_set_report_callback set_report_cb;
+ bthd_set_protocol_callback set_protocol_cb;
+ bthd_intr_data_callback intr_data_cb;
+ bthd_vc_unplug_callback vc_unplug_cb;
+} bthd_callbacks_t;
+
+/** BT-HD interface */
+typedef struct {
+ size_t size;
+
+ /** init interface and register callbacks */
+ bt_status_t (*init)(bthd_callbacks_t* callbacks);
+
+ /** close interface */
+ void (*cleanup)(void);
+
+ /** register application */
+ bt_status_t (*register_app)(bthd_app_param_t* app_param,
+ bthd_qos_param_t* in_qos,
+ bthd_qos_param_t* out_qos);
+
+ /** unregister application */
+ bt_status_t (*unregister_app)(void);
+
+ /** connects to host with virtual cable */
+ bt_status_t (*connect)(RawAddress* bd_addr);
+
+ /** disconnects from currently connected host */
+ bt_status_t (*disconnect)(void);
+
+ /** send report */
+ bt_status_t (*send_report)(bthd_report_type_t type, uint8_t id, uint16_t len,
+ uint8_t* p_data);
+
+ /** notifies error for invalid SET_REPORT */
+ bt_status_t (*report_error)(uint8_t error);
+
+ /** send Virtual Cable Unplug */
+ bt_status_t (*virtual_cable_unplug)(void);
+
+} bthd_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_HD_H */
diff --git a/include/hardware/bt_hearing_aid.h b/include/hardware/bt_hearing_aid.h
new file mode 100644
index 0000000..a54f82a
--- /dev/null
+++ b/include/hardware/bt_hearing_aid.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_HEARING_AID_H
+#define ANDROID_INCLUDE_BT_HEARING_AID_H
+
+#include <hardware/bluetooth.h>
+
+namespace bluetooth {
+namespace hearing_aid {
+
+enum class ConnectionState {
+ DISCONNECTED = 0,
+ CONNECTING,
+ CONNECTED,
+ DISCONNECTING
+};
+
+class HearingAidCallbacks {
+ public:
+ virtual ~HearingAidCallbacks() = default;
+
+ /** Callback for profile connection state change */
+ virtual void OnConnectionState(ConnectionState state,
+ const RawAddress& address) = 0;
+
+ /** Callback for device being available. Is executed when devices are loaded
+ * from storage on stack bringup, and when new device is connected to profile.
+ * Main purpose of this callback is to keep its users informed of device
+ * capabilities and hiSyncId.
+ */
+ virtual void OnDeviceAvailable(uint8_t capabilities, uint64_t hiSyncId,
+ const RawAddress& address) = 0;
+};
+
+class HearingAidInterface {
+ public:
+ virtual ~HearingAidInterface() = default;
+
+ /** Register the Hearing Aid callbacks */
+ virtual void Init(HearingAidCallbacks* callbacks) = 0;
+
+ /** Connect to Hearing Aid */
+ virtual void Connect(const RawAddress& address) = 0;
+
+ /** Disconnect from Hearing Aid */
+ virtual void Disconnect(const RawAddress& address) = 0;
+
+ /** Set the volume */
+ virtual void SetVolume(int8_t volume) = 0;
+
+ /** Closes the interface. */
+ virtual void Cleanup(void) = 0;
+
+ /* Called when Hearing Aid is unbonded. */
+ virtual void RemoveDevice(const RawAddress& address) = 0;
+};
+
+} // namespace hearing_aid
+} // namespace bluetooth
+
+#endif /* ANDROID_INCLUDE_BT_HEARING_AID_H */
diff --git a/include/hardware/bt_hf.h b/include/hardware/bt_hf.h
new file mode 100644
index 0000000..ac2de4d
--- /dev/null
+++ b/include/hardware/bt_hf.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace bluetooth {
+namespace headset {
+
+/* AT response code - OK/Error */
+typedef enum {
+ BTHF_AT_RESPONSE_ERROR = 0,
+ BTHF_AT_RESPONSE_OK
+} bthf_at_response_t;
+
+typedef enum {
+ BTHF_CONNECTION_STATE_DISCONNECTED = 0,
+ BTHF_CONNECTION_STATE_CONNECTING,
+ BTHF_CONNECTION_STATE_CONNECTED,
+ BTHF_CONNECTION_STATE_SLC_CONNECTED,
+ BTHF_CONNECTION_STATE_DISCONNECTING
+} bthf_connection_state_t;
+
+typedef enum {
+ BTHF_AUDIO_STATE_DISCONNECTED = 0,
+ BTHF_AUDIO_STATE_CONNECTING,
+ BTHF_AUDIO_STATE_CONNECTED,
+ BTHF_AUDIO_STATE_DISCONNECTING
+} bthf_audio_state_t;
+
+typedef enum {
+ BTHF_VR_STATE_STOPPED = 0,
+ BTHF_VR_STATE_STARTED
+} bthf_vr_state_t;
+
+typedef enum {
+ BTHF_VOLUME_TYPE_SPK = 0,
+ BTHF_VOLUME_TYPE_MIC
+} bthf_volume_type_t;
+
+/* Noise Reduction and Echo Cancellation */
+typedef enum { BTHF_NREC_STOP, BTHF_NREC_START } bthf_nrec_t;
+
+/* WBS codec setting */
+typedef enum { BTHF_WBS_NONE, BTHF_WBS_NO, BTHF_WBS_YES } bthf_wbs_config_t;
+
+/* CHLD - Call held handling */
+typedef enum {
+ BTHF_CHLD_TYPE_RELEASEHELD, // Terminate all held or set UDUB("busy") to a
+ // waiting call
+ BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD, // Terminate all active calls and
+ // accepts a waiting/held call
+ BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD, // Hold all active calls and accepts a
+ // waiting/held call
+ BTHF_CHLD_TYPE_ADDHELDTOCONF, // Add all held calls to a conference
+} bthf_chld_type_t;
+
+/* HF Indicators HFP 1.7 */
+typedef enum {
+ BTHF_HF_IND_ENHANCED_DRIVER_SAFETY = 1,
+ BTHF_HF_IND_BATTERY_LEVEL_STATUS = 2,
+} bthf_hf_ind_type_t;
+
+typedef enum {
+ BTHF_HF_IND_DISABLED = 0,
+ BTHF_HF_IND_ENABLED,
+} bthf_hf_ind_status_t;
+
+/** Network Status */
+typedef enum {
+ BTHF_NETWORK_STATE_NOT_AVAILABLE = 0,
+ BTHF_NETWORK_STATE_AVAILABLE
+} bthf_network_state_t;
+
+/** Service type */
+typedef enum {
+ BTHF_SERVICE_TYPE_HOME = 0,
+ BTHF_SERVICE_TYPE_ROAMING
+} bthf_service_type_t;
+
+typedef enum {
+ BTHF_CALL_STATE_ACTIVE = 0,
+ BTHF_CALL_STATE_HELD,
+ BTHF_CALL_STATE_DIALING,
+ BTHF_CALL_STATE_ALERTING,
+ BTHF_CALL_STATE_INCOMING,
+ BTHF_CALL_STATE_WAITING,
+ BTHF_CALL_STATE_IDLE,
+ BTHF_CALL_STATE_DISCONNECTED
+} bthf_call_state_t;
+
+typedef enum {
+ BTHF_CALL_DIRECTION_OUTGOING = 0,
+ BTHF_CALL_DIRECTION_INCOMING
+} bthf_call_direction_t;
+
+typedef enum {
+ BTHF_CALL_TYPE_VOICE = 0,
+ BTHF_CALL_TYPE_DATA,
+ BTHF_CALL_TYPE_FAX
+} bthf_call_mode_t;
+
+typedef enum {
+ BTHF_CALL_MPTY_TYPE_SINGLE = 0,
+ BTHF_CALL_MPTY_TYPE_MULTI
+} bthf_call_mpty_type_t;
+
+typedef enum {
+ BTHF_CALL_ADDRTYPE_UNKNOWN = 0x81,
+ BTHF_CALL_ADDRTYPE_INTERNATIONAL = 0x91
+} bthf_call_addrtype_t;
+
+} // namespace headset
+} // namespace bluetooth
\ No newline at end of file
diff --git a/include/hardware/bt_hf_client.h b/include/hardware/bt_hf_client.h
new file mode 100644
index 0000000..a31de0f
--- /dev/null
+++ b/include/hardware/bt_hf_client.h
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2012-2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_HF_CLIENT_H
+#define ANDROID_INCLUDE_BT_HF_CLIENT_H
+
+__BEGIN_DECLS
+
+typedef enum {
+ BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED = 0,
+ BTHF_CLIENT_CONNECTION_STATE_CONNECTING,
+ BTHF_CLIENT_CONNECTION_STATE_CONNECTED,
+ BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED,
+ BTHF_CLIENT_CONNECTION_STATE_DISCONNECTING
+} bthf_client_connection_state_t;
+
+typedef enum {
+ BTHF_CLIENT_AUDIO_STATE_DISCONNECTED = 0,
+ BTHF_CLIENT_AUDIO_STATE_CONNECTING,
+ BTHF_CLIENT_AUDIO_STATE_CONNECTED,
+ BTHF_CLIENT_AUDIO_STATE_CONNECTED_MSBC,
+} bthf_client_audio_state_t;
+
+typedef enum {
+ BTHF_CLIENT_VR_STATE_STOPPED = 0,
+ BTHF_CLIENT_VR_STATE_STARTED
+} bthf_client_vr_state_t;
+
+typedef enum {
+ BTHF_CLIENT_VOLUME_TYPE_SPK = 0,
+ BTHF_CLIENT_VOLUME_TYPE_MIC
+} bthf_client_volume_type_t;
+
+typedef enum {
+ BTHF_CLIENT_NETWORK_STATE_NOT_AVAILABLE = 0,
+ BTHF_CLIENT_NETWORK_STATE_AVAILABLE
+} bthf_client_network_state_t;
+
+typedef enum {
+ BTHF_CLIENT_SERVICE_TYPE_HOME = 0,
+ BTHF_CLIENT_SERVICE_TYPE_ROAMING
+} bthf_client_service_type_t;
+
+typedef enum {
+ BTHF_CLIENT_CALL_STATE_ACTIVE = 0,
+ BTHF_CLIENT_CALL_STATE_HELD,
+ BTHF_CLIENT_CALL_STATE_DIALING,
+ BTHF_CLIENT_CALL_STATE_ALERTING,
+ BTHF_CLIENT_CALL_STATE_INCOMING,
+ BTHF_CLIENT_CALL_STATE_WAITING,
+ BTHF_CLIENT_CALL_STATE_HELD_BY_RESP_HOLD,
+} bthf_client_call_state_t;
+
+typedef enum {
+ BTHF_CLIENT_CALL_NO_CALLS_IN_PROGRESS = 0,
+ BTHF_CLIENT_CALL_CALLS_IN_PROGRESS
+} bthf_client_call_t;
+
+typedef enum {
+ BTHF_CLIENT_CALLSETUP_NONE = 0,
+ BTHF_CLIENT_CALLSETUP_INCOMING,
+ BTHF_CLIENT_CALLSETUP_OUTGOING,
+ BTHF_CLIENT_CALLSETUP_ALERTING
+
+} bthf_client_callsetup_t;
+
+typedef enum {
+ BTHF_CLIENT_CALLHELD_NONE = 0,
+ BTHF_CLIENT_CALLHELD_HOLD_AND_ACTIVE,
+ BTHF_CLIENT_CALLHELD_HOLD,
+} bthf_client_callheld_t;
+
+typedef enum {
+ BTHF_CLIENT_RESP_AND_HOLD_HELD = 0,
+ BTRH_CLIENT_RESP_AND_HOLD_ACCEPT,
+ BTRH_CLIENT_RESP_AND_HOLD_REJECT,
+} bthf_client_resp_and_hold_t;
+
+typedef enum {
+ BTHF_CLIENT_CALL_DIRECTION_OUTGOING = 0,
+ BTHF_CLIENT_CALL_DIRECTION_INCOMING
+} bthf_client_call_direction_t;
+
+typedef enum {
+ BTHF_CLIENT_CALL_MPTY_TYPE_SINGLE = 0,
+ BTHF_CLIENT_CALL_MPTY_TYPE_MULTI
+} bthf_client_call_mpty_type_t;
+
+typedef enum {
+ BTHF_CLIENT_CMD_COMPLETE_OK = 0,
+ BTHF_CLIENT_CMD_COMPLETE_ERROR,
+ BTHF_CLIENT_CMD_COMPLETE_ERROR_NO_CARRIER,
+ BTHF_CLIENT_CMD_COMPLETE_ERROR_BUSY,
+ BTHF_CLIENT_CMD_COMPLETE_ERROR_NO_ANSWER,
+ BTHF_CLIENT_CMD_COMPLETE_ERROR_DELAYED,
+ BTHF_CLIENT_CMD_COMPLETE_ERROR_BLACKLISTED,
+ BTHF_CLIENT_CMD_COMPLETE_ERROR_CME
+} bthf_client_cmd_complete_t;
+
+typedef enum {
+ BTHF_CLIENT_CALL_ACTION_CHLD_0 = 0,
+ BTHF_CLIENT_CALL_ACTION_CHLD_1,
+ BTHF_CLIENT_CALL_ACTION_CHLD_2,
+ BTHF_CLIENT_CALL_ACTION_CHLD_3,
+ BTHF_CLIENT_CALL_ACTION_CHLD_4,
+ BTHF_CLIENT_CALL_ACTION_CHLD_1x,
+ BTHF_CLIENT_CALL_ACTION_CHLD_2x,
+ BTHF_CLIENT_CALL_ACTION_ATA,
+ BTHF_CLIENT_CALL_ACTION_CHUP,
+ BTHF_CLIENT_CALL_ACTION_BTRH_0,
+ BTHF_CLIENT_CALL_ACTION_BTRH_1,
+ BTHF_CLIENT_CALL_ACTION_BTRH_2,
+} bthf_client_call_action_t;
+
+typedef enum {
+ BTHF_CLIENT_SERVICE_UNKNOWN = 0,
+ BTHF_CLIENT_SERVICE_VOICE,
+ BTHF_CLIENT_SERVICE_FAX
+} bthf_client_subscriber_service_type_t;
+
+typedef enum {
+ BTHF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED = 0,
+ BTHF_CLIENT_IN_BAND_RINGTONE_PROVIDED,
+} bthf_client_in_band_ring_state_t;
+
+/* Peer features masks */
+#define BTHF_CLIENT_PEER_FEAT_3WAY 0x00000001 /* Three-way calling */
+#define BTHF_CLIENT_PEER_FEAT_ECNR \
+ 0x00000002 /* Echo cancellation and/or noise reduction */
+#define BTHF_CLIENT_PEER_FEAT_VREC 0x00000004 /* Voice recognition */
+#define BTHF_CLIENT_PEER_FEAT_INBAND 0x00000008 /* In-band ring tone */
+#define BTHF_CLIENT_PEER_FEAT_VTAG \
+ 0x00000010 /* Attach a phone number to a voice tag */
+#define BTHF_CLIENT_PEER_FEAT_REJECT \
+ 0x00000020 /* Ability to reject incoming call */
+#define BTHF_CLIENT_PEER_FEAT_ECS 0x00000040 /* Enhanced Call Status */
+#define BTHF_CLIENT_PEER_FEAT_ECC 0x00000080 /* Enhanced Call Control */
+#define BTHF_CLIENT_PEER_FEAT_EXTERR 0x00000100 /* Extended error codes */
+#define BTHF_CLIENT_PEER_FEAT_CODEC 0x00000200 /* Codec Negotiation */
+
+/* Peer call handling features masks */
+#define BTHF_CLIENT_CHLD_FEAT_REL \
+ 0x00000001 /* 0 Release waiting call or held calls */
+#define BTHF_CLIENT_CHLD_FEAT_REL_ACC \
+ 0x00000002 /* 1 Release active calls and accept other \
+ (waiting or held) cal */
+#define BTHF_CLIENT_CHLD_FEAT_REL_X \
+ 0x00000004 /* 1x Release specified active call only */
+#define BTHF_CLIENT_CHLD_FEAT_HOLD_ACC \
+ 0x00000008 /* 2 Active calls on hold and accept other \
+ (waiting or held) call */
+#define BTHF_CLIENT_CHLD_FEAT_PRIV_X \
+ 0x00000010 /* 2x Request private mode with specified \
+ call (put the rest on hold) */
+#define BTHF_CLIENT_CHLD_FEAT_MERGE \
+ 0x00000020 /* 3 Add held call to multiparty */
+#define BTHF_CLIENT_CHLD_FEAT_MERGE_DETACH \
+ 0x00000040 /* 4 Connect two calls and leave \
+ (disconnect from) multiparty */
+
+/** Callback for connection state change.
+ * state will have one of the values from BtHfConnectionState
+ * peer/chld_features are valid only for
+ * BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED state
+ */
+typedef void (*bthf_client_connection_state_callback)(
+ const RawAddress* bd_addr, bthf_client_connection_state_t state,
+ unsigned int peer_feat, unsigned int chld_feat);
+
+/** Callback for audio connection state change.
+ * state will have one of the values from BtHfAudioState
+ */
+typedef void (*bthf_client_audio_state_callback)(
+ const RawAddress* bd_addr, bthf_client_audio_state_t state);
+
+/** Callback for VR connection state change.
+ * state will have one of the values from BtHfVRState
+ */
+typedef void (*bthf_client_vr_cmd_callback)(const RawAddress* bd_addr,
+ bthf_client_vr_state_t state);
+
+/** Callback for network state change
+ */
+typedef void (*bthf_client_network_state_callback)(
+ const RawAddress* bd_addr, bthf_client_network_state_t state);
+
+/** Callback for network roaming status change
+ */
+typedef void (*bthf_client_network_roaming_callback)(
+ const RawAddress* bd_addr, bthf_client_service_type_t type);
+
+/** Callback for signal strength indication
+ */
+typedef void (*bthf_client_network_signal_callback)(const RawAddress* bd_addr,
+ int signal_strength);
+
+/** Callback for battery level indication
+ */
+typedef void (*bthf_client_battery_level_callback)(const RawAddress* bd_addr,
+ int battery_level);
+
+/** Callback for current operator name
+ */
+typedef void (*bthf_client_current_operator_callback)(const RawAddress* bd_addr,
+ const char* name);
+
+/** Callback for call indicator
+ */
+typedef void (*bthf_client_call_callback)(const RawAddress* bd_addr,
+ bthf_client_call_t call);
+
+/** Callback for callsetup indicator
+ */
+typedef void (*bthf_client_callsetup_callback)(
+ const RawAddress* bd_addr, bthf_client_callsetup_t callsetup);
+
+/** Callback for callheld indicator
+ */
+typedef void (*bthf_client_callheld_callback)(const RawAddress* bd_addr,
+ bthf_client_callheld_t callheld);
+
+/** Callback for response and hold
+ */
+typedef void (*bthf_client_resp_and_hold_callback)(
+ const RawAddress* bd_addr, bthf_client_resp_and_hold_t resp_and_hold);
+
+/** Callback for Calling Line Identification notification
+ * Will be called only when there is an incoming call and number is provided.
+ */
+typedef void (*bthf_client_clip_callback)(const RawAddress* bd_addr,
+ const char* number);
+
+/**
+ * Callback for Call Waiting notification
+ */
+typedef void (*bthf_client_call_waiting_callback)(const RawAddress* bd_addr,
+ const char* number);
+
+/**
+ * Callback for listing current calls. Can be called multiple time.
+ * If number is unknown NULL is passed.
+ */
+typedef void (*bthf_client_current_calls)(const RawAddress* bd_addr, int index,
+ bthf_client_call_direction_t dir,
+ bthf_client_call_state_t state,
+ bthf_client_call_mpty_type_t mpty,
+ const char* number);
+
+/** Callback for audio volume change
+ */
+typedef void (*bthf_client_volume_change_callback)(
+ const RawAddress* bd_addr, bthf_client_volume_type_t type, int volume);
+
+/** Callback for command complete event
+ * cme is valid only for BTHF_CLIENT_CMD_COMPLETE_ERROR_CME type
+ */
+typedef void (*bthf_client_cmd_complete_callback)(
+ const RawAddress* bd_addr, bthf_client_cmd_complete_t type, int cme);
+
+/** Callback for subscriber information
+ */
+typedef void (*bthf_client_subscriber_info_callback)(
+ const RawAddress* bd_addr, const char* name,
+ bthf_client_subscriber_service_type_t type);
+
+/** Callback for in-band ring tone settings
+ */
+typedef void (*bthf_client_in_band_ring_tone_callback)(
+ const RawAddress* bd_addr, bthf_client_in_band_ring_state_t state);
+
+/**
+ * Callback for requested number from AG
+ */
+typedef void (*bthf_client_last_voice_tag_number_callback)(
+ const RawAddress* bd_addr, const char* number);
+
+/**
+ * Callback for sending ring indication to app
+ */
+typedef void (*bthf_client_ring_indication_callback)(const RawAddress* bd_addr);
+
+/** BT-HF callback structure. */
+typedef struct {
+ /** set to sizeof(BtHfClientCallbacks) */
+ size_t size;
+ bthf_client_connection_state_callback connection_state_cb;
+ bthf_client_audio_state_callback audio_state_cb;
+ bthf_client_vr_cmd_callback vr_cmd_cb;
+ bthf_client_network_state_callback network_state_cb;
+ bthf_client_network_roaming_callback network_roaming_cb;
+ bthf_client_network_signal_callback network_signal_cb;
+ bthf_client_battery_level_callback battery_level_cb;
+ bthf_client_current_operator_callback current_operator_cb;
+ bthf_client_call_callback call_cb;
+ bthf_client_callsetup_callback callsetup_cb;
+ bthf_client_callheld_callback callheld_cb;
+ bthf_client_resp_and_hold_callback resp_and_hold_cb;
+ bthf_client_clip_callback clip_cb;
+ bthf_client_call_waiting_callback call_waiting_cb;
+ bthf_client_current_calls current_calls_cb;
+ bthf_client_volume_change_callback volume_change_cb;
+ bthf_client_cmd_complete_callback cmd_complete_cb;
+ bthf_client_subscriber_info_callback subscriber_info_cb;
+ bthf_client_in_band_ring_tone_callback in_band_ring_tone_cb;
+ bthf_client_last_voice_tag_number_callback last_voice_tag_number_callback;
+ bthf_client_ring_indication_callback ring_indication_cb;
+} bthf_client_callbacks_t;
+
+/** Represents the standard BT-HF interface. */
+typedef struct {
+ /** set to sizeof(BtHfClientInterface) */
+ size_t size;
+ /**
+ * Register the BtHf callbacks
+ */
+ bt_status_t (*init)(bthf_client_callbacks_t* callbacks);
+
+ /** connect to audio gateway */
+ bt_status_t (*connect)(RawAddress* bd_addr);
+
+ /** disconnect from audio gateway */
+ bt_status_t (*disconnect)(const RawAddress* bd_addr);
+
+ /** create an audio connection */
+ bt_status_t (*connect_audio)(const RawAddress* bd_addr);
+
+ /** close the audio connection */
+ bt_status_t (*disconnect_audio)(const RawAddress* bd_addr);
+
+ /** start voice recognition */
+ bt_status_t (*start_voice_recognition)(const RawAddress* bd_addr);
+
+ /** stop voice recognition */
+ bt_status_t (*stop_voice_recognition)(const RawAddress* bd_addr);
+
+ /** volume control */
+ bt_status_t (*volume_control)(const RawAddress* bd_addr,
+ bthf_client_volume_type_t type, int volume);
+
+ /** place a call with number a number
+ * if number is NULL last called number is called (aka re-dial)*/
+ bt_status_t (*dial)(const RawAddress* bd_addr, const char* number);
+
+ /** place a call with number specified by location (speed dial) */
+ bt_status_t (*dial_memory)(const RawAddress* bd_addr, int location);
+
+ /** perform specified call related action
+ * idx is limited only for enhanced call control related action
+ */
+ bt_status_t (*handle_call_action)(const RawAddress* bd_addr,
+ bthf_client_call_action_t action, int idx);
+
+ /** query list of current calls */
+ bt_status_t (*query_current_calls)(const RawAddress* bd_addr);
+
+ /** query name of current selected operator */
+ bt_status_t (*query_current_operator_name)(const RawAddress* bd_addr);
+
+ /** Retrieve subscriber information */
+ bt_status_t (*retrieve_subscriber_info)(const RawAddress* bd_addr);
+
+ /** Send DTMF code*/
+ bt_status_t (*send_dtmf)(const RawAddress* bd_addr, char code);
+
+ /** Request a phone number from AG corresponding to last voice tag recorded */
+ bt_status_t (*request_last_voice_tag_number)(const RawAddress* bd_addr);
+
+ /** Closes the interface. */
+ void (*cleanup)(void);
+
+ /** Send AT Command. */
+ bt_status_t (*send_at_cmd)(const RawAddress* bd_addr, int cmd, int val1,
+ int val2, const char* arg);
+} bthf_client_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_HF_CLIENT_H */
diff --git a/include/hardware/bt_hh.h b/include/hardware/bt_hh.h
new file mode 100644
index 0000000..b87b129
--- /dev/null
+++ b/include/hardware/bt_hh.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_HH_H
+#define ANDROID_INCLUDE_BT_HH_H
+
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+#define BTHH_MAX_DSC_LEN 884
+
+/* HH connection states */
+typedef enum {
+ BTHH_CONN_STATE_CONNECTED = 0,
+ BTHH_CONN_STATE_CONNECTING,
+ BTHH_CONN_STATE_DISCONNECTED,
+ BTHH_CONN_STATE_DISCONNECTING,
+ BTHH_CONN_STATE_FAILED_MOUSE_FROM_HOST,
+ BTHH_CONN_STATE_FAILED_KBD_FROM_HOST,
+ BTHH_CONN_STATE_FAILED_TOO_MANY_DEVICES,
+ BTHH_CONN_STATE_FAILED_NO_BTHID_DRIVER,
+ BTHH_CONN_STATE_FAILED_GENERIC,
+ BTHH_CONN_STATE_UNKNOWN
+} bthh_connection_state_t;
+
+typedef enum {
+ BTHH_OK = 0,
+ BTHH_HS_HID_NOT_READY, /* handshake error : device not ready */
+ BTHH_HS_INVALID_RPT_ID, /* handshake error : invalid report ID */
+ BTHH_HS_TRANS_NOT_SPT, /* handshake error : transaction not spt */
+ BTHH_HS_INVALID_PARAM, /* handshake error : invalid paremter */
+ BTHH_HS_ERROR, /* handshake error : unspecified HS error */
+ BTHH_ERR, /* general BTA HH error */
+ BTHH_ERR_SDP, /* SDP error */
+ BTHH_ERR_PROTO, /* SET_Protocol error,
+ only used in BTA_HH_OPEN_EVT
+ callback */
+ BTHH_ERR_DB_FULL, /* device database full error, used */
+ BTHH_ERR_TOD_UNSPT, /* type of device not supported */
+ BTHH_ERR_NO_RES, /* out of system resources */
+ BTHH_ERR_AUTH_FAILED, /* authentication fail */
+ BTHH_ERR_HDL
+} bthh_status_t;
+
+/* Protocol modes */
+typedef enum {
+ BTHH_REPORT_MODE = 0x00,
+ BTHH_BOOT_MODE = 0x01,
+ BTHH_UNSUPPORTED_MODE = 0xff
+} bthh_protocol_mode_t;
+
+/* Report types */
+typedef enum {
+ BTHH_INPUT_REPORT = 1,
+ BTHH_OUTPUT_REPORT,
+ BTHH_FEATURE_REPORT
+} bthh_report_type_t;
+
+typedef struct {
+ int attr_mask;
+ uint8_t sub_class;
+ uint8_t app_id;
+ int vendor_id;
+ int product_id;
+ int version;
+ uint8_t ctry_code;
+ int dl_len;
+ uint8_t dsc_list[BTHH_MAX_DSC_LEN];
+} bthh_hid_info_t;
+
+/** Callback for connection state change.
+ * state will have one of the values from bthh_connection_state_t
+ */
+typedef void (*bthh_connection_state_callback)(RawAddress* bd_addr,
+ bthh_connection_state_t state);
+
+/** Callback for vitual unplug api.
+ * the status of the vitual unplug
+ */
+typedef void (*bthh_virtual_unplug_callback)(RawAddress* bd_addr,
+ bthh_status_t hh_status);
+
+/** Callback for get hid info
+ * hid_info will contain attr_mask, sub_class, app_id, vendor_id, product_id,
+ * version, ctry_code, len
+ */
+typedef void (*bthh_hid_info_callback)(RawAddress* bd_addr,
+ bthh_hid_info_t hid_info);
+
+/** Callback for get protocol api.
+ * the protocol mode is one of the value from bthh_protocol_mode_t
+ */
+typedef void (*bthh_protocol_mode_callback)(RawAddress* bd_addr,
+ bthh_status_t hh_status,
+ bthh_protocol_mode_t mode);
+
+/** Callback for get/set_idle_time api.
+ */
+typedef void (*bthh_idle_time_callback)(RawAddress* bd_addr,
+ bthh_status_t hh_status, int idle_rate);
+
+/** Callback for get report api.
+ * if staus is ok rpt_data contains the report data
+ */
+typedef void (*bthh_get_report_callback)(RawAddress* bd_addr,
+ bthh_status_t hh_status,
+ uint8_t* rpt_data, int rpt_size);
+
+/** Callback for set_report/set_protocol api and if error
+ * occurs for get_report/get_protocol api.
+ */
+typedef void (*bthh_handshake_callback)(RawAddress* bd_addr,
+ bthh_status_t hh_status);
+
+/** BT-HH callback structure. */
+typedef struct {
+ /** set to sizeof(BtHfCallbacks) */
+ size_t size;
+ bthh_connection_state_callback connection_state_cb;
+ bthh_hid_info_callback hid_info_cb;
+ bthh_protocol_mode_callback protocol_mode_cb;
+ bthh_idle_time_callback idle_time_cb;
+ bthh_get_report_callback get_report_cb;
+ bthh_virtual_unplug_callback virtual_unplug_cb;
+ bthh_handshake_callback handshake_cb;
+
+} bthh_callbacks_t;
+
+/** Represents the standard BT-HH interface. */
+typedef struct {
+ /** set to sizeof(BtHhInterface) */
+ size_t size;
+
+ /**
+ * Register the BtHh callbacks
+ */
+ bt_status_t (*init)(bthh_callbacks_t* callbacks);
+
+ /** connect to hid device */
+ bt_status_t (*connect)(RawAddress* bd_addr);
+
+ /** dis-connect from hid device */
+ bt_status_t (*disconnect)(RawAddress* bd_addr);
+
+ /** Virtual UnPlug (VUP) the specified HID device */
+ bt_status_t (*virtual_unplug)(RawAddress* bd_addr);
+
+ /** Set the HID device descriptor for the specified HID device. */
+ bt_status_t (*set_info)(RawAddress* bd_addr, bthh_hid_info_t hid_info);
+
+ /** Get the HID proto mode. */
+ bt_status_t (*get_protocol)(RawAddress* bd_addr,
+ bthh_protocol_mode_t protocolMode);
+
+ /** Set the HID proto mode. */
+ bt_status_t (*set_protocol)(RawAddress* bd_addr,
+ bthh_protocol_mode_t protocolMode);
+
+ /** Get the HID Idle Time */
+ bt_status_t (*get_idle_time)(RawAddress* bd_addr);
+
+ /** Set the HID Idle Time */
+ bt_status_t (*set_idle_time)(RawAddress* bd_addr, uint8_t idleTime);
+
+ /** Send a GET_REPORT to HID device. */
+ bt_status_t (*get_report)(RawAddress* bd_addr, bthh_report_type_t reportType,
+ uint8_t reportId, int bufferSize);
+
+ /** Send a SET_REPORT to HID device. */
+ bt_status_t (*set_report)(RawAddress* bd_addr, bthh_report_type_t reportType,
+ char* report);
+
+ /** Send data to HID device. */
+ bt_status_t (*send_data)(RawAddress* bd_addr, char* data);
+
+ /** Closes the interface. */
+ void (*cleanup)(void);
+
+} bthh_interface_t;
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_HH_H */
diff --git a/include/hardware/bt_hl.h b/include/hardware/bt_hl.h
new file mode 100644
index 0000000..682605b
--- /dev/null
+++ b/include/hardware/bt_hl.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_HL_H
+#define ANDROID_INCLUDE_BT_HL_H
+
+__BEGIN_DECLS
+
+/* HL connection states */
+
+typedef enum { BTHL_MDEP_ROLE_SOURCE, BTHL_MDEP_ROLE_SINK } bthl_mdep_role_t;
+
+typedef enum {
+ BTHL_APP_REG_STATE_REG_SUCCESS,
+ BTHL_APP_REG_STATE_REG_FAILED,
+ BTHL_APP_REG_STATE_DEREG_SUCCESS,
+ BTHL_APP_REG_STATE_DEREG_FAILED
+} bthl_app_reg_state_t;
+
+typedef enum {
+ BTHL_CHANNEL_TYPE_RELIABLE,
+ BTHL_CHANNEL_TYPE_STREAMING,
+ BTHL_CHANNEL_TYPE_ANY
+} bthl_channel_type_t;
+
+/* HL connection states */
+typedef enum {
+ BTHL_CONN_STATE_CONNECTING,
+ BTHL_CONN_STATE_CONNECTED,
+ BTHL_CONN_STATE_DISCONNECTING,
+ BTHL_CONN_STATE_DISCONNECTED,
+ BTHL_CONN_STATE_DESTROYED
+} bthl_channel_state_t;
+
+typedef struct {
+ bthl_mdep_role_t mdep_role;
+ int data_type;
+ bthl_channel_type_t channel_type;
+ const char* mdep_description; /* MDEP description to be used in the SDP
+ (optional); null terminated */
+} bthl_mdep_cfg_t;
+
+typedef struct {
+ const char* application_name;
+ const char*
+ provider_name; /* provider name to be used in the SDP (optional); null
+ terminated */
+ const char* srv_name; /* service name to be used in the SDP (optional); null
+ terminated*/
+ const char*
+ srv_desp; /* service description to be used in the SDP (optional); null
+ terminated */
+ int number_of_mdeps;
+ bthl_mdep_cfg_t* mdep_cfg; /* Dynamic array */
+} bthl_reg_param_t;
+
+/** Callback for application registration status.
+ * state will have one of the values from bthl_app_reg_state_t
+ */
+typedef void (*bthl_app_reg_state_callback)(int app_id,
+ bthl_app_reg_state_t state);
+
+/** Callback for channel connection state change.
+ * state will have one of the values from
+ * bthl_connection_state_t and fd (file descriptor)
+ */
+typedef void (*bthl_channel_state_callback)(int app_id, RawAddress* bd_addr,
+ int mdep_cfg_index, int channel_id,
+ bthl_channel_state_t state, int fd);
+
+/** BT-HL callback structure. */
+typedef struct {
+ /** set to sizeof(bthl_callbacks_t) */
+ size_t size;
+ bthl_app_reg_state_callback app_reg_state_cb;
+ bthl_channel_state_callback channel_state_cb;
+} bthl_callbacks_t;
+
+/** Represents the standard BT-HL interface. */
+typedef struct {
+ /** set to sizeof(bthl_interface_t) */
+ size_t size;
+
+ /**
+ * Register the Bthl callbacks
+ */
+ bt_status_t (*init)(bthl_callbacks_t* callbacks);
+
+ /** Register HL application */
+ bt_status_t (*register_application)(bthl_reg_param_t* p_reg_param,
+ int* app_id);
+
+ /** Unregister HL application */
+ bt_status_t (*unregister_application)(int app_id);
+
+ /** connect channel */
+ bt_status_t (*connect_channel)(int app_id, RawAddress* bd_addr,
+ int mdep_cfg_index, int* channel_id);
+
+ /** destroy channel */
+ bt_status_t (*destroy_channel)(int channel_id);
+
+ /** Close the Bthl callback **/
+ void (*cleanup)(void);
+
+} bthl_interface_t;
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_HL_H */
diff --git a/include/hardware/bt_mce.h b/include/hardware/bt_mce.h
new file mode 100644
index 0000000..0bb15d4
--- /dev/null
+++ b/include/hardware/bt_mce.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_MCE_H
+#define ANDROID_INCLUDE_BT_MCE_H
+
+__BEGIN_DECLS
+
+/** MAS instance description */
+typedef struct {
+ int id;
+ int scn;
+ int msg_types;
+ char* p_name;
+} btmce_mas_instance_t;
+
+/** callback for get_remote_mas_instances */
+typedef void (*btmce_remote_mas_instances_callback)(
+ bt_status_t status, RawAddress* bd_addr, int num_instances,
+ btmce_mas_instance_t* instances);
+
+typedef struct {
+ /** set to sizeof(btmce_callbacks_t) */
+ size_t size;
+ btmce_remote_mas_instances_callback remote_mas_instances_cb;
+} btmce_callbacks_t;
+
+typedef struct {
+ /** set to size of this struct */
+ size_t size;
+
+ /** register BT MCE callbacks */
+ bt_status_t (*init)(btmce_callbacks_t* callbacks);
+
+ /** search for MAS instances on remote device */
+ bt_status_t (*get_remote_mas_instances)(RawAddress* bd_addr);
+} btmce_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_MCE_H */
diff --git a/include/hardware/bt_pan.h b/include/hardware/bt_pan.h
new file mode 100644
index 0000000..90caa5d
--- /dev/null
+++ b/include/hardware/bt_pan.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_PAN_H
+#define ANDROID_INCLUDE_BT_PAN_H
+
+__BEGIN_DECLS
+
+#define BTPAN_ROLE_NONE 0
+#define BTPAN_ROLE_PANNAP 1
+#define BTPAN_ROLE_PANU 2
+
+typedef enum {
+ BTPAN_STATE_CONNECTED = 0,
+ BTPAN_STATE_CONNECTING = 1,
+ BTPAN_STATE_DISCONNECTED = 2,
+ BTPAN_STATE_DISCONNECTING = 3
+} btpan_connection_state_t;
+
+typedef enum {
+ BTPAN_STATE_ENABLED = 0,
+ BTPAN_STATE_DISABLED = 1
+} btpan_control_state_t;
+
+/**
+ * Callback for pan connection state
+ */
+typedef void (*btpan_connection_state_callback)(btpan_connection_state_t state,
+ bt_status_t error,
+ const RawAddress* bd_addr,
+ int local_role,
+ int remote_role);
+typedef void (*btpan_control_state_callback)(btpan_control_state_t state,
+ int local_role, bt_status_t error,
+ const char* ifname);
+
+typedef struct {
+ size_t size;
+ btpan_control_state_callback control_state_cb;
+ btpan_connection_state_callback connection_state_cb;
+} btpan_callbacks_t;
+typedef struct {
+ /** set to size of this struct*/
+ size_t size;
+ /**
+ * Initialize the pan interface and register the btpan callbacks
+ */
+ bt_status_t (*init)(const btpan_callbacks_t* callbacks);
+ /*
+ * enable the pan service by specified role. The result state of
+ * enabl will be returned by btpan_control_state_callback. when pan-nap is
+ * enabled, the state of connecting panu device will be notified by
+ * btpan_connection_state_callback
+ */
+ bt_status_t (*enable)(int local_role);
+ /*
+ * get current pan local role
+ */
+ int (*get_local_role)(void);
+ /**
+ * start bluetooth pan connection to the remote device by specified pan role.
+ * The result state will be returned by btpan_connection_state_callback
+ */
+ bt_status_t (*connect)(const RawAddress* bd_addr, int local_role,
+ int remote_role);
+ /**
+ * stop bluetooth pan connection. The result state will be returned by
+ * btpan_connection_state_callback
+ */
+ bt_status_t (*disconnect)(const RawAddress* bd_addr);
+
+ /**
+ * Cleanup the pan interface
+ */
+ void (*cleanup)(void);
+
+} btpan_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_PAN_H */
diff --git a/include/hardware/bt_rc.h b/include/hardware/bt_rc.h
new file mode 100644
index 0000000..9349eed
--- /dev/null
+++ b/include/hardware/bt_rc.h
@@ -0,0 +1,709 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_RC_H
+#define ANDROID_INCLUDE_BT_RC_H
+
+__BEGIN_DECLS
+
+/* Change this macro to use multiple RC */
+#define BT_RC_NUM_APP 6
+
+/* Macros */
+#define BTRC_MAX_ATTR_STR_LEN (1 << 16)
+#define BTRC_UID_SIZE 8
+#define BTRC_MAX_APP_SETTINGS 8
+#define BTRC_MAX_FOLDER_DEPTH 4
+#define BTRC_MAX_APP_ATTR_SIZE 16
+#define BTRC_MAX_ELEM_ATTR_SIZE 8
+#define BTRC_FEATURE_BIT_MASK_SIZE 16
+
+/* Macros for valid scopes in get_folder_items */
+#define BTRC_SCOPE_PLAYER_LIST 0x00 /* Media Player List */
+#define BTRC_SCOPE_FILE_SYSTEM 0x01 /* Virtual File System */
+#define BTRC_SCOPE_SEARCH 0x02 /* Search */
+#define BTRC_SCOPE_NOW_PLAYING 0x03 /* Now Playing */
+
+/* Macros for supported character encoding */
+#define BTRC_CHARSET_ID_UTF8 0x006A
+
+/* Macros for item types */
+#define BTRC_ITEM_PLAYER 0x01 /* Media Player */
+#define BTRC_ITEM_FOLDER 0x02 /* Folder */
+#define BTRC_ITEM_MEDIA 0x03 /* Media File */
+
+/* Macros for media attribute IDs */
+#define BTRC_MEDIA_ATTR_ID_INVALID -1
+#define BTRC_MEDIA_ATTR_ID_TITLE 0x00000001
+#define BTRC_MEDIA_ATTR_ID_ARTIST 0x00000002
+#define BTRC_MEDIA_ATTR_ID_ALBUM 0x00000003
+#define BTRC_MEDIA_ATTR_ID_TRACK_NUM 0x00000004
+#define BTRC_MEDIA_ATTR_ID_NUM_TRACKS 0x00000005
+#define BTRC_MEDIA_ATTR_ID_GENRE 0x00000006
+#define BTRC_MEDIA_ATTR_ID_PLAYING_TIME 0x00000007 /* in miliseconds */
+
+/* Macros for folder types */
+#define BTRC_FOLDER_TYPE_MIXED 0x00
+#define BTRC_FOLDER_TYPE_TITLES 0x01
+#define BTRC_FOLDER_TYPE_ALBUMS 0x02
+#define BTRC_FOLDER_TYPE_ARTISTS 0x03
+#define BTRC_FOLDER_TYPE_GENRES 0x04
+#define BTRC_FOLDER_TYPE_PLAYLISTS 0x05
+#define BTRC_FOLDER_TYPE_YEARS 0x06
+
+/* Macros for media types */
+#define BTRC_MEDIA_TYPE_AUDIO 0x00 /* audio */
+#define BTRC_MEDIA_TYPE_VIDEO 0x01 /* video */
+
+/* Macros for num attributes */
+#define BTRC_NUM_ATTR_NONE 0xFF /* No attributes required */
+#define BTRC_NUM_ATTR_ALL 0X00 /* All attributes required */
+
+#define BTRC_HANDLE_NONE 0xFF
+
+typedef uint8_t btrc_uid_t[BTRC_UID_SIZE];
+
+typedef enum {
+ BTRC_CONNECTION_STATE_DISCONNECTED = 0,
+ BTRC_CONNECTION_STATE_CONNECTED
+} btrc_connection_state_t;
+
+typedef enum {
+ BTRC_FEAT_NONE = 0x00, /* AVRCP 1.0 */
+ BTRC_FEAT_METADATA = 0x01, /* AVRCP 1.3 */
+ BTRC_FEAT_ABSOLUTE_VOLUME = 0x02, /* Supports TG role and volume sync */
+ BTRC_FEAT_BROWSE = 0x04, /* AVRCP 1.4 and up, with Browsing support */
+} btrc_remote_features_t;
+
+typedef enum {
+ BTRC_PLAYSTATE_STOPPED = 0x00, /* Stopped */
+ BTRC_PLAYSTATE_PLAYING = 0x01, /* Playing */
+ BTRC_PLAYSTATE_PAUSED = 0x02, /* Paused */
+ BTRC_PLAYSTATE_FWD_SEEK = 0x03, /* Fwd Seek*/
+ BTRC_PLAYSTATE_REV_SEEK = 0x04, /* Rev Seek*/
+ BTRC_PLAYSTATE_ERROR = 0xFF, /* Error */
+} btrc_play_status_t;
+
+typedef enum {
+ BTRC_EVT_PLAY_STATUS_CHANGED = 0x01,
+ BTRC_EVT_TRACK_CHANGE = 0x02,
+ BTRC_EVT_TRACK_REACHED_END = 0x03,
+ BTRC_EVT_TRACK_REACHED_START = 0x04,
+ BTRC_EVT_PLAY_POS_CHANGED = 0x05,
+ BTRC_EVT_APP_SETTINGS_CHANGED = 0x08,
+ BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED = 0x09,
+ BTRC_EVT_AVAL_PLAYER_CHANGE = 0x0a,
+ BTRC_EVT_ADDR_PLAYER_CHANGE = 0x0b,
+ BTRC_EVT_UIDS_CHANGED = 0x0c,
+ BTRC_EVT_VOL_CHANGED = 0x0d,
+} btrc_event_id_t;
+
+typedef enum {
+ BTRC_NOTIFICATION_TYPE_INTERIM = 0,
+ BTRC_NOTIFICATION_TYPE_CHANGED = 1,
+} btrc_notification_type_t;
+
+typedef enum {
+ BTRC_PLAYER_ATTR_EQUALIZER = 0x01,
+ BTRC_PLAYER_ATTR_REPEAT = 0x02,
+ BTRC_PLAYER_ATTR_SHUFFLE = 0x03,
+ BTRC_PLAYER_ATTR_SCAN = 0x04,
+} btrc_player_attr_t;
+
+typedef enum {
+ BTRC_MEDIA_ATTR_TITLE = 0x01,
+ BTRC_MEDIA_ATTR_ARTIST = 0x02,
+ BTRC_MEDIA_ATTR_ALBUM = 0x03,
+ BTRC_MEDIA_ATTR_TRACK_NUM = 0x04,
+ BTRC_MEDIA_ATTR_NUM_TRACKS = 0x05,
+ BTRC_MEDIA_ATTR_GENRE = 0x06,
+ BTRC_MEDIA_ATTR_PLAYING_TIME = 0x07,
+} btrc_media_attr_t;
+
+typedef enum {
+ BTRC_PLAYER_VAL_OFF_REPEAT = 0x01,
+ BTRC_PLAYER_VAL_SINGLE_REPEAT = 0x02,
+ BTRC_PLAYER_VAL_ALL_REPEAT = 0x03,
+ BTRC_PLAYER_VAL_GROUP_REPEAT = 0x04
+} btrc_player_repeat_val_t;
+
+typedef enum {
+ BTRC_PLAYER_VAL_OFF_SHUFFLE = 0x01,
+ BTRC_PLAYER_VAL_ALL_SHUFFLE = 0x02,
+ BTRC_PLAYER_VAL_GROUP_SHUFFLE = 0x03
+} btrc_player_shuffle_val_t;
+
+typedef enum {
+ BTRC_STS_BAD_CMD = 0x00, /* Invalid command */
+ BTRC_STS_BAD_PARAM = 0x01, /* Invalid parameter */
+ BTRC_STS_NOT_FOUND = 0x02, /* Specified parameter is wrong or not found */
+ BTRC_STS_INTERNAL_ERR = 0x03, /* Internal Error */
+ BTRC_STS_NO_ERROR = 0x04, /* Operation Success */
+ BTRC_STS_UID_CHANGED = 0x05, /* UIDs changed */
+ BTRC_STS_RESERVED = 0x06, /* Reserved */
+ BTRC_STS_INV_DIRN = 0x07, /* Invalid direction */
+ BTRC_STS_INV_DIRECTORY = 0x08, /* Invalid directory */
+ BTRC_STS_INV_ITEM = 0x09, /* Invalid Item */
+ BTRC_STS_INV_SCOPE = 0x0a, /* Invalid scope */
+ BTRC_STS_INV_RANGE = 0x0b, /* Invalid range */
+ BTRC_STS_DIRECTORY = 0x0c, /* UID is a directory */
+ BTRC_STS_MEDIA_IN_USE = 0x0d, /* Media in use */
+ BTRC_STS_PLAY_LIST_FULL = 0x0e, /* Playing list full */
+ BTRC_STS_SRCH_NOT_SPRTD = 0x0f, /* Search not supported */
+ BTRC_STS_SRCH_IN_PROG = 0x10, /* Search in progress */
+ BTRC_STS_INV_PLAYER = 0x11, /* Invalid player */
+ BTRC_STS_PLAY_NOT_BROW = 0x12, /* Player not browsable */
+ BTRC_STS_PLAY_NOT_ADDR = 0x13, /* Player not addressed */
+ BTRC_STS_INV_RESULTS = 0x14, /* Invalid results */
+ BTRC_STS_NO_AVBL_PLAY = 0x15, /* No available players */
+ BTRC_STS_ADDR_PLAY_CHGD = 0x16, /* Addressed player changed */
+} btrc_status_t;
+
+typedef struct {
+ uint16_t player_id;
+ uint16_t uid_counter;
+} btrc_addr_player_changed_t;
+
+typedef struct {
+ uint8_t num_attr;
+ uint8_t attr_ids[BTRC_MAX_APP_SETTINGS];
+ uint8_t attr_values[BTRC_MAX_APP_SETTINGS];
+} btrc_player_settings_t;
+
+typedef struct {
+ uint8_t val;
+ uint16_t charset_id;
+ uint16_t str_len;
+ uint8_t* p_str;
+} btrc_player_app_ext_attr_val_t;
+
+typedef struct {
+ uint8_t attr_id;
+ uint16_t charset_id;
+ uint16_t str_len;
+ uint8_t* p_str;
+ uint8_t num_val;
+ btrc_player_app_ext_attr_val_t ext_attr_val[BTRC_MAX_APP_ATTR_SIZE];
+} btrc_player_app_ext_attr_t;
+
+typedef struct {
+ uint8_t attr_id;
+ uint8_t num_val;
+ uint8_t attr_val[BTRC_MAX_APP_ATTR_SIZE];
+} btrc_player_app_attr_t;
+
+typedef struct {
+ uint32_t start_item;
+ uint32_t end_item;
+ uint32_t size;
+ uint32_t attrs[BTRC_MAX_ELEM_ATTR_SIZE];
+ uint8_t attr_count;
+} btrc_getfolderitem_t;
+
+typedef struct {
+ uint16_t type;
+ uint16_t uid_counter;
+} btrc_uids_changed_t;
+
+typedef struct { uint16_t type; } btrc_now_playing_changed_t;
+
+typedef union {
+ btrc_play_status_t play_status;
+ btrc_uid_t track; /* queue position in NowPlaying */
+ uint32_t song_pos;
+ uint16_t uid_counter;
+ btrc_player_settings_t player_setting;
+ btrc_addr_player_changed_t addr_player_changed;
+ btrc_uids_changed_t uids_changed;
+ btrc_now_playing_changed_t now_playing_changed;
+} btrc_register_notification_t;
+
+typedef struct {
+ uint8_t id; /* can be attr_id or value_id */
+ uint8_t text[BTRC_MAX_ATTR_STR_LEN];
+} btrc_player_setting_text_t;
+
+typedef struct {
+ uint32_t attr_id;
+ uint8_t text[BTRC_MAX_ATTR_STR_LEN];
+} btrc_element_attr_val_t;
+
+typedef struct {
+ uint16_t player_id;
+ uint8_t major_type;
+ uint32_t sub_type;
+ uint8_t play_status;
+ uint8_t features[BTRC_FEATURE_BIT_MASK_SIZE];
+ uint16_t charset_id;
+ uint8_t name[BTRC_MAX_ATTR_STR_LEN];
+} btrc_item_player_t;
+
+typedef struct {
+ uint8_t uid[BTRC_UID_SIZE];
+ uint8_t type;
+ uint8_t playable;
+ uint16_t charset_id;
+ uint8_t name[BTRC_MAX_ATTR_STR_LEN];
+} btrc_item_folder_t;
+
+typedef struct {
+ uint8_t uid[BTRC_UID_SIZE];
+ uint8_t type;
+ uint16_t charset_id;
+ uint8_t name[BTRC_MAX_ATTR_STR_LEN];
+ int num_attrs;
+ btrc_element_attr_val_t* p_attrs;
+} btrc_item_media_t;
+
+typedef struct {
+ uint8_t item_type;
+ union {
+ btrc_item_player_t player;
+ btrc_item_folder_t folder;
+ btrc_item_media_t media;
+ };
+} btrc_folder_items_t;
+
+typedef struct {
+ uint16_t str_len;
+ uint8_t p_str[BTRC_MAX_ATTR_STR_LEN];
+} btrc_br_folder_name_t;
+
+/** Callback for the controller's supported feautres */
+typedef void (*btrc_remote_features_callback)(const RawAddress& bd_addr,
+ btrc_remote_features_t features);
+
+/** Callback for play status request */
+typedef void (*btrc_get_play_status_callback)(const RawAddress& bd_addr);
+
+/** Callback for list player application attributes (Shuffle, Repeat,...) */
+typedef void (*btrc_list_player_app_attr_callback)(const RawAddress& bd_addr);
+
+/** Callback for list player application attributes (Shuffle, Repeat,...) */
+typedef void (*btrc_list_player_app_values_callback)(btrc_player_attr_t attr_id,
+ const RawAddress& bd_addr);
+
+/** Callback for getting the current player application settings value
+** num_attr: specifies the number of attribute ids contained in p_attrs
+*/
+typedef void (*btrc_get_player_app_value_callback)(uint8_t num_attr,
+ btrc_player_attr_t* p_attrs,
+ const RawAddress& bd_addr);
+
+/** Callback for getting the player application settings attributes' text
+** num_attr: specifies the number of attribute ids contained in p_attrs
+*/
+typedef void (*btrc_get_player_app_attrs_text_callback)(
+ uint8_t num_attr, btrc_player_attr_t* p_attrs, const RawAddress& bd_addr);
+
+/** Callback for getting the player application settings values' text
+** num_attr: specifies the number of value ids contained in p_vals
+*/
+typedef void (*btrc_get_player_app_values_text_callback)(
+ uint8_t attr_id, uint8_t num_val, uint8_t* p_vals,
+ const RawAddress& bd_addr);
+
+/** Callback for setting the player application settings values */
+typedef void (*btrc_set_player_app_value_callback)(
+ btrc_player_settings_t* p_vals, const RawAddress& bd_addr);
+
+/** Callback to fetch the get element attributes of the current song
+** num_attr: specifies the number of attributes requested in p_attrs
+*/
+typedef void (*btrc_get_element_attr_callback)(uint8_t num_attr,
+ btrc_media_attr_t* p_attrs,
+ const RawAddress& bd_addr);
+
+/** Callback for register notification (Play state change/track change/...)
+** param: Is only valid if event_id is BTRC_EVT_PLAY_POS_CHANGED
+*/
+typedef void (*btrc_register_notification_callback)(btrc_event_id_t event_id,
+ uint32_t param,
+ const RawAddress& bd_addr);
+
+/* AVRCP 1.4 Enhancements */
+/** Callback for volume change on CT
+** volume: Current volume setting on the CT (0-127)
+*/
+typedef void (*btrc_volume_change_callback)(uint8_t volume, uint8_t ctype,
+ const RawAddress& bd_addr);
+
+/** Callback for passthrough commands */
+typedef void (*btrc_passthrough_cmd_callback)(int id, int key_state,
+ const RawAddress& bd_addr);
+
+/** Callback for set addressed player response on TG **/
+typedef void (*btrc_set_addressed_player_callback)(uint16_t player_id,
+ const RawAddress& bd_addr);
+
+/** Callback for set browsed player response on TG **/
+typedef void (*btrc_set_browsed_player_callback)(uint16_t player_id,
+ const RawAddress& bd_addr);
+
+/** Callback for get folder items on TG
+** num_attr: specifies the number of attributes requested in p_attr_ids
+*/
+typedef void (*btrc_get_folder_items_callback)(
+ uint8_t scope, uint32_t start_item, uint32_t end_item, uint8_t num_attr,
+ uint32_t* p_attr_ids, const RawAddress& bd_addr);
+
+/** Callback for changing browsed path on TG **/
+typedef void (*btrc_change_path_callback)(uint8_t direction,
+ uint8_t* folder_uid,
+ const RawAddress& bd_addr);
+
+/** Callback to fetch the get item attributes of the media item
+** num_attr: specifies the number of attributes requested in p_attrs
+*/
+typedef void (*btrc_get_item_attr_callback)(uint8_t scope, uint8_t* uid,
+ uint16_t uid_counter,
+ uint8_t num_attr,
+ btrc_media_attr_t* p_attrs,
+ const RawAddress& bd_addr);
+
+/** Callback for play request for the media item indicated by an identifier */
+typedef void (*btrc_play_item_callback)(uint8_t scope, uint16_t uid_counter,
+ uint8_t* uid,
+ const RawAddress& bd_addr);
+
+/** Callback to fetch total number of items from a folder **/
+typedef void (*btrc_get_total_num_of_items_callback)(uint8_t scope,
+ const RawAddress& bd_addr);
+
+/** Callback for conducting recursive search on a current browsed path for a
+ * specified string */
+typedef void (*btrc_search_callback)(uint16_t charset_id, uint16_t str_len,
+ uint8_t* p_str, const RawAddress& bd_addr);
+
+/** Callback to add a specified media item indicated by an identifier to now
+ * playing queue. */
+typedef void (*btrc_add_to_now_playing_callback)(uint8_t scope, uint8_t* uid,
+ uint16_t uid_counter,
+ const RawAddress& bd_addr);
+
+/** BT-RC Target callback structure. */
+typedef struct {
+ /** set to sizeof(BtRcCallbacks) */
+ size_t size;
+ btrc_remote_features_callback remote_features_cb;
+ btrc_get_play_status_callback get_play_status_cb;
+ btrc_list_player_app_attr_callback list_player_app_attr_cb;
+ btrc_list_player_app_values_callback list_player_app_values_cb;
+ btrc_get_player_app_value_callback get_player_app_value_cb;
+ btrc_get_player_app_attrs_text_callback get_player_app_attrs_text_cb;
+ btrc_get_player_app_values_text_callback get_player_app_values_text_cb;
+ btrc_set_player_app_value_callback set_player_app_value_cb;
+ btrc_get_element_attr_callback get_element_attr_cb;
+ btrc_register_notification_callback register_notification_cb;
+ btrc_volume_change_callback volume_change_cb;
+ btrc_passthrough_cmd_callback passthrough_cmd_cb;
+ btrc_set_addressed_player_callback set_addressed_player_cb;
+ btrc_set_browsed_player_callback set_browsed_player_cb;
+ btrc_get_folder_items_callback get_folder_items_cb;
+ btrc_change_path_callback change_path_cb;
+ btrc_get_item_attr_callback get_item_attr_cb;
+ btrc_play_item_callback play_item_cb;
+ btrc_get_total_num_of_items_callback get_total_num_of_items_cb;
+ btrc_search_callback search_cb;
+ btrc_add_to_now_playing_callback add_to_now_playing_cb;
+} btrc_callbacks_t;
+
+/** Represents the standard BT-RC AVRCP Target interface. */
+typedef struct {
+ /** set to sizeof(BtRcInterface) */
+ size_t size;
+ /**
+ * Register the BtRc callbacks
+ */
+ bt_status_t (*init)(btrc_callbacks_t* callbacks);
+
+ /** Respose to GetPlayStatus request. Contains the current
+ ** 1. Play status
+ ** 2. Song duration/length
+ ** 3. Song position
+ */
+ bt_status_t (*get_play_status_rsp)(const RawAddress& bd_addr,
+ btrc_play_status_t play_status,
+ uint32_t song_len, uint32_t song_pos);
+
+ /** Lists the support player application attributes (Shuffle/Repeat/...)
+ ** num_attr: Specifies the number of attributes contained in the pointer
+ *p_attrs
+ */
+ bt_status_t (*list_player_app_attr_rsp)(const RawAddress& bd_addr,
+ int num_attr,
+ btrc_player_attr_t* p_attrs);
+
+ /** Lists the support player application attributes (Shuffle Off/On/Group)
+ ** num_val: Specifies the number of values contained in the pointer p_vals
+ */
+ bt_status_t (*list_player_app_value_rsp)(const RawAddress& bd_addr,
+ int num_val, uint8_t* p_vals);
+
+ /** Returns the current application attribute values for each of the specified
+ * attr_id */
+ bt_status_t (*get_player_app_value_rsp)(const RawAddress& bd_addr,
+ btrc_player_settings_t* p_vals);
+
+ /** Returns the application attributes text ("Shuffle"/"Repeat"/...)
+ ** num_attr: Specifies the number of attributes' text contained in the
+ *pointer p_attrs
+ */
+ bt_status_t (*get_player_app_attr_text_rsp)(
+ const RawAddress& bd_addr, int num_attr,
+ btrc_player_setting_text_t* p_attrs);
+
+ /** Returns the application attributes text ("Shuffle"/"Repeat"/...)
+ ** num_attr: Specifies the number of attribute values' text contained in the
+ *pointer p_vals
+ */
+ bt_status_t (*get_player_app_value_text_rsp)(
+ const RawAddress& bd_addr, int num_val,
+ btrc_player_setting_text_t* p_vals);
+
+ /** Returns the current songs' element attributes text
+ *("Title"/"Album"/"Artist")
+ ** num_attr: Specifies the number of attributes' text contained in the
+ *pointer p_attrs
+ */
+ bt_status_t (*get_element_attr_rsp)(const RawAddress& bd_addr,
+ uint8_t num_attr,
+ btrc_element_attr_val_t* p_attrs);
+
+ /** Response to set player attribute request ("Shuffle"/"Repeat")
+ ** rsp_status: Status of setting the player attributes for the current media
+ *player
+ */
+ bt_status_t (*set_player_app_value_rsp)(const RawAddress& bd_addr,
+ btrc_status_t rsp_status);
+
+ /* Response to the register notification request (Play state change/track
+ *change/...).
+ ** event_id: Refers to the event_id this notification change corresponds too
+ ** type: Response type - interim/changed
+ ** p_params: Based on the event_id, this parameter should be populated
+ */
+ bt_status_t (*register_notification_rsp)(
+ btrc_event_id_t event_id, btrc_notification_type_t type,
+ btrc_register_notification_t* p_param);
+
+ /* AVRCP 1.4 enhancements */
+
+ /**Send current volume setting to remote side. Support limited to
+ *SetAbsoluteVolume
+ ** This can be enhanced to support Relative Volume (AVRCP 1.0).
+ ** With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN opposed to absolute
+ *volume level
+ ** volume: Should be in the range 0-127. bit7 is reseved and cannot be set
+ */
+ bt_status_t (*set_volume)(uint8_t volume);
+
+ /* Set addressed player response from TG to CT */
+ bt_status_t (*set_addressed_player_rsp)(const RawAddress& bd_addr,
+ btrc_status_t rsp_status);
+
+ /* Set browsed player response from TG to CT */
+ bt_status_t (*set_browsed_player_rsp)(const RawAddress& bd_addr,
+ btrc_status_t rsp_status,
+ uint32_t num_items, uint16_t charset_id,
+ uint8_t folder_depth,
+ btrc_br_folder_name_t* p_folders);
+
+ /* Get folder item list response from TG to CT */
+ bt_status_t (*get_folder_items_list_rsp)(const RawAddress& bd_addr,
+ btrc_status_t rsp_status,
+ uint16_t uid_counter,
+ uint8_t num_items,
+ btrc_folder_items_t* p_items);
+
+ /* Change path response from TG to CT */
+ bt_status_t (*change_path_rsp)(const RawAddress& bd_addr,
+ btrc_status_t rsp_status, uint32_t num_items);
+
+ /** Returns the element's attributes num_attr: Specifies the number of
+ * attributes' text contained in the pointer p_attrs
+ */
+ bt_status_t (*get_item_attr_rsp)(const RawAddress& bd_addr,
+ btrc_status_t rsp_status, uint8_t num_attr,
+ btrc_element_attr_val_t* p_attrs);
+
+ /* play media item response from TG to CT */
+ bt_status_t (*play_item_rsp)(const RawAddress& bd_addr,
+ btrc_status_t rsp_status);
+
+ /* get total number of items response from TG to CT*/
+ bt_status_t (*get_total_num_of_items_rsp)(const RawAddress& bd_addr,
+ btrc_status_t rsp_status,
+ uint32_t uid_counter,
+ uint32_t num_items);
+
+ /* Search VFS response from TG to CT */
+ bt_status_t (*search_rsp)(const RawAddress& bd_addr, btrc_status_t rsp_status,
+ uint32_t uid_counter, uint32_t num_items);
+
+ /* add_to_now playing list response from TG to CT */
+ bt_status_t (*add_to_now_playing_rsp)(const RawAddress& bd_addr,
+ btrc_status_t rsp_status);
+
+ /** Closes the interface. */
+ void (*cleanup)(void);
+} btrc_interface_t;
+
+typedef void (*btrc_passthrough_rsp_callback)(const RawAddress& bd_addr, int id,
+ int key_state);
+
+typedef void (*btrc_groupnavigation_rsp_callback)(int id, int key_state);
+
+typedef void (*btrc_connection_state_callback)(bool rc_connect, bool bt_connect,
+ const RawAddress& bd_addr);
+
+typedef void (*btrc_ctrl_getrcfeatures_callback)(const RawAddress& bd_addr,
+ int features);
+
+typedef void (*btrc_ctrl_setabsvol_cmd_callback)(const RawAddress& bd_addr,
+ uint8_t abs_vol,
+ uint8_t label);
+
+typedef void (*btrc_ctrl_registernotification_abs_vol_callback)(
+ const RawAddress& bd_addr, uint8_t label);
+
+typedef void (*btrc_ctrl_setplayerapplicationsetting_rsp_callback)(
+ const RawAddress& bd_addr, uint8_t accepted);
+
+typedef void (*btrc_ctrl_playerapplicationsetting_callback)(
+ const RawAddress& bd_addr, uint8_t num_attr,
+ btrc_player_app_attr_t* app_attrs, uint8_t num_ext_attr,
+ btrc_player_app_ext_attr_t* ext_attrs);
+
+typedef void (*btrc_ctrl_playerapplicationsetting_changed_callback)(
+ const RawAddress& bd_addr, const btrc_player_settings_t& vals);
+
+typedef void (*btrc_ctrl_track_changed_callback)(
+ const RawAddress& bd_addr, uint8_t num_attr,
+ btrc_element_attr_val_t* p_attrs);
+
+typedef void (*btrc_ctrl_play_position_changed_callback)(
+ const RawAddress& bd_addr, uint32_t song_len, uint32_t song_pos);
+
+typedef void (*btrc_ctrl_play_status_changed_callback)(
+ const RawAddress& bd_addr, btrc_play_status_t play_status);
+
+typedef void (*btrc_ctrl_get_folder_items_callback)(
+ const RawAddress& bd_addr, btrc_status_t status,
+ const btrc_folder_items_t* folder_items, uint8_t count);
+
+typedef void (*btrc_ctrl_change_path_callback)(const RawAddress& bd_addr,
+ uint32_t count);
+
+typedef void (*btrc_ctrl_set_browsed_player_callback)(const RawAddress& bd_addr,
+ uint8_t num_items,
+ uint8_t depth);
+typedef void (*btrc_ctrl_set_addressed_player_callback)(
+ const RawAddress& bd_addr, uint8_t status);
+/** BT-RC Controller callback structure. */
+typedef struct {
+ /** set to sizeof(BtRcCallbacks) */
+ size_t size;
+ btrc_passthrough_rsp_callback passthrough_rsp_cb;
+ btrc_groupnavigation_rsp_callback groupnavigation_rsp_cb;
+ btrc_connection_state_callback connection_state_cb;
+ btrc_ctrl_getrcfeatures_callback getrcfeatures_cb;
+ btrc_ctrl_setplayerapplicationsetting_rsp_callback setplayerappsetting_rsp_cb;
+ btrc_ctrl_playerapplicationsetting_callback playerapplicationsetting_cb;
+ btrc_ctrl_playerapplicationsetting_changed_callback
+ playerapplicationsetting_changed_cb;
+ btrc_ctrl_setabsvol_cmd_callback setabsvol_cmd_cb;
+ btrc_ctrl_registernotification_abs_vol_callback
+ registernotification_absvol_cb;
+ btrc_ctrl_track_changed_callback track_changed_cb;
+ btrc_ctrl_play_position_changed_callback play_position_changed_cb;
+ btrc_ctrl_play_status_changed_callback play_status_changed_cb;
+ btrc_ctrl_get_folder_items_callback get_folder_items_cb;
+ btrc_ctrl_change_path_callback change_folder_path_cb;
+ btrc_ctrl_set_browsed_player_callback set_browsed_player_cb;
+ btrc_ctrl_set_addressed_player_callback set_addressed_player_cb;
+} btrc_ctrl_callbacks_t;
+
+/** Represents the standard BT-RC AVRCP Controller interface. */
+typedef struct {
+ /** set to sizeof(BtRcInterface) */
+ size_t size;
+ /**
+ * Register the BtRc callbacks
+ */
+ bt_status_t (*init)(btrc_ctrl_callbacks_t* callbacks);
+
+ /** send pass through command to target */
+ bt_status_t (*send_pass_through_cmd)(const RawAddress& bd_addr,
+ uint8_t key_code, uint8_t key_state);
+
+ /** send group navigation command to target */
+ bt_status_t (*send_group_navigation_cmd)(const RawAddress& bd_addr,
+ uint8_t key_code, uint8_t key_state);
+
+ /** send command to set player applicaiton setting attributes to target */
+ bt_status_t (*set_player_app_setting_cmd)(const RawAddress& bd_addr,
+ uint8_t num_attrib,
+ uint8_t* attrib_ids,
+ uint8_t* attrib_vals);
+
+ /** send command to play a particular item */
+ bt_status_t (*play_item_cmd)(const RawAddress& bd_addr, uint8_t scope,
+ uint8_t* uid, uint16_t uid_counter);
+
+ /** get the playback state */
+ bt_status_t (*get_playback_state_cmd)(const RawAddress& bd_addr);
+
+ /** get the now playing list */
+ bt_status_t (*get_now_playing_list_cmd)(const RawAddress& bd_addr,
+ uint32_t start, uint32_t end);
+
+ /** get the folder list */
+ bt_status_t (*get_folder_list_cmd)(const RawAddress& bd_addr, uint32_t start,
+ uint32_t end);
+
+ /** get the player list */
+ bt_status_t (*get_player_list_cmd)(const RawAddress& bd_addr, uint32_t start,
+ uint32_t end);
+
+ /** change the folder path */
+ bt_status_t (*change_folder_path_cmd)(const RawAddress& bd_addr,
+ uint8_t direction, uint8_t* uid);
+
+ /** set browsed player */
+ bt_status_t (*set_browsed_player_cmd)(const RawAddress& bd_addr,
+ uint16_t player_id);
+
+ /** set addressed player */
+ bt_status_t (*set_addressed_player_cmd)(const RawAddress& bd_addr,
+ uint16_t player_id);
+
+ /** send rsp to set_abs_vol received from target */
+ bt_status_t (*set_volume_rsp)(const RawAddress& bd_addr, uint8_t abs_vol,
+ uint8_t label);
+
+ /** send notificaiton rsp for abs vol to target */
+ bt_status_t (*register_abs_vol_rsp)(const RawAddress& bd_addr,
+ btrc_notification_type_t rsp_type,
+ uint8_t abs_vol, uint8_t label);
+
+ /** Closes the interface. */
+ void (*cleanup)(void);
+} btrc_ctrl_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_RC_H */
diff --git a/include/hardware/bt_sdp.h b/include/hardware/bt_sdp.h
new file mode 100644
index 0000000..024ee40
--- /dev/null
+++ b/include/hardware/bt_sdp.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "bluetooth.h"
+
+#define SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH 15
+
+__BEGIN_DECLS
+
+/**
+ * These events are handled by the state machine
+ */
+typedef enum {
+ SDP_TYPE_RAW, // Used to carry raw SDP search data for unknown UUIDs
+ SDP_TYPE_MAP_MAS, // Message Access Profile - Server
+ SDP_TYPE_MAP_MNS, // Message Access Profile - Client (Notification Server)
+ SDP_TYPE_PBAP_PSE, // Phone Book Profile - Server
+ SDP_TYPE_PBAP_PCE, // Phone Book Profile - Client
+ SDP_TYPE_OPP_SERVER, // Object Push Profile
+ SDP_TYPE_SAP_SERVER // SIM Access Profile
+} bluetooth_sdp_types;
+
+typedef struct _bluetooth_sdp_hdr {
+ bluetooth_sdp_types type;
+ bluetooth::Uuid uuid;
+ uint32_t service_name_length;
+ char* service_name;
+ int32_t rfcomm_channel_number;
+ int32_t l2cap_psm;
+ int32_t profile_version;
+} bluetooth_sdp_hdr;
+
+/**
+ * Some signals need additional pointers, hence we introduce a
+ * generic way to handle these pointers.
+ */
+typedef struct _bluetooth_sdp_hdr_overlay {
+ bluetooth_sdp_types type;
+ bluetooth::Uuid uuid;
+ uint32_t service_name_length;
+ char* service_name;
+ int32_t rfcomm_channel_number;
+ int32_t l2cap_psm;
+ int32_t profile_version;
+
+ // User pointers, only used for some signals - see bluetooth_sdp_ops_record
+ int user1_ptr_len;
+ uint8_t* user1_ptr;
+ int user2_ptr_len;
+ uint8_t* user2_ptr;
+} bluetooth_sdp_hdr_overlay;
+
+typedef struct _bluetooth_sdp_mas_record {
+ bluetooth_sdp_hdr_overlay hdr;
+ uint32_t mas_instance_id;
+ uint32_t supported_features;
+ uint32_t supported_message_types;
+} bluetooth_sdp_mas_record;
+
+typedef struct _bluetooth_sdp_mns_record {
+ bluetooth_sdp_hdr_overlay hdr;
+ uint32_t supported_features;
+} bluetooth_sdp_mns_record;
+
+typedef struct _bluetooth_sdp_pse_record {
+ bluetooth_sdp_hdr_overlay hdr;
+ uint32_t supported_features;
+ uint32_t supported_repositories;
+} bluetooth_sdp_pse_record;
+
+typedef struct _bluetooth_sdp_pce_record {
+ bluetooth_sdp_hdr_overlay hdr;
+} bluetooth_sdp_pce_record;
+
+typedef struct _bluetooth_sdp_ops_record {
+ bluetooth_sdp_hdr_overlay hdr;
+ int supported_formats_list_len;
+ uint8_t supported_formats_list[SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH];
+} bluetooth_sdp_ops_record;
+
+typedef struct _bluetooth_sdp_sap_record {
+ bluetooth_sdp_hdr_overlay hdr;
+} bluetooth_sdp_sap_record;
+
+typedef union {
+ bluetooth_sdp_hdr_overlay hdr;
+ bluetooth_sdp_mas_record mas;
+ bluetooth_sdp_mns_record mns;
+ bluetooth_sdp_pse_record pse;
+ bluetooth_sdp_pce_record pce;
+ bluetooth_sdp_ops_record ops;
+ bluetooth_sdp_sap_record sap;
+} bluetooth_sdp_record;
+
+/** Callback for SDP search */
+typedef void (*btsdp_search_callback)(bt_status_t status,
+ const RawAddress& bd_addr,
+ const bluetooth::Uuid& uuid,
+ int num_records,
+ bluetooth_sdp_record* records);
+
+typedef struct {
+ /** Set to sizeof(btsdp_callbacks_t) */
+ size_t size;
+ btsdp_search_callback sdp_search_cb;
+} btsdp_callbacks_t;
+
+typedef struct {
+ /** Set to size of this struct */
+ size_t size;
+
+ /** Register BT SDP search callbacks */
+ bt_status_t (*init)(btsdp_callbacks_t* callbacks);
+
+ /** Unregister BT SDP */
+ bt_status_t (*deinit)();
+
+ /** Search for SDP records with specific uuid on remote device */
+ bt_status_t (*sdp_search)(RawAddress* bd_addr, const bluetooth::Uuid& uuid);
+
+ /**
+ * Use listen in the socket interface to create rfcomm and/or l2cap PSM
+ * channels, (without UUID and service_name and set the BTSOCK_FLAG_NO_SDP
+ * flag in flags). Then use createSdpRecord to create the SDP record
+ * associated with the rfcomm/l2cap channels.
+ *
+ * Returns a handle to the SDP record, which can be parsed to
+ * remove_sdp_record.
+ *
+ * record (in) The SDP record to create
+ * record_handle (out)The corresponding record handle will be written to
+ * this pointer.
+ */
+ bt_status_t (*create_sdp_record)(bluetooth_sdp_record* record,
+ int* record_handle);
+
+ /** Remove a SDP record created by createSdpRecord */
+ bt_status_t (*remove_sdp_record)(int sdp_handle);
+} btsdp_interface_t;
+
+__END_DECLS
diff --git a/include/hardware/bt_sock.h b/include/hardware/bt_sock.h
new file mode 100644
index 0000000..04827aa
--- /dev/null
+++ b/include/hardware/bt_sock.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+__BEGIN_DECLS
+
+#define BTSOCK_FLAG_ENCRYPT 1
+#define BTSOCK_FLAG_AUTH (1 << 1)
+#define BTSOCK_FLAG_NO_SDP (1 << 2)
+#define BTSOCK_FLAG_AUTH_MITM (1 << 3)
+#define BTSOCK_FLAG_AUTH_16_DIGIT (1 << 4)
+#define BTSOCK_FLAG_LE_COC (1 << 5)
+
+typedef enum {
+ BTSOCK_RFCOMM = 1,
+ BTSOCK_SCO = 2,
+ BTSOCK_L2CAP = 3,
+ BTSOCK_L2CAP_LE = 4
+} btsock_type_t;
+
+/** Represents the standard BT SOCKET interface. */
+typedef struct {
+ short size;
+ RawAddress bd_addr;
+ int channel;
+ int status;
+
+ // The writer must make writes using a buffer of this maximum size
+ // to avoid loosing data. (L2CAP only)
+ unsigned short max_tx_packet_size;
+
+ // The reader must read using a buffer of at least this size to avoid
+ // loosing data. (L2CAP only)
+ unsigned short max_rx_packet_size;
+} __attribute__((packed)) sock_connect_signal_t;
+
+typedef struct {
+ /** set to size of this struct*/
+ size_t size;
+
+ /**
+ * Listen to a RFCOMM UUID or channel. It returns the socket fd from which
+ * btsock_connect_signal can be read out when a remote device connected.
+ * If neither a UUID nor a channel is provided, a channel will be allocated
+ * and a service record can be created providing the channel number to
+ * create_sdp_record(...) in bt_sdp.
+ * The callingUid is the UID of the application which is requesting the
+ * socket. This is used for traffic accounting purposes.
+ */
+ bt_status_t (*listen)(btsock_type_t type, const char* service_name,
+ const bluetooth::Uuid* service_uuid, int channel,
+ int* sock_fd, int flags, int callingUid);
+
+ /**
+ * Connect to a RFCOMM UUID channel of remote device, It returns the socket fd
+ * from which the btsock_connect_signal and a new socket fd to be accepted can
+ * be read out when connected. The callingUid is the UID of the application
+ * which is requesting the socket. This is used for traffic accounting
+ * purposes.
+ */
+ bt_status_t (*connect)(const RawAddress* bd_addr, btsock_type_t type,
+ const bluetooth::Uuid* uuid, int channel, int* sock_fd,
+ int flags, int callingUid);
+
+ /**
+ * Set the LE Data Length value to this connected peer to the
+ * maximum supported by this BT controller. This command
+ * suggests to the BT controller to set its maximum transmission
+ * packet size.
+ */
+ void (*request_max_tx_data_length)(const RawAddress& bd_addr);
+
+} btsock_interface_t;
+
+__END_DECLS
diff --git a/internal_include/Android.bp b/internal_include/Android.bp
new file mode 100644
index 0000000..3ef202b
--- /dev/null
+++ b/internal_include/Android.bp
@@ -0,0 +1,6 @@
+cc_library_headers {
+ name: "internal_include_headers",
+ export_include_dirs: ["./"],
+ vendor_available: true,
+ host_supported: true,
+}
\ No newline at end of file
diff --git a/include/bt_common.h b/internal_include/bt_common.h
similarity index 95%
rename from include/bt_common.h
rename to internal_include/bt_common.h
index 9680792..a15cb64 100644
--- a/include/bt_common.h
+++ b/internal_include/bt_common.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/include/bt_target.h b/internal_include/bt_target.h
similarity index 92%
rename from include/bt_target.h
rename to internal_include/bt_target.h
index eadfc92..cf09b15 100644
--- a/include/bt_target.h
+++ b/internal_include/bt_target.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
- * Copyright (C) 1999-2016 Broadcom Corporation
+ * Copyright 1999-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,10 +51,6 @@
(L2CAP_MTU_SIZE - L2CAP_MIN_OFFSET - RFCOMM_DATA_OVERHEAD)
#endif
-#ifndef BTA_INCLUDED
-#define BTA_INCLUDED TRUE
-#endif
-
#ifndef BTA_PAN_INCLUDED
#define BTA_PAN_INCLUDED TRUE
#endif
@@ -87,22 +83,14 @@
#define BTA_DISABLE_DELAY 200 /* in milliseconds */
#endif
-#ifndef SBC_FOR_EMBEDDED_LINUX
-#define SBC_FOR_EMBEDDED_LINUX TRUE
-#endif
-
#ifndef AVDT_VERSION
-#define AVDT_VERSION 0x0102
+#define AVDT_VERSION 0x0103
#endif
#ifndef BTA_AG_AT_MAX_LEN
#define BTA_AG_AT_MAX_LEN 512
#endif
-#ifndef BTA_AVRCP_FF_RW_SUPPORT
-#define BTA_AVRCP_FF_RW_SUPPORT TRUE
-#endif
-
#ifndef BTA_AG_SCO_PKT_TYPES
#define BTA_AG_SCO_PKT_TYPES \
(BTM_SCO_LINK_ONLY_MASK | ESCO_PKT_TYPES_MASK_EV3 | \
@@ -119,11 +107,6 @@
#define BTA_AV_CO_CP_SCMS_T FALSE
#endif
-/* This feature is used to enable interleaved scan */
-#ifndef BTA_HOST_INTERLEAVE_SEARCH
-#define BTA_HOST_INTERLEAVE_SEARCH FALSE
-#endif
-
#ifndef BTA_DM_SDP_DB_SIZE
#define BTA_DM_SDP_DB_SIZE 8000
#endif
@@ -141,11 +124,17 @@
#endif
// How long to wait before activating sniff mode after entering the
-// idle state for FTS, OPS connections
+// idle state for server FT/RFCOMM, OPS connections
#ifndef BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS
#define BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS 7000
#endif
+// How long to wait before activating sniff mode after entering the
+// idle state for client FT/RFCOMM connections
+#ifndef BTA_FTC_IDLE_TO_SNIFF_DELAY_MS
+#define BTA_FTC_IDLE_TO_SNIFF_DELAY_MS 5000
+#endif
+
//------------------End added from bdroid_buildcfg.h---------------------
/******************************************************************************
@@ -270,11 +259,6 @@
#define BTA_HL_LRG_DATA_BUF_SIZE (10240 + 24)
#endif
-/* GATT Server Database buffer size */
-#ifndef GATT_DB_BUF_SIZE
-#define GATT_DB_BUF_SIZE 128
-#endif
-
/* GATT Data sending buffer size */
#ifndef GATT_DATA_BUF_SIZE
#define GATT_DATA_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
@@ -296,11 +280,6 @@
#define BTM_SCO_INCLUDED TRUE /* TRUE includes SCO code */
#endif
-/* Includes SCO if TRUE */
-#ifndef BTM_SCO_HCI_INCLUDED
-#define BTM_SCO_HCI_INCLUDED FALSE /* TRUE includes SCO over HCI code */
-#endif
-
/* This is used to work around a controller bug that doesn't like Disconnect
* issued while there is a role switch in progress
*/
@@ -373,11 +352,6 @@
#define BTM_MAX_SCO_LINKS 3
#endif
-/* The preferred type of SCO links (2-eSCO, 0-SCO). */
-#ifndef BTM_DEFAULT_SCO_MODE
-#define BTM_DEFAULT_SCO_MODE 2
-#endif
-
/* The number of security records for peer devices. */
#ifndef BTM_SEC_MAX_DEVICE_RECORDS
#define BTM_SEC_MAX_DEVICE_RECORDS 100
@@ -507,14 +481,14 @@
/* The maximum number of simultaneous links that L2CAP can support. */
#ifndef MAX_ACL_CONNECTIONS
-#define MAX_L2CAP_LINKS 7
+#define MAX_L2CAP_LINKS 13
#else
#define MAX_L2CAP_LINKS MAX_ACL_CONNECTIONS
#endif
/* The maximum number of simultaneous channels that L2CAP can support. */
#ifndef MAX_L2CAP_CHANNELS
-#define MAX_L2CAP_CHANNELS 16
+#define MAX_L2CAP_CHANNELS 32
#endif
/* The maximum number of simultaneous applications that can register with L2CAP.
@@ -585,26 +559,6 @@
#define L2CAP_HCI_FLOW_CONTROL_DEBUG TRUE
#endif
-/* Unicast Connectionless Data */
-#ifndef L2CAP_UCD_INCLUDED
-#define L2CAP_UCD_INCLUDED FALSE
-#endif
-
-/* Unicast Connectionless Data MTU */
-#ifndef L2CAP_UCD_MTU
-#define L2CAP_UCD_MTU L2CAP_MTU_SIZE
-#endif
-
-/* Unicast Connectionless Data Idle Timeout */
-#ifndef L2CAP_UCD_IDLE_TIMEOUT
-#define L2CAP_UCD_IDLE_TIMEOUT 2
-#endif
-
-/* Unicast Connectionless Data Idle Timeout */
-#ifndef L2CAP_UCD_CH_PRIORITY
-#define L2CAP_UCD_CH_PRIORITY L2CAP_CHNL_PRIORITY_MEDIUM
-#endif
-
/* Used for features using fixed channels; set to zero if no fixed channels
* supported (BLE, etc.) */
/* Excluding L2CAP signaling channel and UCD */
@@ -653,7 +607,7 @@
*****************************************************************************/
#ifndef LOCAL_BLE_CONTROLLER_ID
-#define LOCAL_BLE_CONTROLLER_ID (1)
+#define LOCAL_BLE_CONTROLLER_ID 1
#endif
/*
@@ -679,11 +633,6 @@
#define BLE_VND_INCLUDED FALSE
#endif
-#ifndef BTM_BLE_ADV_TX_POWER
-#define BTM_BLE_ADV_TX_POWER \
- { -21, -15, -7, 1, 9 }
-#endif
-
/* The maximum number of simultaneous applications that can register with LE
* L2CAP. */
#ifndef BLE_MAX_L2CAP_CLIENTS
@@ -699,28 +648,12 @@
#define BLE_LLT_INCLUDED TRUE
#endif
-#ifndef ATT_INCLUDED
-#define ATT_INCLUDED TRUE
-#endif
-
-#ifndef ATT_DEBUG
-#define ATT_DEBUG TRUE
-#endif
-
#ifndef BLE_DELAY_REQUEST_ENC
/* This flag is to work around IPHONE problem, We need to wait for iPhone ready
before send encryption request to iPhone */
#define BLE_DELAY_REQUEST_ENC FALSE
#endif
-#ifndef GAP_TRANSPORT_SUPPORTED
-#define GAP_TRANSPORT_SUPPORTED GATT_TRANSPORT_LE_BR_EDR
-#endif
-
-#ifndef GATTP_TRANSPORT_SUPPORTED
-#define GATTP_TRANSPORT_SUPPORTED GATT_TRANSPORT_LE_BR_EDR
-#endif
-
#ifndef GATT_MAX_SR_PROFILES
#define GATT_MAX_SR_PROFILES 32 /* max is 32 */
#endif
@@ -829,7 +762,7 @@
/* The MTU size for the L2CAP configuration. */
#ifndef SDP_MTU_SIZE
-#define SDP_MTU_SIZE 672
+#define SDP_MTU_SIZE 1024
#endif
/* The flush timeout for the L2CAP configuration. */
@@ -920,17 +853,6 @@
#define PORT_FC_DEFAULT PORT_FC_CREDIT
#endif
-/* The maximum number of credits receiver sends to peer when using credit-based
- * flow control. */
-#ifndef PORT_CREDIT_RX_MAX
-#define PORT_CREDIT_RX_MAX 16
-#endif
-
-/* The credit low watermark level. */
-#ifndef PORT_CREDIT_RX_LOW
-#define PORT_CREDIT_RX_LOW 8
-#endif
-
/******************************************************************************
*
* OBEX
@@ -1072,18 +994,9 @@
*
*****************************************************************************/
-#ifndef AVDT_INCLUDED
-#define AVDT_INCLUDED TRUE
-#endif
-
-/* Include reporting capability in AVDTP */
-#ifndef AVDT_REPORTING
-#define AVDT_REPORTING TRUE
-#endif
-
/* Number of simultaneous links to different peer devices. */
#ifndef AVDT_NUM_LINKS
-#define AVDT_NUM_LINKS 2
+#define AVDT_NUM_LINKS 6
#endif
/* Number of simultaneous stream endpoints. */
@@ -1093,7 +1006,7 @@
/* Number of transport channels setup by AVDT for all media streams */
#ifndef AVDT_NUM_TC_TBL
-#define AVDT_NUM_TC_TBL 6
+#define AVDT_NUM_TC_TBL (AVDT_NUM_SEPS + AVDT_NUM_LINKS)
#endif
/* Maximum size in bytes of the content protection information element. */
@@ -1225,10 +1138,6 @@
#define HID_DEV_INCLUDED TRUE
#endif
-#ifndef HID_DEV_SUBCLASS
-#define HID_DEV_SUBCLASS COD_MINOR_POINTING
-#endif
-
#ifndef HID_CONTROL_BUF_SIZE
#define HID_CONTROL_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
#endif
@@ -1280,18 +1189,11 @@
#endif
#ifndef HID_HOST_MAX_CONN_RETRY
-#define HID_HOST_MAX_CONN_RETRY (1)
+#define HID_HOST_MAX_CONN_RETRY 1
#endif
#ifndef HID_HOST_REPAGE_WIN
-#define HID_HOST_REPAGE_WIN (2)
-#endif
-
-/*************************************************************************
- * A2DP Definitions
- */
-#ifndef A2D_INCLUDED
-#define A2D_INCLUDED TRUE
+#define HID_HOST_REPAGE_WIN 2
#endif
/******************************************************************************
@@ -1302,12 +1204,12 @@
/* Number of simultaneous ACL links to different peer devices. */
#ifndef AVCT_NUM_LINKS
-#define AVCT_NUM_LINKS 2
+#define AVCT_NUM_LINKS 6
#endif
/* Number of simultaneous AVCTP connections. */
#ifndef AVCT_NUM_CONN
-#define AVCT_NUM_CONN 3
+#define AVCT_NUM_CONN 14 // 2 * MaxDevices + 2
#endif
/******************************************************************************
@@ -1316,10 +1218,6 @@
*
*****************************************************************************/
-#ifndef AVRC_METADATA_INCLUDED
-#define AVRC_METADATA_INCLUDED TRUE
-#endif
-
#ifndef AVRC_ADV_CTRL_INCLUDED
#define AVRC_ADV_CTRL_INCLUDED TRUE
#endif
diff --git a/include/bt_trace.h b/internal_include/bt_trace.h
similarity index 94%
rename from include/bt_trace.h
rename to internal_include/bt_trace.h
index 44ff2ff..97c761b 100644
--- a/include/bt_trace.h
+++ b/internal_include/bt_trace.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -478,27 +478,27 @@
/* AVDTP */
#define AVDT_TRACE_ERROR(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_ERROR) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__); \
}
#define AVDT_TRACE_WARNING(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_WARNING) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__); \
}
#define AVDT_TRACE_EVENT(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_EVENT) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__); \
}
#define AVDT_TRACE_DEBUG(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_DEBUG) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__); \
}
#define AVDT_TRACE_API(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_API) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_API) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__); \
}
@@ -720,3 +720,55 @@
#ifdef __cplusplus
}
#endif
+
+#ifdef __cplusplus
+
+#include <iomanip>
+#include <sstream>
+#include <type_traits>
+
+#include <base/logging.h>
+
+/* Prints intergral parameter x as hex string, with '0' fill */
+template <typename T>
+std::string loghex(T x) {
+ static_assert(std::is_integral<T>::value,
+ "loghex parameter must be integral.");
+ std::stringstream tmp;
+ tmp << std::showbase << std::internal << std::hex << std::setfill('0')
+ << std::setw((sizeof(T) * 2) + 2) << +x;
+ return tmp.str();
+}
+
+/**
+ * Obtains the string representation of a boolean value.
+ *
+ * @param value the boolean value to use
+ * @return the string representation of the boolean value: "true" or "false"
+ */
+inline std::string logbool(bool value) {
+ std::stringstream tmp;
+ tmp << std::boolalpha << value;
+ return tmp.str();
+}
+
+/**
+ * Append a field name to a string.
+ *
+ * The field names are added to the string with "|" in between.
+ *
+ * @param p_result a pointer to the result string to add the field name to
+ * @param append if true the field name will be added
+ * @param name the field name to add
+ * @return the result string
+ */
+inline std::string& AppendField(std::string* p_result, bool append,
+ const std::string& name) {
+ CHECK(p_result != nullptr);
+ if (!append) return *p_result;
+ if (!p_result->empty()) *p_result += "|";
+ *p_result += name;
+ return *p_result;
+}
+
+#endif
diff --git a/include/bte.h b/internal_include/bte.h
similarity index 98%
rename from include/bte.h
rename to internal_include/bte.h
index 90c9590..754cf53 100644
--- a/include/bte.h
+++ b/internal_include/bte.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2001-2012 Broadcom Corporation
+ * Copyright 2001-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/include/bte_appl.h b/internal_include/bte_appl.h
similarity index 95%
rename from include/bte_appl.h
rename to internal_include/bte_appl.h
index b2aaa02..84ab641 100644
--- a/include/bte_appl.h
+++ b/internal_include/bte_appl.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/include/stack_config.h b/internal_include/stack_config.h
similarity index 90%
rename from include/stack_config.h
rename to internal_include/stack_config.h
index 156f5be..d623fa4 100644
--- a/include/stack_config.h
+++ b/internal_include/stack_config.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,10 +27,11 @@
typedef struct {
bool (*get_trace_config_enabled)(void);
+ bool (*get_pts_avrcp_test)(void);
bool (*get_pts_secure_only_mode)(void);
bool (*get_pts_conn_updates_disabled)(void);
bool (*get_pts_crosskey_sdp_disable)(void);
- const char* (*get_pts_smp_options)(void);
+ const std::string* (*get_pts_smp_options)(void);
int (*get_pts_smp_failure_case)(void);
config_t* (*get_all)(void);
} stack_config_t;
diff --git a/main/Android.bp b/main/Android.bp
index 9dc5a98..c07b849 100644
--- a/main/Android.bp
+++ b/main/Android.bp
@@ -1,9 +1,11 @@
+
// Bluetooth main HW module / shared library for target
// ========================================================
cc_library_shared {
- name: "bluetooth.default",
+ name: "libbluetooth",
defaults: ["fluoride_defaults"],
- relative_install_path: "hw",
+ header_libs: ["libbluetooth_headers"],
+ export_header_lib_headers: ["libbluetooth_headers"],
srcs: [
// platform specific
"bte_conf.cc",
@@ -19,7 +21,7 @@
"system/bt/bta/sys",
"system/bt/bta/dm",
"system/bt/btcore/include",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/stack/include",
"system/bt/stack/l2cap",
"system/bt/stack/a2dp",
@@ -37,6 +39,7 @@
logtags: ["../EventLogTags.logtags"],
shared_libs: [
"android.hardware.bluetooth@1.0",
+ "android.hardware.bluetooth.a2dp@1.0",
"libaudioclient",
"libcutils",
"libdl",
@@ -53,6 +56,7 @@
"libbt-sbc-decoder",
"libbt-sbc-encoder",
"libFraunhoferAAC",
+ "libg722codec",
"libudrv-uipc",
],
whole_static_libs: [
@@ -60,11 +64,11 @@
"libbtdevice",
"libbtif",
"libbt-hci",
- "libbt-protos",
"libbt-stack",
"libbt-utils",
"libbtcore",
"libosi",
+ "libbt-protos-lite",
],
// Shared library link options.
// References to global symbols and functions should bind to the library
@@ -75,7 +79,6 @@
required: [
"bt_did.conf",
"bt_stack.conf",
- "libbt-hci",
"libldacBT_enc",
"libldacBT_abr",
],
@@ -83,3 +86,30 @@
"-DBUILDCFG",
],
}
+
+cc_library_static {
+ name: "libbluetooth-for-tests",
+ defaults: ["fluoride_defaults"],
+
+ srcs: [
+ "bte_conf.cc",
+ "bte_init.cc",
+ "bte_init_cpp_logging.cc",
+ "bte_logmsg.cc",
+ "bte_main.cc",
+ "stack_config.cc",
+ ],
+ include_dirs: [
+ "system/bt",
+ "system/bt/bta/include",
+ "system/bt/btcore/include",
+ "system/bt/btif/include",
+ "system/bt/hci/include",
+ "system/bt/internal_include",
+ "system/bt/stack/include",
+ "system/bt/utils/include",
+ ],
+ cflags: [
+ "-DBUILDCFG",
+ ],
+}
diff --git a/main/BUILD.gn b/main/BUILD.gn
index 957068c..2a07d7b 100644
--- a/main/BUILD.gn
+++ b/main/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,7 +14,14 @@
# limitations under the License.
#
-shared_library("bluetooth.default") {
+config("libbluetooth_config") {
+ include_dirs = [
+ "../include",
+ ]
+}
+
+shared_library("bluetooth") {
+
# HAL layer
sources = [
"//btif/src/bluetooth.cc",
@@ -30,13 +37,15 @@
"stack_config.cc",
]
+ public_configs = [ ":libbluetooth_config" ]
+
include_dirs = [
"//",
"//bta/include",
"//bta/sys",
"//bta/dm",
"//btcore/include",
- "//include",
+ "//internal_include",
"//stack/include",
"//stack/l2cap",
"//stack/a2dp",
diff --git a/main/bte_conf.cc b/main/bte_conf.cc
index f765eb6..a60015a 100644
--- a/main/bte_conf.cc
+++ b/main/bte_conf.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@
void bte_load_did_conf(const char* p_path) {
CHECK(p_path != NULL);
- config_t* config = config_new(p_path);
+ std::unique_ptr<config_t> config = config_new(p_path);
if (!config) {
LOG_ERROR(LOG_TAG, "%s unable to load DID config '%s'.", __func__, p_path);
return;
@@ -43,28 +43,34 @@
char section_name[16] = {0};
snprintf(section_name, sizeof(section_name), "DID%d", i);
- if (!config_has_section(config, section_name)) {
+ if (!config_has_section(*config, section_name)) {
LOG_DEBUG(LOG_TAG, "%s no section named %s.", __func__, section_name);
break;
}
tBTA_DI_RECORD record;
record.vendor =
- config_get_int(config, section_name, "vendorId", LMP_COMPID_BROADCOM);
+ config_get_int(*config, section_name, "vendorId", LMP_COMPID_GOOGLE);
record.vendor_id_source = config_get_int(
- config, section_name, "vendorIdSource", DI_VENDOR_ID_SOURCE_BTSIG);
- record.product = config_get_int(config, section_name, "productId", 0);
- record.version = config_get_int(config, section_name, "version", 0);
+ *config, section_name, "vendorIdSource", DI_VENDOR_ID_SOURCE_BTSIG);
+ record.product = config_get_int(*config, section_name, "productId", 0);
+ record.version = config_get_int(*config, section_name, "version", 0);
record.primary_record =
- config_get_bool(config, section_name, "primaryRecord", false);
- strlcpy(record.client_executable_url,
- config_get_string(config, section_name, "clientExecutableURL", ""),
- sizeof(record.client_executable_url));
- strlcpy(record.service_description,
- config_get_string(config, section_name, "serviceDescription", ""),
- sizeof(record.service_description));
+ config_get_bool(*config, section_name, "primaryRecord", false);
+ std::string empty = "";
+ strlcpy(
+ record.client_executable_url,
+ config_get_string(*config, section_name, "clientExecutableURL", &empty)
+ ->c_str(),
+ sizeof(record.client_executable_url));
+ strlcpy(
+ record.service_description,
+ config_get_string(*config, section_name, "serviceDescription", &empty)
+ ->c_str(),
+ sizeof(record.service_description));
strlcpy(record.documentation_url,
- config_get_string(config, section_name, "documentationURL", ""),
+ config_get_string(*config, section_name, "documentationURL", &empty)
+ ->c_str(),
sizeof(record.documentation_url));
if (record.vendor_id_source != DI_VENDOR_ID_SOURCE_BTSIG &&
@@ -94,6 +100,4 @@
__func__, i, status);
}
}
-
- config_free(config);
}
diff --git a/main/bte_init.cc b/main/bte_init.cc
index 2aa8a97..afbd6bf 100644
--- a/main/bte_init.cc
+++ b/main/bte_init.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2000-2012 Broadcom Corporation
+ * Copyright 2000-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,10 +26,6 @@
#include <string.h>
#include "bt_target.h"
-#ifndef BTA_INCLUDED
-#define BTA_INCLUDED FALSE
-#endif
-
#include "bte.h"
/* Include initialization functions definitions */
@@ -46,10 +42,7 @@
#endif
#include "avrc_api.h"
-
-#if (A2D_INCLUDED == TRUE)
#include "a2dp_api.h"
-#endif
#if (HID_HOST_INCLUDED == TRUE)
#include "hidh_api.h"
@@ -99,9 +92,7 @@
/**************************
* AVDT and its profiles **
**************************/
-#if (A2D_INCLUDED == TRUE)
A2DP_Init();
-#endif /* AADP */
AVRC_Init();
diff --git a/main/bte_init_cpp_logging.cc b/main/bte_init_cpp_logging.cc
index f29500d..f7c10fe 100644
--- a/main/bte_init_cpp_logging.cc
+++ b/main/bte_init_cpp_logging.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Android Open Source Project
+ * Copyright 2016 Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,21 +24,21 @@
// configuring.
if (base::CommandLine::InitializedForCurrentProcess()) return;
- const char* loggingV =
- config_get_string(config, CONFIG_DEFAULT_SECTION, "LoggingV", NULL);
- const char* loggingVModule =
- config_get_string(config, CONFIG_DEFAULT_SECTION, "LoggingVModule", NULL);
+ const std::string* loggingV =
+ config_get_string(*config, CONFIG_DEFAULT_SECTION, "LoggingV", NULL);
+ const std::string* loggingVModule = config_get_string(
+ *config, CONFIG_DEFAULT_SECTION, "LoggingVModule", NULL);
int argc = 1;
const char* argv[] = {"bt_stack", NULL, NULL};
if (loggingV != NULL) {
- argv[argc] = loggingV;
+ argv[argc] = loggingV->c_str();
argc++;
}
if (loggingVModule != NULL) {
- argv[argc] = loggingVModule;
+ argv[argc] = loggingVModule->c_str();
argc++;
}
diff --git a/main/bte_logmsg.cc b/main/bte_logmsg.cc
index 3be38fd..3ccb64d 100644
--- a/main/bte_logmsg.cc
+++ b/main/bte_logmsg.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2001-2012 Broadcom Corporation
+ * Copyright 2001-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,12 +40,8 @@
#include "sdp_api.h"
#include "stack_config.h"
-#if (AVDT_INCLUDED == TRUE)
#include "avdt_api.h"
-#endif
-#if (A2D_INCLUDED == TRUE)
#include "a2dp_api.h"
-#endif
#if (BNEP_INCLUDED == TRUE)
#include "bnep_api.h"
#endif
@@ -66,7 +62,7 @@
#endif
#ifndef BTE_LOG_BUF_SIZE
-#define BTE_LOG_BUF_SIZE 1024
+#define BTE_LOG_BUF_SIZE 256
#endif
#define BTE_LOG_MAX_SIZE (BTE_LOG_BUF_SIZE - 12)
@@ -97,20 +93,12 @@
DEFAULT_CONF_TRACE_LEVEL},
{BTTRC_ID_STK_RFCOMM, BTTRC_ID_STK_RFCOMM_DATA, PORT_SetTraceLevel,
"TRC_RFCOMM", DEFAULT_CONF_TRACE_LEVEL},
-#if (AVDT_INCLUDED == TRUE)
{BTTRC_ID_STK_AVDT, BTTRC_ID_STK_AVDT, AVDT_SetTraceLevel, "TRC_AVDT",
DEFAULT_CONF_TRACE_LEVEL},
-#endif
{BTTRC_ID_STK_AVRC, BTTRC_ID_STK_AVRC, AVRC_SetTraceLevel, "TRC_AVRC",
DEFAULT_CONF_TRACE_LEVEL},
-#if (AVDT_INCLUDED == TRUE)
-//{BTTRC_ID_AVDT_SCB, BTTRC_ID_AVDT_CCB, NULL, "TRC_AVDT_SCB",
-// DEFAULT_CONF_TRACE_LEVEL},
-#endif
-#if (A2D_INCLUDED == TRUE)
{BTTRC_ID_STK_A2DP, BTTRC_ID_STK_A2DP, A2DP_SetTraceLevel, "TRC_A2D",
DEFAULT_CONF_TRACE_LEVEL},
-#endif
#if (BNEP_INCLUDED == TRUE)
{BTTRC_ID_STK_BNEP, BTTRC_ID_STK_BNEP, BNEP_SetTraceLevel, "TRC_BNEP",
DEFAULT_CONF_TRACE_LEVEL},
@@ -144,7 +132,7 @@
{0, 0, NULL, NULL, DEFAULT_CONF_TRACE_LEVEL}};
void LogMsg(uint32_t trace_set_mask, const char* fmt_str, ...) {
- static char buffer[BTE_LOG_BUF_SIZE];
+ char buffer[BTE_LOG_BUF_SIZE];
int trace_layer = TRACE_GET_LAYER(trace_set_mask);
if (trace_layer >= TRACE_LAYER_MAX_NUM) trace_layer = 0;
@@ -199,10 +187,11 @@
for (tBTTRC_FUNC_MAP* functions = &bttrc_set_level_map[0];
functions->trc_name; ++functions) {
- int value =
- config_get_int(config, CONFIG_DEFAULT_SECTION, functions->trc_name, -1);
+ int value = config_get_int(*config, CONFIG_DEFAULT_SECTION,
+ functions->trc_name, -1);
if (value != -1) functions->trace_level = value;
-
+ LOG_INFO(LOG_TAG, "BTE_InitTraceLevels -- %s : Level %d",
+ functions->trc_name, functions->trace_level);
if (functions->p_f) functions->p_f(functions->trace_level);
}
}
diff --git a/main/bte_main.cc b/main/bte_main.cc
index 527d93e..7fdeef03 100644
--- a/main/bte_main.cc
+++ b/main/bte_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/main/main_int.h b/main/main_int.h
index 3ca01c9..5178713 100644
--- a/main/main_int.h
+++ b/main/main_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Android Open Source Project
+ * Copyright 2016 Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/main/stack_config.cc b/main/stack_config.cc
index 1353073..0e56250 100644
--- a/main/stack_config.cc
+++ b/main/stack_config.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,14 +25,17 @@
#include "osi/include/future.h"
#include "osi/include/log.h"
+namespace {
const char* TRACE_CONFIG_ENABLED_KEY = "TraceConf";
+const char* PTS_AVRCP_TEST = "PTS_AvrcpTest";
const char* PTS_SECURE_ONLY_MODE = "PTS_SecurePairOnly";
const char* PTS_LE_CONN_UPDATED_DISABLED = "PTS_DisableConnUpdates";
const char* PTS_DISABLE_SDP_LE_PAIR = "PTS_DisableSDPOnLEPair";
const char* PTS_SMP_PAIRING_OPTIONS_KEY = "PTS_SmpOptions";
const char* PTS_SMP_FAILURE_CASE_KEY = "PTS_SmpFailureCase";
-static config_t* config;
+static std::unique_ptr<config_t> config;
+} // namespace
// Module lifecycle functions
@@ -57,8 +60,7 @@
}
static future_t* clean_up() {
- config_free(config);
- config = NULL;
+ config.reset();
return future_new_immediate(FUTURE_SUCCESS);
}
@@ -72,43 +74,46 @@
// Interface functions
static bool get_trace_config_enabled(void) {
- return config_get_bool(config, CONFIG_DEFAULT_SECTION,
+ return config_get_bool(*config, CONFIG_DEFAULT_SECTION,
TRACE_CONFIG_ENABLED_KEY, false);
}
+static bool get_pts_avrcp_test(void) {
+ return config_get_bool(*config, CONFIG_DEFAULT_SECTION, PTS_AVRCP_TEST,
+ false);
+}
+
static bool get_pts_secure_only_mode(void) {
- return config_get_bool(config, CONFIG_DEFAULT_SECTION, PTS_SECURE_ONLY_MODE,
+ return config_get_bool(*config, CONFIG_DEFAULT_SECTION, PTS_SECURE_ONLY_MODE,
false);
}
static bool get_pts_conn_updates_disabled(void) {
- return config_get_bool(config, CONFIG_DEFAULT_SECTION,
+ return config_get_bool(*config, CONFIG_DEFAULT_SECTION,
PTS_LE_CONN_UPDATED_DISABLED, false);
}
static bool get_pts_crosskey_sdp_disable(void) {
- return config_get_bool(config, CONFIG_DEFAULT_SECTION,
+ return config_get_bool(*config, CONFIG_DEFAULT_SECTION,
PTS_DISABLE_SDP_LE_PAIR, false);
}
-static const char* get_pts_smp_options(void) {
- return config_get_string(config, CONFIG_DEFAULT_SECTION,
+static const std::string* get_pts_smp_options(void) {
+ return config_get_string(*config, CONFIG_DEFAULT_SECTION,
PTS_SMP_PAIRING_OPTIONS_KEY, NULL);
}
static int get_pts_smp_failure_case(void) {
- return config_get_int(config, CONFIG_DEFAULT_SECTION,
+ return config_get_int(*config, CONFIG_DEFAULT_SECTION,
PTS_SMP_FAILURE_CASE_KEY, 0);
}
-static config_t* get_all(void) { return config; }
+static config_t* get_all(void) { return config.get(); }
-const stack_config_t interface = {get_trace_config_enabled,
- get_pts_secure_only_mode,
- get_pts_conn_updates_disabled,
- get_pts_crosskey_sdp_disable,
- get_pts_smp_options,
- get_pts_smp_failure_case,
- get_all};
+const stack_config_t interface = {
+ get_trace_config_enabled, get_pts_avrcp_test,
+ get_pts_secure_only_mode, get_pts_conn_updates_disabled,
+ get_pts_crosskey_sdp_disable, get_pts_smp_options,
+ get_pts_smp_failure_case, get_all};
const stack_config_t* stack_config_get_interface(void) { return &interface; }
diff --git a/osi/Android.bp b/osi/Android.bp
index b93593c..ad2f44b 100644
--- a/osi/Android.bp
+++ b/osi/Android.bp
@@ -3,8 +3,7 @@
defaults: ["fluoride_defaults"],
include_dirs: [
"system/bt",
- "system/bt/include",
- "system/bt/osi/src/protos",
+ "system/bt/internal_include",
"system/bt/utils/include",
"system/bt/stack/include",
]
@@ -21,7 +20,7 @@
host_supported: true,
shared: {
enabled: false
- }
+ },
}
cc_test_library {
@@ -33,22 +32,9 @@
host_supported: true,
shared: {
enabled: false
- }
-}
-
-// Bluetooth Protobuf static library for target and host
-// ========================================================
-cc_library_static {
- name: "libbt-protos",
- defaults: ["fluoride_defaults"],
- srcs: ["src/protos/bluetooth.proto"],
- proto: {
- export_proto_headers: true,
},
- host_supported: true
}
-
// libosi static library for target
// ========================================================
cc_library_static {
@@ -85,16 +71,13 @@
shared_libs: [
"liblog",
],
- static_libs: ["libbt-protos"],
+ static_libs: ["libbt-protos-lite"],
host_supported: true,
// TODO(armansito): Setting _GNU_SOURCE isn't very platform-independent but
// should be compatible for a Linux host OS. We should figure out what to do for
// a non-Linux host OS.
target: {
- darwin: {
- enabled: false,
- },
- linux: {
+ linux_glibc: {
cflags: [
"-D_GNU_SOURCE",
"-DOS_GENERIC",
@@ -139,20 +122,16 @@
"libcutils",
],
static_libs: [
- "libbt-protos",
+ "libbt-protos-lite",
"libgmock",
"libosi",
],
target: {
- linux: {
+ linux_glibc: {
cflags: ["-DOS_GENERIC"],
- host_ldlibs: [
- "-lrt",
- "-lpthread",
- ],
},
- darwin: {
- enabled: false,
- }
+ },
+ sanitize: {
+ cfi: false,
},
}
diff --git a/osi/AndroidTest.xml b/osi/AndroidTest.xml
index a64158c..aa723bb 100644
--- a/osi/AndroidTest.xml
+++ b/osi/AndroidTest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/osi/BUILD.gn b/osi/BUILD.gn
index daecda4..93b74cc 100644
--- a/osi/BUILD.gn
+++ b/osi/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/osi/include/alarm.h b/osi/include/alarm.h
index a01e6d0..b7395ca 100644
--- a/osi/include/alarm.h
+++ b/osi/include/alarm.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/allocation_tracker.h b/osi/include/allocation_tracker.h
index 1e3fa07..a019693 100644
--- a/osi/include/allocation_tracker.h
+++ b/osi/include/allocation_tracker.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/allocator.h b/osi/include/allocator.h
index ef03f9a..3a4141f 100644
--- a/osi/include/allocator.h
+++ b/osi/include/allocator.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/array.h b/osi/include/array.h
index bdae2fa..4b49681 100644
--- a/osi/include/array.h
+++ b/osi/include/array.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/buffer.h b/osi/include/buffer.h
index b81c9e9..a7b3b57 100644
--- a/osi/include/buffer.h
+++ b/osi/include/buffer.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/config.h b/osi/include/config.h
index 0ca4b3a..55adecb 100644
--- a/osi/include/config.h
+++ b/osi/include/config.h
@@ -17,129 +17,114 @@
// - All strings are case sensitive.
#include <stdbool.h>
+#include <list>
+#include <memory>
+#include <string>
// The default section name to use if a key/value pair is not defined within
// a section.
#define CONFIG_DEFAULT_SECTION "Global"
-typedef struct config_t config_t;
-typedef struct config_section_node_t config_section_node_t;
+struct entry_t {
+ std::string key;
+ std::string value;
+};
+
+struct section_t {
+ std::string name;
+ std::list<entry_t> entries;
+};
+
+struct config_t {
+ std::list<section_t> sections;
+};
// Creates a new config object with no entries (i.e. not backed by a file).
-// This function returns a config object or NULL on error. Clients must call
-// |config_free| on the returned handle when it is no longer required.
-config_t* config_new_empty(void);
+// This function returns a unique pointer to config object.
+std::unique_ptr<config_t> config_new_empty(void);
// Loads the specified file and returns a handle to the config file. If there
-// was a problem loading the file or allocating memory, this function returns
-// NULL. Clients must call |config_free| on the returned handle when it is no
-// longer required. |filename| must not be NULL and must point to a readable
+// was a problem loading the file, this function returns
+// NULL. |filename| must not be NULL and must point to a readable
// file on the filesystem.
-config_t* config_new(const char* filename);
+std::unique_ptr<config_t> config_new(const char* filename);
// Clones |src|, including all of it's sections, keys, and values.
// Returns a new config which is a copy and separated from the original;
// changes to the new config are not reflected in any way in the original.
//
-// |src| must not be NULL
// This function will not return NULL.
-// Clients must call config_free on the returned object.
-config_t* config_new_clone(const config_t* src);
-
-// Frees resources associated with the config file. No further operations may
-// be performed on the |config| object after calling this function. |config|
-// may be NULL.
-void config_free(config_t* config);
+std::unique_ptr<config_t> config_new_clone(const config_t& src);
// Returns true if the config file contains a section named |section|. If
// the section has no key/value pairs in it, this function will return false.
-// |config| and |section| must not be NULL.
-bool config_has_section(const config_t* config, const char* section);
+bool config_has_section(const config_t& config, const std::string& section);
// Returns true if the config file has a key named |key| under |section|.
-// Returns false otherwise. |config|, |section|, and |key| must not be NULL.
-bool config_has_key(const config_t* config, const char* section,
- const char* key);
+// Returns false otherwise.
+bool config_has_key(const config_t& config, const std::string& section,
+ const std::string& key);
// Returns the integral value for a given |key| in |section|. If |section|
// or |key| do not exist, or the value cannot be fully converted to an integer,
-// this function returns |def_value|. |config|, |section|, and |key| must not
-// be NULL.
-int config_get_int(const config_t* config, const char* section, const char* key,
- int def_value);
+// this function returns |def_value|.
+int config_get_int(const config_t& config, const std::string& section,
+ const std::string& key, int def_value);
+
+// Returns the uint64_t value for a given |key| in |section|. If |section|
+// or |key| do not exist, or the value cannot be fully converted to an integer,
+// this function returns |def_value|.
+uint64_t config_get_uint64(const config_t& config, const std::string& section,
+ const std::string& key, uint64_t def_value);
// Returns the boolean value for a given |key| in |section|. If |section|
// or |key| do not exist, or the value cannot be converted to a boolean, this
-// function returns |def_value|. |config|, |section|, and |key| must not be
-// NULL.
-bool config_get_bool(const config_t* config, const char* section,
- const char* key, bool def_value);
+// function returns |def_value|.
+bool config_get_bool(const config_t& config, const std::string& section,
+ const std::string& key, bool def_value);
// Returns the string value for a given |key| in |section|. If |section| or
// |key| do not exist, this function returns |def_value|. The returned string
-// is owned by the config module and must not be freed. |config|, |section|,
-// and |key| must not be NULL. |def_value| may be NULL.
-const char* config_get_string(const config_t* config, const char* section,
- const char* key, const char* def_value);
+// is owned by the config module and must not be freed or modified. |def_value|
+// may be NULL.
+const std::string* config_get_string(const config_t& config,
+ const std::string& section,
+ const std::string& key,
+ const std::string* def_value);
// Sets an integral value for the |key| in |section|. If |key| or |section| do
-// not already exist, this function creates them. |config|, |section|, and |key|
-// must not be NULL.
-void config_set_int(config_t* config, const char* section, const char* key,
- int value);
+// not already exist, this function creates them. |config| must not be NULL.
+void config_set_int(config_t* config, const std::string& section,
+ const std::string& key, int value);
+
+// Sets a uint64_t value for the |key| in |section|. If |key| or |section| do
+// not already exist, this function creates them. |config| must not be NULL.
+void config_set_uint64(config_t* config, const std::string& section,
+ const std::string& key, uint64_t value);
// Sets a boolean value for the |key| in |section|. If |key| or |section| do
-// not already exist, this function creates them. |config|, |section|, and |key|
-// must not be NULL.
-void config_set_bool(config_t* config, const char* section, const char* key,
- bool value);
+// not already exist, this function creates them. |config| must not be NULL.
+void config_set_bool(config_t* config, const std::string& section,
+ const std::string& key, bool value);
// Sets a string value for the |key| in |section|. If |key| or |section| do
-// not already exist, this function creates them. |config|, |section|, |key|,
-// and
-// |value| must not be NULL.
-void config_set_string(config_t* config, const char* section, const char* key,
- const char* value);
+// not already exist, this function creates them. |config| must not be NULL.
+void config_set_string(config_t* config, const std::string& section,
+ const std::string& key, const std::string& value);
// Removes |section| from the |config| (and, as a result, all keys in the
// section).
// Returns true if |section| was found and removed from |config|, false
// otherwise.
-// Neither |config| nor |section| may be NULL.
-bool config_remove_section(config_t* config, const char* section);
+// |config| may be NULL.
+bool config_remove_section(config_t* config, const std::string& section);
// Removes one specific |key| residing in |section| of the |config|. Returns
// true
// if the section and key were found and the key was removed, false otherwise.
-// None of |config|, |section|, or |key| may be NULL.
-bool config_remove_key(config_t* config, const char* section, const char* key);
-
-// Returns an iterator to the first section in the config file. If there are no
-// sections, the iterator will equal the return value of |config_section_end|.
-// The returned pointer must be treated as an opaque handle and must not be
-// freed.
-// The iterator is invalidated on any config mutating operation. |config| may
-// not be NULL.
-const config_section_node_t* config_section_begin(const config_t* config);
-
-// Returns an iterator to one past the last section in the config file. It does
-// not represent a valid section, but can be used to determine if all sections
-// have been iterated over. The returned pointer must be treated as an opaque
-// handle and must not be freed and must not be iterated on (must not call
-// |config_section_next| on it). |config| may not be NULL.
-const config_section_node_t* config_section_end(const config_t* config);
-
-// Moves |iter| to the next section. If there are no more sections, |iter| will
-// equal the value of |config_section_end|. |iter| may not be NULL and must be
-// a pointer returned by either |config_section_begin| or |config_section_next|.
-const config_section_node_t* config_section_next(
- const config_section_node_t* iter);
-
-// Returns the name of the section referred to by |iter|. The returned pointer
-// is owned by the config module and must not be freed by the caller. The
-// pointer will remain valid until |config_free| is called. |iter| may not be
-// NULL and must not equal the value returned by |config_section_end|.
-const char* config_section_name(const config_section_node_t* iter);
+// |config|may not be NULL.
+bool config_remove_key(config_t* config, const std::string& section,
+ const std::string& key);
// Saves |config| to a file given by |filename|. Note that this could be a
// destructive operation: if |filename| already exists, it will be overwritten.
@@ -147,4 +132,4 @@
// file was opened with |config_new| and subsequently overwritten with
// |config_save|, all comments and special formatting in the original file will
// be lost. Neither |config| nor |filename| may be NULL.
-bool config_save(const config_t* config, const char* filename);
+bool config_save(const config_t& config, const std::string& filename);
diff --git a/osi/include/fixed_queue.h b/osi/include/fixed_queue.h
index 6b98f7e..adbc5be 100644
--- a/osi/include/fixed_queue.h
+++ b/osi/include/fixed_queue.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/future.h b/osi/include/future.h
index 3ed1a21..dc743e6 100644
--- a/osi/include/future.h
+++ b/osi/include/future.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/hash_map_utils.h b/osi/include/hash_map_utils.h
index 1ea3996..7bf8de2 100644
--- a/osi/include/hash_map_utils.h
+++ b/osi/include/hash_map_utils.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/leaky_bonded_queue.h b/osi/include/leaky_bonded_queue.h
index 8259cdc..6861e8b 100644
--- a/osi/include/leaky_bonded_queue.h
+++ b/osi/include/leaky_bonded_queue.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/list.h b/osi/include/list.h
index 50c3e2c..ae738f5 100644
--- a/osi/include/list.h
+++ b/osi/include/list.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/log.h b/osi/include/log.h
index d42ea62..1c2e96d 100644
--- a/osi/include/log.h
+++ b/osi/include/log.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/metrics.h b/osi/include/metrics.h
index dcd1a20..504a16a 100644
--- a/osi/include/metrics.h
+++ b/osi/include/metrics.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
#pragma once
+#include <bta/include/bta_api.h>
#include <stdint.h>
#include <memory>
#include <string>
@@ -104,6 +105,8 @@
int32_t buffer_overruns_total = -1;
float buffer_underruns_average = -1;
int32_t buffer_underruns_count = -1;
+ int64_t codec_index = -1;
+ bool is_a2dp_offload = false;
};
class BluetoothMetricsLogger {
@@ -209,13 +212,20 @@
*/
void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics);
- /*
- * Writes the metrics, in base64 protobuf format, into the descriptor FD
- * If CLEAR is true, metrics events are cleared afterwards.
+ /**
+ * Log Headset profile RFCOMM connection event
+ *
+ * @param service_id the BTA service ID for this headset connection
*/
- void WriteBase64(int fd, bool clear);
- void WriteBase64String(std::string* serialized, bool clear);
- void WriteString(std::string* serialized, bool clear);
+ void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id);
+
+ /*
+ * Writes the metrics, in base64 protobuf format, into the descriptor FD,
+ * metrics events are always cleared after dump
+ */
+ void WriteBase64(int fd);
+ void WriteBase64String(std::string* serialized);
+ void WriteString(std::string* serialized);
/*
* Reset the metrics logger by cleaning up its staging queues and existing
diff --git a/osi/include/mutex.h b/osi/include/mutex.h
index bf00983..0d9fe10 100644
--- a/osi/include/mutex.h
+++ b/osi/include/mutex.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/osi.h b/osi/include/osi.h
index 3359cbf..a39d56c 100644
--- a/osi/include/osi.h
+++ b/osi/include/osi.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,15 +35,6 @@
#define DUMMY_COUNTER(c) CONCAT(__osi_dummy_, c)
#define DUMMY_PTR DUMMY_COUNTER(__COUNTER__)
-// base/macros.h defines a COMPILE_ASSERT macro to the C++11 keyword
-// "static_assert" (it undef's COMPILE_ASSERT before redefining it).
-// C++ code that includes base and osi/include/osi.h can thus easily default to
-// the definition from libbase but we should check here to avoid compile errors.
-#ifndef COMPILE_ASSERT
-#define COMPILE_ASSERT(COND) \
- typedef int failed_compile_assert[(COND) ? 1 : -1] __attribute__((unused))
-#endif // COMPILE_ASSERT
-
// Macros for safe integer to pointer conversion. In the C language, data is
// commonly cast to opaque pointer containers and back for generic parameter
// passing in callbacks. These macros should be used sparingly in new code
diff --git a/osi/include/properties.h b/osi/include/properties.h
index ececef5..b186f4f 100644
--- a/osi/include/properties.h
+++ b/osi/include/properties.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,11 +19,9 @@
#pragma once
#include <cstdint>
-#if defined(OS_GENERIC)
+
#define PROPERTY_VALUE_MAX 92
-#else
-#include <cutils/properties.h>
-#endif // defined(OS_GENERIC)
+#define BUILD_SANITY_PROPERTY_VALUE_MAX 92
// Get value associated with key |key| into |value|.
// Returns the length of the value which will never be greater than
@@ -43,3 +41,10 @@
// returns the value of |key| truncated and coerced into an
// int32_t. If the property is not set, then the |default_value| is used.
int32_t osi_property_get_int32(const char* key, int32_t default_value);
+
+// Adapter function for property_get_bool in
+// libcutils/include/cutils/properties.h
+//
+// returns the value of |key| coerced into a bool. If the property is not set,
+// then the |default_value| is used.
+bool osi_property_get_bool(const char* key, bool default_value);
\ No newline at end of file
diff --git a/osi/include/reactor.h b/osi/include/reactor.h
index c868a01..211cdd8 100644
--- a/osi/include/reactor.h
+++ b/osi/include/reactor.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/ringbuffer.h b/osi/include/ringbuffer.h
index 6a3c3fa..db0d674 100644
--- a/osi/include/ringbuffer.h
+++ b/osi/include/ringbuffer.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/semaphore.h b/osi/include/semaphore.h
index 9c8f6fb..3ae5e0f 100644
--- a/osi/include/semaphore.h
+++ b/osi/include/semaphore.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/socket.h b/osi/include/socket.h
index 5cd8938..83a4f2d 100644
--- a/osi/include/socket.h
+++ b/osi/include/socket.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/socket_utils/socket_local.h b/osi/include/socket_utils/socket_local.h
index fd3b00c..9fcb9d5 100644
--- a/osi/include/socket_utils/socket_local.h
+++ b/osi/include/socket_utils/socket_local.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/socket_utils/sockets.h b/osi/include/socket_utils/sockets.h
index fc7514f..d2a05d3 100644
--- a/osi/include/socket_utils/sockets.h
+++ b/osi/include/socket_utils/sockets.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/thread.h b/osi/include/thread.h
index c8da381..f69fa34 100644
--- a/osi/include/thread.h
+++ b/osi/include/thread.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/time.h b/osi/include/time.h
index 0988c20..8f533d0 100644
--- a/osi/include/time.h
+++ b/osi/include/time.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/include/wakelock.h b/osi/include/wakelock.h
index 502f9fb..b1475ce 100644
--- a/osi/include/wakelock.h
+++ b/osi/include/wakelock.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/alarm.cc b/osi/src/alarm.cc
index 9bf9cc5..83a661d 100644
--- a/osi/src/alarm.cc
+++ b/osi/src/alarm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
*
******************************************************************************/
-#include "include/bt_target.h"
+#include "internal_include/bt_target.h"
#define LOG_TAG "bt_osi_alarm"
@@ -647,7 +647,8 @@
}
alarm->closure.i.Reset(Bind(alarm_ready_mloop, alarm));
- get_message_loop()->PostTask(FROM_HERE, alarm->closure.i.callback());
+ get_message_loop()->task_runner()->PostTask(FROM_HERE,
+ alarm->closure.i.callback());
} else {
fixed_queue_enqueue(alarm->queue, alarm);
}
diff --git a/osi/src/allocation_tracker.cc b/osi/src/allocation_tracker.cc
index 2dee1dc..ba6b7f1 100644
--- a/osi/src/allocation_tracker.cc
+++ b/osi/src/allocation_tracker.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/allocator.cc b/osi/src/allocator.cc
index 4e4f9a7..1c0449e 100644
--- a/osi/src/allocator.cc
+++ b/osi/src/allocator.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/array.cc b/osi/src/array.cc
index 913b711..f28a70c 100644
--- a/osi/src/array.cc
+++ b/osi/src/array.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/buffer.cc b/osi/src/buffer.cc
index abfacdb..41eea00 100644
--- a/osi/src/buffer.cc
+++ b/osi/src/buffer.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/config.cc b/osi/src/config.cc
index fc64d47..d4ed2e6 100644
--- a/osi/src/config.cc
+++ b/osi/src/config.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,10 @@
*
******************************************************************************/
-#define LOG_TAG "bt_osi_config"
-
#include "osi/include/config.h"
+#include "log/log.h"
+#include <base/files/file_path.h>
#include <base/logging.h>
#include <ctype.h>
#include <errno.h>
@@ -30,267 +30,195 @@
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
-
-#include "osi/include/allocator.h"
-#include "osi/include/list.h"
-#include "osi/include/log.h"
-#include "log/log.h"
-
-typedef struct {
- char* key;
- char* value;
-} entry_t;
-
-typedef struct {
- char* name;
- list_t* entries;
-} section_t;
-
-struct config_t {
- list_t* sections;
-};
+#include <sstream>
+#include <type_traits>
// Empty definition; this type is aliased to list_node_t.
struct config_section_iter_t {};
static bool config_parse(FILE* fp, config_t* config);
-static section_t* section_new(const char* name);
-static void section_free(void* ptr);
-static section_t* section_find(const config_t* config, const char* section);
-
-static entry_t* entry_new(const char* key, const char* value);
-static void entry_free(void* ptr);
-static entry_t* entry_find(const config_t* config, const char* section,
- const char* key);
-
-config_t* config_new_empty(void) {
- config_t* config = static_cast<config_t*>(osi_calloc(sizeof(config_t)));
-
- config->sections = list_new(section_free);
- if (!config->sections) {
- LOG_ERROR(LOG_TAG, "%s unable to allocate list for sections.", __func__);
- goto error;
- }
-
- return config;
-
-error:;
- config_free(config);
- return NULL;
+template <typename T,
+ class = typename std::enable_if<std::is_same<
+ config_t, typename std::remove_const<T>::type>::value>>
+static auto section_find(T& config, const std::string& section) {
+ return std::find_if(
+ config.sections.begin(), config.sections.end(),
+ [§ion](const section_t& sec) { return sec.name == section; });
}
-config_t* config_new(const char* filename) {
- CHECK(filename != NULL);
+static const entry_t* entry_find(const config_t& config,
+ const std::string& section,
+ const std::string& key) {
+ auto sec = section_find(config, section);
+ if (sec == config.sections.end()) return nullptr;
- config_t* config = config_new_empty();
- if (!config) return NULL;
+ for (const entry_t& entry : sec->entries) {
+ if (entry.key == key) return &entry;
+ }
+
+ return nullptr;
+}
+
+std::unique_ptr<config_t> config_new_empty(void) {
+ return std::make_unique<config_t>();
+}
+
+std::unique_ptr<config_t> config_new(const char* filename) {
+ CHECK(filename != nullptr);
+
+ std::unique_ptr<config_t> config = config_new_empty();
FILE* fp = fopen(filename, "rt");
if (!fp) {
- LOG_ERROR(LOG_TAG, "%s unable to open file '%s': %s", __func__, filename,
- strerror(errno));
- config_free(config);
- return NULL;
+ LOG(ERROR) << __func__ << ": unable to open file '" << filename
+ << "': " << strerror(errno);
+ return nullptr;
}
- if (!config_parse(fp, config)) {
- config_free(config);
- config = NULL;
+ if (!config_parse(fp, config.get())) {
+ config.reset();
}
fclose(fp);
return config;
}
-config_t* config_new_clone(const config_t* src) {
- CHECK(src != NULL);
+std::unique_ptr<config_t> config_new_clone(const config_t& src) {
+ std::unique_ptr<config_t> ret = config_new_empty();
- config_t* ret = config_new_empty();
-
- CHECK(ret != NULL);
-
- for (const list_node_t* node = list_begin(src->sections);
- node != list_end(src->sections); node = list_next(node)) {
- section_t* sec = static_cast<section_t*>(list_node(node));
-
- for (const list_node_t* node_entry = list_begin(sec->entries);
- node_entry != list_end(sec->entries);
- node_entry = list_next(node_entry)) {
- entry_t* entry = static_cast<entry_t*>(list_node(node_entry));
-
- config_set_string(ret, sec->name, entry->key, entry->value);
+ for (const section_t& sec : src.sections) {
+ for (const entry_t& entry : sec.entries) {
+ config_set_string(ret.get(), sec.name, entry.key, entry.value);
}
}
return ret;
}
-void config_free(config_t* config) {
- if (!config) return;
-
- list_free(config->sections);
- osi_free(config);
+bool config_has_section(const config_t& config, const std::string& section) {
+ return (section_find(config, section) != config.sections.end());
}
-bool config_has_section(const config_t* config, const char* section) {
- CHECK(config != NULL);
- CHECK(section != NULL);
-
- return (section_find(config, section) != NULL);
+bool config_has_key(const config_t& config, const std::string& section,
+ const std::string& key) {
+ return (entry_find(config, section, key) != nullptr);
}
-bool config_has_key(const config_t* config, const char* section,
- const char* key) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
-
- return (entry_find(config, section, key) != NULL);
-}
-
-int config_get_int(const config_t* config, const char* section, const char* key,
- int def_value) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
-
- entry_t* entry = entry_find(config, section, key);
+int config_get_int(const config_t& config, const std::string& section,
+ const std::string& key, int def_value) {
+ const entry_t* entry = entry_find(config, section, key);
if (!entry) return def_value;
char* endptr;
- int ret = strtol(entry->value, &endptr, 0);
+ int ret = strtol(entry->value.c_str(), &endptr, 0);
return (*endptr == '\0') ? ret : def_value;
}
-bool config_get_bool(const config_t* config, const char* section,
- const char* key, bool def_value) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
-
- entry_t* entry = entry_find(config, section, key);
+uint64_t config_get_uint64(const config_t& config, const std::string& section,
+ const std::string& key, uint64_t def_value) {
+ const entry_t* entry = entry_find(config, section, key);
if (!entry) return def_value;
- if (!strcmp(entry->value, "true")) return true;
- if (!strcmp(entry->value, "false")) return false;
+ char* endptr;
+ uint64_t ret = strtoull(entry->value.c_str(), &endptr, 0);
+ return (*endptr == '\0') ? ret : def_value;
+}
+
+bool config_get_bool(const config_t& config, const std::string& section,
+ const std::string& key, bool def_value) {
+ const entry_t* entry = entry_find(config, section, key);
+ if (!entry) return def_value;
+
+ if (entry->value == "true") return true;
+ if (entry->value == "false") return false;
return def_value;
}
-const char* config_get_string(const config_t* config, const char* section,
- const char* key, const char* def_value) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
-
- entry_t* entry = entry_find(config, section, key);
+const std::string* config_get_string(const config_t& config,
+ const std::string& section,
+ const std::string& key,
+ const std::string* def_value) {
+ const entry_t* entry = entry_find(config, section, key);
if (!entry) return def_value;
- return entry->value;
+ return &entry->value;
}
-void config_set_int(config_t* config, const char* section, const char* key,
- int value) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
-
- char value_str[32] = {0};
- snprintf(value_str, sizeof(value_str), "%d", value);
- config_set_string(config, section, key, value_str);
+void config_set_int(config_t* config, const std::string& section,
+ const std::string& key, int value) {
+ config_set_string(config, section, key, std::to_string(value));
}
-void config_set_bool(config_t* config, const char* section, const char* key,
- bool value) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
+void config_set_uint64(config_t* config, const std::string& section,
+ const std::string& key, uint64_t value) {
+ config_set_string(config, section, key, std::to_string(value));
+}
+void config_set_bool(config_t* config, const std::string& section,
+ const std::string& key, bool value) {
config_set_string(config, section, key, value ? "true" : "false");
}
-void config_set_string(config_t* config, const char* section, const char* key,
- const char* value) {
- section_t* sec = section_find(config, section);
- if (!sec) {
- sec = section_new(section);
- list_append(config->sections, sec);
+void config_set_string(config_t* config, const std::string& section,
+ const std::string& key, const std::string& value) {
+ CHECK(config);
+
+ auto sec = section_find(*config, section);
+ if (sec == config->sections.end()) {
+ config->sections.emplace_back(section_t{.name = section});
+ sec = std::prev(config->sections.end());
}
- std::string value_string = value;
std::string value_no_newline;
- size_t newline_position = value_string.find("\n");
+ size_t newline_position = value.find("\n");
if (newline_position != std::string::npos) {
android_errorWriteLog(0x534e4554, "70808273");
- value_no_newline = value_string.substr(0, newline_position);
+ value_no_newline = value.substr(0, newline_position);
} else {
- value_no_newline = value_string;
+ value_no_newline = value;
}
- for (const list_node_t* node = list_begin(sec->entries);
- node != list_end(sec->entries); node = list_next(node)) {
- entry_t* entry = static_cast<entry_t*>(list_node(node));
- if (!strcmp(entry->key, key)) {
- osi_free(entry->value);
- entry->value = osi_strdup(value_no_newline.c_str());
+ for (entry_t& entry : sec->entries) {
+ if (entry.key == key) {
+ entry.value = value_no_newline;
return;
}
}
- entry_t* entry = entry_new(key, value_no_newline.c_str());
- list_append(sec->entries, entry);
+ sec->entries.emplace_back(entry_t{.key = key, .value = value_no_newline});
}
-bool config_remove_section(config_t* config, const char* section) {
- CHECK(config != NULL);
- CHECK(section != NULL);
+bool config_remove_section(config_t* config, const std::string& section) {
+ CHECK(config);
- section_t* sec = section_find(config, section);
- if (!sec) return false;
+ auto sec = section_find(*config, section);
+ if (sec == config->sections.end()) return false;
- return list_remove(config->sections, sec);
+ config->sections.erase(sec);
+ return true;
}
-bool config_remove_key(config_t* config, const char* section, const char* key) {
- CHECK(config != NULL);
- CHECK(section != NULL);
- CHECK(key != NULL);
+bool config_remove_key(config_t* config, const std::string& section,
+ const std::string& key) {
+ CHECK(config);
+ auto sec = section_find(*config, section);
+ if (sec == config->sections.end()) return false;
- section_t* sec = section_find(config, section);
- entry_t* entry = entry_find(config, section, key);
- if (!sec || !entry) return false;
+ for (auto entry = sec->entries.begin(); entry != sec->entries.end();
+ ++entry) {
+ if (entry->key == key) {
+ sec->entries.erase(entry);
+ return true;
+ }
+ }
- return list_remove(sec->entries, entry);
+ return false;
}
-const config_section_node_t* config_section_begin(const config_t* config) {
- CHECK(config != NULL);
- return (const config_section_node_t*)list_begin(config->sections);
-}
-
-const config_section_node_t* config_section_end(const config_t* config) {
- CHECK(config != NULL);
- return (const config_section_node_t*)list_end(config->sections);
-}
-
-const config_section_node_t* config_section_next(
- const config_section_node_t* node) {
- CHECK(node != NULL);
- return (const config_section_node_t*)list_next((const list_node_t*)node);
-}
-
-const char* config_section_name(const config_section_node_t* node) {
- CHECK(node != NULL);
- const list_node_t* lnode = (const list_node_t*)node;
- const section_t* section = (const section_t*)list_node(lnode);
- return section->name;
-}
-
-bool config_save(const config_t* config, const char* filename) {
- CHECK(config != NULL);
- CHECK(filename != NULL);
- CHECK(*filename != '\0');
+bool config_save(const config_t& config, const std::string& filename) {
+ CHECK(!filename.empty());
// Steps to ensure content of config file gets to disk:
//
@@ -301,119 +229,98 @@
// 4) Sync directory that has the conf file with fsync().
// This ensures directory entries are up-to-date.
int dir_fd = -1;
- FILE* fp = NULL;
+ FILE* fp = nullptr;
+ std::stringstream serialized;
// Build temp config file based on config file (e.g. bt_config.conf.new).
- static const char* temp_file_ext = ".new";
- const int filename_len = strlen(filename);
- const int temp_filename_len = filename_len + strlen(temp_file_ext) + 1;
- char* temp_filename = static_cast<char*>(osi_calloc(temp_filename_len));
- snprintf(temp_filename, temp_filename_len, "%s%s", filename, temp_file_ext);
+ const std::string temp_filename = filename + ".new";
// Extract directory from file path (e.g. /data/misc/bluedroid).
- char* temp_dirname = osi_strdup(filename);
- const char* directoryname = dirname(temp_dirname);
- if (!directoryname) {
- LOG_ERROR(LOG_TAG, "%s error extracting directory from '%s': %s", __func__,
- filename, strerror(errno));
+ const std::string directoryname = base::FilePath(filename).DirName().value();
+ if (directoryname.empty()) {
+ LOG(ERROR) << __func__ << ": error extracting directory from '" << filename
+ << "': " << strerror(errno);
goto error;
}
- dir_fd = open(directoryname, O_RDONLY);
+ dir_fd = open(directoryname.c_str(), O_RDONLY);
if (dir_fd < 0) {
- LOG_ERROR(LOG_TAG, "%s unable to open dir '%s': %s", __func__,
- directoryname, strerror(errno));
+ LOG(ERROR) << __func__ << ": unable to open dir '" << directoryname
+ << "': " << strerror(errno);
goto error;
}
- fp = fopen(temp_filename, "wt");
+ fp = fopen(temp_filename.c_str(), "wt");
if (!fp) {
- LOG_ERROR(LOG_TAG, "%s unable to write file '%s': %s", __func__,
- temp_filename, strerror(errno));
+ LOG(ERROR) << __func__ << ": unable to write to file '" << temp_filename
+ << "': " << strerror(errno);
goto error;
}
- for (const list_node_t* node = list_begin(config->sections);
- node != list_end(config->sections); node = list_next(node)) {
- const section_t* section = (const section_t*)list_node(node);
- if (fprintf(fp, "[%s]\n", section->name) < 0) {
- LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__,
- temp_filename, strerror(errno));
- goto error;
- }
+ for (const section_t& section : config.sections) {
+ serialized << "[" << section.name << "]" << std::endl;
- for (const list_node_t* enode = list_begin(section->entries);
- enode != list_end(section->entries); enode = list_next(enode)) {
- const entry_t* entry = (const entry_t*)list_node(enode);
- if (fprintf(fp, "%s = %s\n", entry->key, entry->value) < 0) {
- LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__,
- temp_filename, strerror(errno));
- goto error;
- }
- }
+ for (const entry_t& entry : section.entries)
+ serialized << entry.key << " = " << entry.value << std::endl;
- // Only add a separating newline if there are more sections.
- if (list_next(node) != list_end(config->sections)) {
- if (fputc('\n', fp) == EOF) {
- LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__,
- temp_filename, strerror(errno));
- goto error;
- }
- }
+ serialized << std::endl;
+ }
+
+ if (fprintf(fp, "%s", serialized.str().c_str()) < 0) {
+ LOG(ERROR) << __func__ << ": unable to write to file '" << temp_filename
+ << "': " << strerror(errno);
+ goto error;
}
// Sync written temp file out to disk. fsync() is blocking until data makes it
// to disk.
if (fsync(fileno(fp)) < 0) {
- LOG_WARN(LOG_TAG, "%s unable to fsync file '%s': %s", __func__,
- temp_filename, strerror(errno));
+ LOG(WARNING) << __func__ << ": unable to fsync file '" << temp_filename
+ << "': " << strerror(errno);
}
if (fclose(fp) == EOF) {
- LOG_ERROR(LOG_TAG, "%s unable to close file '%s': %s", __func__,
- temp_filename, strerror(errno));
+ LOG(ERROR) << __func__ << ": unable to close file '" << temp_filename
+ << "': " << strerror(errno);
goto error;
}
- fp = NULL;
+ fp = nullptr;
// Change the file's permissions to Read/Write by User and Group
- if (chmod(temp_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1) {
- LOG_ERROR(LOG_TAG, "%s unable to change file permissions '%s': %s",
- __func__, filename, strerror(errno));
+ if (chmod(temp_filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) ==
+ -1) {
+ LOG(ERROR) << __func__ << ": unable to change file permissions '"
+ << filename << "': " << strerror(errno);
goto error;
}
// Rename written temp file to the actual config file.
- if (rename(temp_filename, filename) == -1) {
- LOG_ERROR(LOG_TAG, "%s unable to commit file '%s': %s", __func__, filename,
- strerror(errno));
+ if (rename(temp_filename.c_str(), filename.c_str()) == -1) {
+ LOG(ERROR) << __func__ << ": unable to commit file '" << filename
+ << "': " << strerror(errno);
goto error;
}
// This should ensure the directory is updated as well.
if (fsync(dir_fd) < 0) {
- LOG_WARN(LOG_TAG, "%s unable to fsync dir '%s': %s", __func__,
- directoryname, strerror(errno));
+ LOG(WARNING) << __func__ << ": unable to fsync dir '" << directoryname
+ << "': " << strerror(errno);
}
if (close(dir_fd) < 0) {
- LOG_ERROR(LOG_TAG, "%s unable to close dir '%s': %s", __func__,
- directoryname, strerror(errno));
+ LOG(ERROR) << __func__ << ": unable to close dir '" << directoryname
+ << "': " << strerror(errno);
goto error;
}
- osi_free(temp_filename);
- osi_free(temp_dirname);
return true;
error:
// This indicates there is a write issue. Unlink as partial data is not
// acceptable.
- unlink(temp_filename);
+ unlink(temp_filename.c_str());
if (fp) fclose(fp);
if (dir_fd != -1) close(dir_fd);
- osi_free(temp_filename);
- osi_free(temp_dirname);
return false;
}
@@ -430,8 +337,8 @@
}
static bool config_parse(FILE* fp, config_t* config) {
- CHECK(fp != NULL);
- CHECK(config != NULL);
+ CHECK(fp != nullptr);
+ CHECK(config != nullptr);
int line_num = 0;
char line[1024];
@@ -448,17 +355,17 @@
if (*line_ptr == '[') {
size_t len = strlen(line_ptr);
if (line_ptr[len - 1] != ']') {
- LOG_DEBUG(LOG_TAG, "%s unterminated section name on line %d.", __func__,
- line_num);
+ VLOG(1) << __func__ << ": unterminated section name on line "
+ << line_num;
return false;
}
- strncpy(section, line_ptr + 1, len - 2);
+ strncpy(section, line_ptr + 1, len - 2); // NOLINT (len < 1024)
section[len - 2] = '\0';
} else {
char* split = strchr(line_ptr, '=');
if (!split) {
- LOG_DEBUG(LOG_TAG, "%s no key/value separator found on line %d.",
- __func__, line_num);
+ VLOG(1) << __func__ << ": no key/value separator found on line "
+ << line_num;
return false;
}
@@ -468,61 +375,3 @@
}
return true;
}
-
-static section_t* section_new(const char* name) {
- section_t* section = static_cast<section_t*>(osi_calloc(sizeof(section_t)));
-
- section->name = osi_strdup(name);
- section->entries = list_new(entry_free);
- return section;
-}
-
-static void section_free(void* ptr) {
- if (!ptr) return;
-
- section_t* section = static_cast<section_t*>(ptr);
- osi_free(section->name);
- list_free(section->entries);
- osi_free(section);
-}
-
-static section_t* section_find(const config_t* config, const char* section) {
- for (const list_node_t* node = list_begin(config->sections);
- node != list_end(config->sections); node = list_next(node)) {
- section_t* sec = static_cast<section_t*>(list_node(node));
- if (!strcmp(sec->name, section)) return sec;
- }
-
- return NULL;
-}
-
-static entry_t* entry_new(const char* key, const char* value) {
- entry_t* entry = static_cast<entry_t*>(osi_calloc(sizeof(entry_t)));
-
- entry->key = osi_strdup(key);
- entry->value = osi_strdup(value);
- return entry;
-}
-
-static void entry_free(void* ptr) {
- if (!ptr) return;
-
- entry_t* entry = static_cast<entry_t*>(ptr);
- osi_free(entry->key);
- osi_free(entry->value);
- osi_free(entry);
-}
-
-static entry_t* entry_find(const config_t* config, const char* section,
- const char* key) {
- section_t* sec = section_find(config, section);
- if (!sec) return NULL;
-
- for (const list_node_t* node = list_begin(sec->entries);
- node != list_end(sec->entries); node = list_next(node)) {
- entry_t* entry = static_cast<entry_t*>(list_node(node));
- if (!strcmp(entry->key, key)) return entry;
- }
-
- return NULL;
-}
diff --git a/osi/src/fixed_queue.cc b/osi/src/fixed_queue.cc
index c384050..81bd66d 100644
--- a/osi/src/fixed_queue.cc
+++ b/osi/src/fixed_queue.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/future.cc b/osi/src/future.cc
index cbfd91a..e5347a4 100644
--- a/osi/src/future.cc
+++ b/osi/src/future.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/hash_map_utils.cc b/osi/src/hash_map_utils.cc
index c934cfb..6cd58de 100644
--- a/osi/src/hash_map_utils.cc
+++ b/osi/src/hash_map_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/metrics.cc b/osi/src/metrics.cc
index f31bf4e..73450b9 100644
--- a/osi/src/metrics.cc
+++ b/osi/src/metrics.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
#include <unistd.h>
#include <algorithm>
+#include <array>
#include <cerrno>
#include <chrono>
#include <cstdint>
@@ -28,33 +29,41 @@
#include <base/base64.h>
#include <base/logging.h>
+#include <include/hardware/bt_av.h>
+#include "bluetooth/metrics/bluetooth.pb.h"
#include "osi/include/leaky_bonded_queue.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
#include "osi/include/time.h"
#include "stack/include/btm_api_types.h"
-#include "src/protos/bluetooth.pb.h"
-
#include "osi/include/metrics.h"
namespace system_bt_osi {
-using clearcut::connectivity::A2DPSession;
-using clearcut::connectivity::BluetoothLog;
-using clearcut::connectivity::BluetoothSession;
-using clearcut::connectivity::BluetoothSession_ConnectionTechnologyType;
-using clearcut::connectivity::BluetoothSession_DisconnectReasonType;
-using clearcut::connectivity::DeviceInfo;
-using clearcut::connectivity::DeviceInfo_DeviceType;
-using clearcut::connectivity::PairEvent;
-using clearcut::connectivity::ScanEvent;
-using clearcut::connectivity::ScanEvent_ScanTechnologyType;
-using clearcut::connectivity::ScanEvent_ScanEventType;
-using clearcut::connectivity::WakeEvent;
-using clearcut::connectivity::WakeEvent_WakeEventType;
-
+using bluetooth::metrics::BluetoothMetricsProto::A2DPSession;
+using bluetooth::metrics::BluetoothMetricsProto::A2dpSourceCodec;
+using bluetooth::metrics::BluetoothMetricsProto::BluetoothLog;
+using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession;
+using bluetooth::metrics::BluetoothMetricsProto::
+ BluetoothSession_ConnectionTechnologyType;
+using bluetooth::metrics::BluetoothMetricsProto::
+ BluetoothSession_DisconnectReasonType;
+using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo;
+using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo_DeviceType;
+using bluetooth::metrics::BluetoothMetricsProto::PairEvent;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType;
+using bluetooth::metrics::BluetoothMetricsProto::WakeEvent;
+using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MIN;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MAX;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_ARRAYSIZE;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_IsValid;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
/*
* Get current OS boot time in millisecond
*/
@@ -133,6 +142,12 @@
buffer_underruns_count += metrics.buffer_underruns_count;
}
}
+ if (codec_index < 0) {
+ codec_index = metrics.codec_index;
+ }
+ if (!is_a2dp_offload) {
+ is_a2dp_offload = metrics.is_a2dp_offload;
+ }
}
bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const {
@@ -144,7 +159,9 @@
buffer_overruns_max_count == rhs.buffer_overruns_max_count &&
buffer_overruns_total == rhs.buffer_overruns_total &&
buffer_underruns_average == rhs.buffer_underruns_average &&
- buffer_underruns_count == rhs.buffer_underruns_count;
+ buffer_underruns_count == rhs.buffer_underruns_count &&
+ codec_index == rhs.codec_index &&
+ is_a2dp_offload == rhs.is_a2dp_offload;
}
static DeviceInfo_DeviceType get_device_type(device_type_t type) {
@@ -223,6 +240,23 @@
}
}
+static A2dpSourceCodec get_a2dp_source_codec(int64_t codec_index) {
+ switch (codec_index) {
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
+ return A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
+ return A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
+ return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
+ return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX_HD;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
+ return A2dpSourceCodec::A2DP_SOURCE_CODEC_LDAC;
+ default:
+ return A2dpSourceCodec::A2DP_SOURCE_CODEC_UNKNOWN;
+ }
+}
+
struct BluetoothMetricsLogger::impl {
impl(size_t max_bluetooth_session, size_t max_pair_event,
size_t max_wake_event, size_t max_scan_event)
@@ -232,6 +266,7 @@
wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)),
scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) {
bluetooth_log_ = BluetoothLog::default_instance().New();
+ headset_profile_connection_counts_.fill(0);
bluetooth_session_ = nullptr;
bluetooth_session_start_time_ms_ = 0;
a2dp_session_metrics_ = A2dpSessionMetrics();
@@ -239,6 +274,8 @@
/* Bluetooth log lock protected */
BluetoothLog* bluetooth_log_;
+ std::array<int, HeadsetProfileType_ARRAYSIZE>
+ headset_profile_connection_counts_;
std::recursive_mutex bluetooth_log_lock_;
/* End Bluetooth log lock protected */
/* Bluetooth session lock protected */
@@ -346,6 +383,7 @@
get_disconnect_reason_type(disconnect_reason));
pimpl_->bt_session_queue_->Enqueue(pimpl_->bluetooth_session_);
pimpl_->bluetooth_session_ = nullptr;
+ pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
{
std::lock_guard<std::recursive_mutex> log_lock(pimpl_->bluetooth_log_lock_);
pimpl_->bluetooth_log_->set_num_bluetooth_session(
@@ -394,31 +432,50 @@
pimpl_->a2dp_session_metrics_.buffer_underruns_average);
a2dp_session->set_buffer_underruns_count(
pimpl_->a2dp_session_metrics_.buffer_underruns_count);
+ a2dp_session->set_source_codec(
+ get_a2dp_source_codec(pimpl_->a2dp_session_metrics_.codec_index));
+ a2dp_session->set_is_a2dp_offload(
+ pimpl_->a2dp_session_metrics_.is_a2dp_offload);
}
-void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) {
+void BluetoothMetricsLogger::LogHeadsetProfileRfcConnection(
+ tBTA_SERVICE_ID service_id) {
+ std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
+ switch (service_id) {
+ case BTA_HSP_SERVICE_ID:
+ pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HSP]++;
+ break;
+ case BTA_HFP_SERVICE_ID:
+ pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HFP]++;
+ break;
+ default:
+ pimpl_->headset_profile_connection_counts_
+ [HeadsetProfileType::HEADSET_PROFILE_UNKNOWN]++;
+ break;
+ }
+ return;
+}
+
+void BluetoothMetricsLogger::WriteString(std::string* serialized) {
std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
LOG_DEBUG(LOG_TAG, "%s building metrics", __func__);
Build();
LOG_DEBUG(LOG_TAG, "%s serializing metrics", __func__);
if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) {
LOG_ERROR(LOG_TAG, "%s: error serializing metrics", __func__);
- return;
}
- if (clear) {
- pimpl_->bluetooth_log_->Clear();
- }
+ // Always clean up log objects
+ pimpl_->bluetooth_log_->Clear();
}
-void BluetoothMetricsLogger::WriteBase64String(std::string* serialized,
- bool clear) {
- this->WriteString(serialized, clear);
+void BluetoothMetricsLogger::WriteBase64String(std::string* serialized) {
+ this->WriteString(serialized);
base::Base64Encode(*serialized, serialized);
}
-void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) {
+void BluetoothMetricsLogger::WriteBase64(int fd) {
std::string protoBase64;
- this->WriteBase64String(&protoBase64, clear);
+ this->WriteBase64String(&protoBase64);
ssize_t ret;
OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size()));
if (ret == -1) {
@@ -475,6 +532,19 @@
bluetooth_log->mutable_wake_event()->AddAllocated(
pimpl_->wake_event_queue_->Dequeue());
}
+ for (size_t i = 0; i < HeadsetProfileType_ARRAYSIZE; ++i) {
+ int num_times_connected = pimpl_->headset_profile_connection_counts_[i];
+ if (HeadsetProfileType_IsValid(i) && num_times_connected > 0) {
+ HeadsetProfileConnectionStats* headset_profile_connection_stats =
+ bluetooth_log->add_headset_profile_connection_stats();
+ // Able to static_cast because HeadsetProfileType_IsValid(i) is true
+ headset_profile_connection_stats->set_headset_profile_type(
+ static_cast<HeadsetProfileType>(i));
+ headset_profile_connection_stats->set_num_times_connected(
+ num_times_connected);
+ }
+ }
+ pimpl_->headset_profile_connection_counts_.fill(0);
}
void BluetoothMetricsLogger::ResetSession() {
diff --git a/osi/src/metrics_linux.cc b/osi/src/metrics_linux.cc
index 3169131..162f4ca 100644
--- a/osi/src/metrics_linux.cc
+++ b/osi/src/metrics_linux.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/mutex.cc b/osi/src/mutex.cc
index fbbef40..0634f09 100644
--- a/osi/src/mutex.cc
+++ b/osi/src/mutex.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/osi.cc b/osi/src/osi.cc
index 0109a95..73d6c1a 100644
--- a/osi/src/osi.cc
+++ b/osi/src/osi.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/properties.cc b/osi/src/properties.cc
index 7392953..c20b39f 100644
--- a/osi/src/properties.cc
+++ b/osi/src/properties.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,14 @@
#include "osi/include/properties.h"
+#if !defined(OS_GENERIC)
+#undef PROPERTY_VALUE_MAX
+#include <cutils/properties.h>
+#if BUILD_SANITY_PROPERTY_VALUE_MAX != PROPERTY_VALUE_MAX
+#error "PROPERTY_VALUE_MAX from osi/include/properties.h != the Android value"
+#endif // GENERIC_PROPERTY_VALUE_MAX != PROPERTY_VALUE_MAX
+#endif // !defined(OS_GENERIC)
+
int osi_property_get(const char* key, char* value, const char* default_value) {
#if defined(OS_GENERIC)
/* For linux right now just return default value, if present */
@@ -52,3 +60,11 @@
return property_get_int32(key, default_value);
#endif // defined(OS_GENERIC)
}
+
+bool osi_property_get_bool(const char* key, bool default_value) {
+#if defined(OS_GENERIC)
+ return default_value;
+#else
+ return property_get_bool(key, default_value);
+#endif // defined(OS_GENERIC)
+}
\ No newline at end of file
diff --git a/osi/src/reactor.cc b/osi/src/reactor.cc
index 7f88df9..ce1251c 100644
--- a/osi/src/reactor.cc
+++ b/osi/src/reactor.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/ringbuffer.cc b/osi/src/ringbuffer.cc
index 5c7874d..4f7988a 100644
--- a/osi/src/ringbuffer.cc
+++ b/osi/src/ringbuffer.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google Inc.
+ * Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/semaphore.cc b/osi/src/semaphore.cc
index 097f32e..a943aa7 100644
--- a/osi/src/semaphore.cc
+++ b/osi/src/semaphore.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/socket.cc b/osi/src/socket.cc
index 201f976..3f9366f 100644
--- a/osi/src/socket.cc
+++ b/osi/src/socket.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/socket_utils/README b/osi/src/socket_utils/README
index 9ed210a..ac744fd 100644
--- a/osi/src/socket_utils/README
+++ b/osi/src/socket_utils/README
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/socket_utils/socket_local_client.cc b/osi/src/socket_utils/socket_local_client.cc
index 7338407..14f8b83 100644
--- a/osi/src/socket_utils/socket_local_client.cc
+++ b/osi/src/socket_utils/socket_local_client.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/socket_utils/socket_local_server.cc b/osi/src/socket_utils/socket_local_server.cc
index 9bfdf54..9710ab2 100644
--- a/osi/src/socket_utils/socket_local_server.cc
+++ b/osi/src/socket_utils/socket_local_server.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, The Android Open Source Project
+ * Copyright 2006, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/thread.cc b/osi/src/thread.cc
index 61b44f2..e164083 100644
--- a/osi/src/thread.cc
+++ b/osi/src/thread.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/time.cc b/osi/src/time.cc
index 0b7f3a1..1a47504 100644
--- a/osi/src/time.cc
+++ b/osi/src/time.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/src/wakelock.cc b/osi/src/wakelock.cc
index 565735f..46c462c 100644
--- a/osi/src/wakelock.cc
+++ b/osi/src/wakelock.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/AlarmTestHarness.cc b/osi/test/AlarmTestHarness.cc
index ee6aaa3..ad890c4 100644
--- a/osi/test/AlarmTestHarness.cc
+++ b/osi/test/AlarmTestHarness.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/AlarmTestHarness.h b/osi/test/AlarmTestHarness.h
index 39dd218..38be959 100644
--- a/osi/test/AlarmTestHarness.h
+++ b/osi/test/AlarmTestHarness.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/AllocationTestHarness.cc b/osi/test/AllocationTestHarness.cc
index 8df097f..a8582424 100644
--- a/osi/test/AllocationTestHarness.cc
+++ b/osi/test/AllocationTestHarness.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/AllocationTestHarness.h b/osi/test/AllocationTestHarness.h
index cbf29d8..0c6b98e 100644
--- a/osi/test/AllocationTestHarness.h
+++ b/osi/test/AllocationTestHarness.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/alarm_test.cc b/osi/test/alarm_test.cc
index 2eed78f..f7f473d 100644
--- a/osi/test/alarm_test.cc
+++ b/osi/test/alarm_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -347,7 +347,8 @@
for (int i = 0; i < 100; i++) alarm_free(alarms[i]);
- message_loop_->PostTask(FROM_HERE, run_loop_->QuitWhenIdleClosure());
+ message_loop_->task_runner()->PostTask(FROM_HERE,
+ run_loop_->QuitWhenIdleClosure());
thread_free(message_loop_thread_);
EXPECT_FALSE(WakeLockHeld());
}
diff --git a/osi/test/allocation_tracker_test.cc b/osi/test/allocation_tracker_test.cc
index cf979cb..6ce0e69 100644
--- a/osi/test/allocation_tracker_test.cc
+++ b/osi/test/allocation_tracker_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/allocator_test.cc b/osi/test/allocator_test.cc
index 9dc6302..1e09f71 100644
--- a/osi/test/allocator_test.cc
+++ b/osi/test/allocator_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/config_test.cc b/osi/test/config_test.cc
index 6712222..58ce818 100644
--- a/osi/test/config_test.cc
+++ b/osi/test/config_test.cc
@@ -44,6 +44,9 @@
[DID] \n\
[DID] \n\
version = 0x1436 \n\
+ \n\
+HiSyncId = 18446744073709551615 \n\
+HiSyncId2 = 15001900 \n\
";
class ConfigTest : public AllocationTestHarness {
@@ -57,146 +60,116 @@
};
TEST_F(ConfigTest, config_new_empty) {
- config_t* config = config_new_empty();
- EXPECT_TRUE(config != NULL);
- config_free(config);
+ std::unique_ptr<config_t> config = config_new_empty();
+ EXPECT_TRUE(config.get() != NULL);
}
TEST_F(ConfigTest, config_new_no_file) {
- config_t* config = config_new("/meow");
- EXPECT_TRUE(config == NULL);
- config_free(config);
+ std::unique_ptr<config_t> config = config_new("/meow");
+ EXPECT_TRUE(config.get() == NULL);
}
TEST_F(ConfigTest, config_new) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_TRUE(config != NULL);
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_TRUE(config.get() != NULL);
}
-TEST_F(ConfigTest, config_free_null) { config_free(NULL); }
-
TEST_F(ConfigTest, config_new_clone) {
- config_t* config = config_new(CONFIG_FILE);
- config_t* clone = config_new_clone(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ std::unique_ptr<config_t> clone = config_new_clone(*config);
- config_set_string(clone, CONFIG_DEFAULT_SECTION, "first_key", "not_value");
+ config_set_string(clone.get(), CONFIG_DEFAULT_SECTION, "first_key",
+ "not_value");
+ std::string one = std::string("one");
EXPECT_STRNE(
- config_get_string(config, CONFIG_DEFAULT_SECTION, "first_key", "one"),
- config_get_string(clone, CONFIG_DEFAULT_SECTION, "first_key", "one"));
-
- config_free(config);
- config_free(clone);
+ config_get_string(*config, CONFIG_DEFAULT_SECTION, "first_key", &one)
+ ->c_str(),
+ config_get_string(*clone, CONFIG_DEFAULT_SECTION, "first_key", &one)
+ ->c_str());
}
TEST_F(ConfigTest, config_has_section) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_TRUE(config_has_section(config, "DID"));
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_TRUE(config_has_section(*config, "DID"));
}
TEST_F(ConfigTest, config_has_key_in_default_section) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_TRUE(config_has_key(config, CONFIG_DEFAULT_SECTION, "first_key"));
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_TRUE(config_has_key(*config, CONFIG_DEFAULT_SECTION, "first_key"));
EXPECT_STREQ(
- config_get_string(config, CONFIG_DEFAULT_SECTION, "first_key", "meow"),
+ config_get_string(*config, CONFIG_DEFAULT_SECTION, "first_key", nullptr)
+ ->c_str(),
"value");
- config_free(config);
}
TEST_F(ConfigTest, config_has_keys) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_TRUE(config_has_key(config, "DID", "recordNumber"));
- EXPECT_TRUE(config_has_key(config, "DID", "primaryRecord"));
- EXPECT_TRUE(config_has_key(config, "DID", "productId"));
- EXPECT_TRUE(config_has_key(config, "DID", "version"));
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_TRUE(config_has_key(*config, "DID", "recordNumber"));
+ EXPECT_TRUE(config_has_key(*config, "DID", "primaryRecord"));
+ EXPECT_TRUE(config_has_key(*config, "DID", "productId"));
+ EXPECT_TRUE(config_has_key(*config, "DID", "version"));
}
TEST_F(ConfigTest, config_no_bad_keys) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_FALSE(config_has_key(config, "DID_BAD", "primaryRecord"));
- EXPECT_FALSE(config_has_key(config, "DID", "primaryRecord_BAD"));
- EXPECT_FALSE(config_has_key(config, CONFIG_DEFAULT_SECTION, "primaryRecord"));
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_FALSE(config_has_key(*config, "DID_BAD", "primaryRecord"));
+ EXPECT_FALSE(config_has_key(*config, "DID", "primaryRecord_BAD"));
+ EXPECT_FALSE(
+ config_has_key(*config, CONFIG_DEFAULT_SECTION, "primaryRecord"));
}
TEST_F(ConfigTest, config_get_int_version) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_EQ(config_get_int(config, "DID", "version", 0), 0x1436);
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_EQ(config_get_int(*config, "DID", "version", 0), 0x1436);
}
TEST_F(ConfigTest, config_get_int_default) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_EQ(config_get_int(config, "DID", "primaryRecord", 123), 123);
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_EQ(config_get_int(*config, "DID", "primaryRecord", 123), 123);
+}
+
+TEST_F(ConfigTest, config_get_uint64) {
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_EQ(config_get_uint64(*config, "DID", "HiSyncId", 0),
+ 0xFFFFFFFFFFFFFFFF);
+ EXPECT_EQ(config_get_uint64(*config, "DID", "HiSyncId2", 0),
+ uint64_t(15001900));
+}
+
+TEST_F(ConfigTest, config_get_uint64_default) {
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_EQ(config_get_uint64(*config, "DID", "primaryRecord", 123),
+ uint64_t(123));
}
TEST_F(ConfigTest, config_remove_section) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_TRUE(config_remove_section(config, "DID"));
- EXPECT_FALSE(config_has_section(config, "DID"));
- EXPECT_FALSE(config_has_key(config, "DID", "productId"));
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_TRUE(config_remove_section(config.get(), "DID"));
+ EXPECT_FALSE(config_has_section(*config, "DID"));
+ EXPECT_FALSE(config_has_key(*config, "DID", "productId"));
}
TEST_F(ConfigTest, config_remove_section_missing) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_FALSE(config_remove_section(config, "not a section"));
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_FALSE(config_remove_section(config.get(), "not a section"));
}
TEST_F(ConfigTest, config_remove_key) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_EQ(config_get_int(config, "DID", "productId", 999), 0x1200);
- EXPECT_TRUE(config_remove_key(config, "DID", "productId"));
- EXPECT_FALSE(config_has_key(config, "DID", "productId"));
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_EQ(config_get_int(*config, "DID", "productId", 999), 0x1200);
+ EXPECT_TRUE(config_remove_key(config.get(), "DID", "productId"));
+ EXPECT_FALSE(config_has_key(*config, "DID", "productId"));
}
TEST_F(ConfigTest, config_remove_key_missing) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_EQ(config_get_int(config, "DID", "productId", 999), 0x1200);
- EXPECT_TRUE(config_remove_key(config, "DID", "productId"));
- EXPECT_EQ(config_get_int(config, "DID", "productId", 999), 999);
- config_free(config);
-}
-
-TEST_F(ConfigTest, config_section_begin) {
- config_t* config = config_new(CONFIG_FILE);
- const config_section_node_t* section = config_section_begin(config);
- EXPECT_TRUE(section != NULL);
- const char* section_name = config_section_name(section);
- EXPECT_TRUE(section != NULL);
- EXPECT_TRUE(!strcmp(section_name, CONFIG_DEFAULT_SECTION));
- config_free(config);
-}
-
-TEST_F(ConfigTest, config_section_next) {
- config_t* config = config_new(CONFIG_FILE);
- const config_section_node_t* section = config_section_begin(config);
- EXPECT_TRUE(section != NULL);
- section = config_section_next(section);
- EXPECT_TRUE(section != NULL);
- const char* section_name = config_section_name(section);
- EXPECT_TRUE(section != NULL);
- EXPECT_TRUE(!strcmp(section_name, "DID"));
- config_free(config);
-}
-
-TEST_F(ConfigTest, config_section_end) {
- config_t* config = config_new(CONFIG_FILE);
- const config_section_node_t* section = config_section_begin(config);
- section = config_section_next(section);
- section = config_section_next(section);
- EXPECT_EQ(section, config_section_end(config));
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_EQ(config_get_int(*config, "DID", "productId", 999), 0x1200);
+ EXPECT_TRUE(config_remove_key(config.get(), "DID", "productId"));
+ EXPECT_EQ(config_get_int(*config, "DID", "productId", 999), 999);
}
TEST_F(ConfigTest, config_save_basic) {
- config_t* config = config_new(CONFIG_FILE);
- EXPECT_TRUE(config_save(config, CONFIG_FILE));
- config_free(config);
+ std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
+ EXPECT_TRUE(config_save(*config, CONFIG_FILE));
}
diff --git a/osi/test/future_test.cc b/osi/test/future_test.cc
index fe5e7fd..26d319a 100644
--- a/osi/test/future_test.cc
+++ b/osi/test/future_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/hash_map_utils_test.cc b/osi/test/hash_map_utils_test.cc
index 0e483e5..1e312d4 100644
--- a/osi/test/hash_map_utils_test.cc
+++ b/osi/test/hash_map_utils_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/leaky_bonded_queue_test.cc b/osi/test/leaky_bonded_queue_test.cc
index c538101..116676b 100644
--- a/osi/test/leaky_bonded_queue_test.cc
+++ b/osi/test/leaky_bonded_queue_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,10 +26,10 @@
using system_bt_osi::LeakyBondedQueue;
-#define ITEM_EQ(a, b) \
- do { \
- EXPECT_EQ(a, b); \
- EXPECT_EQ(a->index, b->index); \
+#define ITEM_EQ(a, b) \
+ do { \
+ EXPECT_EQ(a, b); \
+ EXPECT_EQ((a)->index, (b)->index); \
} while (0)
class Item {
diff --git a/osi/test/metrics_test.cc b/osi/test/metrics_test.cc
index a8de2fc..bfb548f 100644
--- a/osi/test/metrics_test.cc
+++ b/osi/test/metrics_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,29 +25,35 @@
#include <gtest/gtest.h>
#include <base/logging.h>
+#include <include/hardware/bt_av.h>
+#include "bluetooth/metrics/bluetooth.pb.h"
#include "osi/include/metrics.h"
#include "osi/include/time.h"
-#include "src/protos/bluetooth.pb.h"
#define BTM_COD_MAJOR_AUDIO_TEST 0x04
namespace testing {
-using clearcut::connectivity::A2DPSession;
-using clearcut::connectivity::BluetoothLog;
-using clearcut::connectivity::BluetoothSession;
-using clearcut::connectivity::BluetoothSession_ConnectionTechnologyType;
-using clearcut::connectivity::BluetoothSession_DisconnectReasonType;
-using clearcut::connectivity::DeviceInfo;
-using clearcut::connectivity::DeviceInfo_DeviceType;
-using clearcut::connectivity::PairEvent;
-using clearcut::connectivity::RFCommSession;
-using clearcut::connectivity::ScanEvent;
-using clearcut::connectivity::ScanEvent_ScanTechnologyType;
-using clearcut::connectivity::ScanEvent_ScanEventType;
-using clearcut::connectivity::WakeEvent;
-using clearcut::connectivity::WakeEvent_WakeEventType;
+using bluetooth::metrics::BluetoothMetricsProto::A2DPSession;
+using bluetooth::metrics::BluetoothMetricsProto::A2dpSourceCodec;
+using bluetooth::metrics::BluetoothMetricsProto::BluetoothLog;
+using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession;
+using bluetooth::metrics::BluetoothMetricsProto::
+ BluetoothSession_ConnectionTechnologyType;
+using bluetooth::metrics::BluetoothMetricsProto::
+ BluetoothSession_DisconnectReasonType;
+using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo;
+using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo_DeviceType;
+using bluetooth::metrics::BluetoothMetricsProto::PairEvent;
+using bluetooth::metrics::BluetoothMetricsProto::RFCommSession;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType;
+using bluetooth::metrics::BluetoothMetricsProto::WakeEvent;
+using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
using system_bt_osi::BluetoothMetricsLogger;
using system_bt_osi::A2dpSessionMetrics;
@@ -107,7 +113,8 @@
return event;
}
-A2DPSession* MakeA2DPSession(const A2dpSessionMetrics& metrics) {
+A2DPSession* MakeA2DPSession(const A2dpSessionMetrics& metrics,
+ A2dpSourceCodec source_codec) {
A2DPSession* session = new A2DPSession();
session->set_media_timer_min_millis(metrics.media_timer_min_ms);
session->set_media_timer_max_millis(metrics.media_timer_max_ms);
@@ -117,6 +124,8 @@
session->set_buffer_underruns_average(metrics.buffer_underruns_average);
session->set_buffer_underruns_count(metrics.buffer_underruns_count);
session->set_audio_duration_millis(metrics.audio_duration_ms);
+ session->set_source_codec(source_codec);
+ session->set_is_a2dp_offload(metrics.is_a2dp_offload);
return session;
}
@@ -170,19 +179,21 @@
}
}
-#define COMPARE_A2DP_METRICS(a, b) \
- do { \
- EXPECT_EQ(a.audio_duration_ms, b.audio_duration_ms); \
- EXPECT_EQ(a.media_timer_min_ms, b.media_timer_min_ms); \
- EXPECT_EQ(a.media_timer_max_ms, b.media_timer_max_ms); \
- EXPECT_EQ(a.media_timer_avg_ms, b.media_timer_avg_ms); \
- EXPECT_EQ(a.total_scheduling_count, b.total_scheduling_count); \
- EXPECT_EQ(a.buffer_overruns_max_count, b.buffer_overruns_max_count); \
- EXPECT_EQ(a.buffer_overruns_total, b.buffer_overruns_total); \
- EXPECT_THAT(a.buffer_underruns_average, \
- FloatNear(b.buffer_underruns_average, 0.01)); \
- a.buffer_underruns_average = b.buffer_underruns_average; \
- EXPECT_EQ(a.buffer_underruns_count, b.buffer_underruns_count); \
+#define COMPARE_A2DP_METRICS(a, b) \
+ do { \
+ EXPECT_EQ((a).audio_duration_ms, (b).audio_duration_ms); \
+ EXPECT_EQ((a).media_timer_min_ms, (b).media_timer_min_ms); \
+ EXPECT_EQ((a).media_timer_max_ms, (b).media_timer_max_ms); \
+ EXPECT_EQ((a).media_timer_avg_ms, (b).media_timer_avg_ms); \
+ EXPECT_EQ((a).total_scheduling_count, (b).total_scheduling_count); \
+ EXPECT_EQ((a).buffer_overruns_max_count, (b).buffer_overruns_max_count); \
+ EXPECT_EQ((a).buffer_overruns_total, (b).buffer_overruns_total); \
+ EXPECT_THAT((a).buffer_underruns_average, \
+ FloatNear((b).buffer_underruns_average, 0.01)); \
+ (a).buffer_underruns_average = (b).buffer_underruns_average; \
+ EXPECT_EQ((a).buffer_underruns_count, (b).buffer_underruns_count); \
+ EXPECT_EQ((a).codec_index, (b).codec_index); \
+ EXPECT_EQ((a).is_a2dp_offload, (b).is_a2dp_offload); \
} while (0)
/*
@@ -216,6 +227,12 @@
metrics2.buffer_underruns_count = 2400;
metrics_sum.buffer_underruns_average = 113.33333333;
metrics_sum.buffer_underruns_count = 3600;
+ metrics1.codec_index = -1;
+ metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
+ metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
+ metrics1.is_a2dp_offload = false;
+ metrics2.is_a2dp_offload = true;
+ metrics_sum.is_a2dp_offload = true;
metrics1.Update(metrics2);
COMPARE_A2DP_METRICS(metrics1, metrics_sum);
EXPECT_TRUE(metrics1 == metrics_sum);
@@ -242,6 +259,10 @@
metrics2.buffer_underruns_count = 2400;
metrics_sum.buffer_underruns_average = 130;
metrics_sum.buffer_underruns_count = 2400;
+ metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_APTX;
+ metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_APTX;
+ metrics2.is_a2dp_offload = true;
+ metrics_sum.is_a2dp_offload = true;
metrics1.Update(metrics2);
COMPARE_A2DP_METRICS(metrics1, metrics_sum);
EXPECT_TRUE(metrics1 == metrics_sum);
@@ -268,6 +289,10 @@
metrics2.buffer_underruns_count = 2400;
metrics_sum.buffer_underruns_average = 130;
metrics_sum.buffer_underruns_count = 2400;
+ metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD;
+ metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD;
+ metrics2.is_a2dp_offload = true;
+ metrics_sum.is_a2dp_offload = true;
metrics2.Update(metrics1);
COMPARE_A2DP_METRICS(metrics2, metrics_sum);
EXPECT_TRUE(metrics2 == metrics_sum);
@@ -406,7 +431,7 @@
BluetoothMetricsLogger::GetInstance()->LogPairEvent(
35, 12345, 42, system_bt_osi::DEVICE_TYPE_BREDR);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -418,7 +443,7 @@
BluetoothMetricsLogger::GetInstance()->LogWakeEvent(
system_bt_osi::WAKE_EVENT_ACQUIRED, "TEST_REQ", "TEST_NAME", 12345);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -435,7 +460,7 @@
"TEST_REQ", "TEST_NAME", i);
}
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -449,7 +474,7 @@
BluetoothMetricsLogger::GetInstance()->LogScanEvent(
false, "TEST_INITIATOR", system_bt_osi::SCAN_TECH_TYPE_BREDR, 42, 123456);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -467,7 +492,7 @@
BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
system_bt_osi::DISCONNECT_REASON_UNKNOWN, 133456);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -484,7 +509,7 @@
system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_LE, time_get_os_boottime_ms());
sleep_ms(1000);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -511,7 +536,7 @@
system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_LE, 0);
sleep_ms(2000);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -556,10 +581,17 @@
metrics2.buffer_underruns_count = 2400;
metrics_sum.buffer_underruns_average = 113.33333333;
metrics_sum.buffer_underruns_count = 3600;
+ metrics1.codec_index = -1;
+ metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
+ metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
+ metrics1.is_a2dp_offload = false;
+ metrics2.is_a2dp_offload = true;
+ metrics_sum.is_a2dp_offload = true;
DeviceInfo* info = MakeDeviceInfo(
BTM_COD_MAJOR_AUDIO_TEST,
DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
- A2DPSession* session = MakeA2DPSession(metrics_sum);
+ A2DPSession* session =
+ MakeA2DPSession(metrics_sum, A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC);
bt_sessions_.push_back(MakeBluetoothSession(
10,
BluetoothSession_ConnectionTechnologyType::
@@ -577,7 +609,7 @@
BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
system_bt_osi::DISCONNECT_REASON_UNKNOWN, 133456);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -614,10 +646,13 @@
metrics1.buffer_underruns_count = 1200;
metrics2.buffer_underruns_average = 130;
metrics2.buffer_underruns_count = 2400;
+ metrics1.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC;
+ metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
DeviceInfo* info = MakeDeviceInfo(
BTM_COD_MAJOR_AUDIO_TEST,
DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
- A2DPSession* session = MakeA2DPSession(metrics1);
+ A2DPSession* session =
+ MakeA2DPSession(metrics1, A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC);
bt_sessions_.push_back(MakeBluetoothSession(
1,
BluetoothSession_ConnectionTechnologyType::
@@ -633,13 +668,13 @@
BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1);
sleep_ms(1000);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
ClearLog();
info = MakeDeviceInfo(
BTM_COD_MAJOR_AUDIO_TEST,
DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
- session = MakeA2DPSession(metrics2);
+ session = MakeA2DPSession(metrics2, A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC);
bt_sessions_.push_back(MakeBluetoothSession(
1,
BluetoothSession_ConnectionTechnologyType::
@@ -653,7 +688,87 @@
BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
msg_str.clear();
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
+ EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+/*
+ * Test Case: A2DPSessionTwoUpdatesSeparatedbyEndTest
+ *
+ * 1. Create Instance
+ * 2. LogBluetoothSessionStart
+ * 3. LogA2dpSession
+ * 4. LogBluetoothSessionEnd
+ * 5. LogBluetoothSessionStart
+ * 6. LogA2dpSession
+ * 7. LogBluetoothSessionEnd
+ * 8. WriteString
+ *
+ */
+TEST_F(BluetoothMetricsLoggerTest, A2DPSessionTwoUpdatesSeparatedbyEndTest) {
+ /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */
+ A2dpSessionMetrics metrics1;
+ metrics1.audio_duration_ms = 10;
+ metrics1.media_timer_min_ms = 10;
+ metrics1.media_timer_max_ms = 100;
+ metrics1.media_timer_avg_ms = 50;
+ metrics1.total_scheduling_count = 50;
+ metrics1.buffer_overruns_max_count = 70;
+ metrics1.buffer_underruns_average = 80;
+ metrics1.buffer_underruns_count = 1200;
+ metrics1.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC;
+ DeviceInfo* info = MakeDeviceInfo(
+ BTM_COD_MAJOR_AUDIO_TEST,
+ DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
+ A2DPSession* session =
+ MakeA2DPSession(metrics1, A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC);
+ bt_sessions_.push_back(MakeBluetoothSession(
+ 1,
+ BluetoothSession_ConnectionTechnologyType::
+ BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR,
+ BluetoothSession_DisconnectReasonType::
+ BluetoothSession_DisconnectReasonType_UNKNOWN,
+ info, nullptr, session));
+ UpdateLog();
+ BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+ system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+ BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo(
+ BTM_COD_MAJOR_AUDIO_TEST, system_bt_osi::DEVICE_TYPE_BREDR);
+ BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1);
+ sleep_ms(1000);
+ BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+ system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+ std::string msg_str;
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
+ EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+ ClearLog();
+ A2dpSessionMetrics metrics2;
+ metrics2.audio_duration_ms = 25;
+ metrics2.media_timer_min_ms = 25;
+ metrics2.media_timer_max_ms = 200;
+ metrics2.media_timer_avg_ms = 100;
+ metrics2.total_scheduling_count = 50;
+ metrics2.buffer_overruns_max_count = 80;
+ metrics2.buffer_underruns_average = 130;
+ metrics2.buffer_underruns_count = 2400;
+ metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
+ session = MakeA2DPSession(metrics2, A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC);
+ bt_sessions_.push_back(MakeBluetoothSession(
+ 1,
+ BluetoothSession_ConnectionTechnologyType::
+ BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR,
+ BluetoothSession_DisconnectReasonType::
+ BluetoothSession_DisconnectReasonType_UNKNOWN,
+ nullptr, nullptr, session));
+ UpdateLog();
+ BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+ system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+ sleep_ms(1000);
+ BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
+ BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+ system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+ msg_str.clear();
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -696,10 +811,14 @@
metrics2.buffer_underruns_count = 2400;
metrics_sum.buffer_underruns_average = 113.33333333;
metrics_sum.buffer_underruns_count = 3600;
+ metrics1.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC;
+ metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
+ metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC;
DeviceInfo* info = MakeDeviceInfo(
BTM_COD_MAJOR_AUDIO_TEST,
DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
- A2DPSession* session = MakeA2DPSession(metrics_sum);
+ A2DPSession* session =
+ MakeA2DPSession(metrics_sum, A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC);
bt_sessions_.push_back(MakeBluetoothSession(
1,
BluetoothSession_ConnectionTechnologyType::
@@ -712,7 +831,7 @@
BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
sleep_ms(1000);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
@@ -758,6 +877,9 @@
metrics2.buffer_underruns_count = 2400;
metrics_sum.buffer_underruns_average = 113.33333333;
metrics_sum.buffer_underruns_count = 3600;
+ metrics1.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC;
+ metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
+ metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC;
DeviceInfo* info = MakeDeviceInfo(
BTM_COD_MAJOR_AUDIO_TEST,
DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
@@ -775,13 +897,14 @@
BTM_COD_MAJOR_AUDIO_TEST, system_bt_osi::DEVICE_TYPE_BREDR);
sleep_ms(1000);
std::string msg_str;
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
ClearLog();
info = MakeDeviceInfo(
BTM_COD_MAJOR_AUDIO_TEST,
DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
- A2DPSession* session = MakeA2DPSession(metrics_sum);
+ A2DPSession* session =
+ MakeA2DPSession(metrics_sum, A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC);
bt_sessions_.push_back(MakeBluetoothSession(
1,
BluetoothSession_ConnectionTechnologyType::
@@ -796,7 +919,94 @@
BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
msg_str.clear();
- BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
EXPECT_THAT(msg_str, StrEq(bt_log_str_));
}
+
+TEST_F(BluetoothMetricsLoggerTest, LogHeadsetProfileRfcConnectionTest) {
+ BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(
+ BTA_HSP_SERVICE_ID);
+ BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(
+ BTA_HFP_SERVICE_ID);
+ BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(
+ BTA_HFP_SERVICE_ID);
+ std::string msg_str;
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
+ BluetoothLog* metrics = BluetoothLog::default_instance().New();
+ metrics->ParseFromString(msg_str);
+ EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 2);
+ bool hfp_correct = false;
+ bool hsp_correct = false;
+ for (const HeadsetProfileConnectionStats& headset_profile_connection_stats :
+ metrics->headset_profile_connection_stats()) {
+ switch (headset_profile_connection_stats.headset_profile_type()) {
+ case HeadsetProfileType::HFP:
+ EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 2);
+ hfp_correct = true;
+ break;
+ case HeadsetProfileType::HSP:
+ EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 1);
+ hsp_correct = true;
+ break;
+ default:
+ FAIL();
+ }
+ }
+ EXPECT_TRUE(hfp_correct);
+ EXPECT_TRUE(hsp_correct);
+ metrics->clear_headset_profile_connection_stats();
+ EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 0);
+ msg_str.clear();
+ // Verify that dump after clean up result in an empty list
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
+ metrics->ParseFromString(msg_str);
+ EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 0);
+ delete metrics;
+}
+
+TEST_F(BluetoothMetricsLoggerTest, LogHeadsetProfileRfcConnectionErrorTest) {
+ BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(
+ BTA_HSP_SERVICE_ID);
+ BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(
+ BTA_HFP_SERVICE_ID);
+ BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(
+ BTA_BIP_SERVICE_ID);
+ BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(
+ BTA_HSP_SERVICE_ID);
+ std::string msg_str;
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
+ BluetoothLog* metrics = BluetoothLog::default_instance().New();
+ metrics->ParseFromString(msg_str);
+ EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 3);
+ bool hfp_correct = false;
+ bool hsp_correct = false;
+ bool unknown_correct = false;
+ for (const HeadsetProfileConnectionStats& headset_profile_connection_stats :
+ metrics->headset_profile_connection_stats()) {
+ switch (headset_profile_connection_stats.headset_profile_type()) {
+ case HeadsetProfileType::HFP:
+ EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 1);
+ hfp_correct = true;
+ break;
+ case HeadsetProfileType::HSP:
+ EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 2);
+ hsp_correct = true;
+ break;
+ default:
+ EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 1);
+ unknown_correct = true;
+ break;
+ }
+ }
+ EXPECT_TRUE(hfp_correct);
+ EXPECT_TRUE(hsp_correct);
+ EXPECT_TRUE(unknown_correct);
+ metrics->clear_headset_profile_connection_stats();
+ EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 0);
+ // Verify that dump after clean up result in an empty list
+ BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
+ metrics->ParseFromString(msg_str);
+ EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 0);
+ delete metrics;
+}
}
diff --git a/osi/test/properties_test.cc b/osi/test/properties_test.cc
index f8c503a..499f6f3 100644
--- a/osi/test/properties_test.cc
+++ b/osi/test/properties_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,4 +53,4 @@
int32_t received = osi_property_get_int32("very.useful.set.test", 84);
ASSERT_EQ(received, 42);
-}
+}
\ No newline at end of file
diff --git a/osi/test/test_stubs.h b/osi/test/test_stubs.h
index cbaa967..043fd37 100644
--- a/osi/test/test_stubs.h
+++ b/osi/test/test_stubs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/time_test.cc b/osi/test/time_test.cc
index 6b35c17..f14842d 100644
--- a/osi/test/time_test.cc
+++ b/osi/test/time_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/osi/test/wakelock_test.cc b/osi/test/wakelock_test.cc
index d1ff0a2..0e027be 100644
--- a/osi/test/wakelock_test.cc
+++ b/osi/test/wakelock_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packet/Android.bp b/packet/Android.bp
new file mode 100644
index 0000000..8338c2d
--- /dev/null
+++ b/packet/Android.bp
@@ -0,0 +1,50 @@
+cc_library_static {
+ name: "lib-bt-packets",
+ defaults: ["libchrome_support_defaults"],
+ host_supported: true,
+ export_include_dirs: [
+ "./include",
+ "./",
+ ],
+ whole_static_libs: [
+ "lib-bt-packets-base",
+ "lib-bt-packets-avrcp",
+ ],
+}
+
+cc_test {
+ name: "net_test_btpackets",
+ defaults: ["fluoride_defaults"],
+ host_supported: true,
+ local_include_dirs: ["tests"],
+ srcs: [
+ "tests/avrcp/avrcp_browse_packet_test.cc",
+ "tests/avrcp/avrcp_packet_test.cc",
+ "tests/avrcp/avrcp_reject_packet_test.cc",
+ "tests/avrcp/change_path_packet_test.cc",
+ "tests/avrcp/general_reject_packet_test.cc",
+ "tests/avrcp/get_capabilities_packet_test.cc",
+ "tests/avrcp/get_element_attributes_packet_test.cc",
+ "tests/avrcp/get_folder_items_packet_test.cc",
+ "tests/avrcp/get_item_attributes_packet_test.cc",
+ "tests/avrcp/get_play_status_packet_test.cc",
+ "tests/avrcp/get_total_number_of_items_packet_test.cc",
+ "tests/avrcp/pass_through_packet_test.cc",
+ "tests/avrcp/play_item_packet_test.cc",
+ "tests/avrcp/register_notification_packet_test.cc",
+ "tests/avrcp/set_absolute_volume_packet_test.cc",
+ "tests/avrcp/set_addressed_player_packet_test.cc",
+ "tests/avrcp/set_browsed_player_packet_test.cc",
+ "tests/avrcp/vendor_packet_test.cc",
+ "tests/base/iterator_test.cc",
+ "tests/base/packet_builder_test.cc",
+ "tests/base/packet_test.cc",
+ ],
+ static_libs: [
+ "libgmock",
+ "lib-bt-packets",
+ ],
+ cflags: [
+ "-DBUILDCFG",
+ ],
+}
diff --git a/packet/avrcp/Android.bp b/packet/avrcp/Android.bp
new file mode 100644
index 0000000..80e93e8
--- /dev/null
+++ b/packet/avrcp/Android.bp
@@ -0,0 +1,31 @@
+cc_library_static {
+ name: "lib-bt-packets-avrcp",
+ defaults: ["libchrome_support_defaults"],
+ header_libs: ["avrcp_headers"],
+ export_header_lib_headers: ["avrcp_headers"],
+ export_include_dirs: ["."],
+ host_supported: true,
+ srcs: [
+ "avrcp_browse_packet.cc",
+ "avrcp_packet.cc",
+ "avrcp_reject_packet.cc",
+ "capabilities_packet.cc",
+ "change_path.cc",
+ "general_reject_packet.cc",
+ "get_element_attributes_packet.cc",
+ "get_folder_items.cc",
+ "get_item_attributes.cc",
+ "get_play_status_packet.cc",
+ "get_total_number_of_items.cc",
+ "pass_through_packet.cc",
+ "play_item.cc",
+ "register_notification_packet.cc",
+ "set_absolute_volume.cc",
+ "set_addressed_player.cc",
+ "set_browsed_player.cc",
+ "vendor_packet.cc",
+ ],
+ static_libs: [
+ "lib-bt-packets-base",
+ ],
+}
diff --git a/packet/avrcp/avrcp_browse_packet.cc b/packet/avrcp/avrcp_browse_packet.cc
new file mode 100644
index 0000000..f4a7691
--- /dev/null
+++ b/packet/avrcp/avrcp_browse_packet.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "avrcp_browse_packet.h"
+
+#include <base/logging.h>
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<BrowsePacketBuilder> BrowsePacketBuilder::MakeBuilder(
+ BrowsePdu pdu, std::unique_ptr<::bluetooth::PacketBuilder> payload) {
+ std::unique_ptr<BrowsePacketBuilder> builder =
+ std::unique_ptr<BrowsePacketBuilder>(new BrowsePacketBuilder(pdu));
+
+ builder->payload_ = std::move(payload);
+
+ return builder;
+}
+
+size_t BrowsePacketBuilder::size() const {
+ return BrowsePacket::kMinSize() + payload_->size();
+}
+
+bool BrowsePacketBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ PushHeader(pkt, payload_->size());
+
+ return payload_->Serialize(pkt);
+}
+
+void BrowsePacketBuilder::PushHeader(
+ const std::shared_ptr<::bluetooth::Packet>& pkt, uint16_t length) {
+ AddPayloadOctets1(pkt, (uint8_t)pdu_);
+ AddPayloadOctets2(pkt, base::ByteSwap(length));
+}
+
+std::shared_ptr<BrowsePacket> BrowsePacket::Parse(
+ std::shared_ptr<::bluetooth::Packet> pkt) {
+ return std::shared_ptr<BrowsePacket>(new BrowsePacket(pkt));
+}
+
+BrowsePdu BrowsePacket::GetPdu() const {
+ return static_cast<BrowsePdu>(*begin());
+}
+
+uint16_t BrowsePacket::GetLength() const {
+ auto it = begin() + static_cast<size_t>(1);
+ return base::ByteSwap(it.extract<uint16_t>());
+}
+
+bool BrowsePacket::IsValid() const {
+ if (size() < kMinSize()) return false;
+ return size() == GetLength() + kMinSize();
+}
+
+std::string BrowsePacket::ToString() const {
+ std::stringstream ss;
+ ss << "AvrcpBrowsePacket: " << std::endl;
+ ss << " â”” PDU = " << GetPdu() << std::endl;
+ ss << " â”” Length = " << GetLength() << std::endl;
+ ss << " â”” Payload =";
+ for (auto it = begin() + static_cast<size_t>(3); it != end(); it++) {
+ ss << " " << loghex(*it);
+ }
+ ss << std::endl;
+
+ return ss.str();
+}
+
+std::pair<size_t, size_t> BrowsePacket::GetPayloadIndecies() const {
+ return std::pair<size_t, size_t>(packet_start_index_ + 3, packet_end_index_);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/avrcp_browse_packet.h b/packet/avrcp/avrcp_browse_packet.h
new file mode 100644
index 0000000..d62f0e2
--- /dev/null
+++ b/packet/avrcp/avrcp_browse_packet.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <base/logging.h>
+#include <base/macros.h>
+#include <iostream>
+
+#include "avrcp_common.h"
+#include "avrcp_logging_helper.h"
+#include "iterator.h"
+#include "packet.h"
+#include "packet_builder.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class BrowsePacketBuilder : public ::bluetooth::PacketBuilder {
+ public:
+ virtual ~BrowsePacketBuilder() = default;
+
+ static std::unique_ptr<BrowsePacketBuilder> MakeBuilder(
+ BrowsePdu pdu, std::unique_ptr<::bluetooth::PacketBuilder> payload);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ BrowsePdu pdu_;
+ std::unique_ptr<::bluetooth::PacketBuilder> payload_;
+
+ void PushHeader(const std::shared_ptr<::bluetooth::Packet>& pkt,
+ uint16_t length);
+
+ BrowsePacketBuilder(BrowsePdu pdu) : pdu_(pdu){};
+};
+
+class BrowsePacket : public ::bluetooth::Packet {
+ public:
+ virtual ~BrowsePacket() = default;
+
+ static std::shared_ptr<BrowsePacket> Parse(
+ std::shared_ptr<::bluetooth::Packet> pkt);
+
+ /**
+ * Avrcp Browse Packet Layout
+ * uint8_t pdu_;
+ * uint16_t length_;
+ * uint8_t[] payload_;
+ */
+ static constexpr size_t kMinSize() { return 3; }
+
+ BrowsePdu GetPdu() const;
+ uint16_t GetLength() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using ::bluetooth::Packet::Packet;
+
+ private:
+ virtual std::pair<size_t, size_t> GetPayloadIndecies() const;
+ DISALLOW_COPY_AND_ASSIGN(BrowsePacket);
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/avrcp_packet.cc b/packet/avrcp/avrcp_packet.cc
new file mode 100644
index 0000000..635759a
--- /dev/null
+++ b/packet/avrcp/avrcp_packet.cc
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/logging.h>
+#include <iomanip>
+#include <sstream>
+#include <type_traits>
+
+#include "avrcp_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<PacketBuilder> PacketBuilder::MakeBuilder(
+ CType type, uint8_t subunit_type, uint8_t subunit_id, Opcode opcode,
+ std::unique_ptr<::bluetooth::PacketBuilder> payload) {
+ std::unique_ptr<PacketBuilder> builder = std::unique_ptr<PacketBuilder>(
+ new PacketBuilder(type, subunit_type, subunit_id, opcode));
+
+ builder->payload_ = std::move(payload);
+
+ return builder;
+}
+
+size_t PacketBuilder::size() const {
+ // The size of the header for an Packet is 3
+ return payload_->size() + Packet::kMinSize();
+}
+
+bool PacketBuilder::Serialize(const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ // Push the header for the packet
+ PushHeader(pkt);
+
+ // Push the payload for the packet
+ return payload_->Serialize(pkt);
+}
+
+void PacketBuilder::PushHeader(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(c_type_));
+ AddPayloadOctets1(pkt, (subunit_type_ << 3) | subunit_id_);
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(opcode_));
+}
+
+bool PacketBuilder::PushCompanyId(
+ const std::shared_ptr<::bluetooth::Packet>& pkt, uint32_t company_id) {
+ company_id = base::ByteSwap(company_id);
+ for (int i = 0; i < 3; i++) {
+ company_id >>= 8;
+ AddPayloadOctets1(pkt, company_id & 0xFF);
+ }
+
+ return true;
+}
+
+std::shared_ptr<Packet> Packet::Parse(
+ std::shared_ptr<::bluetooth::Packet> pkt) {
+ return std::shared_ptr<Packet>(new Packet(pkt));
+}
+
+CType Packet::GetCType() const {
+ auto value = *begin() & 0x0F;
+ return static_cast<CType>(value);
+}
+
+uint8_t Packet::GetSubunitType() const {
+ return *(begin() + static_cast<size_t>(1)) >> 3;
+}
+
+uint8_t Packet::GetSubunitId() const {
+ return *(begin() + static_cast<size_t>(1)) & 0b00000111;
+}
+
+Opcode Packet::GetOpcode() const {
+ auto value = *(begin() + static_cast<size_t>(2));
+ return static_cast<Opcode>(value);
+}
+
+bool Packet::IsValid() const { return size() >= kMinSize(); }
+
+std::string Packet::ToString() const {
+ std::stringstream ss;
+ ss << "avrcp::Packet: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Payload =";
+ for (auto it = begin() + static_cast<size_t>(3); it != end(); it++) {
+ ss << " " << loghex(*it);
+ }
+ ss << std::endl;
+
+ return ss.str();
+}
+
+std::pair<size_t, size_t> Packet::GetPayloadIndecies() const {
+ return std::pair<size_t, size_t>(packet_start_index_ + 3, packet_end_index_);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/avrcp_packet.h b/packet/avrcp/avrcp_packet.h
new file mode 100644
index 0000000..1e56186
--- /dev/null
+++ b/packet/avrcp/avrcp_packet.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <base/logging.h>
+#include <base/macros.h>
+#include <iostream>
+
+#include "avrcp_common.h"
+#include "avrcp_logging_helper.h"
+#include "iterator.h"
+#include "packet.h"
+#include "packet_builder.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class PacketBuilder : public ::bluetooth::PacketBuilder {
+ public:
+ virtual ~PacketBuilder() = default;
+
+ static std::unique_ptr<PacketBuilder> MakeBuilder(
+ CType cType, uint8_t subunit_type, uint8_t subunit_id, Opcode opcode,
+ std::unique_ptr<::bluetooth::PacketBuilder> packet);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ CType c_type_;
+ uint8_t subunit_type_ : 5;
+ uint8_t subunit_id_ : 3;
+ Opcode opcode_;
+ std::unique_ptr<::bluetooth::PacketBuilder> payload_;
+
+ void PushHeader(const std::shared_ptr<::bluetooth::Packet>& pkt);
+ bool PushCompanyId(const std::shared_ptr<::bluetooth::Packet>& pkt,
+ uint32_t company_id);
+
+ PacketBuilder(CType type, uint8_t subunit_type, uint8_t subunit_id,
+ Opcode opcode)
+ : c_type_(type),
+ subunit_type_(subunit_type),
+ subunit_id_(subunit_id),
+ opcode_(opcode){};
+};
+
+class Packet : public ::bluetooth::Packet {
+ public:
+ virtual ~Packet() = default;
+
+ // TODO (apanicke): Right now we can use this to build an AvrcpPacket from
+ // another packet type. In the future, we can remove this in favor of
+ // getting an AVRCP Packet directly from an AVCTP Packet
+ static std::shared_ptr<Packet> Parse(
+ std::shared_ptr<::bluetooth::Packet> pkt);
+
+ /**
+ * Avrcp Packet Layout
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * uint8_t[] payload_;
+ */
+ static constexpr size_t kMinSize() { return 3; };
+
+ // Getter Functions
+ CType GetCType() const;
+ uint8_t GetSubunitType() const;
+ uint8_t GetSubunitId() const;
+ Opcode GetOpcode() const;
+
+ // Overloaded Functions
+ virtual bool IsValid() const;
+ virtual std::string ToString() const override;
+
+ protected:
+ using ::bluetooth::Packet::Packet;
+
+ static inline uint32_t PullCompanyId(Iterator it) {
+ uint32_t value = 0;
+ for (int i = 0; i < 3; i++) {
+ value <<= 8;
+ value |= *it++;
+ }
+ return value;
+ }
+
+ private:
+ virtual std::pair<size_t, size_t> GetPayloadIndecies() const;
+ DISALLOW_COPY_AND_ASSIGN(Packet);
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/avrcp_reject_packet.cc b/packet/avrcp/avrcp_reject_packet.cc
new file mode 100644
index 0000000..d4ad7ad
--- /dev/null
+++ b/packet/avrcp/avrcp_reject_packet.cc
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "avrcp_reject_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<RejectBuilder> RejectBuilder::MakeBuilder(CommandPdu pdu,
+ Status reason) {
+ std::unique_ptr<RejectBuilder> builder =
+ std::unique_ptr<RejectBuilder>(new RejectBuilder(pdu, reason));
+
+ return builder;
+}
+
+size_t RejectBuilder::size() const { return VendorPacket::kMinSize() + 1; }
+
+bool RejectBuilder::Serialize(const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ // Push the standard avrcp headers
+ PacketBuilder::PushHeader(pkt);
+
+ // Push the avrcp vendor command headers
+ VendorPacketBuilder::PushHeader(pkt, 1);
+
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(reason_));
+
+ return true;
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/avrcp_reject_packet.h b/packet/avrcp/avrcp_reject_packet.h
new file mode 100644
index 0000000..9b7f3a9
--- /dev/null
+++ b/packet/avrcp/avrcp_reject_packet.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "vendor_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class RejectBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~RejectBuilder() = default;
+
+ static std::unique_ptr<RejectBuilder> MakeBuilder(CommandPdu pdu,
+ Status reason);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ Status reason_;
+
+ RejectBuilder(CommandPdu pdu, Status reason)
+ : VendorPacketBuilder(CType::REJECTED, pdu, PacketType::SINGLE),
+ reason_(reason){};
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/capabilities_packet.cc b/packet/avrcp/capabilities_packet.cc
new file mode 100644
index 0000000..459b47d
--- /dev/null
+++ b/packet/avrcp/capabilities_packet.cc
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "capabilities_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<GetCapabilitiesRequestBuilder>
+GetCapabilitiesRequestBuilder::MakeBuilder(Capability capability) {
+ std::unique_ptr<GetCapabilitiesRequestBuilder> builder(
+ new GetCapabilitiesRequestBuilder(capability));
+
+ return builder;
+}
+
+size_t GetCapabilitiesRequestBuilder::size() const {
+ return GetCapabilitiesRequest::kMinSize();
+}
+
+bool GetCapabilitiesRequestBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ // Push the standard avrcp headers
+ PacketBuilder::PushHeader(pkt);
+
+ // Push the avrcp vendor command headers, the parameter length is always 1
+ VendorPacketBuilder::PushHeader(pkt, 1);
+
+ // Push the capability
+ return AddPayloadOctets1(pkt, static_cast<uint8_t>(capability_));
+}
+
+Capability GetCapabilitiesRequest::GetCapabilityRequested() const {
+ auto value = *(begin() + VendorPacket::kMinSize());
+ return static_cast<Capability>(value);
+}
+
+bool GetCapabilitiesRequest::IsValid() const {
+ if (!VendorPacket::IsValid()) return false;
+ return (size() == VendorPacket::kMinSize() + 1);
+}
+
+std::string GetCapabilitiesRequest::ToString() const {
+ std::stringstream ss;
+ ss << "AvrcpCapabilityReqPacket: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Company ID = " << loghex(GetCompanyId()) << std::endl;
+ ss << " â”” Command PDU = " << GetCommandPdu() << std::endl;
+ ss << " â”” PacketType = " << GetPacketType() << std::endl;
+ ss << " â”” Parameter Length = " << loghex(GetParameterLength()) << std::endl;
+ ss << " â”” Capabilities Request = " << GetCapabilityRequested() << std::endl;
+ return ss.str();
+}
+
+std::unique_ptr<GetCapabilitiesResponseBuilder>
+GetCapabilitiesResponseBuilder::MakeCompanyIdBuilder(
+ uint32_t company_id_element) {
+ std::unique_ptr<GetCapabilitiesResponseBuilder> builder(
+ new GetCapabilitiesResponseBuilder(Capability::COMPANY_ID));
+
+ company_id_element &= 0x00FFFFFF;
+ builder->elements_.insert(company_id_element);
+
+ return builder;
+}
+
+std::unique_ptr<GetCapabilitiesResponseBuilder>
+GetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(Event event) {
+ std::unique_ptr<GetCapabilitiesResponseBuilder> builder(
+ new GetCapabilitiesResponseBuilder(Capability::EVENTS_SUPPORTED));
+
+ builder->elements_.insert(static_cast<uint8_t>(event));
+
+ return builder;
+}
+
+GetCapabilitiesResponseBuilder* GetCapabilitiesResponseBuilder::AddCompanyId(
+ uint32_t company_id) {
+ CHECK_EQ(capability_, Capability::COMPANY_ID);
+ CHECK_LT(elements_.size(), size_t(0xFF))
+ << __func__ << ": maximum capability count reached";
+
+ company_id &= 0x00FFFFFF;
+ elements_.insert(company_id);
+
+ return this;
+}
+
+GetCapabilitiesResponseBuilder* GetCapabilitiesResponseBuilder::AddEvent(
+ Event event) {
+ CHECK_EQ(capability_, Capability::EVENTS_SUPPORTED);
+ CHECK_LT(elements_.size(), size_t(0xFF))
+ << __func__ << ": maximum capability count reached";
+
+ elements_.insert(static_cast<uint8_t>(event));
+
+ return this;
+}
+
+size_t GetCapabilitiesResponseBuilder::size() const {
+ // Company ID's have a size of 3 while Events have a size of 1
+ size_t capability_count = elements_.size();
+ size_t capability_size = capability_ == Capability::COMPANY_ID ? 3 : 1;
+
+ return GetCapabilitiesResponse::kMinSize() +
+ (capability_count * capability_size);
+}
+
+bool GetCapabilitiesResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ // Push the standard avrcp headers
+ PacketBuilder::PushHeader(pkt);
+
+ // Push the avrcp vendor command headers
+ uint16_t parameter_count = size() - VendorPacket::kMinSize();
+ VendorPacketBuilder::PushHeader(pkt, parameter_count);
+
+ // Push the capability, capability count, and elements
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(capability_));
+ AddPayloadOctets1(pkt, elements_.size());
+ for (auto it = elements_.begin(); it != elements_.end(); it++) {
+ if (capability_ == Capability::COMPANY_ID)
+ PushCompanyId(pkt, *it);
+ else
+ AddPayloadOctets1(pkt, *it);
+ }
+
+ return true;
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/capabilities_packet.h b/packet/avrcp/capabilities_packet.h
new file mode 100644
index 0000000..3a4607f
--- /dev/null
+++ b/packet/avrcp/capabilities_packet.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <set>
+
+#include "vendor_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class GetCapabilitiesRequestBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~GetCapabilitiesRequestBuilder() = default;
+
+ static std::unique_ptr<GetCapabilitiesRequestBuilder> MakeBuilder(
+ Capability capability);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ Capability capability_;
+
+ GetCapabilitiesRequestBuilder(Capability capability)
+ : VendorPacketBuilder(CType::STATUS, CommandPdu::GET_CAPABILITIES,
+ PacketType::SINGLE),
+ capability_(capability){};
+};
+
+class GetCapabilitiesRequest : public VendorPacket {
+ public:
+ virtual ~GetCapabilitiesRequest() = default;
+
+ /**
+ * Get Capabilities Response Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t param_length;
+ * GetCapabilitiesRequestPacket:
+ * uint8_t capability_requested:
+ */
+ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 1; };
+
+ // Getter Functions
+ Capability GetCapabilityRequested() const;
+
+ // Overloaded Functions
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using VendorPacket::VendorPacket;
+};
+
+class GetCapabilitiesResponseBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~GetCapabilitiesResponseBuilder() = default;
+
+ static std::unique_ptr<GetCapabilitiesResponseBuilder> MakeCompanyIdBuilder(
+ uint32_t company_id_element);
+
+ static std::unique_ptr<GetCapabilitiesResponseBuilder>
+ MakeEventsSupportedBuilder(Event event);
+
+ GetCapabilitiesResponseBuilder* AddCompanyId(uint32_t company_id);
+ GetCapabilitiesResponseBuilder* AddEvent(Event event);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ private:
+ Capability capability_;
+ std::set<uint32_t> elements_;
+
+ GetCapabilitiesResponseBuilder(Capability capability)
+ : VendorPacketBuilder(CType::STABLE, CommandPdu::GET_CAPABILITIES,
+ PacketType::SINGLE),
+ capability_(capability){};
+};
+
+class GetCapabilitiesResponse : public VendorPacket {
+ public:
+ /**
+ * Get Capabilities Response Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t param_length;
+ * GetCapabilitiesRequestPacket;
+ * uint8_t capability_requested;
+ * uint16_t capability_count;
+ * union {
+ * uint8_t event_supported;
+ * uint8_t company_id[3];
+ * } capability_array[];
+ */
+ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 2; };
+
+ // TODO: Implement these for AVRCP Controller
+ // virtual uint8_t GetCapabilityReturned() const;
+ // virtual uint8_t GetCapabilityCount() const;
+ // virtual std::vector<Event> GetEventsSupported() const;
+ // virtual std::vector<uint32_t> GetCompanyIds() const;
+
+ virtual std::string ToString() const override;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/change_path.cc b/packet/avrcp/change_path.cc
new file mode 100644
index 0000000..3c69903
--- /dev/null
+++ b/packet/avrcp/change_path.cc
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "change_path.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<ChangePathResponseBuilder>
+ChangePathResponseBuilder::MakeBuilder(Status status,
+ uint32_t num_items_in_folder) {
+ std::unique_ptr<ChangePathResponseBuilder> builder(
+ new ChangePathResponseBuilder(status, num_items_in_folder));
+
+ return builder;
+}
+
+size_t ChangePathResponseBuilder::size() const {
+ size_t len = BrowsePacket::kMinSize();
+ len += 1; // Status
+ if (status_ != Status::NO_ERROR) return len;
+
+ len += 4; // Number of items in folder
+ return len;
+}
+
+bool ChangePathResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());
+
+ AddPayloadOctets1(pkt, (uint8_t)status_);
+ if (status_ != Status::NO_ERROR) return true;
+
+ AddPayloadOctets4(pkt, base::ByteSwap(num_items_in_folder_));
+ return true;
+}
+
+uint16_t ChangePathRequest::GetUidCounter() const {
+ auto it = begin() + BrowsePacket::kMinSize();
+ return base::ByteSwap(it.extract<uint16_t>());
+}
+
+Direction ChangePathRequest::GetDirection() const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(2);
+ return static_cast<Direction>(*it);
+}
+
+uint64_t ChangePathRequest::GetUid() const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(3);
+ return base::ByteSwap(it.extract<uint64_t>());
+}
+
+bool ChangePathRequest::IsValid() const {
+ if (!BrowsePacket::IsValid()) return false;
+ // Change path request packets are always the same size
+ return size() == kMinSize();
+}
+
+std::string ChangePathRequest::ToString() const {
+ std::stringstream ss;
+ ss << "ChangePathRequestPacket: " << std::endl;
+ ss << " â”” PDU = " << GetPdu() << std::endl;
+ ss << " â”” Length = " << GetLength() << std::endl;
+ ss << " â”” UID Counter = " << loghex(GetUidCounter()) << std::endl;
+ ss << " â”” Direction = " << GetDirection() << std::endl;
+ ss << " â”” UID Requested = " << loghex(GetUid()) << std::endl;
+ ss << std::endl;
+
+ return ss.str();
+}
+
+std::unique_ptr<ChangePathRequestBuilder> ChangePathRequestBuilder::MakeBuilder(
+ uint16_t uid_counter, Direction direction, uint64_t folder_uid) {
+ std::unique_ptr<ChangePathRequestBuilder> builder(
+ new ChangePathRequestBuilder(uid_counter, direction, folder_uid));
+
+ return builder;
+}
+
+size_t ChangePathRequestBuilder::size() const {
+ return ChangePathRequest::kMinSize();
+}
+
+bool ChangePathRequestBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());
+
+ AddPayloadOctets2(pkt, base::ByteSwap(uid_counter_));
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(direction_));
+ AddPayloadOctets8(pkt, base::ByteSwap(folder_uid_));
+ return true;
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/change_path.h b/packet/avrcp/change_path.h
new file mode 100644
index 0000000..a033aa8
--- /dev/null
+++ b/packet/avrcp/change_path.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "avrcp_browse_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class ChangePathResponseBuilder : public BrowsePacketBuilder {
+ public:
+ virtual ~ChangePathResponseBuilder() = default;
+
+ static std::unique_ptr<ChangePathResponseBuilder> MakeBuilder(
+ Status status, uint32_t num_items_in_folder);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ private:
+ Status status_;
+ uint32_t num_items_in_folder_;
+
+ ChangePathResponseBuilder(Status status, uint32_t num_items_in_folder)
+ : BrowsePacketBuilder(BrowsePdu::CHANGE_PATH),
+ status_(status),
+ num_items_in_folder_(num_items_in_folder) {}
+};
+
+class ChangePathRequest : public BrowsePacket {
+ public:
+ virtual ~ChangePathRequest() = default;
+
+ /**
+ * Avrcp Change Path Packet Layout
+ * BrowsePacket:
+ * uint8_t pdu_;
+ * uint16_t length_;
+ * ChangePathRequest:
+ * uint16_t uid_counter_;
+ * uint8_t direction_;
+ * uint64_t folder_uid_;
+ */
+ static constexpr size_t kMinSize() { return BrowsePacket::kMinSize() + 11; }
+
+ uint16_t GetUidCounter() const;
+ Direction GetDirection() const;
+ uint64_t GetUid() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using BrowsePacket::BrowsePacket;
+};
+
+class ChangePathRequestBuilder : public BrowsePacketBuilder {
+ public:
+ virtual ~ChangePathRequestBuilder() = default;
+
+ static std::unique_ptr<ChangePathRequestBuilder> MakeBuilder(
+ uint16_t uid_counter, Direction direction, uint64_t folder_uid);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ private:
+ ChangePathRequestBuilder(uint16_t uid_counter, Direction direction,
+ uint64_t folder_uid)
+ : BrowsePacketBuilder(BrowsePdu::CHANGE_PATH),
+ uid_counter_(uid_counter),
+ direction_(direction),
+ folder_uid_(folder_uid){};
+
+ uint16_t uid_counter_;
+ Direction direction_;
+ uint64_t folder_uid_;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/general_reject_packet.cc b/packet/avrcp/general_reject_packet.cc
new file mode 100644
index 0000000..cde0031
--- /dev/null
+++ b/packet/avrcp/general_reject_packet.cc
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "general_reject_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<GeneralRejectBuilder> GeneralRejectBuilder::MakeBuilder(
+ BrowsePdu pdu, Status reason) {
+ std::unique_ptr<GeneralRejectBuilder> builder =
+ std::unique_ptr<GeneralRejectBuilder>(
+ new GeneralRejectBuilder(pdu, reason));
+
+ return builder;
+}
+
+size_t GeneralRejectBuilder::size() const {
+ return BrowsePacket::kMinSize() + 1;
+}
+
+bool GeneralRejectBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());
+
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(reason_));
+
+ return true;
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/packet/avrcp/general_reject_packet.h b/packet/avrcp/general_reject_packet.h
new file mode 100644
index 0000000..4058fd4
--- /dev/null
+++ b/packet/avrcp/general_reject_packet.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "avrcp_browse_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class GeneralRejectBuilder : public BrowsePacketBuilder {
+ public:
+ virtual ~GeneralRejectBuilder() = default;
+
+ static std::unique_ptr<GeneralRejectBuilder> MakeBuilder(BrowsePdu pdu,
+ Status reason);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ Status reason_;
+
+ GeneralRejectBuilder(BrowsePdu pdu, Status reason)
+ : BrowsePacketBuilder(pdu), reason_(reason){};
+};
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/packet/avrcp/get_element_attributes_packet.cc b/packet/avrcp/get_element_attributes_packet.cc
new file mode 100644
index 0000000..c26207e
--- /dev/null
+++ b/packet/avrcp/get_element_attributes_packet.cc
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+
+#include "get_element_attributes_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+uint64_t GetElementAttributesRequest::GetIdentifier() const {
+ auto it = begin() + VendorPacket::kMinSize();
+ return it.extract<uint64_t>();
+}
+
+uint8_t GetElementAttributesRequest::GetNumAttributes() const {
+ auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(8);
+ return it.extract<uint8_t>();
+}
+
+std::vector<Attribute> GetElementAttributesRequest::GetAttributesRequested()
+ const {
+ auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(8);
+
+ size_t number_of_attributes = it.extract<uint8_t>();
+
+ std::vector<Attribute> attribute_list;
+
+ for (size_t i = 0; i < number_of_attributes; i++) {
+ attribute_list.push_back((Attribute)base::ByteSwap(it.extract<uint32_t>()));
+ }
+
+ return attribute_list;
+}
+
+bool GetElementAttributesRequest::IsValid() const {
+ if (!VendorPacket::IsValid()) return false;
+ if (size() < kMinSize()) return false;
+
+ size_t num_attributes = GetNumAttributes();
+ auto attr_start = begin() + VendorPacket::kMinSize() + static_cast<size_t>(9);
+
+ // Casting the int returned from end - attr_start should be fine. If an
+ // overflow occurs we can definitly say the packet is invalid
+ return (num_attributes * sizeof(Attribute)) == (size_t)(end() - attr_start);
+}
+
+std::string GetElementAttributesRequest::ToString() const {
+ std::stringstream ss;
+ ss << "RegisterNotificationPacket: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Company ID = " << loghex(GetCompanyId()) << std::endl;
+ ss << " â”” Command PDU = " << GetCommandPdu() << std::endl;
+ ss << " â”” PacketType = " << GetPacketType() << std::endl;
+ ss << " â”” Parameter Length = " << GetParameterLength() << std::endl;
+ ss << " â”” Identifier = " << loghex(GetIdentifier()) << std::endl;
+
+ auto attr_list = GetAttributesRequested();
+
+ ss << " â”” Attribute List: Size: " << attr_list.size() << std::endl;
+ for (auto it = attr_list.begin(); it != attr_list.end(); it++) {
+ ss << " â”” " << loghex((uint32_t)(*it)) << std::endl;
+ }
+ ss << std::endl;
+
+ return ss.str();
+}
+
+std::unique_ptr<GetElementAttributesResponseBuilder>
+GetElementAttributesResponseBuilder::MakeBuilder(size_t mtu) {
+ std::unique_ptr<GetElementAttributesResponseBuilder> builder(
+ new GetElementAttributesResponseBuilder(mtu));
+
+ return builder;
+}
+
+bool GetElementAttributesResponseBuilder::AddAttributeEntry(
+ AttributeEntry entry) {
+ CHECK_LT(entries_.size(), size_t(0xFF))
+ << __func__ << ": attribute entry overflow";
+
+ size_t remaining_space = mtu_ - size();
+ if (entry.size() > remaining_space) {
+ entry.resize(remaining_space);
+ }
+
+ if (entry.empty()) {
+ return false;
+ }
+
+ entries_.insert(entry);
+ return true;
+}
+
+bool GetElementAttributesResponseBuilder::AddAttributeEntry(Attribute attribute,
+ std::string value) {
+ return AddAttributeEntry(AttributeEntry(attribute, value));
+}
+
+size_t GetElementAttributesResponseBuilder::size() const {
+ size_t attr_list_size = 0;
+
+ for (auto& attribute_entry : entries_) {
+ attr_list_size += attribute_entry.size();
+ }
+
+ return VendorPacket::kMinSize() + 1 + attr_list_size;
+}
+
+bool GetElementAttributesResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ PacketBuilder::PushHeader(pkt);
+
+ VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
+
+ AddPayloadOctets1(pkt, entries_.size());
+ for (auto attribute_entry : entries_) {
+ PushAttributeValue(pkt, attribute_entry);
+ }
+
+ return true;
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/get_element_attributes_packet.h b/packet/avrcp/get_element_attributes_packet.h
new file mode 100644
index 0000000..03fa8d1
--- /dev/null
+++ b/packet/avrcp/get_element_attributes_packet.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <set>
+#include "vendor_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class GetElementAttributesRequest : public VendorPacket {
+ public:
+ virtual ~GetElementAttributesRequest() = default;
+
+ /**
+ * Register Notificaiton Request Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t param_length;
+ * RegisterNotificationRequestPacket:
+ * uint64_t identifier;
+ * uint8_t number_of_attributes;
+ * uint32_t attributes_requested[];
+ */
+ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 9; }
+
+ // Getter Functions
+ uint64_t GetIdentifier() const;
+ uint8_t GetNumAttributes() const;
+ std::vector<Attribute> GetAttributesRequested() const;
+
+ // Overloaded Functions
+ virtual bool IsValid() const;
+ virtual std::string ToString() const override;
+
+ protected:
+ using VendorPacket::VendorPacket;
+};
+
+class GetElementAttributesResponseBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~GetElementAttributesResponseBuilder() = default;
+
+ static std::unique_ptr<GetElementAttributesResponseBuilder> MakeBuilder(
+ size_t mtu);
+
+ bool AddAttributeEntry(AttributeEntry entry);
+ bool AddAttributeEntry(Attribute attribute, std::string value);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ private:
+ std::set<AttributeEntry> entries_;
+ size_t mtu_;
+
+ GetElementAttributesResponseBuilder(size_t mtu)
+ : VendorPacketBuilder(CType::STABLE, CommandPdu::GET_ELEMENT_ATTRIBUTES,
+ PacketType::SINGLE),
+ mtu_(mtu){};
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/get_folder_items.cc b/packet/avrcp/get_folder_items.cc
new file mode 100644
index 0000000..c95bb4a
--- /dev/null
+++ b/packet/avrcp/get_folder_items.cc
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "get_folder_items.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<GetFolderItemsResponseBuilder>
+GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status status,
+ uint16_t uid_counter,
+ size_t mtu) {
+ std::unique_ptr<GetFolderItemsResponseBuilder> builder(
+ new GetFolderItemsResponseBuilder(Scope::MEDIA_PLAYER_LIST, status,
+ uid_counter, mtu));
+
+ return builder;
+}
+
+std::unique_ptr<GetFolderItemsResponseBuilder>
+GetFolderItemsResponseBuilder::MakeVFSBuilder(Status status,
+ uint16_t uid_counter,
+ size_t mtu) {
+ std::unique_ptr<GetFolderItemsResponseBuilder> builder(
+ new GetFolderItemsResponseBuilder(Scope::VFS, status, uid_counter, mtu));
+
+ return builder;
+}
+
+std::unique_ptr<GetFolderItemsResponseBuilder>
+GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(Status status,
+ uint16_t uid_counter,
+ size_t mtu) {
+ std::unique_ptr<GetFolderItemsResponseBuilder> builder(
+ new GetFolderItemsResponseBuilder(Scope::NOW_PLAYING, status, uid_counter,
+ mtu));
+
+ return builder;
+}
+
+size_t GetFolderItemsResponseBuilder::size() const {
+ size_t len = BrowsePacket::kMinSize();
+ len += 1; // Status
+
+ // There is nothing other than the status in the packet if the status isn't
+ // NO_ERROR
+ if (status_ != Status::NO_ERROR || items_.size() == 0) return len;
+
+ len += 2; // UID Counter
+ len += 2; // Number of Items;
+ for (const auto& item : items_) {
+ len += item.size();
+ }
+
+ return len;
+}
+
+bool GetFolderItemsResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());
+
+ if (status_ == Status::NO_ERROR && items_.size() == 0) {
+ // Return range out of bounds if there are zero items in the folder
+ status_ = Status::RANGE_OUT_OF_BOUNDS;
+ }
+
+ AddPayloadOctets1(pkt, (uint8_t)status_); // Status
+ if (status_ != Status::NO_ERROR) return true;
+
+ AddPayloadOctets2(pkt, base::ByteSwap(uid_counter_));
+ uint16_t num_items = items_.size();
+ AddPayloadOctets2(pkt, base::ByteSwap(num_items));
+
+ for (const auto& item : items_) {
+ PushMediaListItem(pkt, item);
+ }
+
+ return true;
+}
+
+bool GetFolderItemsResponseBuilder::AddMediaPlayer(MediaPlayerItem item) {
+ CHECK(scope_ == Scope::MEDIA_PLAYER_LIST);
+
+ if (size() + item.size() > mtu_) return false;
+
+ items_.push_back(MediaListItem(item));
+ return true;
+}
+
+bool GetFolderItemsResponseBuilder::AddSong(MediaElementItem item) {
+ CHECK(scope_ == Scope::VFS || scope_ == Scope::NOW_PLAYING);
+
+ if (size() + item.size() > mtu_) return false;
+
+ items_.push_back(MediaListItem(item));
+ return true;
+}
+
+bool GetFolderItemsResponseBuilder::AddFolder(FolderItem item) {
+ CHECK(scope_ == Scope::VFS);
+
+ if (size() + item.size() > mtu_) return false;
+
+ items_.push_back(MediaListItem(item));
+ return true;
+}
+
+void GetFolderItemsResponseBuilder::PushMediaListItem(
+ const std::shared_ptr<::bluetooth::Packet>& pkt,
+ const MediaListItem& item) {
+ switch (item.type_) {
+ case MediaListItem::PLAYER:
+ PushMediaPlayerItem(pkt, item.player_);
+ break;
+ case MediaListItem::FOLDER:
+ PushFolderItem(pkt, item.folder_);
+ break;
+ case MediaListItem::SONG:
+ PushMediaElementItem(pkt, item.song_);
+ break;
+ }
+}
+
+void GetFolderItemsResponseBuilder::PushMediaPlayerItem(
+ const std::shared_ptr<::bluetooth::Packet>& pkt,
+ const MediaPlayerItem& item) {
+ AddPayloadOctets1(pkt, 0x01); // Media Player Item
+ uint16_t item_len = item.size() - 3;
+ AddPayloadOctets2(pkt, base::ByteSwap(item_len)); // Item length
+ AddPayloadOctets2(pkt, base::ByteSwap(item.id_)); // Player ID
+ AddPayloadOctets1(pkt, 0x01); // Player Type
+ AddPayloadOctets4(pkt, 0x00000000); // Player Subtype
+ AddPayloadOctets1(
+ pkt, 0x02); // Player Play Status // TODO: Add this as a passed field
+
+ // Features
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0xb7);
+ AddPayloadOctets1(pkt, 0x01);
+ if (item.browsable_) {
+ AddPayloadOctets1(pkt, 0x0C);
+ AddPayloadOctets1(pkt, 0x0a);
+ } else {
+ AddPayloadOctets1(pkt, 0x04);
+ AddPayloadOctets1(pkt, 0x00);
+ }
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+ AddPayloadOctets1(pkt, 0x00);
+
+ AddPayloadOctets2(pkt, base::ByteSwap((uint16_t)0x006a));
+ uint16_t name_len = item.name_.size();
+ AddPayloadOctets2(pkt, base::ByteSwap(name_len));
+
+ for (const uint8_t& byte : item.name_) {
+ AddPayloadOctets1(pkt, byte);
+ }
+}
+
+void GetFolderItemsResponseBuilder::PushFolderItem(
+ const std::shared_ptr<::bluetooth::Packet>& pkt, const FolderItem& item) {
+ AddPayloadOctets1(pkt, 0x02); // Folder Item
+ uint16_t item_len = item.size() - 3;
+ AddPayloadOctets2(pkt, base::ByteSwap(item_len));
+ AddPayloadOctets8(pkt, base::ByteSwap(item.uid_));
+ AddPayloadOctets1(pkt, item.folder_type_);
+ AddPayloadOctets1(pkt, item.is_playable_ ? 0x01 : 0x00);
+ AddPayloadOctets2(pkt,
+ base::ByteSwap((uint16_t)0x006a)); // UTF-8 Character Set
+ uint16_t name_len = item.name_.size();
+ AddPayloadOctets2(pkt, base::ByteSwap(name_len));
+ for (const uint8_t& byte : item.name_) {
+ AddPayloadOctets1(pkt, byte);
+ }
+}
+
+void GetFolderItemsResponseBuilder::PushMediaElementItem(
+ const std::shared_ptr<::bluetooth::Packet>& pkt,
+ const MediaElementItem& item) {
+ AddPayloadOctets1(pkt, 0x03); // Media Element Item
+ uint16_t item_len = item.size() - 3;
+ AddPayloadOctets2(pkt, base::ByteSwap(item_len));
+ AddPayloadOctets8(pkt, base::ByteSwap(item.uid_));
+ AddPayloadOctets1(pkt, 0x00); // Media Type Audio
+ AddPayloadOctets2(pkt,
+ base::ByteSwap((uint16_t)0x006a)); // UTF-8 Character Set
+ uint16_t name_len = item.name_.size();
+ AddPayloadOctets2(pkt, base::ByteSwap(name_len));
+ for (const uint8_t& byte : item.name_) {
+ AddPayloadOctets1(pkt, byte);
+ }
+
+ AddPayloadOctets1(pkt, (uint8_t)item.attributes_.size());
+ for (const auto& entry : item.attributes_) {
+ AddPayloadOctets4(pkt, base::ByteSwap((uint32_t)entry.attribute()));
+ AddPayloadOctets2(pkt,
+ base::ByteSwap((uint16_t)0x006a)); // UTF-8 Character Set
+
+ std::string attr_val = entry.value();
+ uint16_t attr_len = attr_val.size();
+
+ AddPayloadOctets2(pkt, base::ByteSwap(attr_len));
+ for (const uint8_t& byte : attr_val) {
+ AddPayloadOctets1(pkt, byte);
+ }
+ }
+}
+
+Scope GetFolderItemsRequest::GetScope() const {
+ auto it = begin() + BrowsePacket::kMinSize();
+ return static_cast<Scope>(*it);
+}
+
+uint32_t GetFolderItemsRequest::GetStartItem() const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(1);
+ return base::ByteSwap(it.extract<uint32_t>());
+}
+
+uint32_t GetFolderItemsRequest::GetEndItem() const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(5);
+ return base::ByteSwap(it.extract<uint32_t>());
+}
+
+uint8_t GetFolderItemsRequest::GetNumAttributes() const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(9);
+ return *it;
+}
+
+std::vector<Attribute> GetFolderItemsRequest::GetAttributesRequested() const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(9);
+
+ size_t number_of_attributes = it.extract<uint8_t>();
+ std::vector<Attribute> attribute_list;
+
+ // No attributes requested
+ if (number_of_attributes == 0xFF) return attribute_list;
+
+ // TODO: If the number of attributes equals 0, then all attributes are
+ // requested right now thats handled in the service itself, but it'd be nice
+ // to have this function return a vector with all the attributes
+
+ for (size_t i = 0; i < number_of_attributes; i++) {
+ attribute_list.push_back((Attribute)base::ByteSwap(it.extract<uint32_t>()));
+ }
+
+ return attribute_list;
+}
+
+bool GetFolderItemsRequest::IsValid() const {
+ if (!BrowsePacket::IsValid()) return false;
+ // The minimum size required to be valid
+ if (size() < kMinSize()) return false;
+
+ auto attr_count = GetNumAttributes();
+
+ // No items requested
+ if (attr_count == 0xFF) return true;
+
+ auto attr_start = begin() + kMinSize();
+
+ // Casting the int returned from end - attr_start should be fine. If an
+ // overflow occurs we can definitly say the packet is invalid
+ return (attr_count * sizeof(Attribute)) == (size_t)(end() - attr_start);
+}
+
+std::string GetFolderItemsRequest::ToString() const {
+ std::stringstream ss;
+ ss << "GetFolderItemsRequestPacket: " << std::endl;
+ ss << " â”” PDU = " << GetPdu() << std::endl;
+ ss << " â”” Length = " << GetLength() << std::endl;
+ ss << " â”” Scope = " << GetScope() << std::endl;
+ ss << " â”” Start Item = " << loghex(GetStartItem()) << std::endl;
+ ss << " â”” End Item = " << loghex(GetEndItem()) << std::endl;
+ ss << " â”” Attribute Count = " << loghex(GetNumAttributes()) << std::endl;
+
+ ss << std::endl;
+
+ return ss.str();
+}
+
+std::unique_ptr<GetFolderItemsRequestBuilder>
+GetFolderItemsRequestBuilder::MakeBuilder(
+ Scope scope, uint32_t start_item, uint32_t end_item,
+ const std::set<Attribute>& requested_attrs) {
+ std::unique_ptr<GetFolderItemsRequestBuilder> builder(
+ new GetFolderItemsRequestBuilder(scope, start_item, end_item,
+ requested_attrs));
+
+ return builder;
+}
+
+size_t GetFolderItemsRequestBuilder::size() const {
+ size_t len = GetFolderItemsRequest::kMinSize();
+ len += requested_attrs_.size() * sizeof(Attribute);
+ return len;
+}
+
+bool GetFolderItemsRequestBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());
+
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(scope_));
+ AddPayloadOctets4(pkt, base::ByteSwap(start_item_));
+ AddPayloadOctets4(pkt, base::ByteSwap(end_item_));
+
+ if (requested_attrs_.size() == 0) {
+ // 0xFF is the value to signify that there are no attributes requested.
+ AddPayloadOctets1(pkt, 0xFF);
+ return true;
+ }
+
+ AddPayloadOctets1(pkt, requested_attrs_.size());
+ for (const auto& attr : requested_attrs_) {
+ AddPayloadOctets4(pkt, base::ByteSwap(static_cast<uint32_t>(attr)));
+ }
+ return true;
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/get_folder_items.h b/packet/avrcp/get_folder_items.h
new file mode 100644
index 0000000..f5291af
--- /dev/null
+++ b/packet/avrcp/get_folder_items.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "avrcp_browse_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class GetFolderItemsResponseBuilder : public BrowsePacketBuilder {
+ public:
+ virtual ~GetFolderItemsResponseBuilder() = default;
+ static std::unique_ptr<GetFolderItemsResponseBuilder> MakePlayerListBuilder(
+ Status status, uint16_t uid_counter, size_t mtu);
+ static std::unique_ptr<GetFolderItemsResponseBuilder> MakeVFSBuilder(
+ Status status, uint16_t uid_counter, size_t mtu);
+ static std::unique_ptr<GetFolderItemsResponseBuilder> MakeNowPlayingBuilder(
+ Status status, uint16_t uid_counter, size_t mtu);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ // Returns false if adding an item would exceed the MTU
+ bool AddMediaPlayer(MediaPlayerItem item);
+ bool AddSong(MediaElementItem item);
+ bool AddFolder(FolderItem item);
+
+ protected:
+ Scope scope_;
+ std::vector<MediaListItem> items_;
+ Status status_;
+ uint16_t uid_counter_;
+ size_t mtu_;
+
+ GetFolderItemsResponseBuilder(Scope scope, Status status,
+ uint16_t uid_counter, size_t mtu)
+ : BrowsePacketBuilder(BrowsePdu::GET_FOLDER_ITEMS),
+ scope_(scope),
+ status_(status),
+ uid_counter_(uid_counter),
+ mtu_(mtu){};
+
+ private:
+ void PushMediaListItem(const std::shared_ptr<::bluetooth::Packet>& pkt,
+ const MediaListItem& item);
+ void PushMediaPlayerItem(const std::shared_ptr<::bluetooth::Packet>& pkt,
+ const MediaPlayerItem& item);
+ void PushMediaElementItem(const std::shared_ptr<::bluetooth::Packet>& pkt,
+ const MediaElementItem& item);
+ void PushFolderItem(const std::shared_ptr<::bluetooth::Packet>& pkt,
+ const FolderItem& item);
+};
+
+class GetFolderItemsRequest : public BrowsePacket {
+ public:
+ virtual ~GetFolderItemsRequest() = default;
+
+ /**
+ * Avrcp Change Path Packet Layout
+ * BrowsePacket:
+ * uint8_t pdu_;
+ * uint16_t length_;
+ * GetFolderItemsRequest:
+ * uint8_t scope_;
+ * uint32_t start_item_;
+ * uint32_t end_item_;
+ * uint8_t attr_count_;
+ * uint32_t[] attr_requested_;
+ */
+ static constexpr size_t kMinSize() { return BrowsePacket::kMinSize() + 10; }
+
+ Scope GetScope() const;
+ uint32_t GetStartItem() const;
+ uint32_t GetEndItem() const;
+ uint8_t GetNumAttributes() const;
+ std::vector<Attribute> GetAttributesRequested() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using BrowsePacket::BrowsePacket;
+};
+
+class GetFolderItemsRequestBuilder : public BrowsePacketBuilder {
+ public:
+ virtual ~GetFolderItemsRequestBuilder() = default;
+
+ static std::unique_ptr<GetFolderItemsRequestBuilder> MakeBuilder(
+ Scope scope, uint32_t start_item, uint32_t end_item,
+ const std::set<Attribute>& requested_attrs);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ GetFolderItemsRequestBuilder(Scope scope, uint32_t start_item,
+ uint32_t end_item,
+ const std::set<Attribute>& requested_attrs)
+ : BrowsePacketBuilder(BrowsePdu::GET_FOLDER_ITEMS),
+ scope_(scope),
+ start_item_(start_item),
+ end_item_(end_item),
+ requested_attrs_(requested_attrs){};
+
+ Scope scope_;
+ uint32_t start_item_;
+ uint32_t end_item_;
+ std::set<Attribute> requested_attrs_;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/get_item_attributes.cc b/packet/avrcp/get_item_attributes.cc
new file mode 100644
index 0000000..3430474
--- /dev/null
+++ b/packet/avrcp/get_item_attributes.cc
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "get_item_attributes.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<GetItemAttributesResponseBuilder>
+GetItemAttributesResponseBuilder::MakeBuilder(Status status, size_t mtu) {
+ std::unique_ptr<GetItemAttributesResponseBuilder> builder(
+ new GetItemAttributesResponseBuilder(status, mtu));
+
+ return builder;
+}
+
+bool GetItemAttributesResponseBuilder::AddAttributeEntry(AttributeEntry entry) {
+ CHECK(entries_.size() < 0xFF);
+
+ size_t remaining_space = mtu_ - size();
+ if (entry.size() > remaining_space) {
+ entry.resize(remaining_space);
+ }
+
+ if (entry.empty()) {
+ return false;
+ }
+
+ entries_.insert(entry);
+ return true;
+}
+
+bool GetItemAttributesResponseBuilder::AddAttributeEntry(Attribute attribute,
+ std::string value) {
+ return AddAttributeEntry(AttributeEntry(attribute, value));
+}
+
+size_t GetItemAttributesResponseBuilder::size() const {
+ size_t len = BrowsePacket::kMinSize();
+ len += 1; // Status
+ if (status_ != Status::NO_ERROR) return len;
+
+ len += 1; // Number of attributes
+ for (const auto& entry : entries_) {
+ len += entry.size();
+ }
+ return len;
+}
+
+bool GetItemAttributesResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());
+
+ AddPayloadOctets1(pkt, (uint8_t)status_);
+ if (status_ != Status::NO_ERROR) return true;
+
+ AddPayloadOctets1(pkt, entries_.size());
+ for (auto entry : entries_) {
+ AddPayloadOctets4(pkt, base::ByteSwap((uint32_t)entry.attribute()));
+ uint16_t character_set = 0x006a; // UTF-8
+ AddPayloadOctets2(pkt, base::ByteSwap(character_set));
+ uint16_t value_length = entry.value().length();
+ AddPayloadOctets2(pkt, base::ByteSwap(value_length));
+ for (const uint8_t& byte : entry.value()) {
+ AddPayloadOctets1(pkt, byte);
+ }
+ }
+
+ return true;
+}
+
+Scope GetItemAttributesRequest::GetScope() const {
+ auto it = begin() + BrowsePacket::kMinSize();
+ return static_cast<Scope>(*it);
+}
+
+uint64_t GetItemAttributesRequest::GetUid() const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(1);
+ return base::ByteSwap(it.extract<uint64_t>());
+}
+
+uint16_t GetItemAttributesRequest::GetUidCounter() const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(9);
+ return base::ByteSwap(it.extract<uint16_t>());
+}
+
+uint8_t GetItemAttributesRequest::GetNumAttributes() const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(11);
+ return *it;
+}
+
+std::vector<Attribute> GetItemAttributesRequest::GetAttributesRequested()
+ const {
+ auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(11);
+ size_t number_of_attributes = it.extract<uint8_t>();
+
+ std::vector<Attribute> attribute_list;
+ for (size_t i = 0; i < number_of_attributes; i++) {
+ attribute_list.push_back((Attribute)base::ByteSwap(it.extract<uint32_t>()));
+ }
+
+ return attribute_list;
+}
+
+bool GetItemAttributesRequest::IsValid() const {
+ if (!BrowsePacket::IsValid()) return false;
+ if (size() < kMinSize()) return false;
+
+ // Casting the int returned from end - attr_start should be fine. If an
+ // overflow occurs we can definitly say the packet is invalid
+ return (GetNumAttributes() * sizeof(Attribute)) == (size() - kMinSize());
+}
+
+std::string GetItemAttributesRequest::ToString() const {
+ std::stringstream ss;
+ ss << "GetItemAttributesRequestPacket: " << std::endl;
+ ss << " â”” PDU = " << GetPdu() << std::endl;
+ ss << " â”” Length = " << GetLength() << std::endl;
+ ss << " â”” Scope = " << GetScope() << std::endl;
+ ss << " â”” UID Requested = " << loghex(GetUid()) << std::endl;
+ ss << " â”” UID Counter = " << loghex(GetUidCounter()) << std::endl;
+ ss << " â”” Num Attributes = " << loghex(GetNumAttributes()) << std::endl;
+
+ auto attr_list = GetAttributesRequested();
+ ss << " â”” Attribute List: Size: " << attr_list.size() << std::endl;
+ for (auto it = attr_list.begin(); it != attr_list.end(); it++) {
+ ss << " â”” " << loghex((uint32_t)(*it)) << std::endl;
+ }
+ ss << std::endl;
+
+ return ss.str();
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/get_item_attributes.h b/packet/avrcp/get_item_attributes.h
new file mode 100644
index 0000000..aa1db71
--- /dev/null
+++ b/packet/avrcp/get_item_attributes.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <set>
+
+#include "avrcp_browse_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class GetItemAttributesResponseBuilder : public BrowsePacketBuilder {
+ public:
+ virtual ~GetItemAttributesResponseBuilder() = default;
+
+ static std::unique_ptr<GetItemAttributesResponseBuilder> MakeBuilder(
+ Status status, size_t mtu);
+
+ bool AddAttributeEntry(AttributeEntry entry);
+ bool AddAttributeEntry(Attribute, std::string);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ private:
+ Status status_;
+ size_t mtu_;
+ std::set<AttributeEntry> entries_;
+
+ GetItemAttributesResponseBuilder(Status status, size_t mtu)
+ : BrowsePacketBuilder(BrowsePdu::GET_ITEM_ATTRIBUTES),
+ status_(status),
+ mtu_(mtu) {}
+};
+
+class GetItemAttributesRequest : public BrowsePacket {
+ public:
+ virtual ~GetItemAttributesRequest() = default;
+
+ /**
+ * Avrcp Change Path Packet Layout
+ * BrowsePacket:
+ * uint8_t pdu_;
+ * uint16_t length_;
+ * GetItemAttributesRequest:
+ * uint8_t scope_;
+ * uint64_t uid_;
+ * uint16_t uid_counter_;
+ * uint8_t attr_count_;
+ * uint32_t[] attr_requested_;
+ */
+ static constexpr size_t kMinSize() { return BrowsePacket::kMinSize() + 12; }
+
+ Scope GetScope() const;
+ uint64_t GetUid() const;
+ uint16_t GetUidCounter() const;
+ uint8_t GetNumAttributes()
+ const; // If this value is zero, then all attributes are requested
+ std::vector<Attribute> GetAttributesRequested() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using BrowsePacket::BrowsePacket;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/get_play_status_packet.cc b/packet/avrcp/get_play_status_packet.cc
new file mode 100644
index 0000000..8a40de9
--- /dev/null
+++ b/packet/avrcp/get_play_status_packet.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "get_play_status_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::string GetPlayStatusRequest::ToString() const {
+ return "GetPlayStatusRequest";
+}
+
+std::unique_ptr<GetPlayStatusResponseBuilder>
+GetPlayStatusResponseBuilder::MakeBuilder(uint32_t song_length,
+ uint32_t song_position,
+ uint8_t play_status) {
+ std::unique_ptr<GetPlayStatusResponseBuilder> builder(
+ new GetPlayStatusResponseBuilder(song_length, song_position,
+ play_status));
+
+ return builder;
+}
+
+size_t GetPlayStatusResponseBuilder::size() const {
+ return VendorPacket::kMinSize() + 4 + 4 + 1;
+}
+
+bool GetPlayStatusResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ // Push the standard avrcp headers
+ PacketBuilder::PushHeader(pkt);
+
+ // Push the avrcp vendor command headers
+ uint16_t parameter_count = size() - VendorPacket::kMinSize();
+ VendorPacketBuilder::PushHeader(pkt, parameter_count);
+
+ AddPayloadOctets4(pkt, base::ByteSwap(song_length_));
+ AddPayloadOctets4(pkt, base::ByteSwap(song_position_));
+ AddPayloadOctets1(pkt, play_status_);
+
+ return true;
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/get_play_status_packet.h b/packet/avrcp/get_play_status_packet.h
new file mode 100644
index 0000000..5714c26
--- /dev/null
+++ b/packet/avrcp/get_play_status_packet.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "vendor_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+// TODO (apanicke): This packet doesn't really need to exist as it provides
+// zero extra information other than it is a strong type and provides a
+// validator
+class GetPlayStatusRequest : public VendorPacket {
+ public:
+ virtual ~GetPlayStatusRequest() = default;
+
+ /**
+ * Get Capabilities Response Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t param_length = 0;
+ */
+ static constexpr size_t kMinSize() { return Packet::kMinSize() + 7; }
+
+ // Overloaded Functions
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using VendorPacket::VendorPacket;
+};
+
+class GetPlayStatusResponseBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~GetPlayStatusResponseBuilder() = default;
+
+ static std::unique_ptr<GetPlayStatusResponseBuilder> MakeBuilder(
+ uint32_t song_length, uint32_t song_position, uint8_t play_status);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ uint32_t song_length_;
+ uint32_t song_position_;
+ uint8_t play_status_;
+
+ GetPlayStatusResponseBuilder(uint32_t song_length, uint32_t song_position,
+ uint8_t play_status)
+ : VendorPacketBuilder(CType::STABLE, CommandPdu::GET_PLAY_STATUS,
+ PacketType::SINGLE),
+ song_length_(song_length),
+ song_position_(song_position),
+ play_status_(play_status){};
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/get_total_number_of_items.cc b/packet/avrcp/get_total_number_of_items.cc
new file mode 100644
index 0000000..ab601ea
--- /dev/null
+++ b/packet/avrcp/get_total_number_of_items.cc
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "get_total_number_of_items.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<GetTotalNumberOfItemsResponseBuilder>
+GetTotalNumberOfItemsResponseBuilder::MakeBuilder(
+ Status status, uint16_t uid_counter, uint32_t num_items_in_folder) {
+ std::unique_ptr<GetTotalNumberOfItemsResponseBuilder> builder(
+ new GetTotalNumberOfItemsResponseBuilder(status, uid_counter,
+ num_items_in_folder));
+
+ return builder;
+}
+
+size_t GetTotalNumberOfItemsResponseBuilder::size() const {
+ size_t len = BrowsePacket::kMinSize();
+ len += 1; // Status
+
+ if (status_ != Status::NO_ERROR) return len;
+
+ len += 2; // UID Counter
+ len += 4; // Number of items in folder
+ return len;
+}
+
+bool GetTotalNumberOfItemsResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());
+
+ AddPayloadOctets1(pkt, (uint8_t)status_);
+
+ if (status_ != Status::NO_ERROR) return true;
+ AddPayloadOctets2(pkt, base::ByteSwap(uid_counter_));
+ AddPayloadOctets4(pkt, base::ByteSwap(num_items_in_folder_));
+ return true;
+}
+
+Scope GetTotalNumberOfItemsRequest::GetScope() const {
+ auto it = begin() + BrowsePacket::kMinSize();
+ return static_cast<Scope>(*it);
+}
+
+bool GetTotalNumberOfItemsRequest::IsValid() const {
+ if (!BrowsePacket::IsValid()) return false;
+ return size() == kMinSize();
+}
+
+std::string GetTotalNumberOfItemsRequest::ToString() const {
+ std::stringstream ss;
+ ss << "GetTotalNumberOfItemsRequest: " << std::endl;
+ ss << " â”” PDU = " << GetPdu() << std::endl;
+ ss << " â”” Length = " << GetLength() << std::endl;
+ ss << " â”” Scope = " << GetScope() << std::endl;
+ ss << std::endl;
+
+ return ss.str();
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/packet/avrcp/get_total_number_of_items.h b/packet/avrcp/get_total_number_of_items.h
new file mode 100644
index 0000000..51842c9
--- /dev/null
+++ b/packet/avrcp/get_total_number_of_items.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "avrcp_browse_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class GetTotalNumberOfItemsResponseBuilder : public BrowsePacketBuilder {
+ public:
+ virtual ~GetTotalNumberOfItemsResponseBuilder() = default;
+
+ static std::unique_ptr<GetTotalNumberOfItemsResponseBuilder> MakeBuilder(
+ Status status, uint16_t uid_counter, uint32_t num_items_in_folder);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ Status status_;
+ uint16_t uid_counter_;
+ uint32_t num_items_in_folder_;
+
+ GetTotalNumberOfItemsResponseBuilder(Status status, uint16_t uid_counter,
+ uint32_t num_items_in_folder)
+ : BrowsePacketBuilder(BrowsePdu::GET_TOTAL_NUMBER_OF_ITEMS),
+ status_(status),
+ uid_counter_(uid_counter),
+ num_items_in_folder_(num_items_in_folder){};
+};
+
+class GetTotalNumberOfItemsRequest : public BrowsePacket {
+ public:
+ virtual ~GetTotalNumberOfItemsRequest() = default;
+
+ /**
+ * AVRCP Get Total Number Of Items Packet Layout
+ * BrowsePacket:
+ * uint8_t pdu_;
+ * uint16_t length_;
+ * GetTotalNumberOfItemsRequest:
+ * uint8_t scope_;
+ */
+ static constexpr size_t kMinSize() { return BrowsePacket::kMinSize() + 1; }
+
+ Scope GetScope() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using BrowsePacket::BrowsePacket;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/pass_through_packet.cc b/packet/avrcp/pass_through_packet.cc
new file mode 100644
index 0000000..67b8d16
--- /dev/null
+++ b/packet/avrcp/pass_through_packet.cc
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pass_through_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<PassThroughPacketBuilder> PassThroughPacketBuilder::MakeBuilder(
+ bool response, bool pushed, uint8_t opperation_id) {
+ auto builder = std::unique_ptr<PassThroughPacketBuilder>(
+ new PassThroughPacketBuilder(response, pushed, opperation_id));
+
+ return builder;
+}
+
+size_t PassThroughPacketBuilder::size() const {
+ return PassThroughPacket::kMinSize();
+}
+
+bool PassThroughPacketBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ PacketBuilder::PushHeader(pkt);
+
+ uint8_t byte = opperation_id_ & 0b01111111;
+ if (!pushed_) byte |= 0b10000000;
+ AddPayloadOctets1(pkt, byte);
+ // Data length, for this packet it's always 0;
+ AddPayloadOctets1(pkt, 0x00);
+
+ return true;
+}
+
+KeyState PassThroughPacket::GetKeyState() const {
+ auto it = begin() + Packet::kMinSize();
+ return static_cast<KeyState>(((*it) & 0b10000000) >> 7);
+}
+
+uint8_t PassThroughPacket::GetOperationId() const {
+ return *(begin() + Packet::kMinSize()) & 0b01111111;
+}
+
+bool PassThroughPacket::IsValid() const { return size() == kMinSize(); }
+
+std::string PassThroughPacket::ToString() const {
+ std::stringstream ss;
+ ss << "Avrcp::AvrcpPacket: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Pushed = " << GetKeyState() << std::endl;
+ ss << " â”” Opperation ID = " << loghex(GetOperationId()) << std::endl;
+
+ return ss.str();
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/pass_through_packet.h b/packet/avrcp/pass_through_packet.h
new file mode 100644
index 0000000..903b3d8
--- /dev/null
+++ b/packet/avrcp/pass_through_packet.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "avrcp_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class PassThroughPacketBuilder : public PacketBuilder {
+ public:
+ virtual ~PassThroughPacketBuilder() = default;
+
+ static std::unique_ptr<PassThroughPacketBuilder> MakeBuilder(
+ bool response, bool pushed, uint8_t operation_id);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ private:
+ bool pushed_;
+ uint8_t opperation_id_;
+
+ PassThroughPacketBuilder(bool response, bool pushed, uint8_t opperation_id)
+ : PacketBuilder(response ? CType::ACCEPTED : CType::CONTROL, 0x09, 0x00,
+ Opcode::PASS_THROUGH),
+ pushed_(pushed),
+ opperation_id_(opperation_id){};
+};
+
+class PassThroughPacket : public Packet {
+ public:
+ virtual ~PassThroughPacket() = default;
+
+ /**
+ * Pass Through Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * PassThroughPacket:
+ * uint8_t state : 1;
+ * uint8_t opperation_id : 7;
+ * uint8_t data_length;
+ */
+ static constexpr size_t kMinSize() { return Packet::kMinSize() + 2; }
+
+ // Getter Functions
+ KeyState GetKeyState() const;
+ uint8_t GetOperationId() const;
+
+ // Overloaded Functions
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using Packet::Packet;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/play_item.cc b/packet/avrcp/play_item.cc
new file mode 100644
index 0000000..27b242b
--- /dev/null
+++ b/packet/avrcp/play_item.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "play_item.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<PlayItemResponseBuilder> PlayItemResponseBuilder::MakeBuilder(
+ Status status) {
+ std::unique_ptr<PlayItemResponseBuilder> builder(
+ new PlayItemResponseBuilder(status));
+
+ return builder;
+}
+
+size_t PlayItemResponseBuilder::size() const {
+ size_t len = VendorPacket::kMinSize();
+ len += 1; // Status
+ return len;
+}
+
+bool PlayItemResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ PacketBuilder::PushHeader(pkt);
+
+ VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
+
+ AddPayloadOctets1(pkt, (uint8_t)status_);
+
+ return true;
+}
+
+Scope PlayItemRequest::GetScope() const {
+ auto it = begin() + VendorPacket::kMinSize();
+ return static_cast<Scope>(*it);
+}
+
+uint64_t PlayItemRequest::GetUid() const {
+ auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
+ return base::ByteSwap(it.extract<uint64_t>());
+}
+
+uint16_t PlayItemRequest::GetUidCounter() const {
+ auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(9);
+ return base::ByteSwap(it.extract<uint16_t>());
+}
+
+bool PlayItemRequest::IsValid() const {
+ if (!VendorPacket::IsValid()) return false;
+ return size() == kMinSize();
+}
+
+std::string PlayItemRequest::ToString() const {
+ std::stringstream ss;
+ ss << "PlayItemRequest: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Company ID = " << loghex(GetCompanyId()) << std::endl;
+ ss << " â”” Command PDU = " << GetCommandPdu() << std::endl;
+ ss << " â”” PacketType = " << GetPacketType() << std::endl;
+ ss << " â”” Parameter Length = " << loghex(GetParameterLength()) << std::endl;
+ ss << " â”” Scope = " << GetScope() << std::endl;
+ ss << " â”” UID = " << loghex(GetUid()) << std::endl;
+ ss << " â”” UID Counter = " << loghex(GetUidCounter()) << std::endl;
+ ss << std::endl;
+
+ return ss.str();
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/play_item.h b/packet/avrcp/play_item.h
new file mode 100644
index 0000000..e1c2d48
--- /dev/null
+++ b/packet/avrcp/play_item.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "vendor_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class PlayItemResponseBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~PlayItemResponseBuilder() = default;
+
+ static std::unique_ptr<PlayItemResponseBuilder> MakeBuilder(Status status);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ Status status_;
+
+ PlayItemResponseBuilder(Status status)
+ : VendorPacketBuilder(CType::ACCEPTED, CommandPdu::PLAY_ITEM,
+ PacketType::SINGLE),
+ status_(status){};
+};
+
+class PlayItemRequest : public VendorPacket {
+ public:
+ virtual ~PlayItemRequest() = default;
+
+ /**
+ * AVRCP Play Item Request Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t parameter_length;
+ * PlayItemRequest:
+ * uint8_t scope_;
+ * uint64_t uid_;
+ * uint16_t uid_counter_;
+ */
+ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 11; }
+
+ Scope GetScope() const;
+ uint64_t GetUid() const;
+ uint16_t GetUidCounter() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using VendorPacket::VendorPacket;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/register_notification_packet.cc b/packet/avrcp/register_notification_packet.cc
new file mode 100644
index 0000000..86115e1
--- /dev/null
+++ b/packet/avrcp/register_notification_packet.cc
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/logging.h>
+
+#include "register_notification_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+bool RegisterNotificationResponse::IsInterim() const {
+ return GetCType() == CType::INTERIM;
+}
+
+Event RegisterNotificationResponse::GetEvent() const {
+ auto value = *(begin() + VendorPacket::kMinSize());
+ return static_cast<Event>(value);
+}
+
+uint8_t RegisterNotificationResponse::GetVolume() const {
+ CHECK(GetEvent() == Event::VOLUME_CHANGED);
+ auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
+ return *it;
+}
+
+bool RegisterNotificationResponse::IsValid() const {
+ if (!VendorPacket::IsValid()) return false;
+ if (size() < kMinSize()) return false;
+ if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED)
+ return false;
+
+ switch (GetEvent()) {
+ case Event::VOLUME_CHANGED:
+ return size() == (kMinSize() + 1);
+ default:
+ // TODO (apanicke): Add the remaining events when implementing AVRCP
+ // Controller
+ return false;
+ }
+}
+
+std::string RegisterNotificationResponse::ToString() const {
+ std::stringstream ss;
+ ss << "RegisterNotificationResponse: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Company ID = " << loghex(GetCompanyId()) << std::endl;
+ ss << " â”” Command PDU = " << GetCommandPdu() << std::endl;
+ ss << " â”” PacketType = " << GetPacketType() << std::endl;
+ ss << " â”” Parameter Length = " << loghex(GetParameterLength()) << std::endl;
+ ss << " â”” Event Registered = " << GetEvent() << std::endl;
+ ss << std::endl;
+
+ return ss.str();
+}
+
+std::unique_ptr<RegisterNotificationResponseBuilder>
+RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
+ bool interim, uint8_t play_status) {
+ std::unique_ptr<RegisterNotificationResponseBuilder> builder(
+ new RegisterNotificationResponseBuilder(interim,
+ Event::PLAYBACK_STATUS_CHANGED));
+
+ builder->data_ = play_status;
+ return builder;
+}
+
+std::unique_ptr<RegisterNotificationResponseBuilder>
+RegisterNotificationResponseBuilder::MakeTrackChangedBuilder(
+ bool interim, uint64_t track_uid) {
+ std::unique_ptr<RegisterNotificationResponseBuilder> builder(
+ new RegisterNotificationResponseBuilder(interim, Event::TRACK_CHANGED));
+
+ builder->data_ = track_uid;
+ return builder;
+}
+
+std::unique_ptr<RegisterNotificationResponseBuilder>
+RegisterNotificationResponseBuilder::MakePlaybackPositionBuilder(
+ bool interim, uint32_t playback_pos) {
+ std::unique_ptr<RegisterNotificationResponseBuilder> builder(
+ new RegisterNotificationResponseBuilder(interim,
+ Event::PLAYBACK_POS_CHANGED));
+
+ builder->data_ = playback_pos;
+ return builder;
+}
+
+std::unique_ptr<RegisterNotificationResponseBuilder>
+RegisterNotificationResponseBuilder::MakeNowPlayingBuilder(bool interim) {
+ std::unique_ptr<RegisterNotificationResponseBuilder> builder(
+ new RegisterNotificationResponseBuilder(
+ interim, Event::NOW_PLAYING_CONTENT_CHANGED));
+ return builder;
+}
+
+std::unique_ptr<RegisterNotificationResponseBuilder>
+RegisterNotificationResponseBuilder::MakeAvailablePlayersBuilder(bool interim) {
+ std::unique_ptr<RegisterNotificationResponseBuilder> builder(
+ new RegisterNotificationResponseBuilder(
+ interim, Event::AVAILABLE_PLAYERS_CHANGED));
+ return builder;
+}
+
+std::unique_ptr<RegisterNotificationResponseBuilder>
+RegisterNotificationResponseBuilder::MakeAddressedPlayerBuilder(
+ bool interim, uint16_t player_id, uint16_t uid_counter) {
+ std::unique_ptr<RegisterNotificationResponseBuilder> builder(
+ new RegisterNotificationResponseBuilder(interim,
+ Event::ADDRESSED_PLAYER_CHANGED));
+ builder->data_ = ((uint32_t)player_id) << 16;
+ builder->data_ |= uid_counter;
+ return builder;
+}
+
+std::unique_ptr<RegisterNotificationResponseBuilder>
+RegisterNotificationResponseBuilder::MakeUidsChangedBuilder(
+ bool interim, uint16_t uid_counter) {
+ std::unique_ptr<RegisterNotificationResponseBuilder> builder(
+ new RegisterNotificationResponseBuilder(interim, Event::UIDS_CHANGED));
+
+ builder->data_ = uid_counter;
+ return builder;
+}
+
+size_t RegisterNotificationResponseBuilder::size() const {
+ size_t data_size = 0;
+
+ // We specifically avoid having a default case here in order to ensure that
+ // there is an error in case an event isn't handled.
+ switch (event_) {
+ case Event::PLAYBACK_STATUS_CHANGED:
+ data_size = 1;
+ break;
+ case Event::TRACK_CHANGED:
+ data_size = 8;
+ break;
+ case Event::PLAYBACK_POS_CHANGED:
+ data_size = 4;
+ break;
+ case Event::PLAYER_APPLICATION_SETTING_CHANGED:
+ LOG(FATAL) << "Player Application Notification Not Implemented";
+ break;
+ case Event::NOW_PLAYING_CONTENT_CHANGED:
+ data_size = 0;
+ break;
+ case Event::AVAILABLE_PLAYERS_CHANGED:
+ data_size = 0;
+ break;
+ case Event::ADDRESSED_PLAYER_CHANGED:
+ data_size = 4;
+ break;
+ case Event::UIDS_CHANGED:
+ data_size = 2;
+ break;
+ case Event::VOLUME_CHANGED:
+ LOG(FATAL) << "Volume Changed Notification Not Implemented";
+ break;
+ }
+
+ return VendorPacket::kMinSize() + 1 + data_size;
+}
+
+bool RegisterNotificationResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ PacketBuilder::PushHeader(pkt);
+
+ VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
+
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(event_));
+ switch (event_) {
+ case Event::PLAYBACK_STATUS_CHANGED: {
+ uint8_t playback_status = data_ & 0xFF;
+ AddPayloadOctets1(pkt, playback_status);
+ break;
+ }
+ case Event::TRACK_CHANGED: {
+ AddPayloadOctets8(pkt, base::ByteSwap(data_));
+ break;
+ }
+ case Event::PLAYBACK_POS_CHANGED: {
+ uint32_t playback_pos = data_ & 0xFFFFFFFF;
+ AddPayloadOctets4(pkt, base::ByteSwap(playback_pos));
+ break;
+ }
+ case Event::PLAYER_APPLICATION_SETTING_CHANGED:
+ break; // No additional data
+ case Event::NOW_PLAYING_CONTENT_CHANGED:
+ break; // No additional data
+ case Event::AVAILABLE_PLAYERS_CHANGED:
+ break; // No additional data
+ case Event::ADDRESSED_PLAYER_CHANGED: {
+ uint16_t uid_counter = data_ & 0xFFFF;
+ uint16_t player_id = (data_ >> 16) & 0xFFFF;
+ AddPayloadOctets2(pkt, base::ByteSwap(player_id));
+ AddPayloadOctets2(pkt, base::ByteSwap(uid_counter));
+ break;
+ }
+ case Event::UIDS_CHANGED: {
+ uint16_t uid_counter = data_ & 0xFFFF;
+ AddPayloadOctets2(pkt, base::ByteSwap(uid_counter));
+ break;
+ }
+ case Event::VOLUME_CHANGED:
+ // TODO (apanicke): Add Volume Changed builder for when we are controller.
+ LOG(FATAL) << "Volume Changed Notification Not Implemented";
+ break;
+ }
+
+ return true;
+}
+
+Event RegisterNotificationRequest::GetEventRegistered() const {
+ auto value = *(begin() + VendorPacket::kMinSize());
+ return static_cast<Event>(value);
+}
+
+uint32_t RegisterNotificationRequest::GetInterval() const {
+ auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
+ return base::ByteSwap(it.extract<uint32_t>());
+}
+
+bool RegisterNotificationRequest::IsValid() const {
+ return (size() == kMinSize());
+}
+
+std::string RegisterNotificationRequest::ToString() const {
+ std::stringstream ss;
+ ss << "RegisterNotificationPacket: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Company ID = " << loghex(GetCompanyId()) << std::endl;
+ ss << " â”” Command PDU = " << GetCommandPdu() << std::endl;
+ ss << " â”” PacketType = " << GetPacketType() << std::endl;
+ ss << " â”” Parameter Length = " << loghex(GetParameterLength()) << std::endl;
+ ss << " â”” Event Registered = " << GetEventRegistered() << std::endl;
+ ss << " â”” Interval = " << loghex(GetInterval()) << std::endl;
+ ss << std::endl;
+
+ return ss.str();
+}
+
+std::unique_ptr<RegisterNotificationRequestBuilder>
+RegisterNotificationRequestBuilder::MakeBuilder(Event event,
+ uint32_t interval) {
+ std::unique_ptr<RegisterNotificationRequestBuilder> builder(
+ new RegisterNotificationRequestBuilder(event, interval));
+
+ return builder;
+}
+
+size_t RegisterNotificationRequestBuilder::size() const {
+ return RegisterNotificationRequest::kMinSize();
+}
+
+bool RegisterNotificationRequestBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ PacketBuilder::PushHeader(pkt);
+
+ VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
+
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(event_));
+
+ AddPayloadOctets4(pkt, base::ByteSwap(interval_));
+
+ return true;
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/register_notification_packet.h b/packet/avrcp/register_notification_packet.h
new file mode 100644
index 0000000..53286c4
--- /dev/null
+++ b/packet/avrcp/register_notification_packet.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "vendor_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class RegisterNotificationResponse : public VendorPacket {
+ public:
+ virtual ~RegisterNotificationResponse() = default;
+
+ /**
+ * Register Notificaiton Request Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t param_length;
+ * RegisterNotificationRequestPacket:
+ * uint8_t event_id;
+ * uint8_t[] data; // Length changes based on the event_id
+ */
+ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 1; }
+
+ // TODO (apanicke): Add other getters when implementing AVRCP Controller
+ bool IsInterim() const;
+ Event GetEvent() const;
+ uint8_t GetVolume() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using VendorPacket::VendorPacket;
+};
+
+class RegisterNotificationResponseBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~RegisterNotificationResponseBuilder() = default;
+
+ static std::unique_ptr<RegisterNotificationResponseBuilder>
+ MakePlaybackStatusBuilder(bool interim, uint8_t play_status);
+
+ static std::unique_ptr<RegisterNotificationResponseBuilder>
+ MakeTrackChangedBuilder(bool interim, uint64_t track_uid);
+
+ static std::unique_ptr<RegisterNotificationResponseBuilder>
+ MakePlaybackPositionBuilder(bool interim, uint32_t playback_pos);
+
+ static std::unique_ptr<RegisterNotificationResponseBuilder>
+ MakeNowPlayingBuilder(bool interim);
+
+ static std::unique_ptr<RegisterNotificationResponseBuilder>
+ MakeAvailablePlayersBuilder(bool interim);
+
+ static std::unique_ptr<RegisterNotificationResponseBuilder>
+ MakeAddressedPlayerBuilder(bool interim, uint16_t player_id,
+ uint16_t uid_counter);
+
+ static std::unique_ptr<RegisterNotificationResponseBuilder>
+ MakeUidsChangedBuilder(bool interim, uint16_t uid_counter);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ Event event_;
+ uint64_t data_;
+
+ RegisterNotificationResponseBuilder(bool interim, Event event)
+ : VendorPacketBuilder(interim ? CType::INTERIM : CType::CHANGED,
+ CommandPdu::REGISTER_NOTIFICATION,
+ PacketType::SINGLE),
+ event_(event){};
+};
+
+class RegisterNotificationRequest : public VendorPacket {
+ public:
+ virtual ~RegisterNotificationRequest() = default;
+
+ /**
+ * Register Notificaiton Request Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t param_length;
+ * RegisterNotificationRequestPacket:
+ * uint8_t event_id;
+ * uint32_t interval; // Only used for PLAYBACK_POS_CHANGED
+ */
+ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 5; }
+
+ // Getter Functions
+ Event GetEventRegistered() const;
+ uint32_t GetInterval() const;
+
+ // Overloaded Functions
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using VendorPacket::VendorPacket;
+};
+
+class RegisterNotificationRequestBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~RegisterNotificationRequestBuilder() = default;
+
+ static std::unique_ptr<RegisterNotificationRequestBuilder> MakeBuilder(
+ Event event, uint32_t interval);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ Event event_;
+ uint32_t interval_;
+
+ RegisterNotificationRequestBuilder(Event event, uint32_t interval)
+ : VendorPacketBuilder(CType::NOTIFY, CommandPdu::REGISTER_NOTIFICATION,
+ PacketType::SINGLE),
+ event_(event),
+ interval_(interval){};
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/set_absolute_volume.cc b/packet/avrcp/set_absolute_volume.cc
new file mode 100644
index 0000000..ff6b7ac
--- /dev/null
+++ b/packet/avrcp/set_absolute_volume.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "set_absolute_volume.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<SetAbsoluteVolumeRequestBuilder>
+SetAbsoluteVolumeRequestBuilder::MakeBuilder(uint8_t volume) {
+ std::unique_ptr<SetAbsoluteVolumeRequestBuilder> builder(
+ new SetAbsoluteVolumeRequestBuilder(volume & 0x7F));
+
+ return builder;
+}
+
+size_t SetAbsoluteVolumeRequestBuilder::size() const {
+ return VendorPacket::kMinSize() + 1;
+}
+
+bool SetAbsoluteVolumeRequestBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ PacketBuilder::PushHeader(pkt);
+
+ VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
+
+ AddPayloadOctets1(pkt, volume_);
+
+ return true;
+}
+
+uint8_t SetAbsoluteVolumeResponse::GetVolume() const {
+ auto it = begin() + VendorPacket::kMinSize();
+ return *it;
+}
+
+bool SetAbsoluteVolumeResponse::IsValid() const {
+ if (!VendorPacket::IsValid()) return false;
+ if (GetCType() != CType::ACCEPTED) return false;
+ return size() == kMinSize();
+}
+
+std::string SetAbsoluteVolumeResponse::ToString() const {
+ std::stringstream ss;
+ ss << "SetAbsoluteVolumeResponse: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Company ID = " << loghex(GetCompanyId()) << std::endl;
+ ss << " â”” Command PDU = " << GetCommandPdu() << std::endl;
+ ss << " â”” PacketType = " << GetPacketType() << std::endl;
+ ss << " â”” Parameter Length = " << loghex(GetParameterLength()) << std::endl;
+ ss << " â”” Volume = " << GetVolume() << std::endl;
+ ss << std::endl;
+
+ return ss.str();
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/set_absolute_volume.h b/packet/avrcp/set_absolute_volume.h
new file mode 100644
index 0000000..48cd388
--- /dev/null
+++ b/packet/avrcp/set_absolute_volume.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "vendor_packet.h"
+
+// TODO (apanicke): Set Absolute Volume request vs response have the same
+// packet structure, the only difference between the two is the CType.
+// Adding a passed flag as a parameter would be possible but I feel that
+// this would break the design pattern of request vs response. Look into
+// this for the future.
+
+namespace bluetooth {
+namespace avrcp {
+
+class SetAbsoluteVolumeRequestBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~SetAbsoluteVolumeRequestBuilder() = default;
+
+ static std::unique_ptr<SetAbsoluteVolumeRequestBuilder> MakeBuilder(
+ uint8_t volume);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ uint8_t volume_;
+
+ SetAbsoluteVolumeRequestBuilder(uint8_t volume)
+ : VendorPacketBuilder(CType::CONTROL, CommandPdu::SET_ABSOLUTE_VOLUME,
+ PacketType::SINGLE),
+ volume_(volume){};
+};
+
+class SetAbsoluteVolumeResponse : public VendorPacket {
+ public:
+ virtual ~SetAbsoluteVolumeResponse() = default;
+
+ /**
+ * AVRCP Play Item Request Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t parameter_length;
+ * SetAbsoluteVolumeResponse:
+ * uint8_t volume;
+ */
+ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 1; }
+
+ uint8_t GetVolume() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using VendorPacket::VendorPacket;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/set_addressed_player.cc b/packet/avrcp/set_addressed_player.cc
new file mode 100644
index 0000000..f4b4ddd
--- /dev/null
+++ b/packet/avrcp/set_addressed_player.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "set_addressed_player.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<SetAddressedPlayerResponseBuilder>
+SetAddressedPlayerResponseBuilder::MakeBuilder(Status status) {
+ std::unique_ptr<SetAddressedPlayerResponseBuilder> builder(
+ new SetAddressedPlayerResponseBuilder(status));
+
+ return builder;
+}
+
+size_t SetAddressedPlayerResponseBuilder::size() const {
+ size_t len = VendorPacket::kMinSize();
+ len += 1; // Status
+ return len;
+}
+
+bool SetAddressedPlayerResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ PacketBuilder::PushHeader(pkt);
+
+ VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
+
+ AddPayloadOctets1(pkt, (uint8_t)status_);
+
+ return true;
+}
+
+uint16_t SetAddressedPlayerRequest::GetPlayerId() const {
+ auto it = begin() + VendorPacket::kMinSize();
+ return base::ByteSwap(it.extract<uint16_t>());
+}
+
+bool SetAddressedPlayerRequest::IsValid() const {
+ if (!VendorPacket::IsValid()) return false;
+ return size() == kMinSize();
+}
+
+std::string SetAddressedPlayerRequest::ToString() const {
+ std::stringstream ss;
+ ss << "SetAddressedPlayerRequest: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Company ID = " << loghex(GetCompanyId()) << std::endl;
+ ss << " â”” Command PDU = " << GetCommandPdu() << std::endl;
+ ss << " â”” PacketType = " << GetPacketType() << std::endl;
+ ss << " â”” Parameter Length = " << loghex(GetParameterLength()) << std::endl;
+ ss << " â”” Player ID = " << loghex(GetPlayerId()) << std::endl;
+ ss << std::endl;
+
+ return ss.str();
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/set_addressed_player.h b/packet/avrcp/set_addressed_player.h
new file mode 100644
index 0000000..8234116
--- /dev/null
+++ b/packet/avrcp/set_addressed_player.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "vendor_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class SetAddressedPlayerResponseBuilder : public VendorPacketBuilder {
+ public:
+ virtual ~SetAddressedPlayerResponseBuilder() = default;
+
+ static std::unique_ptr<SetAddressedPlayerResponseBuilder> MakeBuilder(
+ Status status);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ Status status_;
+
+ SetAddressedPlayerResponseBuilder(Status status)
+ : VendorPacketBuilder(CType::ACCEPTED, CommandPdu::SET_ADDRESSED_PLAYER,
+ PacketType::SINGLE),
+ status_(status){};
+};
+
+class SetAddressedPlayerRequest : public VendorPacket {
+ public:
+ virtual ~SetAddressedPlayerRequest() = default;
+
+ /**
+ * Register Notificaiton Request Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t param_length;
+ * SetAddressedPlayerRequest:
+ * uint16_t player_id;
+ */
+ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 2; }
+
+ uint16_t GetPlayerId() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using VendorPacket::VendorPacket;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/set_browsed_player.cc b/packet/avrcp/set_browsed_player.cc
new file mode 100644
index 0000000..b8463fa
--- /dev/null
+++ b/packet/avrcp/set_browsed_player.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "set_browsed_player.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<SetBrowsedPlayerResponseBuilder>
+SetBrowsedPlayerResponseBuilder::MakeBuilder(Status status,
+ uint16_t uid_counter,
+ uint32_t num_items_in_folder,
+ uint8_t folder_depth,
+ std::string folder_name) {
+ std::unique_ptr<SetBrowsedPlayerResponseBuilder> builder(
+ new SetBrowsedPlayerResponseBuilder(
+ status, uid_counter, num_items_in_folder, folder_depth, folder_name));
+
+ return builder;
+}
+
+size_t SetBrowsedPlayerResponseBuilder::size() const {
+ size_t len = BrowsePacket::kMinSize();
+ len += 1; // Status
+
+ // If the status isn't success the rest of the fields are ommited
+ if (status_ != Status::NO_ERROR) return len;
+
+ len += 2; // UID Counter
+ len += 4; // Number of items in folder
+ len += 2; // UTF-8 Character Set
+ len += 1; // Folder Depth
+
+ // This is only included if the folder returned isn't the root folder
+ if (folder_depth_ != 0) {
+ len += 2; // Folder Name Size;
+ len += folder_name_.size(); // Folder Name
+ }
+
+ return len;
+}
+
+bool SetBrowsedPlayerResponseBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());
+
+ AddPayloadOctets1(pkt, (uint8_t)status_);
+
+ if (status_ != Status::NO_ERROR) return true;
+ AddPayloadOctets2(pkt, base::ByteSwap(uid_counter_));
+ AddPayloadOctets4(pkt, base::ByteSwap(num_items_in_folder_));
+ AddPayloadOctets2(pkt, base::ByteSwap((uint16_t)0x006a)); // UTF-8
+ AddPayloadOctets1(pkt, folder_depth_);
+
+ // Skip adding the folder name if the folder depth is 0
+ if (folder_depth_ == 0) return true;
+ uint16_t folder_name_len = folder_name_.size();
+ AddPayloadOctets2(pkt, base::ByteSwap(folder_name_len));
+ for (auto it = folder_name_.begin(); it != folder_name_.end(); it++) {
+ AddPayloadOctets1(pkt, *it);
+ }
+
+ return true;
+}
+
+uint16_t SetBrowsedPlayerRequest::GetPlayerId() const {
+ auto it = begin() + BrowsePacket::kMinSize();
+ return base::ByteSwap(it.extract<uint16_t>());
+}
+
+bool SetBrowsedPlayerRequest::IsValid() const {
+ if (!BrowsePacket::IsValid()) return false;
+ return size() == kMinSize();
+}
+
+std::string SetBrowsedPlayerRequest::ToString() const {
+ std::stringstream ss;
+ ss << "SetBrowsedPlayerRequestPacket: " << std::endl;
+ ss << " â”” PDU = " << GetPdu() << std::endl;
+ ss << " â”” Length = " << GetLength() << std::endl;
+ ss << " â”” Player ID = " << loghex(GetPlayerId()) << std::endl;
+ ss << std::endl;
+
+ return ss.str();
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/set_browsed_player.h b/packet/avrcp/set_browsed_player.h
new file mode 100644
index 0000000..336c4e1
--- /dev/null
+++ b/packet/avrcp/set_browsed_player.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "avrcp_browse_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class SetBrowsedPlayerResponseBuilder : public BrowsePacketBuilder {
+ public:
+ virtual ~SetBrowsedPlayerResponseBuilder() = default;
+
+ static std::unique_ptr<SetBrowsedPlayerResponseBuilder> MakeBuilder(
+ Status status, uint16_t uid_counter, uint32_t num_items_in_folder,
+ uint8_t folder_depth, std::string folder_name);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ Status status_;
+ uint16_t uid_counter_;
+ uint32_t num_items_in_folder_;
+ uint8_t folder_depth_;
+ std::string folder_name_;
+
+ SetBrowsedPlayerResponseBuilder(Status status, uint16_t uid_counter,
+ uint32_t num_items_in_folder,
+ uint8_t folder_depth, std::string folder_name)
+ : BrowsePacketBuilder(BrowsePdu::SET_BROWSED_PLAYER),
+ status_(status),
+ uid_counter_(uid_counter),
+ num_items_in_folder_(num_items_in_folder),
+ folder_depth_(folder_depth),
+ folder_name_(folder_name) {}
+};
+
+class SetBrowsedPlayerRequest : public BrowsePacket {
+ public:
+ virtual ~SetBrowsedPlayerRequest() = default;
+
+ /**
+ * Avrcp Change Path Packet Layout
+ * BrowsePacket:
+ * uint8_t pdu_;
+ * uint16_t length_;
+ * GetFolderItemsRequest:
+ * uint16_t player_id_;
+ */
+ static constexpr size_t kMinSize() { return BrowsePacket::kMinSize() + 2; }
+
+ uint16_t GetPlayerId() const;
+
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using BrowsePacket::BrowsePacket;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/vendor_packet.cc b/packet/avrcp/vendor_packet.cc
new file mode 100644
index 0000000..982cf81
--- /dev/null
+++ b/packet/avrcp/vendor_packet.cc
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "vendor_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+std::unique_ptr<VendorPacketBuilder> VendorPacketBuilder::MakeBuilder(
+ CType ctype, CommandPdu pdu, PacketType packet_type,
+ std::unique_ptr<::bluetooth::PacketBuilder> payload) {
+ // If the payload size is greater than max uint16_t
+ // the packet should be fragmented
+ CHECK_LE(payload->size(), size_t(0xFFFF))
+ << __func__ << ": payload size bigger than uint16_t";
+
+ std::unique_ptr<VendorPacketBuilder> builder(
+ new VendorPacketBuilder(ctype, pdu, packet_type));
+ builder->payload_ = std::move(payload);
+
+ return builder;
+}
+
+size_t VendorPacketBuilder::size() const {
+ return VendorPacket::kMinSize() + payload_->size();
+}
+
+bool VendorPacketBuilder::Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) {
+ ReserveSpace(pkt, size());
+
+ // Push the standard avrcp headers
+ PacketBuilder::PushHeader(pkt);
+
+ // Push the avrcp vendor command headers
+ CHECK_LT(payload_->size(), size_t(0xFFFF))
+ << __func__ << ": payload size bigger than uint16_t";
+ PushHeader(pkt, payload_->size());
+
+ // Push the payload for the packet
+ return payload_->Serialize(pkt);
+}
+
+void VendorPacketBuilder::PushHeader(
+ const std::shared_ptr<::bluetooth::Packet>& pkt,
+ uint16_t parameter_length) {
+ PushCompanyId(pkt, BLUETOOTH_COMPANY_ID);
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(pdu_));
+ AddPayloadOctets1(pkt, static_cast<uint8_t>(packet_type_));
+ AddPayloadOctets2(pkt, base::ByteSwap(parameter_length));
+}
+
+bool VendorPacketBuilder::PushAttributeValue(
+ const std::shared_ptr<::bluetooth::Packet>& pkt,
+ const AttributeEntry& entry) {
+ AddPayloadOctets4(pkt,
+ base::ByteSwap(static_cast<uint32_t>(entry.attribute())));
+ uint16_t character_set = 0x006a; // UTF-8
+ AddPayloadOctets2(pkt, base::ByteSwap(character_set));
+ uint16_t value_length = entry.value().length();
+ AddPayloadOctets2(pkt, base::ByteSwap(value_length));
+ for (int i = 0; i < value_length; i++) {
+ AddPayloadOctets1(pkt, entry.value()[i]);
+ }
+
+ return true;
+}
+
+uint32_t VendorPacket::GetCompanyId() const {
+ return PullCompanyId(begin() + Packet::kMinSize());
+}
+
+CommandPdu VendorPacket::GetCommandPdu() const {
+ auto value = *(begin() + Packet::kMinSize() + static_cast<size_t>(3));
+ return static_cast<CommandPdu>(value);
+}
+
+PacketType VendorPacket::GetPacketType() const {
+ auto value = *(begin() + Packet::kMinSize() + static_cast<size_t>(4));
+ return static_cast<PacketType>(value);
+}
+
+uint16_t VendorPacket::GetParameterLength() const {
+ auto it = begin() + Packet::kMinSize() + static_cast<size_t>(5);
+ // Swap to little endian
+ return base::ByteSwap(it.extract<uint16_t>());
+}
+
+bool VendorPacket::IsValid() const {
+ if (size() < VendorPacket::kMinSize()) return false;
+
+ auto start = begin() + VendorPacket::kMinSize();
+ // Even if end is less than start and a sign extension occurs, thats fine as
+ // its pretty definitive proof that the packet is poorly formated
+ return GetParameterLength() == (end() - start);
+}
+
+std::string VendorPacket::ToString() const {
+ std::stringstream ss;
+ ss << "VendorPacket: " << std::endl;
+ ss << " â”” cType = " << GetCType() << std::endl;
+ ss << " â”” Subunit Type = " << loghex(GetSubunitType()) << std::endl;
+ ss << " â”” Subunit ID = " << loghex(GetSubunitId()) << std::endl;
+ ss << " â”” OpCode = " << GetOpcode() << std::endl;
+ ss << " â”” Company ID = " << loghex(GetCompanyId()) << std::endl;
+ ss << " â”” Command PDU = " << GetCommandPdu() << std::endl;
+ ss << " â”” PacketType = " << GetPacketType() << std::endl;
+ ss << " â”” Parameter Length = " << loghex(GetParameterLength()) << std::endl;
+ ss << " â”” Payload =";
+ for (auto it = begin(); it != end(); it++) {
+ ss << " " << loghex(*it);
+ }
+ ss << std::endl;
+ return ss.str();
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/avrcp/vendor_packet.h b/packet/avrcp/vendor_packet.h
new file mode 100644
index 0000000..b9e1f10
--- /dev/null
+++ b/packet/avrcp/vendor_packet.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "avrcp_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+class VendorPacketBuilder : public avrcp::PacketBuilder {
+ public:
+ virtual ~VendorPacketBuilder() = default;
+
+ static std::unique_ptr<VendorPacketBuilder> MakeBuilder(
+ CType ctype, CommandPdu pdu, PacketType packet_type,
+ std::unique_ptr<::bluetooth::PacketBuilder> payload);
+
+ virtual size_t size() const override;
+ virtual bool Serialize(
+ const std::shared_ptr<::bluetooth::Packet>& pkt) override;
+
+ protected:
+ CommandPdu pdu_;
+ PacketType packet_type_;
+ uint16_t param_length_;
+
+ void PushHeader(const std::shared_ptr<::bluetooth::Packet>& pkt,
+ uint16_t parameter_length);
+
+ // Helper function used a couple other AVRCP packet builders
+ bool PushAttributeValue(const std::shared_ptr<::bluetooth::Packet>& pkt,
+ const AttributeEntry& entry);
+
+ VendorPacketBuilder(CType ctype, CommandPdu pdu, PacketType packet_type)
+ : PacketBuilder(ctype, 0x09, 0x00, Opcode::VENDOR),
+ pdu_(pdu),
+ packet_type_(packet_type){};
+};
+
+class VendorPacket : public avrcp::Packet {
+ public:
+ virtual ~VendorPacket() = default;
+
+ /**
+ * Avrcp Vendor Packet Layout
+ * AvrcpPacket:
+ * CType c_type_;
+ * uint8_t subunit_type_ : 5;
+ * uint8_t subunit_id_ : 3;
+ * Opcode opcode_;
+ * VendorPacket:
+ * uint8_t company_id[3];
+ * uint8_t command_pdu;
+ * uint8_t packet_type;
+ * uint16_t parameter_length;
+ * uint8_t[] payload;
+ */
+ static constexpr size_t kMinSize() { return Packet::kMinSize() + 7; };
+
+ // Getter Functions
+ uint32_t GetCompanyId() const;
+ CommandPdu GetCommandPdu() const;
+ PacketType GetPacketType() const;
+ uint16_t GetParameterLength() const;
+
+ // Overloaded functions
+ virtual bool IsValid() const override;
+ virtual std::string ToString() const override;
+
+ protected:
+ using Packet::Packet;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/base/Android.bp b/packet/base/Android.bp
new file mode 100644
index 0000000..67f77d6
--- /dev/null
+++ b/packet/base/Android.bp
@@ -0,0 +1,11 @@
+cc_library_static {
+ name: "lib-bt-packets-base",
+ defaults: ["libchrome_support_defaults"],
+ export_include_dirs: ["./"],
+ host_supported: true,
+ srcs: [
+ "packet.cc",
+ "iterator.cc",
+ "packet_builder.cc",
+ ],
+}
diff --git a/packet/base/iterator.cc b/packet/base/iterator.cc
new file mode 100644
index 0000000..b2c1c23
--- /dev/null
+++ b/packet/base/iterator.cc
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "iterator.h"
+
+#include <base/logging.h>
+
+#include "packet.h"
+
+namespace bluetooth {
+
+Iterator::Iterator(std::shared_ptr<const Packet> packet, size_t i) {
+ packet_ = packet;
+ index_ = i;
+
+ CHECK_GE(index_, packet->packet_start_index_);
+ CHECK_LE(index_, packet->packet_end_index_);
+}
+
+Iterator::Iterator(const Iterator& itr) { *this = itr; }
+
+Iterator Iterator::operator+(size_t offset) {
+ auto itr(*this);
+
+ return itr += offset;
+}
+
+Iterator& Iterator::operator+=(size_t offset) {
+ size_t new_offset = index_ + offset;
+ index_ = new_offset > packet_->packet_end_index_ ? packet_->packet_end_index_
+ : new_offset;
+ return *this;
+}
+
+Iterator Iterator::operator++(int) {
+ auto itr(*this);
+ index_++;
+
+ if (index_ > packet_->packet_end_index_) index_ = packet_->packet_end_index_;
+
+ return itr;
+}
+
+Iterator& Iterator::operator++() {
+ index_++;
+
+ if (index_ > packet_->packet_end_index_) index_ = packet_->packet_end_index_;
+
+ return *this;
+}
+
+Iterator Iterator::operator-(size_t offset) {
+ auto itr(*this);
+
+ return itr -= offset;
+}
+
+int Iterator::operator-(const Iterator& itr) { return index_ - itr.index_; }
+
+Iterator& Iterator::operator-=(size_t offset) {
+ index_ = (index_ < offset || index_ - offset < packet_->packet_start_index_)
+ ? packet_->packet_start_index_
+ : index_ - offset;
+
+ return *this;
+}
+
+Iterator Iterator::operator--(int) {
+ auto itr(*this);
+ if (index_ != packet_->packet_start_index_) index_--;
+
+ return itr;
+}
+
+Iterator& Iterator::operator--() {
+ if (index_ != packet_->packet_start_index_) index_--;
+
+ return *this;
+}
+
+Iterator& Iterator::operator=(const Iterator& itr) {
+ packet_ = itr.packet_;
+ index_ = itr.index_;
+
+ return *this;
+}
+
+bool Iterator::operator==(const Iterator& itr) const {
+ return ((packet_ == itr.packet_) && (index_ == itr.index_));
+}
+
+bool Iterator::operator!=(const Iterator& itr) const { return !(*this == itr); }
+
+bool Iterator::operator<(const Iterator& itr) const {
+ return ((packet_ == itr.packet_) && (index_ < itr.index_));
+}
+
+bool Iterator::operator>(const Iterator& itr) const {
+ return ((packet_ == itr.packet_) && (index_ > itr.index_));
+}
+
+bool Iterator::operator<=(const Iterator& itr) const {
+ return ((packet_ == itr.packet_) && (index_ <= itr.index_));
+}
+
+bool Iterator::operator>=(const Iterator& itr) const {
+ return ((packet_ == itr.packet_) && (index_ >= itr.index_));
+}
+
+uint8_t Iterator::operator*() const {
+ CHECK_NE(index_, packet_->packet_end_index_);
+
+ return packet_->get_at_index(index_);
+}
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/base/iterator.h b/packet/base/iterator.h
new file mode 100644
index 0000000..c4ad32c
--- /dev/null
+++ b/packet/base/iterator.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <iterator>
+#include <memory>
+
+namespace bluetooth {
+
+// Forward declare Packet class
+class Packet;
+
+// Iterator is a custom iterator class for Packets.
+class Iterator
+ : public std::iterator<std::random_access_iterator_tag, uint8_t> {
+ public:
+ Iterator(std::shared_ptr<const Packet> packet, size_t i);
+ Iterator(const Iterator& itr);
+
+ // All addition and subtraction operators are bounded from 0 to the length of
+ // the packet.
+ Iterator operator+(size_t offset);
+ Iterator& operator+=(size_t offset);
+ Iterator operator++(int);
+ Iterator& operator++();
+
+ Iterator operator-(size_t offset);
+ int operator-(const Iterator& itr);
+ Iterator& operator-=(size_t offset);
+ Iterator operator--(int);
+ Iterator& operator--();
+
+ Iterator& operator=(const Iterator& itr);
+
+ bool operator!=(const Iterator& itr) const;
+ bool operator==(const Iterator& itr) const;
+
+ bool operator<(const Iterator& itr) const;
+ bool operator>(const Iterator& itr) const;
+
+ bool operator<=(const Iterator& itr) const;
+ bool operator>=(const Iterator& itr) const;
+
+ uint8_t operator*() const;
+
+ template <typename FixedWidthIntegerType>
+ FixedWidthIntegerType extract() {
+ static_assert(std::is_integral<FixedWidthIntegerType>::value,
+ "Iterator::extract requires an integral type.");
+
+ FixedWidthIntegerType extracted_value = 0;
+ for (size_t i = 0; i < sizeof(FixedWidthIntegerType); i++) {
+ extracted_value |= static_cast<FixedWidthIntegerType>(**this) << i * 8;
+ (*this)++;
+ }
+
+ return extracted_value;
+ }
+
+ uint8_t extract8() { return extract<uint8_t>(); }
+ uint16_t extract16() { return extract<uint16_t>(); }
+ uint32_t extract32() { return extract<uint32_t>(); }
+ uint64_t extract64() { return extract<uint64_t>(); }
+
+ private:
+ std::shared_ptr<const Packet> packet_;
+ size_t index_;
+}; // Iterator
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/base/packet.cc b/packet/base/packet.cc
new file mode 100644
index 0000000..e17691c
--- /dev/null
+++ b/packet/base/packet.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet.h"
+
+#include <base/logging.h>
+#include <algorithm>
+
+#include "iterator.h"
+
+namespace bluetooth {
+
+size_t Packet::size() const { return packet_end_index_ - packet_start_index_; }
+
+Iterator Packet::begin() const {
+ return Iterator(shared_from_this(), packet_start_index_);
+}
+
+Iterator Packet::end() const {
+ return Iterator(shared_from_this(), packet_end_index_);
+}
+
+// For the Array operator, treat index 0 as the relative start of the packet
+uint8_t Packet::operator[](size_t i) {
+ return get_at_index(i + packet_start_index_);
+}
+
+size_t Packet::get_length() const { return data_->size(); }
+
+// Iterators use the absolute index to access data.
+uint8_t Packet::get_at_index(size_t index) const {
+ CHECK_GE(index, packet_start_index_);
+ CHECK_LT(index, packet_end_index_);
+ return data_->at(index);
+}
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/base/packet.h b/packet/base/packet.h
new file mode 100644
index 0000000..8c8f229
--- /dev/null
+++ b/packet/base/packet.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+namespace bluetooth {
+
+// Abstract base class that is subclassed to provide type-specifc accessors on
+// data. Manages said data's memory and guarantees the data's persistence. Once
+// created the underlying data is immutable.
+class Packet : public std::enable_shared_from_this<Packet> {
+ friend class Iterator;
+ friend class PacketBuilder;
+
+ public:
+ virtual ~Packet() = default;
+
+ protected:
+ Packet()
+ : packet_start_index_(0),
+ packet_end_index_(0),
+ data_(std::make_shared<std::vector<uint8_t>>(0)){};
+ Packet(std::shared_ptr<const Packet> pkt, size_t start, size_t end)
+ : packet_start_index_(start), packet_end_index_(end), data_(pkt->data_){};
+ Packet(std::shared_ptr<const Packet> pkt) : data_(pkt->data_) {
+ auto indices = pkt->GetPayloadIndecies();
+ packet_start_index_ = indices.first;
+ packet_end_index_ = indices.second;
+ };
+
+ public:
+ size_t size() const;
+ class Iterator begin() const;
+ class Iterator end() const;
+
+ uint8_t operator[](size_t i);
+
+ // Check to see if the packet is structured correctly and have the correct
+ // lengths. Data access on an invalid packet may cause a crash.
+ virtual bool IsValid() const = 0;
+
+ // Debug string representation of the packet
+ virtual std::string ToString() const = 0;
+
+ // Convert a packet horizontally in a layer, you may only specialize
+ // into a more specific type and doing otherwise will cause a compiler error
+ //
+ // Example:
+ // std::shared_ptr<AvrcpPacket> base;
+ // std::shared_ptr<AvrcpVendorPacket> p =
+ // Packet::Specialize<AvrcpVendorPacket>(base);
+ template <class T, class U>
+ static std::shared_ptr<T> Specialize(const std::shared_ptr<U>& pkt) {
+ static_assert(std::is_convertible<U*, Packet*>::value,
+ "Unable to specialize a non-packet object.");
+ static_assert(std::is_convertible<T*, Packet*>::value,
+ "Unable to specialize to something that isn't a packet");
+ static_assert(std::is_convertible<T*, U*>::value,
+ "Can not convert between the two packet types.");
+ return std::shared_ptr<T>(
+ new T(pkt, pkt->packet_start_index_, pkt->packet_end_index_));
+ };
+
+ protected:
+ // Packet should be immutable other than when building
+ size_t packet_start_index_;
+ size_t packet_end_index_;
+ std::shared_ptr<std::vector<uint8_t>> data_;
+
+ private:
+ // Only Available to the iterators
+ virtual size_t get_length() const;
+ virtual uint8_t get_at_index(size_t index) const;
+
+ // Returns the begining and end indicies of the payload of the packet.
+ // Used when constructing a packet from another packet when moving
+ // between layers.
+ virtual std::pair<size_t, size_t> GetPayloadIndecies() const = 0;
+};
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/base/packet_builder.cc b/packet/base/packet_builder.cc
new file mode 100644
index 0000000..ea3f3d2
--- /dev/null
+++ b/packet/base/packet_builder.cc
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet_builder.h"
+
+#include <base/logging.h>
+
+#include "packet.h"
+
+namespace bluetooth {
+
+void PacketBuilder::ReserveSpace(const std::shared_ptr<Packet>& pkt,
+ size_t size) {
+ pkt->data_->reserve(size);
+}
+
+bool PacketBuilder::AddPayloadOctets(const std::shared_ptr<Packet>& pkt,
+ size_t octets, uint64_t value) {
+ CHECK_LE(octets, sizeof(uint64_t));
+
+ for (size_t i = 0; i < octets; i++) {
+ pkt->data_->push_back(value & 0xff);
+ pkt->packet_end_index_++;
+ value = value >> 8;
+ }
+
+ return true;
+}
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/base/packet_builder.h b/packet/base/packet_builder.h
new file mode 100644
index 0000000..eb71708
--- /dev/null
+++ b/packet/base/packet_builder.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+namespace bluetooth {
+
+class Packet;
+
+class PacketBuilder {
+ public:
+ virtual size_t size() const = 0;
+ virtual bool Serialize(const std::shared_ptr<Packet>& pkt) = 0;
+
+ virtual ~PacketBuilder() = default;
+
+ protected:
+ // Only Builders should be able to call these
+ void ReserveSpace(const std::shared_ptr<Packet>& pkt, size_t size);
+ bool AddPayloadOctets1(const std::shared_ptr<Packet>& pkt, uint8_t value) {
+ return AddPayloadOctets(pkt, 1, value);
+ }
+ bool AddPayloadOctets2(const std::shared_ptr<Packet>& pkt, uint16_t value) {
+ return AddPayloadOctets(pkt, 2, value);
+ }
+ bool AddPayloadOctets3(const std::shared_ptr<Packet>& pkt, uint32_t value) {
+ return AddPayloadOctets(pkt, 3, value);
+ }
+ bool AddPayloadOctets4(const std::shared_ptr<Packet>& pkt, uint32_t value) {
+ return AddPayloadOctets(pkt, 4, value);
+ }
+ bool AddPayloadOctets6(const std::shared_ptr<Packet>& pkt, uint64_t value) {
+ return AddPayloadOctets(pkt, 6, value);
+ }
+ bool AddPayloadOctets8(const std::shared_ptr<Packet>& pkt, uint64_t value) {
+ return AddPayloadOctets(pkt, 8, value);
+ }
+
+ private:
+ // Add |octets| bytes to the payload. Return true if:
+ // - the value of |value| fits in |octets| bytes and
+ // - the new size of the payload is still < |kMaxPayloadOctets|
+ bool AddPayloadOctets(const std::shared_ptr<Packet>& pkt, size_t octets,
+ uint64_t value);
+};
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/include/avrcp_packet.h b/packet/include/avrcp_packet.h
new file mode 100644
index 0000000..e086c7d
--- /dev/null
+++ b/packet/include/avrcp_packet.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "avrcp/avrcp_packet.h"
+#include "avrcp/avrcp_reject_packet.h"
+#include "avrcp/capabilities_packet.h"
+#include "avrcp/get_element_attributes_packet.h"
+#include "avrcp/get_play_status_packet.h"
+#include "avrcp/pass_through_packet.h"
+#include "avrcp/register_notification_packet.h"
+#include "avrcp/vendor_packet.h"
+
+#include "avrcp/avrcp_browse_packet.h"
+#include "avrcp/change_path.h"
+#include "avrcp/general_reject_packet.h"
+#include "avrcp/get_folder_items.h"
+#include "avrcp/get_item_attributes.h"
+#include "avrcp/get_total_number_of_items.h"
+#include "avrcp/play_item.h"
+#include "avrcp/set_absolute_volume.h"
+#include "avrcp/set_addressed_player.h"
+#include "avrcp/set_browsed_player.h"
\ No newline at end of file
diff --git a/packet/include/packet.h b/packet/include/packet.h
new file mode 100644
index 0000000..01368af
--- /dev/null
+++ b/packet/include/packet.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "base/iterator.h"
+#include "base/packet.h"
+#include "base/packet_builder.h"
\ No newline at end of file
diff --git a/packet/tests/avrcp/avrcp_browse_packet_test.cc b/packet/tests/avrcp/avrcp_browse_packet_test.cc
new file mode 100644
index 0000000..cde0867
--- /dev/null
+++ b/packet/tests/avrcp/avrcp_browse_packet_test.cc
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_browse_packet.h"
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+
+// A helper class that has public accessors to protected methods
+class TestPacketBuilder : public PacketBuilder {
+ public:
+ static std::unique_ptr<TestPacketBuilder> MakeBuilder(
+ std::vector<uint8_t> data) {
+ std::unique_ptr<TestPacketBuilder> builder(new TestPacketBuilder(data));
+ return builder;
+ };
+
+ // Make all the utility functions public
+ using PacketBuilder::ReserveSpace;
+ using PacketBuilder::AddPayloadOctets1;
+ using PacketBuilder::AddPayloadOctets2;
+ using PacketBuilder::AddPayloadOctets3;
+ using PacketBuilder::AddPayloadOctets4;
+ using PacketBuilder::AddPayloadOctets6;
+ using PacketBuilder::AddPayloadOctets8;
+
+ size_t size() const override { return data_.size(); };
+
+ bool Serialize(const std::shared_ptr<Packet>& pkt) override {
+ ReserveSpace(pkt, size());
+
+ for (uint8_t byte : data_) {
+ AddPayloadOctets1(pkt, byte);
+ }
+
+ return true;
+ }
+
+ TestPacketBuilder(std::vector<uint8_t> data) : data_(data){};
+
+ std::vector<uint8_t> data_;
+};
+
+namespace avrcp {
+
+using TestBrowsePacket = TestPacketType<BrowsePacket>;
+
+TEST(AvrcpBrowsePacketBuilderTest, buildPacketTest) {
+ std::vector<uint8_t> get_folder_items_request_payload = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00};
+ auto payload_builder =
+ TestPacketBuilder::MakeBuilder(get_folder_items_request_payload);
+
+ auto builder = BrowsePacketBuilder::MakeBuilder(BrowsePdu::GET_FOLDER_ITEMS,
+ std::move(payload_builder));
+
+ ASSERT_EQ(builder->size(), get_folder_items_request.size());
+
+ auto test_packet = TestBrowsePacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_request);
+}
+
+TEST(AvrcpBrowsePacketTest, gettersTest) {
+ auto test_browse_packet = TestBrowsePacket::Make(get_folder_items_request);
+
+ ASSERT_EQ(test_browse_packet->GetPdu(), BrowsePdu::GET_FOLDER_ITEMS);
+ ASSERT_EQ(test_browse_packet->GetLength(), 10u);
+}
+
+TEST(AvrcpBrowsePacketTest, payloadBoundsTest) {
+ auto test_browse_packet = TestBrowsePacket::Make(get_folder_items_request);
+ std::vector<uint8_t> get_folder_items_request_payload = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00};
+
+ // Make a folder items payload packet out of the payload of the browse packet
+ auto get_folder_items_payload = TestBrowsePacket::Make(test_browse_packet);
+
+ for (size_t i = 0; i < get_folder_items_request_payload.size(); i++) {
+ ASSERT_EQ((*get_folder_items_payload)[i],
+ get_folder_items_request_payload[i]);
+ }
+}
+
+TEST(AvrcpBrowsePacketTest, validTest) {
+ auto test_browse_packet = TestBrowsePacket::Make(get_folder_items_request);
+
+ ASSERT_TRUE(test_browse_packet->IsValid());
+}
+
+TEST(AvrcpBrowsePacketTest, invalidTest) {
+ auto packet_copy = get_folder_items_request;
+ packet_copy.push_back(0x00);
+ auto test_browse_packet = TestBrowsePacket::Make(packet_copy);
+ ASSERT_FALSE(test_browse_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x00, 0x01};
+ test_browse_packet = TestBrowsePacket::Make(short_packet);
+ ASSERT_FALSE(test_browse_packet->IsValid());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/avrcp_packet_test.cc b/packet/tests/avrcp/avrcp_packet_test.cc
new file mode 100644
index 0000000..8a438b3
--- /dev/null
+++ b/packet/tests/avrcp/avrcp_packet_test.cc
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_packet.h"
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+
+// A helper class that has public accessors to protected methods
+class TestPacketBuilder : public PacketBuilder {
+ public:
+ static std::unique_ptr<TestPacketBuilder> MakeBuilder(
+ std::vector<uint8_t> data) {
+ std::unique_ptr<TestPacketBuilder> builder(new TestPacketBuilder(data));
+ return builder;
+ };
+
+ // Make all the utility functions public
+ using PacketBuilder::ReserveSpace;
+ using PacketBuilder::AddPayloadOctets1;
+ using PacketBuilder::AddPayloadOctets2;
+ using PacketBuilder::AddPayloadOctets3;
+ using PacketBuilder::AddPayloadOctets4;
+ using PacketBuilder::AddPayloadOctets6;
+ using PacketBuilder::AddPayloadOctets8;
+
+ size_t size() const override { return data_.size(); };
+
+ bool Serialize(const std::shared_ptr<Packet>& pkt) override {
+ ReserveSpace(pkt, size());
+
+ for (uint8_t byte : data_) {
+ AddPayloadOctets1(pkt, byte);
+ }
+
+ return true;
+ }
+
+ TestPacketBuilder(std::vector<uint8_t> data) : data_(data){};
+
+ std::vector<uint8_t> data_;
+};
+
+namespace avrcp {
+
+using TestAvrcpPacket = TestPacketType<Packet>;
+
+TEST(AvrcpPacketBuilderTest, buildPacketTest) {
+ std::vector<uint8_t> get_capabilities_request_payload = {
+ 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x01, 0x03};
+ auto cap_req_builder =
+ TestPacketBuilder::MakeBuilder(get_capabilities_request_payload);
+
+ auto builder = PacketBuilder::MakeBuilder(
+ CType::STATUS, 0x09, 0x00, Opcode::VENDOR, std::move(cap_req_builder));
+
+ ASSERT_EQ(builder->size(), get_capabilities_request.size());
+
+ auto test_packet = TestAvrcpPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_capabilities_request);
+}
+
+TEST(AvrcpPacketTest, getterTests) {
+ auto test_avrcp_packet = TestAvrcpPacket::Make(get_capabilities_request);
+
+ ASSERT_EQ(test_avrcp_packet->GetCType(), CType::STATUS);
+ ASSERT_EQ(test_avrcp_packet->GetSubunitType(), 0x09);
+ ASSERT_EQ(test_avrcp_packet->GetSubunitId(), 0x00);
+ ASSERT_EQ(test_avrcp_packet->GetOpcode(), Opcode::VENDOR);
+}
+
+TEST(AvrcpPacketTest, getterMaskTests) {
+ auto bad_get_cap_data = get_capabilities_request;
+ bad_get_cap_data[0] = 0xFF; // CType
+ bad_get_cap_data[1] = 0xFF; // Subunit Type & ID
+
+ auto test_avrcp_packet = TestAvrcpPacket::Make(bad_get_cap_data);
+
+ ASSERT_EQ(test_avrcp_packet->GetCType(), CType::INTERIM);
+ ASSERT_EQ(test_avrcp_packet->GetSubunitType(), 0b00011111);
+ ASSERT_EQ(test_avrcp_packet->GetSubunitId(), 0b00000111);
+}
+
+TEST(AvrcpPacketTest, payloadBoundsTest) {
+ auto test_avrcp_packet = TestAvrcpPacket::Make(get_capabilities_request);
+
+ std::vector<uint8_t> get_cap_payload_data = {0x00, 0x19, 0x58, 0x10,
+ 0x00, 0x00, 0x01, 0x03};
+
+ auto get_cap_payload_packet = TestAvrcpPacket::Make(test_avrcp_packet);
+
+ // We are unable to do a direct vector compare here as one of the packets is
+ // a larger vector that only has a segment of data currently visible.
+ for (size_t i = 0; i < get_cap_payload_data.size(); i++) {
+ ASSERT_EQ(get_cap_payload_data[i], (*get_cap_payload_packet)[i]);
+ }
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/avrcp_reject_packet_test.cc b/packet/tests/avrcp/avrcp_reject_packet_test.cc
new file mode 100644
index 0000000..ebaa9a6
--- /dev/null
+++ b/packet/tests/avrcp/avrcp_reject_packet_test.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_reject_packet.h"
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestAvrcpPacket = TestPacketType<Packet>;
+
+TEST(RejectPacketBuilderTest, buildPacketTest) {
+ auto builder = RejectBuilder::MakeBuilder(
+ CommandPdu::LIST_APPLICATION_SETTING_ATTRIBUTES, Status::INVALID_COMMAND);
+
+ ASSERT_EQ(builder->size(), reject_player_app_settings_response.size());
+
+ auto test_packet = TestAvrcpPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), reject_player_app_settings_response);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/avrcp_test_packets.h b/packet/tests/avrcp/avrcp_test_packets.h
new file mode 100644
index 0000000..13994d0
--- /dev/null
+++ b/packet/tests/avrcp/avrcp_test_packets.h
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+// AVRCP packets pulled from wireshark
+namespace {
+
+// AVRCP Get Capabilities Request packet
+std::vector<uint8_t> get_capabilities_request = {
+ 0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x01, 0x03};
+
+// AVRCP Get Capabilities Request packet with Company ID
+std::vector<uint8_t> get_capabilities_request_company_id = {
+ 0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x01, 0x02};
+
+// AVRCP Get Capabilities Request packet with Unknown
+std::vector<uint8_t> get_capabilities_request_unknown = {
+ 0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x01, 0x7f};
+
+// AVRCP Get Capabilities Response to Company ID request
+std::vector<uint8_t> get_capabilities_response_company_id = {
+ 0x0c, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00,
+ 0x08, 0x02, 0x02, 0x00, 0x19, 0x58, 0x00, 0x23, 0x45};
+
+// AVRCP Get Capabilities Response to Events Supported request
+std::vector<uint8_t> get_capabilities_response_events_supported = {
+ 0x0c, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00,
+ 0x00, 0x05, 0x03, 0x03, 0x01, 0x02, 0x05};
+
+// AVRCP Get Element Attributes request for current playing song and attribute
+// Title
+std::vector<uint8_t> get_element_attributes_request_partial = {
+ 0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x20, 0x00, 0x00, 0x0d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01};
+
+// AVRCP Get Element Attributes request for current playing song and attributes
+// Title, Artist, Album, Media Number, Playing Time, Total Number of Media, and
+// Genre
+std::vector<uint8_t> get_element_attributes_request_full = {
+ 0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x20, 0x00, 0x00, 0x25, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06};
+
+// AVRCP Get Element Attributes response with attribute values as follows
+// Title: "Test Song"
+// Artist: "Test Artist"
+// Album: "Test Album"
+// Track Number: "1"
+// Number of Tracks: "2"
+// Genre: "Test Genre"
+// Duration: "1000"
+std::vector<uint8_t> get_elements_attributes_response_full = {
+ 0x0c, 0x48, 0x00, 0x00, 0x19, 0x58, 0x20, 0x00, 0x00, 0x67, 0x07, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x6a, 0x00, 0x09, 0x54, 0x65, 0x73, 0x74, 0x20,
+ 0x53, 0x6f, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x0b,
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x72, 0x74, 0x69, 0x73, 0x74, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x6a, 0x00, 0x0a, 0x54, 0x65, 0x73, 0x74, 0x20,
+ 0x41, 0x6c, 0x62, 0x75, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6a, 0x00,
+ 0x01, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x6a, 0x00, 0x01, 0x32, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x6a, 0x00, 0x0a, 0x54, 0x65, 0x73, 0x74, 0x20,
+ 0x47, 0x65, 0x6e, 0x72, 0x65, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6a, 0x00,
+ 0x04, 0x31, 0x30, 0x30, 0x30};
+
+// AVRCP Get Play Status Request
+std::vector<uint8_t> get_play_status_request = {0x01, 0x48, 0x00, 0x00, 0x19,
+ 0x58, 0x30, 0x00, 0x00, 0x00};
+
+// AVRCP Get Play Status Response
+std::vector<uint8_t> get_play_status_response = {
+ 0x0c, 0x48, 0x00, 0x00, 0x19, 0x58, 0x30, 0x00, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00};
+
+// AVRCP Pass Through Command Play Pushed Request
+std::vector<uint8_t> pass_through_command_play_pushed = {0x00, 0x48, 0x7c, 0x44,
+ 0x00};
+
+// AVRCP Pass Through Command Play Pushed Response
+std::vector<uint8_t> pass_through_command_play_released = {0x09, 0x48, 0x7c,
+ 0xc4, 0x00};
+
+// AVRCP Register Playback Status Notification
+std::vector<uint8_t> register_play_status_notification = {
+ 0x03, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00,
+ 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x05};
+
+// AVRCP Register Volume Changed Notification
+std::vector<uint8_t> register_volume_changed_notification = {
+ 0x03, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00,
+ 0x00, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x00};
+
+// AVRCP Register Notification without any parameter
+std::vector<uint8_t> register_notification_invalid = {
+ 0x03, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x05};
+
+// AVRCP Interim Playback Status Notification
+std::vector<uint8_t> interim_play_status_notification = {
+ 0x0f, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x02, 0x01, 0x00};
+
+// AVRCP Interim Track Changed Notification
+std::vector<uint8_t> interim_track_changed_notification = {
+ 0x0f, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x09,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+// AVRCP Changed Playback Position Notification
+std::vector<uint8_t> changed_play_pos_notification = {
+ 0x0d, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00,
+ 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00};
+
+// AVRCP Interim Now Playing Changed Notification
+std::vector<uint8_t> interim_now_playing_notification = {
+ 0x0f, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x01, 0x09};
+
+// AVRCP Interim Available Players Changed Notification
+std::vector<uint8_t> interim_available_players_notification = {
+ 0x0f, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x01, 0x0a};
+
+// AVRCP Interim Addressed Player Changed Notification with active
+// player ID 1
+std::vector<uint8_t> interim_addressed_player_notification = {
+ 0x0f, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00,
+ 0x00, 0x05, 0x0b, 0x00, 0x01, 0x00, 0x00};
+
+// AVRCP Interim UIDs Changed Notification
+std::vector<uint8_t> interim_uids_notificaiton = {0x0f, 0x48, 0x00, 0x00, 0x19,
+ 0x58, 0x31, 0x00, 0x00, 0x03,
+ 0x0c, 0x00, 0x00};
+
+// AVRCP Interim Volume Changed Notification with volume at 55% (0x47)
+std::vector<uint8_t> interim_volume_changed_notification = {
+ 0x0f, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x02, 0x0d, 0x47};
+
+// AVRCP Rejected Volume Changed Notification with volume at 0%
+std::vector<uint8_t> rejected_volume_changed_notification = {
+ 0x0a, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x02, 0x0d, 0x00};
+
+// AVRCP Changed Volume Changed Notification with volume at 55% (0x47)
+std::vector<uint8_t> changed_volume_changed_notification = {
+ 0x0d, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x02, 0x0d, 0x47};
+
+// AVRCP Reject List Player Application Settings Response
+std::vector<uint8_t> reject_player_app_settings_response = {
+ 0x0a, 0x48, 0x00, 0x00, 0x19, 0x58, 0x11, 0x00, 0x00, 0x01, 0x00};
+
+// AVRCP Browse General Reject packet for invalid PDU ID
+std::vector<uint8_t> general_reject_invalid_command_packet = {0xa0, 0x00, 0x01,
+ 0x00};
+
+// AVRCP Browse Get Folder Items Request packet for media players with
+// the following data:
+// scope = 0x00 (Media Player List)
+// start_item = 0x00
+// end_item = 0x03
+// attributes_requested: all
+std::vector<uint8_t> get_folder_items_request = {0x71, 0x00, 0x0a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x00};
+
+// AVRCP Browse Get Folder Items Request packet for media players with
+// the following data:
+// scope = 0x01 (VFS)
+// start_item = 0x00
+// end_item = 0x09
+// attributes_requested: none
+std::vector<uint8_t> get_folder_items_request_no_attrs = {
+ 0x71, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x09, 0xff};
+
+// AVRCP Browse Get Folder Items Request packet for media players with
+// the following data:
+// scope = 0x01 (VFS)
+// start_item = 0x00
+// end_item = 0x09
+// attributes_requested: Title
+std::vector<uint8_t> get_folder_items_request_title = {
+ 0x71, 0x00, 0x0e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x00, 0x1};
+
+// AVRCP Browse Get Folder Items Request packet for vfs with
+// the following data:
+// scope = 0x01 (VFS)
+// start_item = 0x00
+// end_item = 0x05
+// attributes_requested: TITLE
+std::vector<uint8_t> get_folder_items_request_vfs = {
+ 0x71, 0x00, 0x0e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x01};
+
+// AVRCP Browse Get Folder Items Request packet for now playing with
+// the following data:
+// scope = 0x03 (Now Playing)
+// start_item = 0x00
+// end_item = 0x05
+// attributes_requested: All Items
+std::vector<uint8_t> get_folder_items_request_now_playing = {
+ 0x71, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00};
+
+// AVRCP Browse Get Folder Items Response packet with range out of bounds error
+std::vector<uint8_t> get_folder_items_error_response = {0x71, 0x00, 0x01, 0x0b};
+
+// AVRCP Browse Get Folder Items Response packet for media players
+// Contains one media player with the following fields:
+// id = 0x0001
+// name = "com.google.android.music"
+// browsing_supported = true
+std::vector<uint8_t> get_folder_items_media_player_response = {
+ 0x71, 0x00, 0x3c, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x34,
+ 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xb7, 0x01, 0x0c, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x6a, 0x00, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2e, 0x6d, 0x75, 0x73, 0x69, 0x63};
+
+// AVRCP Browse Get Folder Items Response packet with one folder
+// with the following fields:
+// uid = 0x0000000000000001
+// type = 0x00 (Mixed);
+// name = "Test Folder"
+// is_playable = true
+std::vector<uint8_t> get_folder_items_folder_response = {
+ 0x71, 0x00, 0x21, 0x04, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x19, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x6a, 0x00,
+ 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72};
+
+// AVRCP Browse Get Folder Items Response packet with one song
+// with the following fields:
+// uid = 0x0000000000000002
+// name = "Test Title"
+// attribute[TITLE] = "Test Title"
+std::vector<uint8_t> get_folder_items_song_response = {
+ 0x71, 0x00, 0x32, 0x04, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x2a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x6a,
+ 0x00, 0x0a, 0x54, 0x65, 0x73, 0x74, 0x20, 0x54, 0x69, 0x74, 0x6c,
+ 0x65, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6a, 0x00, 0x0a, 0x54,
+ 0x65, 0x73, 0x74, 0x20, 0x54, 0x69, 0x74, 0x6c, 0x65};
+
+// AVRCP Browse Change Path Request down to folder with UID 0x0000000000000002
+std::vector<uint8_t> change_path_request = {0x72, 0x00, 0x0b, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02};
+
+// AVRCP Browse Change Path Request up
+std::vector<uint8_t> change_path_up_request = {0x72, 0x00, 0x0b, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF};
+
+// AVRCP Browse Change Path Response with two items in current folder
+std::vector<uint8_t> change_path_response = {0x72, 0x00, 0x05, 0x04,
+ 0x00, 0x00, 0x00, 0x02};
+
+// AVRCP Browse Change Path Response with an error of invalid direction
+std::vector<uint8_t> change_path_error_response = {0x72, 0x00, 0x01, 0x07};
+
+// AVRCP Get Item Attributes request with all attributes requested
+// with the following fields:
+// scope = 0x03 (Now Playing List)
+// uid_counter = 0x0000
+// uid = 0x0000000000000001
+std::vector<uint8_t> get_item_attributes_request_all_attributes = {
+ 0x73, 0x00, 0x28, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07};
+
+// AVRCP Get Item Attributes request with all attributes requested
+// with the following fields:
+// scope = 0x03 (Now Playing List)
+// uid_counter = 0x0001
+// uid = 0x0000000000000001
+std::vector<uint8_t> get_item_attributes_request_all_attributes_invalid = {
+ 0x73, 0x00, 0x28, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07};
+
+// AVRCP Get Item Attributes Response with the following attributes:
+// title = "Test Song"
+// artist = "Test Artist"
+// album = "Test Album"
+std::vector<uint8_t> get_item_attributes_song_response = {
+ 0x73, 0x00, 0x38, 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6a, 0x00,
+ 0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x6f, 0x6e, 0x67, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x6a, 0x00, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x41,
+ 0x72, 0x74, 0x69, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6a, 0x00,
+ 0x0a, 0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x6c, 0x62, 0x75, 0x6d};
+
+// AVRCP Set Addressed Player Request with player_id = 0
+std::vector<uint8_t> set_addressed_player_request = {
+ 0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x60, 0x00, 0x00, 0x02, 0x00, 0x00};
+
+// AVRCP Set Addressed Player Request with player_id = 1
+std::vector<uint8_t> set_addressed_player_id_1_request = {
+ 0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x60, 0x00, 0x00, 0x02, 0x00, 0x01};
+
+// AVRCP Set Addressed Player Response with status success
+std::vector<uint8_t> set_addressed_player_response = {
+ 0x09, 0x48, 0x00, 0x00, 0x19, 0x58, 0x60, 0x00, 0x00, 0x01, 0x04};
+
+// AVRCP Set Browsed Player Request with player_id = 2
+std::vector<uint8_t> set_browsed_player_request = {0x70, 0x00, 0x02, 0x00,
+ 0x02};
+
+// AVRCP Set Browsed Player Response with num items = 4 and depth = 0
+std::vector<uint8_t> set_browsed_player_response = {
+ 0x70, 0x00, 0x0a, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x6a, 0x00};
+
+// AVRCP Get Total Number of Items Request with Scope = Media Player List
+std::vector<uint8_t> get_total_number_of_items_request_media_players = {
+ 0x75, 0x00, 0x01, 0x00};
+
+// AVRCP Get Total Number of Items Request with Scope = VFS
+std::vector<uint8_t> get_total_number_of_items_request_vfs = {0x75, 0x00, 0x01,
+ 0x01};
+
+// AVRCP Get Total Number of Items Request with Scope = Now Playing List
+std::vector<uint8_t> get_total_number_of_items_request_now_playing = {
+ 0x75, 0x00, 0x01, 0x03};
+
+// AVRCP Get Total number of Items Response with 5 items in folder
+std::vector<uint8_t> get_total_number_of_items_response = {
+ 0x75, 0x00, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05};
+
+// AVRCP Play Item Request with scope = Now Playing and
+// UID = 0x0000000000000003
+std::vector<uint8_t> play_item_request = {
+ 0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x74, 0x00, 0x00, 0x0b, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00};
+
+// AVRCP Play Item Response
+std::vector<uint8_t> play_item_response = {0x09, 0x48, 0x00, 0x00, 0x19, 0x58,
+ 0x74, 0x00, 0x00, 0x01, 0x04};
+
+// AVRCP Set Absolute Volume Request with volume at 56% (0x48)
+std::vector<uint8_t> set_absolute_volume_request = {
+ 0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x50, 0x00, 0x00, 0x01, 0x48};
+
+// AVRCP Set Absolute Volume Response with voume at 52% (0x43)
+std::vector<uint8_t> set_absolute_volume_response = {
+ 0x09, 0x48, 0x00, 0x00, 0x19, 0x58, 0x50, 0x00, 0x00, 0x01, 0x43};
+
+} // namespace
diff --git a/packet/tests/avrcp/change_path_packet_test.cc b/packet/tests/avrcp/change_path_packet_test.cc
new file mode 100644
index 0000000..b14d577
--- /dev/null
+++ b/packet/tests/avrcp/change_path_packet_test.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/logging.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "change_path.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestChangePathReqPacket = TestPacketType<ChangePathRequest>;
+
+TEST(ChangePathResponseBuilderTest, builderTest) {
+ auto builder = ChangePathResponseBuilder::MakeBuilder(Status::NO_ERROR, 2);
+ ASSERT_EQ(builder->size(), change_path_response.size());
+
+ auto test_packet = TestChangePathReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), change_path_response);
+}
+
+TEST(ChangePathResponseBuilderTest, builderErrorStatusTest) {
+ // NOTE: The num items in folder field doesn't matter when the status is
+ // not NO_ERROR
+ auto builder =
+ ChangePathResponseBuilder::MakeBuilder(Status::INVALID_DIRECTION, 2);
+ ASSERT_EQ(builder->size(), change_path_error_response.size());
+
+ auto test_packet = TestChangePathReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), change_path_error_response);
+}
+
+TEST(ChangePathRequestTest, getterTest) {
+ auto test_packet = TestChangePathReqPacket::Make(change_path_request);
+
+ ASSERT_EQ(test_packet->GetUidCounter(), 0x0000u);
+ ASSERT_EQ(test_packet->GetDirection(), Direction::DOWN);
+ ASSERT_EQ(test_packet->GetUid(), 0x0000000000000002u);
+}
+
+TEST(ChangePathRequestTest, validTest) {
+ auto test_packet = TestChangePathReqPacket::Make(change_path_request);
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(ChangePathRequestTest, invalidTest) {
+ auto packet_copy = change_path_request;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestChangePathReqPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x00, 0x01, 0x02, 0x03, 0x04};
+ test_packet = TestChangePathReqPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+TEST(ChangePathRequestBuilder, builderTest) {
+ auto builder = ChangePathRequestBuilder::MakeBuilder(0, Direction::DOWN, 2);
+ ASSERT_EQ(builder->size(), change_path_request.size());
+
+ auto test_packet = TestChangePathReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), change_path_request);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/general_reject_packet_test.cc b/packet/tests/avrcp/general_reject_packet_test.cc
new file mode 100644
index 0000000..e27d0b7
--- /dev/null
+++ b/packet/tests/avrcp/general_reject_packet_test.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "general_reject_packet.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestGeneralRejectPacket = TestPacketType<BrowsePacket>;
+
+TEST(GeneralRejectPacketBuilderTest, buildPacketTest) {
+ auto builder = GeneralRejectBuilder::MakeBuilder(BrowsePdu::GENERAL_REJECT,
+ Status::INVALID_COMMAND);
+
+ ASSERT_EQ(builder->size(), general_reject_invalid_command_packet.size());
+
+ auto test_packet = TestGeneralRejectPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), general_reject_invalid_command_packet);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/packet/tests/avrcp/get_capabilities_packet_test.cc b/packet/tests/avrcp/get_capabilities_packet_test.cc
new file mode 100644
index 0000000..267c62b
--- /dev/null
+++ b/packet/tests/avrcp/get_capabilities_packet_test.cc
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "capabilities_packet.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using GetCapRequestTestPacket = TestPacketType<GetCapabilitiesRequest>;
+
+// Test parsing a GetCapabilities Request
+TEST(GetCapabilitiesRequestPacketTest, getterTest) {
+ auto test_packet = GetCapRequestTestPacket::Make(get_capabilities_request);
+
+ ASSERT_EQ(test_packet->GetCapabilityRequested(),
+ Capability::EVENTS_SUPPORTED);
+}
+
+TEST(GetCapabilitiesRequestPacketTest, validTest) {
+ auto test_packet = GetCapRequestTestPacket::Make(get_capabilities_request);
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(GetCapabilitiesRequestPacketTest, invalidTest) {
+ std::vector<uint8_t> packet_copy = get_capabilities_request;
+ packet_copy.push_back(0x00);
+ auto test_packet = GetCapRequestTestPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {
+ 0, 1, 2, 3, 4, 5, 6,
+ };
+ test_packet = GetCapRequestTestPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+// Test that the length returned by the builder grows correctlyas fields are
+// added
+TEST(GetCapabilityResponseBuilder, builderLengthTest) {
+ auto builder = GetCapabilitiesResponseBuilder::MakeCompanyIdBuilder(0x000000);
+ ASSERT_EQ(builder->size(), 15u);
+ builder->AddCompanyId(0x000001);
+ ASSERT_EQ(builder->size(), 18u);
+ builder->AddCompanyId(0x000002);
+ ASSERT_EQ(builder->size(), 21u);
+
+ builder = GetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(
+ Event::PLAYBACK_STATUS_CHANGED);
+ ASSERT_EQ(builder->size(), 13u);
+ builder->AddEvent(Event::TRACK_CHANGED);
+ ASSERT_EQ(builder->size(), 14u);
+ builder->AddEvent(Event::PLAYBACK_POS_CHANGED);
+ ASSERT_EQ(builder->size(), 15u);
+}
+
+// Check to see that adding the same value multiple times does nothing
+TEST(GetCapabilityResponseBuilder, duplicateAddTest) {
+ auto builder = GetCapabilitiesResponseBuilder::MakeCompanyIdBuilder(0x000000);
+ ASSERT_EQ(builder->size(), 15u);
+ builder->AddCompanyId(0x000000);
+ ASSERT_EQ(builder->size(), 15u);
+
+ builder = GetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(
+ Event::PLAYBACK_STATUS_CHANGED);
+ ASSERT_EQ(builder->size(), 13u);
+ builder->AddEvent(Event::PLAYBACK_STATUS_CHANGED);
+ ASSERT_EQ(builder->size(), 13u);
+}
+
+// Test that trying to to add the wrong type of field to a builder causes death
+TEST(GetCapabilityResponseBuilder, mismatchAddDeathTest) {
+ auto builder = GetCapabilitiesResponseBuilder::MakeCompanyIdBuilder(0x000000);
+ ASSERT_DEATH(builder->AddEvent(Event::PLAYBACK_STATUS_CHANGED),
+ "capability_ == Capability::EVENTS_SUPPORTED");
+
+ builder = GetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(
+ Event::PLAYBACK_STATUS_CHANGED);
+ ASSERT_DEATH(builder->AddCompanyId(0x000000),
+ "capability_ == Capability::COMPANY_ID");
+}
+
+// Test building a GetCapabilities Response to a Company ID request
+TEST(GetCapabilityResponseBuilder, comanyIdBuilderTest) {
+ auto builder = GetCapabilitiesResponseBuilder::MakeCompanyIdBuilder(0x002345);
+ builder->AddCompanyId(BLUETOOTH_COMPANY_ID);
+
+ auto test_packet = GetCapRequestTestPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_capabilities_response_company_id);
+}
+
+// Test building a GetCapabilities Response to an Events Supported request
+TEST(GetCapabilityResponseBuilder, eventsSupportedBuilderTest) {
+ auto builder = GetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(
+ Event::PLAYBACK_STATUS_CHANGED);
+ builder->AddEvent(Event::TRACK_CHANGED);
+ builder->AddEvent(Event::PLAYBACK_POS_CHANGED);
+
+ auto test_packet = GetCapRequestTestPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_capabilities_response_events_supported);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/get_element_attributes_packet_test.cc b/packet/tests/avrcp/get_element_attributes_packet_test.cc
new file mode 100644
index 0000000..8a05487
--- /dev/null
+++ b/packet/tests/avrcp/get_element_attributes_packet_test.cc
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "get_element_attributes_packet.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestGetElemAttrReqPacket = TestPacketType<GetElementAttributesRequest>;
+
+TEST(GetElementAttributesRequestPacketTest, getterTest) {
+ // Only Title is requested
+ auto test_packet =
+ TestGetElemAttrReqPacket::Make(get_element_attributes_request_partial);
+
+ ASSERT_EQ(test_packet->GetIdentifier(), 0u);
+
+ auto attribute_list = test_packet->GetAttributesRequested();
+ ASSERT_EQ(attribute_list.size(), 1u);
+ ASSERT_EQ(attribute_list[0], Attribute::TITLE);
+
+ // Title, Artist, Album, Media Numer, Playing Time, Total Number of Media,
+ // and Genre requested
+ test_packet =
+ TestGetElemAttrReqPacket::Make(get_element_attributes_request_full);
+
+ ASSERT_EQ(test_packet->GetIdentifier(), 0u);
+
+ attribute_list = test_packet->GetAttributesRequested();
+ ASSERT_EQ(attribute_list.size(), 7u);
+ ASSERT_EQ(attribute_list[0], Attribute::TITLE);
+ ASSERT_EQ(attribute_list[1], Attribute::ARTIST_NAME);
+ ASSERT_EQ(attribute_list[2], Attribute::ALBUM_NAME);
+ ASSERT_EQ(attribute_list[3], Attribute::TRACK_NUMBER);
+ ASSERT_EQ(attribute_list[4], Attribute::PLAYING_TIME);
+ ASSERT_EQ(attribute_list[5], Attribute::TOTAL_NUMBER_OF_TRACKS);
+ ASSERT_EQ(attribute_list[6], Attribute::GENRE);
+}
+
+TEST(GetElementAttributesRequestPacketTest, validTest) {
+ auto test_packet =
+ TestGetElemAttrReqPacket::Make(get_element_attributes_request_partial);
+ ASSERT_TRUE(test_packet->IsValid());
+
+ test_packet =
+ TestGetElemAttrReqPacket::Make(get_element_attributes_request_full);
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(GetElementAttributesRequestPacketTest, invalidTest) {
+ std::vector<uint8_t> packet_copy = get_element_attributes_request_partial;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestGetElemAttrReqPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00};
+ test_packet = TestGetElemAttrReqPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+TEST(GetElementAttributesResponseBuilderTest, builderLengthTest) {
+ // Attributes have a size of 8 + string length
+ auto builder = GetElementAttributesResponseBuilder::MakeBuilder(0xFFFF);
+ ASSERT_EQ(builder->size(), 11u);
+ builder->AddAttributeEntry(Attribute::TITLE, "test");
+ ASSERT_EQ(builder->size(), 23u);
+ builder->AddAttributeEntry(Attribute::ARTIST_NAME, "test");
+ ASSERT_EQ(builder->size(), 35u);
+}
+
+TEST(GetElementAttributesResponseBuilderTest, builderTest) {
+ auto builder = GetElementAttributesResponseBuilder::MakeBuilder(0xFFFF);
+ builder->AddAttributeEntry(Attribute::TITLE, "Test Song");
+ builder->AddAttributeEntry(Attribute::ARTIST_NAME, "Test Artist");
+ builder->AddAttributeEntry(Attribute::ALBUM_NAME, "Test Album");
+ builder->AddAttributeEntry(Attribute::TRACK_NUMBER, "1");
+ builder->AddAttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2");
+ builder->AddAttributeEntry(Attribute::GENRE, "Test Genre");
+ builder->AddAttributeEntry(Attribute::PLAYING_TIME, "1000");
+
+ ASSERT_EQ(builder->size(), get_elements_attributes_response_full.size());
+
+ auto test_packet = TestGetElemAttrReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_elements_attributes_response_full);
+}
+
+TEST(GetElementAttributesResponseBuilderTest, truncateBuilderTest) {
+ auto attribute = AttributeEntry(Attribute::TITLE, "1234");
+ size_t truncated_size = VendorPacket::kMinSize();
+ truncated_size += 1; // Number of attributes
+ truncated_size += attribute.size(); // Attribute size
+
+ auto truncated_builder =
+ GetElementAttributesResponseBuilder::MakeBuilder(truncated_size);
+ ASSERT_TRUE(
+ truncated_builder->AddAttributeEntry(Attribute::TITLE, "1234truncated"));
+ ASSERT_EQ(truncated_builder->size(), truncated_size);
+
+ ASSERT_FALSE(truncated_builder->AddAttributeEntry(Attribute::ARTIST_NAME,
+ "Can not add"));
+
+ auto truncated_packet = TestGetElemAttrReqPacket::Make();
+ truncated_builder->Serialize(truncated_packet);
+
+ auto builder = GetElementAttributesResponseBuilder::MakeBuilder(0xFFFF);
+ builder->AddAttributeEntry(attribute);
+ auto test_packet = TestGetElemAttrReqPacket::Make();
+ builder->Serialize(test_packet);
+
+ ASSERT_EQ(truncated_packet->GetData(), test_packet->GetData());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/get_folder_items_packet_test.cc b/packet/tests/avrcp/get_folder_items_packet_test.cc
new file mode 100644
index 0000000..ec2d733
--- /dev/null
+++ b/packet/tests/avrcp/get_folder_items_packet_test.cc
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "get_folder_items.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestGetFolderItemsReqPacket = TestPacketType<GetFolderItemsRequest>;
+
+TEST(GetFolderItemsResponseBuilderTest, builderMediaPlayerSizeTest) {
+ auto builder = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ // If there are no items, then the only data in the packet is the status
+ ASSERT_EQ(builder->size(), get_folder_items_error_response.size());
+
+ auto player = MediaPlayerItem(0x0001, "com.google.android.music", true);
+ builder->AddMediaPlayer(player);
+ ASSERT_EQ(builder->size(), get_folder_items_media_player_response.size());
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderMediaPlayerAddTest) {
+ auto builder = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ auto player = MediaPlayerItem(0x0001, "com.google.android.music", true);
+ builder->AddMediaPlayer(player);
+
+ auto test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_media_player_response);
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderPlayerAddMtuTest) {
+ MediaPlayerItem player1(1, "Player 1 that fits", true);
+ MediaPlayerItem player2(2, "Player 2 that doesn't fit", true);
+ MediaPlayerItem player3(3, "Player 3 that fits", true);
+
+ // Browsing Header + Status field + UID Counter field + Number of Items field
+ auto packet_size = BrowsePacket::kMinSize() + 5;
+ packet_size += player1.size() + player3.size();
+
+ auto builder = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
+ Status::NO_ERROR, 0x0000, packet_size);
+
+ ASSERT_TRUE(builder->AddMediaPlayer(player1));
+ ASSERT_FALSE(builder->AddMediaPlayer(player2));
+ ASSERT_TRUE(builder->AddMediaPlayer(player3));
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderFolderSizeTest) {
+ auto builder = GetFolderItemsResponseBuilder::MakeVFSBuilder(Status::NO_ERROR,
+ 0x0000, 0xFFFF);
+ ASSERT_EQ(builder->size(), get_folder_items_error_response.size());
+
+ auto folder = FolderItem(0x0000000000000001, 0x00, true, "Test Folder");
+ builder->AddFolder(folder);
+ ASSERT_EQ(builder->size(), get_folder_items_folder_response.size());
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderFolderAddTest) {
+ auto builder = GetFolderItemsResponseBuilder::MakeVFSBuilder(Status::NO_ERROR,
+ 0x0000, 0xFFFF);
+ auto folder = FolderItem(0x0000000000000001, 0x00, true, "Test Folder");
+ builder->AddFolder(folder);
+
+ auto test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_folder_response);
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderFolderAddMtuTest) {
+ FolderItem folder1(0x01, 0x00, true, "Folder 1 that fits");
+ FolderItem folder2(0x02, 0x00, true, "Folder 2 that doesn't fit");
+ FolderItem folder3(0x03, 0x00, true, "Folder 3 that fits");
+
+ // Browsing Header + Status field + UID Counter field + Number of Items field
+ auto packet_size = BrowsePacket::kMinSize() + 5;
+ packet_size += folder1.size() + folder3.size();
+
+ auto builder = GetFolderItemsResponseBuilder::MakeVFSBuilder(
+ Status::NO_ERROR, 0x0000, packet_size);
+
+ ASSERT_TRUE(builder->AddFolder(folder1));
+ ASSERT_FALSE(builder->AddFolder(folder2));
+ ASSERT_TRUE(builder->AddFolder(folder3));
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderSongSizeTest) {
+ auto builder = GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ ASSERT_EQ(builder->size(), get_folder_items_error_response.size());
+
+ std::set<AttributeEntry> attributes;
+ attributes.insert(AttributeEntry(Attribute::TITLE, "Test Title"));
+ auto song = MediaElementItem(0x02, "Test Title", attributes);
+ builder->AddSong(song);
+ ASSERT_EQ(builder->size(), get_folder_items_song_response.size());
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderSongAddTest) {
+ auto builder = GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ std::set<AttributeEntry> attributes;
+ attributes.insert(AttributeEntry(Attribute::TITLE, "Test Title"));
+ auto song = MediaElementItem(0x02, "Test Title", attributes);
+ builder->AddSong(song);
+
+ auto test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_song_response);
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderSongAddMtuTest) {
+ MediaElementItem song1(0x01, "Song 1 that fits", std::set<AttributeEntry>());
+ MediaElementItem song2(0x02, "Song 2 that doesn't fit",
+ std::set<AttributeEntry>());
+ MediaElementItem song3(0x03, "Song 3 that fits", std::set<AttributeEntry>());
+
+ auto packet_size = BrowsePacket::kMinSize() + 5;
+ packet_size += song1.size() + song3.size();
+
+ auto builder = GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(
+ Status::NO_ERROR, 0x0000, packet_size);
+
+ ASSERT_TRUE(builder->AddSong(song1));
+ ASSERT_FALSE(builder->AddSong(song2));
+ ASSERT_TRUE(builder->AddSong(song3));
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderNoItemsTest) {
+ auto builder = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ auto test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_error_response);
+
+ builder = GetFolderItemsResponseBuilder::MakeVFSBuilder(Status::NO_ERROR,
+ 0x0000, 0xFFFF);
+ test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_error_response);
+
+ builder = GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_error_response);
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderErrorStatusTest) {
+ std::vector<uint8_t> get_folder_items_inv_scope = {0x71, 0x00, 0x01, 0x0a};
+
+ auto builder = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
+ Status::INVALID_SCOPE, 0x0000, 0xFFFF);
+
+ // Check that the status remains INVALID_SCOPE even though there are zero
+ // items
+ auto test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_inv_scope);
+
+ auto player = MediaPlayerItem(0x0001, "com.google.android.music", true);
+ builder->AddMediaPlayer(player);
+
+ // Check to make sure that even though we added an item, it doesn't get
+ // written to the packet
+ test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_inv_scope);
+}
+
+TEST(GetFolderItemsResponseBuilderTest, builderDeathTest) {
+ auto player = MediaPlayerItem(0x0001, "com.google.android.music", true);
+ auto folder = FolderItem(0x01, 0x00, true, "test folder");
+ auto song = MediaElementItem(0x01, "test song", std::set<AttributeEntry>());
+
+ auto builder = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ ASSERT_DEATH(builder->AddFolder(folder), "scope_ == Scope::VFS");
+ ASSERT_DEATH(builder->AddSong(song),
+ "scope_ == Scope::VFS \\|\\| scope_ == Scope::NOW_PLAYING");
+
+ builder = GetFolderItemsResponseBuilder::MakeVFSBuilder(Status::NO_ERROR,
+ 0x0000, 0xFFFF);
+ ASSERT_DEATH(builder->AddMediaPlayer(player),
+ "scope_ == Scope::MEDIA_PLAYER_LIST");
+
+ builder = GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ ASSERT_DEATH(builder->AddMediaPlayer(player),
+ "scope_ == Scope::MEDIA_PLAYER_LIST");
+ ASSERT_DEATH(builder->AddFolder(folder), "scope_ == Scope::VFS");
+}
+
+TEST(GetFolderItemsRequestTest, getterTest) {
+ auto test_packet =
+ TestGetFolderItemsReqPacket::Make(get_folder_items_request_vfs);
+
+ ASSERT_EQ(test_packet->GetScope(), Scope::VFS);
+ ASSERT_EQ(test_packet->GetStartItem(), 0x00000000u);
+ ASSERT_EQ(test_packet->GetEndItem(), 0x00000005u);
+ ASSERT_EQ(test_packet->GetNumAttributes(), 1);
+
+ std::vector<Attribute> attribute_list = {Attribute::TITLE};
+ ASSERT_EQ(test_packet->GetAttributesRequested(), attribute_list);
+}
+
+TEST(GetFolderItemsRequestBuilderTest, builderZeroAttrsTest) {
+ auto builder =
+ GetFolderItemsRequestBuilder::MakeBuilder(Scope::VFS, 0, 9, {});
+ ASSERT_EQ(builder->size(), get_folder_items_request_no_attrs.size());
+
+ auto test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_request_no_attrs);
+}
+
+TEST(GetFolderItemsRequestBuilderTest, builderTest) {
+ auto builder = GetFolderItemsRequestBuilder::MakeBuilder(Scope::VFS, 0, 9,
+ {Attribute::TITLE});
+ ASSERT_EQ(builder->size(), get_folder_items_request_title.size());
+
+ auto test_packet = TestGetFolderItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_folder_items_request_title);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/get_item_attributes_packet_test.cc b/packet/tests/avrcp/get_item_attributes_packet_test.cc
new file mode 100644
index 0000000..3d6f691
--- /dev/null
+++ b/packet/tests/avrcp/get_item_attributes_packet_test.cc
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "get_item_attributes.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestGetItemAttrsReqPacket = TestPacketType<GetItemAttributesRequest>;
+
+TEST(GetItemAttributesResponseBuilderTest, builderSizeTest) {
+ auto builder =
+ GetItemAttributesResponseBuilder::MakeBuilder(Status::NO_ERROR, 0xFFFF);
+ ASSERT_EQ(builder->size(), 5u);
+
+ builder->AddAttributeEntry(Attribute::TITLE, "Test Song");
+ ASSERT_EQ(builder->size(), 22u);
+
+ builder->AddAttributeEntry(Attribute::ARTIST_NAME, "Test Artist");
+ ASSERT_EQ(builder->size(), 41u);
+
+ builder->AddAttributeEntry(Attribute::ALBUM_NAME, "Test Album");
+ ASSERT_EQ(builder->size(), get_item_attributes_song_response.size());
+}
+
+TEST(GetItemAttributesResponseBuilderTest, builderTest) {
+ auto builder =
+ GetItemAttributesResponseBuilder::MakeBuilder(Status::NO_ERROR, 0xFFFF);
+ builder->AddAttributeEntry(Attribute::TITLE, "Test Song");
+ builder->AddAttributeEntry(Attribute::ARTIST_NAME, "Test Artist");
+ builder->AddAttributeEntry(Attribute::ALBUM_NAME, "Test Album");
+
+ auto test_packet = TestGetItemAttrsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_item_attributes_song_response);
+}
+
+TEST(GetItemAttributesResponseBuilderTest, truncateBuilderTest) {
+ auto attribute = AttributeEntry(Attribute::TITLE, "1234");
+ size_t truncated_size = BrowsePacket::kMinSize();
+ truncated_size += 2; // Status field + Number of attributes field
+ truncated_size += attribute.size(); // Attribute size
+
+ auto truncated_builder = GetItemAttributesResponseBuilder::MakeBuilder(
+ Status::NO_ERROR, truncated_size);
+ ASSERT_TRUE(
+ truncated_builder->AddAttributeEntry(Attribute::TITLE, "1234truncated"));
+ ASSERT_EQ(truncated_builder->size(), truncated_size);
+
+ ASSERT_FALSE(truncated_builder->AddAttributeEntry(Attribute::ARTIST_NAME,
+ "Can not add"));
+
+ auto truncated_packet = TestGetItemAttrsReqPacket::Make();
+ truncated_builder->Serialize(truncated_packet);
+
+ auto builder =
+ GetItemAttributesResponseBuilder::MakeBuilder(Status::NO_ERROR, 0xFFFF);
+ builder->AddAttributeEntry(attribute);
+ auto test_packet = TestGetItemAttrsReqPacket::Make();
+ builder->Serialize(test_packet);
+
+ ASSERT_EQ(truncated_packet->GetData(), test_packet->GetData());
+}
+
+TEST(GetItemAttributesResponseBuilderTest, errorStatusTest) {
+ std::vector<uint8_t> does_not_exist_status = {0x73, 0x00, 0x01, 0x09};
+ auto builder = GetItemAttributesResponseBuilder::MakeBuilder(
+ Status::DOES_NOT_EXIST, 0xFFFF);
+ ASSERT_EQ(builder->size(), does_not_exist_status.size());
+
+ auto test_packet = TestGetItemAttrsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), does_not_exist_status);
+}
+
+TEST(GetItemAttributesRequestTest, getterTest) {
+ auto test_packet = TestGetItemAttrsReqPacket::Make(
+ get_item_attributes_request_all_attributes);
+
+ ASSERT_EQ(test_packet->GetScope(), Scope::NOW_PLAYING);
+ ASSERT_EQ(test_packet->GetUidCounter(), 0x0000u);
+ ASSERT_EQ(test_packet->GetUid(), 0x0000000000000001u);
+ ASSERT_EQ(test_packet->GetNumAttributes(), 7);
+ std::vector<Attribute> attrs_requested = {Attribute::TITLE,
+ Attribute::ARTIST_NAME,
+ Attribute::ALBUM_NAME,
+ Attribute::TRACK_NUMBER,
+ Attribute::TOTAL_NUMBER_OF_TRACKS,
+ Attribute::GENRE,
+ Attribute::PLAYING_TIME};
+ ASSERT_EQ(test_packet->GetAttributesRequested(), attrs_requested);
+}
+
+TEST(GetItemAttributesRequestTest, validTest) {
+ auto test_packet = TestGetItemAttrsReqPacket::Make(
+ get_item_attributes_request_all_attributes);
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(GetItemAttributesRequestTest, invalidTest) {
+ auto packet_copy = get_item_attributes_request_all_attributes;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestGetItemAttrsReqPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07};
+ test_packet = TestGetItemAttrsReqPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/get_play_status_packet_test.cc b/packet/tests/avrcp/get_play_status_packet_test.cc
new file mode 100644
index 0000000..c15147d
--- /dev/null
+++ b/packet/tests/avrcp/get_play_status_packet_test.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "get_play_status_packet.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestGetPlayStatusRspPacket = TestPacketType<Packet>;
+
+TEST(GetPlayStatusResponseBuilderTest, builderTest) {
+ auto builder = GetPlayStatusResponseBuilder::MakeBuilder(0, 0xFFFFFFFF, 0);
+
+ ASSERT_EQ(builder->size(), get_play_status_response.size());
+
+ auto test_packet = TestGetPlayStatusRspPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_play_status_response);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/get_total_number_of_items_packet_test.cc b/packet/tests/avrcp/get_total_number_of_items_packet_test.cc
new file mode 100644
index 0000000..eb7efc2
--- /dev/null
+++ b/packet/tests/avrcp/get_total_number_of_items_packet_test.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "get_total_number_of_items.h"
+#include "packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestGetTotalNumItemsReqPacket =
+ TestPacketType<GetTotalNumberOfItemsRequest>;
+
+TEST(GetTotalNumberOfItemsResponseBuilderTest, builderTest) {
+ auto builder = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(
+ Status::NO_ERROR, 0x0000u, 0x00000005u);
+ ASSERT_EQ(builder->size(), get_total_number_of_items_response.size());
+
+ auto test_packet = TestGetTotalNumItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_total_number_of_items_response);
+}
+
+TEST(GetTotalNumberOfItemsResponseBuilderTest, errorStatusTest) {
+ std::vector<uint8_t> inv_scope_status_packet = {0x75, 0x00, 0x01, 0x0a};
+ auto builder = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(
+ Status::INVALID_SCOPE, 0x1234u, 0x56789abcu);
+ ASSERT_EQ(builder->size(), inv_scope_status_packet.size());
+
+ auto test_packet = TestGetTotalNumItemsReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), inv_scope_status_packet);
+}
+
+TEST(GetTotalNumberOfItemsRequestTest, getterTest) {
+ auto test_packet = TestGetTotalNumItemsReqPacket::Make(
+ get_total_number_of_items_request_now_playing);
+ ASSERT_EQ(test_packet->GetScope(), Scope::NOW_PLAYING);
+}
+
+TEST(GetTotalNumberOfItemsRequestTest, validTest) {
+ auto test_packet = TestGetTotalNumItemsReqPacket::Make(
+ get_total_number_of_items_request_now_playing);
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(GetTotalNumberOfItemsRequestTest, invalidTest) {
+ auto packet_copy = get_total_number_of_items_request_now_playing;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestGetTotalNumItemsReqPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x00, 0x01, 0x02, 0x03};
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/pass_through_packet_test.cc b/packet/tests/avrcp/pass_through_packet_test.cc
new file mode 100644
index 0000000..5ea749f
--- /dev/null
+++ b/packet/tests/avrcp/pass_through_packet_test.cc
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+#include "pass_through_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestPassThroughPacket = TestPacketType<PassThroughPacket>;
+
+TEST(PassThroughPacketBuilderTest, builderTest) {
+ auto builder = PassThroughPacketBuilder::MakeBuilder(false, true, 0x44);
+ ASSERT_EQ(builder->size(), pass_through_command_play_pushed.size());
+ auto test_packet = TestPassThroughPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), pass_through_command_play_pushed);
+
+ builder = PassThroughPacketBuilder::MakeBuilder(true, false, 0x44);
+ ASSERT_EQ(builder->size(), pass_through_command_play_released.size());
+ test_packet = TestPassThroughPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), pass_through_command_play_released);
+}
+
+TEST(PassThroughPacketTest, getterTest) {
+ auto test_packet =
+ TestPassThroughPacket::Make(pass_through_command_play_pushed);
+ ASSERT_EQ(test_packet->GetKeyState(), KeyState::PUSHED);
+ ASSERT_EQ(test_packet->GetOperationId(), 0x44);
+
+ test_packet = TestPassThroughPacket::Make(pass_through_command_play_released);
+ ASSERT_EQ(test_packet->GetKeyState(), KeyState::RELEASED);
+ ASSERT_EQ(test_packet->GetOperationId(), 0x44);
+}
+
+TEST(PassThroughPacketTest, validTest) {
+ auto test_packet =
+ TestPassThroughPacket::Make(pass_through_command_play_pushed);
+ ASSERT_TRUE(test_packet->IsValid());
+
+ test_packet = TestPassThroughPacket::Make(pass_through_command_play_released);
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(PassThroughPacketTest, invalidTest) {
+ std::vector<uint8_t> packet_copy = pass_through_command_play_pushed;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestPassThroughPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0, 1, 2, 3, 4, 5};
+ test_packet = TestPassThroughPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/play_item_packet_test.cc b/packet/tests/avrcp/play_item_packet_test.cc
new file mode 100644
index 0000000..f2e48aa
--- /dev/null
+++ b/packet/tests/avrcp/play_item_packet_test.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+#include "play_item.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestPlayItemReqPacket = TestPacketType<PlayItemRequest>;
+
+TEST(PlayItemResponseBuilderTest, builderTest) {
+ auto builder = PlayItemResponseBuilder::MakeBuilder(Status::NO_ERROR);
+ ASSERT_EQ(builder->size(), play_item_response.size());
+
+ auto test_packet = TestPlayItemReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), play_item_response);
+}
+
+TEST(PlayItemResponseTest, getterTest) {
+ auto test_packet = TestPlayItemReqPacket::Make(play_item_request);
+
+ ASSERT_EQ(test_packet->GetScope(), Scope::NOW_PLAYING);
+ ASSERT_EQ(test_packet->GetUid(), 0x0000000000000003u);
+ ASSERT_EQ(test_packet->GetUidCounter(), 0x0000u);
+}
+
+TEST(PlayItemResponseTest, validTest) {
+ auto test_packet = TestPlayItemReqPacket::Make(play_item_request);
+
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(PlayItemResponseTest, invalidTest) {
+ auto packet_copy = play_item_request;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestPlayItemReqPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x00, 0x01, 0x02, 0x03, 0x04};
+ test_packet = TestPlayItemReqPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/packet/tests/avrcp/register_notification_packet_test.cc b/packet/tests/avrcp/register_notification_packet_test.cc
new file mode 100644
index 0000000..abc0951
--- /dev/null
+++ b/packet/tests/avrcp/register_notification_packet_test.cc
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+#include "register_notification_packet.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestRegNotifReqPacket = TestPacketType<RegisterNotificationRequest>;
+using TestRegNotifRspPacket = TestPacketType<RegisterNotificationResponse>;
+
+TEST(RegisterNotificationRequestTest, getterTest) {
+ auto test_packet =
+ TestRegNotifReqPacket::Make(register_play_status_notification);
+
+ ASSERT_EQ(test_packet->GetEventRegistered(), Event::PLAYBACK_STATUS_CHANGED);
+ ASSERT_EQ(test_packet->GetInterval(), 5u);
+}
+
+TEST(RegisterNotificationRequestTest, validTest) {
+ auto test_packet =
+ TestRegNotifReqPacket::Make(register_play_status_notification);
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(RegisterNotificationRequestTest, invalidTest) {
+ std::vector<uint8_t> packet_copy = register_play_status_notification;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestRegNotifReqPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0, 1, 2, 3, 4};
+ test_packet = TestRegNotifReqPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+TEST(RegisterNotificationRequestBuilderTest, builderTest) {
+ auto builder =
+ RegisterNotificationRequestBuilder::MakeBuilder(Event::VOLUME_CHANGED, 0);
+ ASSERT_EQ(builder->size(), register_volume_changed_notification.size());
+
+ auto test_packet = TestRegNotifReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), register_volume_changed_notification);
+}
+
+TEST(RegisterNotificationResponseTest, volumeGetterTest) {
+ auto test_packet =
+ TestRegNotifRspPacket::Make(interim_volume_changed_notification);
+
+ ASSERT_TRUE(test_packet->IsInterim());
+ ASSERT_EQ(test_packet->GetEvent(), Event::VOLUME_CHANGED);
+ ASSERT_EQ(test_packet->GetVolume(), 0x47);
+}
+
+TEST(RegisterNotificationResponseTest, validTest) {
+ auto test_packet =
+ TestRegNotifRspPacket::Make(interim_volume_changed_notification);
+
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(RegisterNotificationResponseTest, invalidTest) {
+ std::vector<uint8_t> packet_copy = interim_volume_changed_notification;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestRegNotifRspPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0, 1, 2, 3, 4};
+ test_packet = TestRegNotifRspPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ auto wrong_ctype = interim_volume_changed_notification;
+ wrong_ctype[0] = 0x00;
+ test_packet = TestRegNotifRspPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+TEST(RegisterNotificationResponseTest, wrongEventDeathTest) {
+ auto wrong_event = interim_volume_changed_notification;
+ wrong_event[10] = 0x00;
+ auto test_packet = TestRegNotifRspPacket::Make(wrong_event);
+
+ ASSERT_DEATH(test_packet->GetVolume(),
+ "GetEvent\\(\\) == Event::VOLUME_CHANGED");
+}
+
+TEST(RegisterNotificationResponseBuilderTest, playStatusBuilderTest) {
+ auto builder = RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
+ true, 0x00);
+ ASSERT_EQ(builder->size(), interim_play_status_notification.size());
+ auto test_packet = TestRegNotifReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), interim_play_status_notification);
+}
+
+TEST(RegisterNotificationResponseBuilderTest, trackChangedBuilderTest) {
+ auto builder = RegisterNotificationResponseBuilder::MakeTrackChangedBuilder(
+ true, 0x0000000000000000);
+ ASSERT_EQ(builder->size(), interim_track_changed_notification.size());
+ auto test_packet = TestRegNotifReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), interim_track_changed_notification);
+}
+
+TEST(RegisterNotificationResponseBuilderTest, playPositionBuilderTest) {
+ auto builder =
+ RegisterNotificationResponseBuilder::MakePlaybackPositionBuilder(
+ false, 0x00000000);
+ ASSERT_EQ(builder->size(), changed_play_pos_notification.size());
+ auto test_packet = TestRegNotifReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), changed_play_pos_notification);
+}
+
+TEST(RegisterNotificationResponseBuilderTest, nowPlayingBuilderTest) {
+ auto builder =
+ RegisterNotificationResponseBuilder::MakeNowPlayingBuilder(true);
+ ASSERT_EQ(builder->size(), interim_now_playing_notification.size());
+ auto test_packet = TestRegNotifReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), interim_now_playing_notification);
+}
+
+TEST(RegisterNotificationResponseBuilderTest, availablePlayersBuilderTest) {
+ auto builder =
+ RegisterNotificationResponseBuilder::MakeAvailablePlayersBuilder(true);
+ ASSERT_EQ(builder->size(), interim_available_players_notification.size());
+ auto test_packet = TestRegNotifReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), interim_available_players_notification);
+}
+
+TEST(RegisterNotificationResponseBuilderTest, addressedPlayerBuilderTest) {
+ auto builder =
+ RegisterNotificationResponseBuilder::MakeAddressedPlayerBuilder(true, 1,
+ 0x0000);
+ ASSERT_EQ(builder->size(), interim_addressed_player_notification.size());
+ auto test_packet = TestRegNotifReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), interim_addressed_player_notification);
+}
+
+TEST(RegisterNotificationResponseBuilderTest, uidsChangedBuilderTest) {
+ auto builder =
+ RegisterNotificationResponseBuilder::MakeUidsChangedBuilder(true, 0x0000);
+ ASSERT_EQ(builder->size(), interim_uids_notificaiton.size());
+ auto test_packet = TestRegNotifReqPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), interim_uids_notificaiton);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/packet/tests/avrcp/set_absolute_volume_packet_test.cc b/packet/tests/avrcp/set_absolute_volume_packet_test.cc
new file mode 100644
index 0000000..8be462e
--- /dev/null
+++ b/packet/tests/avrcp/set_absolute_volume_packet_test.cc
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+#include "set_absolute_volume.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestSetVolumeRspPacket = TestPacketType<SetAbsoluteVolumeResponse>;
+
+TEST(SetAbsoluteVolumeRequestBuilderTest, builderTest) {
+ auto builder = SetAbsoluteVolumeRequestBuilder::MakeBuilder(0x48);
+ ASSERT_EQ(builder->size(), set_absolute_volume_request.size());
+
+ auto test_packet = TestSetVolumeRspPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), set_absolute_volume_request);
+}
+
+// Test whether the volume field has the highest bit masked
+TEST(SetAbsoluteVolumeRequestBuilderTest, volumeMaskTest) {
+ auto builder = SetAbsoluteVolumeRequestBuilder::MakeBuilder(0xc8);
+ auto test_packet = TestSetVolumeRspPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), set_absolute_volume_request);
+}
+
+TEST(SetAbsoluteVolumeResponseTest, getterTest) {
+ auto test_packet = TestSetVolumeRspPacket::Make(set_absolute_volume_response);
+
+ ASSERT_EQ(test_packet->GetVolume(), 0x43);
+}
+
+TEST(SetAbsoluteVolumeResponseTest, validTest) {
+ auto test_packet = TestSetVolumeRspPacket::Make(set_absolute_volume_response);
+
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(SetAbsoluteVolumeResponseTest, invalidTest) {
+ auto packet_copy = set_absolute_volume_request;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestSetVolumeRspPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x00, 0x01, 0x02, 0x03, 0x04};
+ test_packet = TestSetVolumeRspPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ auto wrong_ctype = set_absolute_volume_request;
+ wrong_ctype[0] = 0x00;
+ test_packet = TestSetVolumeRspPacket::Make(wrong_ctype);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/set_addressed_player_packet_test.cc b/packet/tests/avrcp/set_addressed_player_packet_test.cc
new file mode 100644
index 0000000..a6ced9e
--- /dev/null
+++ b/packet/tests/avrcp/set_addressed_player_packet_test.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+#include "set_addressed_player.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestSetAddrPlayerPacket = TestPacketType<SetAddressedPlayerRequest>;
+
+TEST(SetAddressedPlayerResponseBuilderTest, builderTest) {
+ auto builder =
+ SetAddressedPlayerResponseBuilder::MakeBuilder(Status::NO_ERROR);
+ ASSERT_EQ(builder->size(), set_addressed_player_response.size());
+
+ auto test_packet = TestSetAddrPlayerPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), set_addressed_player_response);
+}
+
+TEST(SetAddressedPlayerRequestTest, getterTest) {
+ auto test_packet =
+ TestSetAddrPlayerPacket::Make(set_addressed_player_request);
+
+ ASSERT_EQ(test_packet->GetPlayerId(), 0x0000u);
+}
+
+TEST(SetAddressedPlayerRequestTest, validTest) {
+ auto test_packet =
+ TestSetAddrPlayerPacket::Make(set_addressed_player_request);
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(SetAddressedPlayerRequestTest, invalidTest) {
+ auto packet_copy = set_addressed_player_request;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestSetAddrPlayerPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x00, 0x01, 0x02, 0x03, 0x04};
+ test_packet = TestSetAddrPlayerPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/packet/tests/avrcp/set_browsed_player_packet_test.cc b/packet/tests/avrcp/set_browsed_player_packet_test.cc
new file mode 100644
index 0000000..828df18
--- /dev/null
+++ b/packet/tests/avrcp/set_browsed_player_packet_test.cc
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+#include "set_browsed_player.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using TestSetBrowsedPlayerPacket = TestPacketType<SetBrowsedPlayerRequest>;
+
+TEST(SetBrowsedPlayerResponseBuilder, builderTest) {
+ auto builder = SetBrowsedPlayerResponseBuilder::MakeBuilder(Status::NO_ERROR,
+ 0x0000, 4, 0, "");
+ ASSERT_EQ(builder->size(), set_browsed_player_response.size());
+
+ auto test_packet = TestSetBrowsedPlayerPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), set_browsed_player_response);
+}
+
+TEST(SetBrowsedPlayerResponseBuilder, errorStatusTest) {
+ std::vector<uint8_t> player_not_browsable_status = {0x70, 0x00, 0x01, 0x12};
+ auto builder = SetBrowsedPlayerResponseBuilder::MakeBuilder(
+ Status::PLAYER_NOT_BROWSABLE, 0x1234, 5, 6, "Field Not Used");
+ ASSERT_EQ(builder->size(), player_not_browsable_status.size());
+
+ auto test_packet = TestSetBrowsedPlayerPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), player_not_browsable_status);
+}
+
+TEST(SetBrowsedPlayerRequestTest, getterTest) {
+ auto test_packet =
+ TestSetBrowsedPlayerPacket::Make(set_browsed_player_request);
+
+ ASSERT_EQ(test_packet->GetPlayerId(), 0x0002u);
+}
+
+TEST(SetBrowsedPlayerRequestTest, validTest) {
+ auto test_packet =
+ TestSetBrowsedPlayerPacket::Make(set_browsed_player_request);
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST(SetBrowsedPlayerRequestTest, invalidTest) {
+ auto packet_copy = set_browsed_player_request;
+ packet_copy.push_back(0x00);
+ auto test_packet = TestSetBrowsedPlayerPacket::Make(packet_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x00, 0x01, 0x02, 0x03, 0x04};
+ test_packet = TestSetBrowsedPlayerPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/avrcp/vendor_packet_test.cc b/packet/tests/avrcp/vendor_packet_test.cc
new file mode 100644
index 0000000..e933824
--- /dev/null
+++ b/packet/tests/avrcp/vendor_packet_test.cc
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <tuple>
+
+#include <gtest/gtest.h>
+
+#include "avrcp_test_packets.h"
+#include "packet_test_helper.h"
+#include "vendor_packet.h"
+
+namespace bluetooth {
+
+// A helper class that has public accessors to protected methods
+class TestPacketBuilder : public PacketBuilder {
+ public:
+ static std::unique_ptr<TestPacketBuilder> MakeBuilder(
+ std::vector<uint8_t> data) {
+ std::unique_ptr<TestPacketBuilder> builder(new TestPacketBuilder(data));
+ return builder;
+ };
+
+ // Make all the utility functions public
+ using PacketBuilder::ReserveSpace;
+ using PacketBuilder::AddPayloadOctets1;
+ using PacketBuilder::AddPayloadOctets2;
+ using PacketBuilder::AddPayloadOctets3;
+ using PacketBuilder::AddPayloadOctets4;
+ using PacketBuilder::AddPayloadOctets6;
+ using PacketBuilder::AddPayloadOctets8;
+
+ size_t size() const override { return data_.size(); };
+
+ bool Serialize(const std::shared_ptr<Packet>& pkt) override {
+ ReserveSpace(pkt, size());
+
+ for (uint8_t byte : data_) {
+ AddPayloadOctets1(pkt, byte);
+ }
+
+ return true;
+ }
+
+ TestPacketBuilder(std::vector<uint8_t> data) : data_(data){};
+
+ std::vector<uint8_t> data_;
+};
+
+namespace avrcp {
+
+using TestVendorPacket = TestPacketType<VendorPacket>;
+
+TEST(VendorPacketBuilderTest, builderTest) {
+ std::vector<uint8_t> get_cap_payload_data = {0x03};
+
+ auto get_cap_payload = TestPacketBuilder::MakeBuilder(get_cap_payload_data);
+
+ auto builder = VendorPacketBuilder::MakeBuilder(
+ CType::STATUS, CommandPdu::GET_CAPABILITIES, PacketType::SINGLE,
+ std::move(get_cap_payload));
+
+ ASSERT_EQ(builder->size(), get_capabilities_request.size());
+
+ auto test_packet = TestVendorPacket::Make();
+ builder->Serialize(test_packet);
+ ASSERT_EQ(test_packet->GetData(), get_capabilities_request);
+}
+
+using TestParam = std::tuple<std::vector<uint8_t>, CommandPdu>;
+class VendorPacketTest : public ::testing::TestWithParam<TestParam> {
+ public:
+ std::vector<uint8_t> GetPacketData() { return std::get<0>(GetParam()); }
+ CommandPdu GetCommandPdu() { return std::get<1>(GetParam()); }
+};
+
+INSTANTIATE_TEST_CASE_P(
+ VendorPacketParameterTest, VendorPacketTest,
+ ::testing::Values(
+ std::make_tuple(get_capabilities_request, CommandPdu::GET_CAPABILITIES),
+ std::make_tuple(get_capabilities_response_company_id,
+ CommandPdu::GET_CAPABILITIES),
+ std::make_tuple(get_capabilities_response_events_supported,
+ CommandPdu::GET_CAPABILITIES),
+ std::make_tuple(get_element_attributes_request_partial,
+ CommandPdu::GET_ELEMENT_ATTRIBUTES),
+ std::make_tuple(get_element_attributes_request_full,
+ CommandPdu::GET_ELEMENT_ATTRIBUTES),
+ std::make_tuple(get_elements_attributes_response_full,
+ CommandPdu::GET_ELEMENT_ATTRIBUTES),
+ std::make_tuple(get_play_status_request, CommandPdu::GET_PLAY_STATUS),
+ std::make_tuple(get_play_status_response, CommandPdu::GET_PLAY_STATUS),
+ std::make_tuple(register_play_status_notification,
+ CommandPdu::REGISTER_NOTIFICATION),
+ std::make_tuple(interim_play_status_notification,
+ CommandPdu::REGISTER_NOTIFICATION),
+ std::make_tuple(interim_track_changed_notification,
+ CommandPdu::REGISTER_NOTIFICATION),
+ std::make_tuple(changed_play_pos_notification,
+ CommandPdu::REGISTER_NOTIFICATION)));
+
+TEST_P(VendorPacketTest, getterTest) {
+ auto test_packet = TestVendorPacket::Make(GetPacketData());
+
+ ASSERT_EQ(test_packet->GetCompanyId(), BLUETOOTH_COMPANY_ID);
+ ASSERT_EQ(test_packet->GetCommandPdu(), GetCommandPdu());
+ ASSERT_EQ(test_packet->GetPacketType(), PacketType::SINGLE);
+ // ASSERT_EQ(test_packet->GetParameterLength(), 0x01);
+}
+
+TEST_P(VendorPacketTest, validTest) {
+ auto test_packet = TestVendorPacket::Make(GetPacketData());
+ ASSERT_TRUE(test_packet->IsValid());
+}
+
+TEST_F(VendorPacketTest, invalidTest) {
+ auto get_capabilities_request_copy = get_capabilities_request;
+ get_capabilities_request_copy.push_back(0x00);
+ auto test_packet = TestVendorPacket::Make(get_capabilities_request_copy);
+ ASSERT_FALSE(test_packet->IsValid());
+
+ std::vector<uint8_t> short_packet = {0x01, 0x02, 0x03, 0x04, 0x05};
+ test_packet = TestVendorPacket::Make(short_packet);
+ ASSERT_FALSE(test_packet->IsValid());
+}
+
+} // namespace avrcp
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/base/iterator_test.cc b/packet/tests/base/iterator_test.cc
new file mode 100644
index 0000000..5794686
--- /dev/null
+++ b/packet/tests/base/iterator_test.cc
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <memory>
+
+#include "packet.h"
+#include "packet_test_common.h"
+#include "test_packets.h"
+
+namespace bluetooth {
+
+using pair = std::pair<size_t, size_t>;
+
+class IteratorTest
+ : public ::testing::TestWithParam<std::pair<size_t, size_t>> {
+ public:
+ std::shared_ptr<TestPacket> GetTestPacket() {
+ auto bounds = GetParam();
+ auto lower_bound = bounds.first;
+ auto upper_bound = bounds.second;
+
+ return TestPacket::Make(test_l2cap_data, lower_bound, upper_bound);
+ }
+
+ size_t GetTestPacketLength() { return GetParam().second - GetParam().first; }
+
+ size_t GetLowerBound() { return GetParam().first; }
+
+ size_t GetUpperBound() { return GetParam().second; }
+};
+
+INSTANTIATE_TEST_CASE_P(IteratorParameterTest, IteratorTest,
+ ::testing::Values(pair(0, test_l2cap_data.size()),
+ pair(3, test_l2cap_data.size() - 2)));
+
+TEST_F(IteratorTest, iteratorCreateDeathTest) {
+ auto packet =
+ TestPacket::Make(test_l2cap_data, 3, test_l2cap_data.size() - 2);
+ ASSERT_DEATH(Iterator(packet, 0), "index_ >= packet->packet_start_index_");
+ ASSERT_DEATH(Iterator(packet, test_l2cap_data.size()),
+ "index_ <= packet->packet_end_index_");
+}
+
+TEST_F(IteratorTest, extractTest) {
+ auto packet = TestPacket::Make(test_l2cap_data);
+ Iterator general_case = packet->begin();
+
+ ASSERT_EQ(0x02u, general_case.extract<uint8_t>());
+ ASSERT_EQ(0x2edcu, general_case.extract<uint16_t>());
+ ASSERT_EQ(0x00620066u, general_case.extract<uint32_t>());
+ ASSERT_EQ(0x00010000000a0013u, general_case.extract<uint64_t>());
+}
+
+TEST_P(IteratorTest, payloadBoundsTest) {
+ auto packet = GetTestPacket();
+ ASSERT_EQ(static_cast<size_t>(packet->end() - packet->begin()),
+ GetTestPacketLength());
+
+ auto it = packet->begin();
+ for (size_t i = 0; i < GetTestPacketLength(); i++) {
+ ASSERT_EQ(test_l2cap_data[i + GetLowerBound()], *it++);
+ }
+}
+
+TEST_P(IteratorTest, extractBoundsDeathTest) {
+ auto packet = GetTestPacket();
+ Iterator bounds_test = packet->end();
+ ASSERT_DEATH(bounds_test.extract<uint8_t>(),
+ "index_ != packet_->packet_end_index_");
+ ASSERT_DEATH(bounds_test.extract<uint16_t>(),
+ "index_ != packet_->packet_end_index_");
+ ASSERT_DEATH(bounds_test.extract<uint32_t>(),
+ "index_ != packet_->packet_end_index_");
+ ASSERT_DEATH(bounds_test.extract<uint64_t>(),
+ "index_ != packet_->packet_end_index_");
+}
+
+TEST_P(IteratorTest, dereferenceDeathTest) {
+ auto packet = GetTestPacket();
+ Iterator dereference_test = packet->end();
+
+ ASSERT_EQ((*packet)[GetTestPacketLength() - 1],
+ *(dereference_test - static_cast<size_t>(1)));
+ ASSERT_DEATH(*dereference_test, "index_ != packet_->packet_end_index_");
+}
+
+TEST_P(IteratorTest, plusEqTest) {
+ auto packet = GetTestPacket();
+ Iterator plus_eq = packet->begin();
+ for (size_t i = 0; i < GetTestPacketLength(); i += 2) {
+ ASSERT_EQ(test_l2cap_data[i + GetLowerBound()], *plus_eq)
+ << "+= test: Dereferenced iterator does not equal expected at index "
+ << i;
+ plus_eq += 2;
+ }
+
+ ASSERT_EQ(plus_eq, packet->end());
+}
+
+TEST_P(IteratorTest, preIncrementTest) {
+ auto packet = GetTestPacket();
+ Iterator plus_plus = packet->begin();
+ for (size_t i = 0; i < GetTestPacketLength() - 1; i++) {
+ ASSERT_EQ(test_l2cap_data[i + GetLowerBound() + 1], *(++plus_plus))
+ << "Pre-increment test: Dereferenced iterator does not equal expected "
+ << "at index " << i;
+ }
+}
+
+TEST_P(IteratorTest, postIncrementTest) {
+ auto packet = GetTestPacket();
+ Iterator plus_plus = packet->begin();
+ for (size_t i = 0; i < GetTestPacketLength(); i++) {
+ ASSERT_EQ(test_l2cap_data[i + GetLowerBound()], *(plus_plus++))
+ << "Post-increment test: Dereferenced iterator does not equal expected "
+ << "at index " << i;
+ }
+}
+
+TEST_P(IteratorTest, additionTest) {
+ auto packet = GetTestPacket();
+ Iterator plus = packet->begin();
+ for (size_t i = 0; i < GetTestPacketLength(); i++) {
+ ASSERT_EQ(test_l2cap_data[i + GetLowerBound()], *plus)
+ << "+ test: Dereferenced iterator does not equal expected at index "
+ << i;
+ plus = plus + static_cast<size_t>(1);
+ }
+}
+
+TEST_P(IteratorTest, minusEqTest) {
+ auto packet = GetTestPacket();
+ Iterator minus_eq = packet->end();
+ minus_eq -= 1;
+ for (int i = GetTestPacketLength() - 1; i > 0; i -= 2) {
+ ASSERT_EQ(test_l2cap_data[static_cast<size_t>(i) + GetLowerBound()],
+ *minus_eq)
+ << "-= test: Dereferenced iterator does not equal expected at index "
+ << i;
+ minus_eq -= 2;
+ }
+}
+
+TEST_P(IteratorTest, preDecrementTest) {
+ auto packet = GetTestPacket();
+ Iterator minus_minus = packet->end();
+ for (int i = GetTestPacketLength(); i > 0; i--) {
+ ASSERT_EQ(test_l2cap_data[static_cast<size_t>(i) + GetLowerBound() - 1],
+ *(--minus_minus))
+ << "Pre-decrement test: Dereferenced iterator does not equal expected "
+ << "at index " << i;
+ }
+}
+
+TEST_P(IteratorTest, postDecrementTest) {
+ auto packet = GetTestPacket();
+ Iterator minus_minus = packet->end();
+ minus_minus--;
+ for (int i = GetTestPacketLength() - 1; i > 0; i--) {
+ ASSERT_EQ(test_l2cap_data[static_cast<size_t>(i) + GetLowerBound()],
+ *(minus_minus--))
+ << "Post-decrement test: Dereferenced iterator does not equal expected "
+ << "at index " << i;
+ }
+}
+
+TEST_P(IteratorTest, subtractionTest) {
+ auto packet = GetTestPacket();
+ Iterator minus = packet->end();
+ minus = minus - static_cast<size_t>(1);
+ for (int i = GetTestPacketLength() - 1; i > 0; i--) {
+ ASSERT_EQ(test_l2cap_data[static_cast<size_t>(i) + GetLowerBound()], *minus)
+ << "- test: Dereferenced iterator does not equal expected at index "
+ << i;
+ minus = minus - static_cast<size_t>(1);
+ }
+}
+
+TEST_P(IteratorTest, plusEqBoundsTest) {
+ auto packet = GetTestPacket();
+ Iterator plus_eq = packet->end();
+ for (size_t i = 0; i < 100; i++) {
+ plus_eq += i;
+ ASSERT_EQ(packet->end(), plus_eq)
+ << "+= test: Iterator exceeded the upper bound set by get_length()";
+ }
+}
+
+TEST_P(IteratorTest, preIncrementBoundsTest) {
+ auto packet = GetTestPacket();
+ Iterator plus_plus = packet->end();
+ plus_plus--;
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_EQ(packet->end(), ++plus_plus)
+ << "Pre-increment test: Iterator exceeded the upper bound set "
+ "by get_length()";
+ }
+}
+
+TEST_P(IteratorTest, postIncrementBoundsTest) {
+ auto packet = GetTestPacket();
+ Iterator plus_plus = packet->end();
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_EQ(packet->end(), plus_plus++)
+ << "Post-increment test: Iterator exceeded the upper bound set "
+ "by get_length()";
+ }
+}
+
+TEST_P(IteratorTest, additionBoundsTest) {
+ auto packet = GetTestPacket();
+ Iterator plus = packet->end();
+ for (size_t i = 0; i < 100; i++) {
+ plus = plus + static_cast<size_t>(i);
+ ASSERT_EQ(packet->end(), plus)
+ << "+ test: Iterator exceeded the upper bound set by get_length()";
+ }
+}
+
+TEST_P(IteratorTest, minusEqBoundsTest) {
+ auto packet = GetTestPacket();
+ Iterator minus_eq = packet->begin();
+ for (size_t i = 0; i < 100; i++) {
+ minus_eq -= i;
+ ASSERT_EQ(test_l2cap_data[GetLowerBound()], *minus_eq)
+ << "-= test: Iterator is less than the lower bound set by "
+ "packet->begin()";
+ }
+}
+
+TEST_P(IteratorTest, preDecrementBoundsTest) {
+ auto packet = GetTestPacket();
+ Iterator minus_minus = packet->begin();
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_EQ(test_l2cap_data[GetLowerBound()], *(--minus_minus))
+ << "Pre-decrement test: Iterator is less than the lower bound set by "
+ "packet->begin()";
+ }
+}
+
+TEST_P(IteratorTest, postDecrementBoundsTest) {
+ auto packet = GetTestPacket();
+ Iterator minus_minus = packet->begin();
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_EQ(test_l2cap_data[GetLowerBound()], *(minus_minus--))
+ << "Post-decrement test: Iterator is less than the lower bound set by "
+ "packet->begin()";
+ }
+}
+
+TEST_P(IteratorTest, subtractionBoundsTest) {
+ auto packet = GetTestPacket();
+ Iterator minus = packet->begin();
+ for (size_t i = 0; i < 100; i++) {
+ minus = minus - static_cast<size_t>(i);
+ ASSERT_EQ(test_l2cap_data[GetLowerBound()], *minus)
+ << "- test: Iterator is less than the lower bound set "
+ "by packet->begin()";
+ }
+}
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/base/packet_builder_test.cc b/packet/tests/base/packet_builder_test.cc
new file mode 100644
index 0000000..c057606
--- /dev/null
+++ b/packet/tests/base/packet_builder_test.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <memory>
+
+#include "packet.h"
+#include "packet_test_common.h"
+#include "test_packets.h"
+
+using std::vector;
+
+namespace bluetooth {
+
+TEST(PacketBuilderTest, serializeTest) {
+ auto builder = TestPacketBuilder::MakeBuilder(test_l2cap_data);
+ auto packet = TestPacket::Make();
+
+ builder->Serialize(packet);
+
+ for (size_t i = 0; i < test_l2cap_data.size(); i++) {
+ ASSERT_EQ(test_l2cap_data[i], (*packet)[i]);
+ }
+}
+
+TEST(PacketBuilderTest, sizeTest) {
+ auto builder = TestPacketBuilder::MakeBuilder(test_l2cap_data);
+
+ ASSERT_EQ(builder->size(), test_l2cap_data.size());
+}
+
+TEST(PacketBuilderTest, reserveSpaceTest) {
+ auto packet = TestPacket::Make();
+ ASSERT_EQ(packet->GetData().capacity(), 0u);
+
+ auto builder = TestPacketBuilder::MakeBuilder(test_l2cap_data);
+ builder->ReserveSpace(packet, test_l2cap_data.size());
+
+ ASSERT_GE(packet->GetData().capacity(), test_l2cap_data.size());
+}
+
+TEST(PacketBuilderTest, addPayloadOctetsTest) {
+ auto builder = TestPacketBuilder::MakeBuilder(test_l2cap_data);
+ auto packet = TestPacket::Make();
+
+ builder->AddPayloadOctets1(packet, 0x01u);
+ builder->AddPayloadOctets2(packet, 0x0302u);
+ builder->AddPayloadOctets3(packet, 0x060504u);
+ builder->AddPayloadOctets4(packet, 0x0A090807u);
+ builder->AddPayloadOctets6(packet, 0x100F0E0D0C0Bu);
+ builder->AddPayloadOctets8(packet, 0x1817161514131211u);
+
+ for (size_t i = 0; i < 0x18; i++) {
+ ASSERT_EQ((*packet)[i], i + 1);
+ }
+}
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/base/packet_test.cc b/packet/tests/base/packet_test.cc
new file mode 100644
index 0000000..2c4c147
--- /dev/null
+++ b/packet/tests/base/packet_test.cc
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "packet.h"
+#include "packet_test_common.h"
+#include "test_packets.h"
+
+namespace bluetooth {
+
+// Test making a packet from another packet. The new packet should have the
+// same payload bounds as the old packet.
+TEST(PacketTest, newPacketFromPacketTest) {
+ // Create a packet with payload bounds
+ auto packet = TestPacket::Make(
+ test_avctp_data, test_avctp_data_payload_offset, test_avctp_data.size());
+
+ // Create packet from bounded packet
+ auto new_packet = TestPacket::Make(packet);
+
+ // Check to see if the new packet is bounded by the payload of the old packet
+ auto it = new_packet->begin();
+ for (size_t i = 0; i < test_avrcp_data.size(); i++) {
+ ASSERT_EQ(test_avrcp_data[i], *it++);
+ }
+}
+
+// Test that the correct payload length is returned
+TEST(PacketTest, sizeTest) {
+ auto packet = TestPacket::Make(test_avctp_data);
+ ASSERT_EQ(packet->size(), test_avctp_data.size());
+
+ packet = TestPacket::Make(test_avctp_data, test_avctp_data_payload_offset,
+ test_avctp_data.size());
+ ASSERT_EQ(packet->size(), test_avrcp_data.size());
+}
+
+// Test the array access operator
+TEST(PacketTest, arrayAccessTest) {
+ auto packet = TestPacket::Make(test_l2cap_data);
+ for (size_t i = 0; i < test_l2cap_data.size(); i++) {
+ ASSERT_EQ(test_l2cap_data[i], (*packet)[i]);
+ }
+
+ packet = TestPacket::Make(test_avctp_data, test_avctp_data_payload_offset,
+ test_avctp_data.size());
+ for (size_t i = 0; i < test_avrcp_data.size(); i++) {
+ ASSERT_EQ(test_avrcp_data[i], (*packet)[i]);
+ }
+}
+
+// Test that accessing past the end of the defined payload dies
+TEST(PacketTest, arrayAccessDeathTest) {
+ auto packet =
+ TestPacket::Make(test_l2cap_data, 3, test_l2cap_data.size() - 2);
+ ASSERT_DEATH((*packet)[test_l2cap_data.size()], "");
+}
+
+// Test that the iterator and array access operator return the same data
+TEST(PacketTest, iteratorTest) {
+ auto packet = TestPacket::Make(
+ test_avctp_data, test_avctp_data_payload_offset, test_avctp_data.size());
+
+ // Check to see if the data matches
+ auto it = packet->begin();
+ for (size_t i = 0; i < packet->size(); i++) {
+ ASSERT_EQ((*packet)[i], *it++);
+ }
+
+ // Check to see if the iterator points to the end of the data
+ ASSERT_EQ(it, packet->end());
+}
+
+class ChildTestPacket : public TestPacket {
+ public:
+ using TestPacket::TestPacket;
+
+ std::string ToString() const override { return "ChildTestPacket"; };
+};
+
+// Test specializing a packet to another packet type
+TEST(PacketTest, specializeTest) {
+ auto packet = TestPacket::Make(test_l2cap_data);
+
+ std::shared_ptr<ChildTestPacket> specialized_packet =
+ Packet::Specialize<ChildTestPacket>(packet);
+
+ // Test that the new packet is an instance of ChildTestPacket
+ ASSERT_EQ(specialized_packet->ToString(), "ChildTestPacket");
+
+ // Test that the underlying data is the same and no copy took place
+ ASSERT_EQ(&specialized_packet->GetData(), &packet->GetData());
+}
+
+// Test that when the packet goes out of scope, that the underlying memory is
+// freed
+TEST(PacketTest, memoryFreeTest) {
+ auto packet = TestPacket::Make(test_l2cap_data);
+ std::weak_ptr<std::vector<uint8_t>> data_ptr(packet->GetDataPointer());
+
+ ASSERT_FALSE(data_ptr.expired());
+
+ packet.reset();
+
+ ASSERT_TRUE(data_ptr.expired());
+}
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/base/packet_test_common.h b/packet/tests/base/packet_test_common.h
new file mode 100644
index 0000000..26302ef
--- /dev/null
+++ b/packet/tests/base/packet_test_common.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "packet.h"
+#include "packet_test_helper.h"
+
+// We have our own definition of loghex to avoid dependencies
+namespace {
+template <typename T>
+std::string loghex(T x) {
+ std::stringstream tmp;
+ tmp << "0x" << std::internal << std::hex << std::setfill('0')
+ << std::setw(sizeof(T) * 2) << (unsigned int)x;
+ return tmp.str();
+}
+} // namespace
+
+namespace bluetooth {
+
+class PacketImpl : public Packet {
+ public:
+ using Packet::Packet; // Inherit constructors
+
+ virtual bool IsValid() const { return true; }
+
+ virtual std::string ToString() const {
+ std::stringstream ss;
+ ss << "TestPacket: Start = " << packet_start_index_
+ << " : End = " << packet_end_index_ << std::endl;
+ ss << " â”” Payload =";
+ for (auto it = begin(); it != end(); it++) {
+ ss << " " << loghex(*it);
+ }
+ ss << std::endl;
+
+ return ss.str();
+ };
+
+ virtual std::pair<size_t, size_t> GetPayloadIndecies() const {
+ return std::pair<size_t, size_t>(packet_start_index_, packet_end_index_);
+ }
+};
+
+using TestPacket = TestPacketType<PacketImpl>;
+
+// A helper class that has public accessors to protected methods
+class TestPacketBuilder : public PacketBuilder {
+ public:
+ static std::unique_ptr<TestPacketBuilder> MakeBuilder(
+ std::vector<uint8_t> data) {
+ std::unique_ptr<TestPacketBuilder> builder(new TestPacketBuilder(data));
+ return builder;
+ };
+
+ // Make all the utility functions public
+ using PacketBuilder::ReserveSpace;
+ using PacketBuilder::AddPayloadOctets1;
+ using PacketBuilder::AddPayloadOctets2;
+ using PacketBuilder::AddPayloadOctets3;
+ using PacketBuilder::AddPayloadOctets4;
+ using PacketBuilder::AddPayloadOctets6;
+ using PacketBuilder::AddPayloadOctets8;
+
+ size_t size() const override { return data_.size(); };
+
+ bool Serialize(const std::shared_ptr<Packet>& pkt) override {
+ ReserveSpace(pkt, size());
+
+ for (uint8_t byte : data_) {
+ AddPayloadOctets1(pkt, byte);
+ }
+
+ return true;
+ }
+
+ TestPacketBuilder(std::vector<uint8_t> data) : data_(data){};
+
+ std::vector<uint8_t> data_;
+};
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/packet_test_helper.h b/packet/tests/packet_test_helper.h
new file mode 100644
index 0000000..ad3db2c
--- /dev/null
+++ b/packet/tests/packet_test_helper.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "packet.h"
+
+namespace bluetooth {
+
+// A helper templated class to access the protected members of Packet to make
+// testing easier
+template <class PacketType>
+class TestPacketType : public PacketType {
+ public:
+ using PacketType::PacketType;
+
+ static std::shared_ptr<TestPacketType<PacketType>> Make() {
+ return std::shared_ptr<TestPacketType<PacketType>>(
+ new TestPacketType<PacketType>());
+ }
+
+ static std::shared_ptr<TestPacketType<PacketType>> Make(
+ std::shared_ptr<Packet> packet) {
+ return std::shared_ptr<TestPacketType<PacketType>>(
+ new TestPacketType<PacketType>(packet));
+ }
+
+ static std::shared_ptr<TestPacketType<PacketType>> Make(
+ std::vector<uint8_t> payload) {
+ size_t end = payload.size();
+ return Make(std::move(payload), 0, end);
+ }
+
+ static std::shared_ptr<TestPacketType<PacketType>> Make(
+ std::vector<uint8_t> payload, size_t start, size_t end) {
+ auto pkt = std::shared_ptr<TestPacketType<PacketType>>(
+ new TestPacketType<PacketType>());
+ pkt->packet_start_index_ = start;
+ pkt->packet_end_index_ = end;
+ pkt->data_ = std::make_shared<std::vector<uint8_t>>(std::move(payload));
+ return pkt;
+ }
+
+ const std::vector<uint8_t>& GetData() { return *PacketType::data_; }
+
+ std::shared_ptr<std::vector<uint8_t>> GetDataPointer() {
+ return PacketType::data_;
+ }
+};
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/packet/tests/test_packets.h b/packet/tests/test_packets.h
new file mode 100644
index 0000000..0e0db42
--- /dev/null
+++ b/packet/tests/test_packets.h
@@ -0,0 +1,50 @@
+#pragma once
+
+namespace {
+
+// L2CAP packet pulled from Wireshark
+std::vector<uint8_t> test_l2cap_data = {
+ 0x02, 0xdc, 0x2e, 0x66, 0x00, 0x62, 0x00, 0x13, 0x00, 0x0a, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0xb8, 0x9c, 0x00, 0x80, 0x56, 0x00, 0x43, 0xc4, 0x9a,
+ 0x86, 0x36, 0x10, 0x00, 0x26, 0x43, 0x1c, 0x9b, 0x88, 0x1d, 0x06, 0x03,
+ 0x26, 0x86, 0x36, 0x10, 0x00, 0x26, 0x43, 0xb4, 0x9b, 0x88, 0x1d, 0x06,
+ 0x03, 0x26, 0x86, 0x36, 0x10, 0x00, 0x26, 0x43, 0xe4, 0x9b, 0x88, 0x1d,
+ 0x06, 0x03, 0x26, 0x86, 0x36, 0x10, 0x00, 0x26, 0x43, 0xf8, 0x9b, 0x88,
+ 0x1d, 0x06, 0x03, 0x26, 0x86, 0x36, 0x10, 0x00, 0x26, 0x43, 0x08, 0x9c,
+ 0x88, 0x1d, 0x06, 0x03, 0x26, 0x86, 0x36, 0x10, 0x00, 0x26, 0x43, 0xa8,
+ 0x9c, 0x88, 0x1d, 0x06, 0x03, 0x26, 0x86, 0x36, 0x10, 0x00, 0x26};
+
+// AVCTP packet pulled from Wireshark
+std::vector<uint8_t> test_avctp_data = {
+ 0xf2, 0x11, 0x0e, 0x0c, 0x48, 0x00, 0x00, 0x19, 0x58, 0x20, 0x00, 0x00,
+ 0x85, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6a, 0x00, 0x22, 0x57, 0x61,
+ 0x72, 0x20, 0x50, 0x69, 0x67, 0x73, 0x20, 0x28, 0x32, 0x30, 0x30, 0x39,
+ 0x20, 0x52, 0x65, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x6a, 0x00, 0x0d, 0x42, 0x6c, 0x61, 0x63, 0x6b, 0x20, 0x53, 0x61,
+ 0x62, 0x62, 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6a, 0x00,
+ 0x17, 0x54, 0x68, 0x65, 0x20, 0x55, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x74,
+ 0x65, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x6a, 0x00, 0x06, 0x34, 0x37, 0x33, 0x30,
+ 0x30, 0x30};
+
+// An avrcp packet pulled from wireshark. This data is the payload of
+// test_avctp_packet
+size_t test_avctp_data_payload_offset = 3;
+std::vector<uint8_t> test_avrcp_data = {
+ 0x0c, 0x48, 0x00, 0x00, 0x19, 0x58, 0x20, 0x00, 0x00, 0x85, 0x07, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x6a, 0x00, 0x22, 0x57, 0x61, 0x72, 0x20, 0x50,
+ 0x69, 0x67, 0x73, 0x20, 0x28, 0x32, 0x30, 0x30, 0x39, 0x20, 0x52, 0x65,
+ 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72,
+ 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6a, 0x00,
+ 0x0d, 0x42, 0x6c, 0x61, 0x63, 0x6b, 0x20, 0x53, 0x61, 0x62, 0x62, 0x61,
+ 0x74, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6a, 0x00, 0x17, 0x54, 0x68,
+ 0x65, 0x20, 0x55, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x43,
+ 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x6a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x6a, 0x00, 0x06, 0x34, 0x37, 0x33, 0x30, 0x30, 0x30};
+
+} // namespace
\ No newline at end of file
diff --git a/profile/avrcp/Android.bp b/profile/avrcp/Android.bp
new file mode 100644
index 0000000..1e27861
--- /dev/null
+++ b/profile/avrcp/Android.bp
@@ -0,0 +1,48 @@
+cc_library_static {
+ name: "avrcp-target-service",
+ defaults: ["fluoride_defaults"],
+ host_supported: true,
+ include_dirs: [
+ "system/bt",
+ "system/bt/btcore/include",
+ "system/bt/internal_include",
+ "system/bt/stack/include",
+ ],
+ export_include_dirs: ["./"],
+ srcs: [
+ "connection_handler.cc",
+ "device.cc",
+ ],
+ static_libs: [
+ "lib-bt-packets",
+ "libbluetooth-types",
+ "libosi",
+ ],
+}
+
+cc_test {
+ name: "net_test_avrcp",
+ defaults: ["fluoride_defaults"],
+ host_supported: true,
+ include_dirs: [
+ "system/bt",
+ "system/bt/btcore/include",
+ "system/bt/internal_include",
+ "system/bt/stack/include",
+ ],
+ srcs: [
+ "tests/avrcp_connection_handler_test.cc",
+ "tests/avrcp_device_test.cc",
+ ],
+ static_libs: [
+ "libgmock",
+ "lib-bt-packets",
+ "libosi",
+ "avrcp-target-service",
+ ],
+ sanitize: {
+ cfi: false,
+ },
+
+ cflags: ["-DBUILDCFG"],
+}
diff --git a/profile/avrcp/avrcp_internal.h b/profile/avrcp/avrcp_internal.h
new file mode 100644
index 0000000..c2e6549
--- /dev/null
+++ b/profile/avrcp/avrcp_internal.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "stack/include/avrc_api.h"
+#include "stack/include/sdp_api.h"
+
+/**
+ * Wrapper classes for the API functions currently defined in "system/bt/stack".
+ * ConnectionHandler and AvrcpDevice both use this interface to manage AVRCP
+ * SDP, connections, and packets. We use these intermediate interfaces instead
+ * of calling the functions directly in order to make mocking and testing
+ * easier.
+ */
+// TODO (apanicke): Update the api's in "system/bt/stack" so that no wrapper is
+// required
+class AvrcpInterface {
+ public:
+ virtual uint16_t AddRecord(uint16_t service_uuid, const char* p_service_name,
+ const char* p_provider_name, uint16_t categories,
+ uint32_t sdp_handle, bool browse_supported,
+ uint16_t profile_version) = 0;
+
+ virtual uint16_t FindService(uint16_t service_uuid, const RawAddress& bd_addr,
+ tAVRC_SDP_DB_PARAMS* p_db,
+ tAVRC_FIND_CBACK p_cback) = 0;
+
+ virtual uint16_t Open(uint8_t* p_handle, tAVRC_CONN_CB* p_ccb,
+ const RawAddress& bd_addr) = 0;
+
+ virtual uint16_t OpenBrowse(uint8_t handle, uint8_t conn_role) = 0;
+
+ virtual uint16_t GetPeerMtu(uint8_t handle) = 0;
+
+ virtual uint16_t GetBrowseMtu(uint8_t handle) = 0;
+
+ virtual uint16_t Close(uint8_t handle) = 0;
+
+ virtual uint16_t CloseBrowse(uint8_t handle) = 0;
+
+ virtual uint16_t MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
+ BT_HDR* p_pkt) = 0;
+
+ virtual ~AvrcpInterface() = default;
+};
+
+class SdpInterface {
+ public:
+ virtual bool InitDiscoveryDb(tSDP_DISCOVERY_DB* a, uint32_t b, uint16_t c,
+ const bluetooth::Uuid* d, uint16_t e,
+ uint16_t* f) = 0;
+
+ virtual bool ServiceSearchAttributeRequest(const RawAddress& a,
+ tSDP_DISCOVERY_DB* b,
+ tSDP_DISC_CMPL_CB* c) = 0;
+
+ virtual tSDP_DISC_REC* FindServiceInDb(tSDP_DISCOVERY_DB* a, uint16_t b,
+ t_sdp_disc_rec* c) = 0;
+
+ virtual tSDP_DISC_ATTR* FindAttributeInRec(t_sdp_disc_rec* a, uint16_t b) = 0;
+
+ virtual bool FindProfileVersionInRec(t_sdp_disc_rec* a, uint16_t b,
+ uint16_t* c) = 0;
+
+ virtual ~SdpInterface() = default;
+};
+
+class A2dpInterface {
+ public:
+ virtual RawAddress active_peer() = 0;
+
+ virtual ~A2dpInterface() = default;
+};
\ No newline at end of file
diff --git a/profile/avrcp/avrcp_message_converter.h b/profile/avrcp/avrcp_message_converter.h
new file mode 100644
index 0000000..389a497
--- /dev/null
+++ b/profile/avrcp/avrcp_message_converter.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <iostream>
+#include <vector>
+
+#include "avrcp_packet.h"
+
+// These classes are temporary placeholders to easily switch between BT_HDR and
+// packets.
+class VectorPacket : public ::bluetooth::Packet {
+ public:
+ using Packet::Packet; // Inherit constructors
+
+ static std::shared_ptr<VectorPacket> Make() {
+ return std::shared_ptr<VectorPacket>(new VectorPacket());
+ };
+
+ static std::shared_ptr<VectorPacket> Make(std::vector<uint8_t> payload) {
+ auto pkt = VectorPacket::Make();
+ pkt->packet_start_index_ = 0;
+ pkt->packet_end_index_ = payload.size();
+ pkt->data_ = std::make_shared<std::vector<uint8_t>>(std::move(payload));
+ return pkt;
+ };
+
+ const std::vector<uint8_t>& GetData() { return *data_; };
+
+ virtual std::string ToString() const {
+ std::stringstream ss;
+ ss << "VectorPacket:" << std::endl;
+ ss << " â”” Payload =";
+ for (auto it = begin(); it != end(); it++) {
+ ss << " " << loghex(*it);
+ }
+ ss << std::endl;
+
+ return ss.str();
+ };
+
+ virtual std::pair<size_t, size_t> GetPayloadIndecies() const override {
+ return std::pair<size_t, size_t>(packet_start_index_, packet_end_index_);
+ }
+
+ virtual bool IsValid() const override { return true; }
+};
+
+// TODO (apanicke): When deleting the old AVRCP Stack, remove this class and
+// instead create a BT_HDR Parsing packet.
+class AvrcpMessageConverter {
+ public:
+ static std::shared_ptr<::bluetooth::Packet> Parse(tAVRC_MSG* m) {
+ std::vector<uint8_t> data;
+
+ switch (m->hdr.opcode) {
+ case AVRC_OP_VENDOR: {
+ tAVRC_MSG_VENDOR* msg = (tAVRC_MSG_VENDOR*)m;
+ data.push_back(m->hdr.ctype);
+ data.push_back((m->hdr.subunit_type << 3) | m->hdr.subunit_id);
+ data.push_back(m->hdr.opcode);
+ for (int i = 2; i >= 0; i--) {
+ data.push_back((uint8_t)((msg->company_id >> i * 8) & 0xff));
+ }
+ for (uint8_t i = 0; i < msg->vendor_len; i++) {
+ data.push_back(msg->p_vendor_data[i]);
+ }
+ } break;
+ case AVRC_OP_PASS_THRU: {
+ tAVRC_MSG_PASS* msg = (tAVRC_MSG_PASS*)m;
+ data.push_back(m->hdr.ctype);
+ data.push_back((m->hdr.subunit_type << 3) | m->hdr.subunit_id);
+ data.push_back(m->hdr.opcode);
+ data.push_back((msg->state << 7) | msg->op_id);
+ data.push_back(0x00);
+ } break;
+ case AVRC_OP_BROWSE: {
+ tAVRC_MSG_BROWSE* msg = (tAVRC_MSG_BROWSE*)m;
+ // The first 3 bytes are header bytes that aren't actually in AVRCP
+ // packets
+ for (int i = 0; i < msg->browse_len; i++) {
+ data.push_back(msg->p_browse_data[i]);
+ }
+ } break;
+ default:
+ LOG(ERROR) << "Unknown opcode for AVRCP message";
+ break;
+ }
+
+ return VectorPacket::Make(data);
+ }
+};
\ No newline at end of file
diff --git a/profile/avrcp/connection_handler.cc b/profile/avrcp/connection_handler.cc
new file mode 100644
index 0000000..874bf77
--- /dev/null
+++ b/profile/avrcp/connection_handler.cc
@@ -0,0 +1,522 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "connection_handler.h"
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <map>
+
+#include "avrc_defs.h"
+#include "avrcp_message_converter.h"
+#include "avrcp_packet.h"
+#include "bt_types.h"
+#include "btu.h"
+// TODO (apanicke): Remove dependency on this header once we cleanup feature
+// handling.
+#include "bta/include/bta_av_api.h"
+#include "osi/include/allocator.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+ConnectionHandler* ConnectionHandler::instance_ = nullptr;
+
+ConnectionHandler* ConnectionHandler::Get() {
+ CHECK(instance_);
+
+ return instance_;
+}
+
+bool ConnectionHandler::Initialize(const ConnectionCallback& callback,
+ AvrcpInterface* avrcp, SdpInterface* sdp,
+ VolumeInterface* vol) {
+ CHECK(instance_ == nullptr);
+ CHECK(avrcp != nullptr);
+ CHECK(sdp != nullptr);
+
+ // TODO (apanicke): When transitioning to using this service, implement
+ // SDP Initialization for AVRCP Here.
+ instance_ = new ConnectionHandler();
+ instance_->connection_cb_ = callback;
+ instance_->avrc_ = avrcp;
+ instance_->sdp_ = sdp;
+ instance_->vol_ = vol;
+
+ // Set up the AVRCP acceptor connection
+ if (!instance_->AvrcpConnect(false, RawAddress::kAny)) {
+ instance_->CleanUp();
+ return false;
+ }
+
+ return true;
+}
+
+bool ConnectionHandler::CleanUp() {
+ CHECK(instance_ != nullptr);
+
+ // TODO (apanicke): Cleanup the SDP Entries here
+ for (const auto& entry : instance_->device_map_) {
+ entry.second->DeviceDisconnected();
+ instance_->avrc_->Close(entry.first);
+ }
+ instance_->device_map_.clear();
+ instance_->feature_map_.clear();
+
+ instance_->weak_ptr_factory_.InvalidateWeakPtrs();
+
+ delete instance_;
+ instance_ = nullptr;
+
+ return true;
+}
+
+void ConnectionHandler::InitForTesting(ConnectionHandler* handler) {
+ CHECK(instance_ == nullptr);
+ instance_ = handler;
+}
+
+bool ConnectionHandler::ConnectDevice(const RawAddress& bdaddr) {
+ LOG(INFO) << "Attempting to connect to device " << bdaddr;
+
+ for (const auto& pair : device_map_) {
+ if (bdaddr == pair.second->GetAddress()) {
+ LOG(WARNING) << "Already connected to device with address " << bdaddr;
+ return false;
+ }
+ }
+
+ auto connection_lambda = [](ConnectionHandler* instance_,
+ const RawAddress& bdaddr, uint16_t status,
+ uint16_t version, uint16_t features) {
+ LOG(INFO) << __PRETTY_FUNCTION__
+ << " SDP Completed features=" << loghex(features);
+ if (status != AVRC_SUCCESS || !(features & BTA_AV_FEAT_RCCT)) {
+ LOG(ERROR) << "Failed to do SDP: status=" << loghex(status)
+ << " features=" << loghex(features)
+ << " supports controller: " << (features & BTA_AV_FEAT_RCCT);
+ instance_->connection_cb_.Run(std::shared_ptr<Device>());
+ }
+
+ instance_->feature_map_.emplace(bdaddr, features);
+ instance_->AvrcpConnect(true, bdaddr);
+ return;
+ };
+
+ return SdpLookup(bdaddr, base::Bind(connection_lambda, this, bdaddr));
+}
+
+bool ConnectionHandler::DisconnectDevice(const RawAddress& bdaddr) {
+ for (auto it = device_map_.begin(); it != device_map_.end(); it++) {
+ if (bdaddr == it->second->GetAddress()) {
+ it->second->DeviceDisconnected();
+ uint8_t handle = it->first;
+ device_map_.erase(handle);
+ return avrc_->Close(handle) == AVRC_SUCCESS;
+ }
+ }
+
+ return false;
+}
+
+std::vector<std::shared_ptr<Device>> ConnectionHandler::GetListOfDevices()
+ const {
+ std::vector<std::shared_ptr<Device>> list;
+ for (auto device : device_map_) {
+ list.push_back(device.second);
+ }
+ return list;
+}
+
+bool ConnectionHandler::SdpLookup(const RawAddress& bdaddr, SdpCallback cb) {
+ LOG(INFO) << __PRETTY_FUNCTION__;
+
+ tAVRC_SDP_DB_PARAMS db_params;
+ // TODO (apanicke): This needs to be replaced with smarter memory management.
+ tSDP_DISCOVERY_DB* disc_db =
+ (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
+ uint16_t attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
+ ATTR_ID_BT_PROFILE_DESC_LIST,
+ ATTR_ID_SUPPORTED_FEATURES};
+
+ db_params.db_len =
+ BT_DEFAULT_BUFFER_SIZE; // Some magic number found in the AVRCP code
+ db_params.num_attr = sizeof(attr_list) / sizeof(attr_list[0]);
+ db_params.p_db = disc_db;
+ db_params.p_attrs = attr_list;
+
+ return avrc_->FindService(
+ UUID_SERVCLASS_AV_REMOTE_CONTROL, bdaddr, &db_params,
+ base::Bind(&ConnectionHandler::SdpCb, base::Unretained(this),
+ bdaddr, cb, disc_db)) == AVRC_SUCCESS;
+}
+
+bool ConnectionHandler::AvrcpConnect(bool initiator, const RawAddress& bdaddr) {
+ LOG(INFO) << "Connect to device " << bdaddr.ToString();
+
+ tAVRC_CONN_CB open_cb;
+ if (initiator) {
+ open_cb.ctrl_cback = base::Bind(&ConnectionHandler::InitiatorControlCb,
+ weak_ptr_factory_.GetWeakPtr());
+ } else {
+ open_cb.ctrl_cback = base::Bind(&ConnectionHandler::AcceptorControlCb,
+ weak_ptr_factory_.GetWeakPtr());
+ }
+ open_cb.msg_cback =
+ base::Bind(&ConnectionHandler::MessageCb, base::Unretained(this));
+ open_cb.company_id = AVRC_CO_GOOGLE;
+ open_cb.conn = initiator ? AVRC_CONN_INT
+ : AVRC_CONN_ACP; // 0 if initiator, 1 if acceptor
+ // TODO (apanicke): We shouldn't need RCCT to do absolute volume. The current
+ // AVRC_API requires it though.
+ open_cb.control = BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_METADATA;
+
+ uint8_t handle = 0;
+ uint16_t status = avrc_->Open(&handle, &open_cb, bdaddr);
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": handle=" << loghex(handle)
+ << " status= " << loghex(status);
+ return status == AVRC_SUCCESS;
+}
+
+void ConnectionHandler::InitiatorControlCb(uint8_t handle, uint8_t event,
+ uint16_t result,
+ const RawAddress* peer_addr) {
+ DCHECK(!connection_cb_.is_null());
+
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": handle=" << loghex(handle)
+ << " result=" << loghex(result)
+ << " addr=" << (peer_addr ? peer_addr->ToString() : "none");
+
+ switch (event) {
+ case AVRC_OPEN_IND_EVT: {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Opened Event";
+
+ const auto& feature_iter = feature_map_.find(*peer_addr);
+ if (feature_iter == feature_map_.end()) {
+ LOG(ERROR) << "Features do not exist even though SDP should have been "
+ "done first";
+ return;
+ }
+
+ bool supports_browsing = feature_iter->second & BTA_AV_FEAT_BROWSE;
+
+ if (supports_browsing) {
+ avrc_->OpenBrowse(handle, AVCT_INT);
+ }
+
+ // TODO (apanicke): Implement a system to cache SDP entries. For most
+ // devices SDP is completed after the device connects AVRCP so that
+ // information isn't very useful when trying to control our
+ // capabilities. For now always use AVRCP 1.6.
+ auto&& callback = base::Bind(&ConnectionHandler::SendMessage,
+ base::Unretained(this), handle);
+ auto&& ctrl_mtu = avrc_->GetPeerMtu(handle) - AVCT_HDR_LEN;
+ auto&& browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
+ std::shared_ptr<Device> newDevice = std::make_shared<Device>(
+ *peer_addr, !supports_browsing, callback, ctrl_mtu, browse_mtu);
+
+ device_map_[handle] = newDevice;
+ // TODO (apanicke): Create the device with all of the interfaces it
+ // needs. Return the new device where the service will register the
+ // interfaces it needs.
+ connection_cb_.Run(newDevice);
+
+ if (feature_iter->second & BTA_AV_FEAT_ADV_CTRL) {
+ newDevice->RegisterVolumeChanged();
+ } else if (instance_->vol_ != nullptr) {
+ instance_->vol_->DeviceConnected(newDevice->GetAddress());
+ }
+
+ } break;
+
+ case AVRC_CLOSE_IND_EVT: {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Closed Event";
+
+ if (device_map_.find(handle) == device_map_.end()) {
+ LOG(WARNING)
+ << "Connection Close received from device that doesn't exist";
+ return;
+ }
+ avrc_->Close(handle);
+ feature_map_.erase(device_map_[handle]->GetAddress());
+ device_map_[handle]->DeviceDisconnected();
+ device_map_.erase(handle);
+ } break;
+
+ case AVRC_BROWSE_OPEN_IND_EVT:
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Open Event";
+ // NOTE (apanicke): We don't need to explicitly handle this message
+ // since the AVCTP Layer will still send us browsing messages
+ // regardless. It would be useful to note this though for future
+ // compatibility issues.
+ break;
+ case AVRC_BROWSE_CLOSE_IND_EVT:
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Close Event";
+ break;
+ default:
+ LOG(ERROR) << "Unknown AVRCP Control event";
+ break;
+ }
+}
+
+void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event,
+ uint16_t result,
+ const RawAddress* peer_addr) {
+ DCHECK(!connection_cb_.is_null());
+
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": handle=" << loghex(handle)
+ << " result=" << loghex(result)
+ << " addr=" << (peer_addr ? peer_addr->ToString() : "none");
+
+ switch (event) {
+ case AVRC_OPEN_IND_EVT: {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Opened Event";
+
+ auto&& callback = base::Bind(&ConnectionHandler::SendMessage,
+ base::Unretained(this), handle);
+ auto&& ctrl_mtu = avrc_->GetPeerMtu(handle) - AVCT_HDR_LEN;
+ auto&& browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
+ std::shared_ptr<Device> newDevice = std::make_shared<Device>(
+ *peer_addr, false, callback, ctrl_mtu, browse_mtu);
+
+ device_map_[handle] = newDevice;
+ connection_cb_.Run(newDevice);
+
+ LOG(INFO) << __PRETTY_FUNCTION__
+ << ": Performing SDP on connected device. address="
+ << peer_addr->ToString();
+ auto sdp_lambda = [](ConnectionHandler* instance_, uint8_t handle,
+ uint16_t status, uint16_t version,
+ uint16_t features) {
+ if (instance_->device_map_.find(handle) ==
+ instance_->device_map_.end()) {
+ LOG(WARNING) << __PRETTY_FUNCTION__
+ << ": No device found for handle: " << loghex(handle);
+ return;
+ }
+
+ auto device = instance_->device_map_[handle];
+ instance_->feature_map_.emplace(device->GetAddress(), features);
+
+ // TODO (apanicke): Report to the VolumeInterface that a new Device is
+ // connected that doesn't support absolute volume.
+ if (features & BTA_AV_FEAT_ADV_CTRL) {
+ device->RegisterVolumeChanged();
+ } else if (instance_->vol_ != nullptr) {
+ instance_->vol_->DeviceConnected(device->GetAddress());
+ }
+ };
+
+ SdpLookup(*peer_addr, base::Bind(sdp_lambda, this, handle));
+
+ avrc_->OpenBrowse(handle, AVCT_ACP);
+ AvrcpConnect(false, RawAddress::kAny);
+ } break;
+
+ case AVRC_CLOSE_IND_EVT: {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Closed Event";
+
+ if (device_map_.find(handle) == device_map_.end()) {
+ LOG(WARNING)
+ << "Connection Close received from device that doesn't exist";
+ return;
+ }
+ avrc_->Close(handle);
+ feature_map_.erase(device_map_[handle]->GetAddress());
+ device_map_[handle]->DeviceDisconnected();
+ device_map_.erase(handle);
+ } break;
+
+ case AVRC_BROWSE_OPEN_IND_EVT:
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Open Event";
+ // NOTE (apanicke): We don't need to explicitly handle this message
+ // since the AVCTP Layer will still send us browsing messages
+ // regardless. It would be useful to note this though for future
+ // compatibility issues.
+ break;
+ case AVRC_BROWSE_CLOSE_IND_EVT:
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Close Event";
+ break;
+ default:
+ LOG(ERROR) << "Unknown AVRCP Control event";
+ break;
+ }
+}
+
+void ConnectionHandler::MessageCb(uint8_t handle, uint8_t label, uint8_t opcode,
+ tAVRC_MSG* p_msg) {
+ if (device_map_[handle] == nullptr) {
+ LOG(ERROR) << "Message received for unconnected device: handle="
+ << loghex(handle);
+ return;
+ }
+
+ auto pkt = AvrcpMessageConverter::Parse(p_msg);
+
+ if (opcode == AVRC_OP_BROWSE) {
+ VLOG(4) << "Browse Message received on handle " << (unsigned int)handle;
+ device_map_[handle]->BrowseMessageReceived(label, BrowsePacket::Parse(pkt));
+ return;
+ }
+
+ VLOG(4) << "Message received on handle " << (unsigned int)handle;
+ device_map_[handle]->MessageReceived(label, Packet::Parse(pkt));
+}
+
+void ConnectionHandler::SdpCb(const RawAddress& bdaddr, SdpCallback cb,
+ tSDP_DISCOVERY_DB* disc_db, uint16_t status) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": SDP lookup callback received";
+
+ if (status != AVRC_SUCCESS) {
+ LOG(ERROR) << __PRETTY_FUNCTION__
+ << ": SDP Failure: status = " << (unsigned int)status;
+ cb.Run(status, 0, 0);
+ osi_free(disc_db);
+ return;
+ }
+
+ // Check the peer features
+ tSDP_DISC_REC* sdp_record = nullptr;
+ uint16_t peer_features = 0;
+ uint16_t peer_avrcp_version = 0;
+
+ // TODO (apanicke): Replace this in favor of our own supported features.
+ sdp_record =
+ sdp_->FindServiceInDb(disc_db, UUID_SERVCLASS_AV_REMOTE_CONTROL, nullptr);
+ if (sdp_record != nullptr) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
+ << " supports remote control";
+ peer_features |= BTA_AV_FEAT_RCCT;
+
+ if ((sdp_->FindAttributeInRec(sdp_record, ATTR_ID_BT_PROFILE_DESC_LIST)) !=
+ NULL) {
+ /* get profile version (if failure, version parameter is not updated) */
+ sdp_->FindProfileVersionInRec(
+ sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_avrcp_version);
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
+ << " peer avrcp version=" << loghex(peer_avrcp_version);
+
+ if (peer_avrcp_version >= AVRC_REV_1_3) {
+ // These are the standard features, another way to check this is to
+ // search for CAT1 on the remote device
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
+ << " supports metadata";
+ peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
+ }
+ if (peer_avrcp_version >= AVRC_REV_1_4) {
+ /* get supported categories */
+ LOG(INFO) << __PRETTY_FUNCTION__ << " Get Supported categories";
+ tSDP_DISC_ATTR* sdp_attribute =
+ sdp_->FindAttributeInRec(sdp_record, ATTR_ID_SUPPORTED_FEATURES);
+ if (sdp_attribute != NULL) {
+ LOG(INFO) << __PRETTY_FUNCTION__
+ << "Get Supported categories SDP ATTRIBUTES != null";
+ uint16_t categories = sdp_attribute->attr_value.v.u16;
+ if (categories & AVRC_SUPF_CT_CAT2) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
+ << " supports advanced control";
+ peer_features |= (BTA_AV_FEAT_ADV_CTRL);
+ }
+ if (categories & AVRC_SUPF_CT_BROWSE) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
+ << " supports browsing";
+ peer_features |= (BTA_AV_FEAT_BROWSE);
+ }
+ }
+ }
+ }
+ }
+
+ sdp_record = sdp_->FindServiceInDb(disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET,
+ nullptr);
+ if (sdp_record != nullptr) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
+ << " supports remote control target";
+
+ uint16_t peer_avrcp_target_version = 0;
+ sdp_->FindProfileVersionInRec(sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL,
+ &peer_avrcp_target_version);
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
+ << " peer avrcp target version="
+ << loghex(peer_avrcp_target_version);
+
+ if ((sdp_->FindAttributeInRec(sdp_record, ATTR_ID_BT_PROFILE_DESC_LIST)) !=
+ NULL) {
+ if (peer_avrcp_target_version >= AVRC_REV_1_4) {
+ /* get supported categories */
+ LOG(INFO) << __PRETTY_FUNCTION__ << " Get Supported categories";
+ tSDP_DISC_ATTR* sdp_attribute =
+ sdp_->FindAttributeInRec(sdp_record, ATTR_ID_SUPPORTED_FEATURES);
+ if (sdp_attribute != NULL) {
+ LOG(INFO) << __PRETTY_FUNCTION__
+ << "Get Supported categories SDP ATTRIBUTES != null";
+ uint16_t categories = sdp_attribute->attr_value.v.u16;
+ if (categories & AVRC_SUPF_CT_CAT2) {
+ LOG(INFO) << __PRETTY_FUNCTION__ << ": Device " << bdaddr.ToString()
+ << " supports advanced control";
+ peer_features |= (BTA_AV_FEAT_ADV_CTRL);
+ }
+ }
+ }
+ }
+ }
+
+ osi_free(disc_db);
+
+ cb.Run(status, peer_avrcp_version, peer_features);
+}
+
+void ConnectionHandler::SendMessage(
+ uint8_t handle, uint8_t label, bool browse,
+ std::unique_ptr<::bluetooth::PacketBuilder> message) {
+ std::shared_ptr<::bluetooth::Packet> packet = VectorPacket::Make();
+ message->Serialize(packet);
+
+ uint8_t ctype = AVRC_RSP_ACCEPT;
+ if (!browse) {
+ ctype =
+ (uint8_t)(::bluetooth::Packet::Specialize<Packet>(packet)->GetCType());
+ }
+
+ DLOG(INFO) << "SendMessage to handle=" << loghex(handle);
+
+ BT_HDR* pkt = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
+
+ pkt->offset = AVCT_MSG_OFFSET;
+ // TODO (apanicke): Update this constant. Currently this is a unique event
+ // used to tell the AVRCP API layer that the data is properly formatted and
+ // doesn't need to be processed. In the future, this is the only place sending
+ // the packet so none of these layer specific fields will be used.
+ pkt->event = 0xFFFF;
+
+ // TODO (apanicke): This layer specific stuff can go away once we move over
+ // to the new service.
+ pkt->layer_specific = AVCT_DATA_CTRL;
+ if (browse) {
+ pkt->layer_specific = AVCT_DATA_BROWSE;
+ }
+
+ pkt->len = packet->size();
+ uint8_t* p_data = (uint8_t*)(pkt + 1) + pkt->offset;
+ for (auto it = packet->begin(); it != packet->end(); it++) {
+ *p_data++ = *it;
+ }
+
+ avrc_->MsgReq(handle, label, ctype, pkt);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/profile/avrcp/connection_handler.h b/profile/avrcp/connection_handler.h
new file mode 100644
index 0000000..63bc8a0
--- /dev/null
+++ b/profile/avrcp/connection_handler.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <base/bind.h>
+#include <base/memory/weak_ptr.h>
+#include <map>
+#include <memory>
+
+#include "avrcp_internal.h"
+#include "avrcp_packet.h"
+#include "device.h"
+#include "packet.h"
+#include "raw_address.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+// TODO: Remove the singleton design structure for this class.
+// AvrcpTargetService is already a singleton and can manage the lifetime of this
+// object. multiple singleton objects can lead to code that is hard to test and
+// have hard to debug lifetimes.
+
+// TODO (apanicke): Use a device factory instead of just the constructor in
+// order to create device objects. This will allow us to create specific device
+// classes that can provide interop fixes for certain badly behaving devices.
+
+/**
+ * ConnectionHandler handles SDP, connecting to remote AVRCP devices
+ * and multiplexing/delivering messages to devices.
+ */
+class ConnectionHandler {
+ public:
+ /**
+ * This callback is used to return a new device after a connection attempt.
+ * A reference to the new Avrcp device is located in the shared_ptr.
+ * If there was an issue during connection the pointer value will be null.
+ */
+ using ConnectionCallback = base::Callback<void(std::shared_ptr<Device>)>;
+
+ /**
+ * Initializes the singleton instance and sets up SDP. Also Opens the
+ * AVRCP Acceptor to receive connection requests from a remote device.
+ *
+ * Params:
+ * callback - A callback that gets called any time a new AVRCP Device
+ * is connected. Will return nullpointer if a device fails
+ * to connect via ConnectDevice();
+ *
+ * TODO: Add message loop to determine which thread events are posted to
+ */
+ static bool Initialize(const ConnectionCallback& callback,
+ AvrcpInterface* avrcp, SdpInterface* sdp,
+ VolumeInterface* vol);
+
+ /**
+ * Clears the singleton and tears down SDP
+ */
+ static bool CleanUp();
+
+ /**
+ * Get the singleton instance of Connection Handler
+ */
+ static ConnectionHandler* Get();
+
+ /**
+ * Attempt to connect AVRCP on a device. The callback will be called with
+ * either a smart pointer pointing to the connected AVRCP device or null
+ * if the connection failed.
+ *
+ * The order of operations for this function is as follows.
+ * 1. Perform SDP on remote device
+ * 2. Connect the AVCTP Channel
+ * 2. (Optional) If supported connect the AVCTP Browse channel
+ * 4. Call the provided callback with the new
+ *
+ * Params:
+ * bdaddr - Bluetooth address of device to connect to
+ * callback - The function that gets called when a connection succeeds or
+ * fails. The pointer being cleared implies that the connection
+ * failed.
+ *
+ * Returns:
+ * true if the connection attempt starts, false if there are no resources to
+ * connect AVRCP
+ */
+ virtual bool ConnectDevice(const RawAddress& bdaddr);
+
+ /**
+ * Disconnects AVRCP from a device that was successfully connected too using
+ * ConnectionHandler::ConnectDevice
+ *
+ * Returns:
+ * true if the AVRCP was successfully disconnected for the device or false
+ * if the device was already disconnected or in an invalid state
+ */
+ virtual bool DisconnectDevice(const RawAddress& bdaddr);
+
+ virtual std::vector<std::shared_ptr<Device>> GetListOfDevices() const;
+
+ /**
+ * Provide a custom ConnectionHandler that will be returned by Get().
+ * Initialize and CleanUp should not be called as the owner of the handler
+ * determines its lifetime.
+ */
+ static void InitForTesting(ConnectionHandler* handler);
+
+ private:
+ AvrcpInterface* avrc_;
+ SdpInterface* sdp_;
+ VolumeInterface* vol_;
+
+ ConnectionCallback connection_cb_;
+
+ std::map<uint8_t, std::shared_ptr<Device>> device_map_;
+ // TODO (apanicke): Replace the features with a class that has individual
+ // fields.
+ std::map<RawAddress, uint16_t> feature_map_;
+
+ static ConnectionHandler* instance_;
+
+ using SdpCallback = base::Callback<void(uint16_t status, uint16_t version,
+ uint16_t features)>;
+ virtual bool SdpLookup(const RawAddress& bdaddr, SdpCallback cb);
+ void SdpCb(const RawAddress& bdaddr, SdpCallback cb,
+ tSDP_DISCOVERY_DB* disc_db, uint16_t status);
+
+ virtual bool AvrcpConnect(bool initiator, const RawAddress& bdaddr);
+
+ // Callbacks when connecting to a device
+ void InitiatorControlCb(uint8_t handle, uint8_t event, uint16_t result,
+ const RawAddress* peer_addr);
+ void AcceptorControlCb(uint8_t handle, uint8_t event, uint16_t result,
+ const RawAddress* peer_addr);
+ void MessageCb(uint8_t handle, uint8_t label, uint8_t opcode,
+ tAVRC_MSG* p_msg);
+
+ ConnectionHandler() : weak_ptr_factory_(this){};
+ virtual ~ConnectionHandler() = default;
+
+ // Callback for when sending a response to a device
+ void SendMessage(uint8_t handle, uint8_t label, bool browse,
+ std::unique_ptr<::bluetooth::PacketBuilder> message);
+
+ base::WeakPtrFactory<ConnectionHandler> weak_ptr_factory_;
+ DISALLOW_COPY_AND_ASSIGN(ConnectionHandler);
+};
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/profile/avrcp/device.cc b/profile/avrcp/device.cc
new file mode 100644
index 0000000..9a31ef3
--- /dev/null
+++ b/profile/avrcp/device.cc
@@ -0,0 +1,1308 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/message_loop/message_loop.h>
+
+#include "connection_handler.h"
+#include "device.h"
+#include "stack_config.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+#define DEVICE_LOG(LEVEL) LOG(LEVEL) << address_.ToString() << " : "
+#define DEVICE_VLOG(LEVEL) VLOG(LEVEL) << address_.ToString() << " : "
+
+#define VOL_NOT_SUPPORTED -1
+#define VOL_REGISTRATION_FAILED -2
+
+Device::Device(
+ const RawAddress& bdaddr, bool avrcp13_compatibility,
+ base::Callback<void(uint8_t label, bool browse,
+ std::unique_ptr<::bluetooth::PacketBuilder> message)>
+ send_msg_cb,
+ uint16_t ctrl_mtu, uint16_t browse_mtu)
+ : weak_ptr_factory_(this),
+ address_(bdaddr),
+ avrcp13_compatibility_(avrcp13_compatibility),
+ send_message_cb_(send_msg_cb),
+ ctrl_mtu_(ctrl_mtu),
+ browse_mtu_(browse_mtu) {}
+
+void Device::RegisterInterfaces(MediaInterface* media_interface,
+ A2dpInterface* a2dp_interface,
+ VolumeInterface* volume_interface) {
+ CHECK(media_interface);
+ CHECK(a2dp_interface);
+ a2dp_interface_ = a2dp_interface;
+ media_interface_ = media_interface;
+ volume_interface_ = volume_interface;
+}
+
+bool Device::IsActive() const {
+ return address_ == a2dp_interface_->active_peer();
+}
+
+void Device::VendorPacketHandler(uint8_t label,
+ std::shared_ptr<VendorPacket> pkt) {
+ CHECK(media_interface_);
+ DEVICE_VLOG(3) << __func__ << ": pdu=" << pkt->GetCommandPdu();
+
+ // All CTypes at and above NOT_IMPLEMENTED are all response types.
+ if (pkt->GetCType() == CType::NOT_IMPLEMENTED) {
+ return;
+ }
+
+ if (pkt->GetCType() >= CType::ACCEPTED) {
+ switch (pkt->GetCommandPdu()) {
+ // VOLUME_CHANGED is the only notification we register for while target.
+ case CommandPdu::REGISTER_NOTIFICATION: {
+ auto register_notification =
+ Packet::Specialize<RegisterNotificationResponse>(pkt);
+ if (register_notification->GetEvent() != Event::VOLUME_CHANGED) {
+ DEVICE_LOG(WARNING)
+ << __func__ << ": Unhandled register notification received: "
+ << register_notification->GetEvent();
+ return;
+ }
+ HandleVolumeChanged(label, register_notification);
+ break;
+ }
+ case CommandPdu::SET_ABSOLUTE_VOLUME:
+ // TODO (apanicke): Add a retry mechanism if the response has a
+ // different volume than the one we set. For now, we don't care
+ // about the response to this message.
+ break;
+ default:
+ DEVICE_LOG(WARNING)
+ << __func__ << ": Unhandled Response: pdu=" << pkt->GetCommandPdu();
+ break;
+ }
+ return;
+ }
+
+ switch (pkt->GetCommandPdu()) {
+ case CommandPdu::GET_CAPABILITIES: {
+ HandleGetCapabilities(label,
+ Packet::Specialize<GetCapabilitiesRequest>(pkt));
+ } break;
+
+ case CommandPdu::REGISTER_NOTIFICATION: {
+ HandleNotification(label,
+ Packet::Specialize<RegisterNotificationRequest>(pkt));
+ } break;
+
+ case CommandPdu::GET_ELEMENT_ATTRIBUTES: {
+ media_interface_->GetSongInfo(base::Bind(
+ &Device::GetElementAttributesResponse, weak_ptr_factory_.GetWeakPtr(),
+ label, Packet::Specialize<GetElementAttributesRequest>(pkt)));
+ } break;
+
+ case CommandPdu::GET_PLAY_STATUS: {
+ media_interface_->GetPlayStatus(base::Bind(&Device::GetPlayStatusResponse,
+ weak_ptr_factory_.GetWeakPtr(),
+ label));
+ } break;
+
+ case CommandPdu::PLAY_ITEM: {
+ HandlePlayItem(label, Packet::Specialize<PlayItemRequest>(pkt));
+ } break;
+
+ case CommandPdu::SET_ADDRESSED_PLAYER: {
+ // TODO (apanicke): Implement set addressed player. We don't need
+ // this currently since the current implementation only has one
+ // player and the player will never change, but we need it for a
+ // more complete implementation.
+ media_interface_->GetMediaPlayerList(base::Bind(
+ &Device::HandleSetAddressedPlayer, weak_ptr_factory_.GetWeakPtr(),
+ label, Packet::Specialize<SetAddressedPlayerRequest>(pkt)));
+ } break;
+
+ default: {
+ DEVICE_LOG(ERROR) << "Unhandled Vendor Packet: " << pkt->ToString();
+ auto response = RejectBuilder::MakeBuilder(
+ (CommandPdu)pkt->GetCommandPdu(), Status::INVALID_COMMAND);
+ send_message(label, false, std::move(response));
+ } break;
+ }
+}
+
+void Device::HandleGetCapabilities(
+ uint8_t label, const std::shared_ptr<GetCapabilitiesRequest>& pkt) {
+ DEVICE_VLOG(4) << __func__
+ << ": capability=" << pkt->GetCapabilityRequested();
+
+ switch (pkt->GetCapabilityRequested()) {
+ case Capability::COMPANY_ID: {
+ auto response =
+ GetCapabilitiesResponseBuilder::MakeCompanyIdBuilder(0x001958);
+ response->AddCompanyId(0x002345);
+ send_message_cb_.Run(label, false, std::move(response));
+ } break;
+
+ case Capability::EVENTS_SUPPORTED: {
+ auto response =
+ GetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(
+ Event::PLAYBACK_STATUS_CHANGED);
+ response->AddEvent(Event::TRACK_CHANGED);
+ response->AddEvent(Event::PLAYBACK_POS_CHANGED);
+
+ if (!avrcp13_compatibility_) {
+ response->AddEvent(Event::AVAILABLE_PLAYERS_CHANGED);
+ response->AddEvent(Event::ADDRESSED_PLAYER_CHANGED);
+ response->AddEvent(Event::UIDS_CHANGED);
+ response->AddEvent(Event::NOW_PLAYING_CONTENT_CHANGED);
+ }
+
+ send_message(label, false, std::move(response));
+ } break;
+
+ default: {
+ DEVICE_LOG(WARNING) << "Unhandled Capability: "
+ << pkt->GetCapabilityRequested();
+ auto response = RejectBuilder::MakeBuilder(CommandPdu::GET_CAPABILITIES,
+ Status::INVALID_PARAMETER);
+ send_message(label, false, std::move(response));
+ } break;
+ }
+}
+
+void Device::HandleNotification(
+ uint8_t label, const std::shared_ptr<RegisterNotificationRequest>& pkt) {
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(ERROR) << __func__ << ": Request packet is not valid";
+ auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
+ Status::INVALID_PARAMETER);
+ send_message(label, false, std::move(response));
+ return;
+ }
+
+ DEVICE_VLOG(4) << __func__ << ": event=" << pkt->GetEventRegistered();
+
+ switch (pkt->GetEventRegistered()) {
+ case Event::TRACK_CHANGED: {
+ track_changed_ = Notification(true, label);
+ media_interface_->GetNowPlayingList(
+ base::Bind(&Device::TrackChangedNotificationResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, true));
+ } break;
+
+ case Event::PLAYBACK_STATUS_CHANGED: {
+ play_status_changed_ = Notification(true, label);
+ media_interface_->GetPlayStatus(
+ base::Bind(&Device::PlaybackStatusNotificationResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, true));
+ } break;
+
+ case Event::PLAYBACK_POS_CHANGED: {
+ play_pos_changed_ = Notification(true, label);
+ play_pos_interval_ = pkt->GetInterval();
+ media_interface_->GetPlayStatus(
+ base::Bind(&Device::PlaybackPosNotificationResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, true));
+ } break;
+
+ case Event::NOW_PLAYING_CONTENT_CHANGED: {
+ now_playing_changed_ = Notification(true, label);
+ media_interface_->GetNowPlayingList(base::Bind(
+ &Device::HandleNowPlayingNotificationResponse,
+ weak_ptr_factory_.GetWeakPtr(), now_playing_changed_.second, true));
+ } break;
+
+ case Event::AVAILABLE_PLAYERS_CHANGED: {
+ // Respond immediately since this notification doesn't require any info
+ avail_players_changed_ = Notification(true, label);
+ auto response =
+ RegisterNotificationResponseBuilder::MakeAvailablePlayersBuilder(
+ true);
+ send_message(label, false, std::move(response));
+ } break;
+
+ case Event::ADDRESSED_PLAYER_CHANGED: {
+ addr_player_changed_ = Notification(true, label);
+ media_interface_->GetMediaPlayerList(
+ base::Bind(&Device::AddressedPlayerNotificationResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, true));
+ } break;
+
+ case Event::UIDS_CHANGED: {
+ // Respond immediately since this notification doesn't require any info
+ uids_changed_ = Notification(true, label);
+ auto response =
+ RegisterNotificationResponseBuilder::MakeUidsChangedBuilder(true, 0);
+ send_message(label, false, std::move(response));
+ } break;
+
+ default: {
+ DEVICE_LOG(ERROR) << __func__ << " : Unknown event registered. Event ID="
+ << pkt->GetEventRegistered();
+ auto response = RejectBuilder::MakeBuilder(
+ (CommandPdu)pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+ send_message(label, false, std::move(response));
+ } break;
+ }
+}
+
+void Device::RegisterVolumeChanged() {
+ DEVICE_VLOG(2) << __func__;
+ if (volume_interface_ == nullptr) return;
+
+ auto request =
+ RegisterNotificationRequestBuilder::MakeBuilder(Event::VOLUME_CHANGED, 0);
+
+ // Find an open transaction label to prevent conflicts with other commands
+ // that are in flight. We can not use the reserved label while the
+ // notification hasn't been completed.
+ uint8_t label = MAX_TRANSACTION_LABEL;
+ for (uint8_t i = 0; i < MAX_TRANSACTION_LABEL; i++) {
+ if (active_labels_.find(i) == active_labels_.end()) {
+ active_labels_.insert(i);
+ label = i;
+ break;
+ }
+ }
+
+ if (label == MAX_TRANSACTION_LABEL) {
+ DEVICE_LOG(FATAL)
+ << __func__
+ << ": Abandon all hope, something went catastrophically wrong";
+ }
+
+ send_message_cb_.Run(label, false, std::move(request));
+}
+
+void Device::HandleVolumeChanged(
+ uint8_t label, const std::shared_ptr<RegisterNotificationResponse>& pkt) {
+ DEVICE_VLOG(1) << __func__ << ": interim=" << pkt->IsInterim();
+ if (volume_interface_ == nullptr) return;
+
+ if (pkt->GetCType() == CType::REJECTED) {
+ // Disable Absolute Volume
+ active_labels_.erase(label);
+ volume_interface_ = nullptr;
+ volume_ = VOL_REGISTRATION_FAILED;
+ return;
+ }
+
+ // We only update on interim and just re-register on changes.
+ if (!pkt->IsInterim()) {
+ active_labels_.erase(label);
+ RegisterVolumeChanged();
+ return;
+ }
+
+ // Handle the first volume update.
+ if (volume_ == VOL_NOT_SUPPORTED) {
+ volume_ = pkt->GetVolume();
+ volume_interface_->DeviceConnected(
+ GetAddress(),
+ base::Bind(&Device::SetVolume, weak_ptr_factory_.GetWeakPtr()));
+
+ // Ignore the returned volume in favor of the volume returned
+ // by the volume interface.
+ return;
+ }
+
+ if (!IsActive()) {
+ DEVICE_VLOG(3) << __func__
+ << ": Ignoring volume changes from non active device";
+ return;
+ }
+
+ volume_ = pkt->GetVolume();
+ DEVICE_VLOG(1) << __func__ << ": Volume has changed to " << (uint32_t)volume_;
+ volume_interface_->SetVolume(volume_);
+}
+
+void Device::SetVolume(int8_t volume) {
+ // TODO (apanicke): Implement logic for Multi-AVRCP
+ DEVICE_VLOG(1) << __func__ << ": volume=" << (int)volume;
+ auto request = SetAbsoluteVolumeRequestBuilder::MakeBuilder(volume);
+
+ uint8_t label = MAX_TRANSACTION_LABEL;
+ for (uint8_t i = 0; i < MAX_TRANSACTION_LABEL; i++) {
+ if (active_labels_.find(i) == active_labels_.end()) {
+ active_labels_.insert(i);
+ label = i;
+ break;
+ }
+ }
+
+ volume_ = volume;
+ send_message_cb_.Run(label, false, std::move(request));
+}
+
+void Device::TrackChangedNotificationResponse(uint8_t label, bool interim,
+ std::string curr_song_id,
+ std::vector<SongInfo> song_list) {
+ DEVICE_VLOG(1) << __func__;
+ uint64_t uid = 0;
+
+ if (!track_changed_.first) {
+ DEVICE_VLOG(0) << __func__ << ": Device not registered for update";
+ return;
+ }
+
+ // Anytime we use the now playing list, update our map so that its always
+ // current
+ now_playing_ids_.clear();
+ for (const SongInfo& song : song_list) {
+ now_playing_ids_.insert(song.media_id);
+ if (curr_song_id == song.media_id) {
+ DEVICE_VLOG(3) << __func__ << ": Found media ID match for "
+ << song.media_id;
+ uid = now_playing_ids_.get_uid(curr_song_id);
+ }
+ }
+
+ if (curr_song_id == "") {
+ DEVICE_LOG(WARNING) << "Empty media ID";
+ uid = 0;
+ if (stack_config_get_interface()->get_pts_avrcp_test()) {
+ DEVICE_LOG(WARNING) << __func__ << ": pts test mode";
+ uid = 0xffffffffffffffff;
+ }
+ }
+
+ auto response = RegisterNotificationResponseBuilder::MakeTrackChangedBuilder(
+ interim, uid);
+ send_message_cb_.Run(label, false, std::move(response));
+ if (!interim) {
+ active_labels_.erase(label);
+ track_changed_ = Notification(false, 0);
+ }
+}
+
+void Device::PlaybackStatusNotificationResponse(uint8_t label, bool interim,
+ PlayStatus status) {
+ DEVICE_VLOG(1) << __func__;
+ if (status.state == PlayState::PAUSED) play_pos_update_cb_.Cancel();
+
+ if (!play_status_changed_.first) {
+ DEVICE_VLOG(0) << __func__ << ": Device not registered for update";
+ return;
+ }
+
+ auto state_to_send = status.state;
+ if (!IsActive()) state_to_send = PlayState::PAUSED;
+ if (!interim && state_to_send == last_play_status_.state) {
+ DEVICE_VLOG(0) << __func__
+ << ": Not sending notification due to no state update "
+ << address_.ToString();
+ return;
+ }
+
+ last_play_status_.state = state_to_send;
+
+ auto response =
+ RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
+ interim, IsActive() ? status.state : PlayState::PAUSED);
+ send_message_cb_.Run(label, false, std::move(response));
+
+ if (!interim) {
+ active_labels_.erase(label);
+ play_status_changed_ = Notification(false, 0);
+ }
+}
+
+void Device::PlaybackPosNotificationResponse(uint8_t label, bool interim,
+ PlayStatus status) {
+ DEVICE_VLOG(4) << __func__;
+
+ if (!play_pos_changed_.first) {
+ DEVICE_VLOG(3) << __func__ << ": Device not registered for update";
+ return;
+ }
+
+ if (!interim && last_play_status_.position == status.position) {
+ DEVICE_LOG(WARNING) << address_.ToString()
+ << ": No update to play position";
+ return;
+ }
+
+ auto response =
+ RegisterNotificationResponseBuilder::MakePlaybackPositionBuilder(
+ interim, status.position);
+ send_message_cb_.Run(label, false, std::move(response));
+
+ last_play_status_.position = status.position;
+
+ if (!interim) {
+ active_labels_.erase(label);
+ play_pos_changed_ = Notification(false, 0);
+ }
+
+ // We still try to send updates while music is playing to the non active
+ // device even though the device thinks the music is paused. This makes
+ // the status bar on the remote device move.
+ if (status.state == PlayState::PLAYING) {
+ DEVICE_VLOG(0) << __func__ << ": Queue next play position update";
+ play_pos_update_cb_.Reset(base::Bind(&Device::HandlePlayPosUpdate,
+ weak_ptr_factory_.GetWeakPtr()));
+ base::MessageLoop::current()->task_runner()->PostDelayedTask(
+ FROM_HERE, play_pos_update_cb_.callback(),
+ base::TimeDelta::FromSeconds(play_pos_interval_));
+ }
+}
+
+// TODO (apanicke): Finish implementing when we add support for more than one
+// player
+void Device::AddressedPlayerNotificationResponse(
+ uint8_t label, bool interim, uint16_t curr_player,
+ std::vector<MediaPlayerInfo> /* unused */) {
+ DEVICE_VLOG(1) << __func__
+ << ": curr_player_id=" << (unsigned int)curr_player;
+ // If there is no set browsed player, use the current addressed player as the
+ // default NOTE: Using any browsing commands before the browsed player is set
+ // is a violation of the AVRCP Spec but there are some carkits that try too
+ // anyways
+ if (curr_browsed_player_id_ == -1) curr_browsed_player_id_ = curr_player;
+
+ auto response =
+ RegisterNotificationResponseBuilder::MakeAddressedPlayerBuilder(
+ interim, curr_player, 0x0000);
+ send_message_cb_.Run(label, false, std::move(response));
+
+ if (!interim) {
+ active_labels_.erase(label);
+ addr_player_changed_ = Notification(false, 0);
+ RejectNotification();
+ }
+}
+
+void Device::RejectNotification() {
+ DEVICE_VLOG(1) << __func__;
+ Notification* rejectNotification[] = {&play_status_changed_, &track_changed_,
+ &play_pos_changed_,
+ &now_playing_changed_};
+ for (int i = 0; i < 4; i++) {
+ uint8_t label = rejectNotification[i]->second;
+ auto response = RejectBuilder::MakeBuilder(
+ CommandPdu::REGISTER_NOTIFICATION, Status::ADDRESSED_PLAYER_CHANGED);
+ send_message_cb_.Run(label, false, std::move(response));
+ active_labels_.erase(label);
+ rejectNotification[i] = new Notification(false, 0);
+ }
+}
+
+void Device::GetPlayStatusResponse(uint8_t label, PlayStatus status) {
+ DEVICE_VLOG(2) << __func__ << ": position=" << status.position
+ << " duration=" << status.duration
+ << " state=" << status.state;
+ auto response = GetPlayStatusResponseBuilder::MakeBuilder(
+ status.duration, status.position,
+ IsActive() ? status.state : PlayState::PAUSED);
+ send_message(label, false, std::move(response));
+}
+
+void Device::GetElementAttributesResponse(
+ uint8_t label, std::shared_ptr<GetElementAttributesRequest> pkt,
+ SongInfo info) {
+ DEVICE_VLOG(2) << __func__;
+ auto get_element_attributes_pkt = pkt;
+ auto attributes_requested =
+ get_element_attributes_pkt->GetAttributesRequested();
+
+ auto response = GetElementAttributesResponseBuilder::MakeBuilder(ctrl_mtu_);
+
+ last_song_info_ = info;
+
+ if (attributes_requested.size() != 0) {
+ for (const auto& attribute : attributes_requested) {
+ if (info.attributes.find(attribute) != info.attributes.end()) {
+ response->AddAttributeEntry(*info.attributes.find(attribute));
+ }
+ }
+ } else { // zero attributes requested which means all attributes requested
+ for (const auto& attribute : info.attributes) {
+ response->AddAttributeEntry(attribute);
+ }
+ }
+
+ send_message(label, false, std::move(response));
+}
+
+void Device::MessageReceived(uint8_t label, std::shared_ptr<Packet> pkt) {
+ DEVICE_VLOG(4) << __func__ << ": opcode=" << pkt->GetOpcode();
+
+ active_labels_.insert(label);
+
+ switch (pkt->GetOpcode()) {
+ // TODO (apanicke): Remove handling of UNIT_INFO and SUBUNIT_INFO from
+ // the AVRC_API and instead handle it here to reduce fragmentation.
+ case Opcode::UNIT_INFO: {
+ } break;
+ case Opcode::SUBUNIT_INFO: {
+ } break;
+ case Opcode::PASS_THROUGH: {
+ auto pass_through_packet = Packet::Specialize<PassThroughPacket>(pkt);
+ auto response = PassThroughPacketBuilder::MakeBuilder(
+ true, pass_through_packet->GetKeyState() == KeyState::PUSHED,
+ pass_through_packet->GetOperationId());
+ send_message(label, false, std::move(response));
+
+ // TODO (apanicke): Use an enum for media key ID's
+ if (pass_through_packet->GetOperationId() == 0x44 &&
+ pass_through_packet->GetKeyState() == KeyState::PUSHED) {
+ // We need to get the play status since we need to know
+ // what the actual playstate is without being modified
+ // by whether the device is active.
+ media_interface_->GetPlayStatus(base::Bind(
+ [](base::WeakPtr<Device> d, PlayStatus s) {
+ if (!d) return;
+
+ if (!d->IsActive()) {
+ LOG(INFO) << "Setting " << d->address_.ToString()
+ << " to be the active device";
+ d->media_interface_->SetActiveDevice(d->address_);
+
+ if (s.state == PlayState::PLAYING) {
+ LOG(INFO)
+ << "Skipping sendKeyEvent since music is already playing";
+ return;
+ }
+ }
+
+ d->media_interface_->SendKeyEvent(0x44, KeyState::PUSHED);
+ },
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+
+ if (IsActive()) {
+ media_interface_->SendKeyEvent(pass_through_packet->GetOperationId(),
+ pass_through_packet->GetKeyState());
+ }
+ } break;
+ case Opcode::VENDOR: {
+ auto vendor_pkt = Packet::Specialize<VendorPacket>(pkt);
+ VendorPacketHandler(label, vendor_pkt);
+ } break;
+ }
+}
+
+void Device::HandlePlayItem(uint8_t label,
+ std::shared_ptr<PlayItemRequest> pkt) {
+ DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope()
+ << " uid=" << pkt->GetUid();
+
+ std::string media_id = "";
+ switch (pkt->GetScope()) {
+ case Scope::NOW_PLAYING:
+ media_id = now_playing_ids_.get_media_id(pkt->GetUid());
+ break;
+ case Scope::VFS:
+ media_id = vfs_ids_.get_media_id(pkt->GetUid());
+ break;
+ default:
+ DEVICE_LOG(WARNING) << __func__ << ": Unknown scope for play item";
+ }
+
+ if (media_id == "") {
+ DEVICE_VLOG(2) << "Could not find item";
+ auto response = RejectBuilder::MakeBuilder(CommandPdu::PLAY_ITEM,
+ Status::DOES_NOT_EXIST);
+ send_message(label, false, std::move(response));
+ return;
+ }
+
+ media_interface_->PlayItem(curr_browsed_player_id_,
+ pkt->GetScope() == Scope::NOW_PLAYING, media_id);
+
+ auto response = PlayItemResponseBuilder::MakeBuilder(Status::NO_ERROR);
+ send_message(label, false, std::move(response));
+}
+
+void Device::HandleSetAddressedPlayer(
+ uint8_t label, std::shared_ptr<SetAddressedPlayerRequest> pkt,
+ uint16_t curr_player, std::vector<MediaPlayerInfo> players) {
+ DEVICE_VLOG(2) << __func__ << ": PlayerId=" << pkt->GetPlayerId();
+
+ if (curr_player != pkt->GetPlayerId()) {
+ DEVICE_VLOG(2) << "Reject invalid addressed player ID";
+ auto response = RejectBuilder::MakeBuilder(CommandPdu::SET_ADDRESSED_PLAYER,
+ Status::INVALID_PLAYER_ID);
+ send_message(label, false, std::move(response));
+ return;
+ }
+
+ auto response =
+ SetAddressedPlayerResponseBuilder::MakeBuilder(Status::NO_ERROR);
+ send_message(label, false, std::move(response));
+}
+
+void Device::BrowseMessageReceived(uint8_t label,
+ std::shared_ptr<BrowsePacket> pkt) {
+ DEVICE_VLOG(1) << __func__ << ": pdu=" << pkt->GetPdu();
+
+ switch (pkt->GetPdu()) {
+ case BrowsePdu::SET_BROWSED_PLAYER:
+ HandleSetBrowsedPlayer(label,
+ Packet::Specialize<SetBrowsedPlayerRequest>(pkt));
+ break;
+ case BrowsePdu::GET_FOLDER_ITEMS:
+ HandleGetFolderItems(label,
+ Packet::Specialize<GetFolderItemsRequest>(pkt));
+ break;
+ case BrowsePdu::CHANGE_PATH:
+ HandleChangePath(label, Packet::Specialize<ChangePathRequest>(pkt));
+ break;
+ case BrowsePdu::GET_ITEM_ATTRIBUTES:
+ HandleGetItemAttributes(
+ label, Packet::Specialize<GetItemAttributesRequest>(pkt));
+ break;
+ case BrowsePdu::GET_TOTAL_NUMBER_OF_ITEMS:
+ HandleGetTotalNumberOfItems(
+ label, Packet::Specialize<GetTotalNumberOfItemsRequest>(pkt));
+ break;
+ default:
+ DEVICE_LOG(WARNING) << __func__ << ": " << pkt->GetPdu();
+ auto response = GeneralRejectBuilder::MakeBuilder(
+ BrowsePdu::GENERAL_REJECT, Status::INVALID_COMMAND);
+ send_message(label, true, std::move(response));
+
+ break;
+ }
+}
+
+void Device::HandleGetFolderItems(uint8_t label,
+ std::shared_ptr<GetFolderItemsRequest> pkt) {
+ DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope();
+
+ switch (pkt->GetScope()) {
+ case Scope::MEDIA_PLAYER_LIST:
+ media_interface_->GetMediaPlayerList(
+ base::Bind(&Device::GetMediaPlayerListResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, pkt));
+ break;
+ case Scope::VFS:
+ media_interface_->GetFolderItems(
+ curr_browsed_player_id_, CurrentFolder(),
+ base::Bind(&Device::GetVFSListResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, pkt));
+ break;
+ case Scope::NOW_PLAYING:
+ media_interface_->GetNowPlayingList(
+ base::Bind(&Device::GetNowPlayingListResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, pkt));
+ break;
+ default:
+ DEVICE_LOG(ERROR) << __func__ << ": " << pkt->GetScope();
+ break;
+ }
+}
+
+void Device::HandleGetTotalNumberOfItems(
+ uint8_t label, std::shared_ptr<GetTotalNumberOfItemsRequest> pkt) {
+ DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope();
+
+ switch (pkt->GetScope()) {
+ case Scope::MEDIA_PLAYER_LIST: {
+ media_interface_->GetMediaPlayerList(
+ base::Bind(&Device::GetTotalNumberOfItemsMediaPlayersResponse,
+ weak_ptr_factory_.GetWeakPtr(), label));
+ break;
+ }
+ case Scope::VFS:
+ media_interface_->GetFolderItems(
+ curr_browsed_player_id_, CurrentFolder(),
+ base::Bind(&Device::GetTotalNumberOfItemsVFSResponse,
+ weak_ptr_factory_.GetWeakPtr(), label));
+ break;
+ case Scope::NOW_PLAYING:
+ media_interface_->GetNowPlayingList(
+ base::Bind(&Device::GetTotalNumberOfItemsNowPlayingResponse,
+ weak_ptr_factory_.GetWeakPtr(), label));
+ break;
+ default:
+ DEVICE_LOG(ERROR) << __func__ << ": " << pkt->GetScope();
+ break;
+ }
+}
+
+void Device::GetTotalNumberOfItemsMediaPlayersResponse(
+ uint8_t label, uint16_t curr_player, std::vector<MediaPlayerInfo> list) {
+ DEVICE_VLOG(2) << __func__ << ": num_items=" << list.size();
+
+ auto builder = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(
+ Status::NO_ERROR, 0x0000, list.size());
+ send_message(label, true, std::move(builder));
+}
+
+void Device::GetTotalNumberOfItemsVFSResponse(uint8_t label,
+ std::vector<ListItem> list) {
+ DEVICE_VLOG(2) << __func__ << ": num_items=" << list.size();
+
+ auto builder = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(
+ Status::NO_ERROR, 0x0000, list.size());
+ send_message(label, true, std::move(builder));
+}
+
+void Device::GetTotalNumberOfItemsNowPlayingResponse(
+ uint8_t label, std::string curr_song_id, std::vector<SongInfo> list) {
+ DEVICE_VLOG(2) << __func__ << ": num_items=" << list.size();
+
+ auto builder = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(
+ Status::NO_ERROR, 0x0000, list.size());
+ send_message(label, true, std::move(builder));
+}
+
+void Device::HandleChangePath(uint8_t label,
+ std::shared_ptr<ChangePathRequest> pkt) {
+ DEVICE_VLOG(2) << __func__ << ": direction=" << pkt->GetDirection()
+ << " uid=" << loghex(pkt->GetUid());
+
+ if (pkt->GetDirection() == Direction::DOWN &&
+ vfs_ids_.get_media_id(pkt->GetUid()) == "") {
+ DEVICE_LOG(ERROR) << __func__
+ << ": No item found for UID=" << pkt->GetUid();
+ auto builder =
+ ChangePathResponseBuilder::MakeBuilder(Status::DOES_NOT_EXIST, 0);
+ send_message(label, true, std::move(builder));
+ return;
+ }
+
+ if (pkt->GetDirection() == Direction::DOWN) {
+ current_path_.push(vfs_ids_.get_media_id(pkt->GetUid()));
+ DEVICE_VLOG(2) << "Pushing Path to stack: \"" << CurrentFolder() << "\"";
+ } else {
+ // Don't pop the root id off the stack
+ if (current_path_.size() > 1) {
+ current_path_.pop();
+ } else {
+ DEVICE_LOG(ERROR) << "Trying to change directory up past root.";
+ auto builder =
+ ChangePathResponseBuilder::MakeBuilder(Status::DOES_NOT_EXIST, 0);
+ send_message(label, true, std::move(builder));
+ return;
+ }
+
+ DEVICE_VLOG(2) << "Popping Path from stack: new path=\"" << CurrentFolder()
+ << "\"";
+ }
+
+ media_interface_->GetFolderItems(
+ curr_browsed_player_id_, CurrentFolder(),
+ base::Bind(&Device::ChangePathResponse, weak_ptr_factory_.GetWeakPtr(),
+ label, pkt));
+}
+
+void Device::ChangePathResponse(uint8_t label,
+ std::shared_ptr<ChangePathRequest> pkt,
+ std::vector<ListItem> list) {
+ // TODO (apanicke): Reconstruct the VFS ID's here. Right now it gets
+ // reconstructed in GetFolderItemsVFS
+ auto builder =
+ ChangePathResponseBuilder::MakeBuilder(Status::NO_ERROR, list.size());
+ send_message(label, true, std::move(builder));
+}
+
+void Device::HandleGetItemAttributes(
+ uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt) {
+ DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope()
+ << " uid=" << loghex(pkt->GetUid())
+ << " uid counter=" << loghex(pkt->GetUidCounter());
+ if (pkt->GetUidCounter() != 0x0000) { // For database unaware player, use 0
+ DEVICE_LOG(WARNING) << "UidCounter is invalid";
+ auto builder = GetItemAttributesResponseBuilder::MakeBuilder(
+ Status::UIDS_CHANGED, browse_mtu_);
+ send_message(label, true, std::move(builder));
+ return;
+ }
+ switch (pkt->GetScope()) {
+ case Scope::NOW_PLAYING: {
+ media_interface_->GetNowPlayingList(
+ base::Bind(&Device::GetItemAttributesNowPlayingResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, pkt));
+ } break;
+ case Scope::VFS:
+ // TODO (apanicke): Check the vfs_ids_ here. If the item doesn't exist
+ // then we can auto send the error without calling up. We do this check
+ // later right now though in order to prevent race conditions with updates
+ // on the media layer.
+ media_interface_->GetFolderItems(
+ curr_browsed_player_id_, CurrentFolder(),
+ base::Bind(&Device::GetItemAttributesVFSResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, pkt));
+ break;
+ default:
+ DEVICE_LOG(ERROR) << "UNKNOWN SCOPE FOR HANDLE GET ITEM ATTRIBUTES";
+ break;
+ }
+}
+
+void Device::GetItemAttributesNowPlayingResponse(
+ uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt,
+ std::string curr_media_id, std::vector<SongInfo> song_list) {
+ DEVICE_VLOG(2) << __func__ << ": uid=" << loghex(pkt->GetUid());
+ auto builder = GetItemAttributesResponseBuilder::MakeBuilder(Status::NO_ERROR,
+ browse_mtu_);
+
+ auto media_id = now_playing_ids_.get_media_id(pkt->GetUid());
+ if (media_id == "") {
+ media_id = curr_media_id;
+ }
+
+ DEVICE_VLOG(2) << __func__ << ": media_id=\"" << media_id << "\"";
+
+ SongInfo info;
+ for (const auto& temp : song_list) {
+ if (temp.media_id == media_id) {
+ info = temp;
+ }
+ }
+
+ auto attributes_requested = pkt->GetAttributesRequested();
+ if (attributes_requested.size() != 0) {
+ for (const auto& attribute : attributes_requested) {
+ if (info.attributes.find(attribute) != info.attributes.end()) {
+ builder->AddAttributeEntry(*info.attributes.find(attribute));
+ }
+ }
+ } else {
+ // If zero attributes were requested, that means all attributes were
+ // requested
+ for (const auto& attribute : info.attributes) {
+ builder->AddAttributeEntry(attribute);
+ }
+ }
+
+ send_message(label, true, std::move(builder));
+}
+
+void Device::GetItemAttributesVFSResponse(
+ uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt,
+ std::vector<ListItem> item_list) {
+ DEVICE_VLOG(2) << __func__ << ": uid=" << loghex(pkt->GetUid());
+
+ auto media_id = vfs_ids_.get_media_id(pkt->GetUid());
+ if (media_id == "") {
+ LOG(WARNING) << __func__ << ": Item not found";
+ auto builder = GetItemAttributesResponseBuilder::MakeBuilder(
+ Status::DOES_NOT_EXIST, browse_mtu_);
+ send_message(label, true, std::move(builder));
+ return;
+ }
+
+ auto builder = GetItemAttributesResponseBuilder::MakeBuilder(Status::NO_ERROR,
+ browse_mtu_);
+
+ ListItem item_requested;
+ for (const auto& temp : item_list) {
+ if ((temp.type == ListItem::FOLDER && temp.folder.media_id == media_id) ||
+ (temp.type == ListItem::SONG && temp.song.media_id == media_id)) {
+ item_requested = temp;
+ }
+ }
+
+ // TODO (apanicke): Add a helper function or allow adding a map
+ // of attributes to GetItemAttributesResponseBuilder
+ auto attributes_requested = pkt->GetAttributesRequested();
+ if (item_requested.type == ListItem::FOLDER) {
+ if (attributes_requested.size() == 0) {
+ builder->AddAttributeEntry(Attribute::TITLE, item_requested.folder.name);
+ } else {
+ for (auto& attr : attributes_requested) {
+ if (attr == Attribute::TITLE) {
+ builder->AddAttributeEntry(Attribute::TITLE,
+ item_requested.folder.name);
+ }
+ }
+ }
+ } else {
+ if (attributes_requested.size() != 0) {
+ for (const auto& attribute : attributes_requested) {
+ if (item_requested.song.attributes.find(attribute) !=
+ item_requested.song.attributes.end()) {
+ builder->AddAttributeEntry(
+ *item_requested.song.attributes.find(attribute));
+ }
+ }
+ } else {
+ // If zero attributes were requested, that means all attributes were
+ // requested
+ for (const auto& attribute : item_requested.song.attributes) {
+ builder->AddAttributeEntry(attribute);
+ }
+ }
+ }
+
+ send_message(label, true, std::move(builder));
+}
+
+void Device::GetMediaPlayerListResponse(
+ uint8_t label, std::shared_ptr<GetFolderItemsRequest> pkt,
+ uint16_t curr_player, std::vector<MediaPlayerInfo> players) {
+ DEVICE_VLOG(2) << __func__;
+
+ if (players.size() == 0) {
+ auto no_items_rsp = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
+ Status::RANGE_OUT_OF_BOUNDS, 0x0000, browse_mtu_);
+ send_message(label, true, std::move(no_items_rsp));
+ }
+
+ auto builder = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
+ Status::NO_ERROR, 0x0000, browse_mtu_);
+
+ // Move the current player to the first slot due to some carkits always
+ // connecting to the first listed player rather than using the ID
+ // returned by Addressed Player Changed
+ for (auto it = players.begin(); it != players.end(); it++) {
+ if (it->id == curr_player) {
+ DEVICE_VLOG(1) << " Adding player to first spot: " << it->name;
+ auto temp_player = *it;
+ players.erase(it);
+ players.insert(players.begin(), temp_player);
+ break;
+ }
+ }
+
+ for (size_t i = pkt->GetStartItem();
+ i <= pkt->GetEndItem() && i < players.size(); i++) {
+ MediaPlayerItem item(players[i].id, players[i].name,
+ players[i].browsing_supported);
+ builder->AddMediaPlayer(item);
+ }
+
+ send_message(label, true, std::move(builder));
+}
+
+std::set<AttributeEntry> filter_attributes_requested(
+ const SongInfo& song, const std::vector<Attribute>& attrs) {
+ std::set<AttributeEntry> result;
+ for (const auto& attr : attrs) {
+ if (song.attributes.find(attr) != song.attributes.end()) {
+ result.insert(*song.attributes.find(attr));
+ }
+ }
+
+ return result;
+}
+
+void Device::GetVFSListResponse(uint8_t label,
+ std::shared_ptr<GetFolderItemsRequest> pkt,
+ std::vector<ListItem> items) {
+ DEVICE_VLOG(2) << __func__ << ": start_item=" << pkt->GetStartItem()
+ << " end_item=" << pkt->GetEndItem();
+
+ // The builder will automatically correct the status if there are zero items
+ auto builder = GetFolderItemsResponseBuilder::MakeVFSBuilder(
+ Status::NO_ERROR, 0x0000, browse_mtu_);
+
+ // TODO (apanicke): Add test that checks if vfs_ids_ is the correct size after
+ // an operation.
+ for (const auto& item : items) {
+ if (item.type == ListItem::FOLDER) {
+ vfs_ids_.insert(item.folder.media_id);
+ } else if (item.type == ListItem::SONG) {
+ vfs_ids_.insert(item.song.media_id);
+ }
+ }
+
+ // Add the elements retrieved in the last get folder items request and map
+ // them to UIDs The maps will be cleared every time a directory change
+ // happens. These items do not need to correspond with the now playing list as
+ // the UID's only need to be unique in the context of the current scope and
+ // the current folder
+ for (auto i = pkt->GetStartItem(); i <= pkt->GetEndItem() && i < items.size();
+ i++) {
+ if (items[i].type == ListItem::FOLDER) {
+ auto folder = items[i].folder;
+ // right now we always use folders of mixed type
+ FolderItem folder_item(vfs_ids_.get_uid(folder.media_id), 0x00,
+ folder.is_playable, folder.name);
+ builder->AddFolder(folder_item);
+ } else if (items[i].type == ListItem::SONG) {
+ auto song = items[i].song;
+ auto title =
+ song.attributes.find(Attribute::TITLE) != song.attributes.end()
+ ? song.attributes.find(Attribute::TITLE)->value()
+ : "No Song Info";
+ MediaElementItem song_item(vfs_ids_.get_uid(song.media_id), title,
+ std::set<AttributeEntry>());
+
+ if (pkt->GetNumAttributes() == 0x00) { // All attributes requested
+ song_item.attributes_ = std::move(song.attributes);
+ } else {
+ song_item.attributes_ =
+ filter_attributes_requested(song, pkt->GetAttributesRequested());
+ }
+
+ builder->AddSong(song_item);
+ }
+ }
+
+ send_message(label, true, std::move(builder));
+}
+
+void Device::GetNowPlayingListResponse(
+ uint8_t label, std::shared_ptr<GetFolderItemsRequest> pkt,
+ std::string /* unused curr_song_id */, std::vector<SongInfo> song_list) {
+ DEVICE_VLOG(2) << __func__;
+ auto builder = GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(
+ Status::NO_ERROR, 0x0000, browse_mtu_);
+
+ now_playing_ids_.clear();
+ for (const SongInfo& song : song_list) {
+ now_playing_ids_.insert(song.media_id);
+ }
+
+ for (size_t i = pkt->GetStartItem();
+ i <= pkt->GetEndItem() && i < song_list.size(); i++) {
+ auto song = song_list[i];
+ auto title = song.attributes.find(Attribute::TITLE) != song.attributes.end()
+ ? song.attributes.find(Attribute::TITLE)->value()
+ : "No Song Info";
+
+ MediaElementItem item(i + 1, title, std::set<AttributeEntry>());
+ if (pkt->GetNumAttributes() == 0x00) {
+ item.attributes_ = std::move(song.attributes);
+ } else {
+ item.attributes_ =
+ filter_attributes_requested(song, pkt->GetAttributesRequested());
+ }
+ builder->AddSong(item);
+ }
+
+ send_message(label, true, std::move(builder));
+}
+
+void Device::HandleSetBrowsedPlayer(
+ uint8_t label, std::shared_ptr<SetBrowsedPlayerRequest> pkt) {
+ DEVICE_VLOG(2) << __func__ << ": player_id=" << pkt->GetPlayerId();
+ media_interface_->SetBrowsedPlayer(
+ pkt->GetPlayerId(),
+ base::Bind(&Device::SetBrowsedPlayerResponse,
+ weak_ptr_factory_.GetWeakPtr(), label, pkt));
+}
+
+void Device::SetBrowsedPlayerResponse(
+ uint8_t label, std::shared_ptr<SetBrowsedPlayerRequest> pkt, bool success,
+ std::string root_id, uint32_t num_items) {
+ DEVICE_VLOG(2) << __func__ << ": success=" << success << " root_id=\""
+ << root_id << "\" num_items=" << num_items;
+
+ if (!success) {
+ auto response = SetBrowsedPlayerResponseBuilder::MakeBuilder(
+ Status::INVALID_PLAYER_ID, 0x0000, num_items, 0, "");
+ send_message(label, true, std::move(response));
+ return;
+ }
+
+ curr_browsed_player_id_ = pkt->GetPlayerId();
+
+ // Clear the path and push the new root.
+ current_path_ = std::stack<std::string>();
+ current_path_.push(root_id);
+
+ auto response = SetBrowsedPlayerResponseBuilder::MakeBuilder(
+ Status::NO_ERROR, 0x0000, num_items, 0, "");
+ send_message(label, true, std::move(response));
+}
+
+void Device::SendMediaUpdate(bool metadata, bool play_status, bool queue) {
+ CHECK(media_interface_);
+ DEVICE_VLOG(4) << __func__ << ": Metadata=" << metadata
+ << " : play_status= " << play_status << " : queue=" << queue;
+
+ if (queue) {
+ HandleNowPlayingUpdate();
+ }
+
+ if (play_status) {
+ HandlePlayStatusUpdate();
+ HandlePlayPosUpdate();
+ }
+
+ if (metadata) HandleTrackUpdate();
+}
+
+void Device::SendFolderUpdate(bool available_players, bool addressed_player,
+ bool uids) {
+ CHECK(media_interface_);
+ DEVICE_VLOG(4) << __func__;
+
+ if (available_players) {
+ HandleAvailablePlayerUpdate();
+ }
+
+ if (addressed_player) {
+ HandleAddressedPlayerUpdate();
+ }
+}
+
+void Device::HandleTrackUpdate() {
+ DEVICE_VLOG(2) << __func__;
+ if (!track_changed_.first) {
+ LOG(WARNING) << "Device is not registered for track changed updates";
+ return;
+ }
+
+ media_interface_->GetNowPlayingList(
+ base::Bind(&Device::TrackChangedNotificationResponse,
+ weak_ptr_factory_.GetWeakPtr(), track_changed_.second, false));
+}
+
+void Device::HandlePlayStatusUpdate() {
+ DEVICE_VLOG(2) << __func__;
+ if (!play_status_changed_.first) {
+ LOG(WARNING) << "Device is not registered for play status updates";
+ return;
+ }
+
+ media_interface_->GetPlayStatus(base::Bind(
+ &Device::PlaybackStatusNotificationResponse,
+ weak_ptr_factory_.GetWeakPtr(), play_status_changed_.second, false));
+}
+
+void Device::HandleNowPlayingUpdate() {
+ DEVICE_VLOG(2) << __func__;
+
+ if (!now_playing_changed_.first) {
+ LOG(WARNING) << "Device is not registered for now playing updates";
+ return;
+ }
+
+ media_interface_->GetNowPlayingList(base::Bind(
+ &Device::HandleNowPlayingNotificationResponse,
+ weak_ptr_factory_.GetWeakPtr(), now_playing_changed_.second, false));
+}
+
+void Device::HandleNowPlayingNotificationResponse(
+ uint8_t label, bool interim, std::string curr_song_id,
+ std::vector<SongInfo> song_list) {
+ if (!now_playing_changed_.first) {
+ LOG(WARNING) << "Device is not registered for now playing updates";
+ return;
+ }
+
+ now_playing_ids_.clear();
+ for (const SongInfo& song : song_list) {
+ now_playing_ids_.insert(song.media_id);
+ }
+
+ auto response =
+ RegisterNotificationResponseBuilder::MakeNowPlayingBuilder(interim);
+ send_message(now_playing_changed_.second, false, std::move(response));
+
+ if (!interim) {
+ active_labels_.erase(label);
+ now_playing_changed_ = Notification(false, 0);
+ }
+}
+
+void Device::HandlePlayPosUpdate() {
+ DEVICE_VLOG(0) << __func__;
+ if (!play_pos_changed_.first) {
+ LOG(WARNING) << "Device is not registered for play position updates";
+ return;
+ }
+
+ media_interface_->GetPlayStatus(base::Bind(
+ &Device::PlaybackPosNotificationResponse, weak_ptr_factory_.GetWeakPtr(),
+ play_pos_changed_.second, false));
+}
+
+void Device::HandleAvailablePlayerUpdate() {
+ DEVICE_VLOG(1) << __func__;
+
+ if (!avail_players_changed_.first) {
+ LOG(WARNING) << "Device is not registered for available player updates";
+ return;
+ }
+
+ auto response =
+ RegisterNotificationResponseBuilder::MakeAvailablePlayersBuilder(false);
+ send_message_cb_.Run(avail_players_changed_.second, false,
+ std::move(response));
+
+ if (!avail_players_changed_.first) {
+ active_labels_.erase(avail_players_changed_.second);
+ avail_players_changed_ = Notification(false, 0);
+ }
+}
+
+void Device::HandleAddressedPlayerUpdate() {
+ DEVICE_VLOG(1) << __func__;
+ if (!addr_player_changed_.first) {
+ DEVICE_LOG(WARNING)
+ << "Device is not registered for addressed player updates";
+ return;
+ }
+ media_interface_->GetMediaPlayerList(base::Bind(
+ &Device::AddressedPlayerNotificationResponse,
+ weak_ptr_factory_.GetWeakPtr(), addr_player_changed_.second, false));
+}
+
+void Device::DeviceDisconnected() {
+ DEVICE_LOG(INFO) << "Device was disconnected";
+ play_pos_update_cb_.Cancel();
+
+ // TODO (apanicke): Once the interfaces are set in the Device construction,
+ // remove these conditionals.
+ if (volume_interface_ != nullptr)
+ volume_interface_->DeviceDisconnected(GetAddress());
+}
+
+static std::string volumeToStr(int8_t volume) {
+ if (volume == VOL_NOT_SUPPORTED) return "Absolute Volume not supported";
+ if (volume == VOL_REGISTRATION_FAILED)
+ return "Volume changed notification was rejected";
+ return std::to_string(volume);
+}
+
+std::ostream& operator<<(std::ostream& out, const Device& d) {
+ out << " " << d.address_.ToString();
+ if (d.IsActive()) out << " <Active>";
+ out << std::endl;
+ out << " Current Volume: " << volumeToStr(d.volume_) << std::endl;
+ out << " Current Browsed Player ID: " << d.curr_browsed_player_id_
+ << std::endl;
+ out << " Registered Notifications: " << std::endl;
+ if (d.track_changed_.first) {
+ out << " Track Changed" << std::endl;
+ }
+ if (d.play_status_changed_.first) {
+ out << " Play Status" << std::endl;
+ }
+ if (d.play_pos_changed_.first) {
+ out << " Play Position" << std::endl;
+ }
+ if (d.now_playing_changed_.first) {
+ out << " Now Playing" << std::endl;
+ }
+ if (d.addr_player_changed_.first) {
+ out << " Addressed Player" << std::endl;
+ }
+ if (d.avail_players_changed_.first) {
+ out << " Available Players" << std::endl;
+ }
+ if (d.uids_changed_.first) {
+ out << " UIDs Changed" << std::endl;
+ }
+
+ out << " Last Play State: " << d.last_play_status_.state << std::endl;
+ out << " Last Song Sent ID: \"" << d.last_song_info_.media_id << "\""
+ << std::endl;
+ out << " Current Folder: \"" << d.CurrentFolder() << "\"" << std::endl;
+ out << " MTU Sizes: CTRL=" << d.ctrl_mtu_ << " BROWSE=" << d.browse_mtu_
+ << std::endl;
+ // TODO (apanicke): Add supported features as well as media keys
+ return out;
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/profile/avrcp/device.h b/profile/avrcp/device.h
new file mode 100644
index 0000000..5ef886d
--- /dev/null
+++ b/profile/avrcp/device.h
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <iostream>
+#include <memory>
+#include <stack>
+
+#include <base/bind.h>
+#include <base/cancelable_callback.h>
+
+#include "avrcp.h"
+#include "avrcp_internal.h"
+#include "avrcp_packet.h"
+#include "media_id_map.h"
+#include "raw_address.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+/**
+ * A class representing a connection with a remote AVRCP device. It holds all
+ * the state and message handling for the device that it represents.
+ */
+// TODO (apanicke): Once we move over to having the individual message
+// responders for Browse and Classic AVRCP Messages move the device around via a
+// weak pointer.
+class Device {
+ public:
+ /**
+ * Device is friends with Avrcp::ConnectionHandler so that ConnectionHandler
+ * can deliver messages to individual devices.
+ */
+ friend class ConnectionHandler;
+
+ Device(
+ const RawAddress& bdaddr, bool avrcp13_compatibility,
+ base::Callback<void(uint8_t label, bool browse,
+ std::unique_ptr<::bluetooth::PacketBuilder> message)>
+ send_msg_cb,
+ uint16_t ctrl_mtu, uint16_t browse_mtu);
+ virtual ~Device() = default;
+
+ const RawAddress& GetAddress() const { return address_; };
+
+ /**
+ * Disconnects the AVRCP connection that this device represents.
+ */
+ bool Disconnect();
+
+ /**
+ * Returns true if the current device is active.
+ */
+ bool IsActive() const;
+
+ /**
+ * Register the interfaces that the device uses to get information. If the
+ * Volume Interface is null, then absolute volume is disabled.
+ * TODO (apanicke): Add these to the constructor/factory so that each device
+ * is created valid and can't be accidentally interacted with when no
+ * interfaces are registered.
+ */
+ void RegisterInterfaces(MediaInterface* interface,
+ A2dpInterface* a2dp_interface,
+ VolumeInterface* volume_interface);
+
+ /**
+ * Notify the device that metadata, play_status, and/or queue have updated
+ * via a boolean. Each boolean represents whether its respective content has
+ * updated.
+ */
+ virtual void SendMediaUpdate(bool metadata, bool play_status, bool queue);
+
+ /**
+ * Notify the device that the available_player, addressed_player, or UIDs
+ * have updated via a boolean. Each boolean represents whether its respective
+ * content has updated.
+ */
+ virtual void SendFolderUpdate(bool available_player, bool addressed_player,
+ bool uids);
+
+ // TODO (apanicke): Split the message handlers into two files. One
+ // for handling Browse Messages and the other for handling all other
+ // messages. This prevents the .cc file from getting bloated like it is
+ // now. The Device class will then become a state holder for each message
+ // and all the functions in these handler classes can be static since the
+ // device will be passed in. The extensions of the Device class can contain
+ // any interop handling for specific messages on specific devices.
+
+ void MessageReceived(uint8_t label, std::shared_ptr<Packet> pkt);
+ void BrowseMessageReceived(uint8_t label, std::shared_ptr<BrowsePacket> pkt);
+ void VendorPacketHandler(uint8_t label, std::shared_ptr<VendorPacket> pkt);
+
+ /********************
+ * MESSAGE RESPONSES
+ ********************/
+ // CURRENT TRACK CHANGED
+ virtual void HandleTrackUpdate();
+ virtual void TrackChangedNotificationResponse(
+ uint8_t label, bool interim, std::string curr_song_id,
+ std::vector<SongInfo> song_list);
+
+ // GET CAPABILITY
+ virtual void HandleGetCapabilities(
+ uint8_t label, const std::shared_ptr<GetCapabilitiesRequest>& pkt);
+
+ // REGISTER NOTIFICATION
+ virtual void HandleNotification(
+ uint8_t label, const std::shared_ptr<RegisterNotificationRequest>& pkt);
+
+ // PLAY STATUS CHANGED
+ virtual void HandlePlayStatusUpdate();
+
+ // NOW PLAYING LIST CHANGED
+ virtual void HandleNowPlayingUpdate();
+ virtual void HandleNowPlayingNotificationResponse(
+ uint8_t label, bool interim, std::string curr_song_id,
+ std::vector<SongInfo> song_list);
+
+ // PLAY POSITION CHANGED
+ virtual void HandlePlayPosUpdate();
+ virtual void PlaybackPosNotificationResponse(uint8_t label, bool interim,
+ PlayStatus status);
+
+ // GET PLAY STATUS
+ virtual void GetPlayStatusResponse(uint8_t label, PlayStatus status);
+ virtual void PlaybackStatusNotificationResponse(uint8_t label, bool interim,
+ PlayStatus status);
+
+ // GET ELEMENT ATTRIBUTE
+ // TODO (apanicke): Add a Handler function for this so if a specific device
+ // needs to implement an interop fix, you only need to overload the one
+ // function.
+ virtual void GetElementAttributesResponse(
+ uint8_t label, std::shared_ptr<GetElementAttributesRequest> pkt,
+ SongInfo info);
+
+ // AVAILABLE PLAYER CHANGED
+ virtual void HandleAvailablePlayerUpdate();
+
+ // ADDRESSED PLAYER CHANGED
+ virtual void HandleAddressedPlayerUpdate();
+ virtual void RejectNotification();
+ virtual void AddressedPlayerNotificationResponse(
+ uint8_t label, bool interim, uint16_t curr_player,
+ std::vector<MediaPlayerInfo> /* unused */);
+
+ // GET FOLDER ITEMS
+ virtual void HandleGetFolderItems(
+ uint8_t label, std::shared_ptr<GetFolderItemsRequest> request);
+ virtual void GetMediaPlayerListResponse(
+ uint8_t label, std::shared_ptr<GetFolderItemsRequest> pkt,
+ uint16_t curr_player, std::vector<MediaPlayerInfo> players);
+ virtual void GetVFSListResponse(uint8_t label,
+ std::shared_ptr<GetFolderItemsRequest> pkt,
+ std::vector<ListItem> items);
+ virtual void GetNowPlayingListResponse(
+ uint8_t label, std::shared_ptr<GetFolderItemsRequest> pkt,
+ std::string curr_song_id, std::vector<SongInfo> song_list);
+
+ // GET TOTAL NUMBER OF ITEMS
+ virtual void HandleGetTotalNumberOfItems(
+ uint8_t label, std::shared_ptr<GetTotalNumberOfItemsRequest> pkt);
+ virtual void GetTotalNumberOfItemsMediaPlayersResponse(
+ uint8_t label, uint16_t curr_player, std::vector<MediaPlayerInfo> list);
+ virtual void GetTotalNumberOfItemsVFSResponse(uint8_t label,
+ std::vector<ListItem> items);
+ virtual void GetTotalNumberOfItemsNowPlayingResponse(
+ uint8_t label, std::string curr_song_id, std::vector<SongInfo> song_list);
+
+ // GET ITEM ATTRIBUTES
+ virtual void HandleGetItemAttributes(
+ uint8_t label, std::shared_ptr<GetItemAttributesRequest> request);
+ virtual void GetItemAttributesNowPlayingResponse(
+ uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt,
+ std::string curr_media_id, std::vector<SongInfo> song_list);
+ virtual void GetItemAttributesVFSResponse(
+ uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt,
+ std::vector<ListItem> item_list);
+
+ // SET BROWSED PLAYER
+ virtual void HandleSetBrowsedPlayer(
+ uint8_t label, std::shared_ptr<SetBrowsedPlayerRequest> request);
+ virtual void SetBrowsedPlayerResponse(
+ uint8_t label, std::shared_ptr<SetBrowsedPlayerRequest> pkt, bool success,
+ std::string root_id, uint32_t num_items);
+
+ // CHANGE PATH
+ virtual void HandleChangePath(uint8_t label,
+ std::shared_ptr<ChangePathRequest> request);
+ virtual void ChangePathResponse(uint8_t label,
+ std::shared_ptr<ChangePathRequest> request,
+ std::vector<ListItem> list);
+
+ // PLAY ITEM
+ virtual void HandlePlayItem(uint8_t label,
+ std::shared_ptr<PlayItemRequest> request);
+
+ // SET ADDRESSED PLAYER
+ virtual void HandleSetAddressedPlayer(
+ uint8_t label, std::shared_ptr<SetAddressedPlayerRequest> request,
+ uint16_t curr_player, std::vector<MediaPlayerInfo> players);
+
+ /********************
+ * MESSAGE REQUESTS
+ ********************/
+ // VOLUME CHANGED NOTIFICATION
+ virtual void RegisterVolumeChanged();
+ virtual void HandleVolumeChanged(
+ uint8_t label, const std::shared_ptr<RegisterNotificationResponse>& pkt);
+
+ // SET VOLUME
+ virtual void SetVolume(int8_t volume);
+
+ /**
+ * This function is called by Avrcp::ConnectionHandler to signify that
+ * the remote device was disconnected.
+ *
+ * TODO (apanicke): Prevent allowing responses to messages while the device is
+ * disconnected by using a weak pointer handle to the device when we separate
+ * out the message handling. Also separate the logic in the future when
+ * disconnecting only browsing (Though this shouldn't matter as if we are
+ * disconnecting browsing then we should be fully disconnecting the device).
+ */
+ void DeviceDisconnected();
+
+ friend std::ostream& operator<<(std::ostream& out, const Device& c);
+
+ private:
+ // This should always contain one item which represents the root id on the
+ // current player.
+ std::string CurrentFolder() const {
+ if (current_path_.empty()) return "";
+ return current_path_.top();
+ }
+
+ void send_message(uint8_t label, bool browse,
+ std::unique_ptr<::bluetooth::PacketBuilder> message) {
+ active_labels_.erase(label);
+ send_message_cb_.Run(label, browse, std::move(message));
+ }
+ base::WeakPtrFactory<Device> weak_ptr_factory_;
+
+ // TODO (apanicke): Initialize all the variables in the constructor.
+ RawAddress address_;
+
+ // Enables AVRCP 1.3 Compatibility mode. This disables any AVRCP 1.4+ features
+ // such as browsing and playlists but has the highest chance of working.
+ bool avrcp13_compatibility_ = false;
+ base::Callback<void(uint8_t label, bool browse,
+ std::unique_ptr<::bluetooth::PacketBuilder> message)>
+ send_message_cb_;
+ uint16_t ctrl_mtu_;
+ uint16_t browse_mtu_;
+
+ int curr_browsed_player_id_ = -1;
+
+ std::stack<std::string> current_path_;
+
+ // Notification Trackers
+ using Notification = std::pair<bool, uint8_t>;
+ Notification track_changed_ = Notification(false, 0);
+ Notification play_status_changed_ = Notification(false, 0);
+ Notification play_pos_changed_ = Notification(false, 0);
+ Notification now_playing_changed_ = Notification(false, 0);
+ Notification addr_player_changed_ = Notification(false, 0);
+ Notification avail_players_changed_ = Notification(false, 0);
+ Notification uids_changed_ = Notification(false, 0);
+
+ MediaIdMap vfs_ids_;
+ MediaIdMap now_playing_ids_;
+
+ uint32_t play_pos_interval_ = 0;
+
+ SongInfo last_song_info_;
+ PlayStatus last_play_status_;
+
+ base::CancelableClosure play_pos_update_cb_;
+
+ MediaInterface* media_interface_ = nullptr;
+ A2dpInterface* a2dp_interface_ = nullptr;
+ VolumeInterface* volume_interface_ = nullptr;
+
+ // Labels used for messages currently in flight.
+ std::set<uint8_t> active_labels_;
+
+ int8_t volume_ = -1;
+ DISALLOW_COPY_AND_ASSIGN(Device);
+};
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/profile/avrcp/media_id_map.h b/profile/avrcp/media_id_map.h
new file mode 100644
index 0000000..f282f20
--- /dev/null
+++ b/profile/avrcp/media_id_map.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <map>
+
+namespace bluetooth {
+namespace avrcp {
+
+// A helper class to convert Media ID's (represented as strings) that are
+// received from the AVRCP Media Interface layer into UID's to be used
+// with connected devices.
+class MediaIdMap {
+ public:
+ void clear() {
+ media_id_to_uid_.clear();
+ uid_to_media_id_.clear();
+ }
+
+ std::string get_media_id(uint64_t uid) {
+ const auto& uid_it = uid_to_media_id_.find(uid);
+ if (uid_it == uid_to_media_id_.end()) return "";
+ return uid_it->second;
+ }
+
+ uint64_t get_uid(std::string media_id) {
+ const auto& media_id_it = media_id_to_uid_.find(media_id);
+ if (media_id_it == media_id_to_uid_.end()) return 0;
+ return media_id_it->second;
+ }
+
+ uint64_t insert(std::string media_id) {
+ if (media_id_to_uid_.find(media_id) != media_id_to_uid_.end()) {
+ return media_id_to_uid_[media_id];
+ }
+
+ uint64_t uid = media_id_to_uid_.size() + 1;
+ media_id_to_uid_.insert(std::pair<std::string, uint64_t>(media_id, uid));
+ uid_to_media_id_.insert(std::pair<uint64_t, std::string>(uid, media_id));
+ return uid;
+ }
+
+ private:
+ std::map<std::string, uint64_t> media_id_to_uid_;
+ std::map<uint64_t, std::string> uid_to_media_id_;
+};
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/profile/avrcp/tests/avrcp_connection_handler_test.cc b/profile/avrcp/tests/avrcp_connection_handler_test.cc
new file mode 100644
index 0000000..4f542f6
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_connection_handler_test.cc
@@ -0,0 +1,529 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <base/message_loop/message_loop.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "avrcp_internal.h"
+#include "avrcp_test_helper.h"
+#include "connection_handler.h"
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::SaveArgPointee;
+using ::testing::SetArgPointee;
+using ::testing::MockFunction;
+using ::testing::NiceMock;
+using ::testing::StrictMock;
+
+namespace bluetooth {
+namespace avrcp {
+
+using device_ptr = std::shared_ptr<Device>;
+
+class AvrcpConnectionHandlerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ ON_CALL(mock_avrcp_, Close(_)).WillByDefault(Return(0));
+ }
+
+ void SetUpSdp(tAVRC_FIND_CBACK* sdp_cb, bool browsing, bool absolute_volume) {
+ EXPECT_CALL(mock_avrcp_, FindService(_, _, _, _))
+ .Times(1)
+ .WillOnce(DoAll(SaveArg<3>(sdp_cb), Return(0)));
+
+ static tSDP_DISC_ATTR fake_features;
+
+ fake_features = {
+ .p_next_attr = nullptr,
+ .attr_id = 0,
+ .attr_len_type = 0,
+ .attr_value.v.u16 = 0,
+ };
+
+ if (browsing) fake_features.attr_value.v.u16 |= AVRC_SUPF_CT_BROWSE;
+ if (absolute_volume) fake_features.attr_value.v.u16 |= AVRC_SUPF_CT_CAT2;
+
+ EXPECT_CALL(mock_sdp_, FindAttributeInRec(_, _))
+ .Times(4)
+ .WillRepeatedly(Return(&fake_features));
+
+ EXPECT_CALL(mock_sdp_, FindServiceInDb(_, _, _))
+ .Times(2)
+ .WillOnce(Return((tSDP_DISC_REC*)0x01)) // Return any non null pointer
+ .WillOnce(Return((tSDP_DISC_REC*)0x01)); // Return any non null pointer
+
+ EXPECT_CALL(mock_sdp_, FindProfileVersionInRec(_, _, _))
+ .Times(2)
+ .WillRepeatedly(DoAll(SetArgPointee<2>(AVRC_REV_1_6), Return(true)));
+ }
+
+ protected:
+ ConnectionHandler* connection_handler_ = nullptr;
+
+ // We use NiceMock's here because each function of this code does quite a few
+ // operations. This way it is much easier to write a higher number of smaller
+ // tests without having a large amount of warnings.
+ NiceMock<MockFunction<void(device_ptr)>> device_cb;
+ NiceMock<MockAvrcpInterface> mock_avrcp_;
+ NiceMock<MockSdpInterface> mock_sdp_;
+ NiceMock<MockVolumeInterface> mock_volume_;
+};
+
+TEST_F(AvrcpConnectionHandlerTest, initializeTest) {
+ // Set an Expectation that Open will be called as an acceptor and save the
+ // connection callback once it is called
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kAny))
+ .Times(1)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Check that the callback was sent with us as the acceptor
+ ASSERT_EQ(conn_cb.conn, 1);
+
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+// Check that disconnecting without an active connection
+TEST_F(AvrcpConnectionHandlerTest, notConnectedDisconnectTest) {
+ // Set an Expectation that Open will be called twice as an acceptor and save
+ // the connection callback once it is called.
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kAny))
+ .Times(1)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Call the callback with a message saying the connection has closed
+ conn_cb.ctrl_cback.Run(1, AVRC_CLOSE_IND_EVT, 0, &RawAddress::kAny);
+
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+};
+
+// Test calling the connection callback after the handler is cleaned up
+TEST_F(AvrcpConnectionHandlerTest, disconnectAfterCleanupTest) {
+ // Set an Expectation that Open will be called twice as an acceptor and save
+ // the connection callback once it is called.
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kAny))
+ .Times(1)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+
+ // Call the callback with a message saying the connection has closed
+ conn_cb.ctrl_cback.Run(1, AVRC_CLOSE_IND_EVT, 0, &RawAddress::kAny);
+};
+
+// Check that we can handle having a remote device connect to us, start SDP, and
+// open another acceptor connection
+TEST_F(AvrcpConnectionHandlerTest, remoteDeviceConnectionTest) {
+ // Set an Expectation that Open will be called twice as an acceptor and save
+ // the connection callback once it is called.
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kAny))
+ .Times(2)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)))
+ .WillOnce(
+ DoAll(SetArgPointee<0>(2), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Check that the callback was sent with us as the acceptor
+ ASSERT_EQ(conn_cb.conn, 1);
+
+ // Set an Expectations that SDP will be performed
+ tAVRC_FIND_CBACK sdp_cb;
+ SetUpSdp(&sdp_cb, false, false);
+
+ // Set an expectation that a device will be created
+ EXPECT_CALL(device_cb, Call(_)).Times(1);
+
+ // Set an Expectation that OpenBrowse will be called in acceptor mode when the
+ // device connects.
+ EXPECT_CALL(mock_avrcp_, OpenBrowse(1, AVCT_ACP)).Times(1);
+
+ // Call the callback with a message saying that a remote device has connected
+ conn_cb.ctrl_cback.Run(1, AVRC_OPEN_IND_EVT, 0, &RawAddress::kAny);
+
+ // Run the SDP callback with status success
+ sdp_cb.Run(0);
+
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+// Check that when a device does not support absolute volume, that the
+// handler reports that via the volume interface.
+TEST_F(AvrcpConnectionHandlerTest, noAbsoluteVolumeTest) {
+ // Set an Expectation that Open will be called twice as an acceptor and save
+ // the connection callback once it is called.
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kAny))
+ .Times(2)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)))
+ .WillOnce(
+ DoAll(SetArgPointee<0>(2), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Set an Expectations that SDP will be performed
+ tAVRC_FIND_CBACK sdp_cb;
+ SetUpSdp(&sdp_cb, false, false);
+
+ EXPECT_CALL(mock_volume_, DeviceConnected(RawAddress::kAny)).Times(1);
+
+ // Call the callback with a message saying that a remote device has connected
+ conn_cb.ctrl_cback.Run(1, AVRC_OPEN_IND_EVT, 0, &RawAddress::kAny);
+
+ // Run the SDP callback with status success
+ sdp_cb.Run(0);
+
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+// Check that when a device does support absolute volume, that the handler
+// doesn't report it. Instead that will be left up to the device.
+TEST_F(AvrcpConnectionHandlerTest, absoluteVolumeTest) {
+ // Set an Expectation that Open will be called twice as an acceptor and save
+ // the connection callback once it is called.
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kAny))
+ .Times(2)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)))
+ .WillOnce(
+ DoAll(SetArgPointee<0>(2), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+
+ StrictMock<MockVolumeInterface> strict_volume;
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &strict_volume));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Set an Expectations that SDP will be performed with absolute volume
+ // supported
+ tAVRC_FIND_CBACK sdp_cb;
+ SetUpSdp(&sdp_cb, false, true);
+
+ // Call the callback with a message saying that a remote device has connected
+ conn_cb.ctrl_cback.Run(1, AVRC_OPEN_IND_EVT, 0, &RawAddress::kAny);
+
+ // Run the SDP callback with status success
+ sdp_cb.Run(0);
+
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+TEST_F(AvrcpConnectionHandlerTest, disconnectTest) {
+ // Set an Expectation that Open will be called twice as an acceptor and save
+ // the connection callback once it is called.
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kAny))
+ .Times(2)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<0>(2), Return(0)));
+
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Call the callback with a message saying that a remote device has connected
+ conn_cb.ctrl_cback.Run(1, AVRC_OPEN_IND_EVT, 0, &RawAddress::kAny);
+
+ // Set up the expectation that Close will be called
+ EXPECT_CALL(mock_avrcp_, Close(1)).Times(1);
+
+ // Call the callback with a message saying that a remote device has
+ // disconnected
+ conn_cb.ctrl_cback.Run(1, AVRC_CLOSE_IND_EVT, 0, &RawAddress::kAny);
+
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+// Check that we can handle having a remote device connect to us, start SDP, and
+// open another acceptor connection
+TEST_F(AvrcpConnectionHandlerTest, multipleRemoteDeviceConnectionTest) {
+ // Set an Expectation that Open will be called three times as an acceptor and
+ // save the connection callback once it is called.
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kAny))
+ .Times(3)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)))
+ .WillOnce(
+ DoAll(SetArgPointee<0>(2), SaveArgPointee<1>(&conn_cb), Return(0)))
+ .WillOnce(
+ DoAll(SetArgPointee<0>(3), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Check that the callback was sent with us as the acceptor
+ ASSERT_EQ(conn_cb.conn, 1);
+
+ // Set an Expectations that SDP will be performed
+ tAVRC_FIND_CBACK sdp_cb;
+ SetUpSdp(&sdp_cb, false, false);
+
+ // Set an expectation that a device will be created
+ EXPECT_CALL(device_cb, Call(_)).Times(1);
+
+ // Set an Expectation that OpenBrowse will be called in acceptor mode when the
+ // device connects on handle 1
+ EXPECT_CALL(mock_avrcp_, OpenBrowse(1, AVCT_ACP)).Times(1);
+
+ // Call the callback with a message saying that a remote device has connected
+ conn_cb.ctrl_cback.Run(1, AVRC_OPEN_IND_EVT, 0, &RawAddress::kAny);
+
+ // Run the SDP callback with status success
+ sdp_cb.Run(0);
+
+ // Set an Expectations that SDP will be performed again
+ SetUpSdp(&sdp_cb, false, false);
+
+ // Set an expectation that a device will be created again
+ EXPECT_CALL(device_cb, Call(_)).Times(1);
+
+ // Set an Expectation that OpenBrowse will be called in acceptor mode when the
+ // device connects on handle 2
+ EXPECT_CALL(mock_avrcp_, OpenBrowse(2, AVCT_ACP)).Times(1);
+
+ // Call the callback with a message saying that a remote device has connected
+ // with a different address
+ conn_cb.ctrl_cback.Run(2, AVRC_OPEN_IND_EVT, 0, &RawAddress::kEmpty);
+
+ // Run the SDP callback with status success
+ sdp_cb.Run(0);
+
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+TEST_F(AvrcpConnectionHandlerTest, cleanupTest) {
+ // Set Up Expectations for Initialize
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, _))
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)))
+ .WillOnce(
+ DoAll(SetArgPointee<0>(2), SaveArgPointee<1>(&conn_cb), Return(0)))
+ .WillOnce(
+ DoAll(SetArgPointee<0>(3), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Call the callback twice with a message saying that a remote device has
+ // connected
+ conn_cb.ctrl_cback.Run(1, AVRC_OPEN_IND_EVT, 0, &RawAddress::kAny);
+ conn_cb.ctrl_cback.Run(2, AVRC_OPEN_IND_EVT, 0, &RawAddress::kEmpty);
+
+ // Set an Expectation that Close will be called twice with handles 1 and 2
+ EXPECT_CALL(mock_avrcp_, Close(1));
+ EXPECT_CALL(mock_avrcp_, Close(2));
+
+ // Cleanup the object causing all open connections to be closed
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+TEST_F(AvrcpConnectionHandlerTest, connectToRemoteDeviceTest) {
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Set an Expectation that SDP will be performed
+ tAVRC_FIND_CBACK sdp_cb;
+ SetUpSdp(&sdp_cb, false, false);
+
+ // Connect to the device which starts SDP
+ connection_handler_->ConnectDevice(RawAddress::kEmpty);
+
+ // Set an expectation that the handler will try to open an AVRCP connection
+ // after doing SDP
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kEmpty))
+ .Times(1)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ // Complete SDP
+ sdp_cb.Run(0);
+
+ // Check that the callback was sent with us as the initiator
+ ASSERT_EQ(conn_cb.conn, 0);
+
+ // Set an expectation that a device will be created
+ EXPECT_CALL(device_cb, Call(_)).Times(1);
+
+ // Set an Expectation that OpenBrowse will NOT be called since the SDP entry
+ // didn't list browsing as a feature
+ EXPECT_CALL(mock_avrcp_, OpenBrowse(_, _)).Times(0);
+
+ // Call the callback with a message saying that a remote device has connected
+ // with a different address
+ conn_cb.ctrl_cback.Run(2, AVRC_OPEN_IND_EVT, 0, &RawAddress::kEmpty);
+
+ // Cleanup the object causing all open connections to be closed
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+TEST_F(AvrcpConnectionHandlerTest, connectToBrowsableRemoteDeviceTest) {
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Set an Expectation that SDP will be performed
+ tAVRC_FIND_CBACK sdp_cb;
+ SetUpSdp(&sdp_cb, true, false);
+
+ // Connect to the device which starts SDP
+ connection_handler_->ConnectDevice(RawAddress::kEmpty);
+
+ // Set an expectation that the handler will try to open an AVRCP connection
+ // after doing SDP
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kEmpty))
+ .Times(1)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)));
+
+ // Complete SDP
+ sdp_cb.Run(0);
+
+ // Check that the callback was sent with us as the initiator
+ ASSERT_EQ(conn_cb.conn, 0);
+
+ // Set an expectation that a device will be created
+ EXPECT_CALL(device_cb, Call(_)).Times(1);
+
+ // Set an Expectation that OpenBrowse will be called since browsing is listed
+ // as supported in SDP
+ EXPECT_CALL(mock_avrcp_, OpenBrowse(1, AVCT_INT)).Times(1);
+
+ // Call the callback with a message saying that a remote device has connected
+ // with a different address
+ conn_cb.ctrl_cback.Run(1, AVRC_OPEN_IND_EVT, 0, &RawAddress::kEmpty);
+
+ // Cleanup the object causing all open connections to be closed
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+TEST_F(AvrcpConnectionHandlerTest, disconnectWhileDoingSdpTest) {
+ // Set an Expectation that Open will be called twice as an acceptor and save
+ // the connection callback once it is called.
+ tAVRC_CONN_CB conn_cb;
+ EXPECT_CALL(mock_avrcp_, Open(_, _, RawAddress::kAny))
+ .Times(2)
+ .WillOnce(
+ DoAll(SetArgPointee<0>(1), SaveArgPointee<1>(&conn_cb), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<0>(2), Return(0)));
+
+ // Initialize the interface
+ auto bound_callback = base::Bind(&MockFunction<void(device_ptr)>::Call,
+ base::Unretained(&device_cb));
+ ASSERT_TRUE(ConnectionHandler::Initialize(bound_callback, &mock_avrcp_,
+ &mock_sdp_, &mock_volume_));
+ connection_handler_ = ConnectionHandler::Get();
+
+ // Set an Expectation that SDP will be performed
+ tAVRC_FIND_CBACK sdp_cb;
+ SetUpSdp(&sdp_cb, true, false);
+
+ // Call the callback with a message saying that a remote device has connected
+ conn_cb.ctrl_cback.Run(1, AVRC_OPEN_IND_EVT, 0, &RawAddress::kAny);
+
+ // Call the callback with a message saying that a remote device has
+ // disconnected
+ conn_cb.ctrl_cback.Run(1, AVRC_CLOSE_IND_EVT, 0, &RawAddress::kAny);
+
+ // Signal that SDP has completed
+ sdp_cb.Run(0);
+
+ connection_handler_ = nullptr;
+ ConnectionHandler::CleanUp();
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/profile/avrcp/tests/avrcp_device_test.cc b/profile/avrcp/tests/avrcp_device_test.cc
new file mode 100644
index 0000000..56f03e4
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_device_test.cc
@@ -0,0 +1,1072 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <iostream>
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <base/threading/thread.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "avrcp_packet.h"
+#include "avrcp_test_helper.h"
+#include "device.h"
+#include "stack_config.h"
+#include "tests/avrcp/avrcp_test_packets.h"
+#include "tests/packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+// TODO (apanicke): All the tests below are just basic positive unit tests.
+// Add more tests to increase code coverage.
+
+using AvrcpResponse = std::unique_ptr<::bluetooth::PacketBuilder>;
+using TestAvrcpPacket = TestPacketType<Packet>;
+using TestBrowsePacket = TestPacketType<BrowsePacket>;
+
+using ::testing::_;
+using ::testing::MockFunction;
+using ::testing::Mock;
+using ::testing::NiceMock;
+using ::testing::Return;
+
+bool get_pts_avrcp_test(void) { return false; }
+
+const stack_config_t interface = {
+ nullptr, get_pts_avrcp_test, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr};
+
+// TODO (apanicke): All the tests below are just basic positive unit tests.
+// Add more tests to increase code coverage.
+class AvrcpDeviceTest : public ::testing::Test {
+ public:
+ virtual void SetUp() override {
+ // NOTE: We use a wrapper lambda for the MockFunction in order to
+ // add a const qualifier to the response. Otherwise the MockFunction
+ // type doesn't match the callback type and a compiler error occurs.
+ base::Callback<void(uint8_t, bool, AvrcpResponse)> cb = base::Bind(
+ [](MockFunction<void(uint8_t, bool, const AvrcpResponse&)>* a,
+ uint8_t b, bool c, AvrcpResponse d) { a->Call(b, c, d); },
+ &response_cb);
+
+ // TODO (apanicke): Test setting avrc13 to false once we have full
+ // functionality.
+ test_device = new Device(RawAddress::kAny, true, cb, 0xFFFF, 0xFFFF);
+ }
+
+ virtual void TearDown() override {
+ delete test_device;
+ Mock::VerifyAndClear(&response_cb);
+ }
+
+ void SendMessage(uint8_t label, std::shared_ptr<Packet> message) {
+ test_device->MessageReceived(label, message);
+ }
+
+ void SendBrowseMessage(uint8_t label, std::shared_ptr<BrowsePacket> message) {
+ test_device->BrowseMessageReceived(label, message);
+ }
+
+ MockFunction<void(uint8_t, bool, const AvrcpResponse&)> response_cb;
+ Device* test_device;
+};
+
+TEST_F(AvrcpDeviceTest, addressTest) {
+ base::Callback<void(uint8_t, bool, AvrcpResponse)> cb =
+ base::Bind([](MockFunction<void(uint8_t, bool, const AvrcpResponse&)>* a,
+ uint8_t b, bool c, AvrcpResponse d) { a->Call(b, c, d); },
+ &response_cb);
+
+ Device device(RawAddress::kAny, true, cb, 0xFFFF, 0xFFFF);
+ ASSERT_EQ(device.GetAddress(), RawAddress::kAny);
+}
+
+TEST_F(AvrcpDeviceTest, trackChangedTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ SongInfo info = {"test_id",
+ {// The attribute map
+ AttributeEntry(Attribute::TITLE, "Test Song"),
+ AttributeEntry(Attribute::ARTIST_NAME, "Test Artist"),
+ AttributeEntry(Attribute::ALBUM_NAME, "Test Album"),
+ AttributeEntry(Attribute::TRACK_NUMBER, "1"),
+ AttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2"),
+ AttributeEntry(Attribute::GENRE, "Test Genre"),
+ AttributeEntry(Attribute::PLAYING_TIME, "1000")}};
+ std::vector<SongInfo> list = {info};
+
+ EXPECT_CALL(interface, GetNowPlayingList(_))
+ .Times(2)
+ .WillRepeatedly(InvokeCb<0>("test_id", list));
+
+ // Test the interim response for track changed
+ auto interim_response =
+ RegisterNotificationResponseBuilder::MakeTrackChangedBuilder(true, 0x01);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(interim_response))))
+ .Times(1);
+
+ auto request =
+ RegisterNotificationRequestBuilder::MakeBuilder(Event::TRACK_CHANGED, 0);
+ auto pkt = TestAvrcpPacket::Make();
+ request->Serialize(pkt);
+ SendMessage(1, pkt);
+
+ // Test the changed response for track changed
+ auto changed_response =
+ RegisterNotificationResponseBuilder::MakeTrackChangedBuilder(false, 0x01);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(changed_response))))
+ .Times(1);
+
+ test_device->HandleTrackUpdate();
+}
+
+TEST_F(AvrcpDeviceTest, playStatusTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ PlayStatus status1 = {0x1234, 0x5678, PlayState::PLAYING};
+ PlayStatus status2 = {0x1234, 0x5678, PlayState::STOPPED};
+
+ EXPECT_CALL(interface, GetPlayStatus(_))
+ .Times(2)
+ .WillOnce(InvokeCb<0>(status1))
+ .WillOnce(InvokeCb<0>(status2));
+
+ // Pretend the device is active
+ EXPECT_CALL(a2dp_interface, active_peer())
+ .WillRepeatedly(Return(test_device->GetAddress()));
+
+ // Test the interim response for play status changed
+ auto interim_response =
+ RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
+ true, PlayState::PLAYING);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(interim_response))))
+ .Times(1);
+
+ auto request = RegisterNotificationRequestBuilder::MakeBuilder(
+ Event::PLAYBACK_STATUS_CHANGED, 0);
+ auto pkt = TestAvrcpPacket::Make();
+ request->Serialize(pkt);
+ SendMessage(1, pkt);
+
+ // Test the changed response for play status changed
+ auto changed_response =
+ RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
+ false, PlayState::STOPPED);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(changed_response))))
+ .Times(1);
+ test_device->HandlePlayStatusUpdate();
+}
+
+TEST_F(AvrcpDeviceTest, playPositionTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ PlayStatus status1 = {0x1234, 0x5678, PlayState::PLAYING};
+ PlayStatus status2 = {0x5678, 0x9ABC, PlayState::STOPPED};
+
+ EXPECT_CALL(interface, GetPlayStatus(_))
+ .Times(2)
+ .WillOnce(InvokeCb<0>(status1))
+ .WillOnce(InvokeCb<0>(status2));
+
+ // Pretend the device is active
+ EXPECT_CALL(a2dp_interface, active_peer())
+ .WillRepeatedly(Return(test_device->GetAddress()));
+
+ // Test the interim response for play status changed
+ auto interim_response =
+ RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
+ true, PlayState::PLAYING);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(interim_response))))
+ .Times(1);
+
+ auto request = RegisterNotificationRequestBuilder::MakeBuilder(
+ Event::PLAYBACK_STATUS_CHANGED, 0);
+ auto pkt = TestAvrcpPacket::Make();
+ request->Serialize(pkt);
+ SendMessage(1, pkt);
+
+ // Test the changed response for play status changed
+ auto changed_response =
+ RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
+ false, PlayState::STOPPED);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(changed_response))))
+ .Times(1);
+ test_device->HandlePlayStatusUpdate();
+}
+
+TEST_F(AvrcpDeviceTest, nowPlayingTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ SongInfo info = {"test_id",
+ {// The attribute map
+ AttributeEntry(Attribute::TITLE, "Test Song"),
+ AttributeEntry(Attribute::ARTIST_NAME, "Test Artist"),
+ AttributeEntry(Attribute::ALBUM_NAME, "Test Album"),
+ AttributeEntry(Attribute::TRACK_NUMBER, "1"),
+ AttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2"),
+ AttributeEntry(Attribute::GENRE, "Test Genre"),
+ AttributeEntry(Attribute::PLAYING_TIME, "1000")}};
+ std::vector<SongInfo> list = {info};
+ EXPECT_CALL(interface, GetNowPlayingList(_))
+ .Times(2)
+ .WillRepeatedly(InvokeCb<0>("test_id", list));
+
+ // Test the interim response for now playing list changed
+ auto interim_response =
+ RegisterNotificationResponseBuilder::MakeNowPlayingBuilder(true);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(interim_response))))
+ .Times(1);
+
+ auto request = RegisterNotificationRequestBuilder::MakeBuilder(
+ Event::NOW_PLAYING_CONTENT_CHANGED, 0);
+ auto pkt = TestAvrcpPacket::Make();
+ request->Serialize(pkt);
+ SendMessage(1, pkt);
+
+ // Test the changed response for now playing list changed
+ auto changed_response =
+ RegisterNotificationResponseBuilder::MakeNowPlayingBuilder(false);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(changed_response))))
+ .Times(1);
+ test_device->HandleNowPlayingUpdate();
+}
+
+TEST_F(AvrcpDeviceTest, getPlayStatusTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ PlayStatus status = {0x1234, 0x5678, PlayState::PLAYING};
+
+ EXPECT_CALL(interface, GetPlayStatus(_))
+ .Times(1)
+ .WillOnce(InvokeCb<0>(status));
+
+ // Pretend the device is active
+ EXPECT_CALL(a2dp_interface, active_peer())
+ .WillRepeatedly(Return(test_device->GetAddress()));
+
+ auto expected_response = GetPlayStatusResponseBuilder::MakeBuilder(
+ 0x5678, 0x1234, PlayState::PLAYING);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(expected_response))))
+ .Times(1);
+
+ auto request = TestAvrcpPacket::Make(get_play_status_request);
+ SendMessage(1, request);
+}
+
+TEST_F(AvrcpDeviceTest, getElementAttributesTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ SongInfo info = {"test_id",
+ {// The attribute map
+ AttributeEntry(Attribute::TITLE, "Test Song"),
+ AttributeEntry(Attribute::ARTIST_NAME, "Test Artist"),
+ AttributeEntry(Attribute::ALBUM_NAME, "Test Album"),
+ AttributeEntry(Attribute::TRACK_NUMBER, "1"),
+ AttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2"),
+ AttributeEntry(Attribute::GENRE, "Test Genre"),
+ AttributeEntry(Attribute::PLAYING_TIME, "1000")}};
+
+ EXPECT_CALL(interface, GetSongInfo(_)).WillRepeatedly(InvokeCb<0>(info));
+
+ auto compare_to_partial =
+ GetElementAttributesResponseBuilder::MakeBuilder(0xFFFF);
+ compare_to_partial->AddAttributeEntry(Attribute::TITLE, "Test Song");
+ EXPECT_CALL(response_cb,
+ Call(2, false, matchPacket(std::move(compare_to_partial))))
+ .Times(1);
+ SendMessage(2, TestAvrcpPacket::Make(get_element_attributes_request_partial));
+
+ auto compare_to_full =
+ GetElementAttributesResponseBuilder::MakeBuilder(0xFFFF);
+ compare_to_full->AddAttributeEntry(Attribute::TITLE, "Test Song");
+ compare_to_full->AddAttributeEntry(Attribute::ARTIST_NAME, "Test Artist");
+ compare_to_full->AddAttributeEntry(Attribute::ALBUM_NAME, "Test Album");
+ compare_to_full->AddAttributeEntry(Attribute::TRACK_NUMBER, "1");
+ compare_to_full->AddAttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2");
+ compare_to_full->AddAttributeEntry(Attribute::GENRE, "Test Genre");
+ compare_to_full->AddAttributeEntry(Attribute::PLAYING_TIME, "1000");
+ EXPECT_CALL(response_cb,
+ Call(3, false, matchPacket(std::move(compare_to_full))))
+ .Times(1);
+ SendMessage(3, TestAvrcpPacket::Make(get_element_attributes_request_full));
+}
+
+TEST_F(AvrcpDeviceTest, getElementAttributesMtuTest) {
+ auto truncated_packet =
+ GetElementAttributesResponseBuilder::MakeBuilder(0xFFFF);
+ truncated_packet->AddAttributeEntry(Attribute::TITLE, "1234");
+
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ base::Callback<void(uint8_t, bool, AvrcpResponse)> cb =
+ base::Bind([](MockFunction<void(uint8_t, bool, const AvrcpResponse&)>* a,
+ uint8_t b, bool c, AvrcpResponse d) { a->Call(b, c, d); },
+ &response_cb);
+ Device device(RawAddress::kAny, true, cb, truncated_packet->size(), 0xFFFF);
+
+ device.RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ SongInfo info = {"test_id",
+ {AttributeEntry(Attribute::TITLE, "1234truncated")}};
+ EXPECT_CALL(interface, GetSongInfo(_)).WillRepeatedly(InvokeCb<0>(info));
+
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(truncated_packet))))
+ .Times(1);
+
+ device.MessageReceived(
+ 1, TestAvrcpPacket::Make(get_element_attributes_request_full));
+}
+
+TEST_F(AvrcpDeviceTest, getTotalNumberOfItemsMediaPlayersTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ std::vector<MediaPlayerInfo> player_list = {
+ {0, "player1", true}, {1, "player2", true}, {2, "player3", true},
+ };
+
+ EXPECT_CALL(interface, GetMediaPlayerList(_))
+ .Times(1)
+ .WillOnce(InvokeCb<0>(0, player_list));
+
+ auto expected_response = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(
+ Status::NO_ERROR, 0, player_list.size());
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(expected_response))))
+ .Times(1);
+
+ SendBrowseMessage(1, TestBrowsePacket::Make(
+ get_total_number_of_items_request_media_players));
+}
+
+TEST_F(AvrcpDeviceTest, getTotalNumberOfItemsVFSTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ std::vector<ListItem> vfs_list = {
+ {ListItem::FOLDER, {"id1", true, "folder1"}, SongInfo()},
+ {ListItem::FOLDER, {"id2", true, "folder2"}, SongInfo()},
+ };
+
+ EXPECT_CALL(interface, GetFolderItems(_, "", _))
+ .Times(1)
+ .WillOnce(InvokeCb<2>(vfs_list));
+
+ auto expected_response = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(
+ Status::NO_ERROR, 0, vfs_list.size());
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(expected_response))))
+ .Times(1);
+
+ SendBrowseMessage(
+ 1, TestBrowsePacket::Make(get_total_number_of_items_request_vfs));
+}
+
+TEST_F(AvrcpDeviceTest, getTotalNumberOfItemsNowPlayingTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ std::vector<SongInfo> now_playing_list = {
+ {"test_id1", {}}, {"test_id2", {}}, {"test_id3", {}},
+ {"test_id4", {}}, {"test_id5", {}},
+ };
+
+ EXPECT_CALL(interface, GetNowPlayingList(_))
+ .WillRepeatedly(InvokeCb<0>("test_id1", now_playing_list));
+
+ auto expected_response = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(
+ Status::NO_ERROR, 0, now_playing_list.size());
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(expected_response))))
+ .Times(1);
+
+ SendBrowseMessage(
+ 1, TestBrowsePacket::Make(get_total_number_of_items_request_now_playing));
+}
+
+TEST_F(AvrcpDeviceTest, getMediaPlayerListTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ MediaPlayerInfo info = {0, "Test Player", true};
+ std::vector<MediaPlayerInfo> list = {info};
+
+ EXPECT_CALL(interface, GetMediaPlayerList(_))
+ .Times(1)
+ .WillOnce(InvokeCb<0>(0, list));
+
+ auto expected_response = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ expected_response->AddMediaPlayer(MediaPlayerItem(0, "Test Player", true));
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(expected_response))))
+ .Times(1);
+
+ auto request = TestBrowsePacket::Make(get_folder_items_request);
+ SendBrowseMessage(1, request);
+}
+
+TEST_F(AvrcpDeviceTest, getNowPlayingListTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ SongInfo info = {"test_id",
+ {// The attribute map
+ AttributeEntry(Attribute::TITLE, "Test Song"),
+ AttributeEntry(Attribute::ARTIST_NAME, "Test Artist"),
+ AttributeEntry(Attribute::ALBUM_NAME, "Test Album"),
+ AttributeEntry(Attribute::TRACK_NUMBER, "1"),
+ AttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2"),
+ AttributeEntry(Attribute::GENRE, "Test Genre"),
+ AttributeEntry(Attribute::PLAYING_TIME, "1000")}};
+ std::vector<SongInfo> list = {info};
+
+ EXPECT_CALL(interface, GetNowPlayingList(_))
+ .WillRepeatedly(InvokeCb<0>("test_id", list));
+
+ auto expected_response = GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ expected_response->AddSong(MediaElementItem(1, "Test Song", info.attributes));
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(expected_response))))
+ .Times(1);
+
+ auto request = TestBrowsePacket::Make(get_folder_items_request_now_playing);
+ SendBrowseMessage(1, request);
+}
+
+TEST_F(AvrcpDeviceTest, getVFSFolderTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ FolderInfo info = {"test_id", true, "Test Folder"};
+ ListItem item = {ListItem::FOLDER, info, SongInfo()};
+ std::vector<ListItem> list = {item};
+
+ EXPECT_CALL(interface, GetFolderItems(_, "", _))
+ .Times(1)
+ .WillOnce(InvokeCb<2>(list));
+
+ auto expected_response = GetFolderItemsResponseBuilder::MakeVFSBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ expected_response->AddFolder(FolderItem(1, 0, true, "Test Folder"));
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(expected_response))))
+ .Times(1);
+
+ auto request = TestBrowsePacket::Make(get_folder_items_request_vfs);
+ SendBrowseMessage(1, request);
+}
+
+TEST_F(AvrcpDeviceTest, getFolderItemsMtuTest) {
+ auto truncated_packet = GetFolderItemsResponseBuilder::MakeVFSBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ truncated_packet->AddFolder(FolderItem(1, 0, true, "Test Folder0"));
+ truncated_packet->AddFolder(FolderItem(2, 0, true, "Test Folder1"));
+
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+ base::Callback<void(uint8_t, bool, AvrcpResponse)> cb =
+ base::Bind([](MockFunction<void(uint8_t, bool, const AvrcpResponse&)>* a,
+ uint8_t b, bool c, AvrcpResponse d) { a->Call(b, c, d); },
+ &response_cb);
+ Device device(RawAddress::kAny, true, cb, 0xFFFF, truncated_packet->size());
+ device.RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ FolderInfo info0 = {"test_id0", true, "Test Folder0"};
+ FolderInfo info1 = {"test_id1", true, "Test Folder1"};
+ FolderInfo info2 = {"test_id1", true, "Truncated folder"};
+ ListItem item0 = {ListItem::FOLDER, info0, SongInfo()};
+ ListItem item1 = {ListItem::FOLDER, info1, SongInfo()};
+ ListItem item2 = {ListItem::FOLDER, info1, SongInfo()};
+ std::vector<ListItem> list0 = {item0, item1, item2};
+ EXPECT_CALL(interface, GetFolderItems(_, "", _))
+ .WillRepeatedly(InvokeCb<2>(list0));
+
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(truncated_packet))))
+ .Times(1);
+ device.BrowseMessageReceived(
+ 1, TestBrowsePacket::Make(get_folder_items_request_vfs));
+}
+
+TEST_F(AvrcpDeviceTest, changePathTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ FolderInfo info0 = {"test_id0", true, "Test Folder0"};
+ FolderInfo info1 = {"test_id1", true, "Test Folder1"};
+ ListItem item0 = {ListItem::FOLDER, info0, SongInfo()};
+ ListItem item1 = {ListItem::FOLDER, info1, SongInfo()};
+ std::vector<ListItem> list0 = {item0, item1};
+ EXPECT_CALL(interface, GetFolderItems(_, "", _))
+ .Times(1)
+ .WillRepeatedly(InvokeCb<2>(list0));
+
+ FolderInfo info2 = {"test_id2", true, "Test Folder2"};
+ FolderInfo info3 = {"test_id3", true, "Test Folder3"};
+ FolderInfo info4 = {"test_id4", true, "Test Folder4"};
+ ListItem item2 = {ListItem::FOLDER, info2, SongInfo()};
+ ListItem item3 = {ListItem::FOLDER, info3, SongInfo()};
+ ListItem item4 = {ListItem::FOLDER, info4, SongInfo()};
+ std::vector<ListItem> list1 = {item2, item3, item4};
+ EXPECT_CALL(interface, GetFolderItems(_, "test_id1", _))
+ .Times(3)
+ .WillRepeatedly(InvokeCb<2>(list1));
+
+ std::vector<ListItem> list2 = {};
+ EXPECT_CALL(interface, GetFolderItems(_, "test_id3", _))
+ .Times(1)
+ .WillOnce(InvokeCb<2>(list2));
+
+ // Populate the VFS ID map
+ auto folder_items_response = GetFolderItemsResponseBuilder::MakeVFSBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ folder_items_response->AddFolder(FolderItem(1, 0, true, "Test Folder0"));
+ folder_items_response->AddFolder(FolderItem(2, 0, true, "Test Folder1"));
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(folder_items_response))))
+ .Times(1);
+
+ auto folder_request_builder =
+ GetFolderItemsRequestBuilder::MakeBuilder(Scope::VFS, 0, 3, {});
+ auto request = TestBrowsePacket::Make();
+ folder_request_builder->Serialize(request);
+ SendBrowseMessage(1, request);
+
+ // Change path down into Test Folder1
+ auto change_path_response =
+ ChangePathResponseBuilder::MakeBuilder(Status::NO_ERROR, list1.size());
+ EXPECT_CALL(response_cb,
+ Call(2, true, matchPacket(std::move(change_path_response))));
+ auto path_request_builder =
+ ChangePathRequestBuilder::MakeBuilder(0, Direction::DOWN, 2);
+ request = TestBrowsePacket::Make();
+ path_request_builder->Serialize(request);
+ SendBrowseMessage(2, request);
+
+ // Populate the new VFS ID
+ folder_items_response = GetFolderItemsResponseBuilder::MakeVFSBuilder(
+ Status::NO_ERROR, 0x0000, 0xFFFF);
+ folder_items_response->AddFolder(FolderItem(3, 0, true, "Test Folder2"));
+ folder_items_response->AddFolder(FolderItem(4, 0, true, "Test Folder3"));
+ folder_items_response->AddFolder(FolderItem(5, 0, true, "Test Folder4"));
+ EXPECT_CALL(response_cb,
+ Call(3, true, matchPacket(std::move(folder_items_response))))
+ .Times(1);
+ folder_request_builder =
+ GetFolderItemsRequestBuilder::MakeBuilder(Scope::VFS, 0, 3, {});
+ request = TestBrowsePacket::Make();
+ folder_request_builder->Serialize(request);
+ SendBrowseMessage(3, request);
+
+ // Change path down into Test Folder3
+ change_path_response =
+ ChangePathResponseBuilder::MakeBuilder(Status::NO_ERROR, list2.size());
+ EXPECT_CALL(response_cb,
+ Call(4, true, matchPacket(std::move(change_path_response))));
+ path_request_builder =
+ ChangePathRequestBuilder::MakeBuilder(0, Direction::DOWN, 4);
+ request = TestBrowsePacket::Make();
+ path_request_builder->Serialize(request);
+ SendBrowseMessage(4, request);
+
+ // Change path up back into Test Folder1
+ change_path_response =
+ ChangePathResponseBuilder::MakeBuilder(Status::NO_ERROR, list1.size());
+ EXPECT_CALL(response_cb,
+ Call(5, true, matchPacket(std::move(change_path_response))));
+ path_request_builder =
+ ChangePathRequestBuilder::MakeBuilder(0, Direction::UP, 0);
+ request = TestBrowsePacket::Make();
+ path_request_builder->Serialize(request);
+ SendBrowseMessage(5, request);
+}
+
+TEST_F(AvrcpDeviceTest, getItemAttributesNowPlayingTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ SongInfo info = {"test_id",
+ {// The attribute map
+ AttributeEntry(Attribute::TITLE, "Test Song"),
+ AttributeEntry(Attribute::ARTIST_NAME, "Test Artist"),
+ AttributeEntry(Attribute::ALBUM_NAME, "Test Album"),
+ AttributeEntry(Attribute::TRACK_NUMBER, "1"),
+ AttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2"),
+ AttributeEntry(Attribute::GENRE, "Test Genre"),
+ AttributeEntry(Attribute::PLAYING_TIME, "1000")}};
+ std::vector<SongInfo> list = {info};
+
+ EXPECT_CALL(interface, GetNowPlayingList(_))
+ .WillRepeatedly(InvokeCb<0>("test_id", list));
+
+ auto compare_to_full =
+ GetItemAttributesResponseBuilder::MakeBuilder(Status::NO_ERROR, 0xFFFF);
+ compare_to_full->AddAttributeEntry(Attribute::TITLE, "Test Song");
+ compare_to_full->AddAttributeEntry(Attribute::ARTIST_NAME, "Test Artist");
+ compare_to_full->AddAttributeEntry(Attribute::ALBUM_NAME, "Test Album");
+ compare_to_full->AddAttributeEntry(Attribute::TRACK_NUMBER, "1");
+ compare_to_full->AddAttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2");
+ compare_to_full->AddAttributeEntry(Attribute::GENRE, "Test Genre");
+ compare_to_full->AddAttributeEntry(Attribute::PLAYING_TIME, "1000");
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(compare_to_full))))
+ .Times(1);
+
+ auto request =
+ TestBrowsePacket::Make(get_item_attributes_request_all_attributes);
+ SendBrowseMessage(1, request);
+}
+
+TEST_F(AvrcpDeviceTest, geItemAttributesMtuTest) {
+ auto truncated_packet =
+ GetItemAttributesResponseBuilder::MakeBuilder(Status::NO_ERROR, 0xFFFF);
+ truncated_packet->AddAttributeEntry(Attribute::TITLE, "1234");
+
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+ base::Callback<void(uint8_t, bool, AvrcpResponse)> cb =
+ base::Bind([](MockFunction<void(uint8_t, bool, const AvrcpResponse&)>* a,
+ uint8_t b, bool c, AvrcpResponse d) { a->Call(b, c, d); },
+ &response_cb);
+ Device device(RawAddress::kAny, true, cb, 0xFFFF, truncated_packet->size());
+ device.RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ SongInfo info = {"test_id",
+ {AttributeEntry(Attribute::TITLE, "1234truncated")}};
+ std::vector<SongInfo> list = {info};
+ EXPECT_CALL(interface, GetNowPlayingList(_))
+ .WillRepeatedly(InvokeCb<0>("test_id", list));
+
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(truncated_packet))))
+ .Times(1);
+ device.BrowseMessageReceived(
+ 1, TestBrowsePacket::Make(get_item_attributes_request_all_attributes));
+}
+
+TEST_F(AvrcpDeviceTest, setAddressedPlayerTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ MediaPlayerInfo info = {0, "Test Player", true};
+ std::vector<MediaPlayerInfo> list = {info};
+
+ EXPECT_CALL(interface, GetMediaPlayerList(_))
+ .WillRepeatedly(InvokeCb<0>(0, list));
+
+ auto set_addr_player_rej_rsp = RejectBuilder::MakeBuilder(
+ CommandPdu::SET_ADDRESSED_PLAYER, Status::INVALID_PLAYER_ID);
+
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(set_addr_player_rej_rsp))))
+ .Times(1);
+
+ auto player_id_1_request =
+ TestAvrcpPacket::Make(set_addressed_player_id_1_request);
+ SendMessage(1, player_id_1_request);
+
+ auto set_addr_player_rsp =
+ SetAddressedPlayerResponseBuilder::MakeBuilder(Status::NO_ERROR);
+
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(set_addr_player_rsp))))
+ .Times(1);
+
+ auto request = TestAvrcpPacket::Make(set_addressed_player_request);
+ SendMessage(1, request);
+}
+
+TEST_F(AvrcpDeviceTest, volumeChangedTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+ MockVolumeInterface vol_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+ // Pretend the device is active
+ EXPECT_CALL(a2dp_interface, active_peer())
+ .WillRepeatedly(Return(test_device->GetAddress()));
+
+ auto reg_notif =
+ RegisterNotificationRequestBuilder::MakeBuilder(Event::VOLUME_CHANGED, 0);
+ EXPECT_CALL(response_cb, Call(_, false, matchPacket(std::move(reg_notif))))
+ .Times(1);
+ test_device->RegisterVolumeChanged();
+
+ EXPECT_CALL(vol_interface, DeviceConnected(test_device->GetAddress(), _))
+ .Times(1)
+ .WillOnce(InvokeCb<1>(0x30));
+ auto set_vol = SetAbsoluteVolumeRequestBuilder::MakeBuilder(0x30);
+ EXPECT_CALL(response_cb, Call(_, false, matchPacket(std::move(set_vol))))
+ .Times(1);
+
+ auto response = TestAvrcpPacket::Make(interim_volume_changed_notification);
+ SendMessage(1, response);
+
+ EXPECT_CALL(vol_interface, SetVolume(0x47)).Times(1);
+ auto reg_notif2 =
+ RegisterNotificationRequestBuilder::MakeBuilder(Event::VOLUME_CHANGED, 0);
+ EXPECT_CALL(response_cb, Call(_, false, matchPacket(std::move(reg_notif2))))
+ .Times(1);
+ response = TestAvrcpPacket::Make(changed_volume_changed_notification);
+ SendMessage(1, response);
+ response = TestAvrcpPacket::Make(interim_volume_changed_notification);
+ SendMessage(1, response);
+}
+
+TEST_F(AvrcpDeviceTest, volumeChangedNonActiveTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+ MockVolumeInterface vol_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+ // Pretend the device isn't active
+ EXPECT_CALL(a2dp_interface, active_peer())
+ .WillRepeatedly(Return(RawAddress::kEmpty));
+
+ auto reg_notif =
+ RegisterNotificationRequestBuilder::MakeBuilder(Event::VOLUME_CHANGED, 0);
+ EXPECT_CALL(response_cb, Call(_, false, matchPacket(std::move(reg_notif))))
+ .Times(1);
+ test_device->RegisterVolumeChanged();
+
+ EXPECT_CALL(vol_interface, DeviceConnected(test_device->GetAddress(), _))
+ .Times(1)
+ .WillOnce(InvokeCb<1>(0x30));
+ auto set_vol = SetAbsoluteVolumeRequestBuilder::MakeBuilder(0x30);
+ EXPECT_CALL(response_cb, Call(_, false, matchPacket(std::move(set_vol))))
+ .Times(1);
+
+ auto response = TestAvrcpPacket::Make(interim_volume_changed_notification);
+ SendMessage(1, response);
+
+ // Ensure that SetVolume is never called
+ EXPECT_CALL(vol_interface, SetVolume(0x47)).Times(0);
+
+ auto reg_notif2 =
+ RegisterNotificationRequestBuilder::MakeBuilder(Event::VOLUME_CHANGED, 0);
+ EXPECT_CALL(response_cb, Call(_, false, matchPacket(std::move(reg_notif2))))
+ .Times(1);
+ response = TestAvrcpPacket::Make(changed_volume_changed_notification);
+ SendMessage(1, response);
+ response = TestAvrcpPacket::Make(interim_volume_changed_notification);
+ SendMessage(1, response);
+}
+
+TEST_F(AvrcpDeviceTest, volumeRejectedTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+ MockVolumeInterface vol_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+ auto reg_notif =
+ RegisterNotificationRequestBuilder::MakeBuilder(Event::VOLUME_CHANGED, 0);
+ EXPECT_CALL(response_cb, Call(_, false, matchPacket(std::move(reg_notif))))
+ .Times(1);
+ test_device->RegisterVolumeChanged();
+
+ auto response = TestAvrcpPacket::Make(rejected_volume_changed_notification);
+ SendMessage(1, response);
+
+ EXPECT_CALL(response_cb, Call(_, _, _)).Times(0);
+}
+
+TEST_F(AvrcpDeviceTest, playPushedActiveDeviceTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+ MockVolumeInterface vol_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+ // Pretend the device is active
+ EXPECT_CALL(a2dp_interface, active_peer())
+ .WillRepeatedly(Return(test_device->GetAddress()));
+
+ auto play_pushed = PassThroughPacketBuilder::MakeBuilder(false, true, 0x44);
+ auto play_pushed_response =
+ PassThroughPacketBuilder::MakeBuilder(true, true, 0x44);
+ EXPECT_CALL(response_cb,
+ Call(_, false, matchPacket(std::move(play_pushed_response))))
+ .Times(1);
+
+ PlayStatus status = {0x1234, 0x5678, PlayState::PLAYING};
+ EXPECT_CALL(interface, GetPlayStatus(_))
+ .Times(1)
+ .WillOnce(InvokeCb<0>(status));
+
+ EXPECT_CALL(interface, SendKeyEvent(0x44, KeyState::PUSHED)).Times(1);
+
+ auto play_pushed_pkt = TestAvrcpPacket::Make();
+ play_pushed->Serialize(play_pushed_pkt);
+
+ SendMessage(1, play_pushed_pkt);
+}
+
+TEST_F(AvrcpDeviceTest, playPushedInactiveDeviceTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+ MockVolumeInterface vol_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+ // Pretend the device is not active
+ EXPECT_CALL(a2dp_interface, active_peer())
+ .WillRepeatedly(Return(RawAddress::kEmpty));
+
+ auto play_pushed = PassThroughPacketBuilder::MakeBuilder(false, true, 0x44);
+ auto play_pushed_response =
+ PassThroughPacketBuilder::MakeBuilder(true, true, 0x44);
+ EXPECT_CALL(response_cb,
+ Call(_, false, matchPacket(std::move(play_pushed_response))))
+ .Times(1);
+
+ // Expect that the device will try to set itself as active
+ EXPECT_CALL(interface, SetActiveDevice(test_device->GetAddress())).Times(1);
+
+ // No play command should be sent since the music is already playing
+ PlayStatus status = {0x1234, 0x5678, PlayState::PLAYING};
+ EXPECT_CALL(interface, GetPlayStatus(_))
+ .Times(1)
+ .WillOnce(InvokeCb<0>(status));
+ EXPECT_CALL(interface, SendKeyEvent(0x44, KeyState::PUSHED)).Times(0);
+
+ auto play_pushed_pkt = TestAvrcpPacket::Make();
+ play_pushed->Serialize(play_pushed_pkt);
+
+ SendMessage(1, play_pushed_pkt);
+}
+
+TEST_F(AvrcpDeviceTest, mediaKeyActiveDeviceTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+ MockVolumeInterface vol_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+ // Pretend the device is active
+ EXPECT_CALL(a2dp_interface, active_peer())
+ .WillRepeatedly(Return(test_device->GetAddress()));
+
+ auto play_released =
+ PassThroughPacketBuilder::MakeBuilder(false, false, 0x44);
+ auto play_released_response =
+ PassThroughPacketBuilder::MakeBuilder(true, false, 0x44);
+ EXPECT_CALL(response_cb,
+ Call(_, false, matchPacket(std::move(play_released_response))))
+ .Times(1);
+
+ EXPECT_CALL(interface, GetPlayStatus(_)).Times(0);
+
+ EXPECT_CALL(interface, SendKeyEvent(0x44, KeyState::RELEASED)).Times(1);
+
+ auto play_released_pkt = TestAvrcpPacket::Make();
+ play_released->Serialize(play_released_pkt);
+
+ SendMessage(1, play_released_pkt);
+}
+
+TEST_F(AvrcpDeviceTest, mediaKeyInactiveDeviceTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+ MockVolumeInterface vol_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, &vol_interface);
+
+ // Pretend the device is not active
+ EXPECT_CALL(a2dp_interface, active_peer())
+ .WillRepeatedly(Return(RawAddress::kEmpty));
+
+ auto play_released =
+ PassThroughPacketBuilder::MakeBuilder(false, false, 0x44);
+ auto play_released_response =
+ PassThroughPacketBuilder::MakeBuilder(true, false, 0x44);
+ EXPECT_CALL(response_cb,
+ Call(_, false, matchPacket(std::move(play_released_response))))
+ .Times(1);
+
+ EXPECT_CALL(interface, GetPlayStatus(_)).Times(0);
+
+ // Expect that the key event wont be sent to the media interface
+ EXPECT_CALL(interface, SendKeyEvent(0x44, KeyState::RELEASED)).Times(0);
+
+ auto play_released_pkt = TestAvrcpPacket::Make();
+ play_released->Serialize(play_released_pkt);
+
+ SendMessage(1, play_released_pkt);
+}
+
+TEST_F(AvrcpDeviceTest, getCapabilitiesTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ // GetCapabilities with CapabilityID COMPANY_ID
+ auto request_company_id_response =
+ GetCapabilitiesResponseBuilder::MakeCompanyIdBuilder(0x001958);
+ request_company_id_response->AddCompanyId(0x002345);
+ EXPECT_CALL(
+ response_cb,
+ Call(1, false, matchPacket(std::move(request_company_id_response))))
+ .Times(1);
+
+ auto request_company_id =
+ TestAvrcpPacket::Make(get_capabilities_request_company_id);
+ SendMessage(1, request_company_id);
+
+ // GetCapabilities with CapabilityID EVENTS_SUPPORTED
+ auto request_events_supported_response =
+ GetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(
+ Event::PLAYBACK_STATUS_CHANGED);
+ request_events_supported_response->AddEvent(Event::TRACK_CHANGED);
+ request_events_supported_response->AddEvent(Event::PLAYBACK_POS_CHANGED);
+
+ EXPECT_CALL(
+ response_cb,
+ Call(2, false, matchPacket(std::move(request_events_supported_response))))
+ .Times(1);
+
+ auto request_events_supported =
+ TestAvrcpPacket::Make(get_capabilities_request);
+ SendMessage(2, request_events_supported);
+
+ // GetCapabilities with CapabilityID UNKNOWN
+ auto request_unknown_response = RejectBuilder::MakeBuilder(
+ CommandPdu::GET_CAPABILITIES, Status::INVALID_PARAMETER);
+
+ EXPECT_CALL(response_cb,
+ Call(3, false, matchPacket(std::move(request_unknown_response))))
+ .Times(1);
+
+ auto request_unknown =
+ TestAvrcpPacket::Make(get_capabilities_request_unknown);
+ SendMessage(3, request_unknown);
+}
+
+TEST_F(AvrcpDeviceTest, getInvalidItemAttributesTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ SongInfo info = {"test_id",
+ {// The attribute map
+ AttributeEntry(Attribute::TITLE, "Test Song"),
+ AttributeEntry(Attribute::ARTIST_NAME, "Test Artist"),
+ AttributeEntry(Attribute::ALBUM_NAME, "Test Album"),
+ AttributeEntry(Attribute::TRACK_NUMBER, "1"),
+ AttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2"),
+ AttributeEntry(Attribute::GENRE, "Test Genre"),
+ AttributeEntry(Attribute::PLAYING_TIME, "1000")}};
+ std::vector<SongInfo> list = {info};
+
+ EXPECT_CALL(interface, GetNowPlayingList(_))
+ .WillRepeatedly(InvokeCb<0>("test_id", list));
+
+ auto compare_to_full = GetItemAttributesResponseBuilder::MakeBuilder(
+ Status::UIDS_CHANGED, 0xFFFF);
+ compare_to_full->AddAttributeEntry(Attribute::TITLE, "Test Song");
+ compare_to_full->AddAttributeEntry(Attribute::ARTIST_NAME, "Test Artist");
+ compare_to_full->AddAttributeEntry(Attribute::ALBUM_NAME, "Test Album");
+ compare_to_full->AddAttributeEntry(Attribute::TRACK_NUMBER, "1");
+ compare_to_full->AddAttributeEntry(Attribute::TOTAL_NUMBER_OF_TRACKS, "2");
+ compare_to_full->AddAttributeEntry(Attribute::GENRE, "Test Genre");
+ compare_to_full->AddAttributeEntry(Attribute::PLAYING_TIME, "1000");
+ EXPECT_CALL(response_cb,
+ Call(1, true, matchPacket(std::move(compare_to_full))))
+ .Times(1);
+
+ auto request = TestBrowsePacket::Make(
+ get_item_attributes_request_all_attributes_invalid);
+ SendBrowseMessage(1, request);
+}
+
+TEST_F(AvrcpDeviceTest, invalidRegisterNotificationTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto reg_notif_rej_rsp = RejectBuilder::MakeBuilder(
+ CommandPdu::REGISTER_NOTIFICATION, Status::INVALID_PARAMETER);
+ EXPECT_CALL(response_cb,
+ Call(1, false, matchPacket(std::move(reg_notif_rej_rsp))))
+ .Times(1);
+
+ auto reg_notif_request = TestAvrcpPacket::Make(register_notification_invalid);
+ SendMessage(1, reg_notif_request);
+}
+
+} // namespace avrcp
+} // namespace bluetooth
+
+const stack_config_t* stack_config_get_interface(void) {
+ return &bluetooth::avrcp::interface;
+}
diff --git a/profile/avrcp/tests/avrcp_test_helper.h b/profile/avrcp/tests/avrcp_test_helper.h
new file mode 100644
index 0000000..16fc31f
--- /dev/null
+++ b/profile/avrcp/tests/avrcp_test_helper.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+#include <type_traits>
+
+#include "avrcp.h"
+#include "avrcp_internal.h"
+#include "avrcp_packet.h"
+#include "tests/packet_test_helper.h"
+
+namespace bluetooth {
+namespace avrcp {
+
+using AvrcpResponse = std::unique_ptr<::bluetooth::PacketBuilder>;
+using TestAvrcpPacket = TestPacketType<Packet>;
+using TestBrowsePacket = TestPacketType<BrowsePacket>;
+
+class MockMediaInterface : public MediaInterface {
+ public:
+ MOCK_METHOD2(SendKeyEvent, void(uint8_t, KeyState));
+ MOCK_METHOD1(GetSongInfo, void(MediaInterface::SongInfoCallback));
+ MOCK_METHOD1(GetPlayStatus, void(MediaInterface::PlayStatusCallback));
+ MOCK_METHOD1(GetNowPlayingList, void(MediaInterface::NowPlayingCallback));
+ MOCK_METHOD1(GetMediaPlayerList, void(MediaInterface::MediaListCallback));
+ MOCK_METHOD3(GetFolderItems, void(uint16_t, std::string,
+ MediaInterface::FolderItemsCallback));
+ MOCK_METHOD2(SetBrowsedPlayer,
+ void(uint16_t, MediaInterface::SetBrowsedPlayerCallback));
+ MOCK_METHOD3(PlayItem, void(uint16_t, bool, std::string));
+ MOCK_METHOD1(SetActiveDevice, void(const RawAddress&));
+ MOCK_METHOD1(RegisterUpdateCallback, void(MediaCallbacks*));
+ MOCK_METHOD1(UnregisterUpdateCallback, void(MediaCallbacks*));
+};
+
+class MockVolumeInterface : public VolumeInterface {
+ public:
+ MOCK_METHOD1(DeviceConnected, void(const RawAddress&));
+ MOCK_METHOD2(DeviceConnected, void(const RawAddress&, VolumeChangedCb));
+ MOCK_METHOD1(DeviceDisconnected, void(const RawAddress&));
+ MOCK_METHOD1(SetVolume, void(int8_t));
+};
+
+class MockAvrcpInterface : public AvrcpInterface {
+ public:
+ MOCK_METHOD7(AddRecord, uint16_t(uint16_t, const char*, const char*, uint16_t,
+ uint32_t, bool, uint16_t));
+ MOCK_METHOD4(FindService, uint16_t(uint16_t, const RawAddress&,
+ tAVRC_SDP_DB_PARAMS*, tAVRC_FIND_CBACK));
+ MOCK_METHOD3(Open, uint16_t(uint8_t*, tAVRC_CONN_CB*, const RawAddress&));
+ MOCK_METHOD2(OpenBrowse, uint16_t(uint8_t, uint8_t));
+ MOCK_METHOD1(GetPeerMtu, uint16_t(uint8_t));
+ MOCK_METHOD1(GetBrowseMtu, uint16_t(uint8_t));
+ MOCK_METHOD1(Close, uint16_t(uint8_t));
+ MOCK_METHOD1(CloseBrowse, uint16_t(uint8_t));
+ MOCK_METHOD4(MsgReq, uint16_t(uint8_t, uint8_t, uint8_t, BT_HDR*));
+};
+
+class MockA2dpInterface : public A2dpInterface {
+ public:
+ MOCK_METHOD1(event_open, void(const RawAddress&));
+ MOCK_METHOD1(event_close, void(const RawAddress&));
+ MOCK_METHOD0(active_peer, RawAddress());
+};
+
+class MockSdpInterface : public SdpInterface {
+ public:
+ MOCK_METHOD6(InitDiscoveryDb,
+ bool(tSDP_DISCOVERY_DB*, uint32_t, uint16_t,
+ const bluetooth::Uuid*, uint16_t, uint16_t*));
+ MOCK_METHOD3(ServiceSearchAttributeRequest,
+ bool(const RawAddress&, tSDP_DISCOVERY_DB*, tSDP_DISC_CMPL_CB*));
+ MOCK_METHOD3(FindServiceInDb,
+ tSDP_DISC_REC*(tSDP_DISCOVERY_DB*, uint16_t, t_sdp_disc_rec*));
+ MOCK_METHOD2(FindAttributeInRec, tSDP_DISC_ATTR*(t_sdp_disc_rec*, uint16_t));
+ MOCK_METHOD3(FindProfileVersionInRec,
+ bool(t_sdp_disc_rec*, uint16_t, uint16_t*));
+};
+
+ACTION_TEMPLATE(InvokeCb, HAS_1_TEMPLATE_PARAMS(int, k),
+ AND_1_VALUE_PARAMS(input)) {
+ ::testing::get<k>(args).Run(input);
+}
+
+ACTION_TEMPLATE(InvokeCb, HAS_1_TEMPLATE_PARAMS(int, k),
+ AND_2_VALUE_PARAMS(a, b)) {
+ ::testing::get<k>(args).Run(a, b);
+}
+
+ACTION_TEMPLATE(InvokeCb, HAS_1_TEMPLATE_PARAMS(int, k),
+ AND_3_VALUE_PARAMS(a, b, c)) {
+ ::testing::get<k>(args).Run(a, b, c);
+}
+
+template <class PacketType>
+class PacketMatcher : public ::testing::MatcherInterface<const AvrcpResponse&> {
+ public:
+ AvrcpResponse pkt_to_compare_to_;
+
+ PacketMatcher(AvrcpResponse&& pkt) { pkt_to_compare_to_ = std::move(pkt); }
+
+ bool MatchAndExplain(
+ const AvrcpResponse& r,
+ ::testing::MatchResultListener* listener) const override {
+ auto packet1 = TestPacketType<PacketType>::Make();
+ r->Serialize(packet1);
+
+ auto packet2 = TestPacketType<PacketType>::Make();
+ pkt_to_compare_to_->Serialize(packet2);
+
+ if (packet1->GetData() != packet2->GetData()) {
+ *listener << "\nPacket to compare to: \n";
+ *listener << packet2->ToString();
+ *listener << "\nActual packet: \n";
+ *listener << packet1->ToString();
+ }
+
+ return packet1->GetData() == packet2->GetData();
+ }
+
+ void DescribeTo(::std::ostream* os) const override { *os << "Packets match"; }
+};
+
+inline ::testing::Matcher<const AvrcpResponse&> matchPacket(
+ std::unique_ptr<PacketBuilder>&& arg) {
+ return MakeMatcher(new PacketMatcher<Packet>(std::move(arg)));
+}
+
+inline ::testing::Matcher<const AvrcpResponse&> matchPacket(
+ std::unique_ptr<BrowsePacketBuilder>&& arg) {
+ return MakeMatcher(new PacketMatcher<BrowsePacket>(std::move(arg)));
+}
+
+} // namespace avrcp
+} // namespace bluetooth
diff --git a/proto/Android.bp b/proto/Android.bp
new file mode 100644
index 0000000..0f97c72
--- /dev/null
+++ b/proto/Android.bp
@@ -0,0 +1,19 @@
+java_library_static {
+ name: "bluetooth-protos-lite",
+ host_supported: true,
+ proto: {
+ type: "lite",
+ },
+ srcs: ["bluetooth/metrics/bluetooth.proto"],
+}
+
+cc_library_static {
+ name: "libbt-protos-lite",
+ host_supported: true,
+ proto: {
+ export_proto_headers: true,
+ type: "lite",
+ },
+ srcs: ["bluetooth/metrics/bluetooth.proto"],
+}
+
diff --git a/osi/src/protos/bluetooth.proto b/proto/bluetooth/metrics/bluetooth.proto
similarity index 65%
rename from osi/src/protos/bluetooth.proto
rename to proto/bluetooth/metrics/bluetooth.proto
index f6f1d0b..b1e28c3 100644
--- a/osi/src/protos/bluetooth.proto
+++ b/proto/bluetooth/metrics/bluetooth.proto
@@ -1,16 +1,28 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-// Author: pkanwar@google.com (Pankaj Kanwar)
-// Protos for uploading bluetooth metrics.
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
syntax = "proto2";
+
option optimize_for = LITE_RUNTIME;
-package clearcut.connectivity;
+// C++ namespace: bluetooth::metrics::BluetoothMetricsProto
+package bluetooth.metrics.BluetoothMetricsProto;
-option java_package = "com.google.wireless.android.play.playlog.connectivity";
-// option (datapol.file_vetting_status) = "latest";
-
-// import "storage/datapol/annotations/proto/semantic_annotations.proto";
+option java_package = "com.android.bluetooth";
+option java_outer_classname = "BluetoothMetricsProto";
message BluetoothLog {
// Session information that gets logged for every BT connection.
@@ -39,6 +51,12 @@
// Number of ScanEvent including discarded ones beyond capacity
optional int64 num_scan_event = 9;
+
+ // Statistics about Bluetooth profile connections
+ repeated ProfileConnectionStats profile_connection_stats = 10;
+
+ // Statistics about Headset profile connections
+ repeated HeadsetProfileConnectionStats headset_profile_connection_stats = 11;
}
// The information about the device.
@@ -115,6 +133,15 @@
optional int32 tx_bytes = 2;
}
+enum A2dpSourceCodec {
+ A2DP_SOURCE_CODEC_UNKNOWN = 0;
+ A2DP_SOURCE_CODEC_SBC = 1;
+ A2DP_SOURCE_CODEC_AAC = 2;
+ A2DP_SOURCE_CODEC_APTX = 3;
+ A2DP_SOURCE_CODEC_APTX_HD = 4;
+ A2DP_SOURCE_CODEC_LDAC = 5;
+}
+
// Session information that gets logged for A2DP session.
message A2DPSession {
// Media timer in milliseconds.
@@ -140,11 +167,17 @@
// Total audio time in this A2DP session
optional int64 audio_duration_millis = 8;
+
+ // Audio codec used in this A2DP session in A2DP source role
+ optional A2dpSourceCodec source_codec = 9;
+
+ // Whether A2DP offload is enabled in this A2DP session
+ optional bool is_a2dp_offload = 10;
}
message PairEvent {
// The reason for disconnecting
- // https://cs.corp.google.com/#android/system/bt/stack/include/hcidefs.h&q=failed_establish.
+ // See: system/bt/stack/include/hcidefs.h, HCI_ERR_CONN_FAILED_ESTABLISHMENT
optional int32 disconnect_reason = 1;
// Pair event time
@@ -158,12 +191,9 @@
message WakeEvent {
// Information about the wake event type.
enum WakeEventType {
- // Type is unknown.
UNKNOWN = 0;
-
// WakeLock was acquired.
ACQUIRED = 1;
-
// WakeLock was released.
RELEASED = 2;
}
@@ -172,7 +202,7 @@
optional WakeEventType wake_event_type = 1;
// Initiator of the scan. Only the first three names will be stored.
- // e.g. com.google.gms.
+ // e.g. com.company.app
optional string requestor = 2;
// Name of the wakelock (e.g. bluedroid_timer).
@@ -186,7 +216,6 @@
message ScanEvent {
// Scan type.
enum ScanTechnologyType {
- // Scan Type is unknown.
SCAN_TYPE_UNKNOWN = 0;
SCAN_TECH_TYPE_LE = 1;
@@ -200,7 +229,6 @@
enum ScanEventType {
// Scan started.
SCAN_EVENT_START = 0;
-
// Scan stopped.
SCAN_EVENT_STOP = 1;
}
@@ -209,7 +237,7 @@
optional ScanEventType scan_event_type = 1;
// Initiator of the scan. Only the first three names will be stored.
- // e.g. com.google.gms.
+ // e.g. com.company.app
optional string initiator = 2;
// Technology used for scanning.
@@ -222,3 +250,52 @@
optional int64 event_time_millis =
5; // [(datapol.semantic_type) = ST_TIMESTAMP];
}
+
+// Profile IDs defined in BluetoothProfile API class
+// Values must match API class values
+enum ProfileId {
+ PROFILE_UNKNOWN = 0;
+ HEADSET = 1;
+ A2DP = 2;
+ HEALTH = 3;
+ HID_HOST = 4;
+ PAN = 5;
+ PBAP = 6;
+ GATT = 7;
+ GATT_SERVER = 8;
+ MAP = 9;
+ SAP = 10;
+ A2DP_SINK = 11;
+ AVRCP_CONTROLLER = 12;
+ AVRCP = 13;
+ HEADSET_CLIENT = 16;
+ PBAP_CLIENT = 17;
+ MAP_CLIENT = 18;
+ HID_DEVICE = 19;
+ OPP = 20;
+ HEARING_AID = 21;
+}
+
+// Statistics about Bluetooth profile connections
+message ProfileConnectionStats {
+ // Profile id defined in BluetoothProfile.java
+ optional ProfileId profile_id = 1;
+
+ // Number of times that this profile is connected since last metrics dump
+ optional int32 num_times_connected = 2;
+}
+
+enum HeadsetProfileType {
+ HEADSET_PROFILE_UNKNOWN = 0;
+ HSP = 1;
+ HFP = 2;
+}
+
+// Statistics about headset profile connections
+message HeadsetProfileConnectionStats {
+ // Type of headset profile connected
+ optional HeadsetProfileType headset_profile_type = 1;
+
+ // Number of times this type of headset profile is connected
+ optional int32 num_times_connected = 2;
+}
\ No newline at end of file
diff --git a/service/Android.bp b/service/Android.bp
index 5c8cb6c..d24e0fa 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -8,6 +8,7 @@
include_dirs: [
"system/bt",
],
+ header_libs: [ "libbluetooth_headers" ],
}
// Source variables
@@ -59,7 +60,6 @@
"test/low_energy_client_unittest.cc",
"test/low_energy_scanner_unittest.cc",
"test/settings_unittest.cc",
- "test/uuid_unittest.cc",
]
// Native system service for target
@@ -71,15 +71,16 @@
btserviceLinuxSrc +
btserviceDaemonSrc +
["main.cc"],
- required: ["bluetooth.default"],
static_libs: [
"libbluetooth-binder-common",
"libbtcore",
+ "libbluetooth-types",
+ "libosi",
],
+
shared_libs: [
"libbinder",
"libcutils",
- "libhardware",
"liblog",
"libutils",
],
@@ -107,6 +108,7 @@
"libbluetooth-common",
"libgmock",
"liblog",
+ "libbluetooth-types",
],
host_supported: true,
target: {
@@ -130,19 +132,16 @@
"test/stub_ipc_handler_binder.cc",
],
},
- darwin: {
- srcs: [
- "test/stub_ipc_handler_linux.cc",
- ],
- },
- linux: {
+ linux_glibc: {
srcs: btserviceLinuxSrc + [
// TODO(bcf): Fix this test.
//"test/ipc_linux_unittest.cc",
],
- host_ldlibs: ["-lrt"],
},
},
+ sanitize: {
+ cfi: false,
+ },
}
// Native system service CLI for target
@@ -183,6 +182,7 @@
name: "libbluetoothtbd_hal",
defaults: ["fluoride_defaults"],
include_dirs: ["system/bt"],
+ header_libs: ["libbluetooth_headers"],
srcs: [
"hal/bluetooth_gatt_interface.cc",
"hal/bluetooth_interface.cc",
diff --git a/service/AndroidTest.xml b/service/AndroidTest.xml
index d16e371..0beba75 100644
--- a/service/AndroidTest.xml
+++ b/service/AndroidTest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/service/BUILD.gn b/service/BUILD.gn
index 2ad2982..2fb94b5 100644
--- a/service/BUILD.gn
+++ b/service/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google
+# Copyright 2015 Google
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
"common/bluetooth/scan_settings.cc",
"common/bluetooth/service.cc",
"common/bluetooth/util/atomic_string.cc",
- "common/bluetooth/uuid.cc",
"daemon.cc",
"gatt_client.cc",
"gatt_server.cc",
@@ -51,9 +50,9 @@
include_dirs = [
"//",
+ "//include",
"//service/common",
"//third_party/modp_b64/modp64",
- "//third_party/libhardware/include",
]
deps = [
@@ -88,7 +87,6 @@
sources = [
"test/fake_hal_util.cc",
"test/settings_unittest.cc",
- "test/uuid_unittest.cc",
]
include_dirs = [ "//" ]
diff --git a/service/adapter.cc b/service/adapter.cc
index e059c80..853ffdf 100644
--- a/service/adapter.cc
+++ b/service/adapter.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -330,9 +330,9 @@
}
lock_guard<mutex> lock(observers_lock_);
- FOR_EACH_OBSERVER(
- Adapter::Observer, observers_,
- OnDeviceConnectionStateChanged(this, device_address, connected));
+ for (auto& observer : observers_) {
+ observer.OnDeviceConnectionStateChanged(this, device_address, connected);
+ }
}
// Sends a request to set the given HAL adapter property type and value.
@@ -362,8 +362,9 @@
if (prev_state == new_state) return;
lock_guard<mutex> lock(observers_lock_);
- FOR_EACH_OBSERVER(Adapter::Observer, observers_,
- OnAdapterStateChanged(this, prev_state, new_state));
+ for (auto& observer : observers_) {
+ observer.OnAdapterStateChanged(this, prev_state, new_state);
+ }
}
private:
diff --git a/service/adapter.h b/service/adapter.h
index 37275db..3becaae 100644
--- a/service/adapter.h
+++ b/service/adapter.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/bluetooth_instance.h b/service/bluetooth_instance.h
index 868f425..d0146c5 100644
--- a/service/bluetooth_instance.h
+++ b/service/bluetooth_instance.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -20,21 +20,21 @@
#include <memory>
#include <base/macros.h>
+#include <bluetooth/uuid.h>
#include "service/common/bluetooth/low_energy_constants.h"
-#include "service/common/bluetooth/uuid.h"
namespace bluetooth {
// A BluetoothInstance represents an application's handle to an instance
-// that is registered with the underlying Bluetooth stack using a UUID and has a
+// that is registered with the underlying Bluetooth stack using a Uuid and has a
// stack-assigned integer "instance_id" ID associated with it.
class BluetoothInstance {
public:
virtual ~BluetoothInstance() = default;
// Returns the app-specific unique ID used while registering this instance.
- virtual const UUID& GetAppIdentifier() const = 0;
+ virtual const Uuid& GetAppIdentifier() const = 0;
// Returns the HAL "interface ID" assigned to this instance by the stack.
virtual int GetInstanceId() const = 0;
@@ -58,14 +58,14 @@
// Callback invoked as a result of a call to RegisterInstance.
using RegisterCallback =
- std::function<void(BLEStatus status, const UUID& app_uuid,
+ std::function<void(BLEStatus status, const Uuid& app_uuid,
std::unique_ptr<BluetoothInstance> instance)>;
// Registers an instance for the given unique identifier |app_uuid|.
// On success, this asynchronously invokes |callback| with a unique pointer
// to a BluetoothInstance whose ownership can be taken by the caller. In
// the case of an error, the pointer will contain nullptr.
- virtual bool RegisterInstance(const UUID& app_uuid,
+ virtual bool RegisterInstance(const Uuid& app_uuid,
const RegisterCallback& callback) = 0;
private:
diff --git a/service/client/main.cc b/service/client/main.cc
index be6b15e..e3b4c92 100644
--- a/service/client/main.cc
+++ b/service/client/main.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -593,7 +593,7 @@
bool connectable = false;
bool set_manufacturer_data = false;
bool set_uuid = false;
- bluetooth::UUID uuid;
+ bluetooth::Uuid uuid;
for (auto iter = args.begin(); iter != args.end(); ++iter) {
const std::string& arg = *iter;
@@ -609,14 +609,15 @@
// This flag has a single argument.
++iter;
if (iter == args.end()) {
- PrintError("Expected a UUID after -u");
+ PrintError("Expected a Uuid after -u");
return;
}
std::string uuid_str = *iter;
- uuid = bluetooth::UUID(uuid_str);
- if (!uuid.is_valid()) {
- PrintError("Invalid UUID: " + uuid_str);
+ bool is_valid = false;
+ uuid = bluetooth::Uuid::FromString(uuid_str, &is_valid);
+ if (!is_valid) {
+ PrintError("Invalid Uuid: " + uuid_str);
return;
}
@@ -661,19 +662,19 @@
// Determine the type and length bytes.
int uuid_size = uuid.GetShortestRepresentationSize();
uint8_t type;
- if (uuid_size == bluetooth::UUID::kNumBytes128)
- type = bluetooth::kEIRTypeComplete128BitUUIDs;
- else if (uuid_size == bluetooth::UUID::kNumBytes32)
- type = bluetooth::kEIRTypeComplete32BitUUIDs;
- else if (uuid_size == bluetooth::UUID::kNumBytes16)
- type = bluetooth::kEIRTypeComplete16BitUUIDs;
+ if (uuid_size == bluetooth::Uuid::kNumBytes128)
+ type = bluetooth::kEIRTypeComplete128BitUuids;
+ else if (uuid_size == bluetooth::Uuid::kNumBytes32)
+ type = bluetooth::kEIRTypeComplete32BitUuids;
+ else if (uuid_size == bluetooth::Uuid::kNumBytes16)
+ type = bluetooth::kEIRTypeComplete16BitUuids;
else
NOTREACHED() << "Unexpected size: " << uuid_size;
data.push_back(uuid_size + 1);
data.push_back(type);
- auto uuid_bytes = uuid.GetFullLittleEndian();
+ auto uuid_bytes = uuid.To128BitLE();
int index = (uuid_size == 16) ? 0 : 12;
data.insert(data.end(), uuid_bytes.data() + index,
uuid_bytes.data() + index + uuid_size);
diff --git a/service/common/Android.bp b/service/common/Android.bp
index e85d353..b3fbfc4 100644
--- a/service/common/Android.bp
+++ b/service/common/Android.bp
@@ -7,6 +7,7 @@
"-fvisibility=default",
],
host_supported: true,
+ header_libs: [ "libbluetooth_headers" ],
srcs: [
"bluetooth/adapter_state.cc",
"bluetooth/advertise_data.cc",
@@ -18,7 +19,6 @@
"bluetooth/scan_settings.cc",
"bluetooth/service.cc",
"bluetooth/util/atomic_string.cc",
- "bluetooth/uuid.cc",
],
export_include_dirs: ["./"],
include_dirs: ["system/bt"],
@@ -35,6 +35,7 @@
/* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/
"-fvisibility=default",
],
+ header_libs: [ "libbluetooth_headers" ],
srcs: [
"android/bluetooth/IBluetooth.aidl",
"android/bluetooth/IBluetoothCallback.aidl",
@@ -72,4 +73,7 @@
"libbase",
"libbinder",
],
+ static_libs: [
+ "libbluetooth-types",
+ ]
}
diff --git a/service/common/android/bluetooth/AdvertiseData.aidl b/service/common/android/bluetooth/AdvertiseData.aidl
index 3005670..9250f56 100644
--- a/service/common/android/bluetooth/AdvertiseData.aidl
+++ b/service/common/android/bluetooth/AdvertiseData.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/AdvertiseSettings.aidl b/service/common/android/bluetooth/AdvertiseSettings.aidl
index f479e5a..cc801ec 100644
--- a/service/common/android/bluetooth/AdvertiseSettings.aidl
+++ b/service/common/android/bluetooth/AdvertiseSettings.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/BluetoothGattCharacteristic.aidl b/service/common/android/bluetooth/BluetoothGattCharacteristic.aidl
index 5f3f729..6c6922e 100644
--- a/service/common/android/bluetooth/BluetoothGattCharacteristic.aidl
+++ b/service/common/android/bluetooth/BluetoothGattCharacteristic.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/BluetoothGattDescriptor.aidl b/service/common/android/bluetooth/BluetoothGattDescriptor.aidl
index 51af33e..5f6ed27 100644
--- a/service/common/android/bluetooth/BluetoothGattDescriptor.aidl
+++ b/service/common/android/bluetooth/BluetoothGattDescriptor.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/BluetoothGattIncludedService.aidl b/service/common/android/bluetooth/BluetoothGattIncludedService.aidl
index 0ee3f63..44fded0 100644
--- a/service/common/android/bluetooth/BluetoothGattIncludedService.aidl
+++ b/service/common/android/bluetooth/BluetoothGattIncludedService.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/BluetoothGattService.aidl b/service/common/android/bluetooth/BluetoothGattService.aidl
index 92bdfe0..04dba09 100644
--- a/service/common/android/bluetooth/BluetoothGattService.aidl
+++ b/service/common/android/bluetooth/BluetoothGattService.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetooth.aidl b/service/common/android/bluetooth/IBluetooth.aidl
index 1e96952..cc1e015 100644
--- a/service/common/android/bluetooth/IBluetooth.aidl
+++ b/service/common/android/bluetooth/IBluetooth.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothCallback.aidl b/service/common/android/bluetooth/IBluetoothCallback.aidl
index 24ac89b..96b7cdc 100644
--- a/service/common/android/bluetooth/IBluetoothCallback.aidl
+++ b/service/common/android/bluetooth/IBluetoothCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothGattClient.aidl b/service/common/android/bluetooth/IBluetoothGattClient.aidl
index ccd05b0..3af3831 100644
--- a/service/common/android/bluetooth/IBluetoothGattClient.aidl
+++ b/service/common/android/bluetooth/IBluetoothGattClient.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothGattClientCallback.aidl b/service/common/android/bluetooth/IBluetoothGattClientCallback.aidl
index 94dec9d..c4f4633 100644
--- a/service/common/android/bluetooth/IBluetoothGattClientCallback.aidl
+++ b/service/common/android/bluetooth/IBluetoothGattClientCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothGattServer.aidl b/service/common/android/bluetooth/IBluetoothGattServer.aidl
index 50d0a82..e48fd86 100644
--- a/service/common/android/bluetooth/IBluetoothGattServer.aidl
+++ b/service/common/android/bluetooth/IBluetoothGattServer.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothGattServerCallback.aidl b/service/common/android/bluetooth/IBluetoothGattServerCallback.aidl
index 06340d0..9c91770 100644
--- a/service/common/android/bluetooth/IBluetoothGattServerCallback.aidl
+++ b/service/common/android/bluetooth/IBluetoothGattServerCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothLeAdvertiser.aidl b/service/common/android/bluetooth/IBluetoothLeAdvertiser.aidl
index 5435af3..d5e4fca 100644
--- a/service/common/android/bluetooth/IBluetoothLeAdvertiser.aidl
+++ b/service/common/android/bluetooth/IBluetoothLeAdvertiser.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothLeAdvertiserCallback.aidl b/service/common/android/bluetooth/IBluetoothLeAdvertiserCallback.aidl
index d51657e..d9032e2 100644
--- a/service/common/android/bluetooth/IBluetoothLeAdvertiserCallback.aidl
+++ b/service/common/android/bluetooth/IBluetoothLeAdvertiserCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothLeScanner.aidl b/service/common/android/bluetooth/IBluetoothLeScanner.aidl
index 2f9506d..7d300e2 100644
--- a/service/common/android/bluetooth/IBluetoothLeScanner.aidl
+++ b/service/common/android/bluetooth/IBluetoothLeScanner.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothLeScannerCallback.aidl b/service/common/android/bluetooth/IBluetoothLeScannerCallback.aidl
index 4ee6be3..868b9cb 100644
--- a/service/common/android/bluetooth/IBluetoothLeScannerCallback.aidl
+++ b/service/common/android/bluetooth/IBluetoothLeScannerCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothLowEnergy.aidl b/service/common/android/bluetooth/IBluetoothLowEnergy.aidl
index 4d49430..63470d0 100644
--- a/service/common/android/bluetooth/IBluetoothLowEnergy.aidl
+++ b/service/common/android/bluetooth/IBluetoothLowEnergy.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/IBluetoothLowEnergyCallback.aidl b/service/common/android/bluetooth/IBluetoothLowEnergyCallback.aidl
index 858506a..ed9803b 100644
--- a/service/common/android/bluetooth/IBluetoothLowEnergyCallback.aidl
+++ b/service/common/android/bluetooth/IBluetoothLowEnergyCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/ScanFilter.aidl b/service/common/android/bluetooth/ScanFilter.aidl
index 2787a99..27d1ad8 100644
--- a/service/common/android/bluetooth/ScanFilter.aidl
+++ b/service/common/android/bluetooth/ScanFilter.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/ScanResult.aidl b/service/common/android/bluetooth/ScanResult.aidl
index 7ba2df5..3eac01b 100644
--- a/service/common/android/bluetooth/ScanResult.aidl
+++ b/service/common/android/bluetooth/ScanResult.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/ScanSettings.aidl b/service/common/android/bluetooth/ScanSettings.aidl
index 3b11b247..19b24c9 100644
--- a/service/common/android/bluetooth/ScanSettings.aidl
+++ b/service/common/android/bluetooth/ScanSettings.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/UUID.aidl b/service/common/android/bluetooth/UUID.aidl
index 54f993f..be09aaa 100644
--- a/service/common/android/bluetooth/UUID.aidl
+++ b/service/common/android/bluetooth/UUID.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/advertise_data.cc b/service/common/android/bluetooth/advertise_data.cc
index 7fe3601..75e5c59 100644
--- a/service/common/android/bluetooth/advertise_data.cc
+++ b/service/common/android/bluetooth/advertise_data.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/advertise_data.h b/service/common/android/bluetooth/advertise_data.h
index cde0eac..7543f05 100644
--- a/service/common/android/bluetooth/advertise_data.h
+++ b/service/common/android/bluetooth/advertise_data.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/advertise_settings.cc b/service/common/android/bluetooth/advertise_settings.cc
index b8fb1d1..c812abf 100644
--- a/service/common/android/bluetooth/advertise_settings.cc
+++ b/service/common/android/bluetooth/advertise_settings.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/advertise_settings.h b/service/common/android/bluetooth/advertise_settings.h
index afca233..9ee71b2 100644
--- a/service/common/android/bluetooth/advertise_settings.h
+++ b/service/common/android/bluetooth/advertise_settings.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/bluetooth_gatt_characteristic.cc b/service/common/android/bluetooth/bluetooth_gatt_characteristic.cc
index 6ed9e1a..9dbc076 100644
--- a/service/common/android/bluetooth/bluetooth_gatt_characteristic.cc
+++ b/service/common/android/bluetooth/bluetooth_gatt_characteristic.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@
UUID uuid;
status = parcel->readParcelable(&uuid);
if (status != OK) return status;
- uuid_ = uuid;
+ uuid_ = uuid.uuid;
status = parcel->readInt32(&tmp);
if (status != OK) return status;
diff --git a/service/common/android/bluetooth/bluetooth_gatt_characteristic.h b/service/common/android/bluetooth/bluetooth_gatt_characteristic.h
index 9884d99..954fe95 100644
--- a/service/common/android/bluetooth/bluetooth_gatt_characteristic.h
+++ b/service/common/android/bluetooth/bluetooth_gatt_characteristic.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/bluetooth_gatt_descriptor.cc b/service/common/android/bluetooth/bluetooth_gatt_descriptor.cc
index ecec0e0..e3ec03d 100644
--- a/service/common/android/bluetooth/bluetooth_gatt_descriptor.cc
+++ b/service/common/android/bluetooth/bluetooth_gatt_descriptor.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@
UUID uuid;
status_t status = parcel->readParcelable(&uuid);
if (status != OK) return status;
- uuid_ = (bluetooth::UUID)uuid;
+ uuid_ = uuid.uuid;
int32_t tmp;
status = parcel->readInt32(&tmp);
diff --git a/service/common/android/bluetooth/bluetooth_gatt_descriptor.h b/service/common/android/bluetooth/bluetooth_gatt_descriptor.h
index 955c645..4321f9d 100644
--- a/service/common/android/bluetooth/bluetooth_gatt_descriptor.h
+++ b/service/common/android/bluetooth/bluetooth_gatt_descriptor.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/bluetooth_gatt_included_service.cc b/service/common/android/bluetooth/bluetooth_gatt_included_service.cc
index c66e0d2..21cf19a 100644
--- a/service/common/android/bluetooth/bluetooth_gatt_included_service.cc
+++ b/service/common/android/bluetooth/bluetooth_gatt_included_service.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@
UUID uuid;
status_t status = parcel->readParcelable(&uuid);
if (status != OK) return status;
- uuid_ = uuid;
+ uuid_ = uuid.uuid;
int32_t tmp;
status = parcel->readInt32(&tmp);
diff --git a/service/common/android/bluetooth/bluetooth_gatt_included_service.h b/service/common/android/bluetooth/bluetooth_gatt_included_service.h
index 3a00a19..b011532 100644
--- a/service/common/android/bluetooth/bluetooth_gatt_included_service.h
+++ b/service/common/android/bluetooth/bluetooth_gatt_included_service.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
using android::Parcelable;
using android::status_t;
-using ::bluetooth::UUID;
+using ::bluetooth::Uuid;
namespace android {
namespace bluetooth {
@@ -56,11 +56,11 @@
uint16_t handle() const { return handle_; }
bool primary() const { return primary_; }
- UUID uuid() const { return uuid_; }
+ Uuid uuid() const { return uuid_; }
protected:
uint16_t handle_;
- UUID uuid_;
+ Uuid uuid_;
bool primary_;
};
} // namespace bluetooth
diff --git a/service/common/android/bluetooth/bluetooth_gatt_service.cc b/service/common/android/bluetooth/bluetooth_gatt_service.cc
index 0c0daeb..820ef43 100644
--- a/service/common/android/bluetooth/bluetooth_gatt_service.cc
+++ b/service/common/android/bluetooth/bluetooth_gatt_service.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -64,7 +64,7 @@
UUID uuid;
status = parcel->readParcelable(&uuid);
if (status != OK) return status;
- uuid_ = uuid;
+ uuid_ = uuid.uuid;
std::vector<BluetoothGattCharacteristic> characteristics;
status = parcel->readParcelableVector(&characteristics);
diff --git a/service/common/android/bluetooth/bluetooth_gatt_service.h b/service/common/android/bluetooth/bluetooth_gatt_service.h
index 932d4fb..a17b6da 100644
--- a/service/common/android/bluetooth/bluetooth_gatt_service.h
+++ b/service/common/android/bluetooth/bluetooth_gatt_service.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/scan_filter.cc b/service/common/android/bluetooth/scan_filter.cc
index 6bb6119..12d248a 100644
--- a/service/common/android/bluetooth/scan_filter.cc
+++ b/service/common/android/bluetooth/scan_filter.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -77,14 +77,14 @@
if (status != OK) return status;
device_address_ = std::string(String8(addr).string());
- std::unique_ptr<UUID> uuid;
+ UUID uuid;
status = parcel->readParcelable(&uuid);
if (status != OK) return status;
- service_uuid_ = std::move(uuid);
+ service_uuid_.reset(new ::bluetooth::Uuid(uuid.uuid));
status = parcel->readParcelable(&uuid);
if (status != OK) return status;
- service_uuid_mask_ = std::move(uuid);
+ service_uuid_mask_.reset(new ::bluetooth::Uuid(uuid.uuid));
return status;
}
diff --git a/service/common/android/bluetooth/scan_filter.h b/service/common/android/bluetooth/scan_filter.h
index c14f392..ebf34a4 100644
--- a/service/common/android/bluetooth/scan_filter.h
+++ b/service/common/android/bluetooth/scan_filter.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/scan_result.cc b/service/common/android/bluetooth/scan_result.cc
index 32acae3..5693ead 100644
--- a/service/common/android/bluetooth/scan_result.cc
+++ b/service/common/android/bluetooth/scan_result.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/scan_result.h b/service/common/android/bluetooth/scan_result.h
index 732ef0cc5..1a58b3e 100644
--- a/service/common/android/bluetooth/scan_result.h
+++ b/service/common/android/bluetooth/scan_result.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/scan_settings.cc b/service/common/android/bluetooth/scan_settings.cc
index 8c79cea..ca46c43 100644
--- a/service/common/android/bluetooth/scan_settings.cc
+++ b/service/common/android/bluetooth/scan_settings.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/scan_settings.h b/service/common/android/bluetooth/scan_settings.h
index 14b8bd5..53af9ee 100644
--- a/service/common/android/bluetooth/scan_settings.h
+++ b/service/common/android/bluetooth/scan_settings.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/android/bluetooth/uuid.cc b/service/common/android/bluetooth/uuid.cc
index 6cfc6db..077dd2b 100644
--- a/service/common/android/bluetooth/uuid.cc
+++ b/service/common/android/bluetooth/uuid.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@
// a second 64-bit integer. This is the same as writing the raw-bytes in
// sequence, but we don't want to assume any host-endianness here. So follow
// the same scheme and use the same Parcel APIs.
- UUID::UUID128Bit bytes = GetFullBigEndian();
+ ::bluetooth::Uuid::UUID128Bit bytes = uuid.To128BitBE();
uint64_t most_sig_bits =
((((uint64_t)bytes[0]) << 56) | (((uint64_t)bytes[1]) << 48) |
@@ -55,7 +55,7 @@
}
status_t UUID::readFromParcel(const Parcel* parcel) {
- UUID::UUID128Bit bytes;
+ ::bluetooth::Uuid::UUID128Bit bytes;
uint64_t most_sig_bits, least_sig_bits;
status_t status = parcel->readUint64(&most_sig_bits);
@@ -82,8 +82,7 @@
bytes[14] = (least_sig_bits >> 8) & 0xFF;
bytes[15] = least_sig_bits & 0xFF;
- id_ = bytes;
- is_valid_ = true;
+ uuid = ::bluetooth::Uuid::From128BitBE(bytes);
return status;
}
diff --git a/service/common/android/bluetooth/uuid.h b/service/common/android/bluetooth/uuid.h
index c0a09e0..1e84d19 100644
--- a/service/common/android/bluetooth/uuid.h
+++ b/service/common/android/bluetooth/uuid.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -28,11 +28,11 @@
namespace android {
namespace bluetooth {
-class UUID : public Parcelable, public ::bluetooth::UUID {
+class UUID : public Parcelable {
public:
UUID() = default;
// NOLINT, implicit converter
- UUID(const ::bluetooth::UUID& uuid) : ::bluetooth::UUID(uuid){}; // NOLINT
+ UUID(const ::bluetooth::Uuid& uuid) : uuid(uuid){}; // NOLINT
~UUID() = default;
// Write |this| parcelable to the given |parcel|. Keep in mind that
@@ -48,6 +48,15 @@
//
// Returns android::OK on success and an appropriate error otherwise.
status_t readFromParcel(const Parcel* parcel) override;
+
+ bool operator==(::bluetooth::Uuid rhs) const { return uuid == rhs; }
+
+ ::bluetooth::Uuid uuid;
};
} // namespace bluetooth
} // namespace android
+
+inline bool operator==(const ::bluetooth::Uuid& lhs,
+ const android::bluetooth::UUID& rhs) {
+ return lhs == rhs.uuid;
+}
diff --git a/service/common/bluetooth/adapter_state.cc b/service/common/bluetooth/adapter_state.cc
index 47c07af..a8866d3 100644
--- a/service/common/bluetooth/adapter_state.cc
+++ b/service/common/bluetooth/adapter_state.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/adapter_state.h b/service/common/bluetooth/adapter_state.h
index 1b2fbe4..42897ad 100644
--- a/service/common/bluetooth/adapter_state.h
+++ b/service/common/bluetooth/adapter_state.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/advertise_data.cc b/service/common/bluetooth/advertise_data.cc
index d9cac21..83b3c2f 100644
--- a/service/common/bluetooth/advertise_data.cc
+++ b/service/common/bluetooth/advertise_data.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/advertise_data.h b/service/common/bluetooth/advertise_data.h
index 0eb2bc1..bae83ee 100644
--- a/service/common/bluetooth/advertise_data.h
+++ b/service/common/bluetooth/advertise_data.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@
class AdvertiseData {
public:
// Constructs an AdvertiseData with the given parameters. |data| can only
- // contain the "Service UUIDs", "Service Data", "Manufacturer Data",
+ // contain the "Service Uuids", "Service Data", "Manufacturer Data",
// "Tx Power" and "Device name" fields as specified in the Core Specification
// Supplement. |data| must be properly formatted according to the supplement
// and contains the data as it will be sent over the wire.
diff --git a/service/common/bluetooth/advertise_settings.cc b/service/common/bluetooth/advertise_settings.cc
index 4d2605b..5ecc7b4 100644
--- a/service/common/bluetooth/advertise_settings.cc
+++ b/service/common/bluetooth/advertise_settings.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/advertise_settings.h b/service/common/bluetooth/advertise_settings.h
index 6a533dd..4aff4c9 100644
--- a/service/common/bluetooth/advertise_settings.h
+++ b/service/common/bluetooth/advertise_settings.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/characteristic.cc b/service/common/bluetooth/characteristic.cc
index 492a63a..28d02bc 100644
--- a/service/common/bluetooth/characteristic.cc
+++ b/service/common/bluetooth/characteristic.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/characteristic.h b/service/common/bluetooth/characteristic.h
index ba7328a..e6221b3 100644
--- a/service/common/bluetooth/characteristic.h
+++ b/service/common/bluetooth/characteristic.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
public:
Characteristic() = default;
Characteristic(const Characteristic& other);
- Characteristic(uint16_t handle, const UUID& uuid, uint8_t properties,
+ Characteristic(uint16_t handle, const Uuid& uuid, uint8_t properties,
uint16_t permissions,
const std::vector<Descriptor>& descriptors)
: handle_(handle),
@@ -43,7 +43,7 @@
bool operator!=(const Characteristic& rhs) const;
uint16_t handle() const { return handle_; }
- const UUID& uuid() const { return uuid_; }
+ const Uuid& uuid() const { return uuid_; }
uint8_t properties() const { return properties_; }
uint16_t permissions() const { return permissions_; }
const std::vector<Descriptor>& descriptors() const { return descriptors_; }
@@ -51,7 +51,7 @@
protected:
uint16_t handle_;
- UUID uuid_;
+ Uuid uuid_;
uint8_t properties_;
uint16_t permissions_;
std::vector<Descriptor> descriptors_;
diff --git a/service/common/bluetooth/descriptor.cc b/service/common/bluetooth/descriptor.cc
index 7e37596..b437cc3 100644
--- a/service/common/bluetooth/descriptor.cc
+++ b/service/common/bluetooth/descriptor.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/descriptor.h b/service/common/bluetooth/descriptor.h
index 35fe53e..2633820 100644
--- a/service/common/bluetooth/descriptor.h
+++ b/service/common/bluetooth/descriptor.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
Descriptor() = default;
Descriptor(const Descriptor& other);
Descriptor& operator=(const Descriptor& other);
- Descriptor(uint16_t handle, const UUID& uuid, uint16_t permissions)
+ Descriptor(uint16_t handle, const Uuid& uuid, uint16_t permissions)
: handle_(handle), uuid_(uuid), permissions_(permissions){};
virtual ~Descriptor() = default;
@@ -35,11 +35,11 @@
uint16_t handle() const { return handle_; }
uint16_t permissions() const { return permissions_; }
- const UUID& uuid() const { return uuid_; }
+ const Uuid& uuid() const { return uuid_; }
protected:
uint16_t handle_;
- UUID uuid_;
+ Uuid uuid_;
uint16_t permissions_;
};
}
diff --git a/service/common/bluetooth/low_energy_constants.h b/service/common/bluetooth/low_energy_constants.h
index 348fa60..9ec0aee 100644
--- a/service/common/bluetooth/low_energy_constants.h
+++ b/service/common/bluetooth/low_energy_constants.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -110,12 +110,12 @@
// Various Extended Inquiry Response fields types that are used for advertising
// data fields as defined in the Core Specification Supplement.
const uint8_t kEIRTypeFlags = 0x01;
-const uint8_t kEIRTypeIncomplete16BitUUIDs = 0x02;
-const uint8_t kEIRTypeComplete16BitUUIDs = 0x03;
-const uint8_t kEIRTypeIncomplete32BitUUIDs = 0x04;
-const uint8_t kEIRTypeComplete32BitUUIDs = 0x05;
-const uint8_t kEIRTypeIncomplete128BitUUIDs = 0x06;
-const uint8_t kEIRTypeComplete128BitUUIDs = 0x07;
+const uint8_t kEIRTypeIncomplete16BitUuids = 0x02;
+const uint8_t kEIRTypeComplete16BitUuids = 0x03;
+const uint8_t kEIRTypeIncomplete32BitUuids = 0x04;
+const uint8_t kEIRTypeComplete32BitUuids = 0x05;
+const uint8_t kEIRTypeIncomplete128BitUuids = 0x06;
+const uint8_t kEIRTypeComplete128BitUuids = 0x07;
const uint8_t kEIRTypeShortenedLocalName = 0x08;
const uint8_t kEIRTypeCompleteLocalName = 0x09;
const uint8_t kEIRTypeTxPower = 0x0A;
diff --git a/service/common/bluetooth/scan_filter.cc b/service/common/bluetooth/scan_filter.cc
index 3226c50..5aa4e9c 100644
--- a/service/common/bluetooth/scan_filter.cc
+++ b/service/common/bluetooth/scan_filter.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,16 +16,18 @@
#include "bluetooth/scan_filter.h"
+#include <raw_address.h>
+
namespace bluetooth {
ScanFilter::ScanFilter(const ScanFilter& other) {
device_name_ = other.device_name_;
device_address_ = other.device_address_;
- if (other.service_uuid_) service_uuid_.reset(new UUID(*other.service_uuid_));
+ if (other.service_uuid_) service_uuid_.reset(new Uuid(*other.service_uuid_));
if (other.service_uuid_mask_)
- service_uuid_mask_.reset(new UUID(*other.service_uuid_mask_));
+ service_uuid_mask_.reset(new Uuid(*other.service_uuid_mask_));
}
ScanFilter& ScanFilter::operator=(const ScanFilter& other) {
@@ -33,12 +35,12 @@
device_address_ = other.device_address_;
if (other.service_uuid_)
- service_uuid_.reset(new UUID(*other.service_uuid_));
+ service_uuid_.reset(new Uuid(*other.service_uuid_));
else
service_uuid_ = nullptr;
if (other.service_uuid_mask_)
- service_uuid_mask_.reset(new UUID(*other.service_uuid_mask_));
+ service_uuid_mask_.reset(new Uuid(*other.service_uuid_mask_));
else
service_uuid_mask_ = nullptr;
@@ -52,15 +54,15 @@
return true;
}
-void ScanFilter::SetServiceUuid(const UUID& service_uuid) {
- service_uuid_.reset(new UUID(service_uuid));
+void ScanFilter::SetServiceUuid(const Uuid& service_uuid) {
+ service_uuid_.reset(new Uuid(service_uuid));
service_uuid_mask_.reset();
}
-void ScanFilter::SetServiceUuidWithMask(const UUID& service_uuid,
- const UUID& mask) {
- service_uuid_.reset(new UUID(service_uuid));
- service_uuid_mask_.reset(new UUID(mask));
+void ScanFilter::SetServiceUuidWithMask(const Uuid& service_uuid,
+ const Uuid& mask) {
+ service_uuid_.reset(new Uuid(service_uuid));
+ service_uuid_mask_.reset(new Uuid(mask));
}
bool ScanFilter::operator==(const ScanFilter& rhs) const {
diff --git a/service/common/bluetooth/scan_filter.h b/service/common/bluetooth/scan_filter.h
index a8c30ee..e0afaa7 100644
--- a/service/common/bluetooth/scan_filter.h
+++ b/service/common/bluetooth/scan_filter.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -45,21 +45,21 @@
// |device_address| is in an illegal format.
bool SetDeviceAddress(const std::string& device_address);
- // The service UUID and its mask used while filtering scan results. See
+ // The service Uuid and its mask used while filtering scan results. See
// SetServiceUuidWithMask for what this mask does. The raw pointer returned
// from these getters belongs to the ScanFilter object. nullptr will be
// returned if these fields have not been set on this filter.
- const UUID* service_uuid() const { return service_uuid_.get(); }
- const UUID* service_uuid_mask() const { return service_uuid_mask_.get(); }
+ const Uuid* service_uuid() const { return service_uuid_.get(); }
+ const Uuid* service_uuid_mask() const { return service_uuid_mask_.get(); }
- // Sets the service UUID for this filter.
- void SetServiceUuid(const UUID& service_uuid);
+ // Sets the service Uuid for this filter.
+ void SetServiceUuid(const Uuid& service_uuid);
- // Sets the service UUID for this filter with a 128-bit mask. The mask allows
- // the caller to partially filter scanned service UUIDs. For any of the
- // 128-bits of a UUID, set the corresponding bit in the mask to 1 to match the
+ // Sets the service Uuid for this filter with a 128-bit mask. The mask allows
+ // the caller to partially filter scanned service Uuids. For any of the
+ // 128-bits of a Uuid, set the corresponding bit in the mask to 1 to match the
// advertised value, and 0 to ignore that bit.
- void SetServiceUuidWithMask(const UUID& service_uuid, const UUID& mask);
+ void SetServiceUuidWithMask(const Uuid& service_uuid, const Uuid& mask);
// Comparison operator.
bool operator==(const ScanFilter& rhs) const;
@@ -68,8 +68,8 @@
std::string device_name_;
std::string device_address_;
- std::unique_ptr<UUID> service_uuid_;
- std::unique_ptr<UUID> service_uuid_mask_;
+ std::unique_ptr<Uuid> service_uuid_;
+ std::unique_ptr<Uuid> service_uuid_mask_;
// TODO(armansito): Add service and manufacturer data filter fields.
};
diff --git a/service/common/bluetooth/scan_result.cc b/service/common/bluetooth/scan_result.cc
index 007019e..5258897 100644
--- a/service/common/bluetooth/scan_result.cc
+++ b/service/common/bluetooth/scan_result.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/scan_result.h b/service/common/bluetooth/scan_result.h
index 150ad4e..7fc62ef 100644
--- a/service/common/bluetooth/scan_result.h
+++ b/service/common/bluetooth/scan_result.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/scan_settings.cc b/service/common/bluetooth/scan_settings.cc
index dac0391..7f9aa90 100644
--- a/service/common/bluetooth/scan_settings.cc
+++ b/service/common/bluetooth/scan_settings.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/scan_settings.h b/service/common/bluetooth/scan_settings.h
index da907b5..30f98ba 100644
--- a/service/common/bluetooth/scan_settings.h
+++ b/service/common/bluetooth/scan_settings.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/service.cc b/service/common/bluetooth/service.cc
index 6a8a0c3..e9b3091 100644
--- a/service/common/bluetooth/service.cc
+++ b/service/common/bluetooth/service.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/service.h b/service/common/bluetooth/service.h
index b3ce0ea..9143d6d 100644
--- a/service/common/bluetooth/service.h
+++ b/service/common/bluetooth/service.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
public:
Service() = default;
Service(const Service& other);
- Service(uint16_t handle, bool primary, const UUID& uuid,
+ Service(uint16_t handle, bool primary, const Uuid& uuid,
const std::vector<Characteristic>& characteristics,
const std::vector<Service>& included_services)
: handle_(handle),
@@ -44,7 +44,7 @@
uint16_t handle() const { return handle_; }
bool primary() const { return primary_; }
- const UUID& uuid() const { return uuid_; }
+ const Uuid& uuid() const { return uuid_; }
const std::vector<Characteristic>& characteristics() const {
return characteristics_;
}
@@ -56,7 +56,7 @@
protected:
uint16_t handle_;
bool primary_;
- UUID uuid_;
+ Uuid uuid_;
std::vector<Characteristic> characteristics_;
std::vector<Service> included_services_;
};
diff --git a/service/common/bluetooth/util/atomic_string.cc b/service/common/bluetooth/util/atomic_string.cc
index fd71a5b..e431b40 100644
--- a/service/common/bluetooth/util/atomic_string.cc
+++ b/service/common/bluetooth/util/atomic_string.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/util/atomic_string.h b/service/common/bluetooth/util/atomic_string.h
index 68d37ad..46d4588 100644
--- a/service/common/bluetooth/util/atomic_string.h
+++ b/service/common/bluetooth/util/atomic_string.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/common/bluetooth/uuid.cc b/service/common/bluetooth/uuid.cc
deleted file mode 100644
index 16547ae..0000000
--- a/service/common/bluetooth/uuid.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-//
-// Copyright (C) 2015 Google, Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at:
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include "bluetooth/uuid.h"
-
-#include <algorithm>
-#include <array>
-#include <stack>
-#include <string>
-
-#include <base/rand_util.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-
-namespace bluetooth {
-
-namespace {
-
-const UUID::UUID128Bit kSigBaseUUID = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5f, 0x9b, 0x34, 0xfb}};
-
-} // namespace
-
-// static
-UUID UUID::GetRandom() {
- UUID128Bit bytes;
- base::RandBytes(bytes.data(), bytes.size());
- return UUID(bytes);
-}
-
-// static
-UUID UUID::GetNil() {
- UUID128Bit bytes;
- bytes.fill(0);
- return UUID(bytes);
-}
-
-// static
-UUID UUID::GetMax() {
- UUID128Bit bytes;
- bytes.fill(1);
- return UUID(bytes);
-}
-
-void UUID::InitializeDefault() {
- // Initialize to Bluetooth SIG base UUID.
- id_ = kSigBaseUUID;
- is_valid_ = true;
-}
-
-UUID::UUID() { InitializeDefault(); }
-
-UUID::UUID(std::string uuid) {
- InitializeDefault();
- is_valid_ = false;
-
- if (uuid.empty()) return;
-
- if (uuid.size() < 11 && uuid.find("0x") == 0) uuid = uuid.substr(2);
-
- if (uuid.size() != 4 && uuid.size() != 8 && uuid.size() != 36) return;
-
- if (uuid.size() == 36) {
- if (uuid[8] != '-') return;
- if (uuid[13] != '-') return;
- if (uuid[18] != '-') return;
- if (uuid[23] != '-') return;
-
- std::vector<std::string> tokens = base::SplitString(
- uuid, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
- if (tokens.size() != 5) return;
-
- uuid = base::JoinString(tokens, "");
- }
-
- const int start_index = uuid.size() == 4 ? 2 : 0;
- const size_t copy_size = std::min(id_.size(), uuid.size() / 2);
- for (size_t i = 0; i < copy_size; ++i) {
- std::string octet_text(uuid, i * 2, 2);
- char* temp = nullptr;
- id_[start_index + i] = strtol(octet_text.c_str(), &temp, 16);
- if (*temp != '\0') return;
- }
-
- is_valid_ = true;
-}
-
-UUID::UUID(const bt_uuid_t& uuid) {
- std::reverse_copy(uuid.uu, uuid.uu + sizeof(uuid.uu), id_.begin());
- is_valid_ = true;
-}
-
-UUID::UUID(const UUID16Bit& uuid) {
- InitializeDefault();
- std::copy(uuid.begin(), uuid.end(), id_.begin() + kNumBytes16);
-}
-
-UUID::UUID(const UUID32Bit& uuid) {
- InitializeDefault();
- std::copy(uuid.begin(), uuid.end(), id_.begin());
-}
-
-UUID::UUID(const UUID128Bit& uuid) : id_(uuid), is_valid_(true) {}
-
-UUID::UUID128Bit UUID::GetFullBigEndian() const { return id_; }
-
-UUID::UUID128Bit UUID::GetFullLittleEndian() const {
- UUID::UUID128Bit ret;
- std::reverse_copy(id_.begin(), id_.end(), ret.begin());
- return ret;
-}
-
-bt_uuid_t UUID::GetBlueDroid() const {
- bt_uuid_t ret;
- std::reverse_copy(id_.begin(), id_.end(), ret.uu);
- return ret;
-}
-
-std::string UUID::ToString() const {
- return base::StringPrintf(
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- id_[0], id_[1], id_[2], id_[3], id_[4], id_[5], id_[6], id_[7], id_[8],
- id_[9], id_[10], id_[11], id_[12], id_[13], id_[14], id_[15]);
-}
-
-size_t UUID::GetShortestRepresentationSize() const {
- if (memcmp(id_.data() + 4, kSigBaseUUID.data() + 4, id_.size() - 4) != 0)
- return kNumBytes128;
-
- if (id_[0] == 0 && id_[1] == 0) return kNumBytes16;
-
- return kNumBytes32;
-}
-
-bool UUID::operator<(const UUID& rhs) const {
- return std::lexicographical_compare(id_.begin(), id_.end(), rhs.id_.begin(),
- rhs.id_.end());
-}
-
-bool UUID::operator==(const UUID& rhs) const {
- return std::equal(id_.begin(), id_.end(), rhs.id_.begin());
-}
-
-} // namespace bluetooth
diff --git a/service/common/bluetooth/uuid.h b/service/common/bluetooth/uuid.h
deleted file mode 100644
index 034654c..0000000
--- a/service/common/bluetooth/uuid.h
+++ /dev/null
@@ -1,109 +0,0 @@
-//
-// Copyright (C) 2015 Google, Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at:
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#pragma once
-
-#include <array>
-#include <string>
-
-// TODO: Find places that break include what you use and remove this.
-#include <base/logging.h>
-#include <hardware/bluetooth.h>
-
-namespace bluetooth {
-
-class UUID {
- public:
- static constexpr size_t kNumBytes128 = 16;
- static constexpr size_t kNumBytes32 = 4;
- static constexpr size_t kNumBytes16 = 2;
-
- typedef std::array<uint8_t, kNumBytes16> UUID16Bit;
- typedef std::array<uint8_t, kNumBytes32> UUID32Bit;
- typedef std::array<uint8_t, kNumBytes128> UUID128Bit;
-
- // Creates and returns a random 128-bit UUID.
- static UUID GetRandom();
-
- // Creates and returns a UUID in which all 128 bits are equal to 0.
- static UUID GetNil();
-
- // Creates and returns a UUID in which all 128 bits are equal to 1.
- static UUID GetMax();
-
- // Construct a Bluetooth 'base' UUID.
- UUID();
- virtual ~UUID() = default;
-
- // BlueDroid constructor.
- explicit UUID(const bt_uuid_t& uuid);
-
- // String constructor. Only hex ASCII accepted.
- explicit UUID(std::string uuid);
-
- // std::array variants constructors.
- explicit UUID(const UUID16Bit& uuid);
- explicit UUID(const UUID32Bit& uuid);
- explicit UUID(const UUID128Bit& uuid);
-
- // Provide the full network-byte-ordered blob.
- UUID128Bit GetFullBigEndian() const;
-
- // Provide blob in Little endian (BlueDroid expects this).
- UUID128Bit GetFullLittleEndian() const;
-
- // Helper for bluedroid LE type.
- bt_uuid_t GetBlueDroid() const;
-
- // Returns a string representation for the UUID.
- std::string ToString() const;
-
- // Returns whether or not this UUID was initialized correctly.
- bool is_valid() const { return is_valid_; }
-
- // Returns the shortest possible representation of this UUID in bytes.
- size_t GetShortestRepresentationSize() const;
-
- bool operator<(const UUID& rhs) const;
- bool operator==(const UUID& rhs) const;
- inline bool operator!=(const UUID& rhs) const { return !(*this == rhs); }
-
- protected:
- void InitializeDefault();
-
- // Network-byte-ordered ID.
- UUID128Bit id_;
-
- // True if this UUID was initialized with a correct representation.
- bool is_valid_;
-};
-
-} // namespace bluetooth
-
-// Custom std::hash specialization so that bluetooth::UUID can be used as a key
-// in std::unordered_map.
-namespace std {
-
-template <>
-struct hash<bluetooth::UUID> {
- std::size_t operator()(const bluetooth::UUID& key) const {
- const auto& uuid_bytes = key.GetFullBigEndian();
- std::hash<std::string> hash_fn;
- return hash_fn(std::string((char*)uuid_bytes.data(), uuid_bytes.size()));
- }
-};
-
-} // namespace std
diff --git a/service/daemon.cc b/service/daemon.cc
index 7fd9b2b..86a3b5a 100644
--- a/service/daemon.cc
+++ b/service/daemon.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
#include <memory>
#include <base/logging.h>
+#include <base/run_loop.h>
#include "service/adapter.h"
#include "service/hal/bluetooth_gatt_interface.h"
@@ -44,7 +45,7 @@
CleanUpBluetoothStack();
}
- void StartMainLoop() override { message_loop_->Run(); }
+ void StartMainLoop() override { base::RunLoop().Run(); }
Settings* GetSettings() const override { return settings_.get(); }
diff --git a/service/daemon.h b/service/daemon.h
index 0afefa9..0d6474b 100644
--- a/service/daemon.h
+++ b/service/daemon.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/doc/IBluetooth.txt b/service/doc/IBluetooth.txt
index 54695e6..6560daa 100644
--- a/service/doc/IBluetooth.txt
+++ b/service/doc/IBluetooth.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015, The Android Open Source Project
+ * Copyright 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/doc/IBluetoothCallback.txt b/service/doc/IBluetoothCallback.txt
index 612ecca..93dcdef 100644
--- a/service/doc/IBluetoothCallback.txt
+++ b/service/doc/IBluetoothCallback.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015, The Android Open Source Project
+ * Copyright 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/doc/IBluetoothGattClient.txt b/service/doc/IBluetoothGattClient.txt
index 8e55005..b0fc905 100644
--- a/service/doc/IBluetoothGattClient.txt
+++ b/service/doc/IBluetoothGattClient.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015, The Android Open Source Project
+ * Copyright 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/doc/IBluetoothGattClientCallback.txt b/service/doc/IBluetoothGattClientCallback.txt
index d3ec6ed..455fcac 100644
--- a/service/doc/IBluetoothGattClientCallback.txt
+++ b/service/doc/IBluetoothGattClientCallback.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015, The Android Open Source Project
+ * Copyright 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/doc/IBluetoothGattServer.txt b/service/doc/IBluetoothGattServer.txt
index 0efecab..848109a 100644
--- a/service/doc/IBluetoothGattServer.txt
+++ b/service/doc/IBluetoothGattServer.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015, The Android Open Source Project
+ * Copyright 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/doc/IBluetoothGattServerCallback.txt b/service/doc/IBluetoothGattServerCallback.txt
index 3744ff1..e3eefba 100644
--- a/service/doc/IBluetoothGattServerCallback.txt
+++ b/service/doc/IBluetoothGattServerCallback.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015, The Android Open Source Project
+ * Copyright 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/doc/IBluetoothLowEnergy.txt b/service/doc/IBluetoothLowEnergy.txt
index b7218cb..ac7a6cb 100644
--- a/service/doc/IBluetoothLowEnergy.txt
+++ b/service/doc/IBluetoothLowEnergy.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015, The Android Open Source Project
+ * Copyright 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/doc/IBluetoothLowEnergyCallback.txt b/service/doc/IBluetoothLowEnergyCallback.txt
index 1ced0aa..7867379 100644
--- a/service/doc/IBluetoothLowEnergyCallback.txt
+++ b/service/doc/IBluetoothLowEnergyCallback.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015, The Android Open Source Project
+ * Copyright 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/service/example/heart_rate/constants.h b/service/example/heart_rate/constants.h
index 6159997..884d5ed 100644
--- a/service/example/heart_rate/constants.h
+++ b/service/example/heart_rate/constants.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -28,11 +28,12 @@
const uint16_t kHRSensorContactDetected = (3 << 1);
const uint8_t kHREnergyExpendedPresent = (1 << 3);
-const bluetooth::UUID kCCCDescriptorUUID("2902");
-const bluetooth::UUID kHRServiceUUID("180D");
-const bluetooth::UUID kHRMeasurementUUID("2A37");
-const bluetooth::UUID kBodySensorLocationUUID("2A38");
-const bluetooth::UUID kHRControlPointUUID("2A39");
+const bluetooth::Uuid kCCCDescriptorUuid = bluetooth::Uuid::FromString("2902");
+const bluetooth::Uuid kHRServiceUuid = bluetooth::Uuid::FromString("180D");
+const bluetooth::Uuid kHRMeasurementUuid = bluetooth::Uuid::FromString("2A37");
+const bluetooth::Uuid kBodySensorLocationUuid =
+ bluetooth::Uuid::FromString("2A38");
+const bluetooth::Uuid kHRControlPointUuid = bluetooth::Uuid::FromString("2A39");
const uint8_t kHRBodyLocationOther = 0;
const uint8_t kHRBodyLocationChest = 1;
diff --git a/service/example/heart_rate/heart_rate_server.cc b/service/example/heart_rate/heart_rate_server.cc
index a7bfe52..8b8e879 100644
--- a/service/example/heart_rate/heart_rate_server.cc
+++ b/service/example/heart_rate/heart_rate_server.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -55,8 +55,8 @@
bt_->GetName(&name_param);
std::string name(String8(name_param).string());
- /* Advertising data: 16-bit Service UUID: Heart Rate Service, Tx power*/
- std::vector<uint8_t> data{0x03, bluetooth::kEIRTypeComplete16BitUUIDs,
+ /* Advertising data: 16-bit Service Uuid: Heart Rate Service, Tx power*/
+ std::vector<uint8_t> data{0x03, bluetooth::kEIRTypeComplete16BitUuids,
0x0D, 0x18,
0x02, bluetooth::kEIRTypeTxPower,
0x00};
@@ -239,25 +239,25 @@
LOG(INFO) << "Heart Rate server registered - server_if: " << server_if_;
- bluetooth::Service hrService(
- 0, true, kHRServiceUUID,
- {{0,
- kHRMeasurementUUID,
- bluetooth::kCharacteristicPropertyNotify,
- 0,
- {{0, kCCCDescriptorUUID, (bluetooth::kAttributePermissionRead |
- bluetooth::kAttributePermissionWrite)}}},
- {0,
- kBodySensorLocationUUID,
- bluetooth::kCharacteristicPropertyRead,
- bluetooth::kAttributePermissionRead,
- {}},
- {0,
- kHRControlPointUUID,
- bluetooth::kCharacteristicPropertyWrite,
- bluetooth::kAttributePermissionWrite,
- {}}},
- {});
+ bluetooth::Service hrService(0, true, kHRServiceUuid,
+ {{0,
+ kHRMeasurementUuid,
+ bluetooth::kCharacteristicPropertyNotify,
+ 0,
+ {{0, kCCCDescriptorUuid,
+ (bluetooth::kAttributePermissionRead |
+ bluetooth::kAttributePermissionWrite)}}},
+ {0,
+ kBodySensorLocationUuid,
+ bluetooth::kCharacteristicPropertyRead,
+ bluetooth::kAttributePermissionRead,
+ {}},
+ {0,
+ kHRControlPointUuid,
+ bluetooth::kCharacteristicPropertyWrite,
+ bluetooth::kAttributePermissionWrite,
+ {}}},
+ {});
bool op_status = true;
diff --git a/service/example/heart_rate/heart_rate_server.h b/service/example/heart_rate/heart_rate_server.h
index 5f64d85..0246652 100644
--- a/service/example/heart_rate/heart_rate_server.h
+++ b/service/example/heart_rate/heart_rate_server.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/example/heart_rate/server_main.cc b/service/example/heart_rate/server_main.cc
index 76e7741..8ffded6 100644
--- a/service/example/heart_rate/server_main.cc
+++ b/service/example/heart_rate/server_main.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -153,7 +153,7 @@
// received in dedicated threads set up by the ProcessState::startThreadPool
// call above but we use this main loop for sending out heart rate
// notifications.
- main_loop.Run();
+ base::RunLoop().Run();
LOG(INFO) << "Exiting";
return EXIT_SUCCESS;
diff --git a/service/gatt_client.cc b/service/gatt_client.cc
index 80f5ebf..629b82a 100644
--- a/service/gatt_client.cc
+++ b/service/gatt_client.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
// GattClient implementation
// ========================================================
-GattClient::GattClient(const UUID& uuid, int client_id)
+GattClient::GattClient(const Uuid& uuid, int client_id)
: app_identifier_(uuid), client_id_(client_id) {}
GattClient::~GattClient() {
@@ -38,7 +38,7 @@
->unregister_client(client_id_);
}
-const UUID& GattClient::GetAppIdentifier() const { return app_identifier_; }
+const Uuid& GattClient::GetAppIdentifier() const { return app_identifier_; }
int GattClient::GetInstanceId() const { return client_id_; }
@@ -53,22 +53,21 @@
hal::BluetoothGattInterface::Get()->RemoveClientObserver(this);
}
-bool GattClientFactory::RegisterInstance(const UUID& uuid,
+bool GattClientFactory::RegisterInstance(const Uuid& uuid,
const RegisterCallback& callback) {
- VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+ VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
lock_guard<mutex> lock(pending_calls_lock_);
if (pending_calls_.find(uuid) != pending_calls_.end()) {
- LOG(ERROR) << "GATT client with given UUID already registered - "
- << "UUID: " << uuid.ToString();
+ LOG(ERROR) << "GATT client with given Uuid already registered - "
+ << "Uuid: " << uuid.ToString();
return false;
}
const btgatt_client_interface_t* hal_iface =
hal::BluetoothGattInterface::Get()->GetClientHALInterface();
- bt_uuid_t app_uuid = uuid.GetBlueDroid();
- if (hal_iface->register_client(app_uuid) != BT_STATUS_SUCCESS) return false;
+ if (hal_iface->register_client(uuid) != BT_STATUS_SUCCESS) return false;
pending_calls_[uuid] = callback;
@@ -77,8 +76,8 @@
void GattClientFactory::RegisterClientCallback(
hal::BluetoothGattInterface* /* gatt_iface */, int status, int client_id,
- const bt_uuid_t& app_uuid) {
- UUID uuid(app_uuid);
+ const Uuid& app_uuid) {
+ Uuid uuid(app_uuid);
auto iter = pending_calls_.find(uuid);
if (iter == pending_calls_.end()) {
diff --git a/service/gatt_client.h b/service/gatt_client.h
index fd83ffe..5a0322d 100644
--- a/service/gatt_client.h
+++ b/service/gatt_client.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -20,9 +20,9 @@
#include <unordered_map>
#include <base/macros.h>
+#include <bluetooth/uuid.h>
#include "service/bluetooth_instance.h"
-#include "service/common/bluetooth/uuid.h"
#include "service/hal/bluetooth_gatt_interface.h"
namespace bluetooth {
@@ -35,7 +35,7 @@
~GattClient() override;
// BluetoothClientInstace overrides:
- const UUID& GetAppIdentifier() const override;
+ const Uuid& GetAppIdentifier() const override;
int GetInstanceId() const override;
private:
@@ -43,10 +43,10 @@
// Constructor shouldn't be called directly as instances are meant to be
// obtained from the factory.
- GattClient(const UUID& uuid, int client_id);
+ GattClient(const Uuid& uuid, int client_id);
// See getters above for documentation.
- UUID app_identifier_;
+ Uuid app_identifier_;
int client_id_;
DISALLOW_COPY_AND_ASSIGN(GattClient);
@@ -64,18 +64,18 @@
~GattClientFactory() override;
// BluetoothInstanceFactory override:
- bool RegisterInstance(const UUID& uuid,
+ bool RegisterInstance(const Uuid& uuid,
const RegisterCallback& callback) override;
private:
// hal::BluetoothGattInterface::ClientObserver override:
void RegisterClientCallback(hal::BluetoothGattInterface* gatt_iface,
int status, int client_id,
- const bt_uuid_t& app_uuid) override;
+ const Uuid& app_uuid) override;
// Map of pending calls to register.
std::mutex pending_calls_lock_;
- std::unordered_map<UUID, RegisterCallback> pending_calls_;
+ std::unordered_map<Uuid, RegisterCallback> pending_calls_;
DISALLOW_COPY_AND_ASSIGN(GattClientFactory);
};
diff --git a/service/gatt_server.cc b/service/gatt_server.cc
index 63bacbb..52fd1ed 100644
--- a/service/gatt_server.cc
+++ b/service/gatt_server.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
#include "service/gatt_server.h"
+#include <base/logging.h>
+
#include "service/logging_helpers.h"
#include "stack/include/bt_types.h"
@@ -27,7 +29,7 @@
// GattServer implementation
// ========================================================
-GattServer::GattServer(const UUID& uuid, int server_id)
+GattServer::GattServer(const Uuid& uuid, int server_id)
: app_identifier_(uuid), server_id_(server_id), delegate_(nullptr) {}
GattServer::~GattServer() {
@@ -50,7 +52,7 @@
delegate_ = delegate;
}
-const UUID& GattServer::GetAppIdentifier() const { return app_identifier_; }
+const Uuid& GattServer::GetAppIdentifier() const { return app_identifier_; }
int GattServer::GetInstanceId() const { return server_id_; }
@@ -68,16 +70,16 @@
svc.push_back({.type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE
: BTGATT_DB_SECONDARY_SERVICE),
- .uuid = service.uuid().GetBlueDroid()});
+ .uuid = service.uuid()});
for (const auto& characteristic : service.characteristics()) {
svc.push_back({.type = BTGATT_DB_CHARACTERISTIC,
- .uuid = characteristic.uuid().GetBlueDroid(),
+ .uuid = characteristic.uuid(),
.properties = characteristic.properties(),
.permissions = characteristic.permissions()});
for (const auto& descriptor : characteristic.descriptors())
svc.push_back({.type = BTGATT_DB_DESCRIPTOR,
- .uuid = descriptor.uuid().GetBlueDroid(),
+ .uuid = descriptor.uuid(),
.permissions = descriptor.permissions()});
}
@@ -292,10 +294,10 @@
VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
<< " first handle: " << svc[0].attribute_handle
- << " service UUID: " << UUID(svc[0].uuid).ToString()
+ << " service Uuid: " << Uuid(svc[0].uuid).ToString()
<< " count: " << svc.size();
- Service service(svc[0].attribute_handle, true, UUID(svc[0].uuid), {}, {});
+ Service service(svc[0].attribute_handle, true, Uuid(svc[0].uuid), {}, {});
for (size_t i = 1; i < svc.size(); i++) {
const btgatt_db_element_t& curr = svc[i];
@@ -303,13 +305,13 @@
<< " handle: " << curr.attribute_handle;
if (curr.type == BTGATT_DB_CHARACTERISTIC) {
service.characteristics().push_back({curr.attribute_handle,
- UUID(curr.uuid),
+ Uuid(curr.uuid),
curr.properties,
curr.permissions,
{}});
} else if (curr.type == BTGATT_DB_DESCRIPTOR) {
service.characteristics().back().descriptors().push_back(
- {curr.attribute_handle, UUID(curr.uuid), curr.permissions});
+ {curr.attribute_handle, Uuid(curr.uuid), curr.permissions});
} else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
}
}
@@ -567,22 +569,21 @@
hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
}
-bool GattServerFactory::RegisterInstance(const UUID& uuid,
+bool GattServerFactory::RegisterInstance(const Uuid& uuid,
const RegisterCallback& callback) {
- VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+ VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
lock_guard<mutex> lock(pending_calls_lock_);
if (pending_calls_.find(uuid) != pending_calls_.end()) {
- LOG(ERROR) << "GATT-server client with given UUID already being registered "
- << " - UUID: " << uuid.ToString();
+ LOG(ERROR) << "GATT-server client with given Uuid already being registered "
+ << " - Uuid: " << uuid.ToString();
return false;
}
const btgatt_server_interface_t* hal_iface =
hal::BluetoothGattInterface::Get()->GetServerHALInterface();
- bt_uuid_t app_uuid = uuid.GetBlueDroid();
- if (hal_iface->register_server(app_uuid) != BT_STATUS_SUCCESS) return false;
+ if (hal_iface->register_server(uuid) != BT_STATUS_SUCCESS) return false;
pending_calls_[uuid] = callback;
@@ -591,10 +592,10 @@
void GattServerFactory::RegisterServerCallback(
hal::BluetoothGattInterface* gatt_iface, int status, int server_id,
- const bt_uuid_t& app_uuid) {
- UUID uuid(app_uuid);
+ const Uuid& app_uuid) {
+ Uuid uuid(app_uuid);
- VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+ VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
lock_guard<mutex> lock(pending_calls_lock_);
auto iter = pending_calls_.find(uuid);
diff --git a/service/gatt_server.h b/service/gatt_server.h
index e17e862..ee3970b 100644
--- a/service/gatt_server.h
+++ b/service/gatt_server.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -25,10 +25,10 @@
#include <vector>
#include <base/macros.h>
+#include <bluetooth/uuid.h>
#include "service/bluetooth_instance.h"
#include "service/common/bluetooth/service.h"
-#include "service/common/bluetooth/uuid.h"
#include "service/hal/bluetooth_gatt_interface.h"
namespace bluetooth {
@@ -116,7 +116,7 @@
void SetDelegate(Delegate* delegate);
// BluetoothClientInstace overrides:
- const UUID& GetAppIdentifier() const override;
+ const Uuid& GetAppIdentifier() const override;
int GetInstanceId() const override;
// Callback type used to report the status of an asynchronous GATT server
@@ -134,7 +134,7 @@
// we can add other services to this server instance? Do we need to clean up
// all the entries or does the upper-layer need to remove the service? Or are
// we in a stuck-state where the service declaration hasn't ended?
- bool AddService(const bluetooth::Service&, const ResultCallback& callback);
+ bool AddService(const Service&, const ResultCallback& callback);
// Sends a response for a pending notification. |request_id| and
// |device_address| should match those that were received through one of the
@@ -189,7 +189,7 @@
// Constructor shouldn't be called directly as instances are meant to be
// obtained from the factory.
- GattServer(const UUID& uuid, int server_id);
+ GattServer(const Uuid& uuid, int server_id);
// hal::BluetoothGattInterface::ServerObserver overrides:
void ConnectionCallback(hal::BluetoothGattInterface* gatt_iface, int conn_id,
@@ -237,7 +237,7 @@
int request_id);
// See getters for documentation.
- UUID app_identifier_;
+ Uuid app_identifier_;
int server_id_;
// Mutex that synchronizes access to the entries below.
@@ -277,18 +277,18 @@
~GattServerFactory() override;
// BluetoothInstanceFactory override:
- bool RegisterInstance(const UUID& uuid,
+ bool RegisterInstance(const Uuid& uuid,
const RegisterCallback& callback) override;
private:
// hal::BluetoothGattInterface::ServerObserver override:
void RegisterServerCallback(hal::BluetoothGattInterface* gatt_iface,
int status, int server_id,
- const bt_uuid_t& app_uuid) override;
+ const Uuid& app_uuid) override;
// Map of pending calls to register.
std::mutex pending_calls_lock_;
- std::unordered_map<UUID, RegisterCallback> pending_calls_;
+ std::unordered_map<Uuid, RegisterCallback> pending_calls_;
DISALLOW_COPY_AND_ASSIGN(GattServerFactory);
};
diff --git a/service/gatt_server_old.cc b/service/gatt_server_old.cc
index f6099ef..e97a6c5 100644
--- a/service/gatt_server_old.cc
+++ b/service/gatt_server_old.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -83,7 +83,7 @@
namespace gatt {
struct Characteristic {
- UUID uuid;
+ Uuid uuid;
int blob_section;
std::vector<uint8_t> blob;
@@ -97,11 +97,11 @@
ServerInternals();
~ServerInternals();
int Initialize();
- bt_status_t AddCharacteristic(const UUID& uuid, uint8_t properties,
+ bt_status_t AddCharacteristic(const Uuid& uuid, uint8_t properties,
uint16_t permissions);
- // This maps API attribute UUIDs to BlueDroid handles.
- std::map<UUID, int> uuid_to_attribute;
+ // This maps API attribute Uuids to BlueDroid handles.
+ std::map<Uuid, int> uuid_to_attribute;
// The attribute cache, indexed by BlueDroid handles.
std::unordered_map<int, Characteristic> characteristics;
@@ -111,7 +111,7 @@
ScanResults scan_results;
- UUID last_write;
+ Uuid last_write;
const btgatt_interface_t* gatt;
int server_if;
int client_if;
@@ -130,11 +130,12 @@
/** Callback invoked in response to register_server */
void RegisterServerCallback(int status, int server_if,
- const bt_uuid_t& app_uuid) {
+ const bluetooth::Uuid& app_uuid) {
LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d app_uuid:%p", __func__, status,
server_if, &app_uuid);
g_internal->server_if = server_if;
+
pending_svc_decl.push_back(
{.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = app_uuid});
}
@@ -157,7 +158,7 @@
if (el.type == BTGATT_DB_DESCRIPTOR) {
LOG_INFO(LOG_TAG, "%s: descr_handle:%d", __func__, el.attribute_handle);
} else if (el.type == BTGATT_DB_CHARACTERISTIC) {
- bluetooth::UUID id(el.uuid);
+ bluetooth::Uuid id(el.uuid);
uint16_t char_handle = el.attribute_handle;
LOG_INFO(LOG_TAG, "%s: char_handle:%d", __func__, char_handle);
@@ -192,11 +193,10 @@
pending_svc_decl.clear();
blob_index.clear();
- // The UUID provided here is unimportant, and is only used to satisfy
+ // The Uuid provided here is unimportant, and is only used to satisfy
// BlueDroid.
- // It must be different than any other registered UUID.
- bt_uuid_t client_id = service[0].uuid;
- ++client_id.uu[15];
+ // It must be different than any other registered Uuid.
+ bluetooth::Uuid client_id = bluetooth::Uuid::GetRandom();
bt_status_t btstat = g_internal->gatt->client->register_client(client_id);
if (btstat != BT_STATUS_SUCCESS) {
@@ -277,7 +277,7 @@
} else if (!is_prep) {
// This is a single frame characteristic write.
// Notify upwards because we're done now.
- const bluetooth::UUID::UUID128Bit& attr_uuid = ch.uuid.GetFullBigEndian();
+ const bluetooth::Uuid::UUID128Bit& attr_uuid = ch.uuid.To128BitBE();
ssize_t status;
OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd],
attr_uuid.data(), attr_uuid.size()));
@@ -317,9 +317,8 @@
if (!exec_write) return;
std::lock_guard<std::mutex> lock(g_internal->lock);
- // Communicate the attribute UUID as notification of a write update.
- const bluetooth::UUID::UUID128Bit uuid =
- g_internal->last_write.GetFullBigEndian();
+ // Communicate the attribute Uuid as notification of a write update.
+ const bluetooth::Uuid::UUID128Bit uuid = g_internal->last_write.To128BitBE();
ssize_t status;
OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd], uuid.data(),
uuid.size()));
@@ -347,9 +346,9 @@
}
void RegisterClientCallback(int status, int client_if,
- const bt_uuid_t& app_uuid) {
- LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d uuid[0]:%u", __func__, status,
- client_if, app_uuid.uu[0]);
+ const bluetooth::Uuid& app_uuid) {
+ LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d uuid[0]:%s", __func__, status,
+ client_if, app_uuid.ToString().c_str());
g_internal->client_if = client_if;
// Setup our advertisement. This has no callback.
@@ -500,13 +499,11 @@
return 0;
}
-bt_status_t ServerInternals::AddCharacteristic(const UUID& uuid,
+bt_status_t ServerInternals::AddCharacteristic(const Uuid& uuid,
uint8_t properties,
uint16_t permissions) {
- bt_uuid_t c_uuid = uuid.GetBlueDroid();
-
pending_svc_decl.push_back({.type = BTGATT_DB_CHARACTERISTIC,
- .uuid = c_uuid,
+ .uuid = uuid,
.properties = properties,
.permissions = permissions});
return BT_STATUS_SUCCESS;
@@ -532,7 +529,7 @@
Server::~Server() {}
-bool Server::Initialize(const UUID& service_id, int* gatt_pipe) {
+bool Server::Initialize(const Uuid& service_id, int* gatt_pipe) {
internal_.reset(new ServerInternals);
if (!internal_) {
LOG_ERROR(LOG_TAG, "Error creating internals");
@@ -547,9 +544,7 @@
return false;
}
- bt_uuid_t uuid = service_id.GetBlueDroid();
-
- bt_status_t btstat = internal_->gatt->server->register_server(uuid);
+ bt_status_t btstat = internal_->gatt->server->register_server(service_id);
if (btstat != BT_STATUS_SUCCESS) {
LOG_ERROR(LOG_TAG, "Failed to register server");
return false;
@@ -567,7 +562,7 @@
return true;
}
-bool Server::SetAdvertisement(const std::vector<UUID>& ids,
+bool Server::SetAdvertisement(const std::vector<Uuid>& ids,
const std::vector<uint8_t>& service_data,
const std::vector<uint8_t>& manufacturer_data,
bool transmit_name) {
@@ -575,8 +570,8 @@
// const auto& mutable_manufacturer_data = manufacturer_data;
// const auto& mutable_service_data = service_data;
- // for (const UUID &id : ids) {
- // const auto le_id = id.GetFullLittleEndian();
+ // for (const Uuid &id : ids) {
+ // const auto le_id = id.To128BitLE();
// id_data.insert(id_data.end(), le_id.begin(), le_id.end());
// }
@@ -593,7 +588,7 @@
return true;
}
-bool Server::SetScanResponse(const std::vector<UUID>& ids,
+bool Server::SetScanResponse(const std::vector<Uuid>& ids,
const std::vector<uint8_t>& service_data,
const std::vector<uint8_t>& manufacturer_data,
bool transmit_name) {
@@ -601,8 +596,8 @@
// const auto& mutable_manufacturer_data = manufacturer_data;
// const auto& mutable_service_data = service_data;
- // for (const UUID &id : ids) {
- // const auto le_id = id.GetFullLittleEndian();
+ // for (const Uuid &id : ids) {
+ // const auto le_id = id.To128BitLE();
// id_data.insert(id_data.end(), le_id.begin(), le_id.end());
// }
@@ -621,7 +616,7 @@
return true;
}
-bool Server::AddCharacteristic(const UUID& id, int properties,
+bool Server::AddCharacteristic(const Uuid& id, int properties,
int permissions) {
std::unique_lock<std::mutex> lock(internal_->lock);
bt_status_t btstat =
@@ -637,7 +632,7 @@
return true;
}
-bool Server::AddBlob(const UUID& id, const UUID& control_id, int properties,
+bool Server::AddBlob(const Uuid& id, const Uuid& control_id, int properties,
int permissions) {
std::unique_lock<std::mutex> lock(internal_->lock);
@@ -702,7 +697,7 @@
return true;
}
-bool Server::SetCharacteristicValue(const UUID& id,
+bool Server::SetCharacteristicValue(const Uuid& id,
const std::vector<uint8_t>& value) {
std::lock_guard<std::mutex> lock(internal_->lock);
const int attribute_id = internal_->uuid_to_attribute[id];
@@ -719,7 +714,7 @@
return true;
}
-bool Server::GetCharacteristicValue(const UUID& id,
+bool Server::GetCharacteristicValue(const Uuid& id,
std::vector<uint8_t>* value) {
std::lock_guard<std::mutex> lock(internal_->lock);
const int attribute_id = internal_->uuid_to_attribute[id];
diff --git a/service/gatt_server_old.h b/service/gatt_server_old.h
index a16bdfc..546f164 100644
--- a/service/gatt_server_old.h
+++ b/service/gatt_server_old.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
//
#pragma once
+#include <bluetooth/uuid.h>
#include <array>
#include <memory>
#include <unordered_map>
@@ -22,7 +23,6 @@
#include "hardware/bluetooth.h"
#include "hardware/bt_gatt.h"
-#include "service/common/bluetooth/uuid.h"
namespace bluetooth {
namespace gatt {
@@ -71,35 +71,35 @@
// Register GATT interface, initialize internal state,
// and open a pipe for characteristic write notification.
- bool Initialize(const UUID& service_id, int* gatt_pipe);
+ bool Initialize(const Uuid& service_id, int* gatt_pipe);
// Control the content of service advertisement.
- bool SetAdvertisement(const std::vector<UUID>& ids,
+ bool SetAdvertisement(const std::vector<Uuid>& ids,
const std::vector<uint8_t>& service_data,
const std::vector<uint8_t>& manufacturer_data,
bool transmit_name);
// Control the content of service scan response.
- bool SetScanResponse(const std::vector<UUID>& ids,
+ bool SetScanResponse(const std::vector<Uuid>& ids,
const std::vector<uint8_t>& service_data,
const std::vector<uint8_t>& manufacturer_data,
bool transmit_name);
// Add an ordinary characteristic for reading and/or writing.
- bool AddCharacteristic(const UUID& id, int properties, int permissions);
+ bool AddCharacteristic(const Uuid& id, int properties, int permissions);
// Add a special 'blob' characteristic with a corresponding control
// attribute to manipulate which part of the blob the attribute represents.
- bool AddBlob(const UUID& id, const UUID& control_id, int properties,
+ bool AddBlob(const Uuid& id, const Uuid& control_id, int properties,
int permissions);
// Put a new value into a characeteristic.
// It will be read from a client starting at the next 0-offset read.
- bool SetCharacteristicValue(const UUID& id,
+ bool SetCharacteristicValue(const Uuid& id,
const std::vector<uint8_t>& value);
// Get the current value of a characteristic.
- bool GetCharacteristicValue(const UUID& id, std::vector<uint8_t>* value);
+ bool GetCharacteristicValue(const Uuid& id, std::vector<uint8_t>* value);
// Start this service. Activate advertisements, allow connections.
// Characteristics should all be created before this.
diff --git a/service/hal/bluetooth_gatt_interface.cc b/service/hal/bluetooth_gatt_interface.cc
index f33fdbc..35b295b 100644
--- a/service/hal/bluetooth_gatt_interface.cc
+++ b/service/hal/bluetooth_gatt_interface.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -58,17 +58,20 @@
base::ObserverList<BluetoothGattInterface::ServerObserver>*
GetServerObservers();
-#define FOR_EACH_SCANNER_OBSERVER(func) \
- FOR_EACH_OBSERVER(BluetoothGattInterface::ScannerObserver, \
- *GetScannerObservers(), func)
+#define FOR_EACH_SCANNER_OBSERVER(func) \
+ for (auto& observer : *GetScannerObservers()) { \
+ observer.func; \
+ }
-#define FOR_EACH_CLIENT_OBSERVER(func) \
- FOR_EACH_OBSERVER(BluetoothGattInterface::ClientObserver, \
- *GetClientObservers(), func)
+#define FOR_EACH_CLIENT_OBSERVER(func) \
+ for (auto& observer : *GetClientObservers()) { \
+ observer.func; \
+ }
-#define FOR_EACH_SERVER_OBSERVER(func) \
- FOR_EACH_OBSERVER(BluetoothGattInterface::ServerObserver, \
- *GetServerObservers(), func)
+#define FOR_EACH_SERVER_OBSERVER(func) \
+ for (auto& observer : *GetServerObservers()) { \
+ observer.func; \
+ }
#define VERIFY_INTERFACE_OR_RETURN() \
do { \
@@ -79,7 +82,7 @@
} while (0)
void RegisterClientCallback(int status, int client_if,
- const bt_uuid_t& app_uuid) {
+ const bluetooth::Uuid& app_uuid) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if;
VERIFY_INTERFACE_OR_RETURN();
@@ -222,7 +225,7 @@
}
void RegisterServerCallback(int status, int server_if,
- const bt_uuid_t& app_uuid) {
+ const bluetooth::Uuid& app_uuid) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if;
VERIFY_INTERFACE_OR_RETURN();
@@ -567,7 +570,7 @@
void BluetoothGattInterface::ClientObserver::RegisterClientCallback(
BluetoothGattInterface* /* gatt_iface */, int /* status */,
- int /* client_if */, const bt_uuid_t& /* app_uuid */) {
+ int /* client_if */, const bluetooth::Uuid& /* app_uuid */) {
// Do nothing.
}
@@ -639,7 +642,7 @@
void BluetoothGattInterface::ServerObserver::RegisterServerCallback(
BluetoothGattInterface* /* gatt_iface */, int /* status */,
- int /* server_if */, const bt_uuid_t& /* app_uuid */) {
+ int /* server_if */, const bluetooth::Uuid& /* app_uuid */) {
// Do nothing.
}
diff --git a/service/hal/bluetooth_gatt_interface.h b/service/hal/bluetooth_gatt_interface.h
index 345ed88..08b0e9b 100644
--- a/service/hal/bluetooth_gatt_interface.h
+++ b/service/hal/bluetooth_gatt_interface.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@
virtual void RegisterClientCallback(BluetoothGattInterface* gatt_iface,
int status, int client_if,
- const bt_uuid_t& app_uuid);
+ const bluetooth::Uuid& app_uuid);
virtual void ConnectCallback(BluetoothGattInterface* gatt_iface,
int conn_id, int status, int client_if,
@@ -120,7 +120,7 @@
virtual void RegisterServerCallback(BluetoothGattInterface* gatt_iface,
int status, int server_if,
- const bt_uuid_t& app_uuid);
+ const bluetooth::Uuid& app_uuid);
virtual void ConnectionCallback(BluetoothGattInterface* gatt_iface,
int conn_id, int server_if, int connected,
diff --git a/service/hal/bluetooth_interface.cc b/service/hal/bluetooth_interface.cc
index 39816ef..9296966 100644
--- a/service/hal/bluetooth_interface.cc
+++ b/service/hal/bluetooth_interface.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -54,8 +54,10 @@
// defined below since it depends on BluetoothInterfaceImpl.
base::ObserverList<BluetoothInterface::Observer>* GetObservers();
-#define FOR_EACH_BLUETOOTH_OBSERVER(func) \
- FOR_EACH_OBSERVER(BluetoothInterface::Observer, *GetObservers(), func)
+#define FOR_EACH_BLUETOOTH_OBSERVER(func) \
+ for (auto& observer : *GetObservers()) { \
+ observer.func; \
+ }
#define VERIFY_INTERFACE_OR_RETURN() \
do { \
@@ -209,7 +211,7 @@
// BluetoothInterface implementation for production.
class BluetoothInterfaceImpl : public BluetoothInterface {
public:
- BluetoothInterfaceImpl() : hal_iface_(nullptr), hal_adapter_(nullptr) {}
+ BluetoothInterfaceImpl() : hal_iface_(nullptr) {}
~BluetoothInterfaceImpl() override {
if (hal_iface_) hal_iface_->cleanup();
@@ -230,31 +232,18 @@
bt_callbacks_t* GetHALCallbacks() const override { return &bt_callbacks; }
- const bluetooth_device_t* GetHALAdapter() const override {
- return hal_adapter_;
- }
-
// Initialize the interface. This loads the shared Bluetooth library and sets
// up the callbacks.
bool Initialize() {
// Load the Bluetooth shared library module.
- const hw_module_t* module;
- int status = hal_util_load_bt_library(&module);
- if (status) {
- LOG(ERROR) << "Failed to load Bluetooth library: " << status;
- return false;
- }
-
- // Open the Bluetooth adapter.
- hw_device_t* device;
- status = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+ const bt_interface_t* interface;
+ int status = hal_util_load_bt_library(&interface);
if (status) {
LOG(ERROR) << "Failed to open the Bluetooth module";
return false;
}
- hal_adapter_ = reinterpret_cast<bluetooth_device_t*>(device);
- hal_iface_ = hal_adapter_->get_bluetooth_interface();
+ hal_iface_ = interface;
// Initialize the Bluetooth interface. Set up the adapter (Bluetooth DM) API
// callbacks.
@@ -286,11 +275,6 @@
// to this since the actual data resides in the shared Bluetooth library.
const bt_interface_t* hal_iface_;
- // The HAL handle that represents the underlying Bluetooth adapter. We hold a
- // weak reference to this since the actual data resides in the shared
- // Bluetooth library.
- const bluetooth_device_t* hal_adapter_;
-
DISALLOW_COPY_AND_ASSIGN(BluetoothInterfaceImpl);
};
diff --git a/service/hal/bluetooth_interface.h b/service/hal/bluetooth_interface.h
index 49d621c..897835f 100644
--- a/service/hal/bluetooth_interface.h
+++ b/service/hal/bluetooth_interface.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -111,11 +111,6 @@
// Returns the HAL callbacks that have been initialized previously.
virtual bt_callbacks_t* GetHALCallbacks() const = 0;
- // The HAL module pointer that represents the underlying Bluetooth adapter.
- // This is implemented in and provided by the shared Bluetooth library, so
- // this isn't owned by us.
- virtual const bluetooth_device_t* GetHALAdapter() const = 0;
-
protected:
BluetoothInterface() = default;
virtual ~BluetoothInterface() = default;
diff --git a/service/hal/fake_bluetooth_gatt_interface.cc b/service/hal/fake_bluetooth_gatt_interface.cc
index 42ccb51..dbbbcaa 100644
--- a/service/hal/fake_bluetooth_gatt_interface.cc
+++ b/service/hal/fake_bluetooth_gatt_interface.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
std::shared_ptr<FakeBluetoothGattInterface::TestClientHandler> g_client_handler;
std::shared_ptr<FakeBluetoothGattInterface::TestServerHandler> g_server_handler;
-bt_status_t FakeRegisterClient(const bt_uuid_t& app_uuid) {
+bt_status_t FakeRegisterClient(const bluetooth::Uuid& app_uuid) {
if (g_client_handler) return g_client_handler->RegisterClient(app_uuid);
return BT_STATUS_FAIL;
@@ -57,7 +57,7 @@
return BT_STATUS_FAIL;
}
-bt_status_t FakeRegisterServer(const bt_uuid_t& app_uuid) {
+bt_status_t FakeRegisterServer(const bluetooth::Uuid& app_uuid) {
if (g_server_handler) return g_server_handler->RegisterServer(app_uuid);
return BT_STATUS_FAIL;
@@ -178,95 +178,104 @@
// given parameters.
void FakeBluetoothGattInterface::NotifyScanResultCallback(
const RawAddress& bda, int rssi, std::vector<uint8_t> adv_data) {
- FOR_EACH_OBSERVER(ScannerObserver, scanner_observers_,
- ScanResultCallback(this, bda, rssi, adv_data));
+ for (auto& observer : scanner_observers_) {
+ observer.ScanResultCallback(this, bda, rssi, adv_data);
+ }
}
void FakeBluetoothGattInterface::NotifyRegisterClientCallback(
- int status, int client_if, const bt_uuid_t& app_uuid) {
- FOR_EACH_OBSERVER(ClientObserver, client_observers_,
- RegisterClientCallback(this, status, client_if, app_uuid));
+ int status, int client_if, const bluetooth::Uuid& app_uuid) {
+ for (auto& observer : client_observers_) {
+ observer.RegisterClientCallback(this, status, client_if, app_uuid);
+ }
}
void FakeBluetoothGattInterface::NotifyConnectCallback(int conn_id, int status,
int client_if,
const RawAddress& bda) {
- FOR_EACH_OBSERVER(ClientObserver, client_observers_,
- ConnectCallback(this, conn_id, status, client_if, bda));
+ for (auto& observer : client_observers_) {
+ observer.ConnectCallback(this, conn_id, status, client_if, bda);
+ }
}
void FakeBluetoothGattInterface::NotifyDisconnectCallback(
int conn_id, int status, int client_if, const RawAddress& bda) {
- FOR_EACH_OBSERVER(ClientObserver, client_observers_,
- DisconnectCallback(this, conn_id, status, client_if, bda));
+ for (auto& observer : client_observers_) {
+ observer.DisconnectCallback(this, conn_id, status, client_if, bda);
+ }
}
void FakeBluetoothGattInterface::NotifyRegisterServerCallback(
- int status, int server_if, const bt_uuid_t& app_uuid) {
- FOR_EACH_OBSERVER(ServerObserver, server_observers_,
- RegisterServerCallback(this, status, server_if, app_uuid));
+ int status, int server_if, const Uuid& app_uuid) {
+ for (auto& observer : server_observers_) {
+ observer.RegisterServerCallback(this, status, server_if, app_uuid);
+ }
}
void FakeBluetoothGattInterface::NotifyServerConnectionCallback(
int conn_id, int server_if, int connected, const RawAddress& bda) {
- FOR_EACH_OBSERVER(
- ServerObserver, server_observers_,
- ConnectionCallback(this, conn_id, server_if, connected, bda));
+ for (auto& observer : server_observers_) {
+ observer.ConnectionCallback(this, conn_id, server_if, connected, bda);
+ }
}
void FakeBluetoothGattInterface::NotifyServiceAddedCallback(
int status, int server_if, std::vector<btgatt_db_element_t> service) {
- FOR_EACH_OBSERVER(ServerObserver, server_observers_,
- ServiceAddedCallback(this, status, server_if, service));
+ for (auto& observer : server_observers_) {
+ observer.ServiceAddedCallback(this, status, server_if, service);
+ }
}
void FakeBluetoothGattInterface::NotifyRequestReadCharacteristicCallback(
int conn_id, int trans_id, const RawAddress& bda, int attr_handle,
int offset, bool is_long) {
- FOR_EACH_OBSERVER(
- ServerObserver, server_observers_,
- RequestReadCharacteristicCallback(this, conn_id, trans_id, bda,
- attr_handle, offset, is_long));
+ for (auto& observer : server_observers_) {
+ observer.RequestReadCharacteristicCallback(this, conn_id, trans_id, bda,
+ attr_handle, offset, is_long);
+ }
}
void FakeBluetoothGattInterface::NotifyRequestReadDescriptorCallback(
int conn_id, int trans_id, const RawAddress& bda, int attr_handle,
int offset, bool is_long) {
- FOR_EACH_OBSERVER(
- ServerObserver, server_observers_,
- RequestReadDescriptorCallback(this, conn_id, trans_id, bda, attr_handle,
- offset, is_long));
+ for (auto& observer : server_observers_) {
+ observer.RequestReadDescriptorCallback(this, conn_id, trans_id, bda,
+ attr_handle, offset, is_long);
+ }
}
void FakeBluetoothGattInterface::NotifyRequestWriteCharacteristicCallback(
int conn_id, int trans_id, const RawAddress& bda, int attr_handle,
int offset, bool need_rsp, bool is_prep, std::vector<uint8_t> value) {
- FOR_EACH_OBSERVER(ServerObserver, server_observers_,
- RequestWriteCharacteristicCallback(
- this, conn_id, trans_id, bda, attr_handle, offset,
- need_rsp, is_prep, value));
+ for (auto& observer : server_observers_) {
+ observer.RequestWriteCharacteristicCallback(this, conn_id, trans_id, bda,
+ attr_handle, offset, need_rsp,
+ is_prep, value);
+ }
}
void FakeBluetoothGattInterface::NotifyRequestWriteDescriptorCallback(
int conn_id, int trans_id, const RawAddress& bda, int attr_handle,
int offset, bool need_rsp, bool is_prep, std::vector<uint8_t> value) {
- FOR_EACH_OBSERVER(
- ServerObserver, server_observers_,
- RequestWriteDescriptorCallback(this, conn_id, trans_id, bda, attr_handle,
- offset, need_rsp, is_prep, value));
+ for (auto& observer : server_observers_) {
+ observer.RequestWriteDescriptorCallback(this, conn_id, trans_id, bda,
+ attr_handle, offset, need_rsp,
+ is_prep, value);
+ }
}
void FakeBluetoothGattInterface::NotifyRequestExecWriteCallback(
int conn_id, int trans_id, const RawAddress& bda, int exec_write) {
- FOR_EACH_OBSERVER(
- ServerObserver, server_observers_,
- RequestExecWriteCallback(this, conn_id, trans_id, bda, exec_write));
+ for (auto& observer : server_observers_) {
+ observer.RequestExecWriteCallback(this, conn_id, trans_id, bda, exec_write);
+ }
}
void FakeBluetoothGattInterface::NotifyIndicationSentCallback(int conn_id,
int status) {
- FOR_EACH_OBSERVER(ServerObserver, server_observers_,
- IndicationSentCallback(this, conn_id, status));
+ for (auto& observer : server_observers_) {
+ observer.IndicationSentCallback(this, conn_id, status);
+ }
}
void FakeBluetoothGattInterface::AddScannerObserver(ScannerObserver* observer) {
diff --git a/service/hal/fake_bluetooth_gatt_interface.h b/service/hal/fake_bluetooth_gatt_interface.h
index 7ad3c89..a991a21 100644
--- a/service/hal/fake_bluetooth_gatt_interface.h
+++ b/service/hal/fake_bluetooth_gatt_interface.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
public:
virtual ~TestClientHandler() = default;
- virtual bt_status_t RegisterClient(const bt_uuid_t& app_uuid) = 0;
+ virtual bt_status_t RegisterClient(const bluetooth::Uuid& app_uuid) = 0;
virtual bt_status_t UnregisterClient(int client_if) = 0;
virtual bt_status_t Connect(int client_if, const RawAddress& bd_addr,
@@ -51,7 +51,7 @@
public:
virtual ~TestServerHandler() = default;
- virtual bt_status_t RegisterServer(const bt_uuid_t& app_uuid) = 0;
+ virtual bt_status_t RegisterServer(const bluetooth::Uuid& app_uuid) = 0;
virtual bt_status_t UnregisterServer(int server_if) = 0;
virtual bt_status_t AddService(
int server_if, std::vector<btgatt_db_element_t> service) = 0;
@@ -77,13 +77,13 @@
// given parameters.
void NotifyRegisterScannerCallback(int status, int client_if,
- const bt_uuid_t& app_uuid);
+ const bluetooth::Uuid& app_uuid);
void NotifyScanResultCallback(const RawAddress& bda, int rssi,
std::vector<uint8_t> adv_data);
// Client callbacks:
void NotifyRegisterClientCallback(int status, int client_if,
- const bt_uuid_t& app_uuid);
+ const bluetooth::Uuid& app_uuid);
void NotifyConnectCallback(int conn_id, int status, int client_if,
const RawAddress& bda);
void NotifyDisconnectCallback(int conn_id, int status, int client_if,
@@ -91,17 +91,17 @@
// Server callbacks:
void NotifyRegisterServerCallback(int status, int server_if,
- const bt_uuid_t& app_uuid);
+ const bluetooth::Uuid& app_uuid);
void NotifyServerConnectionCallback(int conn_id, int server_if, int connected,
const RawAddress& bda);
void NotifyServiceAddedCallback(int status, int server_if,
std::vector<btgatt_db_element_t> srvc);
void NotifyCharacteristicAddedCallback(int status, int server_if,
- const bt_uuid_t& uuid, int srvc_handle,
- int char_handle);
+ const bluetooth::Uuid& uuid,
+ int srvc_handle, int char_handle);
void NotifyDescriptorAddedCallback(int status, int server_if,
- const bt_uuid_t& uuid, int srvc_handle,
- int desc_handle);
+ const bluetooth::Uuid& uuid,
+ int srvc_handle, int desc_handle);
void NotifyServiceStartedCallback(int status, int server_if, int srvc_handle);
void NotifyRequestReadCharacteristicCallback(int conn_id, int trans_id,
const RawAddress& bda,
diff --git a/service/hal/fake_bluetooth_interface.cc b/service/hal/fake_bluetooth_interface.cc
index 45fdca0..eb550e7 100644
--- a/service/hal/fake_bluetooth_interface.cc
+++ b/service/hal/fake_bluetooth_interface.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -69,9 +69,11 @@
nullptr, /* set_os_callouts */
nullptr, /* read_energy_info */
nullptr, /* dump */
+ nullptr, /* dumpMetrics */
nullptr, /* config clear */
nullptr, /* interop_database_clear */
- nullptr /* interop_database_add */
+ nullptr, /* interop_database_add */
+ nullptr, /* get_avrcp_service */
};
} // namespace
@@ -87,14 +89,17 @@
set_property_succeed(false) {}
void FakeBluetoothInterface::NotifyAdapterStateChanged(bt_state_t state) {
- FOR_EACH_OBSERVER(Observer, observers_, AdapterStateChangedCallback(state));
+ for (auto& observer : observers_) {
+ observer.AdapterStateChangedCallback(state);
+ }
}
void FakeBluetoothInterface::NotifyAdapterPropertiesChanged(
int num_properties, bt_property_t* properties) {
- FOR_EACH_OBSERVER(
- Observer, observers_,
- AdapterPropertiesCallback(BT_STATUS_SUCCESS, num_properties, properties));
+ for (auto& observer : observers_) {
+ observer.AdapterPropertiesCallback(BT_STATUS_SUCCESS, num_properties,
+ properties);
+ }
}
void FakeBluetoothInterface::NotifyAdapterNamePropertyChanged(
@@ -134,8 +139,9 @@
void FakeBluetoothInterface::NotifyAclStateChangedCallback(
bt_status_t status, const RawAddress& remote_bdaddr, bt_acl_state_t state) {
- FOR_EACH_OBSERVER(Observer, observers_,
- AclStateChangedCallback(status, remote_bdaddr, state));
+ for (auto& observer : observers_) {
+ observer.AclStateChangedCallback(status, remote_bdaddr, state);
+ }
}
void FakeBluetoothInterface::AddObserver(Observer* observer) {
@@ -154,10 +160,5 @@
return nullptr;
}
-const bluetooth_device_t* FakeBluetoothInterface::GetHALAdapter() const {
- // TODO(armansito): Do something meaningful here to simulate test behavior.
- return nullptr;
-}
-
} // namespace hal
} // namespace bluetooth
diff --git a/service/hal/fake_bluetooth_interface.h b/service/hal/fake_bluetooth_interface.h
index b0fd657..b7dc832 100644
--- a/service/hal/fake_bluetooth_interface.h
+++ b/service/hal/fake_bluetooth_interface.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -63,7 +63,6 @@
void RemoveObserver(Observer* observer) override;
const bt_interface_t* GetHALInterface() const override;
bt_callbacks_t* GetHALCallbacks() const override;
- const bluetooth_device_t* GetHALAdapter() const override;
private:
base::ObserverList<Observer> observers_;
diff --git a/service/ipc/binder/bluetooth_binder_server.cc b/service/ipc/binder/bluetooth_binder_server.cc
index ea2d2c2..2d32cee 100644
--- a/service/ipc/binder/bluetooth_binder_server.cc
+++ b/service/ipc/binder/bluetooth_binder_server.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_binder_server.h b/service/ipc/binder/bluetooth_binder_server.h
index 55a3300..b03a815 100644
--- a/service/ipc/binder/bluetooth_binder_server.h
+++ b/service/ipc/binder/bluetooth_binder_server.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -30,9 +30,9 @@
#include <android/bluetooth/IBluetoothLeAdvertiser.h>
#include <android/bluetooth/IBluetoothLeScanner.h>
#include <android/bluetooth/IBluetoothLowEnergy.h>
+#include <bluetooth/uuid.h>
#include "service/adapter.h"
-#include "service/common/bluetooth/uuid.h"
#include "service/ipc/binder/remote_callback_list.h"
using android::String16;
diff --git a/service/ipc/binder/bluetooth_gatt_client_binder_server.cc b/service/ipc/binder/bluetooth_gatt_client_binder_server.cc
index 77a5f75..f72767f 100644
--- a/service/ipc/binder/bluetooth_gatt_client_binder_server.cc
+++ b/service/ipc/binder/bluetooth_gatt_client_binder_server.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_gatt_client_binder_server.h b/service/ipc/binder/bluetooth_gatt_client_binder_server.h
index 390b0ad..65b8b60 100644
--- a/service/ipc/binder/bluetooth_gatt_client_binder_server.h
+++ b/service/ipc/binder/bluetooth_gatt_client_binder_server.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_gatt_server_binder_server.cc b/service/ipc/binder/bluetooth_gatt_server_binder_server.cc
index f0f0717..8dffef7 100644
--- a/service/ipc/binder/bluetooth_gatt_server_binder_server.cc
+++ b/service/ipc/binder/bluetooth_gatt_server_binder_server.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_gatt_server_binder_server.h b/service/ipc/binder/bluetooth_gatt_server_binder_server.h
index 8a6dc02..925339a 100644
--- a/service/ipc/binder/bluetooth_gatt_server_binder_server.h
+++ b/service/ipc/binder/bluetooth_gatt_server_binder_server.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_le_advertiser_binder_server.cc b/service/ipc/binder/bluetooth_le_advertiser_binder_server.cc
index 170e94c..91f70d4 100644
--- a/service/ipc/binder/bluetooth_le_advertiser_binder_server.cc
+++ b/service/ipc/binder/bluetooth_le_advertiser_binder_server.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_le_advertiser_binder_server.h b/service/ipc/binder/bluetooth_le_advertiser_binder_server.h
index fc00db5..6602f5a 100644
--- a/service/ipc/binder/bluetooth_le_advertiser_binder_server.h
+++ b/service/ipc/binder/bluetooth_le_advertiser_binder_server.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_le_scanner_binder_server.cc b/service/ipc/binder/bluetooth_le_scanner_binder_server.cc
index 0c20a46..b6072be 100644
--- a/service/ipc/binder/bluetooth_le_scanner_binder_server.cc
+++ b/service/ipc/binder/bluetooth_le_scanner_binder_server.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_le_scanner_binder_server.h b/service/ipc/binder/bluetooth_le_scanner_binder_server.h
index ef9a900..0cc3ae9 100644
--- a/service/ipc/binder/bluetooth_le_scanner_binder_server.h
+++ b/service/ipc/binder/bluetooth_le_scanner_binder_server.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_low_energy_binder_server.cc b/service/ipc/binder/bluetooth_low_energy_binder_server.cc
index 9b8a863..2520d6d 100644
--- a/service/ipc/binder/bluetooth_low_energy_binder_server.cc
+++ b/service/ipc/binder/bluetooth_low_energy_binder_server.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/bluetooth_low_energy_binder_server.h b/service/ipc/binder/bluetooth_low_energy_binder_server.h
index d393c7d..4508b34 100644
--- a/service/ipc/binder/bluetooth_low_energy_binder_server.h
+++ b/service/ipc/binder/bluetooth_low_energy_binder_server.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/interface_with_instances_base.cc b/service/ipc/binder/interface_with_instances_base.cc
index 18b1eae..ba24657 100644
--- a/service/ipc/binder/interface_with_instances_base.cc
+++ b/service/ipc/binder/interface_with_instances_base.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@
// Store the callback in the pending list. It will get removed later when the
// stack notifies us asynchronously.
- bluetooth::UUID app_uuid = bluetooth::UUID::GetRandom();
+ bluetooth::Uuid app_uuid = bluetooth::Uuid::GetRandom();
if (!pending_callbacks_.Register(app_uuid, callback)) {
LOG(ERROR) << "Failed to store |callback| to map";
return false;
@@ -45,21 +45,22 @@
// (sp) we are using a wp here rather than std::weak_ptr.
android::wp<InterfaceWithInstancesBase> weak_ptr_to_this(this);
- bluetooth::BluetoothInstanceFactory::RegisterCallback cb = [weak_ptr_to_this](
- bluetooth::BLEStatus status, const bluetooth::UUID& in_uuid,
- std::unique_ptr<bluetooth::BluetoothInstance> instance) {
- // If the weak pointer was invalidated then there is nothing we can do.
- android::sp<InterfaceWithInstancesBase> strong_ptr_to_this =
- weak_ptr_to_this.promote();
- if (!strong_ptr_to_this.get()) {
- VLOG(2) << "InterfaceWithInstancesBase was deleted while instance was"
- << " being registered";
- return;
- }
+ bluetooth::BluetoothInstanceFactory::RegisterCallback cb =
+ [weak_ptr_to_this](
+ bluetooth::BLEStatus status, const bluetooth::Uuid& in_uuid,
+ std::unique_ptr<bluetooth::BluetoothInstance> instance) {
+ // If the weak pointer was invalidated then there is nothing we can do.
+ android::sp<InterfaceWithInstancesBase> strong_ptr_to_this =
+ weak_ptr_to_this.promote();
+ if (!strong_ptr_to_this.get()) {
+ VLOG(2) << "InterfaceWithInstancesBase was deleted while instance was"
+ << " being registered";
+ return;
+ }
- strong_ptr_to_this->OnRegisterInstance(status, in_uuid,
- std::move(instance));
- };
+ strong_ptr_to_this->OnRegisterInstance(status, in_uuid,
+ std::move(instance));
+ };
if (factory->RegisterInstance(app_uuid, cb)) return true;
@@ -99,7 +100,7 @@
}
void InterfaceWithInstancesBase::OnRegisterInstance(
- bluetooth::BLEStatus status, const bluetooth::UUID& uuid,
+ bluetooth::BLEStatus status, const bluetooth::Uuid& uuid,
std::unique_ptr<bluetooth::BluetoothInstance> instance) {
VLOG(2) << __func__ << " - status: " << status;
diff --git a/service/ipc/binder/interface_with_instances_base.h b/service/ipc/binder/interface_with_instances_base.h
index f0aa762..90224b6 100644
--- a/service/ipc/binder/interface_with_instances_base.h
+++ b/service/ipc/binder/interface_with_instances_base.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -20,9 +20,9 @@
#include <unordered_map>
#include <base/macros.h>
+#include <bluetooth/uuid.h>
#include "service/bluetooth_instance.h"
-#include "service/common/bluetooth/uuid.h"
#include "service/ipc/binder/remote_callback_map.h"
namespace ipc {
@@ -44,7 +44,7 @@
protected:
// The initial entry point for registering a instance. Invoke this from the
- // registration API to add a instance/UUID pair to the pending list and set up
+ // registration API to add a instance/Uuid pair to the pending list and set up
// the generic asynchronous callback handler and initiate the process with the
// given |factory| instance. Returns false, if there were any errors that
// could be synchronously reported.
@@ -74,7 +74,7 @@
private:
// Base implementation of the register callback.
void OnRegisterInstance(
- bluetooth::BLEStatus status, const bluetooth::UUID& uuid,
+ bluetooth::BLEStatus status, const bluetooth::Uuid& uuid,
std::unique_ptr<bluetooth::BluetoothInstance> instance);
// Called when the callback registration has completed. |instance| is owned by
@@ -89,7 +89,7 @@
// Instances that are pending registration. Once their registration is
// complete, the entry will be removed from this map.
- RemoteCallbackMap<bluetooth::UUID, android::IInterface> pending_callbacks_;
+ RemoteCallbackMap<bluetooth::Uuid, android::IInterface> pending_callbacks_;
// We keep two maps here: one from instance_id IDs to callback Binders and one
// from instance_id IDs to the BluetoothInstance structures themselves.
diff --git a/service/ipc/binder/ipc_handler_binder.cc b/service/ipc/binder/ipc_handler_binder.cc
index 5b92120..becd6e8 100644
--- a/service/ipc/binder/ipc_handler_binder.cc
+++ b/service/ipc/binder/ipc_handler_binder.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/ipc_handler_binder.h b/service/ipc/binder/ipc_handler_binder.h
index 060548b..2edd323 100644
--- a/service/ipc/binder/ipc_handler_binder.h
+++ b/service/ipc/binder/ipc_handler_binder.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/remote_callback_list.h b/service/ipc/binder/remote_callback_list.h
index e62b7ef..8c1f6ac 100644
--- a/service/ipc/binder/remote_callback_list.h
+++ b/service/ipc/binder/remote_callback_list.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/binder/remote_callback_map.h b/service/ipc/binder/remote_callback_map.h
index b3422ac..b07de44 100644
--- a/service/ipc/binder/remote_callback_map.h
+++ b/service/ipc/binder/remote_callback_map.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/dbus/bluetooth_adapter.cc b/service/ipc/dbus/bluetooth_adapter.cc
index 8619a35..fd6688a 100644
--- a/service/ipc/dbus/bluetooth_adapter.cc
+++ b/service/ipc/dbus/bluetooth_adapter.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/dbus/bluetooth_adapter.h b/service/ipc/dbus/bluetooth_adapter.h
index 1d8dd8f..484ac11 100644
--- a/service/ipc/dbus/bluetooth_adapter.h
+++ b/service/ipc/dbus/bluetooth_adapter.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/dbus/ipc_handler_dbus.cc b/service/ipc/dbus/ipc_handler_dbus.cc
index ff7ff43..c8922d3 100644
--- a/service/ipc/dbus/ipc_handler_dbus.cc
+++ b/service/ipc/dbus/ipc_handler_dbus.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/dbus/ipc_handler_dbus.h b/service/ipc/dbus/ipc_handler_dbus.h
index 03f7720..2a83369 100644
--- a/service/ipc/dbus/ipc_handler_dbus.h
+++ b/service/ipc/dbus/ipc_handler_dbus.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/ipc_handler.cc b/service/ipc/ipc_handler.cc
index 66d9c03..11c1a50 100644
--- a/service/ipc/ipc_handler.cc
+++ b/service/ipc/ipc_handler.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/ipc_handler.h b/service/ipc/ipc_handler.h
index b1029ca..9b7994c 100644
--- a/service/ipc/ipc_handler.h
+++ b/service/ipc/ipc_handler.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/ipc_handler_linux.cc b/service/ipc/ipc_handler_linux.cc
index bcd21aa..7fe724e 100644
--- a/service/ipc/ipc_handler_linux.cc
+++ b/service/ipc/ipc_handler_linux.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/ipc_handler_linux.h b/service/ipc/ipc_handler_linux.h
index b00eb27..21c71d2 100644
--- a/service/ipc/ipc_handler_linux.h
+++ b/service/ipc/ipc_handler_linux.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/ipc_manager.cc b/service/ipc/ipc_manager.cc
index 71dc6c7..04870b4 100644
--- a/service/ipc/ipc_manager.cc
+++ b/service/ipc/ipc_manager.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/ipc_manager.h b/service/ipc/ipc_manager.h
index bf0967c..ee960ba 100644
--- a/service/ipc/ipc_manager.h
+++ b/service/ipc/ipc_manager.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/ipc/linux_ipc_host.cc b/service/ipc/linux_ipc_host.cc
index 7b328cf..705748f 100644
--- a/service/ipc/linux_ipc_host.cc
+++ b/service/ipc/linux_ipc_host.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@
#include "service/adapter.h"
using bluetooth::Adapter;
-using bluetooth::UUID;
+using bluetooth::Uuid;
using namespace bluetooth::gatt;
@@ -108,8 +108,8 @@
gatt_servers_[service_uuid] = std::unique_ptr<Server>(new Server);
int gattfd;
- bool status =
- gatt_servers_[service_uuid]->Initialize(UUID(service_uuid), &gattfd);
+ bool status = gatt_servers_[service_uuid]->Initialize(
+ Uuid::FromString(service_uuid), &gattfd);
if (!status) {
LOG_ERROR(LOG_TAG, "Failed to initialize bluetooth");
return false;
@@ -155,11 +155,12 @@
if (control_uuid.empty()) {
gatt_servers_[service_uuid]->AddCharacteristic(
- UUID(characteristic_uuid), properties_mask, permissions_mask);
+ Uuid::FromString(characteristic_uuid), properties_mask,
+ permissions_mask);
} else {
- gatt_servers_[service_uuid]->AddBlob(UUID(characteristic_uuid),
- UUID(control_uuid), properties_mask,
- permissions_mask);
+ gatt_servers_[service_uuid]->AddBlob(Uuid::FromString(characteristic_uuid),
+ Uuid::FromString(control_uuid),
+ properties_mask, permissions_mask);
}
return true;
}
@@ -170,8 +171,8 @@
std::string decoded_data;
base::Base64Decode(value, &decoded_data);
std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
- gatt_servers_[service_uuid]->SetCharacteristicValue(UUID(characteristic_uuid),
- blob_data);
+ gatt_servers_[service_uuid]->SetCharacteristicValue(
+ Uuid::FromString(characteristic_uuid), blob_data);
return true;
}
@@ -187,10 +188,10 @@
std::vector<std::string> advertise_uuid_tokens = base::SplitString(
advertise_uuids, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- // string -> vector<UUID>
- std::vector<UUID> ids;
+ // string -> vector<Uuid>
+ std::vector<Uuid> ids;
for (const auto& uuid_token : advertise_uuid_tokens)
- ids.emplace_back(uuid_token);
+ ids.emplace_back(Uuid::FromString(uuid_token));
std::string decoded_data;
base::Base64Decode(advertise_data, &decoded_data);
@@ -215,10 +216,10 @@
std::vector<std::string> scan_response_uuid_tokens = base::SplitString(
scan_response_uuids, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- // string -> vector<UUID>
- std::vector<UUID> ids;
+ // string -> vector<Uuid>
+ std::vector<Uuid> ids;
for (const auto& uuid_token : scan_response_uuid_tokens)
- ids.emplace_back(uuid_token);
+ ids.emplace_back(Uuid::FromString(uuid_token));
std::string decoded_data;
base::Base64Decode(scan_response_data, &decoded_data);
@@ -304,7 +305,7 @@
}
bool LinuxIPCHost::OnGattWrite() {
- UUID::UUID128Bit id;
+ Uuid::UUID128Bit id;
ssize_t r;
OSI_NO_INTR(r = read(pfds_[kFdGatt].fd, id.data(), id.size()));
@@ -316,7 +317,7 @@
std::vector<uint8_t> value;
// TODO(icoolidge): Generalize this for multiple clients.
auto server = gatt_servers_.begin();
- server->second->GetCharacteristicValue(UUID(id), &value);
+ server->second->GetCharacteristicValue(Uuid::From128BitBE(id), &value);
const std::string value_string(value.begin(), value.end());
std::string encoded_value;
base::Base64Encode(value_string, &encoded_value);
diff --git a/service/ipc/linux_ipc_host.h b/service/ipc/linux_ipc_host.h
index a51a966..012f70e 100644
--- a/service/ipc/linux_ipc_host.h
+++ b/service/ipc/linux_ipc_host.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,11 +17,11 @@
#include <poll.h>
+#include <bluetooth/uuid.h>
#include <memory>
#include <string>
#include <unordered_map>
-#include "service/common/bluetooth/uuid.h"
#include "service/gatt_server_old.h"
namespace bluetooth {
diff --git a/service/logging_helpers.cc b/service/logging_helpers.cc
index 39706ec..70f8720 100644
--- a/service/logging_helpers.cc
+++ b/service/logging_helpers.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/logging_helpers.h b/service/logging_helpers.h
index d3c58d1..aa03e63 100644
--- a/service/logging_helpers.h
+++ b/service/logging_helpers.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/low_energy_advertiser.cc b/service/low_energy_advertiser.cc
index 3df55db..4f4bff9 100644
--- a/service/low_energy_advertiser.cc
+++ b/service/low_energy_advertiser.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -120,7 +120,7 @@
// LowEnergyAdvertiser implementation
// ========================================================
-LowEnergyAdvertiser::LowEnergyAdvertiser(const UUID& uuid, int advertiser_id)
+LowEnergyAdvertiser::LowEnergyAdvertiser(const Uuid& uuid, int advertiser_id)
: app_identifier_(uuid),
advertiser_id_(advertiser_id),
adv_started_(false),
@@ -226,7 +226,7 @@
return IsAdvertisingStarted() && adv_stop_callback_;
}
-const UUID& LowEnergyAdvertiser::GetAppIdentifier() const {
+const Uuid& LowEnergyAdvertiser::GetAppIdentifier() const {
return app_identifier_;
}
@@ -294,13 +294,13 @@
LowEnergyAdvertiserFactory::~LowEnergyAdvertiserFactory() {}
bool LowEnergyAdvertiserFactory::RegisterInstance(
- const UUID& app_uuid, const RegisterCallback& callback) {
+ const Uuid& app_uuid, const RegisterCallback& callback) {
VLOG(1) << __func__;
lock_guard<mutex> lock(pending_calls_lock_);
if (pending_calls_.find(app_uuid) != pending_calls_.end()) {
- LOG(ERROR) << "Low-Energy advertiser with given UUID already registered - "
- << "UUID: " << app_uuid.ToString();
+ LOG(ERROR) << "Low-Energy advertiser with given Uuid already registered - "
+ << "Uuid: " << app_uuid.ToString();
return false;
}
@@ -319,7 +319,7 @@
}
void LowEnergyAdvertiserFactory::RegisterAdvertiserCallback(
- const RegisterCallback& callback, const UUID& app_uuid,
+ const RegisterCallback& callback, const Uuid& app_uuid,
uint8_t advertiser_id, uint8_t status) {
VLOG(1) << __func__;
lock_guard<mutex> lock(pending_calls_lock_);
diff --git a/service/low_energy_advertiser.h b/service/low_energy_advertiser.h
index a014ae1..ec0dd74 100644
--- a/service/low_energy_advertiser.h
+++ b/service/low_energy_advertiser.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
#include <mutex>
#include <base/macros.h>
+#include <bluetooth/uuid.h>
#include "service/bluetooth_instance.h"
#include "service/common/bluetooth/advertise_data.h"
@@ -30,7 +31,6 @@
#include "service/common/bluetooth/scan_filter.h"
#include "service/common/bluetooth/scan_result.h"
#include "service/common/bluetooth/scan_settings.h"
-#include "service/common/bluetooth/uuid.h"
#include "service/hal/bluetooth_gatt_interface.h"
namespace bluetooth {
@@ -75,7 +75,7 @@
}
// BluetoothClientInstace overrides:
- const UUID& GetAppIdentifier() const override;
+ const Uuid& GetAppIdentifier() const override;
int GetInstanceId() const override;
private:
@@ -83,7 +83,7 @@
// Constructor shouldn't be called directly as instances are meant to be
// obtained from the factory.
- LowEnergyAdvertiser(const UUID& uuid, int advertiser_id);
+ LowEnergyAdvertiser(const Uuid& uuid, int advertiser_id);
// BluetoothGattInterface::AdvertiserObserver overrides:
void SetDataCallback(uint8_t advertiser_id, uint8_t status);
@@ -95,7 +95,7 @@
void InvokeAndClearStopCallback(BLEStatus status);
// See getters above for documentation.
- UUID app_identifier_;
+ Uuid app_identifier_;
int advertiser_id_;
// Protects advertising-related members below.
@@ -124,7 +124,7 @@
~LowEnergyAdvertiserFactory() override;
// BluetoothInstanceFactory override:
- bool RegisterInstance(const UUID& app_uuid,
+ bool RegisterInstance(const Uuid& app_uuid,
const RegisterCallback& callback) override;
private:
@@ -132,12 +132,12 @@
// BluetoothGattInterface::AdvertiserObserver overrides:
void RegisterAdvertiserCallback(const RegisterCallback& callback,
- const UUID& app_uuid, uint8_t advertiser_id,
+ const Uuid& app_uuid, uint8_t advertiser_id,
uint8_t status);
// Map of pending calls to register.
std::mutex pending_calls_lock_;
- std::unordered_set<UUID> pending_calls_;
+ std::unordered_set<Uuid> pending_calls_;
DISALLOW_COPY_AND_ASSIGN(LowEnergyAdvertiserFactory);
};
diff --git a/service/low_energy_client.cc b/service/low_energy_client.cc
index 97f3ca6..cc127c3 100644
--- a/service/low_energy_client.cc
+++ b/service/low_energy_client.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
// LowEnergyClient implementation
// ========================================================
-LowEnergyClient::LowEnergyClient(Adapter& adapter, const UUID& uuid,
+LowEnergyClient::LowEnergyClient(Adapter& adapter, const Uuid& uuid,
int client_id)
: adapter_(adapter),
app_identifier_(uuid),
@@ -126,7 +126,7 @@
delegate_ = delegate;
}
-const UUID& LowEnergyClient::GetAppIdentifier() const {
+const Uuid& LowEnergyClient::GetAppIdentifier() const {
return app_identifier_;
}
@@ -205,21 +205,20 @@
}
bool LowEnergyClientFactory::RegisterInstance(
- const UUID& uuid, const RegisterCallback& callback) {
- VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+ const Uuid& uuid, const RegisterCallback& callback) {
+ VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
lock_guard<mutex> lock(pending_calls_lock_);
if (pending_calls_.find(uuid) != pending_calls_.end()) {
- LOG(ERROR) << "Low-Energy client with given UUID already registered - "
- << "UUID: " << uuid.ToString();
+ LOG(ERROR) << "Low-Energy client with given Uuid already registered - "
+ << "Uuid: " << uuid.ToString();
return false;
}
const btgatt_client_interface_t* hal_iface =
hal::BluetoothGattInterface::Get()->GetClientHALInterface();
- bt_uuid_t app_uuid = uuid.GetBlueDroid();
- if (hal_iface->register_client(app_uuid) != BT_STATUS_SUCCESS) return false;
+ if (hal_iface->register_client(uuid) != BT_STATUS_SUCCESS) return false;
pending_calls_[uuid] = callback;
@@ -228,10 +227,10 @@
void LowEnergyClientFactory::RegisterClientCallback(
hal::BluetoothGattInterface* gatt_iface, int status, int client_id,
- const bt_uuid_t& app_uuid) {
- UUID uuid(app_uuid);
+ const bluetooth::Uuid& app_uuid) {
+ Uuid uuid(app_uuid);
- VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+ VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
lock_guard<mutex> lock(pending_calls_lock_);
auto iter = pending_calls_.find(uuid);
diff --git a/service/low_energy_client.h b/service/low_energy_client.h
index 16ef4a5..4a7939b 100644
--- a/service/low_energy_client.h
+++ b/service/low_energy_client.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -22,13 +22,13 @@
#include <mutex>
#include <base/macros.h>
+#include <bluetooth/uuid.h>
#include "service/bluetooth_instance.h"
#include "service/common/bluetooth/low_energy_constants.h"
#include "service/common/bluetooth/scan_filter.h"
#include "service/common/bluetooth/scan_result.h"
#include "service/common/bluetooth/scan_settings.h"
-#include "service/common/bluetooth/uuid.h"
#include "service/hal/bluetooth_gatt_interface.h"
namespace bluetooth {
@@ -91,7 +91,7 @@
bool SetMtu(const std::string& address, int mtu);
// BluetoothClientInstace overrides:
- const UUID& GetAppIdentifier() const override;
+ const Uuid& GetAppIdentifier() const override;
int GetInstanceId() const override;
private:
@@ -99,7 +99,7 @@
// Constructor shouldn't be called directly as instances are meant to be
// obtained from the factory.
- LowEnergyClient(Adapter& adapter, const UUID& uuid, int client_id);
+ LowEnergyClient(Adapter& adapter, const Uuid& uuid, int client_id);
// BluetoothGattInterface::ClientObserver overrides:
void ConnectCallback(hal::BluetoothGattInterface* gatt_iface, int conn_id,
@@ -119,7 +119,7 @@
Adapter& adapter_;
// See getters above for documentation.
- UUID app_identifier_;
+ Uuid app_identifier_;
int client_id_;
// Raw handle to the Delegate, which must outlive this LowEnergyClient
@@ -151,7 +151,7 @@
~LowEnergyClientFactory() override;
// BluetoothInstanceFactory override:
- bool RegisterInstance(const UUID& uuid,
+ bool RegisterInstance(const Uuid& uuid,
const RegisterCallback& callback) override;
private:
@@ -160,11 +160,11 @@
// BluetoothGattInterface::ClientObserver overrides:
void RegisterClientCallback(hal::BluetoothGattInterface* gatt_iface,
int status, int client_id,
- const bt_uuid_t& app_uuid) override;
+ const bluetooth::Uuid& app_uuid) override;
// Map of pending calls to register.
std::mutex pending_calls_lock_;
- std::map<UUID, RegisterCallback> pending_calls_;
+ std::map<Uuid, RegisterCallback> pending_calls_;
// Raw pointer to the Adapter that owns this factory.
Adapter& adapter_;
diff --git a/service/low_energy_scanner.cc b/service/low_energy_scanner.cc
index 093a554..1527563 100644
--- a/service/low_energy_scanner.cc
+++ b/service/low_energy_scanner.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@
// LowEnergyScanner implementation
// ========================================================
-LowEnergyScanner::LowEnergyScanner(Adapter& adapter, const UUID& uuid,
+LowEnergyScanner::LowEnergyScanner(Adapter& adapter, const Uuid& uuid,
int scanner_id)
: adapter_(adapter),
app_identifier_(uuid),
@@ -131,7 +131,7 @@
return true;
}
-const UUID& LowEnergyScanner::GetAppIdentifier() const {
+const Uuid& LowEnergyScanner::GetAppIdentifier() const {
return app_identifier_;
}
@@ -170,13 +170,13 @@
}
bool LowEnergyScannerFactory::RegisterInstance(
- const UUID& uuid, const RegisterCallback& callback) {
- VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+ const Uuid& uuid, const RegisterCallback& callback) {
+ VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
lock_guard<mutex> lock(pending_calls_lock_);
if (pending_calls_.find(uuid) != pending_calls_.end()) {
- LOG(ERROR) << "Low-Energy scanner with given UUID already registered - "
- << "UUID: " << uuid.ToString();
+ LOG(ERROR) << "Low-Energy scanner with given Uuid already registered - "
+ << "Uuid: " << uuid.ToString();
return false;
}
@@ -193,11 +193,11 @@
}
void LowEnergyScannerFactory::RegisterScannerCallback(
- const RegisterCallback& callback, const UUID& app_uuid, uint8_t scanner_id,
+ const RegisterCallback& callback, const Uuid& app_uuid, uint8_t scanner_id,
uint8_t status) {
- UUID uuid(app_uuid);
+ Uuid uuid(app_uuid);
- VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+ VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
lock_guard<mutex> lock(pending_calls_lock_);
auto iter = pending_calls_.find(uuid);
diff --git a/service/low_energy_scanner.h b/service/low_energy_scanner.h
index 279ea7b..b27b72e 100644
--- a/service/low_energy_scanner.h
+++ b/service/low_energy_scanner.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
#include <mutex>
#include <base/macros.h>
+#include <bluetooth/uuid.h>
#include "service/bluetooth_instance.h"
#include "service/common/bluetooth/advertise_data.h"
@@ -30,7 +31,6 @@
#include "service/common/bluetooth/scan_filter.h"
#include "service/common/bluetooth/scan_result.h"
#include "service/common/bluetooth/scan_settings.h"
-#include "service/common/bluetooth/uuid.h"
#include "service/hal/bluetooth_gatt_interface.h"
namespace bluetooth {
@@ -81,7 +81,7 @@
const ScanSettings& scan_settings() const { return scan_settings_; }
// BluetoothInstace overrides:
- const UUID& GetAppIdentifier() const override;
+ const Uuid& GetAppIdentifier() const override;
int GetInstanceId() const override;
void ScanResultCallback(hal::BluetoothGattInterface* gatt_iface,
@@ -93,7 +93,7 @@
// Constructor shouldn't be called directly as instances are meant to be
// obtained from the factory.
- LowEnergyScanner(Adapter& adapter, const UUID& uuid, int scanner_id);
+ LowEnergyScanner(Adapter& adapter, const Uuid& uuid, int scanner_id);
// Calls and clears the pending callbacks.
void InvokeAndClearStartCallback(BLEStatus status);
@@ -103,7 +103,7 @@
Adapter& adapter_;
// See getters above for documentation.
- UUID app_identifier_;
+ Uuid app_identifier_;
int scanner_id_;
// Protects device scan related members below.
@@ -137,7 +137,7 @@
~LowEnergyScannerFactory() override;
// BluetoothInstanceFactory override:
- bool RegisterInstance(const UUID& app_uuid,
+ bool RegisterInstance(const Uuid& app_uuid,
const RegisterCallback& callback) override;
private:
@@ -145,12 +145,12 @@
// BluetoothGattInterface::ScannerObserver overrides:
void RegisterScannerCallback(const RegisterCallback& callback,
- const UUID& app_uuid, uint8_t scanner_id,
+ const Uuid& app_uuid, uint8_t scanner_id,
uint8_t status);
// Map of pending calls to register.
std::mutex pending_calls_lock_;
- std::unordered_set<UUID> pending_calls_;
+ std::unordered_set<Uuid> pending_calls_;
// Raw pointer to the Adapter that owns this factory.
Adapter& adapter_;
diff --git a/service/main.cc b/service/main.cc
index df66497..019098e 100644
--- a/service/main.cc
+++ b/service/main.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -55,16 +55,14 @@
return EXIT_SUCCESS;
}
-#if !defined(OS_GENERIC)
// TODO(armansito): Remove Chromecast specific property out of here. This
// should just be obtained from global config.
char disable_value[PROPERTY_VALUE_MAX];
- int status = property_get(kDisableProperty, disable_value, nullptr);
+ int status = osi_property_get(kDisableProperty, disable_value, nullptr);
if (status && !strcmp(disable_value, "1")) {
LOG(INFO) << "service disabled";
return EXIT_SUCCESS;
}
-#endif // !defined(OS_GENERIC)
if (!bluetooth::Daemon::Initialize()) {
LOG(ERROR) << "Failed to initialize Daemon";
diff --git a/service/settings.cc b/service/settings.cc
index 79ac030..af67fbe 100644
--- a/service/settings.cc
+++ b/service/settings.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/settings.h b/service/settings.h
index 4e7a6b4..1f298d6 100644
--- a/service/settings.h
+++ b/service/settings.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/switches.h b/service/switches.h
index fe6056a..aa1658c 100644
--- a/service/switches.h
+++ b/service/switches.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/test/adapter_unittest.cc b/service/test/adapter_unittest.cc
index c3827dc..e6f5d10 100644
--- a/service/test/adapter_unittest.cc
+++ b/service/test/adapter_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/test/advertise_data_unittest.cc b/service/test/advertise_data_unittest.cc
index bd0787e..28c27bf 100644
--- a/service/test/advertise_data_unittest.cc
+++ b/service/test/advertise_data_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/test/fake_hal_util.cc b/service/test/fake_hal_util.cc
index 0fdc19b..263be64 100644
--- a/service/test/fake_hal_util.cc
+++ b/service/test/fake_hal_util.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -22,4 +22,4 @@
// tests. Instead of doing it this way, however, we should instead provide a C++
// class abstraction for this (and all other btif interfaces) that we can mock
// for testing.
-int hal_util_load_bt_library(const struct hw_module_t** module) { return -1; }
+int hal_util_load_bt_library(const bt_interface_t** interface) { return -1; }
diff --git a/service/test/gatt_client_unittest.cc b/service/test/gatt_client_unittest.cc
index 2d59106..310e4b9 100644
--- a/service/test/gatt_client_unittest.cc
+++ b/service/test/gatt_client_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@
MockGattHandler() = default;
~MockGattHandler() override = default;
- MOCK_METHOD1(RegisterClient, bt_status_t(const bt_uuid_t&));
+ MOCK_METHOD1(RegisterClient, bt_status_t(const bluetooth::Uuid&));
MOCK_METHOD1(UnregisterClient, bt_status_t(int));
MOCK_METHOD1(Scan, bt_status_t(bool));
MOCK_METHOD4(Connect, bt_status_t(int, const RawAddress&, bool, int));
@@ -85,11 +85,11 @@
// These will be asynchronously populated with a result when the callback
// executes.
BLEStatus status = BLE_STATUS_SUCCESS;
- UUID cb_uuid;
+ Uuid cb_uuid;
std::unique_ptr<GattClient> client;
int callback_count = 0;
- auto callback = [&](BLEStatus in_status, const UUID& uuid,
+ auto callback = [&](BLEStatus in_status, const Uuid& uuid,
std::unique_ptr<BluetoothInstance> in_client) {
status = in_status;
cb_uuid = uuid;
@@ -98,7 +98,7 @@
callback_count++;
};
- UUID uuid0 = UUID::GetRandom();
+ Uuid uuid0 = Uuid::GetRandom();
// HAL returns failure.
EXPECT_FALSE(factory_->RegisterInstance(uuid0, callback));
@@ -108,30 +108,28 @@
EXPECT_TRUE(factory_->RegisterInstance(uuid0, callback));
EXPECT_EQ(0, callback_count);
- // Calling twice with the same UUID should fail with no additional call into
+ // Calling twice with the same Uuid should fail with no additional call into
// the stack.
EXPECT_FALSE(factory_->RegisterInstance(uuid0, callback));
testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
- // Call with a different UUID while one is pending.
- UUID uuid1 = UUID::GetRandom();
+ // Call with a different Uuid while one is pending.
+ Uuid uuid1 = Uuid::GetRandom();
EXPECT_CALL(*mock_handler_, RegisterClient(_))
.Times(1)
.WillOnce(Return(BT_STATUS_SUCCESS));
EXPECT_TRUE(factory_->RegisterInstance(uuid1, callback));
- // Trigger callback with an unknown UUID. This should get ignored.
- UUID uuid2 = UUID::GetRandom();
- bt_uuid_t hal_uuid = uuid2.GetBlueDroid();
- fake_hal_gatt_iface_->NotifyRegisterClientCallback(0, 0, hal_uuid);
+ // Trigger callback with an unknown Uuid. This should get ignored.
+ Uuid uuid2 = Uuid::GetRandom();
+ fake_hal_gatt_iface_->NotifyRegisterClientCallback(0, 0, uuid2);
EXPECT_EQ(0, callback_count);
// |uuid0| succeeds.
int client_id0 = 2; // Pick something that's not 0.
- hal_uuid = uuid0.GetBlueDroid();
fake_hal_gatt_iface_->NotifyRegisterClientCallback(BT_STATUS_SUCCESS,
- client_id0, hal_uuid);
+ client_id0, uuid0);
EXPECT_EQ(1, callback_count);
ASSERT_TRUE(client.get() != nullptr); // Assert to terminate in case of error
@@ -149,9 +147,8 @@
// |uuid1| fails.
int client_id1 = 3;
- hal_uuid = uuid1.GetBlueDroid();
fake_hal_gatt_iface_->NotifyRegisterClientCallback(BT_STATUS_FAIL, client_id1,
- hal_uuid);
+ uuid1);
EXPECT_EQ(2, callback_count);
ASSERT_TRUE(client.get() == nullptr); // Assert to terminate in case of error
diff --git a/service/test/gatt_server_unittest.cc b/service/test/gatt_server_unittest.cc
index 0e70ac9..7d7fec2 100644
--- a/service/test/gatt_server_unittest.cc
+++ b/service/test/gatt_server_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -32,11 +32,12 @@
MockGattHandler() = default;
~MockGattHandler() override = default;
- MOCK_METHOD1(RegisterServer, bt_status_t(const bt_uuid_t&));
+ MOCK_METHOD1(RegisterServer, bt_status_t(const bluetooth::Uuid&));
MOCK_METHOD1(UnregisterServer, bt_status_t(int));
MOCK_METHOD2(AddService, bt_status_t(int, std::vector<btgatt_db_element_t>));
- MOCK_METHOD5(AddCharacteristic, bt_status_t(int, int, bt_uuid_t*, int, int));
- MOCK_METHOD4(AddDescriptor, bt_status_t(int, int, bt_uuid_t*, int));
+ MOCK_METHOD5(AddCharacteristic,
+ bt_status_t(int, int, bluetooth::Uuid*, int, int));
+ MOCK_METHOD4(AddDescriptor, bt_status_t(int, int, bluetooth::Uuid*, int));
MOCK_METHOD3(StartService, bt_status_t(int, int, int));
MOCK_METHOD2(DeleteService, bt_status_t(int, int));
MOCK_METHOD5(SendIndication,
@@ -211,8 +212,8 @@
void SetUp() override {
GattServerTest::SetUp();
- UUID uuid = UUID::GetRandom();
- auto callback = [&](BLEStatus status, const UUID& in_uuid,
+ Uuid uuid = Uuid::GetRandom();
+ auto callback = [&](BLEStatus status, const Uuid& in_uuid,
std::unique_ptr<BluetoothInstance> in_client) {
CHECK(in_uuid == uuid);
CHECK(in_client.get());
@@ -228,9 +229,8 @@
factory_->RegisterInstance(uuid, callback);
- bt_uuid_t hal_uuid = uuid.GetBlueDroid();
- fake_hal_gatt_iface_->NotifyRegisterServerCallback(
- BT_STATUS_SUCCESS, kDefaultServerId, hal_uuid);
+ fake_hal_gatt_iface_->NotifyRegisterServerCallback(BT_STATUS_SUCCESS,
+ kDefaultServerId, uuid);
}
void TearDown() override {
@@ -246,9 +246,9 @@
.Times(1)
.WillOnce(Return(BT_STATUS_SUCCESS));
- UUID uuid0 = UUID::GetRandom();
- UUID uuid1 = UUID::GetRandom();
- UUID uuid2 = UUID::GetRandom();
+ Uuid uuid0 = Uuid::GetRandom();
+ Uuid uuid1 = Uuid::GetRandom();
+ Uuid uuid2 = Uuid::GetRandom();
bool register_success = false;
@@ -257,7 +257,7 @@
ASSERT_TRUE(gatt_server_->AddService(
service, [&](BLEStatus status, const Service& added_service) {
ASSERT_EQ(BLE_STATUS_SUCCESS, status);
- ASSERT_TRUE(UUID(added_service.uuid()) == UUID(service.uuid()));
+ ASSERT_TRUE(Uuid(added_service.uuid()) == Uuid(service.uuid()));
ASSERT_TRUE(added_service.handle() == 0x0001);
register_success = true;
}));
@@ -268,13 +268,13 @@
std::vector<btgatt_db_element_t> service_with_handles = {
{.type = BTGATT_DB_PRIMARY_SERVICE,
- .uuid = uuid0.GetBlueDroid(),
+ .uuid = uuid0,
.attribute_handle = srvc_handle_},
{.type = BTGATT_DB_CHARACTERISTIC,
- .uuid = uuid1.GetBlueDroid(),
+ .uuid = uuid1,
.attribute_handle = char_handle_},
{.type = BTGATT_DB_DESCRIPTOR,
- .uuid = uuid2.GetBlueDroid(),
+ .uuid = uuid2,
.attribute_handle = desc_handle_},
};
@@ -306,11 +306,11 @@
// These will be asynchronously populate with a result when the callback
// executes.
BLEStatus status = BLE_STATUS_SUCCESS;
- UUID cb_uuid;
+ Uuid cb_uuid;
std::unique_ptr<GattServer> server;
int callback_count = 0;
- auto callback = [&](BLEStatus in_status, const UUID& uuid,
+ auto callback = [&](BLEStatus in_status, const Uuid& uuid,
std::unique_ptr<BluetoothInstance> in_server) {
status = in_status;
cb_uuid = uuid;
@@ -319,7 +319,7 @@
callback_count++;
};
- UUID uuid0 = UUID::GetRandom();
+ Uuid uuid0 = Uuid::GetRandom();
// HAL returns failure.
EXPECT_FALSE(factory_->RegisterInstance(uuid0, callback));
@@ -329,30 +329,28 @@
EXPECT_TRUE(factory_->RegisterInstance(uuid0, callback));
EXPECT_EQ(0, callback_count);
- // Calling twice with the same UUID should fail with no additional calls into
+ // Calling twice with the same Uuid should fail with no additional calls into
// the stack.
EXPECT_FALSE(factory_->RegisterInstance(uuid0, callback));
testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
- // Call with a different UUID while one is pending.
- UUID uuid1 = UUID::GetRandom();
+ // Call with a different Uuid while one is pending.
+ Uuid uuid1 = Uuid::GetRandom();
EXPECT_CALL(*mock_handler_, RegisterServer(_))
.Times(1)
.WillOnce(Return(BT_STATUS_SUCCESS));
EXPECT_TRUE(factory_->RegisterInstance(uuid1, callback));
- // Trigger callback with an unknown UUID. This should get ignored.
- UUID uuid2 = UUID::GetRandom();
- bt_uuid_t hal_uuid = uuid2.GetBlueDroid();
+ // Trigger callback with an unknown Uuid. This should get ignored.
+ bluetooth::Uuid hal_uuid = bluetooth::Uuid::GetRandom();
fake_hal_gatt_iface_->NotifyRegisterServerCallback(0, 0, hal_uuid);
EXPECT_EQ(0, callback_count);
// |uuid0| succeeds.
int server_if0 = 2; // Pick something that's not 0.
- hal_uuid = uuid0.GetBlueDroid();
fake_hal_gatt_iface_->NotifyRegisterServerCallback(BT_STATUS_SUCCESS,
- server_if0, hal_uuid);
+ server_if0, uuid0);
EXPECT_EQ(1, callback_count);
ASSERT_TRUE(server.get() != nullptr); // Assert to terminate in case of error
@@ -371,9 +369,8 @@
// |uuid1| fails.
int server_if1 = 3;
- hal_uuid = uuid1.GetBlueDroid();
fake_hal_gatt_iface_->NotifyRegisterServerCallback(BT_STATUS_FAIL, server_if1,
- hal_uuid);
+ uuid1);
EXPECT_EQ(2, callback_count);
ASSERT_TRUE(server.get() == nullptr); // Assert to terminate in case of error
diff --git a/service/test/ipc_linux_unittest.cc b/service/test/ipc_linux_unittest.cc
index 39cc741..4a347ae 100644
--- a/service/test/ipc_linux_unittest.cc
+++ b/service/test/ipc_linux_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
#include <base/command_line.h>
#include <base/files/scoped_file.h>
#include <base/macros.h>
+#include <base/run_loop.h>
#include <base/strings/stringprintf.h>
#include <gtest/gtest.h>
@@ -167,7 +168,7 @@
// Run the message loop. We will stop the loop when we receive a delegate
// event.
- message_loop_.Run();
+ base::RunLoop().Run();
// We should have received the started event.
EXPECT_EQ(1, delegate.started_count());
@@ -177,7 +178,7 @@
// connections. TearDown should gracefully clean up the thread and the test
// should succeed without hanging.
ipc_manager_.reset();
- message_loop_.Run();
+ base::RunLoop().Run();
EXPECT_EQ(1, delegate.stopped_count());
}
@@ -188,7 +189,7 @@
// Run the message loop. We will stop the loop when we receive a delegate
// event.
- message_loop_.Run();
+ base::RunLoop().Run();
// We should have received the started event.
EXPECT_EQ(1, delegate.started_count());
diff --git a/service/test/low_energy_advertiser_unittest.cc b/service/test/low_energy_advertiser_unittest.cc
index 03188d7..ad76d82 100644
--- a/service/test/low_energy_advertiser_unittest.cc
+++ b/service/test/low_energy_advertiser_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -126,8 +126,8 @@
void RegisterTestAdvertiser(
const std::function<void(std::unique_ptr<LowEnergyAdvertiser> advertiser)>
callback) {
- UUID uuid = UUID::GetRandom();
- auto api_callback = [&](BLEStatus status, const UUID& in_uuid,
+ Uuid uuid = Uuid::GetRandom();
+ auto api_callback = [&](BLEStatus status, const Uuid& in_uuid,
std::unique_ptr<BluetoothInstance> in_client) {
CHECK(in_uuid == uuid);
CHECK(in_client.get());
@@ -207,11 +207,11 @@
// These will be asynchronously populated with a result when the callback
// executes.
BLEStatus status = BLE_STATUS_SUCCESS;
- UUID cb_uuid;
+ Uuid cb_uuid;
std::unique_ptr<LowEnergyAdvertiser> advertiser;
int callback_count = 0;
- auto callback = [&](BLEStatus in_status, const UUID& uuid,
+ auto callback = [&](BLEStatus in_status, const Uuid& uuid,
std::unique_ptr<BluetoothInstance> in_client) {
status = in_status;
cb_uuid = uuid;
@@ -220,7 +220,7 @@
callback_count++;
};
- UUID uuid0 = UUID::GetRandom();
+ Uuid uuid0 = Uuid::GetRandom();
reg_cb reg_adv1_cb;
EXPECT_CALL(*mock_handler_, RegisterAdvertiser(_))
@@ -231,14 +231,14 @@
EXPECT_TRUE(ble_advertiser_factory_->RegisterInstance(uuid0, callback));
EXPECT_EQ(0, callback_count);
- // Calling twice with the same UUID should fail with no additional call into
+ // Calling twice with the same Uuid should fail with no additional call into
// the stack.
EXPECT_FALSE(ble_advertiser_factory_->RegisterInstance(uuid0, callback));
::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
- // Call with a different UUID while one is pending.
- UUID uuid1 = UUID::GetRandom();
+ // Call with a different Uuid while one is pending.
+ Uuid uuid1 = Uuid::GetRandom();
reg_cb reg_adv2_cb;
EXPECT_CALL(*mock_handler_, RegisterAdvertiser(_))
.Times(1)
@@ -426,11 +426,11 @@
}
TEST_F(LowEnergyAdvertiserPostRegisterTest, AdvertiseDataParsing) {
- const std::vector<uint8_t> kUUID16BitData{
+ const std::vector<uint8_t> kUuid16BitData{
0x03, HCI_EIR_COMPLETE_16BITS_UUID_TYPE, 0xDE, 0xAD,
};
- const std::vector<uint8_t> kUUID32BitData{
+ const std::vector<uint8_t> kUuid32BitData{
0x05, HCI_EIR_COMPLETE_32BITS_UUID_TYPE, 0xDE, 0xAD, 0x01, 0x02};
const std::vector<uint8_t> kUUID128BitData{
@@ -444,7 +444,7 @@
0x0B, 0x0C,
0x0D, 0x0E};
- const std::vector<uint8_t> kMultiUUIDData{
+ const std::vector<uint8_t> kMultiUuidData{
0x11, HCI_EIR_COMPLETE_128BITS_UUID_TYPE,
0xDE, 0xAD,
0x01, 0x02,
@@ -492,7 +492,7 @@
0xDE, 0xAD,
0xBE, 0xEF};
- const std::vector<uint8_t> kServiceUUIDMatch{
+ const std::vector<uint8_t> kServiceUuidMatch{
0x05, HCI_EIR_COMPLETE_32BITS_UUID_TYPE,
0xDE, 0xAD,
0x01, 0x02,
@@ -501,7 +501,7 @@
0x01, 0x02,
0xBE, 0xEF};
- const std::vector<uint8_t> kServiceUUIDMismatch{
+ const std::vector<uint8_t> kServiceUuidMismatch{
0x05, HCI_EIR_COMPLETE_32BITS_UUID_TYPE,
0xDE, 0xAD,
0x01, 0x01,
@@ -510,18 +510,18 @@
0x01, 0x02,
0xBE, 0xEF};
- AdvertiseData uuid_16bit_adv(kUUID16BitData);
- AdvertiseData uuid_32bit_adv(kUUID32BitData);
+ AdvertiseData uuid_16bit_adv(kUuid16BitData);
+ AdvertiseData uuid_32bit_adv(kUuid32BitData);
AdvertiseData uuid_128bit_adv(kUUID128BitData);
- AdvertiseData multi_uuid_adv(kMultiUUIDData);
+ AdvertiseData multi_uuid_adv(kMultiUuidData);
AdvertiseData service_16bit_adv(kServiceData16Bit);
AdvertiseData service_32bit_adv(kServiceData32Bit);
AdvertiseData service_128bit_adv(kServiceData128Bit);
AdvertiseData multi_service_adv(kMultiServiceData);
- AdvertiseData service_uuid_match(kServiceUUIDMatch);
- AdvertiseData service_uuid_mismatch(kServiceUUIDMismatch);
+ AdvertiseData service_uuid_match(kServiceUuidMatch);
+ AdvertiseData service_uuid_mismatch(kServiceUuidMismatch);
AdvertiseSettings settings;
@@ -533,7 +533,7 @@
};
status_cb start_advertising_cb;
- // Multiple UUID test
+ // Multiple Uuid test
EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
.Times(1)
.WillOnce(SaveArg<1>(&start_advertising_cb));
@@ -612,7 +612,7 @@
EXPECT_EQ(8, callback_count);
::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
- // Service data and UUID where the UUID for both match, should succeed.
+ // Service data and Uuid where the Uuid for both match, should succeed.
EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
.Times(1)
.WillOnce(SaveArg<1>(&start_advertising_cb));
@@ -620,7 +620,7 @@
EXPECT_EQ(9, callback_count);
::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
- // Service data and UUID where the UUID for dont match, should fail
+ // Service data and Uuid where the Uuid for dont match, should fail
EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
.Times(1)
.WillOnce(SaveArg<1>(&start_advertising_cb));
diff --git a/service/test/low_energy_client_unittest.cc b/service/test/low_energy_client_unittest.cc
index 5870f2e..3bf566c 100644
--- a/service/test/low_energy_client_unittest.cc
+++ b/service/test/low_energy_client_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@
MockGattHandler(){};
~MockGattHandler() override = default;
- MOCK_METHOD1(RegisterClient, bt_status_t(const bt_uuid_t&));
+ MOCK_METHOD1(RegisterClient, bt_status_t(const bluetooth::Uuid&));
MOCK_METHOD1(UnregisterClient, bt_status_t(int));
MOCK_METHOD4(Connect, bt_status_t(int, const RawAddress&, bool, int));
MOCK_METHOD3(Disconnect, bt_status_t(int, const RawAddress&, int));
@@ -134,8 +134,8 @@
void RegisterTestClient(
const std::function<void(std::unique_ptr<LowEnergyClient> client)>
callback) {
- UUID uuid = UUID::GetRandom();
- auto api_callback = [&](BLEStatus status, const UUID& in_uuid,
+ Uuid uuid = Uuid::GetRandom();
+ auto api_callback = [&](BLEStatus status, const Uuid& in_uuid,
std::unique_ptr<BluetoothInstance> in_client) {
CHECK(in_uuid == uuid);
CHECK(in_client.get());
@@ -151,9 +151,8 @@
ble_factory_->RegisterInstance(uuid, api_callback);
- bt_uuid_t hal_uuid = uuid.GetBlueDroid();
fake_hal_gatt_iface_->NotifyRegisterClientCallback(0, next_client_id_++,
- hal_uuid);
+ uuid);
::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
}
@@ -175,11 +174,11 @@
// These will be asynchronously populated with a result when the callback
// executes.
BLEStatus status = BLE_STATUS_SUCCESS;
- UUID cb_uuid;
+ Uuid cb_uuid;
std::unique_ptr<LowEnergyClient> client;
int callback_count = 0;
- auto callback = [&](BLEStatus in_status, const UUID& uuid,
+ auto callback = [&](BLEStatus in_status, const Uuid& uuid,
std::unique_ptr<BluetoothInstance> in_client) {
status = in_status;
cb_uuid = uuid;
@@ -188,7 +187,7 @@
callback_count++;
};
- UUID uuid0 = UUID::GetRandom();
+ Uuid uuid0 = Uuid::GetRandom();
// HAL returns failure.
EXPECT_FALSE(ble_factory_->RegisterInstance(uuid0, callback));
@@ -198,30 +197,28 @@
EXPECT_TRUE(ble_factory_->RegisterInstance(uuid0, callback));
EXPECT_EQ(0, callback_count);
- // Calling twice with the same UUID should fail with no additional call into
+ // Calling twice with the same Uuid should fail with no additional call into
// the stack.
EXPECT_FALSE(ble_factory_->RegisterInstance(uuid0, callback));
::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
- // Call with a different UUID while one is pending.
- UUID uuid1 = UUID::GetRandom();
+ // Call with a different Uuid while one is pending.
+ Uuid uuid1 = Uuid::GetRandom();
EXPECT_CALL(*mock_handler_, RegisterClient(_))
.Times(1)
.WillOnce(Return(BT_STATUS_SUCCESS));
EXPECT_TRUE(ble_factory_->RegisterInstance(uuid1, callback));
- // Trigger callback with an unknown UUID. This should get ignored.
- UUID uuid2 = UUID::GetRandom();
- bt_uuid_t hal_uuid = uuid2.GetBlueDroid();
- fake_hal_gatt_iface_->NotifyRegisterClientCallback(0, 0, hal_uuid);
+ // Trigger callback with an unknown Uuid. This should get ignored.
+ Uuid uuid2 = Uuid::GetRandom();
+ fake_hal_gatt_iface_->NotifyRegisterClientCallback(0, 0, uuid2);
EXPECT_EQ(0, callback_count);
// |uuid0| succeeds.
int client_if0 = 2; // Pick something that's not 0.
- hal_uuid = uuid0.GetBlueDroid();
fake_hal_gatt_iface_->NotifyRegisterClientCallback(BT_STATUS_SUCCESS,
- client_if0, hal_uuid);
+ client_if0, uuid0);
EXPECT_EQ(1, callback_count);
ASSERT_TRUE(client.get() != nullptr); // Assert to terminate in case of error
@@ -239,9 +236,8 @@
// |uuid1| fails.
int client_if1 = 3;
- hal_uuid = uuid1.GetBlueDroid();
fake_hal_gatt_iface_->NotifyRegisterClientCallback(BT_STATUS_FAIL, client_if1,
- hal_uuid);
+ uuid1);
EXPECT_EQ(2, callback_count);
ASSERT_TRUE(client.get() == nullptr); // Assert to terminate in case of error
diff --git a/service/test/low_energy_scanner_unittest.cc b/service/test/low_energy_scanner_unittest.cc
index d723a50..c8b16f3 100644
--- a/service/test/low_energy_scanner_unittest.cc
+++ b/service/test/low_energy_scanner_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -71,14 +71,8 @@
StartSyncCb, SyncReportCb, SyncLostCb));
MOCK_METHOD1(StopSync, void(uint16_t));
- void ScanFilterAddRemove(int action, int filt_type, int filt_index,
- int company_id, int company_id_mask,
- const bt_uuid_t* p_uuid,
- const bt_uuid_t* p_uuid_mask,
- const RawAddress* bd_addr, char addr_type,
- std::vector<uint8_t> data,
- std::vector<uint8_t> p_mask,
- FilterConfigCallback cb){};
+ void ScanFilterAdd(int filter_index, std::vector<ApcfCommand> filters,
+ FilterConfigCallback cb){};
void ScanFilterParamSetup(
uint8_t client_if, uint8_t action, uint8_t filt_index,
@@ -164,8 +158,8 @@
void RegisterTestScanner(
const std::function<void(std::unique_ptr<LowEnergyScanner> scanner)>
callback) {
- UUID uuid = UUID::GetRandom();
- auto api_callback = [&](BLEStatus status, const UUID& in_uuid,
+ Uuid uuid = Uuid::GetRandom();
+ auto api_callback = [&](BLEStatus status, const Uuid& in_uuid,
std::unique_ptr<BluetoothInstance> in_scanner) {
CHECK(in_uuid == uuid);
CHECK(in_scanner.get());
@@ -204,11 +198,11 @@
// These will be asynchronously populated with a result when the callback
// executes.
BLEStatus status = BLE_STATUS_SUCCESS;
- UUID cb_uuid;
+ Uuid cb_uuid;
std::unique_ptr<LowEnergyScanner> scanner;
int callback_count = 0;
- auto callback = [&](BLEStatus in_status, const UUID& uuid,
+ auto callback = [&](BLEStatus in_status, const Uuid& uuid,
std::unique_ptr<BluetoothInstance> in_scanner) {
status = in_status;
cb_uuid = uuid;
@@ -217,20 +211,20 @@
callback_count++;
};
- UUID uuid0 = UUID::GetRandom();
+ Uuid uuid0 = Uuid::GetRandom();
// HAL returns success.
EXPECT_TRUE(ble_factory_->RegisterInstance(uuid0, callback));
EXPECT_EQ(0, callback_count);
- // Calling twice with the same UUID should fail with no additional call into
+ // Calling twice with the same Uuid should fail with no additional call into
// the stack.
EXPECT_FALSE(ble_factory_->RegisterInstance(uuid0, callback));
::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
- // Call with a different UUID while one is pending.
- UUID uuid1 = UUID::GetRandom();
+ // Call with a different Uuid while one is pending.
+ Uuid uuid1 = Uuid::GetRandom();
BleScannerInterface::RegisterCallback reg_scanner_cb2;
EXPECT_CALL(*mock_handler_, RegisterScanner(_))
.Times(1)
diff --git a/service/test/main.cc b/service/test/main.cc
index 55e0d07..d9a1735 100644
--- a/service/test/main.cc
+++ b/service/test/main.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/test/mock_adapter.h b/service/test/mock_adapter.h
index 1a762fb..4b93792 100644
--- a/service/test/mock_adapter.h
+++ b/service/test/mock_adapter.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/test/mock_daemon.h b/service/test/mock_daemon.h
index a5dd974..9947915 100644
--- a/service/test/mock_daemon.h
+++ b/service/test/mock_daemon.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/test/parcelable_unittest.cc b/service/test/parcelable_unittest.cc
index dcfb8fb..3bc2b61 100644
--- a/service/test/parcelable_unittest.cc
+++ b/service/test/parcelable_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2016 Google, Inc.
+// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@
using bluetooth::ScanResult;
using bluetooth::ScanSettings;
using bluetooth::Service;
-using bluetooth::UUID;
+using bluetooth::Uuid;
namespace bluetooth {
namespace {
@@ -82,11 +82,11 @@
EXPECT_TRUE(result);
}
-TEST(ParcelableTest, UUID) {
- // Try a whole bunch of UUIDs.
+TEST(ParcelableTest, Uuid) {
+ // Try a whole bunch of Uuids.
for (int i = 0; i < 10; i++) {
- UUID uuid = UUID::GetRandom();
- TestData<UUID, android::bluetooth::UUID>(uuid);
+ Uuid uuid = Uuid::GetRandom();
+ TestData<Uuid, android::bluetooth::UUID>(uuid);
}
}
@@ -115,13 +115,13 @@
bool result = TestData<ScanFilter, android::bluetooth::ScanFilter>(filter);
EXPECT_TRUE(result);
- UUID uuid = UUID::GetRandom();
+ Uuid uuid = Uuid::GetRandom();
filter.SetServiceUuid(uuid);
result = TestData<ScanFilter, android::bluetooth::ScanFilter>(filter);
EXPECT_TRUE(result);
- UUID mask = UUID::GetRandom();
+ Uuid mask = Uuid::GetRandom();
filter.SetServiceUuidWithMask(uuid, mask);
result = TestData<ScanFilter, android::bluetooth::ScanFilter>(filter);
EXPECT_TRUE(result);
@@ -146,11 +146,11 @@
}
TEST(ParcelableTest, GattDescriptor) {
- Descriptor s = Descriptor(0x0000, UUID::GetRandom(),
+ Descriptor s = Descriptor(0x0000, Uuid::GetRandom(),
bluetooth::kAttributePermissionRead);
- Descriptor s2 = Descriptor(0xFFFE, UUID::GetRandom(),
+ Descriptor s2 = Descriptor(0xFFFE, Uuid::GetRandom(),
bluetooth::kAttributePermissionWrite);
- Descriptor s3 = Descriptor(0x003D, UUID::GetRandom(),
+ Descriptor s3 = Descriptor(0x003D, Uuid::GetRandom(),
bluetooth::kAttributePermissionReadEncryptedMITM |
bluetooth::kAttributePermissionRead);
@@ -168,10 +168,10 @@
}
TEST(ParcelableTest, GattCharacteristic) {
- Characteristic c = Characteristic(0x0004, UUID::GetRandom(), 0, 0,
- {Descriptor(0x0005, UUID::GetRandom(), 0),
- Descriptor(0x0007, UUID::GetRandom(), 0),
- Descriptor(0x00A1, UUID::GetRandom(), 0)});
+ Characteristic c = Characteristic(0x0004, Uuid::GetRandom(), 0, 0,
+ {Descriptor(0x0005, Uuid::GetRandom(), 0),
+ Descriptor(0x0007, Uuid::GetRandom(), 0),
+ Descriptor(0x00A1, Uuid::GetRandom(), 0)});
bool result =
TestData<Characteristic, android::bluetooth::BluetoothGattCharacteristic>(
@@ -181,19 +181,19 @@
TEST(ParcelableTest, GattService) {
Service s =
- Service(0x0001, true, UUID("CAFE"),
- {Characteristic(0x0004, UUID::GetRandom(),
+ Service(0x0001, true, Uuid::FromString("CAFE", nullptr),
+ {Characteristic(0x0004, Uuid::GetRandom(),
bluetooth::kCharacteristicPropertyNotify,
bluetooth::kAttributePermissionRead,
- {Descriptor(0x0005, UUID::GetRandom(), 0),
- Descriptor(0x0007, UUID::GetRandom(), 0),
- Descriptor(0x0009, UUID::GetRandom(), 0)}),
- Characteristic(0x000D, UUID::GetRandom(),
+ {Descriptor(0x0005, Uuid::GetRandom(), 0),
+ Descriptor(0x0007, Uuid::GetRandom(), 0),
+ Descriptor(0x0009, Uuid::GetRandom(), 0)}),
+ Characteristic(0x000D, Uuid::GetRandom(),
bluetooth::kCharacteristicPropertyWrite,
bluetooth::kAttributePermissionWrite,
- {Descriptor(0x0010, UUID::GetRandom(), 0),
- Descriptor(0x0012, UUID::GetRandom(), 0)}),
- Characteristic(0x0015, UUID::GetRandom(), 0, 0, {})},
+ {Descriptor(0x0010, Uuid::GetRandom(), 0),
+ Descriptor(0x0012, Uuid::GetRandom(), 0)}),
+ Characteristic(0x0015, Uuid::GetRandom(), 0, 0, {})},
{});
Parcel parcel;
diff --git a/service/test/settings_unittest.cc b/service/test/settings_unittest.cc
index 62b6db5..551c1e0 100644
--- a/service/test/settings_unittest.cc
+++ b/service/test/settings_unittest.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/test/stub_ipc_handler_binder.cc b/service/test/stub_ipc_handler_binder.cc
index 8ce064b..2fb450f 100644
--- a/service/test/stub_ipc_handler_binder.cc
+++ b/service/test/stub_ipc_handler_binder.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2015 Google, Inc.
+// Copyright 2015 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/service/test/stub_ipc_handler_linux.cc b/service/test/stub_ipc_handler_linux.cc
deleted file mode 100644
index 011b965..0000000
--- a/service/test/stub_ipc_handler_linux.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// Copyright (C) 2015 Google, Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at:
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include "service/ipc/ipc_handler_linux.h"
-
-// TODO(keybuk): This is a crappy workaround to link IPCHandlerLinux into
-// host-native unit tests. IPCManager shouldn't explicitly reference these
-// classes.
-
-namespace ipc {
-
-IPCHandlerLinux::IPCHandlerLinux(bluetooth::Adapter* adapter,
- IPCManager::Delegate* delegate)
- : IPCHandler(adapter, delegate),
- running_(false),
- thread_("IPCHandlerLinux"),
- keep_running_(true) {
- // Stub
-}
-
-IPCHandlerLinux::~IPCHandlerLinux() {
- // Stub
-}
-
-bool IPCHandlerLinux::Run() {
- // Stub
- return false;
-}
-
-void IPCHandlerLinux::Stop() {
- // Stub
-}
-
-void IPCHandlerLinux::StartListeningOnThread() {
- // Stub
-}
-
-void IPCHandlerLinux::ShutDownOnOriginThread() {
- // Stub
-}
-
-void IPCHandlerLinux::NotifyStartedOnOriginThread() {
- // Stub
-}
-
-void IPCHandlerLinux::NotifyStartedOnCurrentThread() {
- // Stub
-}
-
-void IPCHandlerLinux::NotifyStoppedOnOriginThread() {
- // Stub
-}
-
-void IPCHandlerLinux::NotifyStoppedOnCurrentThread() {
- // Stub
-}
-
-} // namespace
diff --git a/service/test/uuid_unittest.cc b/service/test/uuid_unittest.cc
deleted file mode 100644
index 3a8103a..0000000
--- a/service/test/uuid_unittest.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-//
-// Copyright (C) 2015 Google, Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at:
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include <stdint.h>
-#include <algorithm>
-#include <array>
-
-#include <gtest/gtest.h>
-
-#include "service/common/bluetooth/uuid.h"
-
-using namespace bluetooth;
-
-namespace {
-
-const std::array<uint8_t, UUID::kNumBytes128> kBtSigBaseUUID = {{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5f, 0x9b, 0x34, 0xfb,
-}};
-
-} // namespace
-
-// Verify that an uninitialized UUID is equal
-// To the BT SIG Base UUID.
-TEST(UUIDTest, DefaultUUID) {
- UUID uuid;
- ASSERT_TRUE(uuid.is_valid());
- ASSERT_TRUE(uuid.GetFullBigEndian() == kBtSigBaseUUID);
-}
-
-// Verify that we initialize a 16-bit UUID in a
-// way consistent with how we read it.
-TEST(UUIDTest, Init16Bit) {
- auto my_uuid_16 = kBtSigBaseUUID;
- my_uuid_16[2] = 0xde;
- my_uuid_16[3] = 0xad;
- UUID uuid(UUID::UUID16Bit({{0xde, 0xad}}));
- ASSERT_TRUE(uuid.is_valid());
- ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_16);
- ASSERT_TRUE(UUID::kNumBytes16 == uuid.GetShortestRepresentationSize());
-}
-
-// Verify that we initialize a 16-bit UUID in a
-// way consistent with how we read it.
-TEST(UUIDTest, Init16BitString) {
- auto my_uuid_16 = kBtSigBaseUUID;
- my_uuid_16[2] = 0xde;
- my_uuid_16[3] = 0xad;
- UUID uuid("dead");
- ASSERT_TRUE(uuid.is_valid());
- ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_16);
- ASSERT_TRUE(UUID::kNumBytes16 == uuid.GetShortestRepresentationSize());
-
- uuid = UUID("0xdead");
- ASSERT_TRUE(uuid.is_valid());
- ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_16);
- ASSERT_TRUE(UUID::kNumBytes16 == uuid.GetShortestRepresentationSize());
-}
-
-// Verify that we initialize a 32-bit UUID in a
-// way consistent with how we read it.
-TEST(UUIDTest, Init32Bit) {
- auto my_uuid_32 = kBtSigBaseUUID;
- my_uuid_32[0] = 0xde;
- my_uuid_32[1] = 0xad;
- my_uuid_32[2] = 0xbe;
- my_uuid_32[3] = 0xef;
- UUID uuid(UUID::UUID32Bit({{0xde, 0xad, 0xbe, 0xef}}));
- ASSERT_TRUE(uuid.is_valid());
- ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_32);
- ASSERT_TRUE(UUID::kNumBytes32 == uuid.GetShortestRepresentationSize());
-}
-
-// Verify correct reading of a 32-bit UUID initialized from string.
-TEST(UUIDTest, Init32BitString) {
- auto my_uuid_32 = kBtSigBaseUUID;
- my_uuid_32[0] = 0xde;
- my_uuid_32[1] = 0xad;
- my_uuid_32[2] = 0xbe;
- my_uuid_32[3] = 0xef;
- UUID uuid("deadbeef");
- ASSERT_TRUE(uuid.is_valid());
- ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_32);
- ASSERT_TRUE(UUID::kNumBytes32 == uuid.GetShortestRepresentationSize());
-}
-
-// Verify that we initialize a 128-bit UUID in a
-// way consistent with how we read it.
-TEST(UUIDTest, Init128Bit) {
- auto my_uuid_128 = kBtSigBaseUUID;
- for (int i = 0; i < static_cast<int>(my_uuid_128.size()); ++i) {
- my_uuid_128[i] = i;
- }
-
- UUID uuid(my_uuid_128);
- ASSERT_TRUE(uuid.is_valid());
- ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_128);
- ASSERT_TRUE(UUID::kNumBytes128 == uuid.GetShortestRepresentationSize());
-}
-
-// Verify that we initialize a 128-bit UUID in a
-// way consistent with how we read it as LE.
-TEST(UUIDTest, Init128BitLittleEndian) {
- auto my_uuid_128 = kBtSigBaseUUID;
- for (int i = 0; i < static_cast<int>(my_uuid_128.size()); ++i) {
- my_uuid_128[i] = i;
- }
-
- UUID uuid(my_uuid_128);
- std::reverse(my_uuid_128.begin(), my_uuid_128.end());
- ASSERT_TRUE(uuid.is_valid());
- ASSERT_TRUE(uuid.GetFullLittleEndian() == my_uuid_128);
-}
-
-// Verify that we initialize a 128-bit UUID in a
-// way consistent with how we read it.
-TEST(UUIDTest, Init128BitString) {
- UUID::UUID128Bit my_uuid{
- {7, 1, 6, 8, 14, 255, 16, 2, 3, 4, 5, 6, 7, 8, 9, 10}};
- std::string my_uuid_string("07010608-0eff-1002-0304-05060708090a");
-
- UUID uuid0(my_uuid);
- UUID uuid1(my_uuid_string);
-
- ASSERT_TRUE(uuid0.is_valid());
- ASSERT_TRUE(uuid1.is_valid());
- ASSERT_TRUE(uuid0 == uuid1);
- ASSERT_TRUE(UUID::kNumBytes128 == uuid0.GetShortestRepresentationSize());
-}
-
-TEST(UUIDTest, InitInvalid) {
- UUID uuid0("000102030405060708090A0B0C0D0E0F");
- ASSERT_FALSE(uuid0.is_valid());
-
- UUID uuid1("1*90");
- ASSERT_FALSE(uuid1.is_valid());
-
- UUID uuid2("109g");
- ASSERT_FALSE(uuid1.is_valid());
-}
-
-TEST(UUIDTest, ToString) {
- const UUID::UUID16Bit data{{0x18, 0x0d}};
- UUID uuid(data);
- std::string uuid_string = uuid.ToString();
- EXPECT_EQ("0000180d-0000-1000-8000-00805f9b34fb", uuid_string);
-}
diff --git a/stack/Android.bp b/stack/Android.bp
index 5cb5678..ceb2f13 100644
--- a/stack/Android.bp
+++ b/stack/Android.bp
@@ -20,10 +20,11 @@
"srvc",
],
header_libs: [
- "libhardware_headers",
+ "libbluetooth_headers",
],
include_dirs: [
"external/aac/libAACenc/include",
+ "external/aac/libAACdec/include",
"external/aac/libSYS/include",
"external/libldac/inc",
"external/libldac/abr/inc",
@@ -33,7 +34,7 @@
"system/bt/vnd/ble",
"system/bt/btif/include",
"system/bt/hci/include",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/udrv/include",
"system/bt/bta/include",
"system/bt/bta/sys",
@@ -41,10 +42,12 @@
],
srcs: [
"a2dp/a2dp_aac.cc",
+ "a2dp/a2dp_aac_decoder.cc",
"a2dp/a2dp_aac_encoder.cc",
"a2dp/a2dp_api.cc",
"a2dp/a2dp_codec_config.cc",
"a2dp/a2dp_sbc.cc",
+ "a2dp/a2dp_sbc_decoder.cc",
"a2dp/a2dp_sbc_encoder.cc",
"a2dp/a2dp_sbc_up_sample.cc",
"a2dp/a2dp_vendor.cc",
@@ -125,7 +128,6 @@
"l2cap/l2c_fcr.cc",
"l2cap/l2c_link.cc",
"l2cap/l2c_main.cc",
- "l2cap/l2c_ucd.cc",
"l2cap/l2c_utils.cc",
"l2cap/l2cap_client.cc",
"mcap/mca_api.cc",
@@ -193,19 +195,82 @@
],
include_dirs: [
"system/bt",
- "system/bt/include",
+ "system/bt/internal_include",
],
- srcs: ["test/stack_a2dp_test.cc"],
+ srcs: [
+ "test/stack_a2dp_test.cc",
+ ],
shared_libs: [
+ "libhidlbase",
"liblog",
+ "libprotobuf-cpp-lite",
"libcutils",
+ "libutils",
],
static_libs: [
+ "libbt-bta",
"libbt-stack",
+ "libbt-sbc-decoder",
"libbt-sbc-encoder",
"libFraunhoferAAC",
+ "libbtdevice",
+ "libbt-hci",
"libosi",
+ "libbt-protos-lite",
],
+ whole_static_libs: [
+ "libbluetooth-for-tests",
+ ],
+}
+
+cc_test {
+ name: "net_test_stack_rfcomm",
+ defaults: ["fluoride_defaults"],
+ host_supported: true,
+ local_include_dirs: [
+ "include",
+ "btm",
+ "l2cap",
+ "smp",
+ "rfcomm",
+ "test/common",
+ ],
+ include_dirs: [
+ "system/bt",
+ "system/bt/internal_include",
+ "system/bt/btcore/include",
+ "system/bt/hci/include",
+ "system/bt/utils/include",
+ ],
+ srcs: [
+ "rfcomm/port_api.cc",
+ "rfcomm/port_rfc.cc",
+ "rfcomm/port_utils.cc",
+ "rfcomm/rfc_l2cap_if.cc",
+ "rfcomm/rfc_mx_fsm.cc",
+ "rfcomm/rfc_port_fsm.cc",
+ "rfcomm/rfc_port_if.cc",
+ "rfcomm/rfc_ts_frames.cc",
+ "rfcomm/rfc_utils.cc",
+ "test/common/mock_btm_layer.cc",
+ "test/common/mock_btu_layer.cc",
+ "test/common/mock_l2cap_layer.cc",
+ "test/common/stack_test_packet_utils.cc",
+ "test/rfcomm/stack_rfcomm_test.cc",
+ "test/rfcomm/stack_rfcomm_test_main.cc",
+ "test/rfcomm/stack_rfcomm_test_utils.cc",
+ "test/rfcomm/stack_rfcomm_test_utils_test.cc",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libprotobuf-cpp-lite",
+ ],
+ static_libs: [
+ "liblog",
+ "libgmock",
+ "libosi",
+ "libbt-protos-lite",
+ ],
}
// Bluetooth stack smp unit tests for target
@@ -221,7 +286,7 @@
],
include_dirs: [
"system/bt",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/btcore/include",
"system/bt/hci/include",
"system/bt/utils/include",
@@ -229,6 +294,9 @@
srcs: [
"smp/smp_keys.cc",
"smp/aes.cc",
+ "smp/p_256_curvepara.cc",
+ "smp/p_256_ecc_pp.cc",
+ "smp/p_256_multprecision.cc",
"smp/smp_api.cc",
"smp/smp_main.cc",
"smp/smp_utils.cc",
@@ -256,10 +324,10 @@
],
include_dirs: [
"system/bt",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/btcore/include",
"system/bt/hci/include",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/utils/include",
],
srcs: [
@@ -274,6 +342,9 @@
"liblog",
"libgmock",
],
+ sanitize: {
+ cfi: false,
+ },
}
// Bluetooth stack advertise data parsing unit tests for target
@@ -305,7 +376,7 @@
],
include_dirs: [
"system/bt/",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/btcore/include",
"system/bt/bta/include",
],
@@ -322,6 +393,9 @@
"libbluetooth-types",
"libgmock",
"libosi",
- "libbt-protos",
+ "libbt-protos-lite",
],
+ sanitize: {
+ cfi: false,
+ },
}
diff --git a/stack/BUILD.gn b/stack/BUILD.gn
index 9e386ab..6f3c55a 100644
--- a/stack/BUILD.gn
+++ b/stack/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,10 +17,12 @@
static_library("stack") {
sources = [
"a2dp/a2dp_aac.cc",
+ "a2dp/a2dp_aac_decoder.cc",
"a2dp/a2dp_aac_encoder.cc",
"a2dp/a2dp_api.cc",
"a2dp/a2dp_codec_config.cc",
"a2dp/a2dp_sbc.cc",
+ "a2dp/a2dp_sbc_decoder.cc",
"a2dp/a2dp_sbc_encoder.cc",
"a2dp/a2dp_sbc_up_sample.cc",
"a2dp/a2dp_vendor.cc",
@@ -101,7 +103,6 @@
"l2cap/l2c_fcr.cc",
"l2cap/l2c_link.cc",
"l2cap/l2c_main.cc",
- "l2cap/l2c_ucd.cc",
"l2cap/l2c_utils.cc",
"l2cap/l2cap_client.cc",
"mcap/mca_api.cc",
@@ -166,7 +167,7 @@
"//vnd/ble",
"//btif/include",
"//hci/include",
- "//include",
+ "//internal_include",
"//udrv/include",
"//rpc/include",
"//hcis",
@@ -200,7 +201,7 @@
"//btcore/include",
"//embdrv/sbc/encoder/include",
"//hci/include",
- "//include",
+ "//internal_include",
"//stack/a2dp",
"//stack/btm",
"//stack/include",
@@ -227,7 +228,7 @@
"//embdrv/sbc",
"//hci",
"//types",
- "//main:bluetooth.default",
+ "//main:bluetooth",
"//third_party/googletest:gmock_main",
"//third_party/libchrome:base",
]
@@ -245,7 +246,7 @@
"//",
"//btcore/include",
"//hci/include",
- "//include",
+ "//internal_include",
"//stack/btm",
]
diff --git a/stack/a2dp/a2dp_aac.cc b/stack/a2dp/a2dp_aac.cc
index 730aee3..7792631 100644
--- a/stack/a2dp/a2dp_aac.cc
+++ b/stack/a2dp/a2dp_aac.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
#include <string.h>
#include <base/logging.h>
+#include "a2dp_aac_decoder.h"
#include "a2dp_aac_encoder.h"
#include "bt_utils.h"
#include "osi/include/log.h"
@@ -50,7 +51,7 @@
} tA2DP_AAC_CIE;
/* AAC Source codec capabilities */
-static const tA2DP_AAC_CIE a2dp_aac_caps = {
+static const tA2DP_AAC_CIE a2dp_aac_source_caps = {
// objectType
A2DP_AAC_OBJECT_TYPE_MPEG2_LC,
// sampleRate
@@ -65,6 +66,21 @@
// bits_per_sample
BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16};
+/* AAC Sink codec capabilities */
+static const tA2DP_AAC_CIE a2dp_aac_sink_caps = {
+ // objectType
+ A2DP_AAC_OBJECT_TYPE_MPEG2_LC,
+ // sampleRate
+ A2DP_AAC_SAMPLING_FREQ_44100 | A2DP_AAC_SAMPLING_FREQ_48000,
+ // channelMode
+ A2DP_AAC_CHANNEL_MODE_MONO | A2DP_AAC_CHANNEL_MODE_STEREO,
+ // variableBitRateSupport
+ A2DP_AAC_VARIABLE_BIT_RATE_ENABLED,
+ // bitRate
+ A2DP_AAC_DEFAULT_BITRATE,
+ // bits_per_sample
+ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16};
+
/* Default AAC codec configuration */
static const tA2DP_AAC_CIE a2dp_aac_default_config = {
A2DP_AAC_OBJECT_TYPE_MPEG2_LC, // objectType
@@ -85,9 +101,14 @@
nullptr // set_transmit_queue_length
};
+static const tA2DP_DECODER_INTERFACE a2dp_decoder_interface_aac = {
+ a2dp_aac_decoder_init, a2dp_aac_decoder_cleanup,
+ a2dp_aac_decoder_decode_packet,
+};
+
UNUSED_ATTR static tA2DP_STATUS A2DP_CodecInfoMatchesCapabilityAac(
const tA2DP_AAC_CIE* p_cap, const uint8_t* p_codec_info,
- bool is_peer_codec_info);
+ bool is_capability);
// Builds the AAC Media Codec Capabilities byte sequence beginning from the
// LOSC octet. |media_type| is the media type |AVDT_MEDIA_TYPE_*|.
@@ -191,11 +212,19 @@
}
bool A2DP_IsSinkCodecValidAac(UNUSED_ATTR const uint8_t* p_codec_info) {
- return false;
+ tA2DP_AAC_CIE cfg_cie;
+
+ /* Use a liberal check when parsing the codec info */
+ return (A2DP_ParseInfoAac(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) ||
+ (A2DP_ParseInfoAac(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS);
}
bool A2DP_IsPeerSourceCodecValidAac(UNUSED_ATTR const uint8_t* p_codec_info) {
- return false;
+ tA2DP_AAC_CIE cfg_cie;
+
+ /* Use a liberal check when parsing the codec info */
+ return (A2DP_ParseInfoAac(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) ||
+ (A2DP_ParseInfoAac(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS);
}
bool A2DP_IsPeerSinkCodecValidAac(const uint8_t* p_codec_info) {
@@ -206,27 +235,20 @@
(A2DP_ParseInfoAac(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS);
}
-bool A2DP_IsSinkCodecSupportedAac(UNUSED_ATTR const uint8_t* p_codec_info) {
- return false;
+bool A2DP_IsSinkCodecSupportedAac(const uint8_t* p_codec_info) {
+ return A2DP_CodecInfoMatchesCapabilityAac(&a2dp_aac_sink_caps, p_codec_info,
+ false) == A2DP_SUCCESS;
}
-bool A2DP_IsPeerSourceCodecSupportedAac(
- UNUSED_ATTR const uint8_t* p_codec_info) {
- return false;
-}
-
-tA2DP_STATUS A2DP_BuildSrc2SinkConfigAac(UNUSED_ATTR const uint8_t* p_src_cap,
- UNUSED_ATTR uint8_t* p_pref_cfg) {
- return A2DP_NS_CODEC_TYPE;
+bool A2DP_IsPeerSourceCodecSupportedAac(const uint8_t* p_codec_info) {
+ return A2DP_CodecInfoMatchesCapabilityAac(&a2dp_aac_sink_caps, p_codec_info,
+ true) == A2DP_SUCCESS;
}
// Checks whether A2DP AAC codec configuration matches with a device's codec
// capabilities. |p_cap| is the AAC codec configuration. |p_codec_info| is
-// the device's codec capabilities.
-// If |is_capability| is true, the byte sequence is codec capabilities,
-// otherwise is codec configuration.
-// |p_codec_info| contains the codec capabilities for a peer device that
-// is acting as an A2DP source.
+// the device's codec capabilities. |is_capability| is true if
+// |p_codec_info| contains A2DP codec capability.
// Returns A2DP_SUCCESS if the codec configuration matches with capabilities,
// otherwise the corresponding A2DP error status code.
static tA2DP_STATUS A2DP_CodecInfoMatchesCapabilityAac(
@@ -390,13 +412,24 @@
return -1;
}
-int A2DP_GetSinkTrackChannelTypeAac(UNUSED_ATTR const uint8_t* p_codec_info) {
- return -1;
-}
+int A2DP_GetSinkTrackChannelTypeAac(const uint8_t* p_codec_info) {
+ tA2DP_AAC_CIE aac_cie;
-int A2DP_GetSinkFramesCountToProcessAac(
- UNUSED_ATTR uint64_t time_interval_ms,
- UNUSED_ATTR const uint8_t* p_codec_info) {
+ // Check whether the codec info contains valid data
+ tA2DP_STATUS a2dp_status = A2DP_ParseInfoAac(&aac_cie, p_codec_info, false);
+ if (a2dp_status != A2DP_SUCCESS) {
+ LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__,
+ a2dp_status);
+ return -1;
+ }
+
+ switch (aac_cie.channelMode) {
+ case A2DP_AAC_CHANNEL_MODE_MONO:
+ return 1;
+ case A2DP_AAC_CHANNEL_MODE_STEREO:
+ return 3;
+ }
+
return -1;
}
@@ -529,84 +562,82 @@
return true;
}
-bool A2DP_DumpCodecInfoAac(const uint8_t* p_codec_info) {
+std::string A2DP_CodecInfoStringAac(const uint8_t* p_codec_info) {
+ std::stringstream res;
+ std::string field;
tA2DP_STATUS a2dp_status;
tA2DP_AAC_CIE aac_cie;
- LOG_VERBOSE(LOG_TAG, "%s", __func__);
-
a2dp_status = A2DP_ParseInfoAac(&aac_cie, p_codec_info, true);
if (a2dp_status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: A2DP_ParseInfoAac fail:%d", __func__, a2dp_status);
- return false;
+ res << "A2DP_ParseInfoAac fail: " << loghex(a2dp_status);
+ return res.str();
}
- LOG_VERBOSE(LOG_TAG, "\tobjectType: 0x%x", aac_cie.objectType);
- if (aac_cie.objectType & A2DP_AAC_OBJECT_TYPE_MPEG2_LC) {
- LOG_VERBOSE(LOG_TAG, "\tobjectType: (MPEG-2 AAC LC)");
- }
- if (aac_cie.objectType & A2DP_AAC_OBJECT_TYPE_MPEG4_LC) {
- LOG_VERBOSE(LOG_TAG, "\tobjectType: (MPEG-4 AAC LC)");
- }
- if (aac_cie.objectType & A2DP_AAC_OBJECT_TYPE_MPEG4_LTP) {
- LOG_VERBOSE(LOG_TAG, "\tobjectType: (MPEG-4 AAC LTP)");
- }
- if (aac_cie.objectType & A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE) {
- LOG_VERBOSE(LOG_TAG, "\tobjectType: (MPEG-4 AAC Scalable)");
- }
+ res << "\tname: AAC\n";
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: 0x%x", aac_cie.sampleRate);
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_8000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (8000)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_11025) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (11025)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_12000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (12000)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_16000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (16000)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_22050) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (22050)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_24000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (24000)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_32000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (32000)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (44100)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (48000)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_64000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (64000)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (88200)");
- }
- if (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (96000)");
- }
+ // Object type
+ field.clear();
+ AppendField(&field, (aac_cie.objectType == 0), "NONE");
+ AppendField(&field, (aac_cie.objectType & A2DP_AAC_OBJECT_TYPE_MPEG2_LC),
+ "(MPEG-2 AAC LC)");
+ AppendField(&field, (aac_cie.objectType & A2DP_AAC_OBJECT_TYPE_MPEG4_LC),
+ "(MPEG-4 AAC LC)");
+ AppendField(&field, (aac_cie.objectType & A2DP_AAC_OBJECT_TYPE_MPEG4_LTP),
+ "(MPEG-4 AAC LTP)");
+ AppendField(&field,
+ (aac_cie.objectType & A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE),
+ "(MPEG-4 AAC Scalable)");
+ res << "\tobjectType: " << field << " (" << loghex(aac_cie.objectType)
+ << ")\n";
- LOG_VERBOSE(LOG_TAG, "\tch_mode: 0x%x", aac_cie.channelMode);
- if (aac_cie.channelMode == A2DP_AAC_CHANNEL_MODE_MONO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Mono)");
- }
- if (aac_cie.channelMode == A2DP_AAC_CHANNEL_MODE_STEREO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Stereo)");
- }
+ // Sample frequency
+ field.clear();
+ AppendField(&field, (aac_cie.sampleRate == 0), "NONE");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_8000),
+ "8000");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_11025),
+ "11025");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_12000),
+ "12000");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_16000),
+ "16000");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_22050),
+ "22050");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_24000),
+ "24000");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_32000),
+ "32000");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100),
+ "44100");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_48000),
+ "48000");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_64000),
+ "64000");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_88200),
+ "88200");
+ AppendField(&field, (aac_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_96000),
+ "96000");
+ res << "\tsamp_freq: " << field << " (" << loghex(aac_cie.sampleRate)
+ << ")\n";
- LOG_VERBOSE(LOG_TAG, "\tvariableBitRateSupport: %s",
- (aac_cie.variableBitRateSupport != 0) ? "true" : "false");
+ // Channel mode
+ field.clear();
+ AppendField(&field, (aac_cie.channelMode == 0), "NONE");
+ AppendField(&field, (aac_cie.channelMode == A2DP_AAC_CHANNEL_MODE_MONO),
+ "Mono");
+ AppendField(&field, (aac_cie.channelMode == A2DP_AAC_CHANNEL_MODE_STEREO),
+ "Stereo");
+ res << "\tch_mode: " << field << " (" << loghex(aac_cie.channelMode) << ")\n";
- LOG_VERBOSE(LOG_TAG, "\tbitRate: %u", aac_cie.bitRate);
+ // Variable bit rate support
+ res << "\tvariableBitRateSupport: " << std::boolalpha
+ << (aac_cie.variableBitRateSupport != 0) << "\n";
- return true;
+ // Bit rate
+ res << "\tbitRate: " << std::to_string(aac_cie.bitRate) << "\n";
+
+ return res.str();
}
const tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterfaceAac(
@@ -616,6 +647,13 @@
return &a2dp_encoder_interface_aac;
}
+const tA2DP_DECODER_INTERFACE* A2DP_GetDecoderInterfaceAac(
+ const uint8_t* p_codec_info) {
+ if (!A2DP_IsSinkCodecValidAac(p_codec_info)) return NULL;
+
+ return &a2dp_decoder_interface_aac;
+}
+
bool A2DP_AdjustCodecAac(uint8_t* p_codec_info) {
tA2DP_AAC_CIE cfg_cie;
@@ -631,10 +669,17 @@
return BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
}
+btav_a2dp_codec_index_t A2DP_SinkCodecIndexAac(
+ UNUSED_ATTR const uint8_t* p_codec_info) {
+ return BTAV_A2DP_CODEC_INDEX_SINK_AAC;
+}
+
const char* A2DP_CodecIndexStrAac(void) { return "AAC"; }
-bool A2DP_InitCodecConfigAac(tAVDT_CFG* p_cfg) {
- if (A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aac_caps,
+const char* A2DP_CodecIndexStrAacSink(void) { return "AAC SINK"; }
+
+bool A2DP_InitCodecConfigAac(AvdtpSepConfig* p_cfg) {
+ if (A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aac_source_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
}
@@ -650,6 +695,11 @@
return true;
}
+bool A2DP_InitCodecConfigAacSink(AvdtpSepConfig* p_cfg) {
+ return A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aac_sink_caps,
+ p_cfg->codec_info) == A2DP_SUCCESS;
+}
+
UNUSED_ATTR static void build_codec_config(const tA2DP_AAC_CIE& config_cie,
btav_a2dp_codec_config_t* result) {
if (config_cie.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100)
@@ -670,34 +720,36 @@
}
}
-A2dpCodecConfigAac::A2dpCodecConfigAac(
+A2dpCodecConfigAacSource::A2dpCodecConfigAacSource(
btav_a2dp_codec_priority_t codec_priority)
- : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, "AAC", codec_priority) {
+ : A2dpCodecConfigAacBase(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC,
+ A2DP_CodecIndexStrAac(), codec_priority, true) {
// Compute the local capability
- if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) {
+ if (a2dp_aac_source_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
}
- if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) {
+ if (a2dp_aac_source_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
}
- if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) {
+ if (a2dp_aac_source_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
}
- if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) {
+ if (a2dp_aac_source_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
}
- codec_local_capability_.bits_per_sample = a2dp_aac_caps.bits_per_sample;
- if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_MONO) {
+ codec_local_capability_.bits_per_sample =
+ a2dp_aac_source_caps.bits_per_sample;
+ if (a2dp_aac_source_caps.channelMode & A2DP_AAC_CHANNEL_MODE_MONO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
}
- if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) {
+ if (a2dp_aac_source_caps.channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
}
-A2dpCodecConfigAac::~A2dpCodecConfigAac() {}
+A2dpCodecConfigAacSource::~A2dpCodecConfigAacSource() {}
-bool A2dpCodecConfigAac::init() {
+bool A2dpCodecConfigAacSource::init() {
if (!isValid()) return false;
// Load the encoder
@@ -709,7 +761,7 @@
return true;
}
-bool A2dpCodecConfigAac::useRtpHeaderMarkerBit() const { return true; }
+bool A2dpCodecConfigAacSource::useRtpHeaderMarkerBit() const { return true; }
//
// Selects the best sample rate from |sampleRate|.
@@ -782,6 +834,8 @@
break;
case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
break;
}
@@ -905,15 +959,17 @@
return false;
}
-bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info,
- bool is_capability,
- uint8_t* p_result_codec_config) {
+bool A2dpCodecConfigAacBase::setCodecConfig(const uint8_t* p_peer_codec_info,
+ bool is_capability,
+ uint8_t* p_result_codec_config) {
std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
- tA2DP_AAC_CIE sink_info_cie;
+ tA2DP_AAC_CIE peer_info_cie;
tA2DP_AAC_CIE result_config_cie;
uint8_t channelMode;
uint16_t sampleRate;
btav_a2dp_codec_bits_per_sample_t bits_per_sample;
+ const tA2DP_AAC_CIE* p_a2dp_aac_caps =
+ (is_source_) ? &a2dp_aac_source_caps : &a2dp_aac_sink_caps;
// Save the internal state
btav_a2dp_codec_config_t saved_codec_config = codec_config_;
@@ -932,9 +988,9 @@
sizeof(ota_codec_peer_config_));
tA2DP_STATUS status =
- A2DP_ParseInfoAac(&sink_info_cie, p_peer_codec_info, is_capability);
+ A2DP_ParseInfoAac(&peer_info_cie, p_peer_codec_info, is_capability);
if (status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: can't parse peer's Sink capabilities: error = %d",
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
__func__, status);
goto fail;
}
@@ -945,31 +1001,33 @@
memset(&result_config_cie, 0, sizeof(result_config_cie));
// NOTE: Always assign the Object Type and Variable Bit Rate Support.
- result_config_cie.objectType = a2dp_aac_caps.objectType;
+ result_config_cie.objectType = p_a2dp_aac_caps->objectType;
+ // The Variable Bit Rate Support is disabled if either side disables it
result_config_cie.variableBitRateSupport =
- a2dp_aac_caps.variableBitRateSupport;
+ p_a2dp_aac_caps->variableBitRateSupport &
+ peer_info_cie.variableBitRateSupport;
// Set the bit rate as follows:
- // 1. If the Sink device reports a bogus bit rate
+ // 1. If the remote device reports a bogus bit rate
// (bitRate < A2DP_AAC_MIN_BITRATE), then use the bit rate from our
// configuration. Examples of observed bogus bit rates are zero
// and 24576.
- // 2. If the Sink device reports valid bit rate
+ // 2. If the remote device reports valid bit rate
// (bitRate >= A2DP_AAC_MIN_BITRATE), then use the smaller
- // of the Sink device's bit rate and the bit rate from our configuration.
+ // of the remote device's bit rate and the bit rate from our configuration.
// In either case, the actual streaming bit rate will also consider the MTU.
- if (sink_info_cie.bitRate < A2DP_AAC_MIN_BITRATE) {
+ if (peer_info_cie.bitRate < A2DP_AAC_MIN_BITRATE) {
// Bogus bit rate
- result_config_cie.bitRate = a2dp_aac_caps.bitRate;
+ result_config_cie.bitRate = p_a2dp_aac_caps->bitRate;
} else {
result_config_cie.bitRate =
- std::min(a2dp_aac_caps.bitRate, sink_info_cie.bitRate);
+ std::min(p_a2dp_aac_caps->bitRate, peer_info_cie.bitRate);
}
//
// Select the sample frequency
//
- sampleRate = a2dp_aac_caps.sampleRate & sink_info_cie.sampleRate;
+ sampleRate = p_a2dp_aac_caps->sampleRate & peer_info_cie.sampleRate;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
switch (codec_user_config_.sample_rate) {
case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
@@ -1002,6 +1060,8 @@
break;
case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
codec_capability_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
@@ -1048,7 +1108,7 @@
// No user preference - try the default config
if (select_best_sample_rate(
- a2dp_aac_default_config.sampleRate & sink_info_cie.sampleRate,
+ a2dp_aac_default_config.sampleRate & peer_info_cie.sampleRate,
&result_config_cie, &codec_config_)) {
break;
}
@@ -1062,8 +1122,8 @@
if (codec_config_.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) {
LOG_ERROR(LOG_TAG,
"%s: cannot match sample frequency: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_aac_caps.sampleRate, sink_info_cie.sampleRate);
+ "peer info = 0x%x",
+ __func__, p_a2dp_aac_caps->sampleRate, peer_info_cie.sampleRate);
goto fail;
}
@@ -1072,7 +1132,7 @@
//
// NOTE: this information is NOT included in the AAC A2DP codec description
// that is sent OTA.
- bits_per_sample = a2dp_aac_caps.bits_per_sample;
+ bits_per_sample = p_a2dp_aac_caps->bits_per_sample;
codec_config_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE;
switch (codec_user_config_.bits_per_sample) {
case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
@@ -1107,7 +1167,7 @@
do {
// Compute the selectable capability
codec_selectable_capability_.bits_per_sample =
- a2dp_aac_caps.bits_per_sample;
+ p_a2dp_aac_caps->bits_per_sample;
if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
break;
@@ -1117,7 +1177,7 @@
// No user preference - the the codec audio config
if (select_audio_bits_per_sample(&codec_audio_config_,
- a2dp_aac_caps.bits_per_sample,
+ p_a2dp_aac_caps->bits_per_sample,
&result_config_cie, &codec_config_)) {
break;
}
@@ -1129,7 +1189,7 @@
}
// No user preference - use the best match
- if (select_best_bits_per_sample(a2dp_aac_caps.bits_per_sample,
+ if (select_best_bits_per_sample(p_a2dp_aac_caps->bits_per_sample,
&result_config_cie, &codec_config_)) {
break;
}
@@ -1146,7 +1206,7 @@
//
// Select the channel mode
//
- channelMode = a2dp_aac_caps.channelMode & sink_info_cie.channelMode;
+ channelMode = p_a2dp_aac_caps->channelMode & peer_info_cie.channelMode;
codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
switch (codec_user_config_.channel_mode) {
case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
@@ -1198,7 +1258,7 @@
// No user preference - try the default config
if (select_best_channel_mode(
- a2dp_aac_default_config.channelMode & sink_info_cie.channelMode,
+ a2dp_aac_default_config.channelMode & peer_info_cie.channelMode,
&result_config_cie, &codec_config_)) {
break;
}
@@ -1212,8 +1272,9 @@
if (codec_config_.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) {
LOG_ERROR(LOG_TAG,
"%s: cannot match channel mode: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_aac_caps.channelMode, sink_info_cie.channelMode);
+ "peer info = 0x%x",
+ __func__, p_a2dp_aac_caps->channelMode,
+ peer_info_cie.channelMode);
goto fail;
}
@@ -1234,13 +1295,13 @@
if (codec_user_config_.codec_specific_4 != 0)
codec_config_.codec_specific_4 = codec_user_config_.codec_specific_4;
- // Create a local copy of the peer codec capability, and the
+ // Create a local copy of the peer codec capability/config, and the
// result codec config.
if (is_capability) {
- status = A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie,
+ status = A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
ota_codec_peer_capability_);
} else {
- status = A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie,
+ status = A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
ota_codec_peer_config_);
}
CHECK(status == A2DP_SUCCESS);
@@ -1263,3 +1324,116 @@
sizeof(ota_codec_peer_config_));
return false;
}
+bool A2dpCodecConfigAacBase::setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+ tA2DP_AAC_CIE peer_info_cie;
+ uint8_t channelMode;
+ uint16_t sampleRate;
+ const tA2DP_AAC_CIE* p_a2dp_aac_caps =
+ (is_source_) ? &a2dp_aac_source_caps : &a2dp_aac_sink_caps;
+
+ // Save the internal state
+ btav_a2dp_codec_config_t saved_codec_selectable_capability =
+ codec_selectable_capability_;
+ uint8_t saved_ota_codec_peer_capability[AVDT_CODEC_SIZE];
+ memcpy(saved_ota_codec_peer_capability, ota_codec_peer_capability_,
+ sizeof(ota_codec_peer_capability_));
+
+ tA2DP_STATUS status =
+ A2DP_ParseInfoAac(&peer_info_cie, p_peer_codec_capabilities, true);
+ if (status != A2DP_SUCCESS) {
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
+ __func__, status);
+ goto fail;
+ }
+
+ // Compute the selectable capability - sample rate
+ sampleRate = p_a2dp_aac_caps->sampleRate & peer_info_cie.sampleRate;
+ if (sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+ }
+ if (sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+ }
+ if (sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
+ }
+ if (sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
+ }
+
+ // Compute the selectable capability - bits per sample
+ codec_selectable_capability_.bits_per_sample =
+ p_a2dp_aac_caps->bits_per_sample;
+
+ // Compute the selectable capability - channel mode
+ channelMode = p_a2dp_aac_caps->channelMode & peer_info_cie.channelMode;
+ if (channelMode & A2DP_AAC_CHANNEL_MODE_MONO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+ }
+ if (channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
+
+ status = A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
+ ota_codec_peer_capability_);
+ CHECK(status == A2DP_SUCCESS);
+ return true;
+
+fail:
+ // Restore the internal state
+ codec_selectable_capability_ = saved_codec_selectable_capability;
+ memcpy(ota_codec_peer_capability_, saved_ota_codec_peer_capability,
+ sizeof(ota_codec_peer_capability_));
+ return false;
+}
+
+A2dpCodecConfigAacSink::A2dpCodecConfigAacSink(
+ btav_a2dp_codec_priority_t codec_priority)
+ : A2dpCodecConfigAacBase(BTAV_A2DP_CODEC_INDEX_SINK_AAC,
+ A2DP_CodecIndexStrAacSink(), codec_priority,
+ false) {}
+
+A2dpCodecConfigAacSink::~A2dpCodecConfigAacSink() {}
+
+bool A2dpCodecConfigAacSink::init() {
+ if (!isValid()) return false;
+
+ // Load the decoder
+ if (!A2DP_LoadDecoderAac()) {
+ LOG_ERROR(LOG_TAG, "%s: cannot load the decoder", __func__);
+ return false;
+ }
+
+ return true;
+}
+
+period_ms_t A2dpCodecConfigAacSink::encoderIntervalMs() const {
+ // TODO: This method applies only to Source codecs
+ return 0;
+}
+
+int A2dpCodecConfigAacSink::getEffectiveMtu() const {
+ // TODO: This method applies only to Source codecs
+ return 0;
+}
+
+bool A2dpCodecConfigAacSink::useRtpHeaderMarkerBit() const {
+ // TODO: This method applies only to Source codecs
+ return false;
+}
+
+bool A2dpCodecConfigAacSink::updateEncoderUserConfig(
+ UNUSED_ATTR const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
+ UNUSED_ATTR bool* p_restart_input, UNUSED_ATTR bool* p_restart_output,
+ UNUSED_ATTR bool* p_config_updated) {
+ // TODO: This method applies only to Source codecs
+ return false;
+}
diff --git a/stack/a2dp/a2dp_aac_decoder.cc b/stack/a2dp/a2dp_aac_decoder.cc
new file mode 100644
index 0000000..d9cd85d
--- /dev/null
+++ b/stack/a2dp/a2dp_aac_decoder.cc
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "a2dp_aac_decoder"
+
+#include "a2dp_aac_decoder.h"
+
+#include <aacdecoder_lib.h>
+#include <base/logging.h>
+
+#include "a2dp_aac.h"
+#include "osi/include/allocator.h"
+#include "osi/include/log.h"
+
+#define DECODE_BUF_LEN (8 * 2 * 1024)
+
+typedef struct {
+ HANDLE_AACDECODER aac_handle;
+ bool has_aac_handle; // True if aac_handle is valid
+ INT_PCM* decode_buf;
+ decoded_data_callback_t decode_callback;
+} tA2DP_AAC_DECODER_CB;
+
+static tA2DP_AAC_DECODER_CB a2dp_aac_decoder_cb;
+
+bool A2DP_LoadDecoderAac(void) {
+ // Nothing to do - the library is statically linked
+ return true;
+}
+
+void A2DP_UnloadDecoderAac(void) { a2dp_aac_decoder_cleanup(); }
+
+bool a2dp_aac_decoder_init(decoded_data_callback_t decode_callback) {
+ a2dp_aac_decoder_cleanup();
+
+ a2dp_aac_decoder_cb.aac_handle =
+ aacDecoder_Open(TT_MP4_LATM_MCP1, 1 /* nrOfLayers */);
+ a2dp_aac_decoder_cb.has_aac_handle = true;
+ a2dp_aac_decoder_cb.decode_buf = static_cast<INT_PCM*>(
+ osi_malloc(sizeof(a2dp_aac_decoder_cb.decode_buf[0]) * DECODE_BUF_LEN));
+ a2dp_aac_decoder_cb.decode_callback = decode_callback;
+ return true;
+}
+
+void a2dp_aac_decoder_cleanup(void) {
+ if (a2dp_aac_decoder_cb.has_aac_handle)
+ aacDecoder_Close(a2dp_aac_decoder_cb.aac_handle);
+ free(a2dp_aac_decoder_cb.decode_buf);
+ memset(&a2dp_aac_decoder_cb, 0, sizeof(a2dp_aac_decoder_cb));
+}
+
+bool a2dp_aac_decoder_decode_packet(BT_HDR* p_buf) {
+ auto* pBuffer = reinterpret_cast<UCHAR*>(p_buf->data + p_buf->offset);
+ UINT bufferSize = p_buf->len;
+ UINT bytesValid = p_buf->len;
+ while (bytesValid > 0) {
+ AAC_DECODER_ERROR err = aacDecoder_Fill(a2dp_aac_decoder_cb.aac_handle,
+ &pBuffer, &bufferSize, &bytesValid);
+ if (err != AAC_DEC_OK) {
+ LOG_ERROR(LOG_TAG, "%s: aacDecoder_Fill failed: 0x%x", __func__,
+ static_cast<unsigned>(err));
+ return false;
+ }
+
+ while (true) {
+ err = aacDecoder_DecodeFrame(a2dp_aac_decoder_cb.aac_handle,
+ a2dp_aac_decoder_cb.decode_buf,
+ DECODE_BUF_LEN, 0 /* flags */);
+ if (err == AAC_DEC_NOT_ENOUGH_BITS) {
+ break;
+ }
+ if (err != AAC_DEC_OK) {
+ LOG_ERROR(LOG_TAG, "%s: aacDecoder_DecodeFrame failed: 0x%x", __func__,
+ static_cast<int>(err));
+ break;
+ }
+
+ CStreamInfo* info =
+ aacDecoder_GetStreamInfo(a2dp_aac_decoder_cb.aac_handle);
+ if (!info || info->sampleRate <= 0) {
+ LOG_ERROR(LOG_TAG, "%s: Invalid stream info", __func__);
+ break;
+ }
+
+ size_t frame_len = info->frameSize * info->numChannels *
+ sizeof(a2dp_aac_decoder_cb.decode_buf[0]);
+ a2dp_aac_decoder_cb.decode_callback(
+ reinterpret_cast<uint8_t*>(a2dp_aac_decoder_cb.decode_buf),
+ frame_len);
+ }
+ }
+
+ return true;
+}
diff --git a/stack/a2dp/a2dp_aac_encoder.cc b/stack/a2dp/a2dp_aac_encoder.cc
index 6c79149..43b6181 100644
--- a/stack/a2dp/a2dp_aac_encoder.cc
+++ b/stack/a2dp/a2dp_aac_encoder.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -109,7 +109,7 @@
uint8_t* num_of_frames,
uint64_t timestamp_us);
static void a2dp_aac_encode_frames(uint8_t nb_frame);
-static bool a2dp_aac_read_feeding(uint8_t* read_buffer);
+static bool a2dp_aac_read_feeding(uint8_t* read_buffer, uint32_t* bytes_read);
bool A2DP_LoadEncoderAac(void) {
// Nothing to do - the library is statically linked
@@ -154,7 +154,7 @@
&restart_input, &restart_output, &config_updated);
}
-bool A2dpCodecConfigAac::updateEncoderUserConfig(
+bool A2dpCodecConfigAacSource::updateEncoderUserConfig(
const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params, bool* p_restart_input,
bool* p_restart_output, bool* p_config_updated) {
a2dp_aac_encoder_cb.is_peer_edr = p_peer_params->is_peer_edr;
@@ -222,6 +222,7 @@
LOG_DEBUG(LOG_TAG, "%s: sample_rate=%u bits_per_sample=%u channel_count=%u",
__func__, p_feeding_params->sample_rate,
p_feeding_params->bits_per_sample, p_feeding_params->channel_count);
+ a2dp_aac_feeding_reset();
// The codec parameters
p_encoder_params->sample_rate =
@@ -587,6 +588,7 @@
.numOutBytes = 0, .numInSamples = 0, .numAncBytes = 0};
uint32_t count;
+ uint32_t total_bytes_read = 0;
int written = 0;
while (nb_frame) {
@@ -601,7 +603,8 @@
//
// Read the PCM data and encode it
//
- if (a2dp_aac_read_feeding(read_buffer)) {
+ uint32_t bytes_read = 0;
+ if (a2dp_aac_read_feeding(read_buffer, &bytes_read)) {
uint8_t* packet = (uint8_t*)(p_buf + 1) + p_buf->offset + p_buf->len;
if (!a2dp_aac_encoder_cb.has_aac_handle) {
LOG_ERROR(LOG_TAG, "%s: invalid AAC handle", __func__);
@@ -636,6 +639,7 @@
// no more pcm to read
nb_frame = 0;
}
+ total_bytes_read += bytes_read;
} while ((written == 0) && nb_frame);
// NOTE: We don't check whether the packet will fit in the MTU,
@@ -654,7 +658,9 @@
uint8_t done_nb_frame = remain_nb_frame - nb_frame;
remain_nb_frame = nb_frame;
- if (!a2dp_aac_encoder_cb.enqueue_callback(p_buf, done_nb_frame)) return;
+ if (!a2dp_aac_encoder_cb.enqueue_callback(p_buf, done_nb_frame,
+ total_bytes_read))
+ return;
} else {
a2dp_aac_encoder_cb.stats.media_read_total_dropped_packets++;
osi_free(p_buf);
@@ -662,7 +668,7 @@
}
}
-static bool a2dp_aac_read_feeding(uint8_t* read_buffer) {
+static bool a2dp_aac_read_feeding(uint8_t* read_buffer, uint32_t* bytes_read) {
uint32_t read_size = a2dp_aac_encoder_cb.aac_encoder_params.frame_length *
a2dp_aac_encoder_cb.feeding_params.channel_count *
a2dp_aac_encoder_cb.feeding_params.bits_per_sample / 8;
@@ -674,6 +680,7 @@
uint32_t nb_byte_read =
a2dp_aac_encoder_cb.read_callback(read_buffer, read_size);
a2dp_aac_encoder_cb.stats.media_read_total_actual_read_bytes += nb_byte_read;
+ *bytes_read = nb_byte_read;
if (nb_byte_read < read_size) {
if (nb_byte_read == 0) return false;
@@ -687,11 +694,15 @@
return true;
}
-period_ms_t A2dpCodecConfigAac::encoderIntervalMs() const {
+period_ms_t A2dpCodecConfigAacSource::encoderIntervalMs() const {
return a2dp_aac_get_encoder_interval_ms();
}
-void A2dpCodecConfigAac::debug_codec_dump(int fd) {
+int A2dpCodecConfigAacSource::getEffectiveMtu() const {
+ return a2dp_aac_encoder_cb.TxAaMtuSize;
+}
+
+void A2dpCodecConfigAacSource::debug_codec_dump(int fd) {
a2dp_aac_encoder_stats_t* stats = &a2dp_aac_encoder_cb.stats;
A2dpCodecConfig::debug_codec_dump(fd);
diff --git a/stack/a2dp/a2dp_api.cc b/stack/a2dp/a2dp_api.cc
index 4be2bdd..cc7d01e 100644
--- a/stack/a2dp/a2dp_api.cc
+++ b/stack/a2dp/a2dp_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,8 @@
#include "osi/include/log.h"
#include "sdpdefs.h"
+using bluetooth::Uuid;
+
/*****************************************************************************
* Global data
****************************************************************************/
@@ -66,8 +68,9 @@
bool found = false;
tA2DP_Service a2dp_svc;
tSDP_PROTOCOL_ELEM elem;
+ RawAddress peer_address = RawAddress::kEmpty;
- LOG_VERBOSE(LOG_TAG, "%s: status: %d", __func__, status);
+ LOG_INFO(LOG_TAG, "%s: status: %d", __func__, status);
if (status == SDP_SUCCESS) {
/* loop through all records we found */
@@ -78,6 +81,7 @@
break;
}
memset(&a2dp_svc, 0, sizeof(tA2DP_Service));
+ peer_address = p_rec->remote_bd_addr;
/* get service name */
if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) !=
@@ -116,7 +120,7 @@
osi_free_and_reset((void**)&a2dp_cb.find.p_db);
/* return info from sdp record in app callback function */
if (a2dp_cb.find.p_cback != NULL) {
- (*a2dp_cb.find.p_cback)(found, &a2dp_svc);
+ (*a2dp_cb.find.p_cback)(found, &a2dp_svc, peer_address);
}
return;
@@ -269,22 +273,26 @@
tA2DP_STATUS A2DP_FindService(uint16_t service_uuid, const RawAddress& bd_addr,
tA2DP_SDP_DB_PARAMS* p_db,
tA2DP_FIND_CBACK* p_cback) {
- tSDP_UUID uuid_list;
bool result = true;
- LOG_VERBOSE(LOG_TAG, "%s: uuid: 0x%x", __func__, service_uuid);
+ LOG_INFO(LOG_TAG, "%s: peer: %s UUID: 0x%x", __func__,
+ bd_addr.ToString().c_str(), service_uuid);
if ((service_uuid != UUID_SERVCLASS_AUDIO_SOURCE &&
service_uuid != UUID_SERVCLASS_AUDIO_SINK) ||
- p_db == NULL || p_cback == NULL)
+ p_db == NULL || p_cback == NULL) {
+ LOG_ERROR(LOG_TAG,
+ "%s: cannot find service for peer %s UUID 0x%x: "
+ "invalid parameters",
+ __func__, bd_addr.ToString().c_str(), service_uuid);
return A2DP_INVALID_PARAMS;
+ }
if (a2dp_cb.find.service_uuid == UUID_SERVCLASS_AUDIO_SOURCE ||
- a2dp_cb.find.service_uuid == UUID_SERVCLASS_AUDIO_SINK)
+ a2dp_cb.find.service_uuid == UUID_SERVCLASS_AUDIO_SINK) {
+ LOG_ERROR(LOG_TAG, "%s: cannot find service for peer %s UUID 0x%x: busy",
+ __func__, bd_addr.ToString().c_str(), service_uuid);
return A2DP_BUSY;
-
- /* set up discovery database */
- uuid_list.len = LEN_UUID_16;
- uuid_list.uu.uuid16 = service_uuid;
+ }
if (p_db->p_attrs == NULL || p_db->num_attr == 0) {
p_db->p_attrs = a2dp_attr_list;
@@ -294,10 +302,11 @@
if (a2dp_cb.find.p_db == NULL)
a2dp_cb.find.p_db = (tSDP_DISCOVERY_DB*)osi_malloc(p_db->db_len);
+ Uuid uuid_list = Uuid::From16Bit(service_uuid);
result = SDP_InitDiscoveryDb(a2dp_cb.find.p_db, p_db->db_len, 1, &uuid_list,
p_db->num_attr, p_db->p_attrs);
- if (result == true) {
+ if (result) {
/* store service_uuid */
a2dp_cb.find.service_uuid = service_uuid;
a2dp_cb.find.p_cback = p_cback;
@@ -305,12 +314,19 @@
/* perform service search */
result = SDP_ServiceSearchAttributeRequest(bd_addr, a2dp_cb.find.p_db,
a2dp_sdp_cback);
- if (false == result) {
+ if (!result) {
a2dp_cb.find.service_uuid = 0;
}
}
+ if (!result) {
+ LOG_ERROR(LOG_TAG,
+ "%s: cannot find service for peer %s UUID 0x%x: "
+ "SDP error",
+ __func__, bd_addr.ToString().c_str(), service_uuid);
+ return A2DP_FAIL;
+ }
- return (result ? A2DP_SUCCESS : A2DP_FAIL);
+ return A2DP_SUCCESS;
}
/******************************************************************************
diff --git a/stack/a2dp/a2dp_codec_config.cc b/stack/a2dp/a2dp_codec_config.cc
index 0bf5985..47856fe 100644
--- a/stack/a2dp/a2dp_codec_config.cc
+++ b/stack/a2dp/a2dp_codec_config.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,15 +31,21 @@
#include "a2dp_vendor_aptx.h"
#include "a2dp_vendor_aptx_hd.h"
#include "a2dp_vendor_ldac.h"
+#include "bta/av/bta_av_int.h"
#include "osi/include/log.h"
+#include "osi/include/properties.h"
/* The Media Type offset within the codec info byte array */
#define A2DP_MEDIA_TYPE_OFFSET 1
+/* A2DP Offload enabled in stack */
+static bool a2dp_offload_status;
+
// Initializes the codec config.
// |codec_config| is the codec config to initialize.
// |codec_index| and |codec_priority| are the codec type and priority to use
// for the initialization.
+
static void init_btav_a2dp_codec_config(
btav_a2dp_codec_config_t* codec_config, btav_a2dp_codec_index_t codec_index,
btav_a2dp_codec_priority_t codec_priority) {
@@ -83,6 +89,7 @@
} else {
codec_priority_ = codec_priority;
}
+ codec_config_.codec_priority = codec_priority_;
}
void A2dpCodecConfig::setDefaultCodecPriority() {
@@ -93,6 +100,7 @@
uint32_t priority = 1000 * (codec_index_ + 1) + 1;
codec_priority_ = static_cast<btav_a2dp_codec_priority_t>(priority);
}
+ codec_config_.codec_priority = codec_priority_;
}
A2dpCodecConfig* A2dpCodecConfig::createCodec(
@@ -103,13 +111,16 @@
A2dpCodecConfig* codec_config = nullptr;
switch (codec_index) {
case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
- codec_config = new A2dpCodecConfigSbc(codec_priority);
+ codec_config = new A2dpCodecConfigSbcSource(codec_priority);
break;
case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
codec_config = new A2dpCodecConfigSbcSink(codec_priority);
break;
case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
- codec_config = new A2dpCodecConfigAac(codec_priority);
+ codec_config = new A2dpCodecConfigAacSource(codec_priority);
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
+ codec_config = new A2dpCodecConfigAacSink(codec_priority);
break;
case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
codec_config = new A2dpCodecConfigAptx(codec_priority);
@@ -120,7 +131,6 @@
case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
codec_config = new A2dpCodecConfigLdac(codec_priority);
break;
- // Add a switch statement for each vendor-specific codec
case BTAV_A2DP_CODEC_INDEX_MAX:
break;
}
@@ -135,6 +145,96 @@
return codec_config;
}
+int A2dpCodecConfig::getTrackBitRate() const {
+ uint8_t p_codec_info[AVDT_CODEC_SIZE];
+ memcpy(p_codec_info, ota_codec_config_, sizeof(ota_codec_config_));
+ tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
+
+ LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
+
+ switch (codec_type) {
+ case A2DP_MEDIA_CT_SBC:
+ return A2DP_GetBitrateSbc();
+ case A2DP_MEDIA_CT_AAC:
+ return A2DP_GetBitRateAac(p_codec_info);
+ case A2DP_MEDIA_CT_NON_A2DP:
+ return A2DP_VendorGetBitRate(p_codec_info);
+ default:
+ break;
+ }
+
+ LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
+ return -1;
+}
+
+bool A2dpCodecConfig::getCodecSpecificConfig(tBT_A2DP_OFFLOAD* p_a2dp_offload) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+
+ uint8_t codec_config[AVDT_CODEC_SIZE];
+ uint32_t vendor_id;
+ uint16_t codec_id;
+
+ memset(p_a2dp_offload->codec_info, 0, sizeof(p_a2dp_offload->codec_info));
+
+ if (!A2DP_IsSourceCodecValid(ota_codec_config_)) {
+ return false;
+ }
+
+ memcpy(codec_config, ota_codec_config_, sizeof(ota_codec_config_));
+ tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(codec_config);
+ switch (codec_type) {
+ case A2DP_MEDIA_CT_SBC:
+ p_a2dp_offload->codec_info[0] =
+ codec_config[4]; // blk_len | subbands | Alloc Method
+ p_a2dp_offload->codec_info[1] = codec_config[5]; // Min bit pool
+ p_a2dp_offload->codec_info[2] = codec_config[6]; // Max bit pool
+ break;
+ case A2DP_MEDIA_CT_AAC:
+ p_a2dp_offload->codec_info[0] = codec_config[3]; // object type
+ p_a2dp_offload->codec_info[1] = codec_config[6]; // VBR | BR
+ break;
+ case A2DP_MEDIA_CT_NON_A2DP:
+ vendor_id = A2DP_VendorCodecGetVendorId(codec_config);
+ codec_id = A2DP_VendorCodecGetCodecId(codec_config);
+ p_a2dp_offload->codec_info[0] = (vendor_id & 0x000000FF);
+ p_a2dp_offload->codec_info[1] = (vendor_id & 0x0000FF00) >> 8;
+ p_a2dp_offload->codec_info[2] = (vendor_id & 0x00FF0000) >> 16;
+ p_a2dp_offload->codec_info[3] = (vendor_id & 0xFF000000) >> 24;
+ p_a2dp_offload->codec_info[4] = (codec_id & 0x000000FF);
+ p_a2dp_offload->codec_info[5] = (codec_id & 0x0000FF00) >> 8;
+ if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+ if (codec_config_.codec_specific_1 == 0) { // default is 0, ABR
+ p_a2dp_offload->codec_info[6] =
+ A2DP_LDAC_QUALITY_ABR_OFFLOAD; // ABR in offload
+ } else {
+ switch (codec_config_.codec_specific_1 % 10) {
+ case 0:
+ p_a2dp_offload->codec_info[6] =
+ A2DP_LDAC_QUALITY_HIGH; // High bitrate
+ break;
+ case 1:
+ p_a2dp_offload->codec_info[6] =
+ A2DP_LDAC_QUALITY_MID; // Mid birate
+ break;
+ case 2:
+ p_a2dp_offload->codec_info[6] =
+ A2DP_LDAC_QUALITY_LOW; // Low birate
+ break;
+ case 3: // fall through
+ default:
+ p_a2dp_offload->codec_info[6] =
+ A2DP_LDAC_QUALITY_ABR_OFFLOAD; // ABR in offload
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
bool A2dpCodecConfig::isValid() const { return true; }
bool A2dpCodecConfig::copyOutOtaCodecConfig(uint8_t* p_codec_info) {
@@ -271,12 +371,15 @@
bool encoder_restart_input = *p_restart_input;
bool encoder_restart_output = *p_restart_output;
bool encoder_config_updated = *p_config_updated;
- if (updateEncoderUserConfig(p_peer_params, &encoder_restart_input,
- &encoder_restart_output,
- &encoder_config_updated)) {
- if (encoder_restart_input) *p_restart_input = true;
- if (encoder_restart_output) *p_restart_output = true;
- if (encoder_config_updated) *p_config_updated = true;
+
+ if (!a2dp_offload_status) {
+ if (updateEncoderUserConfig(p_peer_params, &encoder_restart_input,
+ &encoder_restart_output,
+ &encoder_config_updated)) {
+ if (encoder_restart_input) *p_restart_input = true;
+ if (encoder_restart_output) *p_restart_output = true;
+ if (encoder_config_updated) *p_config_updated = true;
+ }
}
if (*p_restart_input || *p_restart_output) *p_config_updated = true;
@@ -396,6 +499,7 @@
dprintf(fd, "\nA2DP %s State:\n", name().c_str());
dprintf(fd, " Priority: %d\n", codecPriority());
dprintf(fd, " Encoder interval (ms): %" PRIu64 "\n", encoderIntervalMs());
+ dprintf(fd, " Effective MTU: %d\n", getEffectiveMtu());
result = codecConfig2Str(getCodecConfig());
dprintf(fd, " Config: %s\n", result.c_str());
@@ -443,6 +547,41 @@
bool A2dpCodecs::init() {
LOG_DEBUG(LOG_TAG, "%s", __func__);
std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+ char* tok = NULL;
+ char* tmp_token = NULL;
+ bool offload_codec_support[BTAV_A2DP_CODEC_INDEX_MAX] = {false};
+ char value_sup[PROPERTY_VALUE_MAX], value_dis[PROPERTY_VALUE_MAX];
+
+ osi_property_get("ro.bluetooth.a2dp_offload.supported", value_sup, "false");
+ osi_property_get("persist.bluetooth.a2dp_offload.disabled", value_dis,
+ "false");
+ a2dp_offload_status =
+ (strcmp(value_sup, "true") == 0) && (strcmp(value_dis, "false") == 0);
+
+ if (a2dp_offload_status) {
+ char value_cap[PROPERTY_VALUE_MAX];
+ osi_property_get("persist.bluetooth.a2dp_offload.cap", value_cap, "");
+ tok = strtok_r((char*)value_cap, "-", &tmp_token);
+ while (tok != NULL) {
+ if (strcmp(tok, "sbc") == 0) {
+ LOG_INFO(LOG_TAG, "%s: SBC offload supported", __func__);
+ offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_SBC] = true;
+ } else if (strcmp(tok, "aac") == 0) {
+ LOG_INFO(LOG_TAG, "%s: AAC offload supported", __func__);
+ offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_AAC] = true;
+ } else if (strcmp(tok, "aptx") == 0) {
+ LOG_INFO(LOG_TAG, "%s: APTX offload supported", __func__);
+ offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_APTX] = true;
+ } else if (strcmp(tok, "aptxhd") == 0) {
+ LOG_INFO(LOG_TAG, "%s: APTXHD offload supported", __func__);
+ offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD] = true;
+ } else if (strcmp(tok, "ldac") == 0) {
+ LOG_INFO(LOG_TAG, "%s: LDAC offload supported", __func__);
+ offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC] = true;
+ }
+ tok = strtok_r(NULL, "-", &tmp_token);
+ };
+ }
for (int i = BTAV_A2DP_CODEC_INDEX_MIN; i < BTAV_A2DP_CODEC_INDEX_MAX; i++) {
btav_a2dp_codec_index_t codec_index =
@@ -456,6 +595,12 @@
codec_priority = cp_iter->second;
}
+ // In offload mode, disable the codecs based on the property
+ if ((codec_index < BTAV_A2DP_CODEC_INDEX_SOURCE_MAX) &&
+ a2dp_offload_status && (offload_codec_support[i] != true)) {
+ codec_priority = BTAV_A2DP_CODEC_PRIORITY_DISABLED;
+ }
+
A2dpCodecConfig* codec_config =
A2dpCodecConfig::createCodec(codec_index, codec_priority);
if (codec_config == nullptr) continue;
@@ -513,6 +658,16 @@
return iter->second;
}
+A2dpCodecConfig* A2dpCodecs::findSinkCodecConfig(const uint8_t* p_codec_info) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+ btav_a2dp_codec_index_t codec_index = A2DP_SinkCodecIndex(p_codec_info);
+ if (codec_index == BTAV_A2DP_CODEC_INDEX_MAX) return nullptr;
+
+ auto iter = indexed_codecs_.find(codec_index);
+ if (iter == indexed_codecs_.end()) return nullptr;
+ return iter->second;
+}
+
bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info,
bool is_capability,
uint8_t* p_result_codec_config,
@@ -530,6 +685,23 @@
return true;
}
+bool A2dpCodecs::setSinkCodecConfig(const uint8_t* p_peer_codec_info,
+ bool is_capability,
+ uint8_t* p_result_codec_config,
+ bool select_current_codec) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+ A2dpCodecConfig* a2dp_codec_config = findSinkCodecConfig(p_peer_codec_info);
+ if (a2dp_codec_config == nullptr) return false;
+ if (!a2dp_codec_config->setCodecConfig(p_peer_codec_info, is_capability,
+ p_result_codec_config)) {
+ return false;
+ }
+ if (select_current_codec) {
+ current_codec_config_ = a2dp_codec_config;
+ }
+ return true;
+}
+
bool A2dpCodecs::setCodecUserConfig(
const btav_a2dp_codec_config_t& codec_user_config,
const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
@@ -543,22 +715,8 @@
*p_restart_output = false;
*p_config_updated = false;
- LOG_DEBUG(
- LOG_TAG,
- "%s: Configuring: codec_type=%d codec_priority=%d "
- "sample_rate=0x%x bits_per_sample=0x%x "
- "channel_mode=0x%x codec_specific_1=%" PRIi64
- " "
- "codec_specific_2=%" PRIi64
- " "
- "codec_specific_3=%" PRIi64
- " "
- "codec_specific_4=%" PRIi64,
- __func__, codec_user_config.codec_type, codec_user_config.codec_priority,
- codec_user_config.sample_rate, codec_user_config.bits_per_sample,
- codec_user_config.channel_mode, codec_user_config.codec_specific_1,
- codec_user_config.codec_specific_2, codec_user_config.codec_specific_3,
- codec_user_config.codec_specific_4);
+ LOG_DEBUG(LOG_TAG, "%s: Configuring: %s", __func__,
+ codec_user_config.ToString().c_str());
if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) {
auto iter = indexed_codecs_.find(codec_user_config.codec_type);
@@ -593,6 +751,7 @@
// Check if there was no previous codec
if (last_codec_config == nullptr) {
current_codec_config_ = a2dp_codec_config;
+ *p_restart_input = true;
*p_restart_output = true;
break;
}
@@ -628,6 +787,7 @@
// connection to select a new codec.
current_codec_config_ = a2dp_codec_config;
last_codec_config->setDefaultCodecPriority();
+ *p_restart_input = true;
*p_restart_output = true;
}
} while (false);
@@ -755,6 +915,28 @@
return false;
}
+bool A2dpCodecs::setPeerSinkCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+
+ if (!A2DP_IsPeerSinkCodecValid(p_peer_codec_capabilities)) return false;
+ A2dpCodecConfig* a2dp_codec_config =
+ findSourceCodecConfig(p_peer_codec_capabilities);
+ if (a2dp_codec_config == nullptr) return false;
+ return a2dp_codec_config->setPeerCodecCapabilities(p_peer_codec_capabilities);
+}
+
+bool A2dpCodecs::setPeerSourceCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+
+ if (!A2DP_IsPeerSourceCodecValid(p_peer_codec_capabilities)) return false;
+ A2dpCodecConfig* a2dp_codec_config =
+ findSinkCodecConfig(p_peer_codec_capabilities);
+ if (a2dp_codec_config == nullptr) return false;
+ return a2dp_codec_config->setPeerCodecCapabilities(p_peer_codec_capabilities);
+}
+
bool A2dpCodecs::getCodecConfigAndCapabilities(
btav_a2dp_codec_config_t* p_codec_config,
std::vector<btav_a2dp_codec_config_t>* p_codecs_local_capabilities,
@@ -934,27 +1116,6 @@
A2DP_InitDefaultCodecSbc(p_codec_info);
}
-tA2DP_STATUS A2DP_BuildSrc2SinkConfig(const uint8_t* p_src_cap,
- uint8_t* p_pref_cfg) {
- tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_src_cap);
-
- LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
-
- switch (codec_type) {
- case A2DP_MEDIA_CT_SBC:
- return A2DP_BuildSrc2SinkConfigSbc(p_src_cap, p_pref_cfg);
- case A2DP_MEDIA_CT_AAC:
- return A2DP_BuildSrc2SinkConfigAac(p_src_cap, p_pref_cfg);
- case A2DP_MEDIA_CT_NON_A2DP:
- return A2DP_VendorBuildSrc2SinkConfig(p_src_cap, p_pref_cfg);
- default:
- break;
- }
-
- LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
- return A2DP_NS_CODEC_TYPE;
-}
-
bool A2DP_UsesRtpHeader(bool content_protection_enabled,
const uint8_t* p_codec_info) {
tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
@@ -1093,30 +1254,6 @@
return -1;
}
-int A2DP_GetSinkFramesCountToProcess(uint64_t time_interval_ms,
- const uint8_t* p_codec_info) {
- tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
-
- LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
-
- switch (codec_type) {
- case A2DP_MEDIA_CT_SBC:
- return A2DP_GetSinkFramesCountToProcessSbc(time_interval_ms,
- p_codec_info);
- case A2DP_MEDIA_CT_AAC:
- return A2DP_GetSinkFramesCountToProcessAac(time_interval_ms,
- p_codec_info);
- case A2DP_MEDIA_CT_NON_A2DP:
- return A2DP_VendorGetSinkFramesCountToProcess(time_interval_ms,
- p_codec_info);
- default:
- break;
- }
-
- LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
- return -1;
-}
-
bool A2DP_GetPacketTimestamp(const uint8_t* p_codec_info, const uint8_t* p_data,
uint32_t* p_timestamp) {
tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
@@ -1177,6 +1314,27 @@
return NULL;
}
+const tA2DP_DECODER_INTERFACE* A2DP_GetDecoderInterface(
+ const uint8_t* p_codec_info) {
+ tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
+
+ LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
+
+ switch (codec_type) {
+ case A2DP_MEDIA_CT_SBC:
+ return A2DP_GetDecoderInterfaceSbc(p_codec_info);
+ case A2DP_MEDIA_CT_AAC:
+ return A2DP_GetDecoderInterfaceAac(p_codec_info);
+ case A2DP_MEDIA_CT_NON_A2DP:
+ return A2DP_VendorGetDecoderInterface(p_codec_info);
+ default:
+ break;
+ }
+
+ LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
+ return NULL;
+}
+
bool A2DP_AdjustCodec(uint8_t* p_codec_info) {
tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
@@ -1215,6 +1373,26 @@
return BTAV_A2DP_CODEC_INDEX_MAX;
}
+btav_a2dp_codec_index_t A2DP_SinkCodecIndex(const uint8_t* p_codec_info) {
+ tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
+
+ LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
+
+ switch (codec_type) {
+ case A2DP_MEDIA_CT_SBC:
+ return A2DP_SinkCodecIndexSbc(p_codec_info);
+ case A2DP_MEDIA_CT_AAC:
+ return A2DP_SinkCodecIndexAac(p_codec_info);
+ case A2DP_MEDIA_CT_NON_A2DP:
+ return A2DP_VendorSinkCodecIndex(p_codec_info);
+ default:
+ break;
+ }
+
+ LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
+ return BTAV_A2DP_CODEC_INDEX_MAX;
+}
+
const char* A2DP_CodecIndexStr(btav_a2dp_codec_index_t codec_index) {
switch (codec_index) {
case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
@@ -1223,6 +1401,8 @@
return A2DP_CodecIndexStrSbcSink();
case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
return A2DP_CodecIndexStrAac();
+ case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
+ return A2DP_CodecIndexStrAacSink();
default:
break;
}
@@ -1234,7 +1414,7 @@
}
bool A2DP_InitCodecConfig(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg) {
+ AvdtpSepConfig* p_cfg) {
LOG_VERBOSE(LOG_TAG, "%s: codec %s", __func__,
A2DP_CodecIndexStr(codec_index));
@@ -1249,6 +1429,8 @@
return A2DP_InitCodecConfigSbcSink(p_cfg);
case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
return A2DP_InitCodecConfigAac(p_cfg);
+ case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
+ return A2DP_InitCodecConfigAacSink(p_cfg);
default:
break;
}
@@ -1259,22 +1441,19 @@
return false;
}
-bool A2DP_DumpCodecInfo(const uint8_t* p_codec_info) {
+std::string A2DP_CodecInfoString(const uint8_t* p_codec_info) {
tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
- LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
-
switch (codec_type) {
case A2DP_MEDIA_CT_SBC:
- return A2DP_DumpCodecInfoSbc(p_codec_info);
+ return A2DP_CodecInfoStringSbc(p_codec_info);
case A2DP_MEDIA_CT_AAC:
- return A2DP_DumpCodecInfoAac(p_codec_info);
+ return A2DP_CodecInfoStringAac(p_codec_info);
case A2DP_MEDIA_CT_NON_A2DP:
- return A2DP_VendorDumpCodecInfo(p_codec_info);
+ return A2DP_VendorCodecInfoString(p_codec_info);
default:
break;
}
- LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
- return false;
+ return "Unsupported codec type: " + loghex(codec_type);
}
diff --git a/stack/a2dp/a2dp_int.h b/stack/a2dp/a2dp_int.h
index 6fb4543..708f908 100644
--- a/stack/a2dp/a2dp_int.h
+++ b/stack/a2dp/a2dp_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
/*****************************************************************************
* Constants
****************************************************************************/
-#define A2DP_VERSION 0x0102
+#define A2DP_VERSION 0x0103
/* Number of attributes in A2DP SDP record. */
#define A2DP_NUM_ATTR 6
diff --git a/stack/a2dp/a2dp_sbc.cc b/stack/a2dp/a2dp_sbc.cc
index cfdaad4..bef5bf9 100644
--- a/stack/a2dp/a2dp_sbc.cc
+++ b/stack/a2dp/a2dp_sbc.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
#include <string.h>
#include <base/logging.h>
+#include "a2dp_sbc_decoder.h"
#include "a2dp_sbc_encoder.h"
#include "bt_utils.h"
#include "embdrv/sbc/encoder/include/sbc_encoder.h"
@@ -52,9 +53,9 @@
btav_a2dp_codec_bits_per_sample_t bits_per_sample;
} tA2DP_SBC_CIE;
-/* SBC SRC codec capabilities */
-static const tA2DP_SBC_CIE a2dp_sbc_caps = {
- A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */
+/* SBC Source codec capabilities */
+static const tA2DP_SBC_CIE a2dp_sbc_source_caps = {
+ (A2DP_SBC_IE_SAMP_FREQ_44), /* samp_freq */
(A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_JOINT), /* ch_mode */
(A2DP_SBC_IE_BLOCKS_16 | A2DP_SBC_IE_BLOCKS_12 | A2DP_SBC_IE_BLOCKS_8 |
A2DP_SBC_IE_BLOCKS_4), /* block_len */
@@ -65,7 +66,7 @@
BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */
};
-/* SBC SINK codec capabilities */
+/* SBC Sink codec capabilities */
static const tA2DP_SBC_CIE a2dp_sbc_sink_caps = {
(A2DP_SBC_IE_SAMP_FREQ_48 | A2DP_SBC_IE_SAMP_FREQ_44), /* samp_freq */
(A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_STEREO |
@@ -101,6 +102,11 @@
nullptr // set_transmit_queue_length
};
+static const tA2DP_DECODER_INTERFACE a2dp_decoder_interface_sbc = {
+ a2dp_sbc_decoder_init, a2dp_sbc_decoder_cleanup,
+ a2dp_sbc_decoder_decode_packet,
+};
+
static tA2DP_STATUS A2DP_CodecInfoMatchesCapabilitySbc(
const tA2DP_SBC_CIE* p_cap, const uint8_t* p_codec_info,
bool is_capability);
@@ -375,64 +381,6 @@
return A2DP_SUCCESS;
}
-tA2DP_STATUS A2DP_BuildSrc2SinkConfigSbc(const uint8_t* p_src_cap,
- uint8_t* p_pref_cfg) {
- tA2DP_SBC_CIE src_cap;
- tA2DP_SBC_CIE pref_cap;
-
- /* initialize it to default SBC configuration */
- A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_default_config,
- p_pref_cfg);
-
- /* now try to build a preferred one */
- /* parse configuration */
- tA2DP_STATUS status = A2DP_ParseInfoSbc(&src_cap, p_src_cap, true);
- if (status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: can't parse src cap ret = %d", __func__, status);
- return A2DP_FAIL;
- }
-
- if (src_cap.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48)
- pref_cap.samp_freq = A2DP_SBC_IE_SAMP_FREQ_48;
- else if (src_cap.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44)
- pref_cap.samp_freq = A2DP_SBC_IE_SAMP_FREQ_44;
-
- if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_JOINT)
- pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_JOINT;
- else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_STEREO)
- pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_STEREO;
- else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_DUAL)
- pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_DUAL;
- else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_MONO)
- pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_MONO;
-
- if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_16)
- pref_cap.block_len = A2DP_SBC_IE_BLOCKS_16;
- else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_12)
- pref_cap.block_len = A2DP_SBC_IE_BLOCKS_12;
- else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_8)
- pref_cap.block_len = A2DP_SBC_IE_BLOCKS_8;
- else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_4)
- pref_cap.block_len = A2DP_SBC_IE_BLOCKS_4;
-
- if (src_cap.num_subbands & A2DP_SBC_IE_SUBBAND_8)
- pref_cap.num_subbands = A2DP_SBC_IE_SUBBAND_8;
- else if (src_cap.num_subbands & A2DP_SBC_IE_SUBBAND_4)
- pref_cap.num_subbands = A2DP_SBC_IE_SUBBAND_4;
-
- if (src_cap.alloc_method & A2DP_SBC_IE_ALLOC_MD_L)
- pref_cap.alloc_method = A2DP_SBC_IE_ALLOC_MD_L;
- else if (src_cap.alloc_method & A2DP_SBC_IE_ALLOC_MD_S)
- pref_cap.alloc_method = A2DP_SBC_IE_ALLOC_MD_S;
-
- pref_cap.min_bitpool = src_cap.min_bitpool;
- pref_cap.max_bitpool = src_cap.max_bitpool;
-
- A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &pref_cap, p_pref_cfg);
-
- return A2DP_SUCCESS;
-}
-
bool A2DP_CodecTypeEqualsSbc(const uint8_t* p_codec_info_a,
const uint8_t* p_codec_info_b) {
tA2DP_SBC_CIE sbc_cie_a;
@@ -692,6 +640,7 @@
return sbc_cie.max_bitpool;
}
+uint32_t A2DP_GetBitrateSbc() { return a2dp_sbc_get_bitrate(); }
int A2DP_GetSinkTrackChannelTypeSbc(const uint8_t* p_codec_info) {
tA2DP_SBC_CIE sbc_cie;
@@ -716,138 +665,6 @@
return -1;
}
-int A2DP_GetSinkFramesCountToProcessSbc(uint64_t time_interval_ms,
- const uint8_t* p_codec_info) {
- tA2DP_SBC_CIE sbc_cie;
- uint32_t freq_multiple;
- uint32_t num_blocks;
- uint32_t num_subbands;
- int frames_to_process;
-
- tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false);
- if (a2dp_status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__,
- a2dp_status);
- return -1;
- }
-
- // Check the sample frequency
- switch (sbc_cie.samp_freq) {
- case A2DP_SBC_IE_SAMP_FREQ_16:
- LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (16000)", __func__,
- sbc_cie.samp_freq);
- freq_multiple = 16 * time_interval_ms;
- break;
- case A2DP_SBC_IE_SAMP_FREQ_32:
- LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (32000)", __func__,
- sbc_cie.samp_freq);
- freq_multiple = 32 * time_interval_ms;
- break;
- case A2DP_SBC_IE_SAMP_FREQ_44:
- LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (44100)", __func__,
- sbc_cie.samp_freq);
- freq_multiple = (441 * time_interval_ms) / 10;
- break;
- case A2DP_SBC_IE_SAMP_FREQ_48:
- LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (48000)", __func__,
- sbc_cie.samp_freq);
- freq_multiple = 48 * time_interval_ms;
- break;
- default:
- LOG_ERROR(LOG_TAG, "%s: unknown frequency: %d", __func__,
- sbc_cie.samp_freq);
- return -1;
- }
-
- // Check the channel mode
- switch (sbc_cie.ch_mode) {
- case A2DP_SBC_IE_CH_MD_MONO:
- LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (Mono)", __func__, sbc_cie.ch_mode);
- break;
- case A2DP_SBC_IE_CH_MD_DUAL:
- LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (DUAL)", __func__, sbc_cie.ch_mode);
- break;
- case A2DP_SBC_IE_CH_MD_STEREO:
- LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (STEREO)", __func__,
- sbc_cie.ch_mode);
- break;
- case A2DP_SBC_IE_CH_MD_JOINT:
- LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (JOINT)", __func__, sbc_cie.ch_mode);
- break;
- default:
- LOG_ERROR(LOG_TAG, "%s: unknown channel mode: %d", __func__,
- sbc_cie.ch_mode);
- return -1;
- }
-
- // Check the block length
- switch (sbc_cie.block_len) {
- case A2DP_SBC_IE_BLOCKS_4:
- LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (4)", __func__, sbc_cie.block_len);
- num_blocks = 4;
- break;
- case A2DP_SBC_IE_BLOCKS_8:
- LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (8)", __func__, sbc_cie.block_len);
- num_blocks = 8;
- break;
- case A2DP_SBC_IE_BLOCKS_12:
- LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (12)", __func__,
- sbc_cie.block_len);
- num_blocks = 12;
- break;
- case A2DP_SBC_IE_BLOCKS_16:
- LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (16)", __func__,
- sbc_cie.block_len);
- num_blocks = 16;
- break;
- default:
- LOG_ERROR(LOG_TAG, "%s: unknown block length: %d", __func__,
- sbc_cie.block_len);
- return -1;
- }
-
- // Check the number of sub-bands
- switch (sbc_cie.num_subbands) {
- case A2DP_SBC_IE_SUBBAND_4:
- LOG_VERBOSE(LOG_TAG, "%s: num_subbands:%d (4)", __func__,
- sbc_cie.num_subbands);
- num_subbands = 4;
- break;
- case A2DP_SBC_IE_SUBBAND_8:
- LOG_VERBOSE(LOG_TAG, "%s: num_subbands:%d (8)", __func__,
- sbc_cie.num_subbands);
- num_subbands = 8;
- break;
- default:
- LOG_ERROR(LOG_TAG, "%s: unknown number of subbands: %d", __func__,
- sbc_cie.num_subbands);
- return -1;
- }
-
- // Check the allocation method
- switch (sbc_cie.alloc_method) {
- case A2DP_SBC_IE_ALLOC_MD_S:
- LOG_VERBOSE(LOG_TAG, "%s: alloc_method:%d (SNR)", __func__,
- sbc_cie.alloc_method);
- break;
- case A2DP_SBC_IE_ALLOC_MD_L:
- LOG_VERBOSE(LOG_TAG, "%s: alloc_method:%d (Loudness)", __func__,
- sbc_cie.alloc_method);
- break;
- default:
- LOG_ERROR(LOG_TAG, "%s: unknown allocation method: %d", __func__,
- sbc_cie.alloc_method);
- return -1;
- }
-
- LOG_VERBOSE(LOG_TAG, "%s: Bit pool Min:%d Max:%d", __func__,
- sbc_cie.min_bitpool, sbc_cie.max_bitpool);
-
- frames_to_process = ((freq_multiple) / (num_blocks * num_subbands)) + 1;
-
- return frames_to_process;
-}
-
bool A2DP_GetPacketTimestampSbc(UNUSED_ATTR const uint8_t* p_codec_info,
const uint8_t* p_data, uint32_t* p_timestamp) {
*p_timestamp = *(const uint32_t*)p_data;
@@ -867,80 +684,69 @@
return true;
}
-bool A2DP_DumpCodecInfoSbc(const uint8_t* p_codec_info) {
+std::string A2DP_CodecInfoStringSbc(const uint8_t* p_codec_info) {
+ std::stringstream res;
+ std::string field;
tA2DP_STATUS a2dp_status;
tA2DP_SBC_CIE sbc_cie;
- LOG_VERBOSE(LOG_TAG, "%s", __func__);
-
a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true);
if (a2dp_status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: A2DP_ParseInfoSbc fail:%d", __func__, a2dp_status);
- return false;
+ res << "A2DP_ParseInfoSbc fail: " << loghex(a2dp_status);
+ return res.str();
}
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: 0x%x", sbc_cie.samp_freq);
- if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_16) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (16000)");
- }
- if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_32) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (32000)");
- }
- if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (44100)");
- }
- if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (48000)");
- }
+ res << "\tname: SBC\n";
- LOG_VERBOSE(LOG_TAG, "\tch_mode: 0x%x", sbc_cie.ch_mode);
- if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Mono)");
- }
- if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Dual)");
- }
- if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Stereo)");
- }
- if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Joint)");
- }
+ // Sample frequency
+ field.clear();
+ AppendField(&field, (sbc_cie.samp_freq == 0), "NONE");
+ AppendField(&field, (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_16), "16000");
+ AppendField(&field, (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_32), "32000");
+ AppendField(&field, (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44), "44100");
+ AppendField(&field, (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48), "48000");
+ res << "\tsamp_freq: " << field << " (" << loghex(sbc_cie.samp_freq) << ")\n";
- LOG_VERBOSE(LOG_TAG, "\tblock_len: 0x%x", sbc_cie.block_len);
- if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_4) {
- LOG_VERBOSE(LOG_TAG, "\tblock_len: (4)");
- }
- if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_8) {
- LOG_VERBOSE(LOG_TAG, "\tblock_len: (8)");
- }
- if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_12) {
- LOG_VERBOSE(LOG_TAG, "\tblock_len: (12)");
- }
- if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_16) {
- LOG_VERBOSE(LOG_TAG, "\tblock_len: (16)");
- }
+ // Channel mode
+ field.clear();
+ AppendField(&field, (sbc_cie.ch_mode == 0), "NONE");
+ AppendField(&field, (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO), "Mono");
+ AppendField(&field, (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_DUAL), "Dual");
+ AppendField(&field, (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_STEREO), "Stereo");
+ AppendField(&field, (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_JOINT), "Joint");
+ res << "\tch_mode: " << field << " (" << loghex(sbc_cie.ch_mode) << ")\n";
- LOG_VERBOSE(LOG_TAG, "\tnum_subbands: 0x%x", sbc_cie.num_subbands);
- if (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_4) {
- LOG_VERBOSE(LOG_TAG, "\tnum_subbands: (4)");
- }
- if (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_8) {
- LOG_VERBOSE(LOG_TAG, "\tnum_subbands: (8)");
- }
+ // Block length
+ field.clear();
+ AppendField(&field, (sbc_cie.block_len == 0), "NONE");
+ AppendField(&field, (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_4), "4");
+ AppendField(&field, (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_8), "8");
+ AppendField(&field, (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_12), "12");
+ AppendField(&field, (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_16), "16");
+ res << "\tblock_len: " << field << " (" << loghex(sbc_cie.block_len) << ")\n";
- LOG_VERBOSE(LOG_TAG, "\talloc_method: 0x%x)", sbc_cie.alloc_method);
- if (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_S) {
- LOG_VERBOSE(LOG_TAG, "\talloc_method: (SNR)");
- }
- if (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_L) {
- LOG_VERBOSE(LOG_TAG, "\talloc_method: (Loundess)");
- }
+ // Number of subbands
+ field.clear();
+ AppendField(&field, (sbc_cie.num_subbands == 0), "NONE");
+ AppendField(&field, (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_4), "4");
+ AppendField(&field, (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_8), "8");
+ res << "\tnum_subbands: " << field << " (" << loghex(sbc_cie.num_subbands)
+ << ")\n";
- LOG_VERBOSE(LOG_TAG, "\tBit pool Min:%d Max:%d", sbc_cie.min_bitpool,
- sbc_cie.max_bitpool);
+ // Allocation method
+ field.clear();
+ AppendField(&field, (sbc_cie.alloc_method == 0), "NONE");
+ AppendField(&field, (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_S), "SNR");
+ AppendField(&field, (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_L),
+ "Loundess");
+ res << "\talloc_method: " << field << " (" << loghex(sbc_cie.alloc_method)
+ << ")\n";
- return true;
+ // Min/max bitloop
+ res << "\tBit pool Min: " << std::to_string(sbc_cie.min_bitpool)
+ << " Max: " << std::to_string(sbc_cie.max_bitpool);
+
+ return res.str();
}
const tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterfaceSbc(
@@ -950,6 +756,13 @@
return &a2dp_encoder_interface_sbc;
}
+const tA2DP_DECODER_INTERFACE* A2DP_GetDecoderInterfaceSbc(
+ const uint8_t* p_codec_info) {
+ if (!A2DP_IsSinkCodecValidSbc(p_codec_info)) return NULL;
+
+ return &a2dp_decoder_interface_sbc;
+}
+
bool A2DP_AdjustCodecSbc(uint8_t* p_codec_info) {
tA2DP_SBC_CIE cfg_cie;
@@ -972,12 +785,17 @@
return BTAV_A2DP_CODEC_INDEX_SOURCE_SBC;
}
+btav_a2dp_codec_index_t A2DP_SinkCodecIndexSbc(
+ UNUSED_ATTR const uint8_t* p_codec_info) {
+ return BTAV_A2DP_CODEC_INDEX_SINK_SBC;
+}
+
const char* A2DP_CodecIndexStrSbc(void) { return "SBC"; }
const char* A2DP_CodecIndexStrSbcSink(void) { return "SBC SINK"; }
-bool A2DP_InitCodecConfigSbc(tAVDT_CFG* p_cfg) {
- if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_caps,
+bool A2DP_InitCodecConfigSbc(AvdtpSepConfig* p_cfg) {
+ if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_source_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
}
@@ -993,7 +811,7 @@
return true;
}
-bool A2DP_InitCodecConfigSbcSink(tAVDT_CFG* p_cfg) {
+bool A2DP_InitCodecConfigSbcSink(AvdtpSepConfig* p_cfg) {
if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_sink_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
@@ -1020,34 +838,36 @@
}
}
-A2dpCodecConfigSbc::A2dpCodecConfigSbc(
+A2dpCodecConfigSbcSource::A2dpCodecConfigSbcSource(
btav_a2dp_codec_priority_t codec_priority)
- : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC", codec_priority) {
+ : A2dpCodecConfigSbcBase(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC",
+ codec_priority, true) {
// Compute the local capability
- if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) {
+ if (a2dp_sbc_source_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
}
- if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) {
+ if (a2dp_sbc_source_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
}
- codec_local_capability_.bits_per_sample = a2dp_sbc_caps.bits_per_sample;
- if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
+ codec_local_capability_.bits_per_sample =
+ a2dp_sbc_source_caps.bits_per_sample;
+ if (a2dp_sbc_source_caps.ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
}
- if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) {
+ if (a2dp_sbc_source_caps.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
- if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) {
+ if (a2dp_sbc_source_caps.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
- if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
+ if (a2dp_sbc_source_caps.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
}
-A2dpCodecConfigSbc::~A2dpCodecConfigSbc() {}
+A2dpCodecConfigSbcSource::~A2dpCodecConfigSbcSource() {}
-bool A2dpCodecConfigSbc::init() {
+bool A2dpCodecConfigSbcSource::init() {
if (!isValid()) return false;
// Load the encoder
@@ -1059,7 +879,7 @@
return true;
}
-bool A2dpCodecConfigSbc::useRtpHeaderMarkerBit() const { return false; }
+bool A2dpCodecConfigSbcSource::useRtpHeaderMarkerBit() const { return false; }
//
// Selects the best sample rate from |samp_freq|.
@@ -1109,6 +929,8 @@
case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
break;
}
@@ -1218,17 +1040,19 @@
return false;
}
-bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info,
- bool is_capability,
- uint8_t* p_result_codec_config) {
+bool A2dpCodecConfigSbcBase::setCodecConfig(const uint8_t* p_peer_codec_info,
+ bool is_capability,
+ uint8_t* p_result_codec_config) {
std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
- tA2DP_SBC_CIE sink_info_cie;
+ tA2DP_SBC_CIE peer_info_cie;
tA2DP_SBC_CIE result_config_cie;
uint8_t samp_freq;
uint8_t ch_mode;
uint8_t block_len;
uint8_t num_subbands;
uint8_t alloc_method;
+ const tA2DP_SBC_CIE* p_a2dp_sbc_caps =
+ (is_source_) ? &a2dp_sbc_source_caps : &a2dp_sbc_sink_caps;
// Save the internal state
btav_a2dp_codec_config_t saved_codec_config = codec_config_;
@@ -1247,20 +1071,30 @@
sizeof(ota_codec_peer_config_));
tA2DP_STATUS status =
- A2DP_ParseInfoSbc(&sink_info_cie, p_peer_codec_info, is_capability);
+ A2DP_ParseInfoSbc(&peer_info_cie, p_peer_codec_info, is_capability);
if (status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: can't parse peer's Sink capabilities: error = %d",
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
__func__, status);
goto fail;
}
// Try using the prefered peer codec config (if valid), instead of the peer
// capability.
- if (is_capability && A2DP_IsPeerSinkCodecValidSbc(ota_codec_peer_config_)) {
- status = A2DP_ParseInfoSbc(&sink_info_cie, ota_codec_peer_config_, false);
+ if (is_capability) {
+ if (is_source_) {
+ if (A2DP_IsPeerSinkCodecValidSbc(ota_codec_peer_config_)) {
+ status =
+ A2DP_ParseInfoSbc(&peer_info_cie, ota_codec_peer_config_, false);
+ }
+ } else {
+ if (A2DP_IsPeerSourceCodecValidSbc(ota_codec_peer_config_)) {
+ status =
+ A2DP_ParseInfoSbc(&peer_info_cie, ota_codec_peer_config_, false);
+ }
+ }
if (status != A2DP_SUCCESS) {
// Use the peer codec capability
status =
- A2DP_ParseInfoSbc(&sink_info_cie, p_peer_codec_info, is_capability);
+ A2DP_ParseInfoSbc(&peer_info_cie, p_peer_codec_info, is_capability);
CHECK(status == A2DP_SUCCESS);
}
}
@@ -1273,7 +1107,7 @@
//
// Select the sample frequency
//
- samp_freq = a2dp_sbc_caps.samp_freq & sink_info_cie.samp_freq;
+ samp_freq = p_a2dp_sbc_caps->samp_freq & peer_info_cie.samp_freq;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
switch (codec_user_config_.sample_rate) {
case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
@@ -1294,6 +1128,8 @@
case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
codec_capability_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
@@ -1328,7 +1164,7 @@
// No user preference - try the default config
if (select_best_sample_rate(
- a2dp_sbc_default_config.samp_freq & sink_info_cie.samp_freq,
+ a2dp_sbc_default_config.samp_freq & peer_info_cie.samp_freq,
&result_config_cie, &codec_config_)) {
break;
}
@@ -1341,9 +1177,9 @@
} while (false);
if (codec_config_.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) {
LOG_ERROR(LOG_TAG,
- "%s: cannot match sample frequency: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_sbc_caps.samp_freq, sink_info_cie.samp_freq);
+ "%s: cannot match sample frequency: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, p_a2dp_sbc_caps->samp_freq, peer_info_cie.samp_freq);
goto fail;
}
@@ -1370,7 +1206,7 @@
do {
// Compute the selectable capability
codec_selectable_capability_.bits_per_sample =
- a2dp_sbc_caps.bits_per_sample;
+ p_a2dp_sbc_caps->bits_per_sample;
if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
break;
@@ -1404,7 +1240,7 @@
//
// Select the channel mode
//
- ch_mode = a2dp_sbc_caps.ch_mode & sink_info_cie.ch_mode;
+ ch_mode = p_a2dp_sbc_caps->ch_mode & peer_info_cie.ch_mode;
codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
switch (codec_user_config_.channel_mode) {
case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
@@ -1478,7 +1314,7 @@
// No user preference - try the default config
if (select_best_channel_mode(
- a2dp_sbc_default_config.ch_mode & sink_info_cie.ch_mode,
+ a2dp_sbc_default_config.ch_mode & peer_info_cie.ch_mode,
&result_config_cie, &codec_config_)) {
break;
}
@@ -1490,16 +1326,16 @@
} while (false);
if (codec_config_.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) {
LOG_ERROR(LOG_TAG,
- "%s: cannot match channel mode: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_sbc_caps.ch_mode, sink_info_cie.ch_mode);
+ "%s: cannot match channel mode: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, p_a2dp_sbc_caps->ch_mode, peer_info_cie.ch_mode);
goto fail;
}
//
// Select the block length
//
- block_len = a2dp_sbc_caps.block_len & sink_info_cie.block_len;
+ block_len = p_a2dp_sbc_caps->block_len & peer_info_cie.block_len;
if (block_len & A2DP_SBC_IE_BLOCKS_16) {
result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_16;
} else if (block_len & A2DP_SBC_IE_BLOCKS_12) {
@@ -1510,59 +1346,62 @@
result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_4;
} else {
LOG_ERROR(LOG_TAG,
- "%s: cannot match block length: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_sbc_caps.block_len, sink_info_cie.block_len);
+ "%s: cannot match block length: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, p_a2dp_sbc_caps->block_len, peer_info_cie.block_len);
goto fail;
}
//
// Select the number of sub-bands
//
- num_subbands = a2dp_sbc_caps.num_subbands & sink_info_cie.num_subbands;
+ num_subbands = p_a2dp_sbc_caps->num_subbands & peer_info_cie.num_subbands;
if (num_subbands & A2DP_SBC_IE_SUBBAND_8) {
result_config_cie.num_subbands = A2DP_SBC_IE_SUBBAND_8;
} else if (num_subbands & A2DP_SBC_IE_SUBBAND_4) {
result_config_cie.num_subbands = A2DP_SBC_IE_SUBBAND_4;
} else {
LOG_ERROR(LOG_TAG,
- "%s: cannot match number of sub-bands: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_sbc_caps.num_subbands, sink_info_cie.num_subbands);
+ "%s: cannot match number of sub-bands: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, p_a2dp_sbc_caps->num_subbands,
+ peer_info_cie.num_subbands);
goto fail;
}
//
// Select the allocation method
//
- alloc_method = a2dp_sbc_caps.alloc_method & sink_info_cie.alloc_method;
+ alloc_method = p_a2dp_sbc_caps->alloc_method & peer_info_cie.alloc_method;
if (alloc_method & A2DP_SBC_IE_ALLOC_MD_L) {
result_config_cie.alloc_method = A2DP_SBC_IE_ALLOC_MD_L;
} else if (alloc_method & A2DP_SBC_IE_ALLOC_MD_S) {
result_config_cie.alloc_method = A2DP_SBC_IE_ALLOC_MD_S;
} else {
LOG_ERROR(LOG_TAG,
- "%s: cannot match allocation method: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_sbc_caps.alloc_method, sink_info_cie.alloc_method);
+ "%s: cannot match allocation method: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, p_a2dp_sbc_caps->alloc_method,
+ peer_info_cie.alloc_method);
goto fail;
}
//
// Select the min/max bitpool
//
- result_config_cie.min_bitpool = a2dp_sbc_caps.min_bitpool;
- if (result_config_cie.min_bitpool < sink_info_cie.min_bitpool)
- result_config_cie.min_bitpool = sink_info_cie.min_bitpool;
- result_config_cie.max_bitpool = a2dp_sbc_caps.max_bitpool;
- if (result_config_cie.max_bitpool > sink_info_cie.max_bitpool)
- result_config_cie.max_bitpool = sink_info_cie.max_bitpool;
+ result_config_cie.min_bitpool = p_a2dp_sbc_caps->min_bitpool;
+ if (result_config_cie.min_bitpool < peer_info_cie.min_bitpool)
+ result_config_cie.min_bitpool = peer_info_cie.min_bitpool;
+ result_config_cie.max_bitpool = p_a2dp_sbc_caps->max_bitpool;
+ if (result_config_cie.max_bitpool > peer_info_cie.max_bitpool)
+ result_config_cie.max_bitpool = peer_info_cie.max_bitpool;
if (result_config_cie.min_bitpool > result_config_cie.max_bitpool) {
LOG_ERROR(LOG_TAG,
"%s: cannot match min/max bitpool: "
- "source caps min/max = 0x%x/0x%x sink info min/max = 0x%x/0x%x",
- __func__, a2dp_sbc_caps.min_bitpool, a2dp_sbc_caps.max_bitpool,
- sink_info_cie.min_bitpool, sink_info_cie.max_bitpool);
+ "local caps min/max = 0x%x/0x%x peer info min/max = 0x%x/0x%x",
+ __func__, p_a2dp_sbc_caps->min_bitpool,
+ p_a2dp_sbc_caps->max_bitpool, peer_info_cie.min_bitpool,
+ peer_info_cie.max_bitpool);
goto fail;
}
@@ -1586,12 +1425,13 @@
// Create a local copy of the peer codec capability/config, and the
// result codec config.
if (is_capability) {
- memcpy(ota_codec_peer_capability_, p_peer_codec_info,
- sizeof(ota_codec_peer_capability_));
+ status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
+ ota_codec_peer_capability_);
} else {
- memcpy(ota_codec_peer_config_, p_peer_codec_info,
- sizeof(ota_codec_peer_config_));
+ status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
+ ota_codec_peer_config_);
}
+ CHECK(status == A2DP_SUCCESS);
status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie,
ota_codec_config_);
CHECK(status == A2DP_SUCCESS);
@@ -1612,16 +1452,93 @@
return false;
}
+bool A2dpCodecConfigSbcBase::setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+ tA2DP_SBC_CIE peer_info_cie;
+ uint8_t samp_freq;
+ uint8_t ch_mode;
+ const tA2DP_SBC_CIE* p_a2dp_sbc_caps =
+ (is_source_) ? &a2dp_sbc_source_caps : &a2dp_sbc_sink_caps;
+
+ // Save the internal state
+ btav_a2dp_codec_config_t saved_codec_selectable_capability =
+ codec_selectable_capability_;
+ uint8_t saved_ota_codec_peer_capability[AVDT_CODEC_SIZE];
+ memcpy(saved_ota_codec_peer_capability, ota_codec_peer_capability_,
+ sizeof(ota_codec_peer_capability_));
+
+ tA2DP_STATUS status =
+ A2DP_ParseInfoSbc(&peer_info_cie, p_peer_codec_capabilities, true);
+ if (status != A2DP_SUCCESS) {
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
+ __func__, status);
+ goto fail;
+ }
+
+ // Compute the selectable capability - sample rate
+ samp_freq = p_a2dp_sbc_caps->samp_freq & peer_info_cie.samp_freq;
+ if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+ }
+ if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+ }
+
+ // Compute the selectable capability - bits per sample
+ codec_selectable_capability_.bits_per_sample =
+ p_a2dp_sbc_caps->bits_per_sample;
+
+ // Compute the selectable capability - channel mode
+ ch_mode = p_a2dp_sbc_caps->ch_mode & peer_info_cie.ch_mode;
+ if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+ }
+ if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
+ if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
+ if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
+
+ status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
+ ota_codec_peer_capability_);
+ CHECK(status == A2DP_SUCCESS);
+ return true;
+
+fail:
+ // Restore the internal state
+ codec_selectable_capability_ = saved_codec_selectable_capability;
+ memcpy(ota_codec_peer_capability_, saved_ota_codec_peer_capability,
+ sizeof(ota_codec_peer_capability_));
+ return false;
+}
+
A2dpCodecConfigSbcSink::A2dpCodecConfigSbcSink(
btav_a2dp_codec_priority_t codec_priority)
- : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SINK_SBC, "SBC(Sink)",
- codec_priority) {}
+ : A2dpCodecConfigSbcBase(BTAV_A2DP_CODEC_INDEX_SINK_SBC, "SBC(Sink)",
+ codec_priority, false) {}
A2dpCodecConfigSbcSink::~A2dpCodecConfigSbcSink() {}
bool A2dpCodecConfigSbcSink::init() {
if (!isValid()) return false;
+ // Load the decoder
+ if (!A2DP_LoadDecoderSbc()) {
+ LOG_ERROR(LOG_TAG, "%s: cannot load the decoder", __func__);
+ return false;
+ }
+
return true;
}
@@ -1630,14 +1547,6 @@
return false;
}
-bool A2dpCodecConfigSbcSink::setCodecConfig(
- UNUSED_ATTR const uint8_t* p_peer_codec_info,
- UNUSED_ATTR bool is_capability,
- UNUSED_ATTR uint8_t* p_result_codec_config) {
- // TODO: This method applies only to Source codecs
- return false;
-}
-
bool A2dpCodecConfigSbcSink::updateEncoderUserConfig(
UNUSED_ATTR const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
UNUSED_ATTR bool* p_restart_input, UNUSED_ATTR bool* p_restart_output,
@@ -1650,3 +1559,8 @@
// TODO: This method applies only to Source codecs
return 0;
}
+
+int A2dpCodecConfigSbcSink::getEffectiveMtu() const {
+ // TODO: This method applies only to Source codecs
+ return 0;
+}
diff --git a/stack/a2dp/a2dp_sbc_decoder.cc b/stack/a2dp/a2dp_sbc_decoder.cc
new file mode 100644
index 0000000..bc64513
--- /dev/null
+++ b/stack/a2dp/a2dp_sbc_decoder.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "a2dp_sbc_decoder"
+
+#include "a2dp_sbc_decoder.h"
+
+#include <base/logging.h>
+
+#include "embdrv/sbc/decoder/include/oi_codec_sbc.h"
+#include "embdrv/sbc/decoder/include/oi_status.h"
+#include "osi/include/log.h"
+
+typedef struct {
+ OI_CODEC_SBC_DECODER_CONTEXT decoder_context;
+ uint32_t context_data[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
+ int16_t decode_buf[15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS];
+ decoded_data_callback_t decode_callback;
+} tA2DP_SBC_DECODER_CB;
+
+static tA2DP_SBC_DECODER_CB a2dp_sbc_decoder_cb;
+
+bool A2DP_LoadDecoderSbc(void) {
+ // Nothing to do - the library is statically linked
+ return true;
+}
+
+void A2DP_UnloadDecoderSbc(void) { a2dp_sbc_decoder_cleanup(); }
+
+bool a2dp_sbc_decoder_init(decoded_data_callback_t decode_callback) {
+ OI_STATUS status = OI_CODEC_SBC_DecoderReset(
+ &a2dp_sbc_decoder_cb.decoder_context, a2dp_sbc_decoder_cb.context_data,
+ sizeof(a2dp_sbc_decoder_cb.context_data), 2, 2, false);
+ if (!OI_SUCCESS(status)) {
+ LOG_ERROR(LOG_TAG,
+ "%s: OI_CODEC_SBC_DecoderReset failed with error code %d",
+ __func__, status);
+ return false;
+ }
+
+ a2dp_sbc_decoder_cb.decode_callback = decode_callback;
+ return true;
+}
+
+void a2dp_sbc_decoder_cleanup(void) {
+ // Do nothing.
+}
+
+bool a2dp_sbc_decoder_decode_packet(BT_HDR* p_buf) {
+ uint8_t* data = p_buf->data + p_buf->offset;
+ size_t data_size = p_buf->len;
+
+ if (data_size == 0) {
+ LOG_ERROR(LOG_TAG, "%s: Empty packet", __func__);
+ return false;
+ }
+ size_t num_frames = data[0] & 0xf;
+ data += 1;
+ data_size -= 1;
+
+ const OI_BYTE* oi_data = data;
+ uint32_t oi_size = data_size;
+ size_t out_avail = sizeof(a2dp_sbc_decoder_cb.decode_buf);
+ int16_t* out_ptr = a2dp_sbc_decoder_cb.decode_buf;
+
+ for (size_t i = 0; i < num_frames; ++i) {
+ uint32_t out_size = out_avail;
+ OI_STATUS status =
+ OI_CODEC_SBC_DecodeFrame(&a2dp_sbc_decoder_cb.decoder_context, &oi_data,
+ &oi_size, out_ptr, &out_size);
+ if (!OI_SUCCESS(status)) {
+ LOG_ERROR(LOG_TAG, "%s: Decoding failure: %d", __func__, status);
+ return false;
+ }
+ out_avail -= out_size;
+ out_ptr += out_size / sizeof(*out_ptr);
+ }
+
+ size_t out_used =
+ (out_ptr - a2dp_sbc_decoder_cb.decode_buf) * sizeof(*out_ptr);
+ a2dp_sbc_decoder_cb.decode_callback(
+ reinterpret_cast<uint8_t*>(a2dp_sbc_decoder_cb.decode_buf), out_used);
+ return true;
+}
diff --git a/stack/a2dp/a2dp_sbc_encoder.cc b/stack/a2dp/a2dp_sbc_encoder.cc
index e4c2049..bd09989 100644
--- a/stack/a2dp/a2dp_sbc_encoder.cc
+++ b/stack/a2dp/a2dp_sbc_encoder.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -118,13 +118,13 @@
bool* p_restart_input,
bool* p_restart_output,
bool* p_config_updated);
-static bool a2dp_sbc_read_feeding(void);
+static bool a2dp_sbc_read_feeding(uint32_t* bytes);
static void a2dp_sbc_encode_frames(uint8_t nb_frame);
static void a2dp_sbc_get_num_frame_iteration(uint8_t* num_of_iterations,
uint8_t* num_of_frames,
uint64_t timestamp_us);
static uint8_t calculate_max_frames_per_packet(void);
-static uint16_t a2dp_sbc_source_rate(void);
+static uint16_t a2dp_sbc_source_rate();
static uint32_t a2dp_sbc_frame_length(void);
bool A2DP_LoadEncoderSbc(void) {
@@ -160,7 +160,7 @@
&restart_input, &restart_output, &config_updated);
}
-bool A2dpCodecConfigSbc::updateEncoderUserConfig(
+bool A2dpCodecConfigSbcSource::updateEncoderUserConfig(
const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params, bool* p_restart_input,
bool* p_restart_output, bool* p_config_updated) {
a2dp_sbc_encoder_cb.is_peer_edr = p_peer_params->is_peer_edr;
@@ -222,6 +222,7 @@
LOG_DEBUG(LOG_TAG, "%s: sample_rate=%u bits_per_sample=%u channel_count=%u",
__func__, p_feeding_params->sample_rate,
p_feeding_params->bits_per_sample, p_feeding_params->channel_count);
+ a2dp_sbc_feeding_reset();
// The codec parameters
p_encoder_params->s16ChannelMode = A2DP_GetChannelModeCodeSbc(p_codec_info);
@@ -368,7 +369,7 @@
LOG_DEBUG(LOG_TAG, "%s: final bit rate %d, final bit pool %d", __func__,
p_encoder_params->u16BitRate, p_encoder_params->s16BitPool);
- /* Reset entirely the SBC encoder */
+ /* Reset the SBC encoder */
SBC_Encoder_Init(&a2dp_sbc_encoder_cb.sbc_encoder_params);
a2dp_sbc_encoder_cb.tx_sbc_frames = calculate_max_frames_per_packet();
}
@@ -529,8 +530,11 @@
p_encoder_params->s16NumOfSubBands * p_encoder_params->s16NumOfBlocks;
uint8_t last_frame_len = 0;
+
while (nb_frame) {
BT_HDR* p_buf = (BT_HDR*)osi_malloc(A2DP_SBC_BUFFER_SIZE);
+ uint32_t bytes_read = 0;
+
p_buf->offset = A2DP_SBC_OFFSET;
p_buf->len = 0;
p_buf->layer_specific = 0;
@@ -540,11 +544,11 @@
/* Fill allocated buffer with 0 */
memset(a2dp_sbc_encoder_cb.pcmBuffer, 0,
blocm_x_subband * p_encoder_params->s16NumOfChannels);
-
//
// Read the PCM data and encode it. If necessary, upsample the data.
//
- if (a2dp_sbc_read_feeding()) {
+ uint32_t num_bytes = 0;
+ if (a2dp_sbc_read_feeding(&num_bytes)) {
uint8_t* output = (uint8_t*)(p_buf + 1) + p_buf->offset + p_buf->len;
int16_t* input = a2dp_sbc_encoder_cb.pcmBuffer;
uint16_t output_len = SBC_Encode(p_encoder_params, input, output);
@@ -554,6 +558,8 @@
p_buf->len += output_len;
nb_frame--;
p_buf->layer_specific++;
+
+ bytes_read += num_bytes;
} else {
LOG_WARN(LOG_TAG, "%s: underflow %d, %d", __func__, nb_frame,
a2dp_sbc_encoder_cb.feeding_state.aa_feed_residue);
@@ -580,7 +586,9 @@
uint8_t done_nb_frame = remain_nb_frame - nb_frame;
remain_nb_frame = nb_frame;
- if (!a2dp_sbc_encoder_cb.enqueue_callback(p_buf, done_nb_frame)) return;
+ if (!a2dp_sbc_encoder_cb.enqueue_callback(p_buf, done_nb_frame,
+ bytes_read))
+ return;
} else {
a2dp_sbc_encoder_cb.stats.media_read_total_dropped_packets++;
osi_free(p_buf);
@@ -588,7 +596,7 @@
}
}
-static bool a2dp_sbc_read_feeding(void) {
+static bool a2dp_sbc_read_feeding(uint32_t* bytes_read) {
SBC_ENC_PARAMS* p_encoder_params = &a2dp_sbc_encoder_cb.sbc_encoder_params;
uint16_t blocm_x_subband =
p_encoder_params->s16NumOfSubBands * p_encoder_params->s16NumOfBlocks;
@@ -639,6 +647,7 @@
a2dp_sbc_encoder_cb.stats.media_read_total_actual_read_bytes +=
nb_byte_read;
+ *bytes_read = nb_byte_read;
if (nb_byte_read != read_size) {
a2dp_sbc_encoder_cb.feeding_state.aa_feed_residue += nb_byte_read;
return false;
@@ -823,7 +832,7 @@
return result;
}
-static uint16_t a2dp_sbc_source_rate(void) {
+static uint16_t a2dp_sbc_source_rate() {
uint16_t rate = A2DP_SBC_DEFAULT_BITRATE;
/* restrict bitrate if a2dp link is non-edr */
@@ -893,11 +902,22 @@
return frame_len;
}
-period_ms_t A2dpCodecConfigSbc::encoderIntervalMs() const {
+uint32_t a2dp_sbc_get_bitrate() {
+ SBC_ENC_PARAMS* p_encoder_params = &a2dp_sbc_encoder_cb.sbc_encoder_params;
+ LOG_DEBUG(LOG_TAG, "%s: bit rate %d ", __func__,
+ p_encoder_params->u16BitRate);
+ return p_encoder_params->u16BitRate * 1000;
+}
+
+period_ms_t A2dpCodecConfigSbcSource::encoderIntervalMs() const {
return a2dp_sbc_get_encoder_interval_ms();
}
-void A2dpCodecConfigSbc::debug_codec_dump(int fd) {
+int A2dpCodecConfigSbcSource::getEffectiveMtu() const {
+ return a2dp_sbc_encoder_cb.TxAaMtuSize;
+}
+
+void A2dpCodecConfigSbcSource::debug_codec_dump(int fd) {
a2dp_sbc_encoder_stats_t* stats = &a2dp_sbc_encoder_cb.stats;
A2dpCodecConfig::debug_codec_dump(fd);
diff --git a/stack/a2dp/a2dp_sbc_up_sample.cc b/stack/a2dp/a2dp_sbc_up_sample.cc
index da15fe9..28cac85 100644
--- a/stack/a2dp/a2dp_sbc_up_sample.cc
+++ b/stack/a2dp/a2dp_sbc_up_sample.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/a2dp/a2dp_vendor.cc b/stack/a2dp/a2dp_vendor.cc
index f0fc277..1a6dcc2 100644
--- a/stack/a2dp/a2dp_vendor.cc
+++ b/stack/a2dp/a2dp_vendor.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -122,17 +122,6 @@
return false;
}
-tA2DP_STATUS A2DP_VendorBuildSrc2SinkConfig(
- UNUSED_ATTR const uint8_t* p_src_cap, UNUSED_ATTR uint8_t* p_pref_cfg) {
- // uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
- // uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
-
- // Add checks based on <vendor_id, codec_id>
- // NOTE: Should be done only for local Sink codecs.
-
- return A2DP_NS_CODEC_TYPE;
-}
-
uint32_t A2DP_VendorCodecGetVendorId(const uint8_t* p_codec_info) {
const uint8_t* p = &p_codec_info[A2DP_VENDOR_CODEC_VENDOR_ID_START_IDX];
@@ -287,6 +276,32 @@
return false;
}
+int A2DP_VendorGetBitRate(const uint8_t* p_codec_info) {
+ uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+ uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+
+ // Check for aptX
+ if (vendor_id == A2DP_APTX_VENDOR_ID &&
+ codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
+ return A2DP_VendorGetBitRateAptx(p_codec_info);
+ }
+
+ // Check for aptX-HD
+ if (vendor_id == A2DP_APTX_HD_VENDOR_ID &&
+ codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
+ return A2DP_VendorGetBitRateAptxHd(p_codec_info);
+ }
+
+ // Check for LDAC
+ if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+ return A2DP_VendorGetBitRateLdac(p_codec_info);
+ }
+
+ // Add checks based on <vendor_id, codec_id>
+
+ return -1;
+}
+
int A2DP_VendorGetTrackSampleRate(const uint8_t* p_codec_info) {
uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
@@ -350,18 +365,6 @@
return -1;
}
-int A2DP_VendorGetSinkFramesCountToProcess(
- UNUSED_ATTR uint64_t time_interval_ms,
- UNUSED_ATTR const uint8_t* p_codec_info) {
- // uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
- // uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
-
- // Add checks based on <vendor_id, codec_id>
- // NOTE: Should be done only for local Sink codecs.
-
- return -1;
-}
-
bool A2DP_VendorGetPacketTimestamp(const uint8_t* p_codec_info,
const uint8_t* p_data,
uint32_t* p_timestamp) {
@@ -448,6 +451,12 @@
return NULL;
}
+const tA2DP_DECODER_INTERFACE* A2DP_VendorGetDecoderInterface(
+ const uint8_t* p_codec_info) {
+ // We do not support vendor codecs for decoding right now.
+ return NULL;
+}
+
bool A2DP_VendorAdjustCodec(uint8_t* p_codec_info) {
uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
@@ -501,12 +510,22 @@
return BTAV_A2DP_CODEC_INDEX_MAX;
}
+btav_a2dp_codec_index_t A2DP_VendorSinkCodecIndex(const uint8_t* p_codec_info) {
+ // uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+ // uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+
+ // Add checks based on <vendor_id, codec_id>
+
+ return BTAV_A2DP_CODEC_INDEX_MAX;
+}
+
const char* A2DP_VendorCodecIndexStr(btav_a2dp_codec_index_t codec_index) {
// Add checks based on codec_index
switch (codec_index) {
case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
+ case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
break; // These are not vendor-specific codecs
case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
return A2DP_VendorCodecIndexStrAptx();
@@ -523,12 +542,13 @@
}
bool A2DP_VendorInitCodecConfig(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg) {
+ AvdtpSepConfig* p_cfg) {
// Add checks based on codec_index
switch (codec_index) {
case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
+ case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
break; // These are not vendor-specific codecs
case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
return A2DP_VendorInitCodecConfigAptx(p_cfg);
@@ -544,28 +564,29 @@
return false;
}
-bool A2DP_VendorDumpCodecInfo(const uint8_t* p_codec_info) {
+std::string A2DP_VendorCodecInfoString(const uint8_t* p_codec_info) {
uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
// Check for aptX
if (vendor_id == A2DP_APTX_VENDOR_ID &&
codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
- return A2DP_VendorDumpCodecInfoAptx(p_codec_info);
+ return A2DP_VendorCodecInfoStringAptx(p_codec_info);
}
// Check for aptX-HD
if (vendor_id == A2DP_APTX_HD_VENDOR_ID &&
codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
- return A2DP_VendorDumpCodecInfoAptxHd(p_codec_info);
+ return A2DP_VendorCodecInfoStringAptxHd(p_codec_info);
}
// Check for LDAC
if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
- return A2DP_VendorDumpCodecInfoLdac(p_codec_info);
+ return A2DP_VendorCodecInfoStringLdac(p_codec_info);
}
// Add checks based on <vendor_id, codec_id>
- return false;
+ return "Unsupported codec vendor_id: " + loghex(vendor_id) +
+ " codec_id: " + loghex(codec_id);
}
diff --git a/stack/a2dp/a2dp_vendor_aptx.cc b/stack/a2dp/a2dp_vendor_aptx.cc
index 92ff7c8..7017f06 100644
--- a/stack/a2dp/a2dp_vendor_aptx.cc
+++ b/stack/a2dp/a2dp_vendor_aptx.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
#include "a2dp_vendor.h"
#include "a2dp_vendor_aptx_encoder.h"
#include "bt_utils.h"
+#include "btif_av_co.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -48,7 +49,7 @@
} tA2DP_APTX_CIE;
/* aptX Source codec capabilities */
-static const tA2DP_APTX_CIE a2dp_aptx_caps = {
+static const tA2DP_APTX_CIE a2dp_aptx_source_caps = {
A2DP_APTX_VENDOR_ID, /* vendorId */
A2DP_APTX_CODEC_ID_BLUETOOTH, /* codecId */
(A2DP_APTX_SAMPLERATE_44100 | A2DP_APTX_SAMPLERATE_48000), /* sampleRate */
@@ -62,7 +63,7 @@
static const tA2DP_APTX_CIE a2dp_aptx_default_config = {
A2DP_APTX_VENDOR_ID, /* vendorId */
A2DP_APTX_CODEC_ID_BLUETOOTH, /* codecId */
- A2DP_APTX_SAMPLERATE_44100, /* sampleRate */
+ A2DP_APTX_SAMPLERATE_48000, /* sampleRate */
A2DP_APTX_CHANNELS_STEREO, /* channelMode */
A2DP_APTX_FUTURE_1, /* future1 */
A2DP_APTX_FUTURE_2, /* future2 */
@@ -279,6 +280,13 @@
(aptx_cie_a.channelMode == aptx_cie_b.channelMode);
}
+int A2DP_VendorGetBitRateAptx(const uint8_t* p_codec_info) {
+ A2dpCodecConfig* CodecConfig = bta_av_get_a2dp_current_codec();
+ tA2DP_BITS_PER_SAMPLE bits_per_sample = CodecConfig->getAudioBitsPerSample();
+ uint16_t samplerate = A2DP_GetTrackSampleRate(p_codec_info);
+ return (samplerate * bits_per_sample * 2) / 4;
+}
+
int A2DP_VendorGetTrackSampleRateAptx(const uint8_t* p_codec_info) {
tA2DP_APTX_CIE aptx_cie;
@@ -332,35 +340,40 @@
return true;
}
-bool A2DP_VendorDumpCodecInfoAptx(const uint8_t* p_codec_info) {
+std::string A2DP_VendorCodecInfoStringAptx(const uint8_t* p_codec_info) {
+ std::stringstream res;
+ std::string field;
tA2DP_STATUS a2dp_status;
tA2DP_APTX_CIE aptx_cie;
- LOG_VERBOSE(LOG_TAG, "%s", __func__);
-
a2dp_status = A2DP_ParseInfoAptx(&aptx_cie, p_codec_info, true);
if (a2dp_status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: A2DP_ParseInfoAptx fail:%d", __func__, a2dp_status);
- return false;
+ res << "A2DP_ParseInfoAptx fail: " << loghex(a2dp_status);
+ return res.str();
}
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: 0x%x", aptx_cie.sampleRate);
- if (aptx_cie.sampleRate & A2DP_APTX_SAMPLERATE_44100) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (44100)");
- }
- if (aptx_cie.sampleRate & A2DP_APTX_SAMPLERATE_48000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (48000)");
- }
+ res << "\tname: aptX\n";
- LOG_VERBOSE(LOG_TAG, "\tch_mode: 0x%x", aptx_cie.channelMode);
- if (aptx_cie.channelMode & A2DP_APTX_CHANNELS_MONO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Mono)");
- }
- if (aptx_cie.channelMode & A2DP_APTX_CHANNELS_STEREO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Stereo)");
- }
+ // Sample frequency
+ field.clear();
+ AppendField(&field, (aptx_cie.sampleRate == 0), "NONE");
+ AppendField(&field, (aptx_cie.sampleRate & A2DP_APTX_SAMPLERATE_44100),
+ "44100");
+ AppendField(&field, (aptx_cie.sampleRate & A2DP_APTX_SAMPLERATE_48000),
+ "48000");
+ res << "\tsamp_freq: " << field << " (" << loghex(aptx_cie.sampleRate)
+ << ")\n";
- return true;
+ // Channel mode
+ field.clear();
+ AppendField(&field, (aptx_cie.channelMode == 0), "NONE");
+ AppendField(&field, (aptx_cie.channelMode & A2DP_APTX_CHANNELS_MONO), "Mono");
+ AppendField(&field, (aptx_cie.channelMode & A2DP_APTX_CHANNELS_STEREO),
+ "Stereo");
+ res << "\tch_mode: " << field << " (" << loghex(aptx_cie.channelMode)
+ << ")\n";
+
+ return res.str();
}
const tA2DP_ENCODER_INTERFACE* A2DP_VendorGetEncoderInterfaceAptx(
@@ -387,8 +400,8 @@
const char* A2DP_VendorCodecIndexStrAptx(void) { return "aptX"; }
-bool A2DP_VendorInitCodecConfigAptx(tAVDT_CFG* p_cfg) {
- if (A2DP_BuildInfoAptx(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aptx_caps,
+bool A2DP_VendorInitCodecConfigAptx(AvdtpSepConfig* p_cfg) {
+ if (A2DP_BuildInfoAptx(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aptx_source_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
}
@@ -409,17 +422,18 @@
: A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, "aptX",
codec_priority) {
// Compute the local capability
- if (a2dp_aptx_caps.sampleRate & A2DP_APTX_SAMPLERATE_44100) {
+ if (a2dp_aptx_source_caps.sampleRate & A2DP_APTX_SAMPLERATE_44100) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
}
- if (a2dp_aptx_caps.sampleRate & A2DP_APTX_SAMPLERATE_48000) {
+ if (a2dp_aptx_source_caps.sampleRate & A2DP_APTX_SAMPLERATE_48000) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
}
- codec_local_capability_.bits_per_sample = a2dp_aptx_caps.bits_per_sample;
- if (a2dp_aptx_caps.channelMode & A2DP_APTX_CHANNELS_MONO) {
+ codec_local_capability_.bits_per_sample =
+ a2dp_aptx_source_caps.bits_per_sample;
+ if (a2dp_aptx_source_caps.channelMode & A2DP_APTX_CHANNELS_MONO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
}
- if (a2dp_aptx_caps.channelMode & A2DP_APTX_CHANNELS_STEREO) {
+ if (a2dp_aptx_source_caps.channelMode & A2DP_APTX_CHANNELS_STEREO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
}
@@ -489,6 +503,8 @@
case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
break;
}
@@ -582,7 +598,7 @@
bool is_capability,
uint8_t* p_result_codec_config) {
std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
- tA2DP_APTX_CIE sink_info_cie;
+ tA2DP_APTX_CIE peer_info_cie;
tA2DP_APTX_CIE result_config_cie;
uint8_t sampleRate;
uint8_t channelMode;
@@ -604,9 +620,9 @@
sizeof(ota_codec_peer_config_));
tA2DP_STATUS status =
- A2DP_ParseInfoAptx(&sink_info_cie, p_peer_codec_info, is_capability);
+ A2DP_ParseInfoAptx(&peer_info_cie, p_peer_codec_info, is_capability);
if (status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: can't parse peer's Sink capabilities: error = %d",
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
__func__, status);
goto fail;
}
@@ -615,13 +631,13 @@
// Build the preferred configuration
//
memset(&result_config_cie, 0, sizeof(result_config_cie));
- result_config_cie.vendorId = a2dp_aptx_caps.vendorId;
- result_config_cie.codecId = a2dp_aptx_caps.codecId;
+ result_config_cie.vendorId = a2dp_aptx_source_caps.vendorId;
+ result_config_cie.codecId = a2dp_aptx_source_caps.codecId;
//
// Select the sample frequency
//
- sampleRate = a2dp_aptx_caps.sampleRate & sink_info_cie.sampleRate;
+ sampleRate = a2dp_aptx_source_caps.sampleRate & peer_info_cie.sampleRate;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
switch (codec_user_config_.sample_rate) {
case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
@@ -642,6 +658,8 @@
case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
codec_capability_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
@@ -676,7 +694,7 @@
// No user preference - try the default config
if (select_best_sample_rate(
- a2dp_aptx_default_config.sampleRate & sink_info_cie.sampleRate,
+ a2dp_aptx_default_config.sampleRate & peer_info_cie.sampleRate,
&result_config_cie, &codec_config_)) {
break;
}
@@ -689,9 +707,10 @@
} while (false);
if (codec_config_.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) {
LOG_ERROR(LOG_TAG,
- "%s: cannot match sample frequency: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_aptx_caps.sampleRate, sink_info_cie.sampleRate);
+ "%s: cannot match sample frequency: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, a2dp_aptx_source_caps.sampleRate,
+ peer_info_cie.sampleRate);
goto fail;
}
@@ -718,7 +737,7 @@
do {
// Compute the selectable capability
codec_selectable_capability_.bits_per_sample =
- a2dp_aptx_caps.bits_per_sample;
+ a2dp_aptx_source_caps.bits_per_sample;
if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
break;
@@ -752,7 +771,7 @@
//
// Select the channel mode
//
- channelMode = a2dp_aptx_caps.channelMode & sink_info_cie.channelMode;
+ channelMode = a2dp_aptx_source_caps.channelMode & peer_info_cie.channelMode;
codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
switch (codec_user_config_.channel_mode) {
case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
@@ -803,7 +822,7 @@
// No user preference - try the default config
if (select_best_channel_mode(
- a2dp_aptx_default_config.channelMode & sink_info_cie.channelMode,
+ a2dp_aptx_default_config.channelMode & peer_info_cie.channelMode,
&result_config_cie, &codec_config_)) {
break;
}
@@ -816,17 +835,20 @@
} while (false);
if (codec_config_.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) {
LOG_ERROR(LOG_TAG,
- "%s: cannot match channel mode: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_aptx_caps.channelMode, sink_info_cie.channelMode);
+ "%s: cannot match channel mode: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, a2dp_aptx_source_caps.channelMode,
+ peer_info_cie.channelMode);
goto fail;
}
//
// Set the rest of the fields as bit-wise AND operation
//
- result_config_cie.future1 = a2dp_aptx_caps.future1 & sink_info_cie.future1;
- result_config_cie.future2 = a2dp_aptx_caps.future2 & sink_info_cie.future2;
+ result_config_cie.future1 =
+ a2dp_aptx_source_caps.future1 & peer_info_cie.future1;
+ result_config_cie.future2 =
+ a2dp_aptx_source_caps.future2 & peer_info_cie.future2;
if (A2DP_BuildInfoAptx(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie,
p_result_codec_config) != A2DP_SUCCESS) {
@@ -848,10 +870,10 @@
// Create a local copy of the peer codec capability/config, and the
// result codec config.
if (is_capability) {
- status = A2DP_BuildInfoAptx(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie,
+ status = A2DP_BuildInfoAptx(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
ota_codec_peer_capability_);
} else {
- status = A2DP_BuildInfoAptx(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie,
+ status = A2DP_BuildInfoAptx(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
ota_codec_peer_config_);
}
CHECK(status == A2DP_SUCCESS);
@@ -875,3 +897,64 @@
sizeof(ota_codec_peer_config_));
return false;
}
+
+bool A2dpCodecConfigAptx::setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+ tA2DP_APTX_CIE peer_info_cie;
+ uint8_t sampleRate;
+ uint8_t channelMode;
+
+ // Save the internal state
+ btav_a2dp_codec_config_t saved_codec_selectable_capability =
+ codec_selectable_capability_;
+ uint8_t saved_ota_codec_peer_capability[AVDT_CODEC_SIZE];
+ memcpy(saved_ota_codec_peer_capability, ota_codec_peer_capability_,
+ sizeof(ota_codec_peer_capability_));
+
+ tA2DP_STATUS status =
+ A2DP_ParseInfoAptx(&peer_info_cie, p_peer_codec_capabilities, true);
+ if (status != A2DP_SUCCESS) {
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
+ __func__, status);
+ goto fail;
+ }
+
+ // Compute the selectable capability - sample rate
+ sampleRate = a2dp_aptx_source_caps.sampleRate & peer_info_cie.sampleRate;
+ if (sampleRate & A2DP_APTX_SAMPLERATE_44100) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+ }
+ if (sampleRate & A2DP_APTX_SAMPLERATE_48000) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+ }
+
+ // Compute the selectable capability - bits per sample
+ codec_selectable_capability_.bits_per_sample =
+ a2dp_aptx_source_caps.bits_per_sample;
+
+ // Compute the selectable capability - channel mode
+ channelMode = a2dp_aptx_source_caps.channelMode & peer_info_cie.channelMode;
+ if (channelMode & A2DP_APTX_CHANNELS_MONO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+ }
+ if (channelMode & A2DP_APTX_CHANNELS_STEREO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
+
+ status = A2DP_BuildInfoAptx(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
+ ota_codec_peer_capability_);
+ CHECK(status == A2DP_SUCCESS);
+ return true;
+
+fail:
+ // Restore the internal state
+ codec_selectable_capability_ = saved_codec_selectable_capability;
+ memcpy(ota_codec_peer_capability_, saved_ota_codec_peer_capability,
+ sizeof(ota_codec_peer_capability_));
+ return false;
+}
diff --git a/stack/a2dp/a2dp_vendor_aptx_encoder.cc b/stack/a2dp/a2dp_vendor_aptx_encoder.cc
index 3fcb6de..0252935 100644
--- a/stack/a2dp/a2dp_vendor_aptx_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_encoder.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@
#define A2DP_APTX_OFFSET (AVDT_MEDIA_OFFSET - AVDT_MEDIA_HDR_SIZE)
#endif
-#define A2DP_APTX_MAX_PCM_BYTES_PER_READ 1024
+#define A2DP_APTX_MAX_PCM_BYTES_PER_READ 4096
typedef struct {
uint64_t sleep_time_ns;
@@ -263,8 +263,7 @@
LOG_DEBUG(LOG_TAG, "%s: sample_rate=%u bits_per_sample=%u channel_count=%u",
__func__, p_feeding_params->sample_rate,
p_feeding_params->bits_per_sample, p_feeding_params->channel_count);
-
- aptx_init_framing_params(&a2dp_aptx_encoder_cb.framing_params);
+ a2dp_vendor_aptx_feeding_reset();
}
void a2dp_vendor_aptx_encoder_cleanup(void) {
@@ -391,32 +390,38 @@
//
// Read the PCM data and encode it
//
- LOG_VERBOSE(LOG_TAG, "%s: %u PCM reads of size %u", __func__,
- framing_params->pcm_reads, framing_params->pcm_bytes_per_read);
+ uint16_t read_buffer16[A2DP_APTX_MAX_PCM_BYTES_PER_READ / sizeof(uint16_t)];
+ uint32_t expected_read_bytes =
+ framing_params->pcm_reads * framing_params->pcm_bytes_per_read;
size_t encoded_ptr_index = 0;
size_t pcm_bytes_encoded = 0;
+ uint32_t bytes_read = 0;
+
a2dp_aptx_encoder_cb.stats.media_read_total_expected_packets++;
- a2dp_aptx_encoder_cb.stats.media_read_total_expected_reads_count +=
- framing_params->pcm_reads;
+ a2dp_aptx_encoder_cb.stats.media_read_total_expected_reads_count++;
a2dp_aptx_encoder_cb.stats.media_read_total_expected_read_bytes +=
- framing_params->pcm_reads * framing_params->pcm_bytes_per_read;
- for (size_t reads = 0; reads < framing_params->pcm_reads; reads++) {
- uint16_t read_buffer16[A2DP_APTX_MAX_PCM_BYTES_PER_READ / sizeof(uint16_t)];
- size_t pcm_bytes_read = a2dp_aptx_encoder_cb.read_callback(
- (uint8_t*)read_buffer16, framing_params->pcm_bytes_per_read);
- a2dp_aptx_encoder_cb.stats.media_read_total_actual_read_bytes +=
- pcm_bytes_read;
- if (pcm_bytes_read < framing_params->pcm_bytes_per_read) {
- LOG_WARN(LOG_TAG,
- "%s: underflow at PCM reading iteration %zu: read %zu "
- "instead of %d",
- __func__, reads, pcm_bytes_read,
- framing_params->pcm_bytes_per_read);
- break;
- }
- a2dp_aptx_encoder_cb.stats.media_read_total_actual_reads_count++;
+ expected_read_bytes;
+
+ LOG_VERBOSE(LOG_TAG, "%s: PCM read of size %u", __func__,
+ expected_read_bytes);
+ bytes_read = a2dp_aptx_encoder_cb.read_callback((uint8_t*)read_buffer16,
+ expected_read_bytes);
+ a2dp_aptx_encoder_cb.stats.media_read_total_actual_read_bytes += bytes_read;
+ if (bytes_read < expected_read_bytes) {
+ LOG_WARN(LOG_TAG,
+ "%s: underflow at PCM reading: read %u bytes instead of %u",
+ __func__, bytes_read, expected_read_bytes);
+ a2dp_aptx_encoder_cb.stats.media_read_total_dropped_packets++;
+ osi_free(p_buf);
+ return;
+ }
+ a2dp_aptx_encoder_cb.stats.media_read_total_actual_reads_count++;
+
+ for (uint32_t reads = 0, offset = 0; reads < framing_params->pcm_reads;
+ reads++, offset +=
+ (framing_params->pcm_bytes_per_read / sizeof(uint16_t))) {
pcm_bytes_encoded += aptx_encode_16bit(framing_params, &encoded_ptr_index,
- read_buffer16, encoded_ptr);
+ read_buffer16 + offset, encoded_ptr);
}
// Compute the number of encoded bytes
@@ -435,7 +440,7 @@
a2dp_aptx_encoder_cb.timestamp += rtp_timestamp;
if (p_buf->len > 0) {
- a2dp_aptx_encoder_cb.enqueue_callback(p_buf, 1);
+ a2dp_aptx_encoder_cb.enqueue_callback(p_buf, 1, bytes_read);
} else {
a2dp_aptx_encoder_cb.stats.media_read_total_dropped_packets++;
osi_free(p_buf);
@@ -479,6 +484,10 @@
return a2dp_vendor_aptx_get_encoder_interval_ms();
}
+int A2dpCodecConfigAptx::getEffectiveMtu() const {
+ return a2dp_aptx_encoder_cb.peer_mtu;
+}
+
void A2dpCodecConfigAptx::debug_codec_dump(int fd) {
a2dp_aptx_encoder_stats_t* stats = &a2dp_aptx_encoder_cb.stats;
diff --git a/stack/a2dp/a2dp_vendor_aptx_hd.cc b/stack/a2dp/a2dp_vendor_aptx_hd.cc
index 85f2365..798e4fd 100644
--- a/stack/a2dp/a2dp_vendor_aptx_hd.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_hd.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
#include "a2dp_vendor.h"
#include "a2dp_vendor_aptx_hd_encoder.h"
#include "bt_utils.h"
+#include "btif_av_co.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -50,7 +51,7 @@
} tA2DP_APTX_HD_CIE;
/* aptX-HD Source codec capabilities */
-static const tA2DP_APTX_HD_CIE a2dp_aptx_hd_caps = {
+static const tA2DP_APTX_HD_CIE a2dp_aptx_hd_source_caps = {
A2DP_APTX_HD_VENDOR_ID, /* vendorId */
A2DP_APTX_HD_CODEC_ID_BLUETOOTH, /* codecId */
(A2DP_APTX_HD_SAMPLERATE_44100 |
@@ -67,7 +68,7 @@
static const tA2DP_APTX_HD_CIE a2dp_aptx_hd_default_config = {
A2DP_APTX_HD_VENDOR_ID, /* vendorId */
A2DP_APTX_HD_CODEC_ID_BLUETOOTH, /* codecId */
- A2DP_APTX_HD_SAMPLERATE_44100, /* sampleRate */
+ A2DP_APTX_HD_SAMPLERATE_48000, /* sampleRate */
A2DP_APTX_HD_CHANNELS_STEREO, /* channelMode */
A2DP_APTX_HD_ACL_SPRINT_RESERVED0, /* acl_sprint_reserved0 */
A2DP_APTX_HD_ACL_SPRINT_RESERVED1, /* acl_sprint_reserved1 */
@@ -293,6 +294,13 @@
(aptx_hd_cie_a.channelMode == aptx_hd_cie_b.channelMode);
}
+int A2DP_VendorGetBitRateAptxHd(const uint8_t* p_codec_info) {
+ A2dpCodecConfig* CodecConfig = bta_av_get_a2dp_current_codec();
+ tA2DP_BITS_PER_SAMPLE bits_per_sample = CodecConfig->getAudioBitsPerSample();
+ uint16_t samplerate = A2DP_GetTrackSampleRate(p_codec_info);
+ return (samplerate * bits_per_sample * 2) / 4;
+}
+
int A2DP_VendorGetTrackSampleRateAptxHd(const uint8_t* p_codec_info) {
tA2DP_APTX_HD_CIE aptx_hd_cie;
@@ -348,36 +356,41 @@
return true;
}
-bool A2DP_VendorDumpCodecInfoAptxHd(const uint8_t* p_codec_info) {
+std::string A2DP_VendorCodecInfoStringAptxHd(const uint8_t* p_codec_info) {
+ std::stringstream res;
+ std::string field;
tA2DP_STATUS a2dp_status;
tA2DP_APTX_HD_CIE aptx_hd_cie;
- LOG_VERBOSE(LOG_TAG, "%s", __func__);
-
a2dp_status = A2DP_ParseInfoAptxHd(&aptx_hd_cie, p_codec_info, true);
if (a2dp_status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: A2DP_ParseInfoAptxHd fail:%d", __func__,
- a2dp_status);
- return false;
+ res << "A2DP_ParseInfoAptxHd fail: " << loghex(a2dp_status);
+ return res.str();
}
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: 0x%x", aptx_hd_cie.sampleRate);
- if (aptx_hd_cie.sampleRate & A2DP_APTX_HD_SAMPLERATE_44100) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (44100)");
- }
- if (aptx_hd_cie.sampleRate & A2DP_APTX_HD_SAMPLERATE_48000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (48000)");
- }
+ res << "\tname: aptX-HD\n";
- LOG_VERBOSE(LOG_TAG, "\tch_mode: 0x%x", aptx_hd_cie.channelMode);
- if (aptx_hd_cie.channelMode & A2DP_APTX_HD_CHANNELS_MONO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Mono)");
- }
- if (aptx_hd_cie.channelMode & A2DP_APTX_HD_CHANNELS_STEREO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Stereo)");
- }
+ // Sample frequency
+ field.clear();
+ AppendField(&field, (aptx_hd_cie.sampleRate == 0), "NONE");
+ AppendField(&field, (aptx_hd_cie.sampleRate & A2DP_APTX_HD_SAMPLERATE_44100),
+ "44100");
+ AppendField(&field, (aptx_hd_cie.sampleRate & A2DP_APTX_HD_SAMPLERATE_48000),
+ "48000");
+ res << "\tsamp_freq: " << field << " (" << loghex(aptx_hd_cie.sampleRate)
+ << ")\n";
- return true;
+ // Channel mode
+ field.clear();
+ AppendField(&field, (aptx_hd_cie.channelMode == 0), "NONE");
+ AppendField(&field, (aptx_hd_cie.channelMode & A2DP_APTX_HD_CHANNELS_MONO),
+ "Mono");
+ AppendField(&field, (aptx_hd_cie.channelMode & A2DP_APTX_HD_CHANNELS_STEREO),
+ "Stereo");
+ res << "\tch_mode: " << field << " (" << loghex(aptx_hd_cie.channelMode)
+ << ")\n";
+
+ return res.str();
}
const tA2DP_ENCODER_INTERFACE* A2DP_VendorGetEncoderInterfaceAptxHd(
@@ -404,8 +417,8 @@
const char* A2DP_VendorCodecIndexStrAptxHd(void) { return "aptX-HD"; }
-bool A2DP_VendorInitCodecConfigAptxHd(tAVDT_CFG* p_cfg) {
- if (A2DP_BuildInfoAptxHd(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aptx_hd_caps,
+bool A2DP_VendorInitCodecConfigAptxHd(AvdtpSepConfig* p_cfg) {
+ if (A2DP_BuildInfoAptxHd(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aptx_hd_source_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
}
@@ -426,17 +439,18 @@
: A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD, "aptX-HD",
codec_priority) {
// Compute the local capability
- if (a2dp_aptx_hd_caps.sampleRate & A2DP_APTX_HD_SAMPLERATE_44100) {
+ if (a2dp_aptx_hd_source_caps.sampleRate & A2DP_APTX_HD_SAMPLERATE_44100) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
}
- if (a2dp_aptx_hd_caps.sampleRate & A2DP_APTX_HD_SAMPLERATE_48000) {
+ if (a2dp_aptx_hd_source_caps.sampleRate & A2DP_APTX_HD_SAMPLERATE_48000) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
}
- codec_local_capability_.bits_per_sample = a2dp_aptx_hd_caps.bits_per_sample;
- if (a2dp_aptx_hd_caps.channelMode & A2DP_APTX_HD_CHANNELS_MONO) {
+ codec_local_capability_.bits_per_sample =
+ a2dp_aptx_hd_source_caps.bits_per_sample;
+ if (a2dp_aptx_hd_source_caps.channelMode & A2DP_APTX_HD_CHANNELS_MONO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
}
- if (a2dp_aptx_hd_caps.channelMode & A2DP_APTX_HD_CHANNELS_STEREO) {
+ if (a2dp_aptx_hd_source_caps.channelMode & A2DP_APTX_HD_CHANNELS_STEREO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
}
@@ -506,6 +520,8 @@
case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
break;
}
@@ -599,7 +615,7 @@
bool is_capability,
uint8_t* p_result_codec_config) {
std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
- tA2DP_APTX_HD_CIE sink_info_cie;
+ tA2DP_APTX_HD_CIE peer_info_cie;
tA2DP_APTX_HD_CIE result_config_cie;
uint8_t sampleRate;
uint8_t channelMode;
@@ -621,9 +637,9 @@
sizeof(ota_codec_peer_config_));
tA2DP_STATUS status =
- A2DP_ParseInfoAptxHd(&sink_info_cie, p_peer_codec_info, is_capability);
+ A2DP_ParseInfoAptxHd(&peer_info_cie, p_peer_codec_info, is_capability);
if (status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: can't parse peer's Sink capabilities: error = %d",
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
__func__, status);
goto fail;
}
@@ -632,13 +648,13 @@
// Build the preferred configuration
//
memset(&result_config_cie, 0, sizeof(result_config_cie));
- result_config_cie.vendorId = a2dp_aptx_hd_caps.vendorId;
- result_config_cie.codecId = a2dp_aptx_hd_caps.codecId;
+ result_config_cie.vendorId = a2dp_aptx_hd_source_caps.vendorId;
+ result_config_cie.codecId = a2dp_aptx_hd_source_caps.codecId;
//
// Select the sample frequency
//
- sampleRate = a2dp_aptx_hd_caps.sampleRate & sink_info_cie.sampleRate;
+ sampleRate = a2dp_aptx_hd_source_caps.sampleRate & peer_info_cie.sampleRate;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
switch (codec_user_config_.sample_rate) {
case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
@@ -659,6 +675,8 @@
case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
codec_capability_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
@@ -693,7 +711,7 @@
// No user preference - try the default config
if (select_best_sample_rate(
- a2dp_aptx_hd_default_config.sampleRate & sink_info_cie.sampleRate,
+ a2dp_aptx_hd_default_config.sampleRate & peer_info_cie.sampleRate,
&result_config_cie, &codec_config_)) {
break;
}
@@ -706,9 +724,10 @@
} while (false);
if (codec_config_.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) {
LOG_ERROR(LOG_TAG,
- "%s: cannot match sample frequency: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_aptx_hd_caps.sampleRate, sink_info_cie.sampleRate);
+ "%s: cannot match sample frequency: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, a2dp_aptx_hd_source_caps.sampleRate,
+ peer_info_cie.sampleRate);
goto fail;
}
@@ -735,7 +754,7 @@
do {
// Compute the selectable capability
codec_selectable_capability_.bits_per_sample =
- a2dp_aptx_hd_caps.bits_per_sample;
+ a2dp_aptx_hd_source_caps.bits_per_sample;
if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
break;
@@ -769,7 +788,8 @@
//
// Select the channel mode
//
- channelMode = a2dp_aptx_hd_caps.channelMode & sink_info_cie.channelMode;
+ channelMode =
+ a2dp_aptx_hd_source_caps.channelMode & peer_info_cie.channelMode;
codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
switch (codec_user_config_.channel_mode) {
case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
@@ -820,7 +840,7 @@
// No user preference - try the default config
if (select_best_channel_mode(
- a2dp_aptx_hd_default_config.channelMode & sink_info_cie.channelMode,
+ a2dp_aptx_hd_default_config.channelMode & peer_info_cie.channelMode,
&result_config_cie, &codec_config_)) {
break;
}
@@ -833,10 +853,10 @@
} while (false);
if (codec_config_.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) {
LOG_ERROR(LOG_TAG,
- "%s: cannot match channel mode: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_aptx_hd_caps.channelMode,
- sink_info_cie.channelMode);
+ "%s: cannot match channel mode: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, a2dp_aptx_hd_source_caps.channelMode,
+ peer_info_cie.channelMode);
goto fail;
}
@@ -844,17 +864,17 @@
// Set the rest of the fields as bit-wise AND operation
//
result_config_cie.acl_sprint_reserved0 =
- a2dp_aptx_hd_caps.acl_sprint_reserved0 &
- sink_info_cie.acl_sprint_reserved0;
+ a2dp_aptx_hd_source_caps.acl_sprint_reserved0 &
+ peer_info_cie.acl_sprint_reserved0;
result_config_cie.acl_sprint_reserved1 =
- a2dp_aptx_hd_caps.acl_sprint_reserved1 &
- sink_info_cie.acl_sprint_reserved1;
+ a2dp_aptx_hd_source_caps.acl_sprint_reserved1 &
+ peer_info_cie.acl_sprint_reserved1;
result_config_cie.acl_sprint_reserved2 =
- a2dp_aptx_hd_caps.acl_sprint_reserved2 &
- sink_info_cie.acl_sprint_reserved2;
+ a2dp_aptx_hd_source_caps.acl_sprint_reserved2 &
+ peer_info_cie.acl_sprint_reserved2;
result_config_cie.acl_sprint_reserved3 =
- a2dp_aptx_hd_caps.acl_sprint_reserved3 &
- sink_info_cie.acl_sprint_reserved3;
+ a2dp_aptx_hd_source_caps.acl_sprint_reserved3 &
+ peer_info_cie.acl_sprint_reserved3;
if (A2DP_BuildInfoAptxHd(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie,
p_result_codec_config) != A2DP_SUCCESS) {
@@ -876,10 +896,10 @@
// Create a local copy of the peer codec capability/config, and the
// result codec config.
if (is_capability) {
- status = A2DP_BuildInfoAptxHd(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie,
+ status = A2DP_BuildInfoAptxHd(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
ota_codec_peer_capability_);
} else {
- status = A2DP_BuildInfoAptxHd(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie,
+ status = A2DP_BuildInfoAptxHd(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
ota_codec_peer_config_);
}
CHECK(status == A2DP_SUCCESS);
@@ -902,3 +922,65 @@
sizeof(ota_codec_peer_config_));
return false;
}
+
+bool A2dpCodecConfigAptxHd::setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+ tA2DP_APTX_HD_CIE peer_info_cie;
+ uint8_t sampleRate;
+ uint8_t channelMode;
+
+ // Save the internal state
+ btav_a2dp_codec_config_t saved_codec_selectable_capability =
+ codec_selectable_capability_;
+ uint8_t saved_ota_codec_peer_capability[AVDT_CODEC_SIZE];
+ memcpy(saved_ota_codec_peer_capability, ota_codec_peer_capability_,
+ sizeof(ota_codec_peer_capability_));
+
+ tA2DP_STATUS status =
+ A2DP_ParseInfoAptxHd(&peer_info_cie, p_peer_codec_capabilities, true);
+ if (status != A2DP_SUCCESS) {
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
+ __func__, status);
+ goto fail;
+ }
+
+ // Compute the selectable capability - sample rate
+ sampleRate = a2dp_aptx_hd_source_caps.sampleRate & peer_info_cie.sampleRate;
+ if (sampleRate & A2DP_APTX_HD_SAMPLERATE_44100) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+ }
+ if (sampleRate & A2DP_APTX_HD_SAMPLERATE_48000) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+ }
+
+ // Compute the selectable capability - bits per sample
+ codec_selectable_capability_.bits_per_sample =
+ a2dp_aptx_hd_source_caps.bits_per_sample;
+
+ // Compute the selectable capability - channel mode
+ channelMode =
+ a2dp_aptx_hd_source_caps.channelMode & peer_info_cie.channelMode;
+ if (channelMode & A2DP_APTX_HD_CHANNELS_MONO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+ }
+ if (channelMode & A2DP_APTX_HD_CHANNELS_STEREO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
+
+ status = A2DP_BuildInfoAptxHd(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
+ ota_codec_peer_capability_);
+ CHECK(status == A2DP_SUCCESS);
+ return true;
+
+fail:
+ // Restore the internal state
+ codec_selectable_capability_ = saved_codec_selectable_capability;
+ memcpy(ota_codec_peer_capability_, saved_ota_codec_peer_capability,
+ sizeof(ota_codec_peer_capability_));
+ return false;
+}
diff --git a/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc b/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
index 084291f..d72ec5a 100644
--- a/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@
#define A2DP_APTX_HD_OFFSET AVDT_MEDIA_OFFSET
#endif
-#define A2DP_APTX_HD_MAX_PCM_BYTES_PER_READ 1024
+#define A2DP_APTX_HD_MAX_PCM_BYTES_PER_READ 4096
typedef struct {
uint64_t sleep_time_ns;
@@ -90,7 +90,7 @@
bool use_SCMS_T;
bool is_peer_edr; // True if the peer device supports EDR
bool peer_supports_3mbps; // True if the peer device supports 3Mbps EDR
- uint16_t peer_mtu; // // MTU of the A2DP peer
+ uint16_t peer_mtu; // MTU of the A2DP peer
uint32_t timestamp; // Timestamp for the A2DP frames
tA2DP_FEEDING_PARAMS feeding_params;
@@ -264,8 +264,7 @@
LOG_DEBUG(LOG_TAG, "%s: sample_rate=%u bits_per_sample=%u channel_count=%u",
__func__, p_feeding_params->sample_rate,
p_feeding_params->bits_per_sample, p_feeding_params->channel_count);
-
- aptx_hd_init_framing_params(&a2dp_aptx_hd_encoder_cb.framing_params);
+ a2dp_vendor_aptx_hd_feeding_reset();
}
void a2dp_vendor_aptx_hd_encoder_cleanup(void) {
@@ -376,33 +375,41 @@
//
// Read the PCM data and encode it
//
- LOG_VERBOSE(LOG_TAG, "%s: %u PCM reads of size %u", __func__,
- framing_params->pcm_reads, framing_params->pcm_bytes_per_read);
+ uint32_t
+ read_buffer32[A2DP_APTX_HD_MAX_PCM_BYTES_PER_READ / sizeof(uint32_t)];
+ uint32_t expected_read_bytes =
+ framing_params->pcm_reads * framing_params->pcm_bytes_per_read;
size_t encoded_ptr_index = 0;
size_t pcm_bytes_encoded = 0;
+ uint32_t bytes_read = 0;
+
a2dp_aptx_hd_encoder_cb.stats.media_read_total_expected_packets++;
- a2dp_aptx_hd_encoder_cb.stats.media_read_total_expected_reads_count +=
- framing_params->pcm_reads;
+ a2dp_aptx_hd_encoder_cb.stats.media_read_total_expected_reads_count++;
a2dp_aptx_hd_encoder_cb.stats.media_read_total_expected_read_bytes +=
- framing_params->pcm_reads * framing_params->pcm_bytes_per_read;
- for (size_t reads = 0; reads < framing_params->pcm_reads; reads++) {
- uint32_t
- read_buffer32[A2DP_APTX_HD_MAX_PCM_BYTES_PER_READ / sizeof(uint32_t)];
- size_t pcm_bytes_read = a2dp_aptx_hd_encoder_cb.read_callback(
- (uint8_t*)read_buffer32, framing_params->pcm_bytes_per_read);
- a2dp_aptx_hd_encoder_cb.stats.media_read_total_actual_read_bytes +=
- pcm_bytes_read;
- if (pcm_bytes_read < framing_params->pcm_bytes_per_read) {
- LOG_WARN(LOG_TAG,
- "%s: underflow at PCM reading iteration %zu: read %zu "
- "instead of %d",
- __func__, reads, pcm_bytes_read,
- framing_params->pcm_bytes_per_read);
- break;
- }
- a2dp_aptx_hd_encoder_cb.stats.media_read_total_actual_reads_count++;
- pcm_bytes_encoded += aptx_hd_encode_24bit(
- framing_params, &encoded_ptr_index, read_buffer32, encoded_ptr);
+ expected_read_bytes;
+
+ LOG_VERBOSE(LOG_TAG, "%s: PCM read of size %u", __func__,
+ expected_read_bytes);
+ bytes_read = a2dp_aptx_hd_encoder_cb.read_callback((uint8_t*)read_buffer32,
+ expected_read_bytes);
+ a2dp_aptx_hd_encoder_cb.stats.media_read_total_actual_read_bytes +=
+ bytes_read;
+ if (bytes_read < expected_read_bytes) {
+ LOG_WARN(LOG_TAG,
+ "%s: underflow at PCM reading: read %u bytes instead of %u",
+ __func__, bytes_read, expected_read_bytes);
+ a2dp_aptx_hd_encoder_cb.stats.media_read_total_dropped_packets++;
+ osi_free(p_buf);
+ return;
+ }
+ a2dp_aptx_hd_encoder_cb.stats.media_read_total_actual_reads_count++;
+
+ for (uint32_t reads = 0, offset = 0; reads < framing_params->pcm_reads;
+ reads++, offset +=
+ framing_params->pcm_bytes_per_read / sizeof(uint32_t)) {
+ pcm_bytes_encoded +=
+ aptx_hd_encode_24bit(framing_params, &encoded_ptr_index,
+ read_buffer32 + offset, encoded_ptr);
}
// Compute the number of encoded bytes
@@ -422,7 +429,7 @@
a2dp_aptx_hd_encoder_cb.timestamp += rtp_timestamp;
if (p_buf->len > 0) {
- a2dp_aptx_hd_encoder_cb.enqueue_callback(p_buf, 1);
+ a2dp_aptx_hd_encoder_cb.enqueue_callback(p_buf, 1, bytes_read);
} else {
a2dp_aptx_hd_encoder_cb.stats.media_read_total_dropped_packets++;
osi_free(p_buf);
@@ -474,6 +481,10 @@
return a2dp_vendor_aptx_hd_get_encoder_interval_ms();
}
+int A2dpCodecConfigAptxHd::getEffectiveMtu() const {
+ return a2dp_aptx_hd_encoder_cb.peer_mtu;
+}
+
void A2dpCodecConfigAptxHd::debug_codec_dump(int fd) {
a2dp_aptx_hd_encoder_stats_t* stats = &a2dp_aptx_hd_encoder_cb.stats;
diff --git a/stack/a2dp/a2dp_vendor_ldac.cc b/stack/a2dp/a2dp_vendor_ldac.cc
index e38424f..266db81 100644
--- a/stack/a2dp/a2dp_vendor_ldac.cc
+++ b/stack/a2dp/a2dp_vendor_ldac.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
#include "a2dp_vendor.h"
#include "a2dp_vendor_ldac_encoder.h"
#include "bt_utils.h"
+#include "btif_av_co.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -47,7 +48,7 @@
} tA2DP_LDAC_CIE;
/* LDAC Source codec capabilities */
-static const tA2DP_LDAC_CIE a2dp_ldac_caps = {
+static const tA2DP_LDAC_CIE a2dp_ldac_source_caps = {
A2DP_LDAC_VENDOR_ID, // vendorId
A2DP_LDAC_CODEC_ID, // codecId
// sampleRate
@@ -301,6 +302,36 @@
(ldac_cie_a.channelMode == ldac_cie_b.channelMode);
}
+int A2DP_VendorGetBitRateLdac(const uint8_t* p_codec_info) {
+ A2dpCodecConfig* current_codec = bta_av_get_a2dp_current_codec();
+ btav_a2dp_codec_config_t codec_config_ = current_codec->getCodecConfig();
+ int samplerate = A2DP_GetTrackSampleRate(p_codec_info);
+ switch (codec_config_.codec_specific_1 % 10) {
+ case 0:
+ if (samplerate == 44100 || samplerate == 88200)
+ return 909000;
+ else
+ return 990000;
+ case 1:
+ if (samplerate == 44100 || samplerate == 88200)
+ return 606000;
+ else
+ return 660000;
+ case 2:
+ if (samplerate == 44100 || samplerate == 88200)
+ return 303000;
+ else
+ return 330000;
+ case 3:
+ default:
+ if (samplerate == 44100 || samplerate == 88200)
+ return 909000;
+ else
+ return 990000;
+ }
+ return 0;
+}
+
int A2DP_VendorGetTrackSampleRateLdac(const uint8_t* p_codec_info) {
tA2DP_LDAC_CIE ldac_cie;
@@ -398,50 +429,51 @@
return true;
}
-bool A2DP_VendorDumpCodecInfoLdac(const uint8_t* p_codec_info) {
+std::string A2DP_VendorCodecInfoStringLdac(const uint8_t* p_codec_info) {
+ std::stringstream res;
+ std::string field;
tA2DP_STATUS a2dp_status;
tA2DP_LDAC_CIE ldac_cie;
- LOG_VERBOSE(LOG_TAG, "%s", __func__);
-
a2dp_status = A2DP_ParseInfoLdac(&ldac_cie, p_codec_info, true);
if (a2dp_status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: A2DP_ParseInfoLdac fail:%d", __func__, a2dp_status);
- return false;
+ res << "A2DP_ParseInfoLdac fail: " << loghex(a2dp_status);
+ return res.str();
}
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: 0x%x", ldac_cie.sampleRate);
- if (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (44100)");
- }
- if (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_48000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (48000)");
- }
- if (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_88200) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (88200)");
- }
- if (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_96000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (96000)");
- }
- if (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_176400) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (176400)");
- }
- if (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_192000) {
- LOG_VERBOSE(LOG_TAG, "\tsamp_freq: (192000)");
- }
+ res << "\tname: LDAC\n";
- LOG_VERBOSE(LOG_TAG, "\tch_mode: 0x%x", ldac_cie.channelMode);
- if (ldac_cie.channelMode & A2DP_LDAC_CHANNEL_MODE_MONO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Mono)");
- }
- if (ldac_cie.channelMode & A2DP_LDAC_CHANNEL_MODE_DUAL) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Dual)");
- }
- if (ldac_cie.channelMode & A2DP_LDAC_CHANNEL_MODE_STEREO) {
- LOG_VERBOSE(LOG_TAG, "\tch_mode: (Stereo)");
- }
+ // Sample frequency
+ field.clear();
+ AppendField(&field, (ldac_cie.sampleRate == 0), "NONE");
+ AppendField(&field, (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100),
+ "44100");
+ AppendField(&field, (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_48000),
+ "48000");
+ AppendField(&field, (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_88200),
+ "88200");
+ AppendField(&field, (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_96000),
+ "96000");
+ AppendField(&field, (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_176400),
+ "176400");
+ AppendField(&field, (ldac_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_192000),
+ "192000");
+ res << "\tsamp_freq: " << field << " (" << loghex(ldac_cie.sampleRate)
+ << ")\n";
- return true;
+ // Channel mode
+ field.clear();
+ AppendField(&field, (ldac_cie.channelMode == 0), "NONE");
+ AppendField(&field, (ldac_cie.channelMode & A2DP_LDAC_CHANNEL_MODE_MONO),
+ "Mono");
+ AppendField(&field, (ldac_cie.channelMode & A2DP_LDAC_CHANNEL_MODE_DUAL),
+ "Dual");
+ AppendField(&field, (ldac_cie.channelMode & A2DP_LDAC_CHANNEL_MODE_STEREO),
+ "Stereo");
+ res << "\tch_mode: " << field << " (" << loghex(ldac_cie.channelMode)
+ << ")\n";
+
+ return res.str();
}
const tA2DP_ENCODER_INTERFACE* A2DP_VendorGetEncoderInterfaceLdac(
@@ -468,8 +500,8 @@
const char* A2DP_VendorCodecIndexStrLdac(void) { return "LDAC"; }
-bool A2DP_VendorInitCodecConfigLdac(tAVDT_CFG* p_cfg) {
- if (A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_ldac_caps,
+bool A2DP_VendorInitCodecConfigLdac(AvdtpSepConfig* p_cfg) {
+ if (A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_ldac_source_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
}
@@ -515,32 +547,33 @@
: A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC, "LDAC",
codec_priority) {
// Compute the local capability
- if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100) {
+ if (a2dp_ldac_source_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
}
- if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_48000) {
+ if (a2dp_ldac_source_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_48000) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
}
- if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_88200) {
+ if (a2dp_ldac_source_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_88200) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
}
- if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_96000) {
+ if (a2dp_ldac_source_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_96000) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
}
- if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_176400) {
+ if (a2dp_ldac_source_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_176400) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_176400;
}
- if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_192000) {
+ if (a2dp_ldac_source_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_192000) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_192000;
}
- codec_local_capability_.bits_per_sample = a2dp_ldac_caps.bits_per_sample;
- if (a2dp_ldac_caps.channelMode & A2DP_LDAC_CHANNEL_MODE_MONO) {
+ codec_local_capability_.bits_per_sample =
+ a2dp_ldac_source_caps.bits_per_sample;
+ if (a2dp_ldac_source_caps.channelMode & A2DP_LDAC_CHANNEL_MODE_MONO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
}
- if (a2dp_ldac_caps.channelMode & A2DP_LDAC_CHANNEL_MODE_STEREO) {
+ if (a2dp_ldac_source_caps.channelMode & A2DP_LDAC_CHANNEL_MODE_STEREO) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
- if (a2dp_ldac_caps.channelMode & A2DP_LDAC_CHANNEL_MODE_DUAL) {
+ if (a2dp_ldac_source_caps.channelMode & A2DP_LDAC_CHANNEL_MODE_DUAL) {
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
}
@@ -654,6 +687,8 @@
return true;
}
break;
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
break;
}
@@ -791,7 +826,7 @@
bool is_capability,
uint8_t* p_result_codec_config) {
std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
- tA2DP_LDAC_CIE sink_info_cie;
+ tA2DP_LDAC_CIE peer_info_cie;
tA2DP_LDAC_CIE result_config_cie;
uint8_t channelMode;
uint8_t sampleRate;
@@ -814,9 +849,9 @@
sizeof(ota_codec_peer_config_));
tA2DP_STATUS status =
- A2DP_ParseInfoLdac(&sink_info_cie, p_peer_codec_info, is_capability);
+ A2DP_ParseInfoLdac(&peer_info_cie, p_peer_codec_info, is_capability);
if (status != A2DP_SUCCESS) {
- LOG_ERROR(LOG_TAG, "%s: can't parse peer's Sink capabilities: error = %d",
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
__func__, status);
goto fail;
}
@@ -825,13 +860,13 @@
// Build the preferred configuration
//
memset(&result_config_cie, 0, sizeof(result_config_cie));
- result_config_cie.vendorId = a2dp_ldac_caps.vendorId;
- result_config_cie.codecId = a2dp_ldac_caps.codecId;
+ result_config_cie.vendorId = a2dp_ldac_source_caps.vendorId;
+ result_config_cie.codecId = a2dp_ldac_source_caps.codecId;
//
// Select the sample frequency
//
- sampleRate = a2dp_ldac_caps.sampleRate & sink_info_cie.sampleRate;
+ sampleRate = a2dp_ldac_source_caps.sampleRate & peer_info_cie.sampleRate;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
switch (codec_user_config_.sample_rate) {
case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
@@ -875,6 +910,8 @@
codec_capability_.sample_rate = codec_user_config_.sample_rate;
codec_config_.sample_rate = codec_user_config_.sample_rate;
}
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+ case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
codec_capability_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
@@ -933,7 +970,7 @@
// No user preference - try the default config
if (select_best_sample_rate(
- a2dp_ldac_default_config.sampleRate & sink_info_cie.sampleRate,
+ a2dp_ldac_default_config.sampleRate & peer_info_cie.sampleRate,
&result_config_cie, &codec_config_)) {
break;
}
@@ -946,9 +983,10 @@
} while (false);
if (codec_config_.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) {
LOG_ERROR(LOG_TAG,
- "%s: cannot match sample frequency: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_ldac_caps.sampleRate, sink_info_cie.sampleRate);
+ "%s: cannot match sample frequency: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, a2dp_ldac_source_caps.sampleRate,
+ peer_info_cie.sampleRate);
goto fail;
}
@@ -957,7 +995,7 @@
//
// NOTE: this information is NOT included in the LDAC A2DP codec description
// that is sent OTA.
- bits_per_sample = a2dp_ldac_caps.bits_per_sample;
+ bits_per_sample = a2dp_ldac_source_caps.bits_per_sample;
codec_config_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE;
switch (codec_user_config_.bits_per_sample) {
case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
@@ -992,7 +1030,7 @@
do {
// Compute the selectable capability
codec_selectable_capability_.bits_per_sample =
- a2dp_ldac_caps.bits_per_sample;
+ a2dp_ldac_source_caps.bits_per_sample;
if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
break;
@@ -1002,7 +1040,7 @@
// No user preference - the the codec audio config
if (select_audio_bits_per_sample(&codec_audio_config_,
- a2dp_ldac_caps.bits_per_sample,
+ a2dp_ldac_source_caps.bits_per_sample,
&result_config_cie, &codec_config_)) {
break;
}
@@ -1014,7 +1052,7 @@
}
// No user preference - use the best match
- if (select_best_bits_per_sample(a2dp_ldac_caps.bits_per_sample,
+ if (select_best_bits_per_sample(a2dp_ldac_source_caps.bits_per_sample,
&result_config_cie, &codec_config_)) {
break;
}
@@ -1031,7 +1069,7 @@
//
// Select the channel mode
//
- channelMode = a2dp_ldac_caps.channelMode & sink_info_cie.channelMode;
+ channelMode = a2dp_ldac_source_caps.channelMode & peer_info_cie.channelMode;
codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
switch (codec_user_config_.channel_mode) {
case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
@@ -1095,7 +1133,7 @@
// No user preference - try the default config
if (select_best_channel_mode(
- a2dp_ldac_default_config.channelMode & sink_info_cie.channelMode,
+ a2dp_ldac_default_config.channelMode & peer_info_cie.channelMode,
&result_config_cie, &codec_config_)) {
break;
}
@@ -1108,9 +1146,10 @@
} while (false);
if (codec_config_.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) {
LOG_ERROR(LOG_TAG,
- "%s: cannot match channel mode: source caps = 0x%x "
- "sink info = 0x%x",
- __func__, a2dp_ldac_caps.channelMode, sink_info_cie.channelMode);
+ "%s: cannot match channel mode: local caps = 0x%x "
+ "peer info = 0x%x",
+ __func__, a2dp_ldac_source_caps.channelMode,
+ peer_info_cie.channelMode);
goto fail;
}
@@ -1134,10 +1173,10 @@
// Create a local copy of the peer codec capability, and the
// result codec config.
if (is_capability) {
- status = A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie,
+ status = A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
ota_codec_peer_capability_);
} else {
- status = A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie,
+ status = A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
ota_codec_peer_config_);
}
CHECK(status == A2DP_SUCCESS);
@@ -1160,3 +1199,84 @@
sizeof(ota_codec_peer_config_));
return false;
}
+
+bool A2dpCodecConfigLdac::setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) {
+ std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+ tA2DP_LDAC_CIE peer_info_cie;
+ uint8_t channelMode;
+ uint8_t sampleRate;
+
+ // Save the internal state
+ btav_a2dp_codec_config_t saved_codec_selectable_capability =
+ codec_selectable_capability_;
+ uint8_t saved_ota_codec_peer_capability[AVDT_CODEC_SIZE];
+ memcpy(saved_ota_codec_peer_capability, ota_codec_peer_capability_,
+ sizeof(ota_codec_peer_capability_));
+
+ tA2DP_STATUS status =
+ A2DP_ParseInfoLdac(&peer_info_cie, p_peer_codec_capabilities, true);
+ if (status != A2DP_SUCCESS) {
+ LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d",
+ __func__, status);
+ goto fail;
+ }
+
+ // Compute the selectable capability - sample rate
+ sampleRate = a2dp_ldac_source_caps.sampleRate & peer_info_cie.sampleRate;
+ if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+ }
+ if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_48000) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+ }
+ if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_88200) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
+ }
+ if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_96000) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
+ }
+ if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_176400) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_176400;
+ }
+ if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_192000) {
+ codec_selectable_capability_.sample_rate |=
+ BTAV_A2DP_CODEC_SAMPLE_RATE_192000;
+ }
+
+ // Compute the selectable capability - bits per sample
+ codec_selectable_capability_.bits_per_sample =
+ a2dp_ldac_source_caps.bits_per_sample;
+
+ // Compute the selectable capability - channel mode
+ channelMode = a2dp_ldac_source_caps.channelMode & peer_info_cie.channelMode;
+ if (channelMode & A2DP_LDAC_CHANNEL_MODE_MONO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+ }
+ if (channelMode & A2DP_LDAC_CHANNEL_MODE_STEREO) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
+ if (channelMode & A2DP_LDAC_CHANNEL_MODE_DUAL) {
+ codec_selectable_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ }
+
+ status = A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
+ ota_codec_peer_capability_);
+ CHECK(status == A2DP_SUCCESS);
+ return true;
+
+fail:
+ // Restore the internal state
+ codec_selectable_capability_ = saved_codec_selectable_capability;
+ memcpy(ota_codec_peer_capability_, saved_ota_codec_peer_capability,
+ sizeof(ota_codec_peer_capability_));
+ return false;
+}
diff --git a/stack/a2dp/a2dp_vendor_ldac_abr.cc b/stack/a2dp/a2dp_vendor_ldac_abr.cc
index 784da88..7715af4 100644
--- a/stack/a2dp/a2dp_vendor_ldac_abr.cc
+++ b/stack/a2dp/a2dp_vendor_ldac_abr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/a2dp/a2dp_vendor_ldac_encoder.cc b/stack/a2dp/a2dp_vendor_ldac_encoder.cc
index 4ca3cdf..21d5e72 100644
--- a/stack/a2dp/a2dp_vendor_ldac_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_ldac_encoder.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -180,7 +180,7 @@
uint8_t* num_of_frames,
uint64_t timestamp_us);
static void a2dp_ldac_encode_frames(uint8_t nb_frame);
-static bool a2dp_ldac_read_feeding(uint8_t* read_buffer);
+static bool a2dp_ldac_read_feeding(uint8_t* read_buffer, uint32_t* bytes_read);
static std::string quality_mode_index_to_name(int quality_mode_index);
static void* load_func(const char* func_name) {
@@ -359,6 +359,7 @@
}
a2dp_ldac_encoder_cb.has_ldac_handle = true;
}
+ CHECK(a2dp_ldac_encoder_cb.ldac_handle != nullptr);
if (!a2dp_codec_config->copyOutOtaCodecConfig(codec_info)) {
LOG_ERROR(LOG_TAG,
@@ -381,6 +382,7 @@
LOG_DEBUG(LOG_TAG, "%s: sample_rate=%u bits_per_sample=%u channel_count=%u",
__func__, p_feeding_params->sample_rate,
p_feeding_params->bits_per_sample, p_feeding_params->channel_count);
+ a2dp_vendor_ldac_feeding_reset();
// The codec parameters
p_encoder_params->sample_rate =
@@ -493,8 +495,13 @@
p_encoder_params->channel_mode, p_encoder_params->pcm_fmt,
p_encoder_params->sample_rate);
if (result != 0) {
- LOG_ERROR(LOG_TAG, "%s: error initializing the LDAC encoder: %d", __func__,
- result);
+ int err_code = ldac_get_error_code_func(a2dp_ldac_encoder_cb.ldac_handle);
+ LOG_ERROR(LOG_TAG,
+ "%s: error initializing the LDAC encoder: %d api_error = %d "
+ "handle_error = %d block_error = %d error_code = 0x%x",
+ __func__, result, LDACBT_API_ERR(err_code),
+ LDACBT_HANDLE_ERR(err_code), LDACBT_BLOCK_ERR(err_code),
+ err_code);
}
}
@@ -627,6 +634,7 @@
int32_t out_frames = 0;
int written = 0;
+ uint32_t bytes_read = 0;
while (nb_frame) {
BT_HDR* p_buf = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
p_buf->offset = A2DP_LDAC_OFFSET;
@@ -639,7 +647,9 @@
//
// Read the PCM data and encode it
//
- if (a2dp_ldac_read_feeding(read_buffer)) {
+ uint32_t temp_bytes_read = 0;
+ if (a2dp_ldac_read_feeding(read_buffer, &temp_bytes_read)) {
+ bytes_read += temp_bytes_read;
uint8_t* packet = (uint8_t*)(p_buf + 1) + p_buf->offset + p_buf->len;
if (a2dp_ldac_encoder_cb.ldac_handle == NULL) {
LOG_ERROR(LOG_TAG, "%s: invalid LDAC handle", __func__);
@@ -655,9 +665,10 @@
ldac_get_error_code_func(a2dp_ldac_encoder_cb.ldac_handle);
LOG_ERROR(LOG_TAG,
"%s: LDAC encoding error: %d api_error = %d "
- "handle_error = %d block_error = %d",
+ "handle_error = %d block_error = %d error_code = 0x%x",
__func__, result, LDACBT_API_ERR(err_code),
- LDACBT_HANDLE_ERR(err_code), LDACBT_BLOCK_ERR(err_code));
+ LDACBT_HANDLE_ERR(err_code), LDACBT_BLOCK_ERR(err_code),
+ err_code);
a2dp_ldac_encoder_cb.stats.media_read_total_dropped_packets++;
osi_free(p_buf);
return;
@@ -689,7 +700,9 @@
uint8_t done_nb_frame = remain_nb_frame - nb_frame;
remain_nb_frame = nb_frame;
- if (!a2dp_ldac_encoder_cb.enqueue_callback(p_buf, done_nb_frame)) return;
+ if (!a2dp_ldac_encoder_cb.enqueue_callback(p_buf, done_nb_frame,
+ bytes_read))
+ return;
} else {
// NOTE: Unlike the execution path for other codecs, it is normal for
// LDAC to NOT write encoded data to the last buffer if there wasn't
@@ -701,7 +714,7 @@
}
}
-static bool a2dp_ldac_read_feeding(uint8_t* read_buffer) {
+static bool a2dp_ldac_read_feeding(uint8_t* read_buffer, uint32_t* bytes_read) {
uint32_t read_size = LDACBT_ENC_LSU *
a2dp_ldac_encoder_cb.feeding_params.channel_count *
a2dp_ldac_encoder_cb.feeding_params.bits_per_sample / 8;
@@ -723,6 +736,7 @@
}
a2dp_ldac_encoder_cb.stats.media_read_total_actual_reads_count++;
+ *bytes_read = nb_byte_read;
return true;
}
@@ -749,6 +763,10 @@
return a2dp_vendor_ldac_get_encoder_interval_ms();
}
+int A2dpCodecConfigLdac::getEffectiveMtu() const {
+ return a2dp_ldac_encoder_cb.TxAaMtuSize;
+}
+
void A2dpCodecConfigLdac::debug_codec_dump(int fd) {
a2dp_ldac_encoder_stats_t* stats = &a2dp_ldac_encoder_cb.stats;
tA2DP_LDAC_ENCODER_PARAMS* p_encoder_params =
diff --git a/stack/avct/avct_api.cc b/stack/avct/avct_api.cc
index af789e3..5ced71f 100644
--- a/stack/avct/avct_api.cc
+++ b/stack/avct/avct_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2016 Broadcom Corporation
+ * Copyright 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/avct/avct_bcb_act.cc b/stack/avct/avct_bcb_act.cc
index 011a52d..616976e 100644
--- a/stack/avct/avct_bcb_act.cc
+++ b/stack/avct/avct_bcb_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2016 Broadcom Corporation
+ * Copyright 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,12 +17,12 @@
******************************************************************************/
/*****************************************************************************
-*
-* Name: avct_bcb_act.cc
-*
-* Description: This module contains action functions of the browsing control
-* state machine.
-*
+ *
+ * Name: avct_bcb_act.cc
+ *
+ * Description: This module contains action functions of the browsing
+ * control state machine.
+ *
*****************************************************************************/
#include <log/log.h>
@@ -187,7 +187,7 @@
}
/* if no ccbs bound to this lcb, disconnect */
- if (bind == false) {
+ if (!bind) {
avct_bcb_event(p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
return;
}
diff --git a/stack/avct/avct_ccb.cc b/stack/avct/avct_ccb.cc
index d15fff2..e551eaf 100644
--- a/stack/avct/avct_ccb.cc
+++ b/stack/avct/avct_ccb.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/avct/avct_defs.h b/stack/avct/avct_defs.h
index 73d4fcf..71748c5 100644
--- a/stack/avct/avct_defs.h
+++ b/stack/avct/avct_defs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/avct/avct_int.h b/stack/avct/avct_int.h
index 53b8b97..ff1bba2 100644
--- a/stack/avct/avct_int.h
+++ b/stack/avct/avct_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2016 Broadcom Corporation
+ * Copyright 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/avct/avct_l2c.cc b/stack/avct/avct_l2c.cc
index f81ed56..718a9c9 100644
--- a/stack/avct/avct_l2c.cc
+++ b/stack/avct/avct_l2c.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,19 +48,18 @@
void avct_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf);
/* L2CAP callback function structure */
-const tL2CAP_APPL_INFO avct_l2c_appl = {
- avct_l2c_connect_ind_cback,
- avct_l2c_connect_cfm_cback,
- NULL,
- avct_l2c_config_ind_cback,
- avct_l2c_config_cfm_cback,
- avct_l2c_disconnect_ind_cback,
- avct_l2c_disconnect_cfm_cback,
- NULL,
- avct_l2c_data_ind_cback,
- avct_l2c_congestion_ind_cback,
- NULL /* tL2CA_TX_COMPLETE_CB */
-};
+const tL2CAP_APPL_INFO avct_l2c_appl = {avct_l2c_connect_ind_cback,
+ avct_l2c_connect_cfm_cback,
+ NULL,
+ avct_l2c_config_ind_cback,
+ avct_l2c_config_cfm_cback,
+ avct_l2c_disconnect_ind_cback,
+ avct_l2c_disconnect_cfm_cback,
+ NULL,
+ avct_l2c_data_ind_cback,
+ avct_l2c_congestion_ind_cback,
+ NULL, /* tL2CA_TX_COMPLETE_CB */
+ NULL /* tL2CA_CREDITS_RECEIVED_CB */};
/*******************************************************************************
*
diff --git a/stack/avct/avct_l2c_br.cc b/stack/avct/avct_l2c_br.cc
index 3b364cd..1be8a7b 100644
--- a/stack/avct/avct_l2c_br.cc
+++ b/stack/avct/avct_l2c_br.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2016 Broadcom Corporation
+ * Copyright 2008-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -92,8 +92,8 @@
NULL,
avct_l2c_br_data_ind_cback,
avct_l2c_br_congestion_ind_cback,
- NULL /* tL2CA_TX_COMPLETE_CB */
-};
+ NULL, /* tL2CA_TX_COMPLETE_CB */
+ NULL /* tL2CA_CREDITS_RECEIVED_CB */};
/* Browsing channel eL2CAP default options */
const tL2CAP_FCR_OPTS avct_l2c_br_fcr_opts_def = {
diff --git a/stack/avct/avct_lcb.cc b/stack/avct/avct_lcb.cc
index 96156a2..8a9c8ee 100644
--- a/stack/avct/avct_lcb.cc
+++ b/stack/avct/avct_lcb.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/avct/avct_lcb_act.cc b/stack/avct/avct_lcb_act.cc
index e2ce9db..faa098b 100644
--- a/stack/avct/avct_lcb_act.cc
+++ b/stack/avct/avct_lcb_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -235,7 +235,7 @@
}
/* if no ccbs bound to this lcb, disconnect */
- if (bind == false) {
+ if (!bind) {
avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
}
}
@@ -419,7 +419,7 @@
/* set event */
event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT;
p_lcb->cong = p_data->cong;
- if (p_lcb->cong == false && !fixed_queue_is_empty(p_lcb->tx_q)) {
+ if (!p_lcb->cong && !fixed_queue_is_empty(p_lcb->tx_q)) {
while (!p_lcb->cong &&
(p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_lcb->tx_q)) != NULL) {
if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED) {
@@ -528,7 +528,7 @@
UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
}
- if (p_lcb->cong == true) {
+ if (p_lcb->cong) {
fixed_queue_enqueue(p_lcb->tx_q, p_buf);
}
diff --git a/stack/avdt/avdt_ad.cc b/stack/avdt/avdt_ad.cc
index 6143985..cc994b0 100644
--- a/stack/avdt/avdt_ad.cc
+++ b/stack/avdt/avdt_ad.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,24 @@
#include "l2cdefs.h"
#include "osi/include/osi.h"
+AvdtpScb* AvdtpAdaptationLayer::LookupAvdtpScb(
+ const AvdtpTransportChannel& tc) {
+ if (tc.ccb_idx >= AVDT_NUM_LINKS) {
+ AVDT_TRACE_ERROR("%s: AvdtpScb entry not found: invalid ccb_idx:%d",
+ __func__, tc.ccb_idx);
+ return nullptr;
+ }
+ if (tc.tcid >= AVDT_NUM_RT_TBL) {
+ AVDT_TRACE_ERROR("%s: AvdtpScb entry not found: invalid tcid:%d", __func__,
+ tc.tcid);
+ return nullptr;
+ }
+ const AvdtpRoutingEntry& re = rt_tbl[tc.ccb_idx][tc.tcid];
+ AVDT_TRACE_DEBUG("%s: ccb_idx:%d tcid:%d scb_hdl:%d", __func__, tc.ccb_idx,
+ tc.tcid, re.scb_hdl);
+ return avdt_scb_by_hdl(re.scb_hdl);
+}
+
/*******************************************************************************
*
* Function avdt_ad_type_to_tcid
@@ -45,19 +63,19 @@
* Returns TCID value.
*
******************************************************************************/
-uint8_t avdt_ad_type_to_tcid(uint8_t type, tAVDT_SCB* p_scb) {
- uint8_t scb_idx;
-
+uint8_t avdt_ad_type_to_tcid(uint8_t type, AvdtpScb* p_scb) {
if (type == AVDT_CHAN_SIG) {
return 0;
- } else {
- scb_idx = avdt_scb_to_hdl(p_scb) - 1;
- /*
- AVDT_TRACE_DEBUG("type: %d, tcid: %d", type, ((scb_idx *
- (AVDT_CHAN_NUM_TYPES - 1)) + type));
- */
- return ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type);
}
+ // The SCB Handle is unique in the [1, AVDT_NUM_LINKS * AVDT_NUM_SEPS]
+ // range. The scb_idx computed here is the SCB index for the corresponding
+ // SEP, and it is in the range [0, AVDT_NUM_SEPS) for a particular link.
+ uint8_t scb_idx = (avdt_scb_to_hdl(p_scb) - 1) % AVDT_NUM_LINKS;
+ // There are AVDT_CHAN_NUM_TYPES channel types per SEP. Here we compute
+ // the type index (TCID) from the SEP index and the type itself.
+ uint8_t tcid = (scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type;
+ AVDT_TRACE_DEBUG("%s: type:%d, tcid: %d", __func__, type, tcid);
+ return tcid;
}
/*******************************************************************************
@@ -99,8 +117,8 @@
******************************************************************************/
void avdt_ad_init(void) {
int i;
- tAVDT_TC_TBL* p_tbl = avdt_cb.ad.tc_tbl;
- memset(&avdt_cb.ad, 0, sizeof(tAVDT_AD));
+ AvdtpTransportChannel* p_tbl = avdtp_cb.ad.tc_tbl;
+ avdtp_cb.ad.Reset();
/* make sure the peer_mtu is a valid value */
for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) {
@@ -121,10 +139,10 @@
* first matching entry (there could be more than one).
*
******************************************************************************/
-tAVDT_TC_TBL* avdt_ad_tc_tbl_by_st(uint8_t type, tAVDT_CCB* p_ccb,
- uint8_t state) {
+AvdtpTransportChannel* avdt_ad_tc_tbl_by_st(uint8_t type, AvdtpCcb* p_ccb,
+ uint8_t state) {
int i;
- tAVDT_TC_TBL* p_tbl = avdt_cb.ad.tc_tbl;
+ AvdtpTransportChannel* p_tbl = avdtp_cb.ad.tc_tbl;
uint8_t ccb_idx;
if (p_ccb == NULL) {
@@ -173,13 +191,13 @@
* Returns Pointer to entry.
*
******************************************************************************/
-tAVDT_TC_TBL* avdt_ad_tc_tbl_by_lcid(uint16_t lcid) {
+AvdtpTransportChannel* avdt_ad_tc_tbl_by_lcid(uint16_t lcid) {
uint8_t idx;
- idx = avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
+ idx = avdtp_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
if (idx < AVDT_NUM_TC_TBL) {
- return &avdt_cb.ad.tc_tbl[idx];
+ return &avdtp_cb.ad.tc_tbl[idx];
} else {
return NULL;
}
@@ -196,11 +214,11 @@
* Returns Pointer to transport channel table entry.
*
******************************************************************************/
-tAVDT_TC_TBL* avdt_ad_tc_tbl_by_type(uint8_t type, tAVDT_CCB* p_ccb,
- tAVDT_SCB* p_scb) {
+AvdtpTransportChannel* avdt_ad_tc_tbl_by_type(uint8_t type, AvdtpCcb* p_ccb,
+ AvdtpScb* p_scb) {
uint8_t tcid;
int i;
- tAVDT_TC_TBL* p_tbl = avdt_cb.ad.tc_tbl;
+ AvdtpTransportChannel* p_tbl = avdtp_cb.ad.tc_tbl;
uint8_t ccb_idx = avdt_ccb_to_idx(p_ccb);
/* get tcid from type, scb */
@@ -227,9 +245,9 @@
* Returns Pointer to entry.
*
******************************************************************************/
-tAVDT_TC_TBL* avdt_ad_tc_tbl_alloc(tAVDT_CCB* p_ccb) {
+AvdtpTransportChannel* avdt_ad_tc_tbl_alloc(AvdtpCcb* p_ccb) {
int i;
- tAVDT_TC_TBL* p_tbl = avdt_cb.ad.tc_tbl;
+ AvdtpTransportChannel* p_tbl = avdtp_cb.ad.tc_tbl;
/* find next free entry in tc table */
for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) {
@@ -259,10 +277,10 @@
* Returns Index value.
*
******************************************************************************/
-uint8_t avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL* p_tbl) {
- AVDT_TRACE_DEBUG("avdt_ad_tc_tbl_to_idx: %d", (p_tbl - avdt_cb.ad.tc_tbl));
+uint8_t avdt_ad_tc_tbl_to_idx(AvdtpTransportChannel* p_tbl) {
+ AVDT_TRACE_DEBUG("avdt_ad_tc_tbl_to_idx: %d", (p_tbl - avdtp_cb.ad.tc_tbl));
/* use array arithmetic to determine index */
- return (uint8_t)(p_tbl - avdt_cb.ad.tc_tbl);
+ return (uint8_t)(p_tbl - avdtp_cb.ad.tc_tbl);
}
/*******************************************************************************
@@ -279,9 +297,10 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_tc_close_ind(tAVDT_TC_TBL* p_tbl, UNUSED_ATTR uint16_t reason) {
- tAVDT_CCB* p_ccb;
- tAVDT_SCB* p_scb;
+void avdt_ad_tc_close_ind(AvdtpTransportChannel* p_tbl,
+ UNUSED_ATTR uint16_t reason) {
+ AvdtpCcb* p_ccb;
+ AvdtpScb* p_scb;
tAVDT_SCB_TC_CLOSE close;
close.old_tc_state = p_tbl->state;
@@ -290,26 +309,27 @@
p_tbl->cfg_flags = 0;
p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
- AVDT_TRACE_DEBUG("avdt_ad_tc_close_ind tcid: %d, old: %d", p_tbl->tcid,
+ AVDT_TRACE_DEBUG("%s: tcid: %d, old: %d", __func__, p_tbl->tcid,
close.old_tc_state);
/* if signaling channel, notify ccb that channel open */
if (p_tbl->tcid == 0) {
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
+ return;
}
/* if media or other channel, notify scb that channel close */
- else {
- /* look up scb in stream routing table by ccb, tcid */
- p_scb =
- avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
- if (p_scb != NULL) {
- close.tcid = p_tbl->tcid;
- close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
- tAVDT_SCB_EVT avdt_scb_evt;
- avdt_scb_evt.close = close;
- avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, &avdt_scb_evt);
- }
+ /* look up scb in stream routing table by ccb, tcid */
+ p_scb = avdtp_cb.ad.LookupAvdtpScb(*p_tbl);
+ if (p_scb == nullptr) {
+ AVDT_TRACE_ERROR("%s: Cannot find AvdtScb entry: ccb_idx:%d tcid:%d",
+ __func__, p_tbl->ccb_idx, p_tbl->tcid);
+ return;
}
+ close.tcid = p_tbl->tcid;
+ close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
+ tAVDT_SCB_EVT avdt_scb_evt;
+ avdt_scb_evt.close = close;
+ avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, &avdt_scb_evt);
}
/*******************************************************************************
@@ -324,18 +344,22 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_tc_open_ind(tAVDT_TC_TBL* p_tbl) {
- tAVDT_CCB* p_ccb;
- tAVDT_SCB* p_scb;
+void avdt_ad_tc_open_ind(AvdtpTransportChannel* p_tbl) {
+ AvdtpCcb* p_ccb;
+ AvdtpScb* p_scb;
tAVDT_OPEN open;
tAVDT_EVT_HDR evt;
+ AVDT_TRACE_DEBUG("%s: p_tbl:%p state:%d ccb_idx:%d tcid:%d scb_hdl:%d",
+ __func__, p_tbl, p_tbl->state, p_tbl->ccb_idx, p_tbl->tcid,
+ avdtp_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
+
p_tbl->state = AVDT_AD_ST_OPEN;
/* if signaling channel, notify ccb that channel open */
if (p_tbl->tcid == 0) {
/* set the signal channel to use high priority within the ACL link */
- L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid,
+ L2CA_SetTxPriority(avdtp_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid,
L2CAP_CHNL_PRIORITY_HIGH);
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
@@ -348,23 +372,23 @@
tAVDT_CCB_EVT avdt_ccb_evt;
avdt_ccb_evt.msg.hdr = evt;
avdt_ccb_event(p_ccb, AVDT_CCB_LL_OPEN_EVT, &avdt_ccb_evt);
+ return;
}
/* if media or other channel, notify scb that channel open */
- else {
- /* look up scb in stream routing table by ccb, tcid */
- p_scb =
- avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
-
- /* put lcid in event data */
- if (p_scb != NULL) {
- open.peer_mtu = p_tbl->peer_mtu;
- open.lcid = avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid;
- open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid);
- tAVDT_SCB_EVT avdt_scb_evt;
- avdt_scb_evt.open = open;
- avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, &avdt_scb_evt);
- }
+ /* look up scb in stream routing table by ccb, tcid */
+ p_scb = avdtp_cb.ad.LookupAvdtpScb(*p_tbl);
+ if (p_scb == nullptr) {
+ AVDT_TRACE_ERROR("%s: Cannot find AvdtScb entry: ccb_idx:%d tcid:%d",
+ __func__, p_tbl->ccb_idx, p_tbl->tcid);
+ return;
}
+ /* put lcid in event data */
+ open.peer_mtu = p_tbl->peer_mtu;
+ open.lcid = avdtp_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid;
+ open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid);
+ tAVDT_SCB_EVT avdt_scb_evt;
+ avdt_scb_evt.open = open;
+ avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, &avdt_scb_evt);
}
/*******************************************************************************
@@ -381,9 +405,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_tc_cong_ind(tAVDT_TC_TBL* p_tbl, bool is_congested) {
- tAVDT_CCB* p_ccb;
- tAVDT_SCB* p_scb;
+void avdt_ad_tc_cong_ind(AvdtpTransportChannel* p_tbl, bool is_congested) {
+ AvdtpCcb* p_ccb;
+ AvdtpScb* p_scb;
/* if signaling channel, notify ccb of congestion */
if (p_tbl->tcid == 0) {
@@ -391,18 +415,19 @@
tAVDT_CCB_EVT avdt_ccb_evt;
avdt_ccb_evt.llcong = is_congested;
avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, &avdt_ccb_evt);
+ return;
}
/* if media or other channel, notify scb that channel open */
- else {
- /* look up scb in stream routing table by ccb, tcid */
- p_scb =
- avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
- if (p_scb != NULL) {
- tAVDT_SCB_EVT avdt_scb_evt;
- avdt_scb_evt.llcong = is_congested;
- avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, &avdt_scb_evt);
- }
+ /* look up scb in stream routing table by ccb, tcid */
+ p_scb = avdtp_cb.ad.LookupAvdtpScb(*p_tbl);
+ if (p_scb == nullptr) {
+ AVDT_TRACE_ERROR("%s: Cannot find AvdtScb entry: ccb_idx:%d tcid:%d",
+ __func__, p_tbl->ccb_idx, p_tbl->tcid);
+ return;
}
+ tAVDT_SCB_EVT avdt_scb_evt;
+ avdt_scb_evt.llcong = is_congested;
+ avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, &avdt_scb_evt);
}
/*******************************************************************************
@@ -417,9 +442,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_tc_data_ind(tAVDT_TC_TBL* p_tbl, BT_HDR* p_buf) {
- tAVDT_CCB* p_ccb;
- tAVDT_SCB* p_scb;
+void avdt_ad_tc_data_ind(AvdtpTransportChannel* p_tbl, BT_HDR* p_buf) {
+ AvdtpCcb* p_ccb;
+ AvdtpScb* p_scb;
/* store type (media, recovery, reporting) */
p_buf->layer_specific = avdt_ad_tcid_to_type(p_tbl->tcid);
@@ -428,18 +453,18 @@
if (p_tbl->tcid == 0) {
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
avdt_msg_ind(p_ccb, p_buf);
+ return;
}
/* if media or other channel, send event to scb */
- else {
- p_scb =
- avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
- if (p_scb != NULL) {
- avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT*)&p_buf);
- } else {
- osi_free(p_buf);
- AVDT_TRACE_ERROR(" avdt_ad_tc_data_ind buffer freed");
- }
+ p_scb = avdtp_cb.ad.LookupAvdtpScb(*p_tbl);
+ if (p_scb == nullptr) {
+ AVDT_TRACE_ERROR("%s: Cannot find AvdtScb entry: ccb_idx:%d tcid:%d",
+ __func__, p_tbl->ccb_idx, p_tbl->tcid);
+ osi_free(p_buf);
+ AVDT_TRACE_ERROR("%s: buffer freed", __func__);
+ return;
}
+ avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT*)&p_buf);
}
/*******************************************************************************
@@ -458,14 +483,14 @@
* AVDT_AD_FAILED, if error
*
******************************************************************************/
-uint8_t avdt_ad_write_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb,
+uint8_t avdt_ad_write_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb,
BT_HDR* p_buf) {
uint8_t tcid;
/* get tcid from type, scb */
tcid = avdt_ad_type_to_tcid(type, p_scb);
- return L2CA_DataWrite(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid,
+ return L2CA_DataWrite(avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid,
p_buf);
}
@@ -485,9 +510,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_open_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb,
+void avdt_ad_open_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb,
uint8_t role) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
uint16_t lcid;
p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
@@ -502,17 +527,17 @@
if (type == AVDT_CHAN_SIG) {
/* if signaling, get mtu from registration control block */
- p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
+ p_tbl->my_mtu = avdtp_cb.rcb.ctrl_mtu;
p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
} else {
/* otherwise get mtu from scb */
- p_tbl->my_mtu = p_scb->cs.mtu;
- p_tbl->my_flush_to = p_scb->cs.flush_to;
+ p_tbl->my_mtu = p_scb->stream_config.mtu;
+ p_tbl->my_flush_to = p_scb->stream_config.flush_to;
/* also set scb_hdl in rt_tbl */
- avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl =
+ avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl =
avdt_scb_to_hdl(p_scb);
- AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].scb_hdl = %d",
+ AVDT_TRACE_DEBUG("avdtp_cb.ad.rt_tbl[%d][%d].scb_hdl = %d",
avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
avdt_scb_to_hdl(p_scb));
}
@@ -529,14 +554,14 @@
lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr);
if (lcid != 0) {
/* if connect req ok, store tcid in lcid table */
- avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
+ avdtp_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
avdt_ad_tc_tbl_to_idx(p_tbl);
- AVDT_TRACE_DEBUG("avdt_cb.ad.lcid_tbl[%d] = %d",
+ AVDT_TRACE_DEBUG("avdtp_cb.ad.lcid_tbl[%d] = %d",
(lcid - L2CAP_BASE_APPL_CID),
avdt_ad_tc_tbl_to_idx(p_tbl));
- avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
- AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].lcid = 0x%x",
+ avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
+ AVDT_TRACE_DEBUG("avdtp_cb.ad.rt_tbl[%d][%d].lcid = 0x%x",
avdt_ccb_to_idx(p_ccb), p_tbl->tcid, lcid);
} else {
/* if connect req failed, call avdt_ad_tc_close_ind() */
@@ -557,9 +582,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_close_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb) {
+void avdt_ad_close_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb) {
uint8_t tcid;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb);
AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d", p_tbl->state);
@@ -577,6 +602,6 @@
tcid = avdt_ad_type_to_tcid(type, p_scb);
/* call l2cap disconnect req */
- L2CA_DisconnectReq(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
+ L2CA_DisconnectReq(avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
}
}
diff --git a/stack/avdt/avdt_api.cc b/stack/avdt/avdt_api.cc
index a507841..43954b4 100644
--- a/stack/avdt/avdt_api.cc
+++ b/stack/avdt/avdt_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,11 +34,11 @@
#include "l2c_api.h"
#include "stack/include/a2dp_codec_api.h"
-/* Control block for AVDT */
-tAVDT_CB avdt_cb;
+/* Control block for AVDTP */
+AvdtpCb avdtp_cb;
void avdt_ccb_idle_ccb_timer_timeout(void* data) {
- tAVDT_CCB* p_ccb = (tAVDT_CCB*)data;
+ AvdtpCcb* p_ccb = (AvdtpCcb*)data;
uint8_t avdt_event = AVDT_CCB_IDLE_TOUT_EVT;
uint8_t err_code = AVDT_ERR_TIMEOUT;
@@ -48,7 +48,7 @@
}
void avdt_ccb_ret_ccb_timer_timeout(void* data) {
- tAVDT_CCB* p_ccb = (tAVDT_CCB*)data;
+ AvdtpCcb* p_ccb = (AvdtpCcb*)data;
uint8_t avdt_event = AVDT_CCB_RET_TOUT_EVT;
uint8_t err_code = AVDT_ERR_TIMEOUT;
@@ -58,7 +58,7 @@
}
void avdt_ccb_rsp_ccb_timer_timeout(void* data) {
- tAVDT_CCB* p_ccb = (tAVDT_CCB*)data;
+ AvdtpCcb* p_ccb = (AvdtpCcb*)data;
uint8_t avdt_event = AVDT_CCB_RSP_TOUT_EVT;
uint8_t err_code = AVDT_ERR_TIMEOUT;
@@ -68,7 +68,7 @@
}
void avdt_scb_transport_channel_timer_timeout(void* data) {
- tAVDT_SCB* p_scb = (tAVDT_SCB*)data;
+ AvdtpScb* p_scb = (AvdtpScb*)data;
uint8_t avdt_event = AVDT_SCB_TC_TOUT_EVT;
avdt_scb_event(p_scb, avdt_event, NULL);
@@ -88,7 +88,7 @@
* Returns void
*
******************************************************************************/
-void AVDT_Register(tAVDT_REG* p_reg, tAVDT_CTRL_CBACK* p_cback) {
+void AVDT_Register(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback) {
/* register PSM with L2CAP */
L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl);
@@ -104,13 +104,11 @@
BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_MEDIA);
-#if (AVDT_REPORTING == TRUE)
/* do not use security on the reporting channel */
BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT);
BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE,
AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT);
-#endif
/* initialize AVDTP data structures */
avdt_scb_init();
@@ -118,8 +116,8 @@
avdt_ad_init();
/* copy registration struct */
- memcpy(&avdt_cb.rcb, p_reg, sizeof(tAVDT_REG));
- avdt_cb.p_conn_cback = p_cback;
+ avdtp_cb.rcb = *p_reg;
+ avdtp_cb.p_conn_cback = p_cback;
}
/*******************************************************************************
@@ -144,7 +142,7 @@
void AVDT_AbortReq(uint8_t handle) {
AVDT_TRACE_WARNING("%s: handle=%d", __func__, handle);
- tAVDT_SCB* p_scb = avdt_scb_by_hdl(handle);
+ AvdtpScb* p_scb = avdt_scb_by_hdl(handle);
if (p_scb != NULL) {
avdt_scb_event(p_scb, AVDT_SCB_API_ABORT_REQ_EVT, NULL);
} else {
@@ -166,20 +164,21 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_CreateStream(uint8_t* p_handle, tAVDT_CS* p_cs) {
+uint16_t AVDT_CreateStream(uint8_t peer_id, uint8_t* p_handle,
+ const AvdtpStreamConfig& avdtp_stream_config) {
uint16_t result = AVDT_SUCCESS;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
- AVDT_TRACE_DEBUG("%s", __func__);
+ AVDT_TRACE_DEBUG("%s: peer_id=%d", __func__, peer_id);
/* Verify parameters; if invalid, return failure */
- if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) ||
- (p_cs->p_ctrl_cback == NULL)) {
+ if (((avdtp_stream_config.cfg.psc_mask & (~AVDT_PSC)) != 0) ||
+ (avdtp_stream_config.p_avdt_ctrl_cback == NULL)) {
result = AVDT_BAD_PARAMS;
}
/* Allocate scb; if no scbs, return failure */
else {
- p_scb = avdt_scb_alloc(p_cs);
+ p_scb = avdt_scb_alloc(peer_id, avdtp_stream_config);
if (p_scb == NULL) {
result = AVDT_NO_RESOURCES;
} else {
@@ -187,7 +186,8 @@
}
}
- AVDT_TRACE_DEBUG("%s: result=%d", __func__, result);
+ AVDT_TRACE_DEBUG("%s: result=%d handle=%d scb_index=%d", __func__, result,
+ *p_handle, avdtp_stream_config.scb_index);
return result;
}
@@ -208,7 +208,7 @@
******************************************************************************/
uint16_t AVDT_RemoveStream(uint8_t handle) {
uint16_t result = AVDT_SUCCESS;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
AVDT_TRACE_DEBUG("%s: handle=%d", __func__, handle);
@@ -252,9 +252,10 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_DiscoverReq(const RawAddress& bd_addr, tAVDT_SEP_INFO* p_sep_info,
- uint8_t max_seps, tAVDT_CTRL_CBACK* p_cback) {
- tAVDT_CCB* p_ccb;
+uint16_t AVDT_DiscoverReq(const RawAddress& bd_addr, uint8_t channel_index,
+ tAVDT_SEP_INFO* p_sep_info, uint8_t max_seps,
+ tAVDT_CTRL_CBACK* p_cback) {
+ AvdtpCcb* p_ccb;
uint16_t result = AVDT_SUCCESS;
tAVDT_CCB_EVT evt;
@@ -263,7 +264,7 @@
/* find channel control block for this bd addr; if none, allocate one */
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb == NULL) {
- p_ccb = avdt_ccb_alloc(bd_addr);
+ p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
if (p_ccb == NULL) {
/* could not allocate channel control block */
result = AVDT_NO_RESOURCES;
@@ -293,15 +294,15 @@
*
* Function avdt_get_cap_req
*
- * Description internal function to serve both AVDT_GetCapReq and
- * AVDT_GetAllCapReq
+ * Description internal function to serve AVDT_GetCapReq
*
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
static uint16_t avdt_get_cap_req(const RawAddress& bd_addr,
+ uint8_t channel_index,
tAVDT_CCB_API_GETCAP* p_evt) {
- tAVDT_CCB* p_ccb = NULL;
+ AvdtpCcb* p_ccb = NULL;
uint16_t result = AVDT_SUCCESS;
AVDT_TRACE_DEBUG("%s", __func__);
@@ -316,7 +317,7 @@
else {
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb == NULL) {
- p_ccb = avdt_ccb_alloc(bd_addr);
+ p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
if (p_ccb == NULL) {
/* could not allocate channel control block */
result = AVDT_NO_RESOURCES;
@@ -364,60 +365,23 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_GetCapReq(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback) {
+uint16_t AVDT_GetCapReq(const RawAddress& bd_addr, uint8_t channel_index,
+ uint8_t seid, AvdtpSepConfig* p_cfg,
+ tAVDT_CTRL_CBACK* p_cback, bool get_all_cap) {
tAVDT_CCB_API_GETCAP getcap;
uint16_t result = AVDT_SUCCESS;
AVDT_TRACE_DEBUG("%s", __func__);
getcap.single.seid = seid;
- getcap.single.sig_id = AVDT_SIG_GETCAP;
+ if (get_all_cap) {
+ getcap.single.sig_id = AVDT_SIG_GET_ALLCAP;
+ } else {
+ getcap.single.sig_id = AVDT_SIG_GETCAP;
+ }
getcap.p_cfg = p_cfg;
getcap.p_cback = p_cback;
- result = avdt_get_cap_req(bd_addr, &getcap);
-
- AVDT_TRACE_DEBUG("%s: result=%d", __func__, result);
-
- return result;
-}
-
-/*******************************************************************************
- *
- * Function AVDT_GetAllCapReq
- *
- * Description This function initiates a connection to the AVDTP service
- * on the peer device, if not already present, and gets the
- * capabilities of a stream endpoint on the peer device.
- * This function can be called at any time regardless of
- * whether there is an AVDTP connection to the peer device.
- *
- * When the procedure is complete, an AVDT_GETCAP_CFM_EVT is
- * sent to the application via its callback function. The
- * application must not call AVDT_GetCapReq() or
- * AVDT_DiscoverReq() again until the procedure is complete.
- *
- * The memory pointed to by p_cfg is allocated by the
- * application. This memory is written to by AVDTP as part
- * of the get capabilities procedure. This memory must
- * remain accessible until the application receives
- * the AVDT_GETCAP_CFM_EVT.
- *
- * Returns AVDT_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-uint16_t AVDT_GetAllCapReq(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback) {
- tAVDT_CCB_API_GETCAP getcap;
- uint16_t result = AVDT_SUCCESS;
-
- AVDT_TRACE_DEBUG("%s", __func__);
-
- getcap.single.seid = seid;
- getcap.single.sig_id = AVDT_SIG_GET_ALLCAP;
- getcap.p_cfg = p_cfg;
- getcap.p_cback = p_cback;
- result = avdt_get_cap_req(bd_addr, &getcap);
+ result = avdt_get_cap_req(bd_addr, channel_index, &getcap);
AVDT_TRACE_DEBUG("%s: result=%d", __func__, result);
@@ -436,7 +400,7 @@
*
******************************************************************************/
uint16_t AVDT_DelayReport(uint8_t handle, uint8_t seid, uint16_t delay) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
@@ -474,10 +438,11 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_OpenReq(uint8_t handle, const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg) {
- tAVDT_CCB* p_ccb = NULL;
- tAVDT_SCB* p_scb = NULL;
+uint16_t AVDT_OpenReq(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t channel_index, uint8_t seid,
+ AvdtpSepConfig* p_cfg) {
+ AvdtpCcb* p_ccb = NULL;
+ AvdtpScb* p_scb = NULL;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
@@ -497,7 +462,7 @@
else {
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb == NULL) {
- p_ccb = avdt_ccb_alloc(bd_addr);
+ p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
if (p_ccb == NULL) {
/* could not allocate channel control block */
result = AVDT_NO_RESOURCES;
@@ -508,7 +473,8 @@
/* send event to scb */
if (result == AVDT_SUCCESS) {
- A2DP_DumpCodecInfo(p_cfg->codec_info);
+ AVDT_TRACE_DEBUG("%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_cfg->codec_info).c_str());
evt.msg.config_cmd.hdr.seid = seid;
evt.msg.config_cmd.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
@@ -536,13 +502,13 @@
******************************************************************************/
uint16_t AVDT_ConfigRsp(uint8_t handle, uint8_t label, uint8_t error_code,
uint8_t category) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_SCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
uint8_t event_code;
- AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=%d category=%d", __func__,
- handle, label, error_code, category);
+ AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=0x%x category=%d",
+ __func__, handle, label, error_code, category);
/* map handle to scb */
p_scb = avdt_scb_by_hdl(handle);
@@ -589,7 +555,7 @@
*
******************************************************************************/
uint16_t AVDT_StartReq(uint8_t* p_handles, uint8_t num_handles) {
- tAVDT_SCB* p_scb = NULL;
+ AvdtpScb* p_scb = NULL;
tAVDT_CCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
int i;
@@ -641,7 +607,7 @@
*
******************************************************************************/
uint16_t AVDT_SuspendReq(uint8_t* p_handles, uint8_t num_handles) {
- tAVDT_SCB* p_scb = NULL;
+ AvdtpScb* p_scb = NULL;
tAVDT_CCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
int i;
@@ -692,7 +658,7 @@
*
******************************************************************************/
uint16_t AVDT_CloseReq(uint8_t handle) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
AVDT_TRACE_DEBUG("%s: handle=%d", __func__, handle);
@@ -729,8 +695,8 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_ReconfigReq(uint8_t handle, tAVDT_CFG* p_cfg) {
- tAVDT_SCB* p_scb;
+uint16_t AVDT_ReconfigReq(uint8_t handle, AvdtpSepConfig* p_cfg) {
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
@@ -768,12 +734,12 @@
******************************************************************************/
uint16_t AVDT_ReconfigRsp(uint8_t handle, uint8_t label, uint8_t error_code,
uint8_t category) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_SCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
- AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=%d category=%d", __func__,
- handle, label, error_code, category);
+ AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=0x%x category=%d",
+ __func__, handle, label, error_code, category);
/* map handle to scb */
p_scb = avdt_scb_by_hdl(handle);
@@ -808,7 +774,7 @@
*
******************************************************************************/
uint16_t AVDT_SecurityReq(uint8_t handle, uint8_t* p_data, uint16_t len) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
@@ -847,11 +813,11 @@
******************************************************************************/
uint16_t AVDT_SecurityRsp(uint8_t handle, uint8_t label, uint8_t error_code,
uint8_t* p_data, uint16_t len) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
- AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=%d len=%d", __func__,
+ AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=0x%x len=%d", __func__,
handle, label, error_code, len);
/* map handle to scb */
@@ -912,7 +878,7 @@
******************************************************************************/
uint16_t AVDT_WriteReqOpt(uint8_t handle, BT_HDR* p_pkt, uint32_t time_stamp,
uint8_t m_pt, tAVDT_DATA_OPT_MASK opt) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_SCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
@@ -990,23 +956,24 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_ConnectReq(const RawAddress& bd_addr, uint8_t sec_mask,
- tAVDT_CTRL_CBACK* p_cback) {
- tAVDT_CCB* p_ccb = NULL;
+uint16_t AVDT_ConnectReq(const RawAddress& bd_addr, uint8_t channel_index,
+ uint8_t sec_mask, tAVDT_CTRL_CBACK* p_cback) {
+ AvdtpCcb* p_ccb = NULL;
uint16_t result = AVDT_SUCCESS;
tAVDT_CCB_EVT evt;
- AVDT_TRACE_DEBUG("%s: sec_mask=0x%x", __func__, sec_mask);
+ AVDT_TRACE_WARNING("%s: address=%s channel_index=%d sec_mask=0x%x", __func__,
+ bd_addr.ToString().c_str(), channel_index, sec_mask);
/* find channel control block for this bd addr; if none, allocate one */
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb == NULL) {
- p_ccb = avdt_ccb_alloc(bd_addr);
+ p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
if (p_ccb == NULL) {
/* could not allocate channel control block */
result = AVDT_NO_RESOURCES;
}
- } else if (p_ccb->ll_opened == false) {
+ } else if (!p_ccb->ll_opened) {
AVDT_TRACE_WARNING("AVDT_ConnectReq: CCB LL is in the middle of opening");
/* ccb was already allocated for the incoming signalling. */
@@ -1020,7 +987,8 @@
avdt_ccb_event(p_ccb, AVDT_CCB_API_CONNECT_REQ_EVT, &evt);
}
- AVDT_TRACE_DEBUG("%s: result=%d", __func__, result);
+ AVDT_TRACE_WARNING("%s: address=%s result=%d", __func__,
+ bd_addr.ToString().c_str(), result);
return result;
}
@@ -1039,7 +1007,7 @@
******************************************************************************/
uint16_t AVDT_DisconnectReq(const RawAddress& bd_addr,
tAVDT_CTRL_CBACK* p_cback) {
- tAVDT_CCB* p_ccb = NULL;
+ AvdtpCcb* p_ccb = NULL;
uint16_t result = AVDT_SUCCESS;
tAVDT_CCB_EVT evt;
@@ -1073,8 +1041,8 @@
*
******************************************************************************/
uint16_t AVDT_GetL2CapChannel(uint8_t handle) {
- tAVDT_SCB* p_scb;
- tAVDT_CCB* p_ccb;
+ AvdtpScb* p_scb;
+ AvdtpCcb* p_ccb;
uint8_t tcid;
uint16_t lcid = 0;
@@ -1084,7 +1052,7 @@
/* get tcid from type, scb */
tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
- lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ lcid = avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
}
return (lcid);
@@ -1101,26 +1069,25 @@
*
******************************************************************************/
uint16_t AVDT_GetSignalChannel(uint8_t handle, const RawAddress& bd_addr) {
- tAVDT_SCB* p_scb;
- tAVDT_CCB* p_ccb;
+ AvdtpScb* p_scb;
+ AvdtpCcb* p_ccb;
uint8_t tcid = 0; /* tcid is always 0 for signal channel */
uint16_t lcid = 0;
/* map handle to scb */
if (((p_scb = avdt_scb_by_hdl(handle)) != NULL) &&
((p_ccb = p_scb->p_ccb) != NULL)) {
- lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ lcid = avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
} else {
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb != NULL) {
- lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ lcid = avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
}
}
return (lcid);
}
-#if (AVDT_REPORTING == TRUE)
/*******************************************************************************
*
* Function AVDT_SendReport
@@ -1134,9 +1101,9 @@
******************************************************************************/
uint16_t AVDT_SendReport(uint8_t handle, AVDT_REPORT_TYPE type,
tAVDT_REPORT_DATA* p_data) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_BAD_PARAMS;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
uint8_t *p, *plen, *pm1, *p_end;
uint32_t ssrc;
uint16_t len;
@@ -1145,8 +1112,10 @@
/* map handle to scb && verify parameters */
if (((p_scb = avdt_scb_by_hdl(handle)) != NULL) && (p_scb->p_ccb != NULL) &&
- (((type == AVDT_RTCP_PT_SR) && (p_scb->cs.tsep == AVDT_TSEP_SRC)) ||
- ((type == AVDT_RTCP_PT_RR) && (p_scb->cs.tsep == AVDT_TSEP_SNK)) ||
+ (((type == AVDT_RTCP_PT_SR) &&
+ (p_scb->stream_config.tsep == AVDT_TSEP_SRC)) ||
+ ((type == AVDT_RTCP_PT_RR) &&
+ (p_scb->stream_config.tsep == AVDT_TSEP_SNK)) ||
(type == AVDT_RTCP_PT_SDES))) {
result = AVDT_NO_RESOURCES;
@@ -1214,7 +1183,6 @@
return result;
}
-#endif
/******************************************************************************
*
@@ -1238,7 +1206,65 @@
*
*****************************************************************************/
uint8_t AVDT_SetTraceLevel(uint8_t new_level) {
- if (new_level != 0xFF) avdt_cb.trace_level = new_level;
+ if (new_level != 0xFF) avdtp_cb.SetTraceLevel(new_level);
- return (avdt_cb.trace_level);
+ return avdtp_cb.TraceLevel();
+}
+
+void stack_debug_avdtp_api_dump(int fd) {
+ dprintf(fd, "\nAVDTP Stack State:\n");
+ dprintf(fd, " AVDTP signalling L2CAP channel MTU: %d\n",
+ avdtp_cb.rcb.ctrl_mtu);
+ dprintf(fd, " Security mask: 0x%x\n", avdtp_cb.rcb.sec_mask);
+
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ const AvdtpCcb& ccb = avdtp_cb.ccb[i];
+ dprintf(fd, "\n Channel control block: %zu peer: %s\n", i,
+ ccb.peer_addr.ToString().c_str());
+ dprintf(fd, " Allocated: %s\n", ccb.allocated ? "true" : "false");
+ dprintf(fd, " State: %d\n", ccb.state);
+ dprintf(fd, " Link-layer opened: %s\n",
+ ccb.ll_opened ? "true" : "false");
+ dprintf(fd, " Discover in progress: %s\n",
+ ccb.proc_busy ? "true" : "false");
+ dprintf(fd, " Congested: %s\n", ccb.cong ? "true" : "false");
+ dprintf(fd, " Reinitiate connection on idle: %s\n",
+ ccb.reconn ? "true" : "false");
+ dprintf(fd, " Command retransmission count: %d\n", ccb.ret_count);
+ dprintf(fd, " BTA AV SCB index: %d\n", ccb.BtaAvScbIndex());
+
+ for (size_t i = 0; i < AVDT_NUM_SEPS; i++) {
+ const AvdtpScb& scb = ccb.scb[i];
+ dprintf(fd, "\n Stream control block: %zu\n", i);
+ dprintf(fd, " SEP codec: %s\n",
+ A2DP_CodecName(scb.stream_config.cfg.codec_info));
+ dprintf(fd, " SEP protocol service capabilities: 0x%x\n",
+ scb.stream_config.cfg.psc_mask);
+ dprintf(fd, " SEP type: 0x%x\n", scb.stream_config.tsep);
+ dprintf(fd, " Media type: 0x%x\n", scb.stream_config.media_type);
+ dprintf(fd, " MTU: %d\n", scb.stream_config.mtu);
+ dprintf(fd, " SCB handle: %d\n", scb.ScbHandle());
+ dprintf(fd, " SCB index: %d\n", scb.stream_config.scb_index);
+ dprintf(fd, " Configured codec: %s\n",
+ A2DP_CodecName(scb.curr_cfg.codec_info));
+ dprintf(fd, " Requested codec: %s\n",
+ A2DP_CodecName(scb.req_cfg.codec_info));
+ dprintf(fd, " Transport channel connect timer: %s\n",
+ alarm_is_scheduled(scb.transport_channel_timer)
+ ? "Scheduled"
+ : "Not scheduled");
+ dprintf(fd, " Channel control block peer: %s\n",
+ (scb.p_ccb != nullptr) ? scb.p_ccb->peer_addr.ToString().c_str()
+ : "null");
+ dprintf(fd, " Allocated: %s\n", scb.allocated ? "true" : "false");
+ dprintf(fd, " In use: %s\n", scb.in_use ? "true" : "false");
+ dprintf(fd, " Role: 0x%x\n", scb.role);
+ dprintf(fd, " Remove: %s\n", scb.remove ? "true" : "false");
+ dprintf(fd, " State: %d\n", scb.state);
+ dprintf(fd, " Peer SEID: %d\n", scb.peer_seid);
+ dprintf(fd, " Current event: %d\n", scb.curr_evt);
+ dprintf(fd, " Congested: %s\n", scb.cong ? "true" : "false");
+ dprintf(fd, " Close response code: %d\n", scb.close_code);
+ }
+ }
}
diff --git a/stack/avdt/avdt_ccb.cc b/stack/avdt/avdt_ccb.cc
index 87e2fd5..edaf4f9 100644
--- a/stack/avdt/avdt_ccb.cc
+++ b/stack/avdt/avdt_ccb.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -348,8 +348,10 @@
*
******************************************************************************/
void avdt_ccb_init(void) {
- memset(&avdt_cb.ccb[0], 0, sizeof(tAVDT_CCB) * AVDT_NUM_LINKS);
- avdt_cb.p_ccb_act = (tAVDT_CCB_ACTION*)avdt_ccb_action;
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ avdtp_cb.ccb[i].Reset(i);
+ }
+ avdtp_cb.p_ccb_act = avdt_ccb_action;
}
/*******************************************************************************
@@ -362,15 +364,15 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ccb_event(tAVDT_CCB* p_ccb, uint8_t event, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_event(AvdtpCcb* p_ccb, uint8_t event, tAVDT_CCB_EVT* p_data) {
tAVDT_CCB_ST_TBL state_table;
uint8_t action;
int i;
#if (AVDT_DEBUG == TRUE)
- AVDT_TRACE_EVENT("%s: CCB ccb=%d event=%s state=%s", __func__,
+ AVDT_TRACE_EVENT("%s: CCB ccb=%d event=%s state=%s p_ccb=%p", __func__,
avdt_ccb_to_idx(p_ccb), avdt_ccb_evt_str[event],
- avdt_ccb_st_str[p_ccb->state]);
+ avdt_ccb_st_str[p_ccb->state], p_ccb);
#endif
/* look up the state table for the current state */
@@ -388,7 +390,7 @@
avdt_ccb_evt_str[event], avdt_ccb_st_str[p_ccb->state],
action);
if (action != AVDT_CCB_IGNORE) {
- (*avdt_cb.p_ccb_act[action])(p_ccb, p_data);
+ (*avdtp_cb.p_ccb_act[action])(p_ccb, p_data);
} else {
break;
}
@@ -405,8 +407,8 @@
* Returns pointer to the ccb, or NULL if none found.
*
******************************************************************************/
-tAVDT_CCB* avdt_ccb_by_bd(const RawAddress& bd_addr) {
- tAVDT_CCB* p_ccb = &avdt_cb.ccb[0];
+AvdtpCcb* avdt_ccb_by_bd(const RawAddress& bd_addr) {
+ AvdtpCcb* p_ccb = &avdtp_cb.ccb[0];
int i;
for (i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++) {
@@ -435,32 +437,53 @@
* Returns pointer to the ccb, or NULL if none could be allocated.
*
******************************************************************************/
-tAVDT_CCB* avdt_ccb_alloc(const RawAddress& bd_addr) {
- tAVDT_CCB* p_ccb = &avdt_cb.ccb[0];
- int i;
-
- for (i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++) {
+AvdtpCcb* avdt_ccb_alloc(const RawAddress& bd_addr) {
+ // Find available entry
+ AvdtpCcb* p_ccb = &avdtp_cb.ccb[0];
+ for (int i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++) {
if (!p_ccb->allocated) {
- p_ccb->allocated = true;
- p_ccb->peer_addr = bd_addr;
- p_ccb->cmd_q = fixed_queue_new(SIZE_MAX);
- p_ccb->rsp_q = fixed_queue_new(SIZE_MAX);
- p_ccb->idle_ccb_timer = alarm_new("avdt_ccb.idle_ccb_timer");
- p_ccb->ret_ccb_timer = alarm_new("avdt_ccb.ret_ccb_timer");
- p_ccb->rsp_ccb_timer = alarm_new("avdt_ccb.rsp_ccb_timer");
- AVDT_TRACE_DEBUG("avdt_ccb_alloc %d", i);
- break;
+ p_ccb->Allocate(bd_addr);
+ AVDT_TRACE_DEBUG("%s: allocated (index %d) for peer %s", __func__, i,
+ bd_addr.ToString().c_str());
+ return p_ccb;
}
}
- if (i == AVDT_NUM_LINKS) {
- /* out of ccbs */
- p_ccb = NULL;
- AVDT_TRACE_WARNING("Out of ccbs");
+ AVDT_TRACE_WARNING("%s: out of AvdtpCcb entries", __func__);
+ return nullptr;
+}
+
+AvdtpCcb* avdt_ccb_alloc_by_channel_index(const RawAddress& bd_addr,
+ uint8_t channel_index) {
+ // Allocate the entry for the specified channel index
+ if (channel_index >= AVDT_NUM_LINKS) {
+ AVDT_TRACE_ERROR("%s: peer %s invalid channel index %d (max %d)", __func__,
+ bd_addr.ToString().c_str(), channel_index, AVDT_NUM_LINKS);
+ return nullptr;
}
+ AvdtpCcb* p_ccb = &avdtp_cb.ccb[channel_index];
+ if (p_ccb->allocated) {
+ AVDT_TRACE_ERROR("%s: peer %s channel index %d already allocated", __func__,
+ bd_addr.ToString().c_str(), channel_index);
+ return nullptr;
+ }
+ p_ccb->Allocate(bd_addr);
+ AVDT_TRACE_DEBUG("%s: allocated (index %d) peer=%s p_ccb=%p", __func__,
+ channel_index, p_ccb->peer_addr.ToString().c_str(), p_ccb);
return p_ccb;
}
+void AvdtpCcb::Allocate(const RawAddress& peer_address) {
+ ResetCcb();
+ peer_addr = peer_address;
+ cmd_q = fixed_queue_new(SIZE_MAX);
+ rsp_q = fixed_queue_new(SIZE_MAX);
+ idle_ccb_timer = alarm_new("avdtp_ccb.idle_ccb_timer");
+ ret_ccb_timer = alarm_new("avdtp_ccb.ret_ccb_timer");
+ rsp_ccb_timer = alarm_new("avdtp_ccb.rsp_ccb_timer");
+ allocated = true;
+}
+
/*******************************************************************************
*
* Function avdt_ccb_dealloc
@@ -471,14 +494,11 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_dealloc(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
- AVDT_TRACE_DEBUG("avdt_ccb_dealloc %d", avdt_ccb_to_idx(p_ccb));
- alarm_free(p_ccb->idle_ccb_timer);
- alarm_free(p_ccb->ret_ccb_timer);
- alarm_free(p_ccb->rsp_ccb_timer);
- fixed_queue_free(p_ccb->cmd_q, NULL);
- fixed_queue_free(p_ccb->rsp_q, NULL);
- memset(p_ccb, 0, sizeof(tAVDT_CCB));
+void avdt_ccb_dealloc(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+ AVDT_TRACE_DEBUG("%s: deallocated (index %d) peer=%s p_ccb=%p", __func__,
+ avdt_ccb_to_idx(p_ccb), p_ccb->peer_addr.ToString().c_str(),
+ p_ccb);
+ p_ccb->ResetCcb();
}
/*******************************************************************************
@@ -491,9 +511,9 @@
* Returns Index of ccb.
*
******************************************************************************/
-uint8_t avdt_ccb_to_idx(tAVDT_CCB* p_ccb) {
+uint8_t avdt_ccb_to_idx(AvdtpCcb* p_ccb) {
/* use array arithmetic to determine index */
- return (uint8_t)(p_ccb - avdt_cb.ccb);
+ return (uint8_t)(p_ccb - avdtp_cb.ccb);
}
/*******************************************************************************
@@ -506,12 +526,12 @@
* Returns pointer to the ccb, or NULL if none found.
*
******************************************************************************/
-tAVDT_CCB* avdt_ccb_by_idx(uint8_t idx) {
- tAVDT_CCB* p_ccb;
+AvdtpCcb* avdt_ccb_by_idx(uint8_t idx) {
+ AvdtpCcb* p_ccb;
/* verify index */
if (idx < AVDT_NUM_LINKS) {
- p_ccb = &avdt_cb.ccb[idx];
+ p_ccb = &avdtp_cb.ccb[idx];
} else {
p_ccb = NULL;
AVDT_TRACE_WARNING("No ccb for idx %d", idx);
diff --git a/stack/avdt/avdt_ccb_act.cc b/stack/avdt/avdt_ccb_act.cc
index f679dab..52f3857 100644
--- a/stack/avdt/avdt_ccb_act.cc
+++ b/stack/avdt/avdt_ccb_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@
* Returns void.
*
******************************************************************************/
-static void avdt_ccb_clear_ccb(tAVDT_CCB* p_ccb) {
+static void avdt_ccb_clear_ccb(AvdtpCcb* p_ccb) {
BT_HDR* p_buf;
/* clear certain ccb variables */
@@ -75,7 +75,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chan_open(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chan_open(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
BTM_SetOutService(p_ccb->peer_addr, BTM_SEC_SERVICE_AVDTP, AVDT_CHAN_SIG);
avdt_ad_open_req(AVDT_CHAN_SIG, p_ccb, NULL, AVDT_INT);
}
@@ -91,7 +91,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chan_close(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chan_close(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
/* close the transport channel used by this CCB */
avdt_ad_close_req(AVDT_CHAN_SIG, p_ccb, NULL);
}
@@ -107,9 +107,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chk_close(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chk_close(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
int i;
- tAVDT_SCB* p_scb = &avdt_cb.scb[0];
+ AvdtpScb* p_scb = &(p_ccb->scb[0]);
/* see if there are any active scbs associated with this ccb */
for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
@@ -122,7 +122,7 @@
if (i == AVDT_NUM_SEPS) {
alarm_cancel(p_ccb->ret_ccb_timer);
alarm_cancel(p_ccb->rsp_ccb_timer);
- period_ms_t interval_ms = avdt_cb.rcb.idle_tout * 1000;
+ period_ms_t interval_ms = avdtp_cb.rcb.idle_tout * 1000;
alarm_set_on_mloop(p_ccb->idle_ccb_timer, interval_ms,
avdt_ccb_idle_ccb_timer_timeout, p_ccb);
}
@@ -141,23 +141,25 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_discover_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
tAVDT_SEP_INFO sep_info[AVDT_NUM_SEPS];
- tAVDT_SCB* p_scb = &avdt_cb.scb[0];
- int i;
+ AvdtpScb* p_scb = &(p_ccb->scb[0]);
+
+ AVDT_TRACE_DEBUG("%s: p_ccb index=%d", __func__, avdt_ccb_to_idx(p_ccb));
p_data->msg.discover_rsp.p_sep_info = sep_info;
p_data->msg.discover_rsp.num_seps = 0;
/* for all allocated scbs */
- for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
+ for (int i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
if (p_scb->allocated) {
/* copy sep info */
sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
- sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
+ sep_info[p_data->msg.discover_rsp.num_seps].seid = p_scb->ScbHandle();
sep_info[p_data->msg.discover_rsp.num_seps].media_type =
- p_scb->cs.media_type;
- sep_info[p_data->msg.discover_rsp.num_seps].tsep = p_scb->cs.tsep;
+ p_scb->stream_config.media_type;
+ sep_info[p_data->msg.discover_rsp.num_seps].tsep =
+ p_scb->stream_config.tsep;
p_data->msg.discover_rsp.num_seps++;
}
@@ -179,13 +181,14 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_discover_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* we're done with procedure */
p_ccb->proc_busy = false;
/* call app callback with results */
- (*p_ccb->proc_cback)(0, &p_ccb->peer_addr, AVDT_DISCOVER_CFM_EVT,
- (tAVDT_CTRL*)(&p_data->msg.discover_rsp));
+ (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_DISCOVER_CFM_EVT,
+ (tAVDT_CTRL*)(&p_data->msg.discover_rsp),
+ p_ccb->BtaAvScbIndex());
}
/*******************************************************************************
@@ -201,13 +204,13 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
- tAVDT_SCB* p_scb;
+void avdt_ccb_hdl_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
+ AvdtpScb* p_scb;
/* look up scb for seid sent to us */
p_scb = avdt_scb_by_hdl(p_data->msg.single.seid);
- p_data->msg.svccap.p_cfg = &p_scb->cs.cfg;
+ p_data->msg.svccap.p_cfg = &p_scb->stream_config.cfg;
avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_RSP_EVT, p_data);
}
@@ -224,13 +227,14 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_getcap_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* we're done with procedure */
p_ccb->proc_busy = false;
/* call app callback with results */
- (*p_ccb->proc_cback)(0, &p_ccb->peer_addr, AVDT_GETCAP_CFM_EVT,
- (tAVDT_CTRL*)(&p_data->msg.svccap));
+ (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_GETCAP_CFM_EVT,
+ (tAVDT_CTRL*)(&p_data->msg.svccap),
+ p_ccb->BtaAvScbIndex());
}
/*******************************************************************************
@@ -246,7 +250,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_start_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t err_code = 0;
/* verify all streams in the right state */
@@ -277,11 +281,11 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_start_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t event;
int i;
uint8_t* p;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
/* determine rsp or rej event */
event = (p_data->msg.hdr.err_code == 0) ? AVDT_SCB_MSG_START_RSP_EVT
@@ -313,7 +317,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t seid;
uint8_t err_code = 0;
@@ -347,11 +351,11 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t event;
int i;
uint8_t* p;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
/* determine rsp or rej event */
event = (p_data->msg.hdr.err_code == 0) ? AVDT_SCB_MSG_SUSPEND_RSP_EVT
@@ -382,7 +386,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_discover_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* store info in ccb struct */
p_ccb->p_proc_data = p_data->discover.p_sep_info;
p_ccb->proc_cback = p_data->discover.p_cback;
@@ -407,7 +411,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_discover_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* send response */
avdt_msg_send_rsp(p_ccb, AVDT_SIG_DISCOVER, &p_data->msg);
}
@@ -425,7 +429,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_getcap_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t sig_id = AVDT_SIG_GETCAP;
/* store info in ccb struct */
@@ -454,7 +458,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_getcap_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t sig_id = AVDT_SIG_GETCAP;
if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
@@ -477,9 +481,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_start_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
int i;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_MSG avdt_msg;
uint8_t seid_list[AVDT_NUM_SEPS];
@@ -527,8 +531,8 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_start_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
- tAVDT_SCB* p_scb;
+void avdt_ccb_snd_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
+ AvdtpScb* p_scb;
int i;
/* send response message */
@@ -557,9 +561,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_suspend_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
int i;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_MSG avdt_msg;
uint8_t seid_list[AVDT_NUM_SEPS];
@@ -602,8 +606,8 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_suspend_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
- tAVDT_SCB* p_scb;
+void avdt_ccb_snd_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
+ AvdtpScb* p_scb;
int i;
/* send response message */
@@ -632,9 +636,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_clear_cmds(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_clear_cmds(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
int i;
- tAVDT_SCB* p_scb = &avdt_cb.scb[0];
+ AvdtpScb* p_scb = &(p_ccb->scb[0]);
uint8_t err_code = AVDT_ERR_CONNECT;
/* clear the ccb */
@@ -675,10 +679,10 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_cmd_fail(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_cmd_fail(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
tAVDT_MSG msg;
uint8_t evt;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
if (p_ccb->p_curr_cmd != NULL) {
/* set up data */
@@ -718,7 +722,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_free_cmd(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_free_cmd(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
osi_free_and_reset((void**)&p_ccb->p_curr_cmd);
}
@@ -733,7 +737,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_cong_state(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_cong_state(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
p_ccb->cong = p_data->llcong;
}
@@ -750,7 +754,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_ret_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_ret_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
p_ccb->ret_count++;
if (p_ccb->ret_count == AVDT_RET_MAX) {
/* command failed */
@@ -776,7 +780,7 @@
/* restart ret timer */
alarm_cancel(p_ccb->idle_ccb_timer);
alarm_cancel(p_ccb->rsp_ccb_timer);
- period_ms_t interval_ms = avdt_cb.rcb.ret_tout * 1000;
+ period_ms_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
alarm_set_on_mloop(p_ccb->ret_ccb_timer, interval_ms,
avdt_ccb_ret_ccb_timer_timeout, p_ccb);
}
@@ -793,7 +797,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_cmd(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_cmd(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
BT_HDR* p_msg;
/* do we have commands to send? send next command; make sure we're clear;
@@ -822,7 +826,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_msg(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_msg(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
BT_HDR* p_msg;
/* if not congested */
@@ -834,7 +838,7 @@
/* do we have responses to send? send them */
else if (!fixed_queue_is_empty(p_ccb->rsp_q)) {
while ((p_msg = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->rsp_q)) != NULL) {
- if (avdt_msg_send(p_ccb, p_msg) == true) {
+ if (avdt_msg_send(p_ccb, p_msg)) {
/* break out if congested */
break;
}
@@ -858,7 +862,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_set_reconn(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_set_reconn(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
p_ccb->reconn = true;
}
@@ -872,7 +876,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_clr_reconn(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_clr_reconn(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
p_ccb->reconn = false;
}
@@ -888,7 +892,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chk_reconn(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chk_reconn(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
if (p_ccb->reconn) {
p_ccb->reconn = false;
@@ -919,7 +923,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chk_timer(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chk_timer(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
alarm_cancel(p_ccb->idle_ccb_timer);
}
@@ -933,7 +937,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_set_conn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_set_conn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* save callback */
p_ccb->p_conn_cback = p_data->connect.p_cback;
@@ -953,7 +957,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_set_disconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_set_disconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/*
AVDT_TRACE_EVENT("avdt_ccb_set_disconn:conn:x%x, api:x%x",
p_ccb->p_conn_cback, p_data->disconnect.p_cback);
@@ -973,7 +977,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_do_disconn(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_do_disconn(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
/* clear any pending commands */
avdt_ccb_clear_cmds(p_ccb, NULL);
@@ -991,17 +995,20 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_ll_closed(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_ll_closed(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
tAVDT_CTRL_CBACK* p_cback;
tAVDT_CTRL avdt_ctrl;
+ AVDT_TRACE_DEBUG("%s peer %s", __func__, p_ccb->peer_addr.ToString().c_str());
+
/* clear any pending commands */
avdt_ccb_clear_cmds(p_ccb, NULL);
/* save callback pointer, bd addr */
p_cback = p_ccb->p_conn_cback;
- if (!p_cback) p_cback = avdt_cb.p_conn_cback;
+ if (!p_cback) p_cback = avdtp_cb.p_conn_cback;
RawAddress bd_addr = p_ccb->peer_addr;
+ uint8_t bta_av_scb_index = p_ccb->BtaAvScbIndex();
/* dealloc ccb */
avdt_ccb_dealloc(p_ccb, NULL);
@@ -1009,7 +1016,8 @@
/* call callback */
if (p_cback) {
avdt_ctrl.hdr.err_code = 0;
- (*p_cback)(0, &bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl);
+ (*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl,
+ bta_av_scb_index);
}
}
@@ -1023,18 +1031,21 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_ll_opened(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_ll_opened(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
+ AVDT_TRACE_DEBUG("%s peer %s BtaAvScbIndex=%d p_ccb=%p", __func__,
+ p_ccb->peer_addr.ToString().c_str(), p_ccb->BtaAvScbIndex(),
+ p_ccb);
p_ccb->ll_opened = true;
- if (!p_ccb->p_conn_cback) p_ccb->p_conn_cback = avdt_cb.p_conn_cback;
+ if (!p_ccb->p_conn_cback) p_ccb->p_conn_cback = avdtp_cb.p_conn_cback;
/* call callback */
if (p_ccb->p_conn_cback) {
avdt_ctrl.hdr.err_code = 0;
avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param;
- (*p_ccb->p_conn_cback)(0, &p_ccb->peer_addr, AVDT_CONNECT_IND_EVT,
- &avdt_ctrl);
+ (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT,
+ &avdt_ctrl, p_ccb->BtaAvScbIndex());
}
}
diff --git a/stack/avdt/avdt_defs.h b/stack/avdt/avdt_defs.h
index 02e9241..5e3c0bd 100644
--- a/stack/avdt/avdt_defs.h
+++ b/stack/avdt/avdt_defs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/avdt/avdt_int.h b/stack/avdt/avdt_int.h
index 1f593ef..1c35448 100644
--- a/stack/avdt/avdt_int.h
+++ b/stack/avdt/avdt_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,20 +45,13 @@
enum {
AVDT_CHAN_SIG, /* signaling channel */
AVDT_CHAN_MEDIA, /* media channel */
-#if (AVDT_REPORTING == TRUE)
AVDT_CHAN_REPORT, /* reporting channel */
-#endif
AVDT_CHAN_NUM_TYPES
};
/* protocol service capabilities of this AVDTP implementation */
-#if (AVDT_REPORTING == TRUE)
#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_REPORT | AVDT_PSC_DELAY_RPT)
#define AVDT_LEG_PSC (AVDT_PSC_TRANS | AVDT_PSC_REPORT)
-#else /* AVDT_REPORTING */
-#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_DELAY_RPT)
-#define AVDT_LEG_PSC (AVDT_PSC_TRANS)
-#endif /* AVDT_REPORTING */
/* initiator/acceptor signaling roles */
#define AVDT_CLOSE_ACP 0
@@ -216,13 +209,9 @@
AVDT_SCB_HDL_SUSPEND_CMD,
AVDT_SCB_HDL_SUSPEND_RSP,
AVDT_SCB_HDL_TC_CLOSE,
-#if (AVDT_REPORTING == TRUE)
AVDT_SCB_HDL_TC_CLOSE_STO,
-#endif
AVDT_SCB_HDL_TC_OPEN,
-#if (AVDT_REPORTING == TRUE)
AVDT_SCB_HDL_TC_OPEN_STO,
-#endif
AVDT_SCB_SND_DELAY_RPT_REQ,
AVDT_SCB_HDL_DELAY_RPT_CMD,
AVDT_SCB_HDL_DELAY_RPT_RSP,
@@ -314,12 +303,8 @@
};
/* adaption layer number of stream routing table entries */
-#if (AVDT_REPORTING == TRUE)
/* 2 channels(1 media, 1 report) for each SEP and one for signalling */
-#define AVDT_NUM_RT_TBL ((AVDT_NUM_SEPS << 1) + 1)
-#else
-#define AVDT_NUM_RT_TBL (AVDT_NUM_SEPS + 1)
-#endif
+#define AVDT_NUM_RT_TBL (AVDT_NUM_SEPS * AVDT_CHAN_NUM_TYPES + 1)
/* adaption layer number of transport channel table entries - moved to target.h
#define AVDT_NUM_TC_TBL (AVDT_NUM_SEPS + AVDT_NUM_LINKS) */
@@ -335,7 +320,7 @@
#define AVDT_AD_ST_SEC_INT 7 /* Security process as INT */
#define AVDT_AD_ST_SEC_ACP 8 /* Security process as ACP */
-/* Configuration flags. tAVDT_TC_TBL.cfg_flags */
+/* Configuration flags. AvdtpTransportChannel.cfg_flags */
#define AVDT_L2C_CFG_IND_DONE (1 << 0)
#define AVDT_L2C_CFG_CFM_DONE (1 << 1)
#define AVDT_L2C_CFG_CONN_INT (1 << 2)
@@ -375,7 +360,7 @@
typedef struct {
tAVDT_EVT_HDR single;
tAVDT_CTRL_CBACK* p_cback;
- tAVDT_CFG* p_cfg;
+ AvdtpSepConfig* p_cfg;
} tAVDT_CCB_API_GETCAP;
/* data type for AVDT_CCB_API_CONNECT_REQ_EVT */
@@ -398,42 +383,6 @@
uint8_t err_code;
} tAVDT_CCB_EVT;
-/* channel control block type */
-typedef struct {
- RawAddress peer_addr; /* BD address of peer */
- /*
- * NOTE: idle_ccb_timer, ret_ccb_timer and rsp_ccb_timer are mutually
- * exclusive - no more than one timer should be running at the same time.
- */
- alarm_t* idle_ccb_timer; /* Idle CCB timer entry */
- alarm_t* ret_ccb_timer; /* Ret CCB timer entry */
- alarm_t* rsp_ccb_timer; /* Rsp CCB timer entry */
- fixed_queue_t* cmd_q; /* Queue for outgoing command messages */
- fixed_queue_t* rsp_q; /* Queue for outgoing response and reject messages */
- tAVDT_CTRL_CBACK* proc_cback; /* Procedure callback function */
- tAVDT_CTRL_CBACK*
- p_conn_cback; /* Connection/disconnection callback function */
- void* p_proc_data; /* Pointer to data storage for procedure */
- BT_HDR* p_curr_cmd; /* Current command being sent awaiting response */
- BT_HDR* p_curr_msg; /* Current message being sent */
- BT_HDR* p_rx_msg; /* Current message being received */
- bool allocated; /* Whether ccb is allocated */
- uint8_t state; /* The CCB state machine state */
- bool ll_opened; /* true if LL is opened */
- bool proc_busy; /* true when a discover or get capabilities procedure in
- progress */
- uint8_t proc_param; /* Procedure parameter; either SEID for get capabilities
- or number of SEPS for discover */
- bool cong; /* Whether signaling channel is congested */
- uint8_t label; /* Message header "label" (sequence number) */
- bool reconn; /* If true, reinitiate connection after transitioning from
- CLOSING to IDLE state */
- uint8_t ret_count; /* Command retransmission count */
-} tAVDT_CCB;
-
-/* type for action functions */
-typedef void (*tAVDT_CCB_ACTION)(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-
/* type for AVDT_SCB_API_WRITE_REQ_EVT */
typedef struct {
BT_HDR* p_buf;
@@ -460,67 +409,404 @@
BT_HDR* p_pkt;
} tAVDT_SCB_EVT;
-/* stream control block type */
-typedef struct {
- tAVDT_CS cs; /* stream creation struct */
- tAVDT_CFG curr_cfg; /* current configuration */
- tAVDT_CFG req_cfg; /* requested configuration */
- alarm_t* transport_channel_timer; /* transport channel connect timer */
- BT_HDR* p_pkt; /* packet waiting to be sent */
- tAVDT_CCB* p_ccb; /* ccb associated with this scb */
- uint16_t media_seq; /* media packet sequence number */
- bool allocated; /* whether scb is allocated or unused */
- bool in_use; /* whether stream being used by peer */
- uint8_t role; /* initiator/acceptor role in current procedure */
- bool remove; /* whether CB is marked for removal */
- uint8_t state; /* state machine state */
- uint8_t peer_seid; /* SEID of peer stream */
- uint8_t curr_evt; /* current event; set only by state machine */
- bool cong; /* Whether media transport channel is congested */
- uint8_t close_code; /* Error code received in close response */
-} tAVDT_SCB;
+class AvdtpCcb;
-/* type for action functions */
-typedef void (*tAVDT_SCB_ACTION)(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
+/**
+ * AVDTP Stream Control Block.
+ */
+class AvdtpScb {
+ public:
+ AvdtpScb()
+ : transport_channel_timer(nullptr),
+ p_pkt(nullptr),
+ p_ccb(nullptr),
+ media_seq(0),
+ allocated(false),
+ in_use(false),
+ role(0),
+ remove(false),
+ state(0),
+ peer_seid(0),
+ curr_evt(0),
+ cong(false),
+ close_code(0),
+ scb_handle_(0) {}
-/* adaption layer type for transport channel table */
-typedef struct {
- uint16_t peer_mtu; /* L2CAP mtu of the peer device */
- uint16_t my_mtu; /* Our MTU for this channel */
- uint16_t my_flush_to; /* Our flush timeout for this channel */
+ /**
+ * Allocate the entry for usage.
+ * Previous state will be reset and initialized.
+ *
+ * @param p_avdtp_ccb the AvdtCcb entry to use
+ * @param avdtp_stream_config the stream config to use
+ */
+ void Allocate(AvdtpCcb* p_avdtp_ccb,
+ const AvdtpStreamConfig& avdtp_stream_config);
+
+ /**
+ * Recycle the entry by resetting it, mark it as allocated and keeping
+ * the following state:
+ * - stream_config
+ * - p_ccb
+ */
+ void Recycle() {
+ AvdtpStreamConfig stream_config_saved = stream_config;
+ AvdtpCcb* p_ccb_saved = p_ccb;
+ Allocate(p_ccb_saved, stream_config_saved);
+ }
+
+ /**
+ * Reset all the state.
+ *
+ * @param scb_handle the AVDTP SCB handle to use
+ */
+ void Reset(uint8_t scb_handle) {
+ stream_config.Reset();
+ curr_cfg.Reset();
+ req_cfg.Reset();
+
+ alarm_free(transport_channel_timer);
+ transport_channel_timer = nullptr;
+
+ p_pkt = nullptr;
+ p_ccb = nullptr;
+ media_seq = 0;
+ allocated = false;
+ in_use = false;
+ role = 0;
+ remove = false;
+ state = 0;
+ peer_seid = 0;
+ curr_evt = 0;
+ cong = false;
+ close_code = 0;
+ scb_handle_ = scb_handle;
+ }
+
+ /**
+ * Get the AVDTP SCB handle for this entry.
+ */
+ uint8_t ScbHandle() const { return scb_handle_; }
+
+ AvdtpStreamConfig stream_config; // Stream configuration
+ AvdtpSepConfig curr_cfg; // Current configuration
+ AvdtpSepConfig req_cfg; // Requested configuration
+ alarm_t* transport_channel_timer; // Transport channel connect timer
+ BT_HDR* p_pkt; // Packet waiting to be sent
+ AvdtpCcb* p_ccb; // CCB associated with this SCB
+ uint16_t media_seq; // Media packet sequence number
+ bool allocated; // True if the SCB is allocated
+ bool in_use; // True if used by peer
+ uint8_t role; // Initiator/acceptor role in current procedure
+ bool remove; // True if the SCB is marked for removal
+ uint8_t state; // State machine state
+ uint8_t peer_seid; // SEID of peer stream
+ uint8_t curr_evt; // current event; set only by the state machine
+ bool cong; // True if the media transport channel is congested
+ uint8_t close_code; // Error code received in close response
+
+ private:
+ uint8_t scb_handle_; // Unique handle for this AvdtpScb entry
+};
+
+/**
+ * AVDTP Channel Control Block.
+ */
+class AvdtpCcb {
+ public:
+ AvdtpCcb()
+ : peer_addr(RawAddress::kEmpty),
+ scb{},
+ idle_ccb_timer(nullptr),
+ ret_ccb_timer(nullptr),
+ rsp_ccb_timer(nullptr),
+ cmd_q(nullptr),
+ rsp_q(nullptr),
+ proc_cback(nullptr),
+ p_conn_cback(nullptr),
+ p_proc_data(nullptr),
+ p_curr_cmd(nullptr),
+ p_curr_msg(nullptr),
+ p_rx_msg(nullptr),
+ allocated(false),
+ state(0),
+ ll_opened(false),
+ proc_busy(false),
+ proc_param(0),
+ cong(false),
+ label(0),
+ reconn(false),
+ ret_count(0),
+ bta_av_scb_index_(0) {}
+
+ /**
+ * Allocate the entry for usage.
+ *
+ * NOTE: The corresponding AvdtpScb entries are allocated independently.
+ * @param peer_address the peer address
+ */
+ void Allocate(const RawAddress& peer_address);
+
+ /**
+ * Reset all the state.
+ *
+ * @param bta_av_scb_index the BTA AV SCB index to use
+ */
+ void Reset(uint8_t bta_av_scb_index) {
+ bta_av_scb_index_ = bta_av_scb_index;
+ ResetCcb();
+ for (size_t i = 0; i < AVDT_NUM_SEPS; i++) {
+ scb[i].Reset(0);
+ }
+ }
+
+ /**
+ * Reset only the Channel Control Block state without the Stream
+ * Control Block entries. The bta_av_scb_index_ is also preserved.
+ */
+ void ResetCcb() {
+ peer_addr = RawAddress::kEmpty;
+
+ alarm_free(idle_ccb_timer);
+ idle_ccb_timer = nullptr;
+
+ alarm_free(ret_ccb_timer);
+ ret_ccb_timer = nullptr;
+
+ alarm_free(rsp_ccb_timer);
+ rsp_ccb_timer = nullptr;
+
+ fixed_queue_free(cmd_q, nullptr);
+ cmd_q = nullptr;
+
+ fixed_queue_free(rsp_q, nullptr);
+ rsp_q = nullptr;
+
+ proc_cback = nullptr;
+ p_conn_cback = nullptr;
+ p_proc_data = nullptr;
+ p_curr_cmd = nullptr;
+ p_curr_msg = nullptr;
+ p_rx_msg = nullptr;
+ allocated = false;
+ state = 0;
+ ll_opened = false;
+ proc_busy = false;
+ proc_param = 0;
+ cong = false;
+ label = 0;
+ reconn = false;
+ ret_count = 0;
+ }
+
+ /**
+ * Get the corresponding BTA AV stream control block index for this entry.
+ */
+ uint8_t BtaAvScbIndex() const { return bta_av_scb_index_; }
+
+ RawAddress peer_addr; // Bluetooth address of peer
+ AvdtpScb scb[AVDT_NUM_SEPS]; // The AVDTP stream control blocks
+
+ /*
+ * NOTE: idle_ccb_timer, ret_ccb_timer and rsp_ccb_timer are mutually
+ * exclusive - no more than one timer should be running at the same time.
+ */
+ alarm_t* idle_ccb_timer; // Idle CCB timer entry
+ alarm_t* ret_ccb_timer; // Ret CCB timer entry
+ alarm_t* rsp_ccb_timer; // Rsp CCB timer entry
+ fixed_queue_t* cmd_q; // Queue for outgoing command messages
+ fixed_queue_t* rsp_q; // Queue for outgoing response and reject messages
+ tAVDT_CTRL_CBACK* proc_cback; // Procedure callback function
+ tAVDT_CTRL_CBACK* p_conn_cback; // Connection/disconnection callback function
+ void* p_proc_data; // Pointer to data storage for procedure
+ BT_HDR* p_curr_cmd; // Current command being sent awaiting response
+ BT_HDR* p_curr_msg; // Current message being sent
+ BT_HDR* p_rx_msg; // Current message being received
+ bool allocated; // Whether ccb is allocated
+ uint8_t state; // The CCB state machine state
+ bool ll_opened; // True if LL is opened
+ bool proc_busy; // True when a discover or get capabilities procedure in
+ // progress
+ uint8_t proc_param; // Procedure parameter; either SEID for get capabilities
+ // or number of SEPS for discover
+ bool cong; // True if the signaling channel is congested
+ uint8_t label; // Message header "label" (sequence number)
+ bool reconn; // If true, reinitiate connection after transitioning from
+ // CLOSING to IDLE state
+ uint8_t ret_count; // Command retransmission count
+
+ private:
+ // The corresponding BTA AV stream control block index for this entry
+ uint8_t bta_av_scb_index_;
+};
+
+/**
+ * AVDTP transport channel entry.
+ * Used in the transport channel table in the adaptation layer.
+ */
+class AvdtpTransportChannel {
+ public:
+ AvdtpTransportChannel()
+ : peer_mtu(0),
+ my_mtu(0),
+ my_flush_to(0),
+ lcid(0),
+ tcid(0),
+ ccb_idx(0),
+ state(0),
+ cfg_flags(0),
+ id(0) {}
+
+ void Reset() {
+ peer_mtu = 0;
+ my_mtu = 0;
+ my_flush_to = 0;
+ lcid = 0;
+ tcid = 0;
+ ccb_idx = 0;
+ state = 0;
+ cfg_flags = 0;
+ id = 0;
+ }
+
+ uint16_t peer_mtu; // L2CAP MTU of the peer device
+ uint16_t my_mtu; // Our MTU for this channel
+ uint16_t my_flush_to; // Our flush timeout for this channel
uint16_t lcid;
- uint8_t tcid; /* transport channel id */
- uint8_t ccb_idx; /* channel control block associated with this tc */
- uint8_t state; /* transport channel state */
- uint8_t cfg_flags; /* L2CAP configuration flags */
+ uint8_t tcid; // Transport channel ID
+ uint8_t ccb_idx; // Channel control block for with this transport channel
+ uint8_t state; // Transport channel state
+ uint8_t cfg_flags; // L2CAP configuration flags
uint8_t id;
-} tAVDT_TC_TBL;
+};
-/* adaption layer type for stream routing table */
-typedef struct {
- uint16_t lcid; /* L2CAP LCID of the associated transport channel */
- uint8_t scb_hdl; /* stream control block associated with this tc */
-} tAVDT_RT_TBL;
+/**
+ * AVDTP stream routing entry.
+ * Used in the routing table in the adaption layer.
+ */
+class AvdtpRoutingEntry {
+ public:
+ AvdtpRoutingEntry() : lcid(0), scb_hdl(0) {}
-/* adaption layer control block */
-typedef struct {
- tAVDT_RT_TBL rt_tbl[AVDT_NUM_LINKS][AVDT_NUM_RT_TBL];
- tAVDT_TC_TBL tc_tbl[AVDT_NUM_TC_TBL];
- uint8_t lcid_tbl[MAX_L2CAP_CHANNELS]; /* map LCID to tc_tbl index */
-} tAVDT_AD;
+ void Reset() {
+ lcid = 0;
+ scb_hdl = 0;
+ }
-/* Control block for AVDT */
-typedef struct {
- tAVDT_REG rcb; /* registration control block */
- tAVDT_CCB ccb[AVDT_NUM_LINKS]; /* channel control blocks */
- tAVDT_SCB scb[AVDT_NUM_SEPS]; /* stream control blocks */
- tAVDT_AD ad; /* adaption layer control block */
- tAVDTC_CTRL_CBACK* p_conf_cback; /* conformance callback function */
- tAVDT_CCB_ACTION* p_ccb_act; /* pointer to CCB action functions */
- tAVDT_SCB_ACTION* p_scb_act; /* pointer to SCB action functions */
- tAVDT_CTRL_CBACK* p_conn_cback; /* connection callback function */
- uint8_t trace_level; /* trace level */
-} tAVDT_CB;
+ uint16_t lcid; // L2CAP LCID of the associated transport channel
+ uint8_t scb_hdl; // Stream control block for this transport channel
+};
+
+/**
+ * AVDTP adaption layer control block.
+ */
+class AvdtpAdaptationLayer {
+ public:
+ AvdtpAdaptationLayer() : lcid_tbl{} {}
+
+ void Reset() {
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ for (size_t j = 0; j < AVDT_NUM_RT_TBL; j++) {
+ rt_tbl[i][j].Reset();
+ }
+ }
+ for (size_t i = 0; i < AVDT_NUM_TC_TBL; i++) {
+ tc_tbl[i].Reset();
+ }
+ memset(lcid_tbl, 0, sizeof(lcid_tbl));
+ }
+
+ /**
+ * Lookup AvdtpScb entry for a transport channel.
+ *
+ * @param tc the transport channel
+ * @return the corresponding AvdtpScb entry or null of the transport
+ * channel is invalid.
+ */
+ AvdtpScb* LookupAvdtpScb(const AvdtpTransportChannel& tc);
+
+ AvdtpRoutingEntry rt_tbl[AVDT_NUM_LINKS][AVDT_NUM_RT_TBL];
+ AvdtpTransportChannel tc_tbl[AVDT_NUM_TC_TBL];
+ uint8_t lcid_tbl[MAX_L2CAP_CHANNELS]; // Map LCID to tc_tbl index
+};
+
+/**
+ * Types for action functions.
+ */
+typedef void (*tAVDT_CCB_ACTION)(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+typedef void (*tAVDT_SCB_ACTION)(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+
+/**
+ * Control block for AVDTP.
+ */
+class AvdtpCb {
+ public:
+ AvdtpCb()
+ : p_conf_cback(nullptr),
+ p_ccb_act(nullptr),
+ p_scb_act(nullptr),
+ p_conn_cback(nullptr),
+ trace_level_(0) {}
+
+ void Reset() {
+ rcb.Reset();
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ ccb[i].Reset(i);
+ }
+ ad.Reset();
+ p_conf_cback = nullptr;
+ p_ccb_act = nullptr;
+ p_scb_act = nullptr;
+ p_conn_cback = nullptr;
+ trace_level_ = 0;
+ }
+
+ AvdtpRcb rcb; // Registration control block
+ AvdtpCcb ccb[AVDT_NUM_LINKS]; // Channel control blocks
+ AvdtpAdaptationLayer ad; // Adaption layer control block
+ tAVDTC_CTRL_CBACK* p_conf_cback; // Conformance callback function
+ const tAVDT_CCB_ACTION* p_ccb_act; // Pointer to CCB action functions
+ const tAVDT_SCB_ACTION* p_scb_act; // Pointer to SCB action functions
+ tAVDT_CTRL_CBACK* p_conn_cback; // Connection callback function
+
+ /**
+ * Compute the SCB handle for a given AvdtpScb entry.
+ *
+ * @param p_scb the entry to use
+ * @return the computed SCB handle or 0 if the entry is invalid.
+ */
+ uint8_t ComputeScbHandle(const AvdtpScb* p_scb) const {
+ uint8_t scb_handle = 0;
+
+ // Find the entry and in the process compute the unique index
+ // TODO: This mechanism is sub-efficient and should be refactored.
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ for (size_t j = 0; j < AVDT_NUM_SEPS; j++) {
+ scb_handle++;
+ if (&ccb[i].scb[j] == p_scb) {
+ return scb_handle;
+ }
+ }
+ }
+ return 0; // Not found
+ }
+
+ /**
+ * Get the current trace level used for logging.
+ *
+ * @return the current trace level
+ */
+ uint8_t TraceLevel() const { return trace_level_; }
+
+ /**
+ * Set the current trace level used for logging.
+ *
+ * @param trace_level the trace level to set. Should be in the range [1, 6].
+ */
+ void SetTraceLevel(uint8_t trace_level) { trace_level_ = trace_level; }
+
+ private:
+ uint8_t trace_level_; /* trace level */
+};
/*****************************************************************************
* function declarations
@@ -528,156 +814,162 @@
/* CCB function declarations */
extern void avdt_ccb_init(void);
-extern void avdt_ccb_event(tAVDT_CCB* p_ccb, uint8_t event,
+extern void avdt_ccb_event(AvdtpCcb* p_ccb, uint8_t event,
tAVDT_CCB_EVT* p_data);
-extern tAVDT_CCB* avdt_ccb_by_bd(const RawAddress& bd_addr);
-extern tAVDT_CCB* avdt_ccb_alloc(const RawAddress& bd_addr);
-extern void avdt_ccb_dealloc(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern uint8_t avdt_ccb_to_idx(tAVDT_CCB* p_ccb);
-extern tAVDT_CCB* avdt_ccb_by_idx(uint8_t idx);
+extern AvdtpCcb* avdt_ccb_by_bd(const RawAddress& bd_addr);
+extern AvdtpCcb* avdt_ccb_alloc(const RawAddress& bd_addr);
+extern AvdtpCcb* avdt_ccb_alloc_by_channel_index(const RawAddress& bd_addr,
+ uint8_t channel_index);
+extern void avdt_ccb_dealloc(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern uint8_t avdt_ccb_to_idx(AvdtpCcb* p_ccb);
+extern AvdtpCcb* avdt_ccb_by_idx(uint8_t idx);
/* CCB action functions */
-extern void avdt_ccb_chan_open(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_chan_close(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_chk_close(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_discover_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_discover_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_getcap_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_start_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_start_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_discover_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_discover_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_getcap_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_getcap_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_start_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_start_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_suspend_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_suspend_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_clear_cmds(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_cmd_fail(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_free_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_cong_state(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_ret_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_msg(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_set_reconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_clr_reconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_chk_reconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_chk_timer(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_set_conn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_set_disconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_do_disconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_ll_closed(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_ll_opened(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chan_open(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chan_close(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chk_close(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_clear_cmds(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_cmd_fail(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_free_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_cong_state(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_ret_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_msg(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_set_reconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_clr_reconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chk_reconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chk_timer(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_set_conn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_set_disconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_do_disconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_ll_closed(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_ll_opened(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
/* SCB function prototypes */
-extern void avdt_scb_event(tAVDT_SCB* p_scb, uint8_t event,
+extern void avdt_scb_event(AvdtpScb* p_scb, uint8_t event,
tAVDT_SCB_EVT* p_data);
extern void avdt_scb_init(void);
-extern tAVDT_SCB* avdt_scb_alloc(tAVDT_CS* p_cs);
-extern void avdt_scb_dealloc(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern uint8_t avdt_scb_to_hdl(tAVDT_SCB* p_scb);
-extern tAVDT_SCB* avdt_scb_by_hdl(uint8_t hdl);
-extern uint8_t avdt_scb_verify(tAVDT_CCB* p_ccb, uint8_t state, uint8_t* p_seid,
+extern AvdtpScb* avdt_scb_alloc(uint8_t peer_id,
+ const AvdtpStreamConfig& avdtp_stream_config);
+extern void avdt_scb_dealloc(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern uint8_t avdt_scb_to_hdl(AvdtpScb* p_scb);
+extern AvdtpScb* avdt_scb_by_hdl(uint8_t hdl);
+extern uint8_t avdt_scb_verify(AvdtpCcb* p_ccb, uint8_t state, uint8_t* p_seid,
uint16_t num_seid, uint8_t* p_err_code);
extern void avdt_scb_peer_seid_list(tAVDT_MULTI* p_multi);
-extern uint32_t avdt_scb_gen_ssrc(tAVDT_SCB* p_scb);
+extern uint32_t avdt_scb_gen_ssrc(AvdtpScb* p_scb);
/* SCB action functions */
-extern void avdt_scb_hdl_abort_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_abort_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_close_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_close_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_getconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_getconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_open_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_open_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_open_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_drop_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_reconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_reconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_security_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_security_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_setconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_setconfig_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_setconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_start_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_start_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_suspend_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_suspend_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_delay_rpt_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_delay_rpt_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_delay_rpt_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_tc_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_tc_open(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_tc_close_sto(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_tc_open_sto(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_write_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_abort_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_abort_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_close_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_stream_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_close_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_getconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_getconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_open_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_open_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_reconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_reconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_security_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_security_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_setconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_setconfig_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_setconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_tc_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_cb_err(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_cong_state(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_rej_state(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_rej_in_use(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_rej_not_in_use(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_set_remove(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_free_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_chk_snd_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_clr_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_transport_channel_timer(tAVDT_SCB* p_scb,
+extern void avdt_scb_hdl_abort_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_abort_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_close_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_close_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_getconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_getconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_open_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_open_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_open_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_drop_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_reconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_reconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_security_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_security_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_setconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_setconfig_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_setconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_start_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_start_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_suspend_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_suspend_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_delay_rpt_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_delay_rpt_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_delay_rpt_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_tc_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_tc_open(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_tc_close_sto(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_tc_open_sto(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_write_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_abort_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_abort_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_close_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_stream_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_close_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_getconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_getconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_open_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_open_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_reconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_reconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_security_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_security_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_setconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_setconfig_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_setconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_tc_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_cb_err(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_cong_state(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_rej_state(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_rej_in_use(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_rej_not_in_use(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_set_remove(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_free_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_chk_snd_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_clr_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_transport_channel_timer(AvdtpScb* p_scb,
tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_clr_vars(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_clr_vars(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
/* msg function declarations */
-extern bool avdt_msg_send(tAVDT_CCB* p_ccb, BT_HDR* p_msg);
-extern void avdt_msg_send_cmd(tAVDT_CCB* p_ccb, void* p_scb, uint8_t sig_id,
+extern bool avdt_msg_send(AvdtpCcb* p_ccb, BT_HDR* p_msg);
+extern void avdt_msg_send_cmd(AvdtpCcb* p_ccb, void* p_scb, uint8_t sig_id,
tAVDT_MSG* p_params);
-extern void avdt_msg_send_rsp(tAVDT_CCB* p_ccb, uint8_t sig_id,
+extern void avdt_msg_send_rsp(AvdtpCcb* p_ccb, uint8_t sig_id,
tAVDT_MSG* p_params);
-extern void avdt_msg_send_rej(tAVDT_CCB* p_ccb, uint8_t sig_id,
+extern void avdt_msg_send_rej(AvdtpCcb* p_ccb, uint8_t sig_id,
tAVDT_MSG* p_params);
-extern void avdt_msg_send_grej(tAVDT_CCB* p_ccb, uint8_t sig_id,
+extern void avdt_msg_send_grej(AvdtpCcb* p_ccb, uint8_t sig_id,
tAVDT_MSG* p_params);
-extern void avdt_msg_ind(tAVDT_CCB* p_ccb, BT_HDR* p_buf);
+extern void avdt_msg_ind(AvdtpCcb* p_ccb, BT_HDR* p_buf);
/* adaption layer function declarations */
extern void avdt_ad_init(void);
-extern uint8_t avdt_ad_type_to_tcid(uint8_t type, tAVDT_SCB* p_scb);
-extern tAVDT_TC_TBL* avdt_ad_tc_tbl_by_st(uint8_t type, tAVDT_CCB* p_ccb,
- uint8_t state);
-extern tAVDT_TC_TBL* avdt_ad_tc_tbl_by_lcid(uint16_t lcid);
-extern tAVDT_TC_TBL* avdt_ad_tc_tbl_alloc(tAVDT_CCB* p_ccb);
-extern uint8_t avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL* p_tbl);
-extern void avdt_ad_tc_close_ind(tAVDT_TC_TBL* p_tbl, uint16_t reason);
-extern void avdt_ad_tc_open_ind(tAVDT_TC_TBL* p_tbl);
-extern void avdt_ad_tc_cong_ind(tAVDT_TC_TBL* p_tbl, bool is_congested);
-extern void avdt_ad_tc_data_ind(tAVDT_TC_TBL* p_tbl, BT_HDR* p_buf);
-extern tAVDT_TC_TBL* avdt_ad_tc_tbl_by_type(uint8_t type, tAVDT_CCB* p_ccb,
- tAVDT_SCB* p_scb);
-extern uint8_t avdt_ad_write_req(uint8_t type, tAVDT_CCB* p_ccb,
- tAVDT_SCB* p_scb, BT_HDR* p_buf);
-extern void avdt_ad_open_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb,
+extern uint8_t avdt_ad_type_to_tcid(uint8_t type, AvdtpScb* p_scb);
+extern AvdtpTransportChannel* avdt_ad_tc_tbl_by_st(uint8_t type,
+ AvdtpCcb* p_ccb,
+ uint8_t state);
+extern AvdtpTransportChannel* avdt_ad_tc_tbl_by_lcid(uint16_t lcid);
+extern AvdtpTransportChannel* avdt_ad_tc_tbl_alloc(AvdtpCcb* p_ccb);
+extern uint8_t avdt_ad_tc_tbl_to_idx(AvdtpTransportChannel* p_tbl);
+extern void avdt_ad_tc_close_ind(AvdtpTransportChannel* p_tbl, uint16_t reason);
+extern void avdt_ad_tc_open_ind(AvdtpTransportChannel* p_tbl);
+extern void avdt_ad_tc_cong_ind(AvdtpTransportChannel* p_tbl,
+ bool is_congested);
+extern void avdt_ad_tc_data_ind(AvdtpTransportChannel* p_tbl, BT_HDR* p_buf);
+extern AvdtpTransportChannel* avdt_ad_tc_tbl_by_type(uint8_t type,
+ AvdtpCcb* p_ccb,
+ AvdtpScb* p_scb);
+extern uint8_t avdt_ad_write_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb,
+ BT_HDR* p_buf);
+extern void avdt_ad_open_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb,
uint8_t role);
-extern void avdt_ad_close_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb);
+extern void avdt_ad_close_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb);
extern void avdt_ccb_idle_ccb_timer_timeout(void* data);
extern void avdt_ccb_ret_ccb_timer_timeout(void* data);
@@ -704,7 +996,7 @@
/******************************************************************************
* Main Control Block
******************************************************************************/
-extern tAVDT_CB avdt_cb;
+extern AvdtpCb avdtp_cb;
/* L2CAP callback registration structure */
extern const tL2CAP_APPL_INFO avdt_l2c_appl;
diff --git a/stack/avdt/avdt_l2c.cc b/stack/avdt/avdt_l2c.cc
index 8ae1d43..db1bf2f 100644
--- a/stack/avdt/avdt_l2c.cc
+++ b/stack/avdt/avdt_l2c.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
#include "bt_target.h"
#include "bt_types.h"
#include "bt_utils.h"
+#include "bta/include/bta_av_api.h"
#include "btm_api.h"
#include "btm_int.h"
#include "device/include/interop.h"
@@ -48,19 +49,18 @@
void avdt_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf);
/* L2CAP callback function structure */
-const tL2CAP_APPL_INFO avdt_l2c_appl = {
- avdt_l2c_connect_ind_cback,
- avdt_l2c_connect_cfm_cback,
- NULL,
- avdt_l2c_config_ind_cback,
- avdt_l2c_config_cfm_cback,
- avdt_l2c_disconnect_ind_cback,
- avdt_l2c_disconnect_cfm_cback,
- NULL,
- avdt_l2c_data_ind_cback,
- avdt_l2c_congestion_ind_cback,
- NULL /* tL2CA_TX_COMPLETE_CB */
-};
+const tL2CAP_APPL_INFO avdt_l2c_appl = {avdt_l2c_connect_ind_cback,
+ avdt_l2c_connect_cfm_cback,
+ NULL,
+ avdt_l2c_config_ind_cback,
+ avdt_l2c_config_cfm_cback,
+ avdt_l2c_disconnect_ind_cback,
+ avdt_l2c_disconnect_cfm_cback,
+ NULL,
+ avdt_l2c_data_ind_cback,
+ avdt_l2c_congestion_ind_cback,
+ NULL, /* tL2CA_TX_COMPLETE_CB */
+ NULL /* tL2CA_CREDITS_RECEIVED_CB */};
/*******************************************************************************
*
@@ -76,9 +76,9 @@
tBT_TRANSPORT transport,
UNUSED_ATTR void* p_ref_data,
uint8_t res) {
- tAVDT_CCB* p_ccb = NULL;
+ AvdtpCcb* p_ccb = NULL;
tL2CAP_CFG_INFO cfg;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d", res);
p_ccb = avdt_ccb_by_bd(*bd_addr);
@@ -92,9 +92,9 @@
L2CAP_CONN_OK);
/* store idx in LCID table, store LCID in routing table */
- avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] =
+ avdtp_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] =
avdt_ad_tc_tbl_to_idx(p_tbl);
- avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid;
+ avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid;
/* transition to configuration state */
p_tbl->state = AVDT_AD_ST_CFG;
@@ -127,9 +127,9 @@
tBT_TRANSPORT trasnport,
UNUSED_ATTR void* p_ref_data,
uint8_t res) {
- tAVDT_CCB* p_ccb = NULL;
+ AvdtpCcb* p_ccb = NULL;
tL2CAP_CFG_INFO cfg;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d", res);
if (bd_addr) p_ccb = avdt_ccb_by_bd(*bd_addr);
@@ -164,8 +164,8 @@
******************************************************************************/
void avdt_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
UNUSED_ATTR uint16_t psm, uint8_t id) {
- tAVDT_CCB* p_ccb;
- tAVDT_TC_TBL* p_tbl = NULL;
+ AvdtpCcb* p_ccb;
+ AvdtpTransportChannel* p_tbl = NULL;
uint16_t result;
tL2CAP_CFG_INFO cfg;
tBTM_STATUS rc;
@@ -174,14 +174,20 @@
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb == NULL) {
/* no, allocate ccb */
- p_ccb = avdt_ccb_alloc(bd_addr);
+ int channel_index = BTA_AvObtainPeerChannelIndex(bd_addr);
+ if (channel_index >= 0) {
+ p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
+ }
+ if (p_ccb == nullptr) {
+ p_ccb = avdt_ccb_alloc(bd_addr);
+ }
if (p_ccb == NULL) {
/* no ccb available, reject L2CAP connection */
result = L2CAP_CONN_NO_RESOURCES;
} else {
/* allocate and set up entry; first channel is always signaling */
p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
- p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
+ p_tbl->my_mtu = avdtp_cb.rcb.ctrl_mtu;
p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
p_tbl->tcid = AVDT_CHAN_SIG;
p_tbl->lcid = lcid;
@@ -208,36 +214,30 @@
}
return;
}
- }
- /* deal with simultaneous control channel connect case */
- else {
+ } else {
+ /* deal with simultaneous control channel connect case */
p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_CONN);
if (p_tbl != NULL) {
/* reject their connection */
result = L2CAP_CONN_NO_RESOURCES;
- }
- /* this must be a traffic channel; are we accepting a traffic channel
- ** for this ccb?
- */
- else {
+ } else {
+ /* This must be a traffic channel; are we accepting a traffic channel
+ * for this ccb?
+ */
p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_MEDIA, p_ccb, AVDT_AD_ST_ACP);
if (p_tbl != NULL) {
/* yes; proceed with connection */
result = L2CAP_CONN_OK;
- }
-#if (AVDT_REPORTING == TRUE)
- /* this must be a reporting channel; are we accepting a reporting channel
- ** for this ccb?
- */
- else {
+ } else {
+ /* this must be a reporting channel; are we accepting a reporting
+ * channel for this ccb?
+ */
p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_REPORT, p_ccb, AVDT_AD_ST_ACP);
if (p_tbl != NULL) {
/* yes; proceed with connection */
result = L2CAP_CONN_OK;
- }
-#endif
- /* else we're not listening for traffic channel; reject */
- else {
+ } else {
+ /* else we're not listening for traffic channel; reject */
result = L2CAP_CONN_NO_PSM;
}
}
@@ -250,9 +250,9 @@
/* if result ok, proceed with connection */
if (result == L2CAP_CONN_OK) {
/* store idx in LCID table, store LCID in routing table */
- avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
+ avdtp_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
avdt_ad_tc_tbl_to_idx(p_tbl);
- avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
+ avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
/* transition to configuration state */
p_tbl->state = AVDT_AD_ST_CFG;
@@ -278,9 +278,9 @@
*
******************************************************************************/
void avdt_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
tL2CAP_CFG_INFO cfg;
- tAVDT_CCB* p_ccb;
+ AvdtpCcb* p_ccb;
AVDT_TRACE_DEBUG("avdt_l2c_connect_cfm_cback lcid: %d, result: %d", lcid,
result);
@@ -351,7 +351,9 @@
*
******************************************************************************/
void avdt_l2c_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
+
+ AVDT_TRACE_DEBUG("%s: lcid: %d", __func__, lcid);
/* look up info for this channel */
p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
@@ -390,7 +392,9 @@
*
******************************************************************************/
void avdt_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
+
+ AVDT_TRACE_DEBUG("%s: lcid: %d", __func__, lcid);
/* look up info for this channel */
p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
@@ -401,7 +405,8 @@
} else {
p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
}
- AVDT_TRACE_DEBUG("peer_mtu: %d, lcid: x%x", p_tbl->peer_mtu, lcid);
+ AVDT_TRACE_DEBUG("%s: peer_mtu: %d, lcid: %d", __func__, p_tbl->peer_mtu,
+ lcid);
/* send L2CAP configure response */
memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
@@ -432,7 +437,7 @@
*
******************************************************************************/
void avdt_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
AVDT_TRACE_DEBUG("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d",
lcid, ack_needed);
@@ -459,7 +464,7 @@
*
******************************************************************************/
void avdt_l2c_disconnect_cfm_cback(uint16_t lcid, uint16_t result) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
AVDT_TRACE_DEBUG("avdt_l2c_disconnect_cfm_cback lcid: %d, result: %d", lcid,
result);
@@ -481,7 +486,7 @@
*
******************************************************************************/
void avdt_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
/* look up info for this channel */
p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
@@ -501,7 +506,7 @@
*
******************************************************************************/
void avdt_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
/* look up info for this channel */
p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
diff --git a/stack/avdt/avdt_msg.cc b/stack/avdt/avdt_msg.cc
index 52ce2e8..cf517d1 100644
--- a/stack/avdt/avdt_msg.cc
+++ b/stack/avdt/avdt_msg.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -272,7 +272,7 @@
* Returns void.
*
******************************************************************************/
-static void avdt_msg_bld_cfg(uint8_t** p, tAVDT_CFG* p_cfg) {
+static void avdt_msg_bld_cfg(uint8_t** p, AvdtpSepConfig* p_cfg) {
uint8_t len;
/* for now, just build media transport, codec, and content protection, and
@@ -284,13 +284,11 @@
*(*p)++ = 0; /* length */
}
-#if (AVDT_REPORTING == TRUE)
/* reporting transport */
if (p_cfg->psc_mask & AVDT_PSC_REPORT) {
*(*p)++ = AVDT_CAT_REPORT;
*(*p)++ = 0; /* length */
}
-#endif
/* codec */
if (p_cfg->num_codec != 0) {
@@ -470,11 +468,11 @@
*
******************************************************************************/
static void avdt_msg_bld_svccap(uint8_t** p, tAVDT_MSG* p_msg) {
- tAVDT_CFG cfg;
+ AvdtpSepConfig cfg = *p_msg->svccap.p_cfg;
- /* make sure the delay report category is not reported */
- memcpy(&cfg, p_msg->svccap.p_cfg, sizeof(tAVDT_CFG));
- cfg.psc_mask &= ~AVDT_PSC_DELAY_RPT;
+ // Include only the Basic Capability
+ cfg.psc_mask &= AVDT_LEG_PSC;
+
avdt_msg_bld_cfg(p, &cfg);
}
@@ -521,7 +519,7 @@
* in p_elem.
*
******************************************************************************/
-static uint8_t avdt_msg_prs_cfg(tAVDT_CFG* p_cfg, uint8_t* p, uint16_t len,
+static uint8_t avdt_msg_prs_cfg(AvdtpSepConfig* p_cfg, uint8_t* p, uint16_t len,
uint8_t* p_elem, uint8_t sig_id) {
uint8_t* p_end;
uint8_t elem = 0;
@@ -640,6 +638,8 @@
break;
case AVDT_CAT_DELAY_RPT:
+ AVDT_TRACE_DEBUG("%s: Remote device supports delay reporting",
+ __func__);
break;
default:
@@ -1036,11 +1036,11 @@
* Returns Congested state; true if CCB congested, false if not.
*
******************************************************************************/
-bool avdt_msg_send(tAVDT_CCB* p_ccb, BT_HDR* p_msg) {
+bool avdt_msg_send(AvdtpCcb* p_ccb, BT_HDR* p_msg) {
uint16_t curr_msg_len;
uint8_t pkt_type;
uint8_t hdr_len;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
BT_HDR* p_buf;
uint8_t* p;
uint8_t label;
@@ -1132,16 +1132,16 @@
if (msg == AVDT_MSG_TYPE_CMD) {
/* if retransmit timeout set to zero, sig doesn't use retransmit */
if ((sig == AVDT_SIG_DISCOVER) || (sig == AVDT_SIG_GETCAP) ||
- (sig == AVDT_SIG_SECURITY) || (avdt_cb.rcb.ret_tout == 0)) {
+ (sig == AVDT_SIG_SECURITY) || (avdtp_cb.rcb.ret_tout == 0)) {
alarm_cancel(p_ccb->idle_ccb_timer);
alarm_cancel(p_ccb->ret_ccb_timer);
- period_ms_t interval_ms = avdt_cb.rcb.sig_tout * 1000;
+ period_ms_t interval_ms = avdtp_cb.rcb.sig_tout * 1000;
alarm_set_on_mloop(p_ccb->rsp_ccb_timer, interval_ms,
avdt_ccb_rsp_ccb_timer_timeout, p_ccb);
} else if (sig != AVDT_SIG_DELAY_RPT) {
alarm_cancel(p_ccb->idle_ccb_timer);
alarm_cancel(p_ccb->rsp_ccb_timer);
- period_ms_t interval_ms = avdt_cb.rcb.ret_tout * 1000;
+ period_ms_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
alarm_set_on_mloop(p_ccb->ret_ccb_timer, interval_ms,
avdt_ccb_ret_ccb_timer_timeout, p_ccb);
}
@@ -1184,7 +1184,7 @@
* available.
*
******************************************************************************/
-BT_HDR* avdt_msg_asmbl(tAVDT_CCB* p_ccb, BT_HDR* p_buf) {
+BT_HDR* avdt_msg_asmbl(AvdtpCcb* p_ccb, BT_HDR* p_buf) {
uint8_t* p;
uint8_t pkt_type;
BT_HDR* p_ret;
@@ -1305,7 +1305,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_send_cmd(tAVDT_CCB* p_ccb, void* p_scb, uint8_t sig_id,
+void avdt_msg_send_cmd(AvdtpCcb* p_ccb, void* p_scb, uint8_t sig_id,
tAVDT_MSG* p_params) {
uint8_t* p;
uint8_t* p_start;
@@ -1331,7 +1331,7 @@
}
/* for all others, p_scb points to scb as usual */
else {
- *p = avdt_scb_to_hdl((tAVDT_SCB*)p_scb);
+ *p = avdt_scb_to_hdl((AvdtpScb*)p_scb);
}
}
@@ -1362,7 +1362,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_send_rsp(tAVDT_CCB* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
+void avdt_msg_send_rsp(AvdtpCcb* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
uint8_t* p;
uint8_t* p_start;
BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVDT_CMD_BUF_SIZE);
@@ -1402,7 +1402,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_send_rej(tAVDT_CCB* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
+void avdt_msg_send_rej(AvdtpCcb* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
uint8_t* p;
uint8_t* p_start;
BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVDT_CMD_BUF_SIZE);
@@ -1453,7 +1453,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_send_grej(tAVDT_CCB* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
+void avdt_msg_send_grej(AvdtpCcb* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
uint8_t* p;
uint8_t* p_start;
BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVDT_CMD_BUF_SIZE);
@@ -1489,8 +1489,8 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_ind(tAVDT_CCB* p_ccb, BT_HDR* p_buf) {
- tAVDT_SCB* p_scb;
+void avdt_msg_ind(AvdtpCcb* p_ccb, BT_HDR* p_buf) {
+ AvdtpScb* p_scb;
uint8_t* p;
bool ok = true;
bool handle_rsp = false;
@@ -1500,7 +1500,7 @@
uint8_t msg_type;
uint8_t sig = 0;
tAVDT_MSG msg;
- tAVDT_CFG cfg;
+ AvdtpSepConfig cfg;
uint8_t err;
uint8_t evt = 0;
uint8_t scb_hdl;
@@ -1565,7 +1565,7 @@
} else if ((msg_type == AVDT_MSG_TYPE_RSP) &&
((sig == AVDT_SIG_GETCAP) || (sig == AVDT_SIG_GET_ALLCAP))) {
/* parse discover rsp message to struct supplied by app */
- msg.svccap.p_cfg = (tAVDT_CFG*)p_ccb->p_proc_data;
+ msg.svccap.p_cfg = (AvdtpSepConfig*)p_ccb->p_proc_data;
} else if ((msg_type == AVDT_MSG_TYPE_RSP) && (sig == AVDT_SIG_GETCONFIG)) {
/* parse get config rsp message to struct allocated locally */
msg.svccap.p_cfg = &cfg;
diff --git a/stack/avdt/avdt_scb.cc b/stack/avdt/avdt_scb.cc
index 777cc73..eacdf83 100644
--- a/stack/avdt/avdt_scb.cc
+++ b/stack/avdt/avdt_scb.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -89,13 +89,9 @@
avdt_scb_hdl_suspend_cmd,
avdt_scb_hdl_suspend_rsp,
avdt_scb_hdl_tc_close,
-#if (AVDT_REPORTING == TRUE)
avdt_scb_hdl_tc_close_sto,
-#endif
avdt_scb_hdl_tc_open,
-#if (AVDT_REPORTING == TRUE)
avdt_scb_hdl_tc_open_sto,
-#endif
avdt_scb_snd_delay_rpt_req,
avdt_scb_hdl_delay_rpt_cmd,
avdt_scb_hdl_delay_rpt_rsp,
@@ -528,17 +524,10 @@
{AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
/* TC_TOUT_EVT */
{AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
-#if (AVDT_REPORTING == TRUE)
/* TC_OPEN_EVT */
{AVDT_SCB_HDL_TC_OPEN_STO, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
/* TC_CLOSE_EVT */
{AVDT_SCB_HDL_TC_CLOSE_STO, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
-#else
- /* TC_OPEN_EVT */
- {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
- /* TC_CLOSE_EVT */
- {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
-#endif
/* TC_CONG_EVT */
{AVDT_SCB_CONG_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
/* TC_DATA_EVT */
@@ -766,15 +755,16 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_event(tAVDT_SCB* p_scb, uint8_t event, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_event(AvdtpScb* p_scb, uint8_t event, tAVDT_SCB_EVT* p_data) {
tAVDT_SCB_ST_TBL state_table;
uint8_t action;
int i;
#if (AVDT_DEBUG == TRUE)
- AVDT_TRACE_EVENT("%s: SCB hdl=%d event=%d/%s state=%s", __func__,
- avdt_scb_to_hdl(p_scb), event, avdt_scb_evt_str[event],
- avdt_scb_st_str[p_scb->state]);
+ AVDT_TRACE_EVENT(
+ "%s: SCB hdl=%d event=%d/%s state=%s p_avdt_scb=%p scb_index=%d",
+ __func__, avdt_scb_to_hdl(p_scb), event, avdt_scb_evt_str[event],
+ avdt_scb_st_str[p_scb->state], p_scb, p_scb->stream_config.scb_index);
#endif
/* set current event */
p_scb->curr_evt = event;
@@ -791,7 +781,7 @@
for (i = 0; i < AVDT_SCB_ACTIONS; i++) {
action = state_table[event][i];
if (action != AVDT_SCB_IGNORE) {
- (*avdt_cb.p_scb_act[action])(p_scb, p_data);
+ (*avdtp_cb.p_scb_act[action])(p_scb, p_data);
} else {
break;
}
@@ -809,8 +799,13 @@
*
******************************************************************************/
void avdt_scb_init(void) {
- memset(&avdt_cb.scb[0], 0, sizeof(tAVDT_SCB) * AVDT_NUM_SEPS);
- avdt_cb.p_scb_act = (tAVDT_SCB_ACTION*)avdt_scb_action;
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ for (size_t j = 0; j < AVDT_NUM_SEPS; j++) {
+ avdtp_cb.ccb[i].scb[j].Reset(0);
+ }
+ }
+
+ avdtp_cb.p_scb_act = avdt_scb_action;
}
/*******************************************************************************
@@ -823,33 +818,34 @@
* Returns pointer to the scb, or NULL if none could be allocated.
*
******************************************************************************/
-tAVDT_SCB* avdt_scb_alloc(tAVDT_CS* p_cs) {
- tAVDT_SCB* p_scb = &avdt_cb.scb[0];
- int i;
+AvdtpScb* avdt_scb_alloc(uint8_t peer_id,
+ const AvdtpStreamConfig& avdtp_stream_config) {
+ CHECK(peer_id < AVDT_NUM_LINKS);
- /* find available scb */
- for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
+ // Find available entry
+ AvdtpScb* p_scb = &avdtp_cb.ccb[peer_id].scb[0];
+ for (int i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
if (!p_scb->allocated) {
- memset(p_scb, 0, sizeof(tAVDT_SCB));
- p_scb->allocated = true;
- p_scb->p_ccb = NULL;
-
- memcpy(&p_scb->cs, p_cs, sizeof(tAVDT_CS));
- p_scb->transport_channel_timer =
- alarm_new("avdt_scb.transport_channel_timer");
- AVDT_TRACE_DEBUG("%s: hdl=%d, psc_mask:0x%x", __func__, i + 1,
- p_cs->cfg.psc_mask);
- break;
+ p_scb->Allocate(&avdtp_cb.ccb[peer_id], avdtp_stream_config);
+ AVDT_TRACE_DEBUG("%s: allocated (handle=%d, psc_mask:0x%x)", __func__,
+ p_scb->ScbHandle(), avdtp_stream_config.cfg.psc_mask);
+ return p_scb;
}
}
- if (i == AVDT_NUM_SEPS) {
- /* out of ccbs */
- p_scb = NULL;
- AVDT_TRACE_WARNING("Out of scbs");
- }
+ AVDT_TRACE_WARNING("%s: out of AvdtScb entries for peer_id %d", __func__,
+ peer_id);
+ return nullptr;
+}
- return p_scb;
+void AvdtpScb::Allocate(AvdtpCcb* p_avdtp_ccb,
+ const AvdtpStreamConfig& avdtp_stream_config) {
+ uint8_t scb_handle = avdtp_cb.ComputeScbHandle(this);
+ Reset(scb_handle);
+ p_ccb = p_avdtp_ccb;
+ stream_config = avdtp_stream_config;
+ transport_channel_timer = alarm_new("avdtp_scb.transport_channel_timer");
+ allocated = true;
}
/*******************************************************************************
@@ -862,10 +858,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_scb_dealloc(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_dealloc(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
AVDT_TRACE_DEBUG("%s: hdl=%d", __func__, avdt_scb_to_hdl(p_scb));
- alarm_free(p_scb->transport_channel_timer);
- memset(p_scb, 0, sizeof(tAVDT_SCB));
+ p_scb->Recycle();
}
/*******************************************************************************
@@ -878,9 +873,7 @@
* Returns Index of scb.
*
******************************************************************************/
-uint8_t avdt_scb_to_hdl(tAVDT_SCB* p_scb) {
- return (uint8_t)(p_scb - avdt_cb.scb + 1);
-}
+uint8_t avdt_scb_to_hdl(AvdtpScb* p_scb) { return p_scb->ScbHandle(); }
/*******************************************************************************
*
@@ -893,22 +886,26 @@
* is not allocated.
*
******************************************************************************/
-tAVDT_SCB* avdt_scb_by_hdl(uint8_t hdl) {
- tAVDT_SCB* p_scb;
-
- /* verify index */
- if ((hdl > 0) && (hdl <= AVDT_NUM_SEPS)) {
- p_scb = &avdt_cb.scb[hdl - 1];
-
- /* verify scb is allocated */
- if (!p_scb->allocated) {
- p_scb = NULL;
- AVDT_TRACE_WARNING("scb hdl %d not allocated", hdl);
- }
- } else {
- p_scb = NULL;
- AVDT_TRACE_WARNING("scb hdl %d out of range", hdl);
+AvdtpScb* avdt_scb_by_hdl(uint8_t hdl) {
+ // Verify the index
+ if ((hdl < 1) || (hdl > AVDT_NUM_LINKS * AVDT_NUM_SEPS)) {
+ AVDT_TRACE_WARNING("%s: SCB handle %d out of range", __func__, hdl);
+ return nullptr;
}
+
+ uint8_t index = hdl - 1;
+ size_t i = index / AVDT_NUM_LINKS;
+ size_t j = index % AVDT_NUM_SEPS;
+
+ AvdtpScb* p_scb = &avdtp_cb.ccb[i].scb[j];
+ // Verify the whether the scb is allocated
+ if (!p_scb->allocated) {
+ AVDT_TRACE_WARNING("%s: SCB handle %d not allocated", __func__, hdl);
+ return nullptr;
+ }
+
+ AVDT_TRACE_DEBUG("%s: SCB for handle %d found: p_scb=%p scb_index=%d",
+ __func__, hdl, p_scb, p_scb->stream_config.scb_index);
return p_scb;
}
@@ -922,10 +919,10 @@
* Returns SEID that failed, or 0 if success.
*
******************************************************************************/
-uint8_t avdt_scb_verify(tAVDT_CCB* p_ccb, uint8_t state, uint8_t* p_seid,
+uint8_t avdt_scb_verify(AvdtpCcb* p_ccb, uint8_t state, uint8_t* p_seid,
uint16_t num_seid, uint8_t* p_err_code) {
int i;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint8_t nsc_mask;
uint8_t ret = 0;
@@ -933,7 +930,9 @@
/* set nonsupported command mask */
/* translate public state into private state */
nsc_mask = 0;
- if (state == AVDT_VERIFY_SUSPEND) nsc_mask = AVDT_NSC_SUSPEND;
+ if (state == AVDT_VERIFY_SUSPEND) {
+ nsc_mask = AvdtpStreamConfig::AVDT_NSC_SUSPEND;
+ }
/* verify every scb */
for (i = 0, *p_err_code = 0;
@@ -943,7 +942,7 @@
*p_err_code = AVDT_ERR_BAD_STATE;
else if (p_scb->p_ccb != p_ccb)
*p_err_code = AVDT_ERR_BAD_STATE;
- else if (p_scb->cs.nsc_mask & nsc_mask)
+ else if (p_scb->stream_config.nsc_mask & nsc_mask)
*p_err_code = AVDT_ERR_NSC;
switch (state) {
@@ -982,7 +981,7 @@
******************************************************************************/
void avdt_scb_peer_seid_list(tAVDT_MULTI* p_multi) {
int i;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
for (i = 0; i < p_multi->num_seps; i++) {
p_scb = avdt_scb_by_hdl(p_multi->seid_list[i]);
diff --git a/stack/avdt/avdt_scb_act.cc b/stack/avdt/avdt_scb_act.cc
index de6912b..d55a22e 100644
--- a/stack/avdt/avdt_scb_act.cc
+++ b/stack/avdt/avdt_scb_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@
* state machine API request event. Note that state machine API request
* events are at the beginning of the event list starting at zero, thus
* allowing for this table.
-*/
+ */
const uint8_t avdt_scb_cback_evt[] = {
0, /* API_REMOVE_EVT (no event) */
AVDT_WRITE_CFM_EVT, /* API_WRITE_REQ_EVT */
@@ -62,10 +62,10 @@
* Returns SSRC value.
*
******************************************************************************/
-uint32_t avdt_scb_gen_ssrc(tAVDT_SCB* p_scb) {
+uint32_t avdt_scb_gen_ssrc(AvdtpScb* p_scb) {
/* combine the value of the media type and codec type of the SCB */
- return (
- (uint32_t)(p_scb->cs.cfg.codec_info[1] | p_scb->cs.cfg.codec_info[2]));
+ return ((uint32_t)(p_scb->stream_config.cfg.codec_info[1] |
+ p_scb->stream_config.cfg.codec_info[2]));
}
/*******************************************************************************
@@ -78,7 +78,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_abort_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_abort_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_scb->role = AVDT_CLOSE_ACP;
avdt_scb_event(p_scb, AVDT_SCB_API_ABORT_RSP_EVT, p_data);
}
@@ -93,7 +93,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_abort_rsp(UNUSED_ATTR tAVDT_SCB* p_scb,
+void avdt_scb_hdl_abort_rsp(UNUSED_ATTR AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
return;
}
@@ -108,7 +108,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_close_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_close_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_scb->role = AVDT_CLOSE_ACP;
avdt_scb_event(p_scb, AVDT_SCB_API_CLOSE_RSP_EVT, p_data);
}
@@ -123,7 +123,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_close_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_close_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_scb->close_code = p_data->msg.hdr.err_code;
}
@@ -138,7 +138,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_getconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_getconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_data->msg.svccap.p_cfg = &p_scb->curr_cfg;
avdt_scb_event(p_scb, AVDT_SCB_API_GETCONFIG_RSP_EVT, p_data);
@@ -154,7 +154,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_getconfig_rsp(UNUSED_ATTR tAVDT_SCB* p_scb,
+void avdt_scb_hdl_getconfig_rsp(UNUSED_ATTR AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
return;
}
@@ -169,7 +169,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_open_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_open_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
avdt_scb_event(p_scb, AVDT_SCB_API_OPEN_RSP_EVT, p_data);
}
@@ -185,7 +185,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_open_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_open_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* do exactly same as setconfig reject */
avdt_scb_hdl_setconfig_rej(p_scb, p_data);
}
@@ -200,8 +200,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_open_rsp(tAVDT_SCB* p_scb,
- UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_open_rsp(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
/* initiate opening of trans channels for this SEID */
p_scb->role = AVDT_OPEN_INT;
avdt_ad_open_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, AVDT_INT);
@@ -221,7 +220,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_pkt_no_frag(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
uint8_t *p, *p_start;
uint8_t o_v, o_p, o_x, o_cc;
uint8_t m_pt;
@@ -271,19 +270,18 @@
p_data->p_pkt->len -= (offset + pad_len);
p_data->p_pkt->offset += offset;
- if (p_scb->cs.p_sink_data_cback != NULL) {
+ if (p_scb->stream_config.p_sink_data_cback != NULL) {
/* report sequence number */
p_data->p_pkt->layer_specific = seq;
- (*p_scb->cs.p_sink_data_cback)(avdt_scb_to_hdl(p_scb), p_data->p_pkt,
- time_stamp,
- (uint8_t)(m_pt | (marker << 7)));
+ (*p_scb->stream_config.p_sink_data_cback)(
+ avdt_scb_to_hdl(p_scb), p_data->p_pkt, time_stamp,
+ (uint8_t)(m_pt | (marker << 7)));
} else {
osi_free_and_reset((void**)&p_data->p_pkt);
}
}
}
-#if (AVDT_REPORTING == TRUE)
/*******************************************************************************
*
* Function avdt_scb_hdl_report
@@ -293,7 +291,7 @@
* Returns Nothing.
*
******************************************************************************/
-uint8_t* avdt_scb_hdl_report(tAVDT_SCB* p_scb, uint8_t* p, uint16_t len) {
+uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) {
uint16_t result = AVDT_SUCCESS;
uint8_t* p_start = p;
uint32_t ssrc;
@@ -302,7 +300,7 @@
tAVDT_REPORT_DATA report;
AVDT_TRACE_DEBUG("%s", __func__);
- if (p_scb->cs.p_report_cback) {
+ if (p_scb->stream_config.p_report_cback) {
/* parse report packet header */
AVDT_MSG_PRS_RPT_OCTET1(p, o_v, o_p, o_cc);
pt = *p++;
@@ -352,12 +350,12 @@
}
if (result == AVDT_SUCCESS)
- (*p_scb->cs.p_report_cback)(avdt_scb_to_hdl(p_scb), pt, &report);
+ (*p_scb->stream_config.p_report_cback)(avdt_scb_to_hdl(p_scb), pt,
+ &report);
}
p_start += len;
return p_start;
}
-#endif
/*******************************************************************************
*
@@ -368,15 +366,14 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
-#if (AVDT_REPORTING == TRUE)
+void avdt_scb_hdl_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_data->p_pkt->layer_specific == AVDT_CHAN_REPORT) {
uint8_t* p = (uint8_t*)(p_data->p_pkt + 1) + p_data->p_pkt->offset;
avdt_scb_hdl_report(p_scb, p, p_data->p_pkt->len);
osi_free_and_reset((void**)&p_data->p_pkt);
- } else
-#endif
+ } else {
avdt_scb_hdl_pkt_no_frag(p_scb, p_data);
+ }
}
/*******************************************************************************
@@ -389,7 +386,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_drop_pkt(UNUSED_ATTR tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_drop_pkt(UNUSED_ATTR AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
AVDT_TRACE_ERROR("%s dropped incoming media packet", __func__);
osi_free_and_reset((void**)&p_data->p_pkt);
}
@@ -404,21 +401,21 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_reconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_reconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* if command not supported */
- if (p_scb->cs.nsc_mask & AVDT_NSC_RECONFIG) {
+ if (p_scb->stream_config.nsc_mask & AvdtpStreamConfig::AVDT_NSC_RECONFIG) {
/* send reject */
p_data->msg.hdr.err_code = AVDT_ERR_NSC;
p_data->msg.hdr.err_param = 0;
avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_RSP_EVT, p_data);
} else {
/* store requested configuration */
- memcpy(&p_scb->req_cfg, p_data->msg.reconfig_cmd.p_cfg, sizeof(tAVDT_CFG));
+ p_scb->req_cfg = *p_data->msg.reconfig_cmd.p_cfg;
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL,
- AVDT_RECONFIG_IND_EVT,
- (tAVDT_CTRL*)&p_data->msg.reconfig_cmd);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_RECONFIG_IND_EVT,
+ (tAVDT_CTRL*)&p_data->msg.reconfig_cmd, p_scb->stream_config.scb_index);
}
}
@@ -432,7 +429,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_reconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_reconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_data->msg.hdr.err_code == 0) {
/* store new configuration */
if (p_scb->req_cfg.num_codec > 0) {
@@ -450,8 +447,9 @@
p_data->msg.svccap.p_cfg = &p_scb->curr_cfg;
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_RECONFIG_CFM_EVT,
- (tAVDT_CTRL*)&p_data->msg.svccap);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_RECONFIG_CFM_EVT,
+ (tAVDT_CTRL*)&p_data->msg.svccap, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -464,17 +462,17 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_security_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_security_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* if command not supported */
- if (p_scb->cs.nsc_mask & AVDT_NSC_SECURITY) {
+ if (p_scb->stream_config.nsc_mask & AvdtpStreamConfig::AVDT_NSC_SECURITY) {
/* send reject */
p_data->msg.hdr.err_code = AVDT_ERR_NSC;
avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_RSP_EVT, p_data);
} else {
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL,
- AVDT_SECURITY_IND_EVT,
- (tAVDT_CTRL*)&p_data->msg.security_cmd);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_SECURITY_IND_EVT,
+ (tAVDT_CTRL*)&p_data->msg.security_cmd, p_scb->stream_config.scb_index);
}
}
@@ -488,10 +486,11 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_security_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_security_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_SECURITY_CFM_EVT,
- (tAVDT_CTRL*)&p_data->msg.security_cmd);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_SECURITY_CFM_EVT,
+ (tAVDT_CTRL*)&p_data->msg.security_cmd, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -505,30 +504,44 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_setconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- tAVDT_CFG* p_cfg;
-
- AVDT_TRACE_DEBUG("%s: p_scb->in_use=%d", __func__, p_scb->in_use);
+void avdt_scb_hdl_setconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ AVDT_TRACE_DEBUG("%s: p_scb->in_use=%d p_avdt_scb=%p scb_index=%d", __func__,
+ p_scb->in_use, p_scb, p_scb->stream_config.scb_index);
if (!p_scb->in_use) {
- A2DP_DumpCodecInfo(p_scb->cs.cfg.codec_info);
- A2DP_DumpCodecInfo(p_data->msg.config_cmd.p_cfg->codec_info);
- p_cfg = p_data->msg.config_cmd.p_cfg;
- if (A2DP_GetCodecType(p_scb->cs.cfg.codec_info) ==
+ AVDT_TRACE_DEBUG(
+ "%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_scb->stream_config.cfg.codec_info).c_str());
+ AVDT_TRACE_DEBUG(
+ "%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_data->msg.config_cmd.p_cfg->codec_info).c_str());
+ AvdtpSepConfig* p_cfg = p_data->msg.config_cmd.p_cfg;
+ if (A2DP_GetCodecType(p_scb->stream_config.cfg.codec_info) ==
A2DP_GetCodecType(p_cfg->codec_info)) {
+ /* copy info to scb */
+ AvdtpCcb* p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
+ if (p_scb->p_ccb != p_ccb) {
+ AVDT_TRACE_ERROR(
+ "%s: mismatch in AVDTP SCB/CCB state: (p_scb->p_ccb=%p != "
+ "p_ccb=%p): "
+ "p_scb=%p scb_handle=%d ccb_idx=%d",
+ __func__, p_scb->p_ccb, p_ccb, p_scb, p_scb->ScbHandle(),
+ p_data->msg.config_cmd.hdr.ccb_idx);
+ avdt_scb_rej_not_in_use(p_scb, p_data);
+ return;
+ }
/* set sep as in use */
p_scb->in_use = true;
- /* copy info to scb */
- p_scb->p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
p_scb->peer_seid = p_data->msg.config_cmd.int_seid;
- memcpy(&p_scb->req_cfg, p_cfg, sizeof(tAVDT_CFG));
+ p_scb->req_cfg = *p_cfg;
/* call app callback */
/* handle of scb- which is same as sep handle of bta_av_cb.p_scb*/
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_CONFIG_IND_EVT,
- (tAVDT_CTRL*)&p_data->msg.config_cmd);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_CONFIG_IND_EVT, (tAVDT_CTRL*)&p_data->msg.config_cmd,
+ p_scb->stream_config.scb_index);
} else {
p_data->msg.hdr.err_code = AVDT_ERR_UNSUP_CFG;
p_data->msg.hdr.err_param = 0;
@@ -552,7 +565,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_setconfig_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_setconfig_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* clear scb variables */
avdt_scb_clr_vars(p_scb, p_data);
@@ -561,8 +574,9 @@
AVDT_CCB_UL_CLOSE_EVT, NULL);
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_OPEN_CFM_EVT,
- (tAVDT_CTRL*)&p_data->msg.hdr);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_OPEN_CFM_EVT,
+ (tAVDT_CTRL*)&p_data->msg.hdr, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -575,13 +589,13 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_setconfig_rsp(tAVDT_SCB* p_scb,
+void avdt_scb_hdl_setconfig_rsp(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR single;
if (p_scb->p_ccb != NULL) {
/* save configuration */
- memcpy(&p_scb->curr_cfg, &p_scb->req_cfg, sizeof(tAVDT_CFG));
+ p_scb->curr_cfg = p_scb->req_cfg;
/* initiate open */
single.seid = p_scb->peer_seid;
@@ -601,11 +615,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_start_cmd(tAVDT_SCB* p_scb,
+void avdt_scb_hdl_start_cmd(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_START_IND_EVT, NULL);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_START_IND_EVT, NULL, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -618,10 +633,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_start_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_START_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr);
+void avdt_scb_hdl_start_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_START_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr,
+ p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -634,11 +651,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_suspend_cmd(tAVDT_SCB* p_scb,
+void avdt_scb_hdl_suspend_cmd(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_SUSPEND_IND_EVT, NULL);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_SUSPEND_IND_EVT, NULL, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -651,10 +669,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_suspend_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(
- avdt_scb_to_hdl(p_scb), p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_SUSPEND_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr);
+void avdt_scb_hdl_suspend_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_SUSPEND_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr,
+ p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -673,13 +693,14 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_tc_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_tc_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
uint8_t hdl = avdt_scb_to_hdl(p_scb);
- tAVDT_CTRL_CBACK* p_ctrl_cback = p_scb->cs.p_ctrl_cback;
+ tAVDT_CTRL_CBACK* p_avdt_ctrl_cback = p_scb->stream_config.p_avdt_ctrl_cback;
tAVDT_CTRL avdt_ctrl;
uint8_t event;
- tAVDT_CCB* p_ccb = p_scb->p_ccb;
+ AvdtpCcb* p_ccb = p_scb->p_ccb;
RawAddress remote_addr = p_ccb->peer_addr;
+ uint8_t scb_index = p_scb->stream_config.scb_index;
/* set up hdr */
avdt_ctrl.hdr.err_code = p_scb->close_code;
@@ -707,7 +728,7 @@
}
/* call app callback */
- (*p_ctrl_cback)(hdl, &remote_addr, event, &avdt_ctrl);
+ (*p_avdt_ctrl_cback)(hdl, remote_addr, event, &avdt_ctrl, scb_index);
}
/*******************************************************************************
@@ -720,7 +741,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_delay_rpt_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_delay_rpt_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_DELAY_RPT,
(tAVDT_MSG*)&p_data->apidelay);
}
@@ -735,10 +756,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_delay_rpt_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(
- avdt_scb_to_hdl(p_scb), p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_DELAY_REPORT_EVT, (tAVDT_CTRL*)&p_data->msg.hdr);
+void avdt_scb_hdl_delay_rpt_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_DELAY_REPORT_EVT, (tAVDT_CTRL*)&p_data->msg.hdr,
+ p_scb->stream_config.scb_index);
if (p_scb->p_ccb)
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_DELAY_RPT, &p_data->msg);
@@ -756,13 +779,14 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_delay_rpt_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(
- avdt_scb_to_hdl(p_scb), p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_DELAY_REPORT_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr);
+void avdt_scb_hdl_delay_rpt_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_DELAY_REPORT_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr,
+ p_scb->stream_config.scb_index);
}
-#if (AVDT_REPORTING == TRUE)
/*******************************************************************************
*
* Function avdt_scb_hdl_tc_close_sto
@@ -773,7 +797,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_tc_close_sto(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_tc_close_sto(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
/* AVDT_CHAN_SIG does not visit this action */
if (p_data && p_data->close.type != AVDT_CHAN_MEDIA) {
@@ -783,9 +807,10 @@
avdt_ctrl.hdr.err_code = 0;
avdt_ctrl.hdr.err_param = 0;
/* call app callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_REPORT_DISCONN_EVT, &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_REPORT_DISCONN_EVT, &avdt_ctrl, p_scb->stream_config.scb_index);
}
} else {
/* must be in OPEN state. need to go back to idle */
@@ -793,7 +818,6 @@
avdt_scb_hdl_tc_close(p_scb, p_data);
}
}
-#endif
/*******************************************************************************
*
@@ -807,11 +831,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_tc_open(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_tc_open(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
uint8_t event;
-#if (AVDT_REPORTING == TRUE)
uint8_t role;
-#endif
alarm_cancel(p_scb->transport_channel_timer);
@@ -819,24 +841,22 @@
(p_scb->role == AVDT_OPEN_INT) ? AVDT_OPEN_CFM_EVT : AVDT_OPEN_IND_EVT;
p_data->open.hdr.err_code = 0;
- AVDT_TRACE_DEBUG("psc_mask: cfg: 0x%x, req:0x%x, cur: 0x%x",
- p_scb->cs.cfg.psc_mask, p_scb->req_cfg.psc_mask,
+ AVDT_TRACE_DEBUG("%s: psc_mask: cfg: 0x%x, req:0x%x, cur: 0x%x", __func__,
+ p_scb->stream_config.cfg.psc_mask, p_scb->req_cfg.psc_mask,
p_scb->curr_cfg.psc_mask);
-#if (AVDT_REPORTING == TRUE)
if (p_scb->curr_cfg.psc_mask & AVDT_PSC_REPORT) {
/* open the reporting channel, if both devices support it */
role = (p_scb->role == AVDT_OPEN_INT) ? AVDT_INT : AVDT_ACP;
avdt_ad_open_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb, role);
}
-#endif
/* call app callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- event, (tAVDT_CTRL*)&p_data->open);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty, event,
+ (tAVDT_CTRL*)&p_data->open, p_scb->stream_config.scb_index);
}
-#if (AVDT_REPORTING == TRUE)
/*******************************************************************************
*
* Function avdt_scb_hdl_tc_open_sto
@@ -849,7 +869,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_tc_open_sto(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_tc_open_sto(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
/* open reporting channel here, when it is implemented */
@@ -857,12 +877,12 @@
if (p_data->open.hdr.err_code == AVDT_CHAN_REPORT) {
avdt_ctrl.hdr.err_code = 0;
avdt_ctrl.hdr.err_param = 1;
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_REPORT_CONN_EVT, &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_REPORT_CONN_EVT, &avdt_ctrl, p_scb->stream_config.scb_index);
}
}
-#endif
/*******************************************************************************
*
@@ -875,7 +895,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_write_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_write_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
uint8_t* p;
uint32_t ssrc;
bool add_rtp_header = !(p_data->apiwrite.opt & AVDT_DATA_OPT_NO_RTP);
@@ -923,7 +943,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_abort_req(tAVDT_SCB* p_scb,
+void avdt_scb_snd_abort_req(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR hdr;
@@ -949,7 +969,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_abort_rsp(UNUSED_ATTR tAVDT_SCB* p_scb,
+void avdt_scb_snd_abort_rsp(UNUSED_ATTR AvdtpScb* p_scb,
tAVDT_SCB_EVT* p_data) {
avdt_msg_send_rsp(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx), AVDT_SIG_ABORT,
&p_data->msg);
@@ -964,7 +984,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_close_req(tAVDT_SCB* p_scb,
+void avdt_scb_snd_close_req(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR hdr;
@@ -986,7 +1006,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_stream_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_stream_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
osi_free_and_reset((void**)&p_scb->p_pkt);
avdt_scb_snd_close_req(p_scb, p_data);
}
@@ -1000,7 +1020,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_close_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_close_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_CLOSE, &p_data->msg);
}
@@ -1013,7 +1033,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_getconfig_req(tAVDT_SCB* p_scb,
+void avdt_scb_snd_getconfig_req(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR hdr;
@@ -1033,7 +1053,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_getconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_getconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_GETCONFIG, &p_data->msg);
}
@@ -1046,8 +1066,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_open_req(tAVDT_SCB* p_scb,
- UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_open_req(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR hdr;
hdr.seid = p_scb->peer_seid;
@@ -1068,7 +1087,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_open_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_open_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* notify adaption that we're waiting for transport channel open */
p_scb->role = AVDT_OPEN_ACP;
avdt_ad_open_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, AVDT_ACP);
@@ -1091,12 +1110,14 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_reconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_reconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
AVDT_TRACE_DEBUG("%s: p_scb->peer_seid=%d p_data->msg.hdr.seid=%d", __func__,
p_scb->peer_seid, p_data->msg.hdr.seid);
- A2DP_DumpCodecInfo(p_data->msg.config_cmd.p_cfg->codec_info);
+ AVDT_TRACE_DEBUG(
+ "%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_data->msg.config_cmd.p_cfg->codec_info).c_str());
- memcpy(&p_scb->req_cfg, p_data->msg.config_cmd.p_cfg, sizeof(tAVDT_CFG));
+ p_scb->req_cfg = *p_data->msg.config_cmd.p_cfg;
p_data->msg.hdr.seid = p_scb->peer_seid;
avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_RECONFIG, &p_data->msg);
}
@@ -1111,7 +1132,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_reconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_reconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_data->msg.hdr.err_code == 0) {
/* store new configuration */
if (p_scb->req_cfg.num_codec > 0) {
@@ -1142,7 +1163,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_security_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_security_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_data->msg.hdr.seid = p_scb->peer_seid;
avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_SECURITY, &p_data->msg);
}
@@ -1156,7 +1177,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_security_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_security_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_data->msg.hdr.err_code == 0) {
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_SECURITY, &p_data->msg);
} else {
@@ -1174,7 +1195,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_setconfig_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_setconfig_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_scb->p_ccb != NULL) {
avdt_msg_send_rej(p_scb->p_ccb, AVDT_SIG_SETCONFIG, &p_data->msg);
@@ -1195,19 +1216,30 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_setconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- tAVDT_CFG *p_req, *p_cfg;
+void avdt_scb_snd_setconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ AvdtpSepConfig *p_req, *p_cfg;
- AVDT_TRACE_DEBUG("%s", __func__);
- A2DP_DumpCodecInfo(p_data->msg.config_cmd.p_cfg->codec_info);
+ AVDT_TRACE_DEBUG(
+ "%s: codec: %s", __func__,
+ A2DP_CodecInfoString(p_data->msg.config_cmd.p_cfg->codec_info).c_str());
/* copy API parameters to scb, set scb as in use */
+
+ AvdtpCcb* p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
+ if (p_scb->p_ccb != p_ccb) {
+ AVDT_TRACE_ERROR(
+ "%s: mismatch in AVDTP SCB/CCB state: (p_scb->p_ccb=%p != p_ccb=%p): "
+ "p_scb=%p scb_handle=%d ccb_idx=%d",
+ __func__, p_scb->p_ccb, p_ccb, p_scb, p_scb->ScbHandle(),
+ p_data->msg.config_cmd.hdr.ccb_idx);
+ avdt_scb_rej_not_in_use(p_scb, p_data);
+ return;
+ }
p_scb->in_use = true;
- p_scb->p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
p_scb->peer_seid = p_data->msg.config_cmd.hdr.seid;
p_req = p_data->msg.config_cmd.p_cfg;
- p_cfg = &p_scb->cs.cfg;
- memcpy(&p_scb->req_cfg, p_data->msg.config_cmd.p_cfg, sizeof(tAVDT_CFG));
+ p_cfg = &p_scb->stream_config.cfg;
+ p_scb->req_cfg = *p_data->msg.config_cmd.p_cfg;
avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_SETCONFIG, &p_data->msg);
@@ -1226,9 +1258,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_setconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_setconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_scb->p_ccb != NULL) {
- memcpy(&p_scb->curr_cfg, &p_scb->req_cfg, sizeof(tAVDT_CFG));
+ p_scb->curr_cfg = p_scb->req_cfg;
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_SETCONFIG, &p_data->msg);
}
@@ -1244,12 +1276,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_tc_close(tAVDT_SCB* p_scb,
- UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
-#if (AVDT_REPORTING == TRUE)
+void avdt_scb_snd_tc_close(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
if (p_scb->curr_cfg.psc_mask & AVDT_PSC_REPORT)
avdt_ad_close_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb);
-#endif
avdt_ad_close_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb);
}
@@ -1263,7 +1292,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_cb_err(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_cb_err(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
/* set error code and parameter */
@@ -1271,8 +1300,10 @@
avdt_ctrl.hdr.err_param = 0;
/* call callback, using lookup table to get callback event */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL,
- avdt_scb_cback_evt[p_scb->curr_evt], &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty,
+ avdt_scb_cback_evt[p_scb->curr_evt], &avdt_ctrl,
+ p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -1285,7 +1316,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_cong_state(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_cong_state(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_scb->cong = p_data->llcong;
}
@@ -1299,7 +1330,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_rej_state(UNUSED_ATTR tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_rej_state(UNUSED_ATTR AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_data->msg.hdr.err_code = AVDT_ERR_BAD_STATE;
p_data->msg.hdr.err_param = 0;
avdt_msg_send_rej(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx),
@@ -1316,7 +1347,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_rej_in_use(UNUSED_ATTR tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_rej_in_use(UNUSED_ATTR AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_data->msg.hdr.err_code = AVDT_ERR_IN_USE;
p_data->msg.hdr.err_param = 0;
avdt_msg_send_rej(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx),
@@ -1333,7 +1364,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_rej_not_in_use(UNUSED_ATTR tAVDT_SCB* p_scb,
+void avdt_scb_rej_not_in_use(UNUSED_ATTR AvdtpScb* p_scb,
tAVDT_SCB_EVT* p_data) {
p_data->msg.hdr.err_code = AVDT_ERR_NOT_IN_USE;
p_data->msg.hdr.err_param = 0;
@@ -1350,7 +1381,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_set_remove(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_set_remove(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
p_scb->remove = true;
}
@@ -1363,7 +1394,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_free_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_free_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
/* set error code and parameter */
@@ -1375,8 +1406,9 @@
AVDT_TRACE_WARNING("Dropped media packet");
/* we need to call callback to keep data flow going */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_WRITE_CFM_EVT,
- &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_WRITE_CFM_EVT,
+ &avdt_ctrl, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -1388,9 +1420,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_clr_pkt(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_clr_pkt(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
- tAVDT_CCB* p_ccb;
+ AvdtpCcb* p_ccb;
uint8_t tcid;
uint16_t lcid;
@@ -1403,7 +1435,7 @@
/* get tcid from type, scb */
tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
- lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ lcid = avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
L2CA_FlushChannel(lcid, L2CAP_FLUSH_CHANS_ALL);
}
@@ -1413,8 +1445,9 @@
AVDT_TRACE_DEBUG("Dropped stored media packet");
/* we need to call callback to keep data flow going */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_WRITE_CFM_EVT,
- &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_WRITE_CFM_EVT,
+ &avdt_ctrl, p_scb->stream_config.scb_index);
}
}
@@ -1430,7 +1463,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_chk_snd_pkt(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_chk_snd_pkt(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
BT_HDR* p_pkt;
@@ -1442,8 +1475,9 @@
p_scb->p_pkt = NULL;
avdt_ad_write_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, p_pkt);
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL,
- AVDT_WRITE_CFM_EVT, &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_WRITE_CFM_EVT,
+ &avdt_ctrl, p_scb->stream_config.scb_index);
}
}
}
@@ -1459,7 +1493,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_transport_channel_timer(tAVDT_SCB* p_scb,
+void avdt_scb_transport_channel_timer(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
alarm_set_on_mloop(p_scb->transport_channel_timer,
AVDT_SCB_TC_DISC_TIMEOUT_MS,
@@ -1475,8 +1509,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_clr_vars(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_clr_vars(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
p_scb->in_use = false;
- p_scb->p_ccb = NULL;
p_scb->peer_seid = 0;
}
diff --git a/stack/avrc/avrc_api.cc b/stack/avrc/avrc_api.cc
index bdf78b7..69534e9 100644
--- a/stack/avrc/avrc_api.cc
+++ b/stack/avrc/avrc_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2016 Broadcom Corporation
+ * Copyright 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -84,13 +84,13 @@
const RawAddress* peer_addr) {
uint8_t avrc_event;
- if (event <= AVRC_MAX_RCV_CTRL_EVT && avrc_cb.ccb[handle].p_ctrl_cback) {
+ if (event <= AVRC_MAX_RCV_CTRL_EVT && avrc_cb.ccb[handle].ctrl_cback) {
avrc_event = avrc_ctrl_event_map[event];
if (event == AVCT_CONNECT_CFM_EVT) {
if (result != 0) /* failed */
avrc_event = AVRC_CLOSE_IND_EVT;
}
- (*avrc_cb.ccb[handle].p_ctrl_cback)(handle, avrc_event, result, peer_addr);
+ avrc_cb.ccb[handle].ctrl_cback.Run(handle, avrc_event, result, peer_addr);
}
if ((event == AVCT_DISCONNECT_CFM_EVT) ||
@@ -135,8 +135,8 @@
param->handle, param->label);
/* Notify app */
- if (avrc_cb.ccb[param->handle].p_ctrl_cback) {
- (*avrc_cb.ccb[param->handle].p_ctrl_cback)(
+ if (avrc_cb.ccb[param->handle].ctrl_cback) {
+ avrc_cb.ccb[param->handle].ctrl_cback.Run(
param->handle, AVRC_CMD_TIMEOUT_EVT, param->label, NULL);
}
@@ -246,7 +246,6 @@
return p_pkt_copy;
}
-#if (AVRC_METADATA_INCLUDED == TRUE)
/******************************************************************************
*
* Function avrc_prep_end_frag
@@ -266,10 +265,9 @@
p_fcb = &avrc_cb.fcb[handle];
/* The response type of the end fragment should be the same as the the PDU of
- *"End Fragment
- ** Response" Errata:
- *https://www.bluetooth.org/errata/errata_view.cfm?errata_id=4383
- */
+ * "End Fragment Response" Errata:
+ * https://www.bluetooth.org/errata/errata_view.cfm?errata_id=4383
+ */
p_orig_data = ((uint8_t*)(p_fcb->p_fmsg + 1) + p_fcb->p_fmsg->offset);
rsp_type = ((*p_orig_data) & AVRC_CTYPE_MASK);
@@ -498,16 +496,16 @@
p_rcb->p_rmsg->offset = p_rcb->rasm_offset = 0;
/*
- * Free original START packet, replace with pointer to
- * reassembly buffer.
- */
+ * Free original START packet, replace with pointer to
+ * reassembly buffer.
+ */
osi_free(p_pkt);
*pp_pkt = p_rcb->p_rmsg;
/*
- * Set offset to point to where to copy next - use the same
- * reassembly logic as AVCT.
- */
+ * Set offset to point to where to copy next - use the same
+ * reassembly logic as AVCT.
+ */
p_rcb->p_rmsg->offset += p_rcb->p_rmsg->len;
req_continue = true;
} else if (p_rcb->p_rmsg == NULL) {
@@ -522,9 +520,9 @@
} else {
/* get size of buffer holding assembled message */
/*
- * NOTE: The buffer is allocated above at the beginning of the
- * reassembly, and is always of size BT_DEFAULT_BUFFER_SIZE.
- */
+ * NOTE: The buffer is allocated above at the beginning of the
+ * reassembly, and is always of size BT_DEFAULT_BUFFER_SIZE.
+ */
uint16_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
/* adjust offset and len of fragment for header byte */
p_pkt->offset += (AVRC_VENDOR_HDR_SIZE + AVRC_MIN_META_HDR_SIZE);
@@ -582,10 +580,10 @@
drop_code = 4;
} else if (cr == AVCT_RSP) {
- if (req_continue == true) {
+ if (req_continue) {
avrc_cmd.pdu = AVRC_PDU_REQUEST_CONTINUATION_RSP;
drop_code = 2;
- } else if (buf_overflow == true) {
+ } else if (buf_overflow) {
/* Incoming message too big to fit in BT_DEFAULT_BUFFER_SIZE. Send abort
* to peer */
avrc_cmd.pdu = AVRC_PDU_ABORT_CONTINUATION_RSP;
@@ -606,7 +604,6 @@
return drop_code;
}
-#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
/******************************************************************************
*
@@ -756,7 +753,6 @@
p_msg->p_vendor_data = p_data;
p_msg->vendor_len = p_pkt->len - (p_data - p_begin);
-#if (AVRC_METADATA_INCLUDED == TRUE)
uint8_t drop_code = 0;
if (p_msg->company_id == AVRC_CO_METADATA) {
/* Validate length for metadata message */
@@ -791,7 +787,6 @@
p_drop_msg = "sent_fragd";
}
}
-#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
/* If vendor response received, and did not ask for continuation */
/* then check queue for addition commands to send */
if ((cr == AVCT_RSP) && (drop_code != 2)) {
@@ -863,9 +858,9 @@
drop = true;
}
- if (drop == false) {
+ if (!drop) {
msg.hdr.opcode = opcode;
- (*avrc_cb.ccb[handle].p_msg_cback)(handle, label, opcode, &msg);
+ avrc_cb.ccb[handle].msg_cback.Run(handle, label, opcode, &msg);
} else {
AVRC_TRACE_WARNING("%s %s msg handle:%d, control:%d, cr:%d, opcode:x%x",
__func__, p_drop_msg, handle,
@@ -879,62 +874,6 @@
if (do_free) osi_free(p_pkt);
}
-static void AVRC_build_empty_packet(BT_HDR* p_pkt) {
- uint8_t* p_start = ((uint8_t*)(p_pkt + 1) + p_pkt->offset);
- *p_start = AVRC_RSP_ACCEPT & AVRC_CTYPE_MASK;
- p_start += AVRC_VENDOR_HDR_SIZE;
- UINT8_TO_BE_STREAM(p_start, 0);
- UINT8_TO_BE_STREAM(p_start, AVRC_PKT_SINGLE);
- UINT16_TO_BE_STREAM(p_start, 0);
- p_pkt->len = AVRC_VENDOR_HDR_SIZE + 4;
-}
-
-static void AVRC_build_error_packet(BT_HDR* p_pkt) {
- uint8_t* p_start = ((uint8_t*)(p_pkt + 1) + p_pkt->offset);
- *p_start = AVRC_RSP_REJ & AVRC_CTYPE_MASK;
- p_start += AVRC_VENDOR_HDR_SIZE;
- UINT8_TO_BE_STREAM(p_start, 0);
- UINT8_TO_BE_STREAM(p_start, AVRC_PKT_SINGLE);
- UINT16_TO_BE_STREAM(p_start, 1);
- UINT8_TO_BE_STREAM(p_start, AVRC_STS_BAD_PARAM);
- p_pkt->len = AVRC_VENDOR_HDR_SIZE + 5;
-}
-
-static uint16_t AVRC_HandleContinueRsp(uint8_t handle, uint8_t label,
- BT_HDR* p_pkt) {
- AVRC_TRACE_DEBUG("%s()", __func__);
-
- uint8_t* p_data =
- ((uint8_t*)(p_pkt + 1) + p_pkt->offset + AVRC_VENDOR_HDR_SIZE);
- tAVRC_FRAG_CB* p_fcb = &avrc_cb.fcb[handle];
-
- uint8_t pdu, pkt_type, target_pdu;
- uint16_t len;
-
- BE_STREAM_TO_UINT8(pdu, p_data);
- BE_STREAM_TO_UINT8(pkt_type, p_data);
- BE_STREAM_TO_UINT16(len, p_data);
- BE_STREAM_TO_UINT8(target_pdu, p_data);
-
- if (pdu == AVRC_PDU_REQUEST_CONTINUATION_RSP &&
- target_pdu == p_fcb->frag_pdu) {
- return avrc_send_continue_frag(handle, label);
- }
-
- if (pdu == AVRC_PDU_ABORT_CONTINUATION_RSP && target_pdu == p_fcb->frag_pdu) {
- AVRC_build_empty_packet(p_pkt);
- } else {
- AVRC_TRACE_ERROR("%s() error: target_pdu: 0x%02x, frag_pdu: 0x%02x",
- __func__, *(p_data + 4), p_fcb->frag_pdu);
- AVRC_build_error_packet(p_pkt);
- }
-
- p_fcb->frag_enabled = false;
- osi_free_and_reset((void**)&p_fcb->p_fmsg);
-
- return AVCT_MsgReq(handle, label, AVCT_RSP, p_pkt);
-}
-
/******************************************************************************
*
* Function avrc_pass_msg
@@ -1043,12 +982,10 @@
status = AVCT_CreateConn(p_handle, &cc, peer_addr);
if (status == AVCT_SUCCESS) {
- memcpy(&avrc_cb.ccb[*p_handle], p_ccb, sizeof(tAVRC_CONN_CB));
+ avrc_cb.ccb[*p_handle] = *p_ccb;
memset(&avrc_cb.ccb_int[*p_handle], 0, sizeof(tAVRC_CONN_INT_CB));
-#if (AVRC_METADATA_INCLUDED == TRUE)
memset(&avrc_cb.fcb[*p_handle], 0, sizeof(tAVRC_FRAG_CB));
memset(&avrc_cb.rcb[*p_handle], 0, sizeof(tAVRC_RASM_CB));
-#endif
avrc_cb.ccb_int[*p_handle].tle = alarm_new("avrcp.commandTimer");
avrc_cb.ccb_int[*p_handle].cmd_q = fixed_queue_new(SIZE_MAX);
}
@@ -1078,6 +1015,7 @@
*****************************************************************************/
uint16_t AVRC_Close(uint8_t handle) {
AVRC_TRACE_DEBUG("%s handle:%d", __func__, handle);
+ avrc_flush_cmd_q(handle);
return AVCT_RemoveConn(handle);
}
@@ -1134,7 +1072,6 @@
*****************************************************************************/
uint16_t AVRC_MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
BT_HDR* p_pkt) {
-#if (AVRC_METADATA_INCLUDED == TRUE)
uint8_t* p_data;
uint8_t cr = AVCT_CMD;
bool chk_frag = true;
@@ -1152,12 +1089,6 @@
if (ctype >= AVRC_RSP_NOT_IMPL) cr = AVCT_RSP;
- p_data = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
- if (*p_data == AVRC_PDU_REQUEST_CONTINUATION_RSP ||
- *p_data == AVRC_PDU_ABORT_CONTINUATION_RSP) {
- return AVRC_HandleContinueRsp(handle, label, p_pkt);
- }
-
if (p_pkt->event == AVRC_OP_VENDOR) {
/* add AVRCP Vendor Dependent headers */
p_start = ((uint8_t*)(p_pkt + 1) + p_pkt->offset);
@@ -1218,7 +1149,7 @@
/* AVRCP spec has not defined any control channel commands that needs
* fragmentation at this level
* check for fragmentation only on the response */
- if ((cr == AVCT_RSP) && (chk_frag == true)) {
+ if ((cr == AVCT_RSP) && (chk_frag)) {
if (p_pkt->len > AVRC_MAX_CTRL_DATA_LEN) {
int offset_len = MAX(AVCT_MSG_OFFSET, p_pkt->offset);
BT_HDR* p_pkt_new =
@@ -1290,9 +1221,6 @@
}
return status;
-#else
- return AVRC_NO_RESOURCES;
-#endif
}
/******************************************************************************
diff --git a/stack/avrc/avrc_bld_ct.cc b/stack/avrc/avrc_bld_ct.cc
index 2cb1246..afb1784b 100644
--- a/stack/avrc/avrc_bld_ct.cc
+++ b/stack/avrc/avrc_bld_ct.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2013 Broadcom Corporation
+ * Copyright 2006-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
* Global data
****************************************************************************/
-#if (AVRC_METADATA_INCLUDED == TRUE)
/*******************************************************************************
*
* Function avrc_bld_next_cmd
@@ -661,4 +660,3 @@
AVRC_TRACE_API("AVRC_BldCommand: returning %d", status);
return status;
}
-#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
diff --git a/stack/avrc/avrc_bld_tg.cc b/stack/avrc/avrc_bld_tg.cc
index f96a5d3..b28c9e2 100644
--- a/stack/avrc/avrc_bld_tg.cc
+++ b/stack/avrc/avrc_bld_tg.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2016 Broadcom Corporation
+ * Copyright 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@
/*****************************************************************************
* Global data
****************************************************************************/
-#if (AVRC_METADATA_INCLUDED == TRUE)
#define AVRC_ITEM_PLAYER_IS_VALID(_p_player) \
((_p_player)->name.p_str && \
((_p_player)->major_type & AVRC_MJ_TYPE_INVALID) == 0 && \
@@ -955,7 +954,7 @@
/* min len required = item_type(1) + item len(2) + min item (14) = 17 */
for (xx = 0;
xx < p_rsp->item_count && len_left > AVRC_MIN_LEN_GET_FOLDER_ITEMS_RSP &&
- multi_items_add_fail == false;
+ !multi_items_add_fail;
xx++) {
p_item_start = p_data;
UINT8_TO_BE_STREAM(p_data, p_item_list[xx].item_type);
@@ -970,8 +969,7 @@
p_player = &p_item_list[xx].u.player;
item_len = AVRC_FEATURE_MASK_SIZE + p_player->name.str_len + 12;
- if ((len_left <= item_len) ||
- AVRC_ITEM_PLAYER_IS_VALID(p_player) == false) {
+ if ((len_left <= item_len) || !AVRC_ITEM_PLAYER_IS_VALID(p_player)) {
p_data = p_item_start;
} else {
UINT16_TO_BE_STREAM(p_data, p_player->player_id);
@@ -1058,7 +1056,7 @@
/* fill in variable item lenth */
UINT16_TO_BE_STREAM(p_item_len, item_len);
} else {
- if (multi_items_add_fail == false) {
+ if (!multi_items_add_fail) {
/* some item is not added properly - set an error status */
if (len_left < item_len)
status = AVRC_STS_INTERNAL_ERR;
@@ -1066,7 +1064,7 @@
status = AVRC_STS_BAD_PARAM;
}
}
- if (multi_items_add_fail == false) {
+ if (!multi_items_add_fail) {
len += item_len;
len += 3; /* the item_type(1) and item_len(2) */
}
@@ -1519,5 +1517,3 @@
AVRC_TRACE_API("%s returning %d", __func__, status);
return status;
}
-
-#endif /* (AVRC_METADATA_INCLUDED == true)*/
diff --git a/stack/avrc/avrc_int.h b/stack/avrc/avrc_int.h
index d6c79c8..779a90a 100644
--- a/stack/avrc/avrc_int.h
+++ b/stack/avrc/avrc_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2016 Broadcom Corporation
+ * Copyright 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -118,7 +118,6 @@
* Type definitions
****************************************************************************/
-#if (AVRC_METADATA_INCLUDED == TRUE)
/* type for Metadata fragmentation control block */
typedef struct {
BT_HDR* p_fmsg; /* the fragmented message */
@@ -132,7 +131,6 @@
uint16_t rasm_offset; /* re-assembly flag, the offset of the start fragment */
uint8_t rasm_pdu; /* the PDU ID for re-assembly */
} tAVRC_RASM_CB;
-#endif
/* AVRC internal connection control block */
typedef struct {
@@ -147,11 +145,9 @@
ccb[AVCT_NUM_CONN]; /* Connection control block from AVRC_Open API */
tAVRC_CONN_INT_CB
ccb_int[AVCT_NUM_CONN]; /* Internal connection control block */
-#if (AVRC_METADATA_INCLUDED == TRUE)
tAVRC_FRAG_CB fcb[AVCT_NUM_CONN];
tAVRC_RASM_CB rcb[AVCT_NUM_CONN];
-#endif
- tAVRC_FIND_CBACK* p_cback; /* pointer to application callback */
+ tAVRC_FIND_CBACK find_cback; /* sdp discovery callback */
tSDP_DISCOVERY_DB* p_db; /* pointer to discovery database */
uint16_t service_uuid; /* service UUID to search */
uint8_t trace_level;
diff --git a/stack/avrc/avrc_opt.cc b/stack/avrc/avrc_opt.cc
index 1c0acb8..de42e15 100644
--- a/stack/avrc/avrc_opt.cc
+++ b/stack/avrc/avrc_opt.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,13 +50,8 @@
CHECK(p_msg != NULL);
-#if (AVRC_METADATA_INCLUDED == TRUE)
CHECK(AVRC_META_CMD_BUF_SIZE > (AVRC_MIN_CMD_LEN + p_msg->vendor_len));
p_cmd = (BT_HDR*)osi_malloc(AVRC_META_CMD_BUF_SIZE);
-#else
- CHECK(AVRC_CMD_BUF_SIZE > (AVRC_MIN_CMD_LEN + p_msg->vendor_len));
- p_cmd = (BT_HDR*)osi_malloc(AVRC_CMD_BUF_SIZE);
-#endif
p_cmd->offset = AVCT_MSG_OFFSET;
p_data = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
diff --git a/stack/avrc/avrc_pars_ct.cc b/stack/avrc/avrc_pars_ct.cc
index fbfeeaf..4421c91 100644
--- a/stack/avrc/avrc_pars_ct.cc
+++ b/stack/avrc/avrc_pars_ct.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2013 Broadcom Corporation
+ * Copyright 2006-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,8 +29,6 @@
* Global data
****************************************************************************/
-#if (AVRC_METADATA_INCLUDED == TRUE)
-
/*******************************************************************************
*
* Function avrc_pars_vendor_rsp
@@ -707,4 +705,3 @@
}
return status;
}
-#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
diff --git a/stack/avrc/avrc_pars_tg.cc b/stack/avrc/avrc_pars_tg.cc
index 12b7598..c0504ee 100644
--- a/stack/avrc/avrc_pars_tg.cc
+++ b/stack/avrc/avrc_pars_tg.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2016 Broadcom Corporation
+ * Copyright 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
/*****************************************************************************
* Global data
****************************************************************************/
-#if (AVRC_METADATA_INCLUDED == TRUE)
/*******************************************************************************
*
@@ -560,5 +559,3 @@
AVRC_TRACE_DEBUG("%s return status:0x%x", __func__, status);
return status;
}
-
-#endif /* (AVRC_METADATA_INCLUDED == true) */
diff --git a/stack/avrc/avrc_sdp.cc b/stack/avrc/avrc_sdp.cc
index 3a7ed96..860a8d0 100644
--- a/stack/avrc/avrc_sdp.cc
+++ b/stack/avrc/avrc_sdp.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2016 Broadcom Corporation
+ * Copyright 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,8 @@
#include "avrc_int.h"
#include "bt_common.h"
+using bluetooth::Uuid;
+
/*****************************************************************************
* Global data
****************************************************************************/
@@ -59,7 +61,7 @@
avrc_cb.service_uuid = 0;
/* return info from sdp record in app callback function */
- (*avrc_cb.p_cback)(status);
+ avrc_cb.find_cback.Run(status);
return;
}
@@ -105,14 +107,13 @@
*****************************************************************************/
uint16_t AVRC_FindService(uint16_t service_uuid, const RawAddress& bd_addr,
tAVRC_SDP_DB_PARAMS* p_db,
- tAVRC_FIND_CBACK* p_cback) {
- tSDP_UUID uuid_list;
+ const tAVRC_FIND_CBACK& find_cback) {
bool result = true;
AVRC_TRACE_API("%s uuid: %x", __func__, service_uuid);
if ((service_uuid != UUID_SERVCLASS_AV_REM_CTRL_TARGET &&
service_uuid != UUID_SERVCLASS_AV_REMOTE_CONTROL) ||
- p_db == NULL || p_db->p_db == NULL || p_cback == NULL)
+ p_db == NULL || p_db->p_db == NULL || find_cback.is_null())
return AVRC_BAD_PARAM;
/* check if it is busy */
@@ -120,23 +121,21 @@
avrc_cb.service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL)
return AVRC_NO_RESOURCES;
- /* set up discovery database */
- uuid_list.len = LEN_UUID_16;
- uuid_list.uu.uuid16 = service_uuid;
if (p_db->p_attrs == NULL || p_db->num_attr == 0) {
p_db->p_attrs = a2dp_attr_list_sdp;
p_db->num_attr = AVRC_NUM_ATTR;
}
+ Uuid uuid_list = Uuid::From16Bit(service_uuid);
result = SDP_InitDiscoveryDb(p_db->p_db, p_db->db_len, 1, &uuid_list,
p_db->num_attr, p_db->p_attrs);
- if (result == true) {
+ if (result) {
/* store service_uuid and discovery db pointer */
avrc_cb.p_db = p_db->p_db;
avrc_cb.service_uuid = service_uuid;
- avrc_cb.p_cback = p_cback;
+ avrc_cb.find_cback = find_cback;
/* perform service search */
result =
@@ -210,7 +209,17 @@
}
result &= SDP_AddServiceClassIdList(sdp_handle, count, class_list);
- /* add protocol descriptor list */
+ uint16_t protocol_reported_version;
+ /* AVRCP versions 1.3 to 1.5 report (version - 1) in the protocol
+ descriptor list. Oh, and 1.6 and 1.6.1 report version 1.4.
+ /because-we-smart */
+ if (profile_version < AVRC_REV_1_6) {
+ protocol_reported_version = profile_version - 1;
+ } else {
+ protocol_reported_version = AVCT_REV_1_4;
+ }
+
+ /* add protocol descriptor list */
tSDP_PROTOCOL_ELEM avrc_proto_desc_list[AVRC_NUM_PROTO_ELEMS];
avrc_proto_desc_list[0].num_params = 1;
avrc_proto_desc_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
@@ -219,13 +228,13 @@
for (index = 1; index < AVRC_NUM_PROTO_ELEMS; index++) {
avrc_proto_desc_list[index].num_params = 1;
avrc_proto_desc_list[index].protocol_uuid = UUID_PROTOCOL_AVCTP;
- avrc_proto_desc_list[index].params[0] = AVCT_REV_1_4;
+ avrc_proto_desc_list[index].params[0] = protocol_reported_version;
avrc_proto_desc_list[index].params[1] = 0;
}
result &= SDP_AddProtocolList(sdp_handle, AVRC_NUM_PROTO_ELEMS,
- (tSDP_PROTOCOL_ELEM*)avrc_proto_desc_list);
+ &avrc_proto_desc_list[0]);
- /* additional protocal descriptor, required only for version > 1.3 */
+ /* additional protocal descriptor, required only for version > 1.3 */
if ((profile_version > AVRC_REV_1_3) && (browse_supported)) {
tSDP_PROTO_LIST_ELEM avrc_add_proto_desc_list;
avrc_add_proto_desc_list.num_elems = 2;
@@ -235,11 +244,11 @@
avrc_add_proto_desc_list.list_elem[0].params[1] = 0;
avrc_add_proto_desc_list.list_elem[1].num_params = 1;
avrc_add_proto_desc_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_AVCTP;
- avrc_add_proto_desc_list.list_elem[1].params[0] = AVCT_REV_1_4;
+ avrc_add_proto_desc_list.list_elem[1].params[0] = protocol_reported_version;
avrc_add_proto_desc_list.list_elem[1].params[1] = 0;
- result &= SDP_AddAdditionProtoLists(
- sdp_handle, 1, (tSDP_PROTO_LIST_ELEM*)&avrc_add_proto_desc_list);
+ result &=
+ SDP_AddAdditionProtoLists(sdp_handle, 1, &avrc_add_proto_desc_list);
}
/* add profile descriptor list */
result &= SDP_AddProfileDescriptorList(
diff --git a/stack/avrc/avrc_utils.cc b/stack/avrc/avrc_utils.cc
index 6504ac4..927f62b 100644
--- a/stack/avrc/avrc_utils.cc
+++ b/stack/avrc/avrc_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2016 Broadcom Corporation
+ * Copyright 2003-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,8 +21,6 @@
#include "avrc_int.h"
#include "bt_common.h"
-#if (AVRC_METADATA_INCLUDED == TRUE)
-
/**************************************************************************
*
* Function AVRC_IsValidAvcType
@@ -230,5 +228,3 @@
}
return is_valid;
}
-
-#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
diff --git a/stack/bnep/bnep_api.cc b/stack/bnep/bnep_api.cc
index e5d3c09..0e7b692 100644
--- a/stack/bnep/bnep_api.cc
+++ b/stack/bnep/bnep_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2001-2012 Broadcom Corporation
+ * Copyright 2001-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,10 +23,11 @@
******************************************************************************/
#include "bnep_api.h"
-#include <log/log.h>
#include <string.h>
#include "bnep_int.h"
+using bluetooth::Uuid;
+
/*******************************************************************************
*
* Function BNEP_Init
@@ -124,8 +125,8 @@
* BNEP_NO_RESOURCES if no resources
*
******************************************************************************/
-tBNEP_RESULT BNEP_Connect(const RawAddress& p_rem_bda, tBT_UUID* src_uuid,
- tBT_UUID* dst_uuid, uint16_t* p_handle) {
+tBNEP_RESULT BNEP_Connect(const RawAddress& p_rem_bda, const Uuid& src_uuid,
+ const Uuid& dst_uuid, uint16_t* p_handle) {
uint16_t cid;
tBNEP_CONN* p_bcb = bnepu_find_bcb_by_bd_addr(p_rem_bda);
@@ -133,9 +134,6 @@
if (!bnep_cb.profile_registered) return BNEP_WRONG_STATE;
- /* Both source and destination UUID lengths should be same */
- if (src_uuid->len != dst_uuid->len) return BNEP_CONN_FAILED_UUID_SIZE;
-
if (!p_bcb) {
p_bcb = bnepu_allocate_bcb(p_rem_bda);
if (p_bcb == NULL) return (BNEP_NO_RESOURCES);
@@ -143,29 +141,27 @@
return BNEP_WRONG_STATE;
else {
/* Backup current UUID values to restore if role change fails */
- memcpy((uint8_t*)&(p_bcb->prv_src_uuid), (uint8_t*)&(p_bcb->src_uuid),
- sizeof(tBT_UUID));
- memcpy((uint8_t*)&(p_bcb->prv_dst_uuid), (uint8_t*)&(p_bcb->dst_uuid),
- sizeof(tBT_UUID));
+ p_bcb->prv_src_uuid = p_bcb->src_uuid;
+ p_bcb->prv_dst_uuid = p_bcb->dst_uuid;
}
/* We are the originator of this connection */
p_bcb->con_flags |= BNEP_FLAGS_IS_ORIG;
- memcpy((uint8_t*)&(p_bcb->src_uuid), (uint8_t*)src_uuid, sizeof(tBT_UUID));
- memcpy((uint8_t*)&(p_bcb->dst_uuid), (uint8_t*)dst_uuid, sizeof(tBT_UUID));
+ p_bcb->src_uuid = src_uuid;
+ p_bcb->dst_uuid = dst_uuid;
if (p_bcb->con_state == BNEP_STATE_CONNECTED) {
/* Transition to the next appropriate state, waiting for connection confirm.
*/
p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
- BNEP_TRACE_API("BNEP initiating security procedures for src uuid 0x%x",
- p_bcb->src_uuid.uu.uuid16);
+ BNEP_TRACE_API("BNEP initiating security procedures for src uuid %s",
+ p_bcb->src_uuid.ToString().c_str());
#if (BNEP_DO_AUTH_FOR_ROLE_SWITCH == TRUE)
btm_sec_mx_access_request(p_bcb->rem_bda, BT_PSM_BNEP, true,
- BTM_SEC_PROTO_BNEP, bnep_get_uuid32(src_uuid),
+ BTM_SEC_PROTO_BNEP, src_uuid.As32Bit(),
&bnep_sec_check_complete, p_bcb);
#else
bnep_sec_check_complete(p_bcb->rem_bda, p_bcb, BTM_SUCCESS);
@@ -250,10 +246,8 @@
p_bcb->con_state = BNEP_STATE_CONNECTED;
p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
- memcpy((uint8_t*)&(p_bcb->src_uuid), (uint8_t*)&(p_bcb->prv_src_uuid),
- sizeof(tBT_UUID));
- memcpy((uint8_t*)&(p_bcb->dst_uuid), (uint8_t*)&(p_bcb->prv_dst_uuid),
- sizeof(tBT_UUID));
+ p_bcb->src_uuid = p_bcb->prv_src_uuid;
+ p_bcb->dst_uuid = p_bcb->prv_dst_uuid;
}
/* Process remaining part of the setup message (extension headers) */
@@ -384,10 +378,7 @@
protocol = 0;
else {
new_len += 4;
- if (new_len > org_len) {
- android_errorWriteLog(0x534e4554, "74947856");
- return BNEP_IGNORE_CMD;
- }
+ if (new_len > org_len) return BNEP_IGNORE_CMD;
p_data[2] = 0;
p_data[3] = 0;
}
@@ -484,10 +475,7 @@
protocol = 0;
else {
new_len += 4;
- if (new_len > org_len) {
- android_errorWriteLog(0x534e4554, "74947856");
- return BNEP_IGNORE_CMD;
- }
+ if (new_len > org_len) return BNEP_IGNORE_CMD;
p_data[2] = 0;
p_data[3] = 0;
}
@@ -689,8 +677,8 @@
p_status->rcvd_mcast_filters = p_bcb->rcvd_mcast_filters;
p_status->rem_bda = p_bcb->rem_bda;
- memcpy(&(p_status->src_uuid), &(p_bcb->src_uuid), sizeof(tBT_UUID));
- memcpy(&(p_status->dst_uuid), &(p_bcb->dst_uuid), sizeof(tBT_UUID));
+ p_status->src_uuid = p_bcb->src_uuid;
+ p_status->dst_uuid = p_bcb->dst_uuid;
return BNEP_SUCCESS;
#else
diff --git a/stack/bnep/bnep_int.h b/stack/bnep/bnep_int.h
index e25e7f8..2587147 100644
--- a/stack/bnep/bnep_int.h
+++ b/stack/bnep/bnep_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2001-2012 Broadcom Corporation
+ * Copyright 2001-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -149,10 +149,10 @@
uint16_t bad_pkts_rcvd;
uint8_t re_transmits;
uint16_t handle;
- tBT_UUID prv_src_uuid;
- tBT_UUID prv_dst_uuid;
- tBT_UUID src_uuid;
- tBT_UUID dst_uuid;
+ bluetooth::Uuid prv_src_uuid;
+ bluetooth::Uuid prv_dst_uuid;
+ bluetooth::Uuid src_uuid;
+ bluetooth::Uuid dst_uuid;
} tBNEP_CONN;
@@ -231,6 +231,5 @@
uint16_t protocol,
bool fw_ext_present,
uint8_t* p_data);
-extern uint32_t bnep_get_uuid32(tBT_UUID* src_uuid);
#endif
diff --git a/stack/bnep/bnep_main.cc b/stack/bnep/bnep_main.cc
index 8772e57..ae6c51b 100644
--- a/stack/bnep/bnep_main.cc
+++ b/stack/bnep/bnep_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2001-2012 Broadcom Corporation
+ * Copyright 2001-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -255,9 +255,9 @@
bnep_conn_timer_timeout, p_bcb);
if (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) {
- btm_sec_mx_access_request(
- p_bcb->rem_bda, BT_PSM_BNEP, true, BTM_SEC_PROTO_BNEP,
- bnep_get_uuid32(&(p_bcb->src_uuid)), &bnep_sec_check_complete, p_bcb);
+ btm_sec_mx_access_request(p_bcb->rem_bda, BT_PSM_BNEP, true,
+ BTM_SEC_PROTO_BNEP, p_bcb->src_uuid.As32Bit(),
+ &bnep_sec_check_complete, p_bcb);
}
}
}
@@ -299,8 +299,7 @@
if (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) {
btm_sec_mx_access_request(p_bcb->rem_bda, BT_PSM_BNEP, true,
- BTM_SEC_PROTO_BNEP,
- bnep_get_uuid32(&(p_bcb->src_uuid)),
+ BTM_SEC_PROTO_BNEP, p_bcb->src_uuid.As32Bit(),
&bnep_sec_check_complete, p_bcb);
}
}
@@ -623,7 +622,6 @@
if (bnep_cb.p_data_buf_cb) {
(*bnep_cb.p_data_buf_cb)(p_bcb->handle, *p_src_addr, *p_dst_addr, protocol,
p_buf, fw_ext_present);
- osi_free(p_buf);
} else if (bnep_cb.p_data_ind_cb) {
(*bnep_cb.p_data_ind_cb)(p_bcb->handle, *p_src_addr, *p_dst_addr, protocol,
p, rem_len, fw_ext_present);
diff --git a/stack/bnep/bnep_utils.cc b/stack/bnep/bnep_utils.cc
index 3bab9ee..48fd5d1 100644
--- a/stack/bnep/bnep_utils.cc
+++ b/stack/bnep/bnep_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2001-2012 Broadcom Corporation
+ * Copyright 2001-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,8 @@
#include "device/include/controller.h"
#include "osi/include/osi.h"
+using bluetooth::Uuid;
+
/******************************************************************************/
/* L O C A L F U N C T I O N P R O T O T Y P E S */
/******************************************************************************/
@@ -166,8 +168,8 @@
BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
uint8_t *p, *p_start;
- BNEP_TRACE_DEBUG("%s: sending setup req with dst uuid %x", __func__,
- p_bcb->dst_uuid.uu.uuid16);
+ BNEP_TRACE_DEBUG("%s: sending setup req with dst uuid %s", __func__,
+ p_bcb->dst_uuid.ToString().c_str());
p_buf->offset = L2CAP_MIN_OFFSET;
p = p_start = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
@@ -178,22 +180,26 @@
/* Put in filter message type - set filters */
UINT8_TO_BE_STREAM(p, BNEP_SETUP_CONNECTION_REQUEST_MSG);
- UINT8_TO_BE_STREAM(p, p_bcb->dst_uuid.len);
+ int len = std::max(p_bcb->dst_uuid.GetShortestRepresentationSize(),
+ p_bcb->src_uuid.GetShortestRepresentationSize());
- if (p_bcb->dst_uuid.len == 2) {
- UINT16_TO_BE_STREAM(p, p_bcb->dst_uuid.uu.uuid16);
- UINT16_TO_BE_STREAM(p, p_bcb->src_uuid.uu.uuid16);
- } else if (p_bcb->dst_uuid.len == 4) {
- UINT32_TO_BE_STREAM(p, p_bcb->dst_uuid.uu.uuid32);
- UINT32_TO_BE_STREAM(p, p_bcb->src_uuid.uu.uuid32);
- } else if (p_bcb->dst_uuid.len == 16) {
- memcpy(p, p_bcb->dst_uuid.uu.uuid128, p_bcb->dst_uuid.len);
- p += p_bcb->dst_uuid.len;
- memcpy(p, p_bcb->src_uuid.uu.uuid128, p_bcb->dst_uuid.len);
- p += p_bcb->dst_uuid.len;
+ UINT8_TO_BE_STREAM(p, len);
+
+ if (len == Uuid::kNumBytes16) {
+ UINT16_TO_BE_STREAM(p, p_bcb->dst_uuid.As16Bit());
+ UINT16_TO_BE_STREAM(p, p_bcb->src_uuid.As16Bit());
+ } else if (len == Uuid::kNumBytes32) {
+ UINT32_TO_BE_STREAM(p, p_bcb->dst_uuid.As32Bit());
+ UINT32_TO_BE_STREAM(p, p_bcb->src_uuid.As32Bit());
+ } else if (len == Uuid::kNumBytes128) {
+ memcpy(p, p_bcb->dst_uuid.To128BitBE().data(), Uuid::kNumBytes128);
+ p += Uuid::kNumBytes128;
+ memcpy(p, p_bcb->src_uuid.To128BitBE().data(), Uuid::kNumBytes128);
+ p += Uuid::kNumBytes128;
} else {
- BNEP_TRACE_ERROR("%s: uuid: %x, invalid length: %x", __func__,
- p_bcb->dst_uuid.uu.uuid16, p_bcb->dst_uuid.len);
+ BNEP_TRACE_ERROR("%s: uuid: %s, invalid length: %zu", __func__,
+ p_bcb->dst_uuid.ToString().c_str(),
+ p_bcb->dst_uuid.GetShortestRepresentationSize());
}
p_buf->len = (uint16_t)(p - p_start);
@@ -525,8 +531,7 @@
******************************************************************************/
void bnep_process_setup_conn_req(tBNEP_CONN* p_bcb, uint8_t* p_setup,
uint8_t len) {
- BNEP_TRACE_EVENT("BNEP - bnep_process_setup_conn_req for CID: 0x%x",
- p_bcb->l2cap_cid);
+ BNEP_TRACE_EVENT("BNEP - %s for CID: 0x%x", __func__, p_bcb->l2cap_cid);
if (p_bcb->con_state != BNEP_STATE_CONN_SETUP &&
p_bcb->con_state != BNEP_STATE_SEC_CHECKING &&
@@ -555,36 +560,43 @@
}
if (p_bcb->con_state == BNEP_STATE_CONNECTED) {
- memcpy((uint8_t*)&(p_bcb->prv_src_uuid), (uint8_t*)&(p_bcb->src_uuid),
- sizeof(tBT_UUID));
- memcpy((uint8_t*)&(p_bcb->prv_dst_uuid), (uint8_t*)&(p_bcb->dst_uuid),
- sizeof(tBT_UUID));
+ p_bcb->prv_src_uuid = p_bcb->src_uuid;
+ p_bcb->prv_dst_uuid = p_bcb->dst_uuid;
}
- p_bcb->dst_uuid.len = p_bcb->src_uuid.len = len;
-
- if (p_bcb->dst_uuid.len == 2) {
+ if (len == Uuid::kNumBytes16) {
/* because peer initiated connection keep src uuid as dst uuid */
- BE_STREAM_TO_UINT16(p_bcb->src_uuid.uu.uuid16, p_setup);
- BE_STREAM_TO_UINT16(p_bcb->dst_uuid.uu.uuid16, p_setup);
+ uint16_t tmp;
+
+ BE_STREAM_TO_UINT16(tmp, p_setup);
+ p_bcb->src_uuid = Uuid::From16Bit(tmp);
+
+ BE_STREAM_TO_UINT16(tmp, p_setup);
+ p_bcb->dst_uuid = Uuid::From16Bit(tmp);
/* If nothing has changed don't bother the profile */
if (p_bcb->con_state == BNEP_STATE_CONNECTED &&
- p_bcb->src_uuid.uu.uuid16 == p_bcb->prv_src_uuid.uu.uuid16 &&
- p_bcb->dst_uuid.uu.uuid16 == p_bcb->prv_dst_uuid.uu.uuid16) {
+ p_bcb->src_uuid == p_bcb->prv_src_uuid &&
+ p_bcb->dst_uuid == p_bcb->prv_dst_uuid) {
bnep_send_conn_responce(p_bcb, BNEP_SETUP_CONN_OK);
return;
}
- } else if (p_bcb->dst_uuid.len == 4) {
- BE_STREAM_TO_UINT32(p_bcb->src_uuid.uu.uuid32, p_setup);
- BE_STREAM_TO_UINT32(p_bcb->dst_uuid.uu.uuid32, p_setup);
- } else if (p_bcb->dst_uuid.len == 16) {
- memcpy(p_bcb->src_uuid.uu.uuid128, p_setup, p_bcb->src_uuid.len);
- p_setup += p_bcb->src_uuid.len;
- memcpy(p_bcb->dst_uuid.uu.uuid128, p_setup, p_bcb->dst_uuid.len);
- p_setup += p_bcb->dst_uuid.len;
+ } else if (len == Uuid::kNumBytes32) {
+ uint32_t tmp;
+
+ BE_STREAM_TO_UINT32(tmp, p_setup);
+ p_bcb->src_uuid = Uuid::From32Bit(tmp);
+
+ BE_STREAM_TO_UINT32(tmp, p_setup);
+ p_bcb->dst_uuid = Uuid::From32Bit(tmp);
+ } else if (len == Uuid::kNumBytes128) {
+ p_bcb->src_uuid = Uuid::From128BitBE(p_setup);
+ p_setup += len;
+
+ p_bcb->dst_uuid = Uuid::From128BitBE(p_setup);
+ p_setup += len;
} else {
- BNEP_TRACE_ERROR("BNEP - Bad UID len %d in ConnReq", p_bcb->dst_uuid.len);
+ BNEP_TRACE_ERROR("BNEP - Bad UID len %d in ConnReq", len);
bnep_send_conn_responce(p_bcb, BNEP_SETUP_INVALID_UUID_SIZE);
return;
}
@@ -593,16 +605,16 @@
p_bcb->con_flags |= BNEP_FLAGS_SETUP_RCVD;
BNEP_TRACE_EVENT(
- "BNEP initiating security check for incoming call for uuid 0x%x",
- p_bcb->src_uuid.uu.uuid16);
+ "BNEP initiating security check for incoming call for uuid %s",
+ p_bcb->src_uuid.ToString().c_str());
#if (BNEP_DO_AUTH_FOR_ROLE_SWITCH == FALSE)
if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
bnep_sec_check_complete(p_bcb->rem_bda, p_bcb, BTM_SUCCESS);
else
#endif
- btm_sec_mx_access_request(
- p_bcb->rem_bda, BT_PSM_BNEP, false, BTM_SEC_PROTO_BNEP,
- bnep_get_uuid32(&(p_bcb->src_uuid)), &bnep_sec_check_complete, p_bcb);
+ btm_sec_mx_access_request(p_bcb->rem_bda, BT_PSM_BNEP, false,
+ BTM_SEC_PROTO_BNEP, p_bcb->src_uuid.As32Bit(),
+ &bnep_sec_check_complete, p_bcb);
return;
}
@@ -666,10 +678,8 @@
/* Restore the earlier BNEP status */
p_bcb->con_state = BNEP_STATE_CONNECTED;
p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
- memcpy((uint8_t*)&(p_bcb->src_uuid), (uint8_t*)&(p_bcb->prv_src_uuid),
- sizeof(tBT_UUID));
- memcpy((uint8_t*)&(p_bcb->dst_uuid), (uint8_t*)&(p_bcb->prv_dst_uuid),
- sizeof(tBT_UUID));
+ p_bcb->src_uuid = p_bcb->prv_src_uuid;
+ p_bcb->dst_uuid = p_bcb->prv_dst_uuid;
/* Ensure timer is stopped */
alarm_cancel(p_bcb->conn_timer);
@@ -1177,10 +1187,8 @@
BNEP_SECURITY_FAIL, is_role_change);
p_bcb->con_state = BNEP_STATE_CONNECTED;
- memcpy((uint8_t*)&(p_bcb->src_uuid), (uint8_t*)&(p_bcb->prv_src_uuid),
- sizeof(tBT_UUID));
- memcpy((uint8_t*)&(p_bcb->dst_uuid), (uint8_t*)&(p_bcb->prv_dst_uuid),
- sizeof(tBT_UUID));
+ p_bcb->src_uuid = p_bcb->prv_src_uuid;
+ p_bcb->dst_uuid = p_bcb->prv_dst_uuid;
return;
}
@@ -1213,10 +1221,8 @@
* state */
p_bcb->con_state = BNEP_STATE_CONNECTED;
p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
- memcpy((uint8_t*)&(p_bcb->src_uuid), (uint8_t*)&(p_bcb->prv_src_uuid),
- sizeof(tBT_UUID));
- memcpy((uint8_t*)&(p_bcb->dst_uuid), (uint8_t*)&(p_bcb->prv_dst_uuid),
- sizeof(tBT_UUID));
+ p_bcb->src_uuid = p_bcb->prv_src_uuid;
+ p_bcb->dst_uuid = p_bcb->prv_dst_uuid;
return;
}
@@ -1228,8 +1234,8 @@
if (bnep_cb.p_conn_ind_cb) {
p_bcb->con_state = BNEP_STATE_CONN_SETUP;
- (*bnep_cb.p_conn_ind_cb)(p_bcb->handle, p_bcb->rem_bda, &p_bcb->dst_uuid,
- &p_bcb->src_uuid, is_role_change);
+ (*bnep_cb.p_conn_ind_cb)(p_bcb->handle, p_bcb->rem_bda, p_bcb->dst_uuid,
+ p_bcb->src_uuid, is_role_change);
} else {
/* Profile didn't register connection indication call back */
bnep_send_conn_responce(p_bcb, resp_code);
@@ -1317,26 +1323,3 @@
return BNEP_SUCCESS;
}
-
-/*******************************************************************************
- *
- * Function bnep_get_uuid32
- *
- * Description This function returns the 32-bit equivalent of the UUID
- *
- * Returns uint32_t - 32-bit equivalent of the UUID
- *
- ******************************************************************************/
-uint32_t bnep_get_uuid32(tBT_UUID* src_uuid) {
- uint32_t result;
-
- if (src_uuid->len == 2)
- return ((uint32_t)src_uuid->uu.uuid16);
- else if (src_uuid->len == 4)
- return (src_uuid->uu.uuid32 & 0x0000FFFF);
- else {
- result = src_uuid->uu.uuid128[2];
- result = (result << 8) | (src_uuid->uu.uuid128[3]);
- return result;
- }
-}
diff --git a/stack/btm/ble_advertiser_hci_interface.cc b/stack/btm/ble_advertiser_hci_interface.cc
index 377f1d4..93b517d 100644
--- a/stack/btm/ble_advertiser_hci_interface.cc
+++ b/stack/btm/ble_advertiser_hci_interface.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -318,7 +318,9 @@
}
void SetAdvertisingEventObserver(
- AdvertisingEventObserver* observer) override {}
+ AdvertisingEventObserver* observer) override {
+ this->advertising_event_observer = observer;
+ }
void SetParameters(uint8_t handle, uint16_t properties, uint32_t adv_int_min,
uint32_t adv_int_max, uint8_t channel_map,
@@ -457,6 +459,19 @@
// Legacy Advertising don't have remove method.
command_complete.Run(0);
}
+
+ public:
+ void OnAdvertisingSetTerminated(uint8_t status, uint16_t connection_handle) {
+ VLOG(1) << __func__;
+
+ AdvertisingEventObserver* observer = this->advertising_event_observer;
+ if (observer)
+ observer->OnAdvertisingSetTerminated(status, 0 /*advertising_handle*/,
+ connection_handle, 0);
+ }
+
+ private:
+ AdvertisingEventObserver* advertising_event_observer = nullptr;
};
class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface {
@@ -697,6 +712,15 @@
}
}
+bool legacy_advertising_in_use = false;
+void btm_ble_advertiser_notify_terminated_legacy(uint8_t status,
+ uint16_t connection_handle) {
+ if (BleAdvertiserHciInterface::Get() && legacy_advertising_in_use) {
+ ((BleAdvertiserLegacyHciInterfaceImpl*)BleAdvertiserHciInterface::Get())
+ ->OnAdvertisingSetTerminated(status, connection_handle);
+ }
+}
+
void BleAdvertiserHciInterface::Initialize() {
VLOG(1) << __func__;
LOG_ASSERT(instance == nullptr) << "Was already initialized.";
@@ -712,6 +736,7 @@
} else {
LOG(INFO) << "Legacy advertising will be in use";
instance = new BleAdvertiserLegacyHciInterfaceImpl();
+ legacy_advertising_in_use = true;
}
}
diff --git a/stack/btm/ble_advertiser_hci_interface.h b/stack/btm/ble_advertiser_hci_interface.h
index 166c1f6..c08bb86 100644
--- a/stack/btm/ble_advertiser_hci_interface.h
+++ b/stack/btm/ble_advertiser_hci_interface.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/btm/btm_acl.cc b/stack/btm/btm_acl.cc
index 8df6acb..ee2530a 100644
--- a/stack/btm/btm_acl.cc
+++ b/stack/btm/btm_acl.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2000-2012 Broadcom Corporation
+ * Copyright 2000-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,8 @@
*
*****************************************************************************/
+#define LOG_TAG "btm_acl"
+
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -48,6 +50,7 @@
#include "hcidefs.h"
#include "hcimsgs.h"
#include "l2c_int.h"
+#include "osi/include/log.h"
#include "osi/include/osi.h"
static void btm_read_remote_features(uint16_t handle);
@@ -191,8 +194,9 @@
tACL_CONN* p;
uint8_t xx;
- BTM_TRACE_DEBUG("btm_acl_created hci_handle=%d link_role=%d transport=%d",
- hci_handle, link_role, transport);
+ BTM_TRACE_DEBUG("%s: peer %s hci_handle=%d link_role=%d transport=%d",
+ __func__, bda.ToString().c_str(), hci_handle, link_role,
+ transport);
/* Ensure we don't have duplicates */
p = btm_bda_to_acl(bda, transport);
if (p != (tACL_CONN*)NULL) {
@@ -240,7 +244,8 @@
p_dev_rec = btm_find_dev_by_handle(hci_handle);
if (p_dev_rec) {
- BTM_TRACE_DEBUG("device_type=0x%x", p_dev_rec->device_type);
+ BTM_TRACE_DEBUG("%s: peer %s device_type=0x%x", __func__,
+ bda.ToString().c_str(), p_dev_rec->device_type);
}
if (p_dev_rec && !(transport == BT_TRANSPORT_LE)) {
@@ -281,8 +286,6 @@
} else {
btm_establish_continue(p);
}
- } else {
- btm_read_remote_features(p->hci_handle);
}
/* read page 1 - on rmt feature event for buffer reasons */
@@ -349,7 +352,7 @@
if (p->link_up_issued) {
p->link_up_issued = false;
- /* If anyone cares, tell him database changed */
+ /* If anyone cares, indicate the database changed */
if (btm_cb.p_bl_changed_cb) {
tBTM_BL_EVENT_DATA evt_data;
evt_data.event = BTM_BL_DISCN_EVT;
@@ -540,7 +543,10 @@
tBTM_STATUS status;
tBTM_PM_MODE pwr_mode;
tBTM_PM_PWR_MD settings;
- VLOG(1) << __func__ << " BDA: " << remote_bd_addr;
+
+ LOG_INFO(LOG_TAG, "%s: peer %s new_role=0x%x p_cb=%p p_switch_role_cb=%p",
+ __func__, remote_bd_addr.ToString().c_str(), new_role, p_cb,
+ btm_cb.devcb.p_switch_role_cb);
/* Make sure the local device supports switching */
if (!controller_get_interface()->supports_master_slave_role_switch())
@@ -565,7 +571,7 @@
/* Check if there is any SCO Active on this BD Address */
is_sco_active = btm_is_sco_active_by_bdaddr(remote_bd_addr);
- if (is_sco_active == true) return (BTM_NO_RESOURCES);
+ if (is_sco_active) return (BTM_NO_RESOURCES);
#endif
/* Ignore role switch request if the previous request was not completed */
@@ -690,8 +696,8 @@
(*btm_cb.p_bl_changed_cb)(&btm_bl_event_data);
BTM_TRACE_DEBUG(
- "Role Switch Event: new_role 0x%02x, HCI Status 0x%02x, rs_st:%d",
- evt.new_role, evt.hci_status, p->switch_role_state);
+ "%s: Role Switch Event: new_role 0x%02x, HCI Status 0x%02x, rs_st:%d",
+ __func__, evt.new_role, evt.hci_status, p->switch_role_state);
}
#if (BTM_DISC_DURING_RS == TRUE)
@@ -882,6 +888,10 @@
STREAM_TO_UINT8(p_acl_cb->lmp_version, p);
STREAM_TO_UINT16(p_acl_cb->manufacturer, p);
STREAM_TO_UINT16(p_acl_cb->lmp_subversion, p);
+
+ if (p_acl_cb->transport == BT_TRANSPORT_BR_EDR) {
+ btm_read_remote_features(p_acl_cb->hci_handle);
+ }
}
if (p_acl_cb->transport == BT_TRANSPORT_LE) {
@@ -931,6 +941,16 @@
HCI_FEATURE_BYTES_PER_PAGE);
}
+ if (!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN) ||
+ p_dev_rec->is_originator) {
+ BTM_TRACE_DEBUG("%s: Calling Next Security Procedure", __func__);
+ uint8_t status = btm_sec_execute_procedure(p_dev_rec);
+ if (status != BTM_CMD_STARTED) {
+ BTM_TRACE_ERROR("%s: Security procedure not started! status %d", __func__,
+ status);
+ btm_sec_dev_rec_cback_event(p_dev_rec, status, false);
+ }
+ }
const uint8_t req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND);
/* Store the Peer Security Capabilites (in SM4 and rmt_sec_caps) */
@@ -1175,6 +1195,10 @@
BTM_SetLinkPolicy(p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
}
#endif
+ if (p_acl_cb->link_up_issued) {
+ BTM_TRACE_ERROR("%s: Already link is up ", __func__);
+ return;
+ }
p_acl_cb->link_up_issued = true;
/* If anyone cares, tell him database changed */
@@ -1435,7 +1459,9 @@
tBTM_ROLE_SWITCH_CMPL* p_data = &btm_cb.devcb.switch_role_ref_data;
tBTM_SEC_DEV_REC* p_dev_rec;
- BTM_TRACE_DEBUG("btm_acl_role_changed");
+ BTM_TRACE_DEBUG("%s: peer %s hci_status:0x%x new_role:%d", __func__,
+ (p_bda != nullptr) ? bd_addr->ToString().c_str() : "nullptr",
+ hci_status, new_role);
/* Ignore any stray events */
if (p == NULL) {
/* it could be a failure */
@@ -1498,7 +1524,9 @@
}
BTM_TRACE_DEBUG(
- "Role Switch Event: new_role 0x%02x, HCI Status 0x%02x, rs_st:%d",
+ "%s: peer %s Role Switch Event: new_role 0x%02x, HCI Status 0x%02x, "
+ "rs_st:%d",
+ __func__, (p_bda != nullptr) ? p_bda->ToString().c_str() : "nullptr",
p_data->role, p_data->hci_status, p->switch_role_state);
#if (BTM_DISC_DURING_RS == TRUE)
@@ -1507,10 +1535,13 @@
if (p_dev_rec != NULL) {
if (p_dev_rec->rs_disc_pending == BTM_SEC_DISC_PENDING) {
BTM_TRACE_WARNING(
- "btm_acl_role_changed -> Issuing delayed HCI_Disconnect!!!");
+ "%s peer %s Issuing delayed HCI_Disconnect!!!", __func__,
+ (p_bda != nullptr) ? p_bda->ToString().c_str() : "nullptr");
btsnd_hcic_disconnect(p_dev_rec->hci_handle, HCI_ERR_PEER_USER);
}
- BTM_TRACE_ERROR("tBTM_SEC_DEV:0x%x rs_disc_pending=%d",
+ BTM_TRACE_ERROR("%s: peer %s tBTM_SEC_DEV:0x%x rs_disc_pending=%d",
+ __func__,
+ (p_bda != nullptr) ? p_bda->ToString().c_str() : "nullptr",
PTR_TO_UINT(p_dev_rec), p_dev_rec->rs_disc_pending);
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
}
@@ -1899,8 +1930,7 @@
*
******************************************************************************/
tBTM_STATUS BTM_ReadRSSI(const RawAddress& remote_bda, tBTM_CMPL_CB* p_cb) {
- tACL_CONN* p;
- tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+ tACL_CONN* p = NULL;
tBT_DEVICE_TYPE dev_type;
tBLE_ADDR_TYPE addr_type;
@@ -1908,10 +1938,16 @@
if (btm_cb.devcb.p_rssi_cmpl_cb) return (BTM_BUSY);
BTM_ReadDevInfo(remote_bda, &dev_type, &addr_type);
- if (dev_type == BT_DEVICE_TYPE_BLE) transport = BT_TRANSPORT_LE;
- p = btm_bda_to_acl(remote_bda, transport);
- if (p != (tACL_CONN*)NULL) {
+ if (dev_type & BT_DEVICE_TYPE_BLE) {
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_LE);
+ }
+
+ if (p == NULL && dev_type & BT_DEVICE_TYPE_BREDR) {
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
+ }
+
+ if (p) {
btm_cb.devcb.p_rssi_cmpl_cb = p_cb;
alarm_set_on_mloop(btm_cb.devcb.read_rssi_timer, BTM_DEV_REPLY_TIMEOUT_MS,
btm_read_rssi_timeout, NULL);
diff --git a/stack/btm/btm_ble.cc b/stack/btm/btm_ble.cc
index cd52216..ca93e1a 100644
--- a/stack/btm/btm_ble.cc
+++ b/stack/btm/btm_ble.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,6 +47,10 @@
extern bool aes_cipher_msg_auth_code(BT_OCTET16 key, uint8_t* input,
uint16_t length, uint16_t tlen,
uint8_t* p_signature);
+extern void gatt_notify_phy_updated(uint8_t status, uint16_t handle,
+ uint8_t tx_phy, uint8_t rx_phy);
+extern void btm_ble_advertiser_notify_terminated_legacy(
+ uint8_t status, uint16_t connection_handle);
/******************************************************************************/
/* External Function to be called by other modules */
@@ -85,8 +89,9 @@
p_dev_rec->conn_params.supervision_tout = BTM_BLE_CONN_PARAM_UNDEF;
p_dev_rec->conn_params.slave_latency = BTM_BLE_CONN_PARAM_UNDEF;
- BTM_TRACE_DEBUG("%s: Device added, handle=0x%x ", __func__,
- p_dev_rec->ble_hci_handle);
+ BTM_TRACE_DEBUG("%s: Device added, handle=0x%x, p_dev_rec=%p, bd_addr=%s",
+ __func__, p_dev_rec->ble_hci_handle, p_dev_rec,
+ bd_addr.ToString().c_str());
}
memset(p_dev_rec->sec_bd_name, 0, sizeof(tBTM_BD_NAME));
@@ -871,7 +876,7 @@
!controller_get_interface()->supports_ble_coded_phy()) {
BTM_TRACE_ERROR("%s failed, request not supported in local controller!",
__func__);
- cb.Run(0, 0, HCI_ERR_ILLEGAL_COMMAND);
+ cb.Run(0, 0, GATT_REQ_NOT_SUPPORTED);
return;
}
@@ -958,22 +963,24 @@
"= 0x%04x",
__func__, all_phys, tx_phys, rx_phys, phy_options);
+ uint16_t handle = p_acl->hci_handle;
+
// checking if local controller supports it!
if (!controller_get_interface()->supports_ble_2m_phy() &&
!controller_get_interface()->supports_ble_coded_phy()) {
BTM_TRACE_ERROR("%s failed, request not supported in local controller!",
__func__);
+ gatt_notify_phy_updated(GATT_REQ_NOT_SUPPORTED, handle, tx_phys, rx_phys);
return;
}
if (!HCI_LE_2M_PHY_SUPPORTED(p_acl->peer_le_features) &&
!HCI_LE_CODED_PHY_SUPPORTED(p_acl->peer_le_features)) {
BTM_TRACE_ERROR("%s failed, peer does not support request", __func__);
+ gatt_notify_phy_updated(GATT_REQ_NOT_SUPPORTED, handle, tx_phys, rx_phys);
return;
}
- uint16_t handle = p_acl->hci_handle;
-
const uint8_t len = HCIC_PARAM_SIZE_BLE_SET_PHY;
uint8_t data[len];
uint8_t* pp = data;
@@ -1311,8 +1318,11 @@
p_rec->ble.static_addr = p_keys->pid_key.static_addr;
p_rec->ble.static_addr_type = p_keys->pid_key.addr_type;
p_rec->ble.key_type |= BTM_LE_KEY_PID;
- BTM_TRACE_DEBUG("BTM_LE_KEY_PID key_type=0x%x save peer IRK",
- p_rec->ble.key_type);
+ BTM_TRACE_DEBUG(
+ "%s: BTM_LE_KEY_PID key_type=0x%x save peer IRK, change bd_addr=%s "
+ "to static_addr=%s",
+ __func__, p_rec->ble.key_type, p_rec->bd_addr.ToString().c_str(),
+ p_keys->pid_key.static_addr.ToString().c_str());
/* update device record address as static address */
p_rec->bd_addr = p_keys->pid_key.static_addr;
/* combine DUMO device security record if needed */
@@ -1374,7 +1384,7 @@
return;
}
- VLOG(1) << "BLE key type 0x" << std::hex << key_type
+ VLOG(1) << "BLE key type 0x" << loghex(key_type)
<< " updated for BDA: " << bd_addr << " (btm_sec_save_le_key)";
/* Notify the application that one of the BLE keys has been updated
@@ -1388,7 +1398,7 @@
return;
}
- LOG(WARNING) << "BLE key type 0x" << std::hex << key_type
+ LOG(WARNING) << "BLE key type 0x" << loghex(key_type)
<< " called for Unknown BDA or type: " << bd_addr
<< "(btm_sec_save_le_key)";
@@ -1548,8 +1558,8 @@
case BTM_BLE_SEC_ENCRYPT_NO_MITM:
case BTM_BLE_SEC_ENCRYPT_MITM:
auth_req = (sec_act == BTM_BLE_SEC_ENCRYPT_NO_MITM)
- ? SMP_AUTH_GEN_BOND
- : (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT);
+ ? SMP_AUTH_BOND
+ : (SMP_AUTH_BOND | SMP_AUTH_YN_BIT);
btm_ble_link_sec_check(bd_addr, auth_req, &sec_req_act);
if (sec_req_act == BTM_BLE_SEC_REQ_ACT_NONE ||
sec_req_act == BTM_BLE_SEC_REQ_ACT_DISCARD) {
@@ -1860,13 +1870,15 @@
*/
if (p_dev_rec) {
VLOG(1) << __func__ << " Security Manager: handle:" << handle
- << " enc_mode:" << enc_mode << " bda: " << bda
- << " RName: " << p_dev_rec->sec_bd_name;
+ << " enc_mode:" << loghex(enc_mode) << " bda: " << bda
+ << " RName: " << p_dev_rec->sec_bd_name
+ << " p_dev_rec:" << p_dev_rec;
BTM_TRACE_DEBUG("btm_ble_connected sec_flags=0x%x", p_dev_rec->sec_flags);
} else {
VLOG(1) << __func__ << " Security Manager: handle:" << handle
- << " enc_mode:" << enc_mode << " bda: " << bda;
+ << " enc_mode:" << loghex(enc_mode) << " bda: " << bda
+ << " p_dev_rec:" << p_dev_rec;
}
if (!p_dev_rec) {
@@ -1978,7 +1990,7 @@
#endif
} else {
role = HCI_ROLE_UNKNOWN;
- if (status != HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT) {
+ if (status != HCI_ERR_ADVERTISING_TIMEOUT) {
btm_ble_set_conn_st(BLE_CONN_IDLE);
#if (BLE_PRIVACY_SPT == TRUE)
btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);
@@ -1992,6 +2004,9 @@
}
btm_ble_update_mode_operation(role, &bda, status);
+
+ if (role == HCI_ROLE_SLAVE)
+ btm_ble_advertiser_notify_terminated_legacy(status, handle);
}
/*****************************************************************************
@@ -2001,9 +2016,20 @@
*
*****************************************************************************/
void btm_ble_create_ll_conn_complete(uint8_t status) {
- if (status != HCI_SUCCESS) {
- btm_ble_set_conn_st(BLE_CONN_IDLE);
- btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, NULL, status);
+ if (status == HCI_SUCCESS) return;
+
+ btm_ble_set_conn_st(BLE_CONN_IDLE);
+ btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, NULL, status);
+
+ LOG(WARNING) << "LE Create Connection attempt failed, status="
+ << loghex(status);
+
+ if (status == HCI_ERR_COMMAND_DISALLOWED) {
+ /* There is already either direct connect, or whitelist connection
+ * pending, but we don't know which one, or to which state should we
+ * transition now. This can be triggered only in case of rare race
+ * condition. Crash to recover. */
+ LOG(FATAL) << "LE Create Connection - command disallowed";
}
}
/*****************************************************************************
@@ -2174,7 +2200,7 @@
ret = aes_cipher_msg_auth_code(p_rec->ble.keys.lcsrk, p_buf,
(uint16_t)(len + 4), BTM_CMAC_TLEN_SIZE,
p_mac);
- if (ret == true) {
+ if (ret) {
btm_ble_increment_sign_ctr(bd_addr, true);
}
@@ -2329,7 +2355,7 @@
extern uint8_t BTM_BleGetSupportedKeySize(const RawAddress& bd_addr) {
#if (L2CAP_LE_COC_INCLUDED == TRUE)
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
- tBTM_LE_IO_REQ dev_io_cfg;
+ tBTM_LE_EVT_DATA btm_le_evt_data;
uint8_t callback_rc;
if (!p_dev_rec) {
@@ -2344,7 +2370,7 @@
}
callback_rc = (*btm_cb.api.p_le_callback)(
- BTM_LE_IO_REQ_EVT, p_dev_rec->bd_addr, (tBTM_LE_EVT_DATA*)&dev_io_cfg);
+ BTM_LE_IO_REQ_EVT, p_dev_rec->bd_addr, &btm_le_evt_data);
if (callback_rc != BTM_SUCCESS) {
BTM_TRACE_ERROR("%s can't access supported key size", __func__);
@@ -2352,8 +2378,8 @@
}
BTM_TRACE_DEBUG("%s device supports key size = %d", __func__,
- dev_io_cfg.max_key_size);
- return (dev_io_cfg.max_key_size);
+ btm_le_evt_data.io_req.max_key_size);
+ return (btm_le_evt_data.io_req.max_key_size);
#else
return 0;
#endif
@@ -2373,7 +2399,7 @@
*
******************************************************************************/
static void btm_notify_new_key(uint8_t key_type) {
- tBTM_BLE_LOCAL_KEYS* p_locak_keys = NULL;
+ tBTM_BLE_LOCAL_KEYS* p_local_keys = NULL;
BTM_TRACE_DEBUG("btm_notify_new_key key_type=%d", key_type);
@@ -2381,12 +2407,12 @@
switch (key_type) {
case BTM_BLE_KEY_TYPE_ID:
BTM_TRACE_DEBUG("BTM_BLE_KEY_TYPE_ID");
- p_locak_keys = (tBTM_BLE_LOCAL_KEYS*)&btm_cb.devcb.id_keys;
+ p_local_keys = (tBTM_BLE_LOCAL_KEYS*)&btm_cb.devcb.id_keys;
break;
case BTM_BLE_KEY_TYPE_ER:
BTM_TRACE_DEBUG("BTM_BLE_KEY_TYPE_ER");
- p_locak_keys =
+ p_local_keys =
(tBTM_BLE_LOCAL_KEYS*)&btm_cb.devcb.ble_encryption_key_value;
break;
@@ -2394,8 +2420,8 @@
BTM_TRACE_ERROR("unknown key type: %d", key_type);
break;
}
- if (p_locak_keys != NULL)
- (*btm_cb.api.p_le_key_callback)(key_type, p_locak_keys);
+ if (p_local_keys != NULL)
+ (*btm_cb.api.p_le_key_callback)(key_type, p_local_keys);
}
}
diff --git a/stack/btm/btm_ble_addr.cc b/stack/btm/btm_ble_addr.cc
index 5459c53..2d0acc6 100644
--- a/stack/btm/btm_ble_addr.cc
+++ b/stack/btm/btm_ble_addr.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/btm/btm_ble_adv_filter.cc b/stack/btm/btm_ble_adv_filter.cc
index eb3fc4d..1f68fb6 100644
--- a/stack/btm/btm_ble_adv_filter.cc
+++ b/stack/btm/btm_ble_adv_filter.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,9 @@
#include "hcidefs.h"
#include "hcimsgs.h"
+using base::Bind;
+using bluetooth::Uuid;
+
#define BTM_BLE_ADV_FILT_META_HDR_LENGTH 3
#define BTM_BLE_ADV_FILT_FEAT_SELN_LEN 13
#define BTM_BLE_ADV_FILT_TRACK_NUM 2
@@ -73,30 +76,8 @@
#define BTM_BLE_ADV_FILT_CB_EVT_MASK 0xF0
#define BTM_BLE_ADV_FILT_SUBCODE_MASK 0x0F
-/*******************************************************************************
- *
- * Function btm_ble_obtain_vsc_details
- *
- * Description This function obtains the VSC details
- *
- * Parameters
- *
- * Returns status
- *
- ******************************************************************************/
-tBTM_STATUS btm_ble_obtain_vsc_details() {
- tBTM_STATUS st = BTM_SUCCESS;
-
-#if (BLE_VND_INCLUDED == TRUE)
- BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
- if (cmn_ble_vsc_cb.filter_support && 0 == cmn_ble_vsc_cb.max_filter) {
- st = BTM_MODE_UNSUPPORTED;
- return st;
- }
-#else
- cmn_ble_vsc_cb.max_filter = BTM_BLE_MAX_FILTER_COUNTER;
-#endif
- return st;
+bool is_filtering_supported() {
+ return cmn_ble_vsc_cb.filter_support != 0 && cmn_ble_vsc_cb.max_filter != 0;
}
/*******************************************************************************
@@ -457,8 +438,6 @@
tBTM_BLE_PF_COUNT* p_addr_filter = NULL;
uint8_t* p_counter = NULL;
- btm_ble_obtain_vsc_details();
-
if (cond_type > BTM_BLE_PF_TYPE_ALL) {
BTM_TRACE_ERROR("unknown PF filter condition type %d", cond_type);
return BTM_BLE_INVALID_COUNTER;
@@ -520,6 +499,19 @@
UINT8_TO_STREAM(p, filt_index);
if (action != BTM_BLE_SCAN_COND_CLEAR) {
+#if (BLE_PRIVACY_SPT == TRUE)
+ if (addr.type == BLE_ADDR_PUBLIC_ID) {
+ LOG(INFO) << __func__ << " Filter address " << addr.bda
+ << " has type PUBLIC_ID, try to get identity address";
+ /* If no matching identity address is found for the input address,
+ * this call will have no effect. */
+ btm_random_pseudo_to_identity_addr(&addr.bda, &addr.type);
+ }
+#endif
+
+ LOG(INFO) << __func__
+ << " Adding scan filter with peer address: " << addr.bda;
+
BDADDR_TO_STREAM(p, addr.bda);
UINT8_TO_STREAM(p, addr.type);
}
@@ -537,9 +529,10 @@
*/
void BTM_LE_PF_uuid_filter(tBTM_BLE_SCAN_COND_OP action,
tBTM_BLE_PF_FILT_INDEX filt_index,
- tBTM_BLE_PF_COND_TYPE filter_type, tBT_UUID uuid,
+ tBTM_BLE_PF_COND_TYPE filter_type,
+ const bluetooth::Uuid& uuid,
tBTM_BLE_PF_LOGIC_TYPE cond_logic,
- tBTM_BLE_PF_COND_MASK* p_uuid_mask,
+ const bluetooth::Uuid& uuid_mask,
tBTM_BLE_PF_CFG_CBACK cb) {
uint8_t evt_type;
@@ -559,36 +552,39 @@
UINT8_TO_STREAM(p, action);
UINT8_TO_STREAM(p, filt_index);
+ uint8_t uuid_len = uuid.GetShortestRepresentationSize();
if (action != BTM_BLE_SCAN_COND_CLEAR) {
- if (uuid.len == LEN_UUID_16) {
- UINT16_TO_STREAM(p, uuid.uu.uuid16);
- len += LEN_UUID_16;
- } else if (uuid.len == LEN_UUID_32) {
- UINT32_TO_STREAM(p, uuid.uu.uuid32);
- len += LEN_UUID_32;
- } else if (uuid.len == LEN_UUID_128) {
- ARRAY_TO_STREAM(p, uuid.uu.uuid128, LEN_UUID_128);
- len += LEN_UUID_128;
+ if (uuid_len == Uuid::kNumBytes16) {
+ UINT16_TO_STREAM(p, uuid.As16Bit());
+ len += Uuid::kNumBytes16;
+ } else if (uuid_len == Uuid::kNumBytes32) {
+ UINT32_TO_STREAM(p, uuid.As32Bit());
+ len += Uuid::kNumBytes32;
+ } else if (uuid_len == Uuid::kNumBytes128) {
+ const auto& tmp = uuid.To128BitLE();
+ ARRAY_TO_STREAM(p, tmp.data(), (int)Uuid::kNumBytes128);
+ len += Uuid::kNumBytes128;
} else {
- BTM_TRACE_ERROR("illegal UUID length: %d", uuid.len);
+ BTM_TRACE_ERROR("illegal UUID length: %d", uuid_len);
cb.Run(0, BTM_BLE_PF_CONFIG, 1 /*BTA_FAILURE*/);
return;
}
- if (p_uuid_mask) {
- if (uuid.len == LEN_UUID_16) {
- UINT16_TO_STREAM(p, p_uuid_mask->uuid16_mask);
- len += LEN_UUID_16;
- } else if (uuid.len == LEN_UUID_32) {
- UINT32_TO_STREAM(p, p_uuid_mask->uuid32_mask);
- len += LEN_UUID_32;
- } else if (uuid.len == LEN_UUID_128) {
- ARRAY_TO_STREAM(p, p_uuid_mask->uuid128_mask, LEN_UUID_128);
- len += LEN_UUID_128;
+ if (!uuid_mask.IsEmpty()) {
+ if (uuid_len == Uuid::kNumBytes16) {
+ UINT16_TO_STREAM(p, uuid_mask.As16Bit());
+ len += Uuid::kNumBytes16;
+ } else if (uuid_len == Uuid::kNumBytes32) {
+ UINT32_TO_STREAM(p, uuid_mask.As32Bit());
+ len += Uuid::kNumBytes32;
+ } else if (uuid_len == Uuid::kNumBytes128) {
+ const auto& tmp = uuid.To128BitLE();
+ ARRAY_TO_STREAM(p, tmp.data(), (int)Uuid::kNumBytes128);
+ len += Uuid::kNumBytes128;
}
} else {
- memset(p, 0xff, uuid.len);
- len += uuid.len;
+ memset(p, 0xff, uuid_len);
+ len += uuid_len;
}
}
@@ -598,11 +594,83 @@
memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
}
+void DoNothing(uint8_t a, uint8_t b, uint8_t c) {}
+
+void BTM_LE_PF_set(tBTM_BLE_PF_FILT_INDEX filt_index,
+ std::vector<ApcfCommand> commands,
+ tBTM_BLE_PF_CFG_CBACK cb) {
+ if (!is_filtering_supported()) {
+ cb.Run(0, BTM_BLE_PF_ENABLE, 1 /* BTA_FAILURE */);
+ return;
+ }
+
+ int action = BTM_BLE_SCAN_COND_ADD;
+ for (const ApcfCommand& cmd : commands) {
+ /* If data is passed, both mask and data have to be the same length */
+ if (cmd.data.size() != cmd.data_mask.size() && cmd.data.size() != 0 &&
+ cmd.data_mask.size() != 0) {
+ LOG(ERROR) << __func__ << " data(" << cmd.data.size() << ") and mask("
+ << cmd.data_mask.size() << ") are of different size";
+ continue;
+ }
+
+ switch (cmd.type) {
+ case BTM_BLE_PF_ADDR_FILTER: {
+ tBLE_BD_ADDR target_addr;
+ target_addr.bda = cmd.address;
+ target_addr.type = cmd.addr_type;
+
+ BTM_LE_PF_addr_filter(action, filt_index, target_addr, Bind(DoNothing));
+ break;
+ }
+
+ case BTM_BLE_PF_SRVC_DATA:
+ BTM_LE_PF_srvc_data(action, filt_index);
+ break;
+
+ case BTM_BLE_PF_SRVC_UUID:
+ case BTM_BLE_PF_SRVC_SOL_UUID: {
+ BTM_LE_PF_uuid_filter(action, filt_index, cmd.type, cmd.uuid,
+ BTM_BLE_PF_LOGIC_AND, cmd.uuid_mask,
+ Bind(DoNothing));
+ break;
+ }
+
+ case BTM_BLE_PF_LOCAL_NAME: {
+ BTM_LE_PF_local_name(action, filt_index, cmd.name, Bind(DoNothing));
+ break;
+ }
+
+ case BTM_BLE_PF_MANU_DATA: {
+ BTM_LE_PF_manu_data(action, filt_index, cmd.company, cmd.company_mask,
+ cmd.data, cmd.data_mask, Bind(DoNothing));
+ break;
+ }
+
+ case BTM_BLE_PF_SRVC_DATA_PATTERN: {
+ BTM_LE_PF_srvc_data_pattern(action, filt_index, cmd.data, cmd.data_mask,
+ Bind(DoNothing));
+ break;
+ }
+
+ default:
+ LOG(ERROR) << __func__ << ": Unknown filter type: " << +cmd.type;
+ break;
+ }
+ }
+ cb.Run(0, 0, 0);
+}
+
/**
* all adv payload filter by de-selecting all the adv pf feature bits
*/
void BTM_LE_PF_clear(tBTM_BLE_PF_FILT_INDEX filt_index,
tBTM_BLE_PF_CFG_CBACK cb) {
+ if (!is_filtering_supported()) {
+ cb.Run(0, BTM_BLE_PF_ENABLE, 1 /* BTA_FAILURE */);
+ return;
+ }
+
/* clear the general filter entry */
{
tBTM_BLE_PF_CFG_CBACK fDoNothing;
@@ -619,10 +687,12 @@
/* clear UUID filter */
BTM_LE_PF_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index,
- BTM_BLE_PF_SRVC_UUID, {}, 0, nullptr, fDoNothing);
+ BTM_BLE_PF_SRVC_UUID, {}, 0, Uuid::kEmpty,
+ fDoNothing);
BTM_LE_PF_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index,
- BTM_BLE_PF_SRVC_SOL_UUID, {}, 0, nullptr, fDoNothing);
+ BTM_BLE_PF_SRVC_SOL_UUID, {}, 0, Uuid::kEmpty,
+ fDoNothing);
/* clear service data filter */
BTM_LE_PF_srvc_data_pattern(BTM_BLE_SCAN_COND_CLEAR, filt_index, {}, {},
@@ -673,7 +743,7 @@
BTM_BLE_ADV_FILT_FEAT_SELN_LEN + BTM_BLE_ADV_FILT_TRACK_NUM;
uint8_t param[len], *p;
- if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) {
+ if (!is_filtering_supported()) {
cb.Run(0, BTM_BLE_PF_ENABLE, 1 /* BTA_FAILURE */);
return;
}
@@ -791,7 +861,7 @@
******************************************************************************/
void BTM_BleEnableDisableFilterFeature(uint8_t enable,
tBTM_BLE_PF_STATUS_CBACK p_stat_cback) {
- if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) {
+ if (!is_filtering_supported()) {
if (p_stat_cback) p_stat_cback.Run(BTM_BLE_PF_ENABLE, 1 /* BTA_FAILURE */);
return;
}
@@ -821,7 +891,10 @@
******************************************************************************/
void btm_ble_adv_filter_init(void) {
memset(&btm_ble_adv_filt_cb, 0, sizeof(tBTM_BLE_ADV_FILTER_CB));
- if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) return;
+
+ BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
+
+ if (!is_filtering_supported()) return;
if (cmn_ble_vsc_cb.max_filter > 0) {
btm_ble_adv_filt_cb.p_addr_filter_count = (tBTM_BLE_PF_COUNT*)osi_malloc(
diff --git a/stack/btm/btm_ble_batchscan.cc b/stack/btm/btm_ble_batchscan.cc
index a0b159c..89b3e6c 100644
--- a/stack/btm/btm_ble_batchscan.cc
+++ b/stack/btm/btm_ble_batchscan.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -496,8 +496,8 @@
/* Check only for modes, as scan reports can be called after disabling batch
* scan */
- if (read_scan_mode < 0 || (scan_mode != BTM_BLE_BATCH_SCAN_MODE_PASS &&
- scan_mode != BTM_BLE_BATCH_SCAN_MODE_ACTI)) {
+ if (scan_mode != BTM_BLE_BATCH_SCAN_MODE_PASS &&
+ scan_mode != BTM_BLE_BATCH_SCAN_MODE_ACTI) {
BTM_TRACE_ERROR("Illegal read scan params: %d, %d, %d", read_scan_mode,
scan_mode, ble_batchscan_cb.cur_state);
cb.Run(BTM_ILLEGAL_VALUE, 0, 0, {});
diff --git a/stack/btm/btm_ble_bgconn.cc b/stack/btm/btm_ble_bgconn.cc
index f2f8307..952e953 100644
--- a/stack/btm/btm_ble_bgconn.cc
+++ b/stack/btm/btm_ble_bgconn.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -344,6 +344,21 @@
BTM_TRACE_EVENT("%s status=%d", __func__, *p);
}
+void btm_ble_create_conn_cancel_complete(uint8_t* p) {
+ uint8_t status;
+ STREAM_TO_UINT8(status, p);
+
+ if (status == HCI_ERR_COMMAND_DISALLOWED) {
+ /* This is a sign that logic around keeping connection state is broken */
+ LOG(ERROR)
+ << "Attempt to cancel LE connection, when no connection is pending.";
+ if (btm_ble_get_conn_st() == BLE_CONN_CANCEL) {
+ btm_ble_set_conn_st(BLE_CONN_IDLE);
+ btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, nullptr, status);
+ }
+ }
+}
+
void btm_send_hci_create_connection(
uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy,
uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own,
diff --git a/stack/btm/btm_ble_cont_energy.cc b/stack/btm/btm_ble_cont_energy.cc
index 61c5327..4e87308 100644
--- a/stack/btm/btm_ble_cont_energy.cc
+++ b/stack/btm/btm_ble_cont_energy.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/btm/btm_ble_gap.cc b/stack/btm/btm_ble_gap.cc
index 341d85d..1f8263f 100644
--- a/stack/btm/btm_ble_gap.cc
+++ b/stack/btm/btm_ble_gap.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2014 Broadcom Corporation
+ * Copyright 2008-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -435,7 +435,7 @@
? BTM_BLE_SCAN_MODE_ACTI
: p_inq->scan_type;
/* assume observe always not using white list */
-#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == true)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
/* enable resolving list */
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
#endif
@@ -485,37 +485,38 @@
BTM_TRACE_DEBUG("%s", __func__);
/* Check status of command complete event */
- if ((p_vcs_cplt_params->opcode == HCI_BLE_VENDOR_CAP_OCF) &&
- (p_vcs_cplt_params->param_len > 0)) {
- p = p_vcs_cplt_params->p_param_buf;
- STREAM_TO_UINT8(status, p);
+ CHECK(p_vcs_cplt_params->opcode == HCI_BLE_VENDOR_CAP_OCF);
+ CHECK(p_vcs_cplt_params->param_len > 0);
+
+ p = p_vcs_cplt_params->p_param_buf;
+ STREAM_TO_UINT8(status, p);
+
+ if (status != HCI_SUCCESS) {
+ BTM_TRACE_DEBUG("%s: Status = 0x%02x (0 is success)", __func__, status);
+ return;
+ }
+ STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.adv_inst_max, p);
+ STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.rpa_offloading, p);
+ STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg, p);
+ STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz, p);
+ STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.filter_support, p);
+ STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_filter, p);
+ STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.energy_support, p);
+
+ if (p_vcs_cplt_params->param_len >
+ BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE) {
+ STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.version_supported, p);
+ } else {
+ btm_cb.cmn_ble_vsc_cb.version_supported = BTM_VSC_CHIP_CAPABILITY_L_VERSION;
}
- if (status == HCI_SUCCESS) {
- STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.adv_inst_max, p);
- STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.rpa_offloading, p);
- STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg, p);
- STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz, p);
- STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.filter_support, p);
- STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_filter, p);
- STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.energy_support, p);
-
- if (p_vcs_cplt_params->param_len >
- BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE) {
- STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.version_supported, p);
- } else {
- btm_cb.cmn_ble_vsc_cb.version_supported =
- BTM_VSC_CHIP_CAPABILITY_L_VERSION;
- }
-
- if (btm_cb.cmn_ble_vsc_cb.version_supported >=
- BTM_VSC_CHIP_CAPABILITY_M_VERSION) {
- STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.total_trackable_advertisers, p);
- STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
- STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
- }
- btm_cb.cmn_ble_vsc_cb.values_read = true;
+ if (btm_cb.cmn_ble_vsc_cb.version_supported >=
+ BTM_VSC_CHIP_CAPABILITY_M_VERSION) {
+ STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.total_trackable_advertisers, p);
+ STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
+ STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
}
+ btm_cb.cmn_ble_vsc_cb.values_read = true;
BTM_TRACE_DEBUG(
"%s: stat=%d, irk=%d, ADV ins:%d, rpa=%d, ener=%d, ext_scan=%d", __func__,
@@ -576,7 +577,7 @@
#if (BLE_VND_INCLUDED == TRUE)
extern void BTM_BleReadControllerFeatures(
tBTM_BLE_CTRL_FEATURES_CBACK* p_vsc_cback) {
- if (true == btm_cb.cmn_ble_vsc_cb.values_read) return;
+ if (btm_cb.cmn_ble_vsc_cb.values_read) return;
BTM_TRACE_DEBUG("BTM_BleReadControllerFeatures");
@@ -630,7 +631,8 @@
/* if LE is not supported, return error */
if (!controller_get_interface()->supports_ble()) return false;
- uint8_t addr_resolution = 0;
+ tGAP_BLE_ATTR_VALUE gap_ble_attr_value;
+ gap_ble_attr_value.addr_resolution = 0;
if (!privacy_mode) /* if privacy disabled, always use public address */
{
p_cb->addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
@@ -645,7 +647,7 @@
/* 4.2 controller only allow privacy 1.2 or mixed mode, resolvable private
* address in controller */
if (controller_get_interface()->supports_ble_privacy()) {
- addr_resolution = 1;
+ gap_ble_attr_value.addr_resolution = 1;
/* check vendor specific capability */
p_cb->privacy_mode =
btm_cb.ble_ctr_cb.mixed_mode ? BTM_PRIVACY_MIXED : BTM_PRIVACY_1_2;
@@ -653,8 +655,7 @@
p_cb->privacy_mode = BTM_PRIVACY_1_1;
}
- GAP_BleAttrDBUpdate(GATT_UUID_GAP_CENTRAL_ADDR_RESOL,
- (tGAP_BLE_ATTR_VALUE*)&addr_resolution);
+ GAP_BleAttrDBUpdate(GATT_UUID_GAP_CENTRAL_ADDR_RESOL, &gap_ble_attr_value);
return true;
#else
@@ -722,6 +723,7 @@
*
******************************************************************************/
void BTM_BleClearBgConnDev(void) {
+ if (!controller_get_interface()->supports_ble()) return;
btm_ble_start_auto_conn(false);
btm_ble_clear_white_list();
gatt_reset_bgdev_list();
@@ -1841,10 +1843,10 @@
}
}
-void btm_ble_process_adv_addr(RawAddress& bda, uint8_t addr_type) {
+void btm_ble_process_adv_addr(RawAddress& bda, uint8_t* addr_type) {
#if (BLE_PRIVACY_SPT == TRUE)
/* map address to security record */
- bool match = btm_identity_addr_to_random_pseudo(&bda, &addr_type, false);
+ bool match = btm_identity_addr_to_random_pseudo(&bda, addr_type, false);
VLOG(1) << __func__ << ": bda=" << bda;
/* always do RRA resolution on host */
@@ -1909,13 +1911,20 @@
uint8_t* pkt_data = p;
p += pkt_data_len; /* Advance to the the next packet*/
-
- if (rssi >= 21 && rssi <= 126) {
- BTM_TRACE_ERROR("%s: bad rssi value in advertising report: ", __func__,
- pkt_data_len, rssi);
+ if (p > data + data_len) {
+ LOG(ERROR) << "Invalid pkt_data_len: " << +pkt_data_len;
+ return;
}
- btm_ble_process_adv_addr(bda, addr_type);
+ if (rssi >= 21 && rssi <= 126) {
+ BTM_TRACE_ERROR("%s: bad rssi value in advertising report: %d", __func__,
+ rssi);
+ }
+
+ if (addr_type != BLE_ADDR_ANONYMOUS) {
+ btm_ble_process_adv_addr(bda, &addr_type);
+ }
+
btm_ble_process_adv_pkt_cont(event_type, addr_type, bda, primary_phy,
secondary_phy, advertising_sid, tx_power, rssi,
periodic_adv_int, pkt_data_len, pkt_data);
@@ -1954,6 +1963,10 @@
uint8_t* pkt_data = p;
p += pkt_data_len; /* Advance to the the rssi byte */
+ if (p > data + data_len - sizeof(rssi)) {
+ LOG(ERROR) << "Invalid pkt_data_len: " << +pkt_data_len;
+ return;
+ }
STREAM_TO_INT8(rssi, p);
@@ -1962,7 +1975,7 @@
pkt_data_len, rssi);
}
- btm_ble_process_adv_addr(bda, addr_type);
+ btm_ble_process_adv_addr(bda, &addr_type);
uint16_t event_type;
if (legacy_evt_type == 0x00) { // ADV_IND;
@@ -2013,7 +2026,8 @@
bool is_start =
ble_evt_type_is_legacy(evt_type) && is_scannable && !is_scan_resp;
- if (is_start) AdvertiseDataParser::RemoveTrailingZeros(tmp);
+ if (ble_evt_type_is_legacy(evt_type))
+ AdvertiseDataParser::RemoveTrailingZeros(tmp);
// We might have send scan request to this device before, but didn't get the
// response. In such case make sure data is put at start, not appended to
@@ -2140,17 +2154,7 @@
STREAM_TO_UINT8(tx_phy, p);
STREAM_TO_UINT8(rx_phy, p);
- tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle);
- if (!p_dev_rec) {
- BTM_TRACE_WARNING("%s: No Device Found!", __func__);
- return;
- }
-
- tGATT_TCB* p_tcb =
- gatt_find_tcb_by_addr(p_dev_rec->ble.pseudo_addr, BT_TRANSPORT_LE);
- if (p_tcb == NULL) return;
-
- gatt_notify_phy_updated(p_tcb, tx_phy, rx_phy, status);
+ gatt_notify_phy_updated(status, handle, tx_phy, rx_phy);
}
/*******************************************************************************
@@ -2257,8 +2261,7 @@
if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) btm_ble_stop_scan();
- if (p_obs_cb)
- (p_obs_cb)((tBTM_INQUIRY_CMPL*)&btm_cb.btm_inq_vars.inq_cmpl_info);
+ if (p_obs_cb) (p_obs_cb)(&btm_cb.btm_inq_vars.inq_cmpl_info);
}
/*******************************************************************************
*
@@ -2564,7 +2567,7 @@
******************************************************************************/
void btm_ble_update_mode_operation(uint8_t link_role, const RawAddress* bd_addr,
uint8_t status) {
- if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT) {
+ if (status == HCI_ERR_ADVERTISING_TIMEOUT) {
btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
/* make device fall back into undirected adv mode by default */
btm_cb.ble_ctr_cb.inq_var.directed_conn = BTM_BLE_CONNECT_EVT;
@@ -2579,7 +2582,7 @@
/* in case of disconnected, we must cancel bgconn and restart
in order to add back device to white list in order to reconnect */
- btm_ble_bgconn_cancel_if_disconnected(*bd_addr);
+ if (bd_addr) btm_ble_bgconn_cancel_if_disconnected(*bd_addr);
/* when no connection is attempted, and controller is not rejecting last
request
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 895d6ba..d4cb411 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/btm/btm_ble_int_types.h b/stack/btm/btm_ble_int_types.h
index b539211..2167f2f 100644
--- a/stack/btm/btm_ble_int_types.h
+++ b/stack/btm/btm_ble_int_types.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/btm/btm_ble_multi_adv.cc b/stack/btm/btm_ble_multi_adv.cc
index 99b8cb5..60490fb 100644
--- a/stack/btm/btm_ble_multi_adv.cc
+++ b/stack/btm/btm_ble_multi_adv.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
- * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2017 The Android Open Source Project
+ * Copyright 2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,9 @@
******************************************************************************/
#include <base/bind.h>
+#include <base/location.h>
#include <base/logging.h>
+#include <base/memory/weak_ptr.h>
#include <base/strings/string_number_conversions.h>
#include <base/time/time.h>
#include <string.h>
@@ -101,7 +103,11 @@
~AdvertisingInstance() {
alarm_free(adv_raddr_timer);
- if (timeout_timer) alarm_free(timeout_timer);
+ adv_raddr_timer = nullptr;
+ if (timeout_timer) {
+ alarm_free(timeout_timer);
+ timeout_timer = nullptr;
+ }
}
};
@@ -138,7 +144,7 @@
/* a temporary type for holding all the data needed in callbacks below*/
struct CreatorParams {
uint8_t inst_id;
- BleAdvertisingManagerImpl* self;
+ base::WeakPtr<BleAdvertisingManagerImpl> self;
IdTxPowerStatusCb cb;
tBTM_BLE_ADV_PARAMS params;
std::vector<uint8_t> advertise_data;
@@ -152,15 +158,18 @@
using c_type = std::unique_ptr<CreatorParams>;
+BleAdvertisingManager* instance;
+base::WeakPtr<BleAdvertisingManagerImpl> instance_weakptr;
+
class BleAdvertisingManagerImpl
: public BleAdvertisingManager,
public BleAdvertiserHciInterface::AdvertisingEventObserver {
public:
- BleAdvertisingManagerImpl(BleAdvertiserHciInterface* interface) {
- this->hci_interface = interface;
+ BleAdvertisingManagerImpl(BleAdvertiserHciInterface* interface)
+ : hci_interface(interface), weak_factory_(this) {
hci_interface->ReadInstanceCount(
base::Bind(&BleAdvertisingManagerImpl::ReadInstanceCountCb,
- base::Unretained(this)));
+ weak_factory_.GetWeakPtr()));
}
~BleAdvertisingManagerImpl() { adv_inst.clear(); }
@@ -209,7 +218,7 @@
void GenerateRpa(base::Callback<void(RawAddress)> cb) {
btm_gen_resolvable_private_addr(
Bind(&BleAdvertisingManagerImpl::OnRpaGenerationComplete,
- base::Unretained(this), std::move(cb)));
+ weak_factory_.GetWeakPtr(), std::move(cb)));
}
void ConfigureRpa(AdvertisingInstance* p_inst, MultiAdvCb configuredCb) {
@@ -231,9 +240,8 @@
/* Connectable advertising set must be disabled when updating RPA */
bool restart = p_inst->IsEnabled() && p_inst->IsConnectable();
- auto hci_interface =
- ((BleAdvertisingManagerImpl*)BleAdvertisingManager::Get())
- ->GetHciInterface();
+ if (!instance_weakptr.get()) return;
+ auto hci_interface = instance_weakptr.get()->GetHciInterface();
if (restart) {
p_inst->enable_status = false;
@@ -243,7 +251,7 @@
/* set it to controller */
hci_interface->SetRandomAddress(
- p_inst->inst_id, p_inst->own_address,
+ p_inst->inst_id, bda,
Bind(
[](AdvertisingInstance* p_inst, RawAddress bda,
MultiAdvCb configuredCb, uint8_t status) {
@@ -307,7 +315,7 @@
/* a temporary type for holding all the data needed in callbacks below*/
struct CreatorParams {
uint8_t inst_id;
- BleAdvertisingManagerImpl* self;
+ base::WeakPtr<BleAdvertisingManagerImpl> self;
MultiAdvCb cb;
tBTM_BLE_ADV_PARAMS params;
std::vector<uint8_t> advertise_data;
@@ -319,7 +327,7 @@
std::unique_ptr<CreatorParams> c;
c.reset(new CreatorParams());
- c->self = this;
+ c->self = weak_factory_.GetWeakPtr();
c->cb = std::move(cb);
c->params = *params;
c->advertise_data = std::move(advertise_data);
@@ -335,7 +343,12 @@
// clang-format off
c->self->SetParameters(c->inst_id, &c->params, Bind(
[](c_type c, uint8_t status, int8_t tx_power) {
- if (status != 0) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
+ if (status) {
LOG(ERROR) << "setting parameters failed, status: " << +status;
c->cb.Run(status);
return;
@@ -346,6 +359,11 @@
const RawAddress& rpa = c->self->adv_inst[c->inst_id].own_address;
c->self->GetHciInterface()->SetRandomAddress(c->inst_id, rpa, Bind(
[](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
LOG(ERROR) << "setting random address failed, status: " << +status;
c->cb.Run(status);
@@ -354,6 +372,11 @@
c->self->SetData(c->inst_id, false, std::move(c->advertise_data), Bind(
[](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
LOG(ERROR) << "setting advertise data failed, status: " << +status;
c->cb.Run(status);
@@ -362,6 +385,11 @@
c->self->SetData(c->inst_id, true, std::move(c->scan_response_data), Bind(
[](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
LOG(ERROR) << "setting scan response data failed, status: " << +status;
c->cb.Run(status);
@@ -387,7 +415,7 @@
std::unique_ptr<CreatorParams> c;
c.reset(new CreatorParams());
- c->self = this;
+ c->self = weak_factory_.GetWeakPtr();
c->cb = std::move(cb);
c->params = *params;
c->advertise_data = std::move(advertise_data);
@@ -403,8 +431,13 @@
// clang-format off
c->self->RegisterAdvertiser(Bind(
[](c_type c, uint8_t advertiser_id, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
- LOG(ERROR) << "registering advertiser failed, status: " << +status;
+ LOG(ERROR) << " failed, status: " << +status;
c->cb.Run(0, 0, status);
return;
}
@@ -413,6 +446,11 @@
c->self->SetParameters(c->inst_id, &c->params, Bind(
[](c_type c, uint8_t status, int8_t tx_power) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
c->self->Unregister(c->inst_id);
LOG(ERROR) << "setting parameters failed, status: " << +status;
@@ -422,9 +460,20 @@
c->self->adv_inst[c->inst_id].tx_power = tx_power;
+ if (c->self->adv_inst[c->inst_id].own_address_type == BLE_ADDR_PUBLIC) {
+ c->self->StartAdvertisingSetAfterAddressPart(std::move(c));
+ return;
+ }
+
+ //own_address_type == BLE_ADDR_RANDOM
const RawAddress& rpa = c->self->adv_inst[c->inst_id].own_address;
c->self->GetHciInterface()->SetRandomAddress(c->inst_id, rpa, Bind(
[](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
c->self->Unregister(c->inst_id);
LOG(ERROR) << "setting random address failed, status: " << +status;
@@ -432,35 +481,59 @@
return;
}
- c->self->SetData(c->inst_id, false, std::move(c->advertise_data), Bind(
- [](c_type c, uint8_t status) {
- if (status != 0) {
- c->self->Unregister(c->inst_id);
- LOG(ERROR) << "setting advertise data failed, status: " << +status;
- c->cb.Run(0, 0, status);
- return;
- }
+ c->self->StartAdvertisingSetAfterAddressPart(std::move(c));
+ }, base::Passed(&c)));
+ }, base::Passed(&c)));
+ }, base::Passed(&c)));
+ // clang-format on
+ }
- c->self->SetData(c->inst_id, true, std::move(c->scan_response_data), Bind(
+ void StartAdvertisingSetAfterAddressPart(c_type c) {
+ c->self->SetData(
+ c->inst_id, false, std::move(c->advertise_data),
+ Bind(
+ [](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
+ if (status != 0) {
+ c->self->Unregister(c->inst_id);
+ LOG(ERROR) << "setting advertise data failed, status: "
+ << +status;
+ c->cb.Run(0, 0, status);
+ return;
+ }
+
+ c->self->SetData(
+ c->inst_id, true, std::move(c->scan_response_data),
+ Bind(
[](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
c->self->Unregister(c->inst_id);
- LOG(ERROR) << "setting scan response data failed, status: " << +status;
+ LOG(ERROR)
+ << "setting scan response data failed, status: "
+ << +status;
c->cb.Run(0, 0, status);
return;
}
if (c->periodic_params.enable) {
- c->self->StartAdvertisingSetPeriodicPart(std::move(c));
+ c->self->StartAdvertisingSetPeriodicPart(
+ std::move(c));
} else {
c->self->StartAdvertisingSetFinish(std::move(c));
}
- }, base::Passed(&c)));
- }, base::Passed(&c)));
- }, base::Passed(&c)));
- }, base::Passed(&c)));
- }, base::Passed(&c)));
- // clang-format on
+ },
+ base::Passed(&c)));
+ },
+ base::Passed(&c)));
}
void StartAdvertisingSetPeriodicPart(c_type c) {
@@ -469,6 +542,11 @@
// clang-format off
c->self->SetPeriodicAdvertisingParameters(c->inst_id, &c->periodic_params, Bind(
[](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
c->self->Unregister(c->inst_id);
LOG(ERROR) << "setting periodic parameters failed, status: " << +status;
@@ -478,6 +556,11 @@
c->self->SetPeriodicAdvertisingData(c->inst_id, std::move(c->periodic_data), Bind(
[](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
c->self->Unregister(c->inst_id);
LOG(ERROR) << "setting periodic parameters failed, status: " << +status;
@@ -487,6 +570,11 @@
c->self->SetPeriodicAdvertisingEnable(c->inst_id, true, Bind(
[](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
c->self->Unregister(c->inst_id);
LOG(ERROR) << "enabling periodic advertising failed, status: " << +status;
@@ -507,9 +595,14 @@
uint16_t duration = c->duration;
uint8_t maxExtAdvEvents = c->maxExtAdvEvents;
RegisterCb timeout_cb = std::move(c->timeout_cb);
- BleAdvertisingManagerImpl* self = c->self;
+ base::WeakPtr<BleAdvertisingManagerImpl> self = c->self;
MultiAdvCb enable_cb = Bind(
[](c_type c, uint8_t status) {
+ if (!c->self) {
+ LOG(INFO) << "Stack was shut down";
+ return;
+ }
+
if (status != 0) {
c->self->Unregister(c->inst_id);
LOG(ERROR) << "enabling advertiser failed, status: " << +status;
@@ -535,9 +628,9 @@
p_inst->timeout_timer = alarm_new("btm_ble.adv_timeout");
- base::Closure cb = Bind(&BleAdvertisingManagerImpl::Enable,
- base::Unretained(this), inst_id, 0 /* disable */,
- std::move(timeout_cb), 0, 0, base::Bind(DoNothing));
+ base::Closure cb = Bind(
+ &BleAdvertisingManagerImpl::Enable, weak_factory_.GetWeakPtr(), inst_id,
+ 0 /* disable */, std::move(timeout_cb), 0, 0, base::Bind(DoNothing));
// schedule disable when the timeout passes
alarm_set_closure(FROM_HERE, p_inst->timeout_timer, duration * 10,
@@ -570,8 +663,8 @@
if (enable && p_inst->address_update_required) {
p_inst->address_update_required = false;
ConfigureRpa(p_inst, base::Bind(&BleAdvertisingManagerImpl::EnableFinish,
- base::Unretained(this), p_inst, enable,
- std::move(cb)));
+ weak_factory_.GetWeakPtr(), p_inst,
+ enable, std::move(cb)));
return;
}
@@ -585,7 +678,7 @@
// TODO(jpawlowski): HCI implementation that can't do duration should
// emulate it, not EnableWithTimerCb.
myCb = Bind(&BleAdvertisingManagerImpl::EnableWithTimerCb,
- base::Unretained(this), p_inst->inst_id, std::move(cb),
+ weak_factory_.GetWeakPtr(), p_inst->inst_id, std::move(cb),
p_inst->duration, p_inst->timeout_cb);
} else {
myCb = std::move(cb);
@@ -683,7 +776,7 @@
DivideAndSendData(
inst_id, data, cb,
base::Bind(&BleAdvertisingManagerImpl::SetDataAdvDataSender,
- base::Unretained(this), is_scan_rsp));
+ weak_factory_.GetWeakPtr(), is_scan_rsp));
}
void SetDataAdvDataSender(uint8_t is_scan_rsp, uint8_t inst_id,
@@ -872,11 +965,12 @@
uint8_t status, uint8_t advertising_handle, uint16_t connection_handle,
uint8_t num_completed_extended_adv_events) override {
AdvertisingInstance* p_inst = &adv_inst[advertising_handle];
- VLOG(1) << __func__ << "status: 0x" << std::hex << +status
- << ", advertising_handle: 0x" << std::hex << +advertising_handle
- << ", connection_handle: 0x" << std::hex << +connection_handle;
+ VLOG(1) << __func__ << "status: " << loghex(status)
+ << ", advertising_handle: " << loghex(advertising_handle)
+ << ", connection_handle: " << loghex(connection_handle);
- if (status == 0x43 || status == 0x3C) {
+ if (status == HCI_ERR_LIMIT_REACHED ||
+ status == HCI_ERR_ADVERTISING_TIMEOUT) {
// either duration elapsed, or maxExtAdvEvents reached
p_inst->enable_status = false;
@@ -896,7 +990,7 @@
VLOG(1) << "reneabling advertising";
- if (p_inst->in_use == true) {
+ if (p_inst->in_use) {
// TODO(jpawlowski): we don't really allow to do directed advertising
// right now. This should probably be removed, check with Andre.
if ((p_inst->advertising_event_properties & 0x0C) == 0) {
@@ -915,34 +1009,55 @@
}
}
+ base::WeakPtr<BleAdvertisingManagerImpl> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
+ void CancelAdvAlarms() {
+ AdvertisingInstance* p_inst = &adv_inst[0];
+ for (uint8_t i = 0; i < inst_count; i++, p_inst++) {
+ if (p_inst->timeout_timer) {
+ alarm_cancel(p_inst->timeout_timer);
+ }
+ if (p_inst->adv_raddr_timer) {
+ alarm_cancel(p_inst->adv_raddr_timer);
+ }
+ }
+ }
+
private:
BleAdvertiserHciInterface* GetHciInterface() { return hci_interface; }
BleAdvertiserHciInterface* hci_interface = nullptr;
std::vector<AdvertisingInstance> adv_inst;
uint8_t inst_count;
+
+ // Member variables should appear before the WeakPtrFactory, to ensure
+ // that any WeakPtrs are invalidated before its members
+ // variable's destructors are executed, rendering them invalid.
+ base::WeakPtrFactory<BleAdvertisingManagerImpl> weak_factory_;
};
-BleAdvertisingManager* instance;
-
void btm_ble_adv_raddr_timer_timeout(void* data) {
- ((BleAdvertisingManagerImpl*)BleAdvertisingManager::Get())
- ->ConfigureRpa((AdvertisingInstance*)data, base::Bind(DoNothing));
+ BleAdvertisingManagerImpl* ptr = instance_weakptr.get();
+ if (ptr) ptr->ConfigureRpa((AdvertisingInstance*)data, base::Bind(DoNothing));
}
} // namespace
void BleAdvertisingManager::Initialize(BleAdvertiserHciInterface* interface) {
instance = new BleAdvertisingManagerImpl(interface);
+ instance_weakptr = ((BleAdvertisingManagerImpl*)instance)->GetWeakPtr();
}
bool BleAdvertisingManager::IsInitialized() { return instance; }
-BleAdvertisingManager* BleAdvertisingManager::Get() {
- CHECK(instance);
- return instance;
+base::WeakPtr<BleAdvertisingManager> BleAdvertisingManager::Get() {
+ return instance_weakptr;
};
void BleAdvertisingManager::CleanUp() {
+ if (instance_weakptr.get()) instance_weakptr.get()->CancelAdvAlarms();
+
delete instance;
instance = nullptr;
};
@@ -954,11 +1069,11 @@
BleAdvertiserHciInterface::Initialize();
BleAdvertisingManager::Initialize(BleAdvertiserHciInterface::Get());
BleAdvertiserHciInterface::Get()->SetAdvertisingEventObserver(
- (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get());
+ (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get().get());
if (BleAdvertiserHciInterface::Get()->QuirkAdvertiserZeroHandle()) {
// If handle 0 can't be used, register advertiser for it, but never use it.
- BleAdvertisingManager::Get()->RegisterAdvertiser(Bind(DoNothing2));
+ BleAdvertisingManager::Get().get()->RegisterAdvertiser(Bind(DoNothing2));
}
}
@@ -985,7 +1100,7 @@
// verify that if duration passed, or is about to pass, recomputation will shut
// down the advertiser completly
void testRecomputeTimeout1() {
- auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get();
+ auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get().get();
TimeTicks start = TimeTicks::Now();
TimeTicks end = start + TimeDelta::FromMilliseconds(111);
@@ -997,15 +1112,15 @@
manager->RecomputeTimeout(&test1, end);
- CHECK(timeout_triggered == true);
+ CHECK(timeout_triggered);
timeout_triggered = false;
- CHECK(test1.enable_status == false);
+ CHECK(!test1.enable_status);
}
// verify that duration and maxExtAdvEvents are properly adjusted when
// recomputing.
void testRecomputeTimeout2() {
- auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get();
+ auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get().get();
TimeTicks start = TimeTicks::Now();
TimeTicks end = start + TimeDelta::FromMilliseconds(250);
@@ -1019,8 +1134,8 @@
manager->RecomputeTimeout(&test1, end);
- CHECK(timeout_triggered == false);
- CHECK(test1.enable_status == true);
+ CHECK(!timeout_triggered);
+ CHECK(test1.enable_status);
CHECK(test1.duration == 25);
CHECK(test1.maxExtAdvEvents == 25);
}
@@ -1028,7 +1143,7 @@
// verify that if maxExtAdvEvents were sent, or are close to end, recomputation
// wil shut down the advertiser completly
void testRecomputeTimeout3() {
- auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get();
+ auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get().get();
TimeTicks start = TimeTicks::Now();
TimeTicks end = start + TimeDelta::FromMilliseconds(495);
@@ -1041,7 +1156,7 @@
manager->RecomputeTimeout(&test1, end);
- CHECK(timeout_triggered == true);
+ CHECK(timeout_triggered);
timeout_triggered = false;
- CHECK(test1.enable_status == false);
+ CHECK(!test1.enable_status);
}
diff --git a/stack/btm/btm_ble_privacy.cc b/stack/btm/btm_ble_privacy.cc
index f1aa509..3845ba6 100644
--- a/stack/btm/btm_ble_privacy.cc
+++ b/stack/btm/btm_ble_privacy.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -681,85 +681,97 @@
*
******************************************************************************/
bool btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC* p_dev_rec) {
- bool rt = false;
- uint8_t rl_mask = btm_cb.ble_ctr_cb.rl_state;
+ const uint8_t rl_state = btm_cb.ble_ctr_cb.rl_state;
- BTM_TRACE_DEBUG("%s btm_cb.ble_ctr_cb.privacy_mode = %d", __func__,
- btm_cb.ble_ctr_cb.privacy_mode);
-
- /* if controller does not support RPA offloading or privacy 1.2, skip */
- if (controller_get_interface()->get_ble_resolving_list_max_size() == 0)
+ if (controller_get_interface()->get_ble_resolving_list_max_size() == 0) {
+ BTM_TRACE_DEBUG(
+ "%s: Controller does not support RPA offloading or privacy 1.2",
+ __func__);
return false;
+ }
- BTM_TRACE_DEBUG("%s btm_cb.ble_ctr_cb.privacy_mode = %d", __func__,
+ BTM_TRACE_DEBUG("%s: btm_cb.ble_ctr_cb.privacy_mode = %d", __func__,
btm_cb.ble_ctr_cb.privacy_mode);
+ if (!p_dev_rec) {
+ BTM_TRACE_DEBUG("%s: No device security record", __func__);
+ return false;
+ }
+
/* only add RPA enabled device into resolving list */
- if (p_dev_rec != NULL && /* RPA is being used and PID is known */
- ((p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0 ||
- (p_dev_rec->ble.key_type & BTM_LE_KEY_LID) != 0)) {
- if (!(p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
- btm_ble_brcm_find_resolving_pending_entry(
- p_dev_rec->bd_addr, BTM_BLE_META_ADD_IRK_ENTRY) == false) {
- if (btm_cb.ble_ctr_cb.resolving_list_avail_size > 0) {
- if (rl_mask) {
- if (!btm_ble_disable_resolving_list(rl_mask, false)) return false;
- }
+ if (controller_get_interface()->supports_ble_privacy()) {
+ if ((p_dev_rec->ble.key_type & (BTM_LE_KEY_PID | BTM_LE_KEY_LID)) == 0) {
+ BTM_TRACE_DEBUG("%s: privacy 1.2: Device not a RPA enabled device",
+ __func__);
+ return false;
+ }
+ } else if ((p_dev_rec->ble.key_type & BTM_LE_KEY_PID) == 0) {
+ BTM_TRACE_DEBUG("%s: RPA offloading: Device not a RPA enabled device",
+ __func__);
+ return false;
+ }
- btm_ble_update_resolving_list(p_dev_rec->bd_addr, true);
- if (controller_get_interface()->supports_ble_privacy()) {
- uint8_t* peer_irk = p_dev_rec->ble.keys.irk;
- uint8_t* local_irk = btm_cb.devcb.id_keys.irk;
+ if ((p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) ||
+ btm_ble_brcm_find_resolving_pending_entry(p_dev_rec->bd_addr,
+ BTM_BLE_META_ADD_IRK_ENTRY)) {
+ BTM_TRACE_ERROR("%s: Device already in Resolving list", __func__);
+ return true;
+ }
- if (p_dev_rec->ble.static_addr.IsEmpty()) {
- p_dev_rec->ble.static_addr = p_dev_rec->bd_addr;
- p_dev_rec->ble.static_addr_type = p_dev_rec->ble.ble_addr_type;
- }
+ if (btm_cb.ble_ctr_cb.resolving_list_avail_size == 0) {
+ return false;
+ }
- BTM_TRACE_DEBUG("%s:adding device to controller resolving list",
- __func__);
- // use identical IRK for now
- btsnd_hcic_ble_add_device_resolving_list(
- p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr,
- peer_irk, local_irk);
+ if (rl_state && !btm_ble_disable_resolving_list(rl_state, false)) {
+ return false;
+ }
- if (controller_get_interface()->supports_ble_set_privacy_mode()) {
- BTM_TRACE_DEBUG("%s: adding device privacy mode", __func__);
- btsnd_hcic_ble_set_privacy_mode(p_dev_rec->ble.static_addr_type,
- p_dev_rec->ble.static_addr, 0x01);
- }
- } else {
- uint8_t param[40] = {0};
- uint8_t* p = param;
+ btm_ble_update_resolving_list(p_dev_rec->bd_addr, true);
+ if (controller_get_interface()->supports_ble_privacy()) {
+ uint8_t* peer_irk = p_dev_rec->ble.keys.irk;
+ uint8_t* local_irk = btm_cb.devcb.id_keys.irk;
- UINT8_TO_STREAM(p, BTM_BLE_META_ADD_IRK_ENTRY);
- ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, BT_OCTET16_LEN);
- UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
- BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
+ if (p_dev_rec->ble.static_addr.IsEmpty()) {
+ p_dev_rec->ble.static_addr = p_dev_rec->bd_addr;
+ p_dev_rec->ble.static_addr_type = p_dev_rec->ble.ble_addr_type;
+ }
- BTM_VendorSpecificCommand(HCI_VENDOR_BLE_RPA_VSC,
- BTM_BLE_META_ADD_IRK_LEN, param,
- btm_ble_resolving_list_vsc_op_cmpl);
- }
+ BTM_TRACE_DEBUG("%s: adding device %s to controller resolving list",
+ __func__, p_dev_rec->ble.static_addr.ToString().c_str());
- rt = true;
- btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
- BTM_BLE_META_ADD_IRK_ENTRY);
+ // use identical IRK for now
+ btsnd_hcic_ble_add_device_resolving_list(p_dev_rec->ble.static_addr_type,
+ p_dev_rec->ble.static_addr,
+ peer_irk, local_irk);
- /* if resolving list has been turned on, re-enable it */
- if (rl_mask)
- btm_ble_enable_resolving_list(rl_mask);
- else
- btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
- }
- } else {
- BTM_TRACE_ERROR("Device already in Resolving list");
- rt = true;
+ if (controller_get_interface()->supports_ble_set_privacy_mode()) {
+ BTM_TRACE_DEBUG("%s: adding device privacy mode", __func__);
+ btsnd_hcic_ble_set_privacy_mode(p_dev_rec->ble.static_addr_type,
+ p_dev_rec->ble.static_addr, 0x01);
}
} else {
- BTM_TRACE_DEBUG("Device not a RPA enabled device");
+ uint8_t param[40] = {0};
+ uint8_t* p = param;
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_ADD_IRK_ENTRY);
+ ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, BT_OCTET16_LEN);
+ UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
+ BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
+
+ BTM_VendorSpecificCommand(HCI_VENDOR_BLE_RPA_VSC, BTM_BLE_META_ADD_IRK_LEN,
+ param, btm_ble_resolving_list_vsc_op_cmpl);
}
- return rt;
+
+ btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
+ BTM_BLE_META_ADD_IRK_ENTRY);
+
+ /* if resolving list has been turned on, re-enable it */
+ if (rl_state)
+ btm_ble_enable_resolving_list(rl_state);
+ else
+ btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
+
+ return true;
}
/*******************************************************************************
@@ -782,8 +794,8 @@
}
if ((p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
- btm_ble_brcm_find_resolving_pending_entry(
- p_dev_rec->bd_addr, BTM_BLE_META_REMOVE_IRK_ENTRY) == false) {
+ !btm_ble_brcm_find_resolving_pending_entry(
+ p_dev_rec->bd_addr, BTM_BLE_META_REMOVE_IRK_ENTRY)) {
btm_ble_update_resolving_list(p_dev_rec->bd_addr, false);
btm_ble_remove_resolving_list_entry(p_dev_rec);
} else {
diff --git a/stack/btm/btm_dev.cc b/stack/btm/btm_dev.cc
index 0fe5c20..5368fad 100644
--- a/stack/btm/btm_dev.cc
+++ b/stack/btm/btm_dev.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -68,6 +68,8 @@
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
if (!p_dev_rec) {
p_dev_rec = btm_sec_allocate_dev_rec();
+ BTM_TRACE_API("%s: allocated p_dev_rec=%p, bd_addr=%s", __func__, p_dev_rec,
+ bd_addr.ToString().c_str());
p_dev_rec->bd_addr = bd_addr;
p_dev_rec->hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_BR_EDR);
@@ -225,10 +227,12 @@
******************************************************************************/
tBTM_SEC_DEV_REC* btm_sec_alloc_dev(const RawAddress& bd_addr) {
tBTM_INQ_INFO* p_inq_info;
- BTM_TRACE_EVENT("btm_sec_alloc_dev");
tBTM_SEC_DEV_REC* p_dev_rec = btm_sec_allocate_dev_rec();
+ BTM_TRACE_EVENT("%s: allocated p_dev_rec=%p, bd_addr=%s", __func__, p_dev_rec,
+ bd_addr.ToString().c_str());
+
/* Check with the BT manager if details about remote device are known */
/* outgoing connection */
p_inq_info = BTM_InqDbRead(bd_addr);
@@ -410,6 +414,8 @@
/* remove the combined record */
list_remove(btm_cb.sec_dev_rec, p_dev_rec);
+ // p_dev_rec gets freed in list_remove, we should not access it further
+ continue;
}
/* an RPA device entry is a duplicate of the target record */
diff --git a/stack/btm/btm_devctl.cc b/stack/btm/btm_devctl.cc
index 4910315..2e425aa 100644
--- a/stack/btm/btm_devctl.cc
+++ b/stack/btm/btm_devctl.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -117,7 +117,6 @@
******************************************************************************/
static void btm_db_reset(void) {
tBTM_CMPL_CB* p_cb;
- tBTM_STATUS status = BTM_DEV_RESET;
btm_inq_db_reset();
@@ -132,21 +131,33 @@
p_cb = btm_cb.devcb.p_rssi_cmpl_cb;
btm_cb.devcb.p_rssi_cmpl_cb = NULL;
- if (p_cb) (*p_cb)((tBTM_RSSI_RESULT*)&status);
+ if (p_cb) {
+ tBTM_RSSI_RESULT btm_rssi_result;
+ btm_rssi_result.status = BTM_DEV_RESET;
+ (*p_cb)(&btm_rssi_result);
+ }
}
if (btm_cb.devcb.p_failed_contact_counter_cmpl_cb) {
p_cb = btm_cb.devcb.p_failed_contact_counter_cmpl_cb;
btm_cb.devcb.p_failed_contact_counter_cmpl_cb = NULL;
- if (p_cb) (*p_cb)((tBTM_FAILED_CONTACT_COUNTER_RESULT*)&status);
+ if (p_cb) {
+ tBTM_FAILED_CONTACT_COUNTER_RESULT btm_failed_contact_counter_result;
+ btm_failed_contact_counter_result.status = BTM_DEV_RESET;
+ (*p_cb)(&btm_failed_contact_counter_result);
+ }
}
if (btm_cb.devcb.p_automatic_flush_timeout_cmpl_cb) {
p_cb = btm_cb.devcb.p_automatic_flush_timeout_cmpl_cb;
btm_cb.devcb.p_automatic_flush_timeout_cmpl_cb = NULL;
- if (p_cb) (*p_cb)((tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT*)&status);
+ if (p_cb) {
+ tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT btm_automatic_flush_timeout_result;
+ btm_automatic_flush_timeout_result.status = BTM_DEV_RESET;
+ (*p_cb)(&btm_automatic_flush_timeout_result);
+ }
}
}
@@ -607,7 +618,7 @@
*
******************************************************************************/
void btm_vsc_complete(uint8_t* p, uint16_t opcode, uint16_t evt_len,
- tBTM_CMPL_CB* p_vsc_cplt_cback) {
+ tBTM_VSC_CMPL_CB* p_vsc_cplt_cback) {
tBTM_VSC_CMPL vcs_cplt_params;
/* If there was a callback address for vcs complete, call it */
@@ -647,7 +658,7 @@
free_idx = i;
} else if (btm_cb.devcb.p_vend_spec_cb[i] == p_cb) {
/* Found callback in lookup table. If deregistering, clear the entry. */
- if (is_register == false) {
+ if (!is_register) {
btm_cb.devcb.p_vend_spec_cb[i] = NULL;
BTM_TRACE_EVENT("BTM Deregister For VSEvents is successfully");
}
diff --git a/stack/btm/btm_inq.cc b/stack/btm/btm_inq.cc
index 213683c..bdcce38 100644
--- a/stack/btm/btm_inq.cc
+++ b/stack/btm/btm_inq.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2014 Broadcom Corporation
+ * Copyright 1999-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,6 +43,8 @@
#include "hcidefs.h"
#include "hcimsgs.h"
+using bluetooth::Uuid;
+
/* 3 second timeout waiting for responses */
#define BTM_INQ_REPLY_TIMEOUT_MS (3 * 1000)
@@ -121,8 +123,6 @@
uint8_t uuid_size,
uint8_t* p_num_uuid,
uint8_t* p_uuid_list_type);
-static uint16_t btm_convert_uuid_to_uuid16(const uint8_t* p_uuid,
- uint8_t uuid_size);
/*******************************************************************************
*
@@ -502,7 +502,7 @@
/* Only cancel if one is active */
if (btm_cb.btm_inq_vars.inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) {
btm_cb.btm_inq_vars.inq_active = BTM_INQUIRY_INACTIVE;
- btm_cb.btm_inq_vars.p_inq_results_cb = (tBTM_INQ_RESULTS_CB*)NULL;
+ btm_cb.btm_inq_vars.p_inq_results_cb = NULL;
btsnd_hcic_exit_per_inq();
@@ -649,9 +649,6 @@
tBTM_STATUS BTM_CancelInquiry(void) {
tBTM_STATUS status = BTM_SUCCESS;
tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- uint8_t active_mode = p_inq->inq_active;
-#endif
BTM_TRACE_API("BTM_CancelInquiry called");
/*** Make sure the device is ready ***/
@@ -663,10 +660,8 @@
(!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE))) {
p_inq->inq_active = BTM_INQUIRY_INACTIVE;
p_inq->state = BTM_INQ_INACTIVE_STATE;
- p_inq->p_inq_results_cb =
- (tBTM_INQ_RESULTS_CB*)NULL; /* Do not notify caller anymore */
- p_inq->p_inq_cmpl_cb =
- (tBTM_CMPL_CB*)NULL; /* Do not notify caller anymore */
+ p_inq->p_inq_results_cb = NULL; /* Do not notify caller anymore */
+ p_inq->p_inq_cmpl_cb = NULL; /* Do not notify caller anymore */
/* If the event filter is in progress, mark it so that the processing of the
return
@@ -677,18 +672,10 @@
}
/* Initiate the cancel inquiry */
else {
- if (((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0)
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- && (active_mode & BTM_BR_INQUIRY_MASK)
-#endif
- ) {
+ if ((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0) {
btsnd_hcic_inq_cancel();
}
- if (((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- && (active_mode & BTM_BLE_INQ_ACTIVE_MASK)
-#endif
- )
+ if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
btm_ble_stop_inquiry();
}
@@ -744,7 +731,6 @@
tBTM_STATUS BTM_StartInquiry(tBTM_INQ_PARMS* p_inqparms,
tBTM_INQ_RESULTS_CB* p_results_cb,
tBTM_CMPL_CB* p_cmpl_cb) {
- tBTM_STATUS status = BTM_CMD_STARTED;
tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
BTM_TRACE_API("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
@@ -756,31 +742,34 @@
if (p_inq->inq_active || p_inq->inqfilt_active) {
/*check if LE observe is already running*/
if (p_inq->scan_type == INQ_LE_OBSERVE &&
- p_inq->p_inq_ble_results_cb != NULL) {
+ p_inq->p_inq_ble_results_cb != nullptr) {
BTM_TRACE_API("BTM_StartInquiry: LE observe in progress");
p_inq->scan_type = INQ_GENERAL;
p_inq->inq_active = BTM_INQUIRY_INACTIVE;
btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
btm_send_hci_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
} else {
- BTM_TRACE_API("BTM_StartInquiry: return BUSY");
+ LOG(ERROR) << __func__ << ": BTM_BUSY";
return (BTM_BUSY);
}
- } else
+ } else {
p_inq->scan_type = INQ_GENERAL;
+ }
/*** Make sure the device is ready ***/
- if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
+ if (!BTM_IsDeviceUp()) {
+ LOG(ERROR) << __func__ << ": adapter is not up";
+ return BTM_WRONG_MODE;
+ }
if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_GENERAL_INQUIRY &&
(p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_LIMITED_INQUIRY &&
(p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_GENERAL_INQUIRY &&
- (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_LIMITED_INQUIRY)
+ (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_LIMITED_INQUIRY) {
+ LOG(ERROR) << __func__ << ": illegal inquiry mode "
+ << std::to_string(p_inqparms->mode);
return (BTM_ILLEGAL_VALUE);
-
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- if (p_inq->next_state == BTM_FINISH) return BTM_ILLEGAL_VALUE;
-#endif
+ }
/* Save the inquiry parameters to be used upon the completion of
* setting/clearing the inquiry filter */
@@ -796,136 +785,70 @@
BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x",
p_inq->inq_active);
-/* interleave scan minimal conditions */
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
-
- /* check if both modes are present */
- if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) &&
- (p_inqparms->mode & BTM_BR_INQUIRY_MASK)) {
- BTM_TRACE_API("BTM:Interleave Inquiry Mode Set");
- p_inqparms->duration = p_inqparms->intl_duration[p_inq->next_state];
- p_inq->inqparms.duration = p_inqparms->duration;
- } else {
- BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x",
- p_inqparms->mode);
- p_inq->next_state = BTM_NO_INTERLEAVING;
- }
-#endif
-
+ tBTM_STATUS status = BTM_CMD_STARTED;
/* start LE inquiry here if requested */
- if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- &&
- (p_inq->next_state == BTM_BLE_ONE || p_inq->next_state == BTM_BLE_TWO ||
- p_inq->next_state == BTM_NO_INTERLEAVING)
-#endif
- )
-
- {
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK);
- BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x",
- p_inqparms->duration,
- (p_inqparms->mode & BTM_BLE_INQUIRY_MASK));
-#endif
+ if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)) {
if (!controller_get_interface()->supports_ble()) {
+ LOG(ERROR) << __func__ << ": trying to do LE scan on a non-LE adapter";
p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
status = BTM_ILLEGAL_VALUE;
- }
- /* BLE for now does not support filter condition for inquiry */
- else {
+ } else {
+ /* BLE for now does not support filter condition for inquiry */
status = btm_ble_start_inquiry(
(uint8_t)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
p_inqparms->duration);
if (status != BTM_CMD_STARTED) {
- BTM_TRACE_ERROR("Err Starting LE Inquiry.");
+ LOG(ERROR) << __func__ << ": Error Starting LE Inquiry";
p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
}
}
-#if (BTA_HOST_INTERLEAVE_SEARCH == FALSE)
p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
-#endif
-
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- if (p_inq->next_state == BTM_NO_INTERLEAVING) {
- p_inq->next_state = BTM_FINISH;
- } else {
- BTM_TRACE_API(
- "BTM:Interleaving: started LE scan, Advancing to next state: %d",
- p_inq->next_state + 1);
- p_inq->next_state += 1;
- }
- /* reset next_state if status <> BTM_Started */
- if (status != BTM_CMD_STARTED) p_inq->next_state = BTM_BR_ONE;
-
- /* if interleave scan..return here */
- return status;
-#endif
BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
}
/* we're done with this routine if BR/EDR inquiry is not desired. */
- if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
+ if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE) {
return status;
+ }
-/* BR/EDR inquiry portion */
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- if ((p_inq->next_state == BTM_BR_ONE || p_inq->next_state == BTM_BR_TWO ||
- p_inq->next_state == BTM_NO_INTERLEAVING)) {
- p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK);
-#endif
- /* If a filter is specified, then save it for later and clear the current
- filter.
- The setting of the filter is done upon completion of clearing of the
- previous
- filter.
- */
- switch (p_inqparms->filter_cond_type) {
- case BTM_CLR_INQUIRY_FILTER:
- p_inq->state = BTM_INQ_SET_FILT_STATE;
- break;
+ /* BR/EDR inquiry portion */
+ /* If a filter is specified, then save it for later and clear the current
+ filter.
+ The setting of the filter is done upon completion of clearing of the
+ previous
+ filter.
+ */
+ switch (p_inqparms->filter_cond_type) {
+ case BTM_CLR_INQUIRY_FILTER:
+ p_inq->state = BTM_INQ_SET_FILT_STATE;
+ break;
- case BTM_FILTER_COND_DEVICE_CLASS:
- case BTM_FILTER_COND_BD_ADDR:
- /* The filter is not being used so simply clear it;
- the inquiry can start after this operation */
- p_inq->state = BTM_INQ_CLR_FILT_STATE;
- p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
- /* =============>>>> adding LE filtering here ????? */
- break;
+ case BTM_FILTER_COND_DEVICE_CLASS:
+ case BTM_FILTER_COND_BD_ADDR:
+ /* The filter is not being used so simply clear it;
+ the inquiry can start after this operation */
+ p_inq->state = BTM_INQ_CLR_FILT_STATE;
+ p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
+ /* =============>>>> adding LE filtering here ????? */
+ break;
- default:
- return (BTM_ILLEGAL_VALUE);
+ default:
+ LOG(ERROR) << __func__ << ": invalid filter condition type "
+ << std::to_string(p_inqparms->filter_cond_type);
+ return (BTM_ILLEGAL_VALUE);
}
/* Before beginning the inquiry the current filter must be cleared, so
* initiate the command */
status = btm_set_inq_event_filter(p_inqparms->filter_cond_type,
&p_inqparms->filter_cond);
- if (status != BTM_CMD_STARTED) p_inq->state = BTM_INQ_INACTIVE_STATE;
-
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- if (p_inq->next_state == BTM_NO_INTERLEAVING)
- p_inq->next_state = BTM_FINISH;
- else {
- BTM_TRACE_API(
- "BTM:Interleaving: Started BTM inq, Advancing to next state: %d",
- p_inq->next_state + 1);
- p_inq->next_state += 1;
+ if (status != BTM_CMD_STARTED) {
+ LOG(ERROR) << __func__ << ": failed to set inquiry event filter";
+ p_inq->state = BTM_INQ_INACTIVE_STATE;
}
- }
- if (status != BTM_CMD_STARTED) {
- /* Some error beginning the scan process.
- Reset the next_state parameter.. Do we need to reset the inq_active also?
- */
- BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x",
- status);
- p_inq->next_state = BTM_BR_ONE;
- }
-#endif
- return (status);
+ return (status);
}
/*******************************************************************************
@@ -1532,7 +1455,7 @@
/* Only process the inquiry filter; Ignore the connection filter until it
is used by the upper layers */
- if (p_inq->inqfilt_active == true) {
+ if (p_inq->inqfilt_active) {
/* Extract the returned status from the buffer */
STREAM_TO_UINT8(hci_status, p);
if (hci_status != HCI_SUCCESS) {
@@ -1804,7 +1727,7 @@
else
p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
- if (is_new == true) {
+ if (is_new) {
/* Save the info */
p_cur = &p_i->inq_info.results;
p_cur->page_scan_rep_mode = page_scan_rep_mode;
@@ -1861,7 +1784,8 @@
/* If a callback is registered, call it with the results */
if (p_inq_results_cb)
- (p_inq_results_cb)((tBTM_INQ_RESULTS*)p_cur, p_eir_data, 62);
+ (p_inq_results_cb)((tBTM_INQ_RESULTS*)p_cur, p_eir_data,
+ HCI_EXT_INQ_RESPONSE_LEN);
}
}
}
@@ -1920,27 +1844,12 @@
tBTM_CMPL_CB* p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- /* inquiry inactive case happens when inquiry is cancelled.
- Make mode 0 for no further inquiries from the current inquiry process
- */
- if (status != HCI_SUCCESS || p_inq->next_state == BTM_FINISH ||
- !p_inq->inq_active) {
- /* re-initialize for next inquiry request */
- p_inq->next_state = BTM_BR_ONE;
- /* make the mode 0 here */
- p_inq->inqparms.mode &= ~(p_inq->inqparms.mode);
- }
-#endif
-
-#if (BTA_HOST_INTERLEAVE_SEARCH == FALSE)
p_inq->inqparms.mode &= ~(mode);
-#endif
if (p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active) {
/*end of LE observe*/
- p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB*)NULL;
- p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB*)NULL;
+ p_inq->p_inq_ble_results_cb = NULL;
+ p_inq->p_inq_ble_cmpl_cb = NULL;
p_inq->scan_type = INQ_NONE;
}
@@ -1974,9 +1883,9 @@
}
/* Clear the results callback if set */
- p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB*)NULL;
+ p_inq->p_inq_results_cb = NULL;
p_inq->inq_active = BTM_INQUIRY_INACTIVE;
- p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB*)NULL;
+ p_inq->p_inq_cmpl_cb = NULL;
/* If we have a callback registered for inquiry complete, call it */
BTM_TRACE_DEBUG("BTM Inq Compl Callback: status 0x%02x, num results %d",
@@ -1985,16 +1894,6 @@
if (p_inq_cb) (p_inq_cb)((tBTM_INQUIRY_CMPL*)&p_inq->inq_cmpl_info);
}
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- if (p_inq->inqparms.mode != 0 &&
- !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)) {
- /* make inquiry inactive for next iteration */
- p_inq->inq_active = BTM_INQUIRY_INACTIVE;
- /* call the inquiry again */
- BTM_StartInquiry(&p_inq->inqparms, p_inq->p_inq_results_cb,
- p_inq->p_inq_cmpl_cb);
- }
-#endif
}
if (p_inq->inqparms.mode == 0 &&
p_inq->scan_type == INQ_GENERAL) // this inquiry is complete
@@ -2127,8 +2026,7 @@
/* If the inquire BDA and remote DBA are the same, then stop the timer and set
* the active to false */
- if ((p_inq->remname_active == true) &&
- (!bda || (*bda == p_inq->remname_bda))) {
+ if ((p_inq->remname_active) && (!bda || (*bda == p_inq->remname_bda))) {
if (BTM_UseLeLink(p_inq->remname_bda)) {
if (hci_status == HCI_ERR_UNSPECIFIED)
btm_ble_cancel_remote_name(p_inq->remname_bda);
@@ -2167,7 +2065,7 @@
p_inq->remname_bda = RawAddress::kEmpty;
p_inq->p_remname_cmpl_cb = NULL;
- if (p_cb) (p_cb)((tBTM_REMOTE_DEV_NAME*)&rem_name);
+ if (p_cb) (p_cb)(&rem_name);
}
}
@@ -2309,7 +2207,7 @@
* false - if not found
*
******************************************************************************/
-bool BTM_HasEirService(uint32_t* p_eir_uuid, uint16_t uuid16) {
+bool BTM_HasEirService(const uint32_t* p_eir_uuid, uint16_t uuid16) {
uint8_t service_id;
service_id = btm_convert_uuid_to_eir_service(uuid16);
@@ -2433,7 +2331,8 @@
*
* Parameters p_eir - EIR
* eir_len - EIR len
- * uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
+ * uuid_size - Uuid::kNumBytes16, Uuid::kNumBytes32,
+ * Uuid::kNumBytes128
* p_num_uuid - return number of UUID in found list
* p_uuid_list - return UUID list
* max_num_uuid - maximum number of UUID to be returned
@@ -2455,7 +2354,7 @@
uint8_t yy, xx;
uint16_t* p_uuid16 = (uint16_t*)p_uuid_list;
uint32_t* p_uuid32 = (uint32_t*)p_uuid_list;
- char buff[LEN_UUID_128 * 2 + 1];
+ char buff[Uuid::kNumBytes128 * 2 + 1];
p_uuid_data =
btm_eir_get_uuid_list(p_eir, eir_len, uuid_size, p_num_uuid, &type);
@@ -2472,22 +2371,22 @@
BTM_TRACE_DEBUG("%s: type = %02X, number of uuid = %d", __func__, type,
*p_num_uuid);
- if (uuid_size == LEN_UUID_16) {
+ if (uuid_size == Uuid::kNumBytes16) {
for (yy = 0; yy < *p_num_uuid; yy++) {
STREAM_TO_UINT16(*(p_uuid16 + yy), p_uuid_data);
BTM_TRACE_DEBUG(" 0x%04X", *(p_uuid16 + yy));
}
- } else if (uuid_size == LEN_UUID_32) {
+ } else if (uuid_size == Uuid::kNumBytes32) {
for (yy = 0; yy < *p_num_uuid; yy++) {
STREAM_TO_UINT32(*(p_uuid32 + yy), p_uuid_data);
BTM_TRACE_DEBUG(" 0x%08X", *(p_uuid32 + yy));
}
- } else if (uuid_size == LEN_UUID_128) {
+ } else if (uuid_size == Uuid::kNumBytes128) {
for (yy = 0; yy < *p_num_uuid; yy++) {
- STREAM_TO_ARRAY16(p_uuid_list + yy * LEN_UUID_128, p_uuid_data);
- for (xx = 0; xx < LEN_UUID_128; xx++)
+ STREAM_TO_ARRAY16(p_uuid_list + yy * Uuid::kNumBytes128, p_uuid_data);
+ for (xx = 0; xx < Uuid::kNumBytes128; xx++)
snprintf(buff + xx * 2, sizeof(buff) - xx * 2, "%02X",
- *(p_uuid_list + yy * LEN_UUID_128 + xx));
+ *(p_uuid_list + yy * Uuid::kNumBytes128 + xx));
BTM_TRACE_DEBUG(" 0x%s", buff);
}
}
@@ -2520,15 +2419,15 @@
uint8_t uuid_len;
switch (uuid_size) {
- case LEN_UUID_16:
+ case Uuid::kNumBytes16:
complete_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
more_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
break;
- case LEN_UUID_32:
+ case Uuid::kNumBytes32:
complete_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
more_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
break;
- case LEN_UUID_128:
+ case Uuid::kNumBytes128:
complete_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
more_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
break;
@@ -2567,7 +2466,7 @@
******************************************************************************/
static uint16_t btm_convert_uuid_to_uuid16(const uint8_t* p_uuid,
uint8_t uuid_size) {
- static const uint8_t base_uuid[LEN_UUID_128] = {
+ static const uint8_t base_uuid[Uuid::kNumBytes128] = {
0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint16_t uuid16 = 0;
@@ -2576,26 +2475,26 @@
uint8_t xx;
switch (uuid_size) {
- case LEN_UUID_16:
+ case Uuid::kNumBytes16:
STREAM_TO_UINT16(uuid16, p_uuid);
break;
- case LEN_UUID_32:
+ case Uuid::kNumBytes32:
STREAM_TO_UINT32(uuid32, p_uuid);
if (uuid32 < 0x10000) uuid16 = (uint16_t)uuid32;
break;
- case LEN_UUID_128:
+ case Uuid::kNumBytes128:
/* See if we can compress his UUID down to 16 or 32bit UUIDs */
is_base_uuid = true;
- for (xx = 0; xx < LEN_UUID_128 - 4; xx++) {
+ for (xx = 0; xx < Uuid::kNumBytes128 - 4; xx++) {
if (p_uuid[xx] != base_uuid[xx]) {
is_base_uuid = false;
break;
}
}
if (is_base_uuid) {
- if ((p_uuid[LEN_UUID_128 - 1] == 0) &&
- (p_uuid[LEN_UUID_128 - 2] == 0)) {
- p_uuid += (LEN_UUID_128 - 4);
+ if ((p_uuid[Uuid::kNumBytes128 - 1] == 0) &&
+ (p_uuid[Uuid::kNumBytes128 - 2] == 0)) {
+ p_uuid += (Uuid::kNumBytes128 - 4);
STREAM_TO_UINT16(uuid16, p_uuid);
}
}
@@ -2629,7 +2528,7 @@
uint8_t type = BTM_EIR_MORE_16BITS_UUID_TYPE;
p_uuid_data = btm_eir_get_uuid_list(p_eir, HCI_EXT_INQ_RESPONSE_LEN,
- LEN_UUID_16, &num_uuid, &type);
+ Uuid::kNumBytes16, &num_uuid, &type);
if (type == BTM_EIR_COMPLETE_16BITS_UUID_TYPE) {
p_results->eir_complete_list = true;
@@ -2648,21 +2547,21 @@
}
p_uuid_data = btm_eir_get_uuid_list(p_eir, HCI_EXT_INQ_RESPONSE_LEN,
- LEN_UUID_32, &num_uuid, &type);
+ Uuid::kNumBytes32, &num_uuid, &type);
if (p_uuid_data) {
for (yy = 0; yy < num_uuid; yy++) {
- uuid16 = btm_convert_uuid_to_uuid16(p_uuid_data, LEN_UUID_32);
- p_uuid_data += LEN_UUID_32;
+ uuid16 = btm_convert_uuid_to_uuid16(p_uuid_data, Uuid::kNumBytes32);
+ p_uuid_data += Uuid::kNumBytes32;
if (uuid16) BTM_AddEirService(p_results->eir_uuid, uuid16);
}
}
p_uuid_data = btm_eir_get_uuid_list(p_eir, HCI_EXT_INQ_RESPONSE_LEN,
- LEN_UUID_128, &num_uuid, &type);
+ Uuid::kNumBytes128, &num_uuid, &type);
if (p_uuid_data) {
for (yy = 0; yy < num_uuid; yy++) {
- uuid16 = btm_convert_uuid_to_uuid16(p_uuid_data, LEN_UUID_128);
- p_uuid_data += LEN_UUID_128;
+ uuid16 = btm_convert_uuid_to_uuid16(p_uuid_data, Uuid::kNumBytes128);
+ p_uuid_data += Uuid::kNumBytes128;
if (uuid16) BTM_AddEirService(p_results->eir_uuid, uuid16);
}
}
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index e6e0dff..21f7ce3 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,6 +47,7 @@
*******************************************
*/
extern void btm_init(void);
+extern void btm_free(void);
/* Internal functions provided by btm_inq.cc
******************************************
@@ -184,6 +185,7 @@
extern void btm_ble_remove_from_white_list_complete(uint8_t* p,
uint16_t evt_len);
extern void btm_ble_clear_white_list_complete(uint8_t* p, uint16_t evt_len);
+extern void btm_ble_create_conn_cancel_complete(uint8_t* p);
extern bool btm_ble_addr_resolvable(const RawAddress& rpa,
tBTM_SEC_DEV_REC* p_dev_rec);
extern tBTM_STATUS btm_ble_read_resolving_list_entry(
@@ -193,7 +195,7 @@
/* Vendor Specific Command complete evt handler */
extern void btm_vsc_complete(uint8_t* p, uint16_t cc_opcode, uint16_t evt_len,
- tBTM_CMPL_CB* p_vsc_cplt_cback);
+ tBTM_VSC_CMPL_CB* p_vsc_cplt_cback);
extern void btm_inq_db_reset(void);
extern void btm_vendor_specific_evt(uint8_t* p, uint8_t evt_len);
extern void btm_delete_stored_link_key_complete(uint8_t* p);
@@ -287,5 +289,6 @@
extern void btm_acl_paging(BT_HDR* p, const RawAddress& dest);
extern uint8_t btm_sec_clr_service_by_psm(uint16_t psm);
extern void btm_sec_clr_temp_auth_service(const RawAddress& bda);
+extern tBTM_STATUS btm_sec_execute_procedure(tBTM_SEC_DEV_REC* p_dev_rec);
#endif
diff --git a/stack/btm/btm_int_types.h b/stack/btm/btm_int_types.h
index c633cf0..8f91cef 100644
--- a/stack/btm/btm_int_types.h
+++ b/stack/btm/btm_int_types.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -291,10 +291,6 @@
uint8_t state; /* Current state that the inquiry process is in */
uint8_t inq_active; /* Bit Mask indicating type of inquiry is active */
bool no_inc_ssp; /* true, to stop inquiry on incoming SSP */
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- btm_inq_state
- next_state; /*interleaving state to determine next mode to be inquired*/
-#endif
} tBTM_INQUIRY_VAR_ST;
/* The MSB of the clock offset field indicates whether the offset is valid. */
@@ -354,9 +350,6 @@
*/
typedef struct {
tBTM_ESCO_INFO esco; /* Current settings */
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- fixed_queue_t* xmit_data_q; /* SCO data transmitting queue */
-#endif
tBTM_SCO_CB* p_conn_cb; /* Callback for when connected */
tBTM_SCO_CB* p_disc_cb; /* Callback for when disconnect */
uint16_t state; /* The state of the SCO link */
@@ -369,9 +362,6 @@
/* SCO Management control block */
typedef struct {
tBTM_SCO_IND_CBACK* app_sco_ind_cb;
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- tBTM_SCO_DATA_CB* p_data_cb; /* Callback for SCO data over HCI */
-#endif
tSCO_CONN sco_db[BTM_MAX_SCO_LINKS];
enh_esco_params_t def_esco_parms;
uint16_t sco_disc_reason;
@@ -417,10 +407,6 @@
uint16_t psm; /* L2CAP PSM value */
uint16_t security_flags; /* Bitmap of required security features */
uint8_t service_id; /* Passed in authorization callback */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- uint16_t
- ucd_security_flags; /* Bitmap of required security features for UCD */
-#endif
#if BTM_SEC_SERVICE_NAME_LEN > 0
uint8_t orig_service_name[BTM_SEC_SERVICE_NAME_LEN + 1];
uint8_t term_service_name[BTM_SEC_SERVICE_NAME_LEN + 1];
@@ -538,10 +524,6 @@
uint8_t sec_state; /* Operating state */
bool is_originator; /* true if device is originating connection */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- bool is_ucd; /* true if device is sending or receiving UCD */
- /* if incoming security failed, received UCD will be discarded */
-#endif
bool role_master; /* true if current mode is master */
uint16_t security_required; /* Security required for connection */
bool link_key_not_sent; /* link key notification has not been sent waiting for
@@ -746,26 +728,10 @@
tBTM_BLE_SEC_ACT sec_act;
} tBTM_SEC_QUEUE_ENTRY;
-#if (L2CAP_UCD_INCLUDED == TRUE)
-
-#define CONN_ORIENT_TERM 0x00 /* incoming connection oriented */
-#define CONN_ORIENT_ORIG 0x01 /* outgoing connection oriented */
-#define CONNLESS_TERM 0x02 /* incoming connectionless */
-#define CONNLESS_ORIG 0x03 /* outgoing connectionless */
-#define CONNECTION_TYPE_ORIG_MASK 0x01 /* mask for direction */
-#define CONNECTION_TYPE_CONNLESS_MASK \
- 0x02 /* mask for connectionless or not \
- */
-typedef uint8_t CONNECTION_TYPE;
-
-#else
-
#define CONN_ORIENT_TERM false
#define CONN_ORIENT_ORIG true
typedef bool CONNECTION_TYPE;
-#endif /* (L2CAP_UCD_INCLUDED == TRUE) */
-
/* Define a structure to hold all the BTM data
*/
diff --git a/stack/btm/btm_main.cc b/stack/btm/btm_main.cc
index 70f3ee4..011feb7 100644
--- a/stack/btm/btm_main.cc
+++ b/stack/btm/btm_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,3 +74,21 @@
btm_dev_init(); /* Device Manager Structures & HCI_Reset */
}
+
+/** This function is called to free dynamic memory and system resource allocated by btm_init */
+void btm_free(void) {
+ fixed_queue_free(btm_cb.page_queue, NULL);
+ btm_cb.page_queue = NULL;
+
+ fixed_queue_free(btm_cb.sec_pending_q, NULL);
+ btm_cb.sec_pending_q = NULL;
+
+ list_free(btm_cb.sec_dev_rec);
+ btm_cb.sec_dev_rec = NULL;
+
+ alarm_free(btm_cb.sec_collision_timer);
+ btm_cb.sec_collision_timer = NULL;
+
+ alarm_free(btm_cb.pairing_timer);
+ btm_cb.pairing_timer = NULL;
+}
diff --git a/stack/btm/btm_pm.cc b/stack/btm/btm_pm.cc
index aeb5170..af06c1b 100644
--- a/stack/btm/btm_pm.cc
+++ b/stack/btm/btm_pm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2000-2012 Broadcom Corporation
+ * Copyright 2000-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@
#include "bt_utils.h"
#include "btm_api.h"
#include "btm_int.h"
+#include "btm_int_types.h"
#include "btu.h"
#include "hcidefs.h"
#include "hcimsgs.h"
@@ -74,8 +75,8 @@
/* function prototype */
static int btm_pm_find_acl_ind(const RawAddress& remote_bda);
static tBTM_STATUS btm_pm_snd_md_req(uint8_t pm_id, int link_ind,
- tBTM_PM_PWR_MD* p_mode);
-static const char* mode_to_string(tBTM_PM_MODE mode);
+ const tBTM_PM_PWR_MD* p_mode);
+static const char* mode_to_string(const tBTM_PM_MODE mode);
#if (BTM_PM_DEBUG == TRUE)
const char* btm_pm_state_str[] = {"pm_active_state", "pm_hold_state",
@@ -144,19 +145,25 @@
*
******************************************************************************/
tBTM_STATUS BTM_SetPowerMode(uint8_t pm_id, const RawAddress& remote_bda,
- tBTM_PM_PWR_MD* p_mode) {
+ const tBTM_PM_PWR_MD* p_mode) {
uint8_t* p_features;
int ind, acl_ind;
- tBTM_PM_MCB* p_cb = NULL; /* per ACL link */
+ tBTM_PM_MCB* p_cb = nullptr; /* per ACL link */
tBTM_PM_MODE mode;
int temp_pm_id;
- if (pm_id >= BTM_MAX_PM_RECORDS) pm_id = BTM_PM_SET_ONLY_ID;
+ if (pm_id >= BTM_MAX_PM_RECORDS) {
+ pm_id = BTM_PM_SET_ONLY_ID;
+ }
- if (p_mode == NULL) return BTM_ILLEGAL_VALUE;
+ if (!p_mode) {
+ LOG(ERROR) << __func__ << ": pm_id " << unsigned(pm_id)
+ << " p_mode is null for " << remote_bda;
+ return BTM_ILLEGAL_VALUE;
+ }
VLOG(2) << __func__ << " pm_id " << pm_id << " BDA: " << remote_bda
- << " mode:0x" << std::hex << p_mode->mode;
+ << " mode:" << std::to_string(p_mode->mode);
/* take out the force bit */
mode = p_mode->mode & ~BTM_PM_MD_FORCE;
@@ -170,12 +177,14 @@
/* check if the requested mode is supported */
ind = mode - BTM_PM_MD_HOLD; /* make it base 0 */
p_features = BTM_ReadLocalFeatures();
- if (!(p_features[btm_pm_mode_off[ind]] & btm_pm_mode_msk[ind]))
+ if (!(p_features[btm_pm_mode_off[ind]] & btm_pm_mode_msk[ind])) {
+ LOG(ERROR) << __func__ << ": pm_id " << unsigned(pm_id) << " mode "
+ << unsigned(mode) << " is not supported for " << remote_bda;
return BTM_MODE_UNSUPPORTED;
+ }
}
- if (mode == p_cb->state) /* the requested mode is current mode */
- {
+ if (mode == p_cb->state) {
/* already in the requested mode and the current interval has less latency
* than the max */
if ((mode == BTM_PM_MD_ACTIVE) ||
@@ -183,14 +192,17 @@
(p_mode->min <= p_cb->interval)) ||
((p_mode->mode & BTM_PM_MD_FORCE) == 0 &&
(p_mode->max >= p_cb->interval))) {
- BTM_TRACE_DEBUG("BTM_SetPowerMode: mode:0x%x interval %d max:%d, min:%d",
- p_mode->mode, p_cb->interval, p_mode->max, p_mode->min);
+ VLOG(1) << __func__ << " already in requested mode "
+ << std::to_string(p_mode->mode) << ", interval " << p_cb->interval
+ << " max " << p_mode->max << " min " << p_mode->min;
return BTM_SUCCESS;
}
}
temp_pm_id = pm_id;
- if (pm_id == BTM_PM_SET_ONLY_ID) temp_pm_id = BTM_MAX_PM_RECORDS;
+ if (pm_id == BTM_PM_SET_ONLY_ID) {
+ temp_pm_id = BTM_MAX_PM_RECORDS;
+ }
/* update mode database */
if (((pm_id != BTM_PM_SET_ONLY_ID) &&
@@ -203,7 +215,7 @@
#endif // BTM_PM_DEBUG
/* Make sure mask is set to BTM_PM_REG_SET */
btm_cb.pm_reg_db[temp_pm_id].mask |= BTM_PM_REG_SET;
- *(&p_cb->req_mode[temp_pm_id]) = *((tBTM_PM_PWR_MD*)p_mode);
+ *(&p_cb->req_mode[temp_pm_id]) = *p_mode;
p_cb->chg_ind = true;
}
@@ -213,12 +225,12 @@
#endif // BTM_PM_DEBUG
/* if mode == hold or pending, return */
if ((p_cb->state == BTM_PM_STS_HOLD) || (p_cb->state == BTM_PM_STS_PENDING) ||
- (btm_cb.pm_pend_link != MAX_L2CAP_LINKS)) /* command pending */
- {
+ (btm_cb.pm_pend_link != MAX_L2CAP_LINKS)) {
+ /* command pending */
if (acl_ind != btm_cb.pm_pend_link) {
/* set the stored mask */
p_cb->state |= BTM_PM_STORED_MASK;
- BTM_TRACE_DEBUG("btm_pm state stored:%d", acl_ind);
+ BTM_TRACE_DEBUG("%s: btm_pm state stored:%d", __func__, acl_ind);
}
return BTM_CMD_STORED;
}
@@ -416,8 +428,8 @@
* Returns void
*
******************************************************************************/
-static tBTM_PM_PWR_MD* btm_pm_compare_modes(tBTM_PM_PWR_MD* p_md1,
- tBTM_PM_PWR_MD* p_md2,
+static tBTM_PM_PWR_MD* btm_pm_compare_modes(const tBTM_PM_PWR_MD* p_md1,
+ const tBTM_PM_PWR_MD* p_md2,
tBTM_PM_PWR_MD* p_res) {
uint8_t res;
@@ -425,7 +437,7 @@
*p_res = *p_md2;
p_res->mode &= ~BTM_PM_MD_FORCE;
- return p_md2;
+ return p_res;
}
if (p_md2->mode == BTM_PM_MD_ACTIVE || p_md1->mode == BTM_PM_MD_ACTIVE) {
@@ -450,11 +462,11 @@
switch (res) {
case BTM_PM_GET_MD1:
*p_res = *p_md1;
- return p_md1;
+ return p_res;
case BTM_PM_GET_MD2:
*p_res = *p_md2;
- return p_md2;
+ return p_res;
case BTM_PM_GET_COMP:
p_res->mode = p_md1->mode;
@@ -489,7 +501,7 @@
*
******************************************************************************/
static tBTM_PM_MODE btm_pm_get_set_mode(uint8_t pm_id, tBTM_PM_MCB* p_cb,
- tBTM_PM_PWR_MD* p_mode,
+ const tBTM_PM_PWR_MD* p_mode,
tBTM_PM_PWR_MD* p_res) {
int xx, loop_max;
tBTM_PM_PWR_MD* p_md = NULL;
@@ -547,7 +559,7 @@
*, bool *p_chg_ind
******************************************************************************/
static tBTM_STATUS btm_pm_snd_md_req(uint8_t pm_id, int link_ind,
- tBTM_PM_PWR_MD* p_mode) {
+ const tBTM_PM_PWR_MD* p_mode) {
tBTM_PM_PWR_MD md_res;
tBTM_PM_MODE mode;
tBTM_PM_MCB* p_cb = &btm_cb.pm_mode_db[link_ind];
@@ -574,7 +586,7 @@
if (mode != BTM_PM_MD_ACTIVE && p_cb->state != BTM_PM_MD_ACTIVE)
p_cb->chg_ind = true; /* needs to wake, then sleep */
- if (p_cb->chg_ind == true) /* needs to wake first */
+ if (p_cb->chg_ind) /* needs to wake first */
md_res.mode = BTM_PM_MD_ACTIVE;
#if (BTM_SSR_INCLUDED == TRUE)
else if (BTM_PM_MD_SNIFF == md_res.mode && p_cb->max_lat) {
@@ -785,7 +797,7 @@
btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, xx, NULL);
} else {
for (zz = 0; zz < MAX_L2CAP_LINKS; zz++) {
- if (btm_cb.pm_mode_db[zz].chg_ind == true) {
+ if (btm_cb.pm_mode_db[zz].chg_ind) {
#if (BTM_PM_DEBUG == TRUE)
BTM_TRACE_DEBUG("btm_pm_proc_mode_change: Sending PM req :%d", zz);
#endif // BTM_PM_DEBUG
@@ -928,15 +940,15 @@
*
******************************************************************************/
tBTM_CONTRL_STATE BTM_PM_ReadControllerState(void) {
- if (true == btm_pm_device_in_active_or_sniff_mode())
+ if (btm_pm_device_in_active_or_sniff_mode())
return BTM_CONTRL_ACTIVE;
- else if (true == btm_pm_device_in_scan_state())
+ else if (btm_pm_device_in_scan_state())
return BTM_CONTRL_SCAN;
else
return BTM_CONTRL_IDLE;
}
-static const char* mode_to_string(tBTM_PM_MODE mode) {
+static const char* mode_to_string(const tBTM_PM_MODE mode) {
switch (mode) {
case BTM_PM_MD_ACTIVE:
return "ACTIVE";
diff --git a/stack/btm/btm_sco.cc b/stack/btm/btm_sco.cc
index dea830f..6e7f97c 100644
--- a/stack/btm/btm_sco.cc
+++ b/stack/btm/btm_sco.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2000-2012 Broadcom Corporation
+ * Copyright 2000-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
*
******************************************************************************/
+#include <device/include/esco_parameters.h>
+#include <stack/include/btm_api_types.h>
#include <string.h>
#include "bt_common.h"
#include "bt_target.h"
@@ -30,6 +32,7 @@
#include "bt_utils.h"
#include "btm_api.h"
#include "btm_int.h"
+#include "btm_int_types.h"
#include "btu.h"
#include "device/include/controller.h"
#include "device/include/esco_parameters.h"
@@ -69,21 +72,8 @@
* Returns void
*
******************************************************************************/
-#if (BTM_SCO_HCI_INCLUDED == TRUE && BTM_MAX_SCO_LINKS > 0)
-void btm_sco_flush_sco_data(uint16_t sco_inx) {
- tSCO_CONN* p;
- BT_HDR* p_buf;
-
- if (sco_inx < BTM_MAX_SCO_LINKS) {
- p = &btm_cb.sco_cb.sco_db[sco_inx];
- while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p->xmit_data_q)) != NULL)
- osi_free(p_buf);
- }
-}
-}
-#else
void btm_sco_flush_sco_data(UNUSED_ATTR uint16_t sco_inx) {}
-#endif
+
/*******************************************************************************
*
* Function btm_sco_init
@@ -94,10 +84,6 @@
*
******************************************************************************/
void btm_sco_init(void) {
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- for (int i = 0; i < BTM_MAX_SCO_LINKS; i++)
- btm_cb.sco_cb.sco_db[i].xmit_data_q = fixed_queue_new(SIZE_MAX);
-#endif
/* Initialize nonzero defaults */
btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON;
btm_cb.sco_cb.def_esco_parms = esco_parameters_for_codec(ESCO_CODEC_CVSD);
@@ -205,35 +191,6 @@
#endif
}
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
-/*******************************************************************************
- *
- * Function btm_sco_check_send_pkts
- *
- * Description This function is called to check if it can send packets
- * to the Host Controller.
- *
- * Returns void
- *
- ******************************************************************************/
-void btm_sco_check_send_pkts(uint16_t sco_inx) {
- tSCO_CB* p_cb = &btm_cb.sco_cb;
- tSCO_CONN* p_ccb = &p_cb->sco_db[sco_inx];
-
- /* If there is data to send, send it now */
- BT_HDR* p_buf;
- while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_data_q)) !=
- NULL) {
-#if (BTM_SCO_HCI_DEBUG == TRUE)
- BTM_TRACE_DEBUG("btm: [%d] buf in xmit_data_q",
- fixed_queue_length(p_ccb->xmit_data_q) + 1);
-#endif
-
- HCI_SCO_DATA_TO_LOWER(p_buf);
- }
-}
-#endif /* BTM_SCO_HCI_INCLUDED == TRUE */
-
/*******************************************************************************
*
* Function btm_route_sco_data
@@ -244,36 +201,7 @@
*
******************************************************************************/
void btm_route_sco_data(BT_HDR* p_msg) {
-#if (BTM_SCO_HCI_INCLUDED == TRUE)
- uint16_t sco_inx, handle;
- uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
- uint8_t pkt_size = 0;
- uint8_t pkt_status = 0;
-
- /* Extract Packet_Status_Flag and handle */
- STREAM_TO_UINT16(handle, p);
- pkt_status = HCID_GET_EVENT(handle);
- handle = HCID_GET_HANDLE(handle);
-
- STREAM_TO_UINT8(pkt_size, p);
-
- sco_inx = btm_find_scb_by_handle(handle);
- if (sco_inx != BTM_MAX_SCO_LINKS) {
- /* send data callback */
- if (!btm_cb.sco_cb.p_data_cb)
- /* if no data callback registered, just free the buffer */
- osi_free(p_msg);
- else {
- (*btm_cb.sco_cb.p_data_cb)(sco_inx, p_msg,
- (tBTM_SCO_DATA_FLAG)pkt_status);
- }
- } else /* no mapping handle SCO connection is active, free the buffer */
- {
- osi_free(p_msg);
- }
-#else
osi_free(p_msg);
-#endif
}
/*******************************************************************************
@@ -297,58 +225,10 @@
*
*
******************************************************************************/
-#if (BTM_SCO_HCI_INCLUDED == TRUE && BTM_MAX_SCO_LINKS > 0)
-tBTM_STATUS BTM_WriteScoData(uint16_t sco_inx, BT_HDR* p_buf) {
- tSCO_CONN* p_ccb = &btm_cb.sco_cb.sco_db[sco_inx];
- uint8_t* p;
- tBTM_STATUS status = BTM_SUCCESS;
-
- if (sco_inx < BTM_MAX_SCO_LINKS && btm_cb.sco_cb.p_data_cb &&
- p_ccb->state == SCO_ST_CONNECTED) {
- /* Ensure we have enough space in the buffer for the SCO and HCI headers */
- if (p_buf->offset < HCI_SCO_PREAMBLE_SIZE) {
- BTM_TRACE_ERROR("BTM SCO - cannot send buffer, offset: %d",
- p_buf->offset);
- osi_free(p_buf);
- status = BTM_ILLEGAL_VALUE;
- } else /* write HCI header */
- {
- /* Step back 3 bytes to add the headers */
- p_buf->offset -= HCI_SCO_PREAMBLE_SIZE;
- /* Set the pointer to the beginning of the data */
- p = (uint8_t*)(p_buf + 1) + p_buf->offset;
- /* add HCI handle */
- UINT16_TO_STREAM(p, p_ccb->hci_handle);
- /* only sent the first BTM_SCO_DATA_SIZE_MAX bytes data if more than max,
- and set warning status */
- if (p_buf->len > BTM_SCO_DATA_SIZE_MAX) {
- p_buf->len = BTM_SCO_DATA_SIZE_MAX;
- status = BTM_SCO_BAD_LENGTH;
- }
-
- UINT8_TO_STREAM(p, (uint8_t)p_buf->len);
- p_buf->len += HCI_SCO_PREAMBLE_SIZE;
-
- fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf);
-
- btm_sco_check_send_pkts(sco_inx);
- }
- } else {
- osi_free(p_buf);
-
- BTM_TRACE_ERROR("%s:invalid sco index: %d at state [%d]", __func__, sco_inx,
- btm_cb.sco_cb.sco_db[sco_inx].state);
- status = BTM_UNKNOWN_ADDR;
- }
-
- return status;
-}
-#else
tBTM_STATUS BTM_WriteScoData(UNUSED_ATTR uint16_t sco_inx,
UNUSED_ATTR BT_HDR* p_buf) {
return (BTM_NO_RESOURCES);
}
-#endif
#if (BTM_MAX_SCO_LINKS > 0)
/*******************************************************************************
@@ -367,10 +247,13 @@
/* Send connect request depending on version of spec */
if (!btm_cb.sco_cb.esco_supported) {
+ LOG(INFO) << __func__ << ": sending non-eSCO request for handle="
+ << unsigned(acl_handle);
btsnd_hcic_add_SCO_conn(acl_handle, BTM_ESCO_2_SCO(p_setup->packet_types));
} else {
uint16_t temp_packet_types =
- (p_setup->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK &
+ (p_setup->packet_types &
+ static_cast<uint16_t>(BTM_SCO_SUPPORTED_PKTS_MASK) &
btm_cb.btm_sco_pkt_types_supported);
/* OR in any exception packet types */
@@ -385,12 +268,12 @@
if (acl_index < MAX_L2CAP_LINKS) {
p_acl = &btm_cb.acl_db[acl_index];
if (!HCI_EDR_ESCO_2MPS_SUPPORTED(p_acl->peer_lmp_feature_pages[0])) {
- BTM_TRACE_WARNING("BTM Remote does not support 2-EDR eSCO");
+ BTM_TRACE_DEBUG("BTM Remote does not support 2-EDR eSCO");
temp_packet_types |=
(ESCO_PKT_TYPES_MASK_NO_2_EV3 | ESCO_PKT_TYPES_MASK_NO_2_EV5);
}
if (!HCI_EDR_ESCO_3MPS_SUPPORTED(p_acl->peer_lmp_feature_pages[0])) {
- BTM_TRACE_WARNING("BTM Remote does not support 3-EDR eSCO");
+ BTM_TRACE_DEBUG("BTM Remote does not support 3-EDR eSCO");
temp_packet_types |=
(ESCO_PKT_TYPES_MASK_NO_3_EV3 | ESCO_PKT_TYPES_MASK_NO_3_EV5);
}
@@ -405,15 +288,21 @@
/* Return error if no packet types left */
if (temp_packet_types == 0) {
- BTM_TRACE_ERROR("%s: SCO Conn (BR/EDR SC): No packet types available",
- __func__);
+ LOG(ERROR) << __func__
+ << ": SCO Conn (BR/EDR SC): No packet types available for "
+ "acl_handle "
+ << unsigned(acl_handle);
return (BTM_WRONG_MODE);
}
} else {
- BTM_TRACE_DEBUG(
- "%s: SCO Conn(BR/EDR SC):local or peer does not support BR/EDR SC",
- __func__);
+ LOG(WARNING) << __func__
+ << ": SCO Conn(BR/EDR SC):local or peer does not support "
+ "BR/EDR SC for acl_handle "
+ << unsigned(acl_handle);
}
+ } else {
+ LOG(ERROR) << __func__ << ": acl_index " << unsigned(acl_index)
+ << " out of range for acl_handle " << unsigned(acl_handle);
}
/* Save the previous types in case command fails */
@@ -426,26 +315,26 @@
/* Use the saved SCO routing */
p_setup->input_data_path = p_setup->output_data_path =
btm_cb.sco_cb.sco_route;
-
- BTM_TRACE_DEBUG(
- "%s: txbw 0x%x, rxbw 0x%x, "
- "lat 0x%x, retrans 0x%02x, pkt 0x%04x, path %u",
- __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
- p_setup->max_latency_ms, p_setup->retransmission_effort,
- p_setup->packet_types, p_setup->input_data_path);
-
+ LOG(INFO) << __func__ << std::hex << ": enhanced parameter list"
+ << " txbw=0x" << unsigned(p_setup->transmit_bandwidth)
+ << ", rxbw=0x" << unsigned(p_setup->receive_bandwidth)
+ << ", latency_ms=0x" << unsigned(p_setup->max_latency_ms)
+ << ", retransmit_effort=0x"
+ << unsigned(p_setup->retransmission_effort) << ", pkt_type=0x"
+ << unsigned(p_setup->packet_types) << ", path=0x"
+ << unsigned(p_setup->input_data_path);
btsnd_hcic_enhanced_set_up_synchronous_connection(acl_handle, p_setup);
p_setup->packet_types = saved_packet_types;
} else { /* Use older command */
uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup);
-
- BTM_TRACE_API(
- "%s: txbw 0x%x, rxbw 0x%x, "
- "lat 0x%x, voice 0x%x, retrans 0x%02x, pkt 0x%04x",
- __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
- p_setup->max_latency_ms, voice_content_format,
- p_setup->retransmission_effort, p_setup->packet_types);
-
+ LOG(INFO) << __func__ << std::hex << ": legacy parameter list"
+ << " txbw=0x" << unsigned(p_setup->transmit_bandwidth)
+ << ", rxbw=0x" << unsigned(p_setup->receive_bandwidth)
+ << ", latency_ms=0x" << unsigned(p_setup->max_latency_ms)
+ << ", retransmit_effort=0x"
+ << unsigned(p_setup->retransmission_effort)
+ << ", voice_content_format=0x" << unsigned(voice_content_format)
+ << ", pkt_type=0x" << unsigned(p_setup->packet_types);
btsnd_hcic_setup_esco_conn(
acl_handle, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
p_setup->max_latency_ms, voice_content_format,
@@ -550,27 +439,19 @@
uint16_t xx;
uint16_t acl_handle = 0;
tACL_CONN* p_acl;
-
-#if (BTM_SCO_WAKE_PARKED_LINK == TRUE)
- tBTM_PM_PWR_MD pm;
- tBTM_PM_STATE state;
-#else
- uint8_t mode;
-#endif // BTM_SCO_WAKE_PARKED_LINK
-
*p_sco_inx = BTM_INVALID_SCO_INDEX;
/* If originating, ensure that there is an ACL connection to the BD Address */
if (is_orig) {
if (!remote_bda) {
- BTM_TRACE_ERROR("%s: remote_bda is null", __func__);
+ LOG(ERROR) << __func__ << ": remote_bda is null";
return BTM_ILLEGAL_VALUE;
}
acl_handle = BTM_GetHCIConnHandle(*remote_bda, BT_TRANSPORT_BR_EDR);
if (acl_handle == 0xFFFF) {
- VLOG(2) << __func__ << ": cannot find ACL handle for remote device "
- << remote_bda;
+ LOG(ERROR) << __func__ << ": cannot find ACL handle for remote device "
+ << remote_bda;
return BTM_UNKNOWN_ADDR;
}
}
@@ -581,13 +462,20 @@
if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) ||
(p->state == SCO_ST_PEND_UNPARK)) &&
(p->esco.data.bd_addr == *remote_bda)) {
+ LOG(ERROR) << __func__ << ": a sco connection is already going on for "
+ << *remote_bda << ", at state " << unsigned(p->state);
return BTM_BUSY;
}
}
} else {
/* Support only 1 wildcard BD address at a time */
for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if ((p->state == SCO_ST_LISTENING) && (!p->rem_bd_known)) return BTM_BUSY;
+ if ((p->state == SCO_ST_LISTENING) && (!p->rem_bd_known)) {
+ LOG(ERROR)
+ << __func__
+ << ": remote_bda is null and not known and we are still listening";
+ return BTM_BUSY;
+ }
}
}
@@ -599,19 +487,24 @@
if (is_orig) {
/* can not create SCO link if in park mode */
#if (BTM_SCO_WAKE_PARKED_LINK == TRUE)
- if ((btm_read_power_mode_state(p->esco.data.bd_addr, &state) ==
- BTM_SUCCESS)) {
+ tBTM_PM_STATE state;
+ if ((btm_read_power_mode_state(*remote_bda, &state) == BTM_SUCCESS)) {
if (state == BTM_PM_ST_SNIFF || state == BTM_PM_ST_PARK ||
state == BTM_PM_ST_PENDING) {
- BTM_TRACE_DEBUG("%s In sniff, park or pend mode: %d", __func__,
- state);
- memset((void*)&pm, 0, sizeof(pm));
+ LOG(INFO) << __func__ << ": " << *remote_bda
+ << " in sniff, park or pending mode "
+ << unsigned(state);
+ tBTM_PM_PWR_MD pm = {};
pm.mode = BTM_PM_MD_ACTIVE;
BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, *remote_bda, &pm);
p->state = SCO_ST_PEND_UNPARK;
}
+ } else {
+ LOG(ERROR) << __func__ << ": failed to read power mode for "
+ << *remote_bda;
}
#else // BTM_SCO_WAKE_PARKED_LINK
+ uint8_t mode;
if ((BTM_ReadPowerMode(*remote_bda, &mode) == BTM_SUCCESS) &&
(mode == BTM_PM_MD_PARK))
return (BTM_WRONG_MODE);
@@ -661,22 +554,29 @@
acl_handle);
if ((btm_send_connect_request(acl_handle, p_setup)) !=
- BTM_CMD_STARTED)
+ BTM_CMD_STARTED) {
+ LOG(ERROR) << __func__ << ": failed to send connect request for "
+ << *remote_bda;
return (BTM_NO_RESOURCES);
+ }
p->state = SCO_ST_CONNECTING;
- } else
+ } else {
+ BTM_TRACE_API("%s:(e)SCO listening for ACL handle 0x%04x", __func__,
+ acl_handle);
p->state = SCO_ST_LISTENING;
+ }
}
*p_sco_inx = xx;
-
+ BTM_TRACE_API("%s: BTM_CreateSco succeeded", __func__);
return BTM_CMD_STARTED;
}
}
#endif
/* If here, all SCO blocks in use */
+ LOG(ERROR) << __func__ << ": all SCO control blocks are in use";
return BTM_NO_RESOURCES;
}
@@ -694,24 +594,22 @@
******************************************************************************/
void btm_sco_chk_pend_unpark(uint8_t hci_status, uint16_t hci_handle) {
#if (BTM_MAX_SCO_LINKS > 0)
- uint16_t xx;
- uint16_t acl_handle;
tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
-
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if ((p->state == SCO_ST_PEND_UNPARK) &&
- ((acl_handle = BTM_GetHCIConnHandle(
- p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle))
-
- {
- BTM_TRACE_API(
- "%s:(e)SCO Link for ACL "
- "handle 0x%04x, hci_status 0x%02x",
- __func__, acl_handle, hci_status);
-
- if ((btm_send_connect_request(acl_handle, &p->esco.setup)) ==
- BTM_CMD_STARTED)
+ for (uint16_t xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
+ uint16_t acl_handle =
+ BTM_GetHCIConnHandle(p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR);
+ if ((p->state == SCO_ST_PEND_UNPARK) && (acl_handle == hci_handle)) {
+ LOG(INFO) << __func__ << ": " << p->esco.data.bd_addr
+ << " unparked, sending connection request, acl_handle="
+ << unsigned(acl_handle)
+ << ", hci_status=" << unsigned(hci_status);
+ if (btm_send_connect_request(acl_handle, &p->esco.setup) ==
+ BTM_CMD_STARTED) {
p->state = SCO_ST_CONNECTING;
+ } else {
+ LOG(ERROR) << __func__ << ": failed to send connection request for "
+ << p->esco.data.bd_addr;
+ }
}
}
#endif // BTM_MAX_SCO_LINKS
@@ -788,7 +686,7 @@
*
* Function btm_sco_conn_req
*
- * Description This function is called by BTIF when an SCO connection
+ * Description This function is called by BTU HCIF when an SCO connection
* request is received from a remote.
*
* Returns void
@@ -799,15 +697,15 @@
#if (BTM_MAX_SCO_LINKS > 0)
tSCO_CB* p_sco = &btm_cb.sco_cb;
tSCO_CONN* p = &p_sco->sco_db[0];
- uint16_t xx;
- tBTM_ESCO_CONN_REQ_EVT_DATA evt_data;
+ tBTM_ESCO_CONN_REQ_EVT_DATA evt_data = {};
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
+ for (uint16_t sco_index = 0; sco_index < BTM_MAX_SCO_LINKS;
+ sco_index++, p++) {
/*
* If the sco state is in the SCO_ST_CONNECTING state, we still need
* to return accept sco to avoid race conditon for sco creation
*/
- int rem_bd_matches = p->rem_bd_known && p->esco.data.bd_addr == bda;
+ bool rem_bd_matches = p->rem_bd_known && p->esco.data.bd_addr == bda;
if (((p->state == SCO_ST_CONNECTING) && rem_bd_matches) ||
((p->state == SCO_ST_LISTENING) &&
(rem_bd_matches || !p->rem_bd_known))) {
@@ -829,18 +727,19 @@
||
(link_type == BTM_LINK_TYPE_SCO &&
!(p_sco->def_esco_parms.packet_types & BTM_SCO_LINK_ONLY_MASK))) {
- btm_esco_conn_rsp(xx, HCI_ERR_HOST_REJECT_RESOURCES, bda, NULL);
- } else /* Accept the request */
- {
- btm_esco_conn_rsp(xx, HCI_SUCCESS, bda, NULL);
+ btm_esco_conn_rsp(sco_index, HCI_ERR_HOST_REJECT_RESOURCES, bda,
+ nullptr);
+ } else {
+ /* Accept the request */
+ btm_esco_conn_rsp(sco_index, HCI_SUCCESS, bda, nullptr);
}
- } else /* Notify upper layer of connect indication */
- {
+ } else {
+ /* Notify upper layer of connect indication */
evt_data.bd_addr = bda;
memcpy(evt_data.dev_class, dev_class, DEV_CLASS_LEN);
evt_data.link_type = link_type;
- evt_data.sco_inx = xx;
- tBTM_ESCO_EVT_DATA btm_esco_evt_data;
+ evt_data.sco_inx = sco_index;
+ tBTM_ESCO_EVT_DATA btm_esco_evt_data = {};
btm_esco_evt_data.conn_evt = evt_data;
p->esco.p_esco_cback(BTM_ESCO_CONN_REQ_EVT, &btm_esco_evt_data);
}
@@ -852,8 +751,9 @@
/* TCS usage */
if (btm_cb.sco_cb.app_sco_ind_cb) {
/* Now, try to find an unused control block */
- for (xx = 0, p = &btm_cb.sco_cb.sco_db[0]; xx < BTM_MAX_SCO_LINKS;
- xx++, p++) {
+ uint16_t sco_index;
+ for (sco_index = 0, p = &btm_cb.sco_cb.sco_db[0];
+ sco_index < BTM_MAX_SCO_LINKS; sco_index++, p++) {
if (p->state == SCO_ST_UNUSED) {
p->is_orig = false;
p->state = SCO_ST_LISTENING;
@@ -864,18 +764,18 @@
break;
}
}
- if (xx < BTM_MAX_SCO_LINKS) {
- btm_cb.sco_cb.app_sco_ind_cb(xx);
+ if (sco_index < BTM_MAX_SCO_LINKS) {
+ btm_cb.sco_cb.app_sco_ind_cb(sco_index);
return;
}
}
#endif
/* If here, no one wants the SCO connection. Reject it */
- BTM_TRACE_WARNING(
- "btm_sco_conn_req: No one wants this SCO connection; rejecting it");
+ BTM_TRACE_WARNING("%s: rejecting SCO for %s", __func__,
+ bda.ToString().c_str());
btm_esco_conn_rsp(BTM_MAX_SCO_LINKS, HCI_ERR_HOST_REJECT_RESOURCES, bda,
- NULL);
+ nullptr);
}
/*******************************************************************************
@@ -894,7 +794,7 @@
tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
uint16_t xx;
bool spt = false;
- tBTM_CHG_ESCO_PARAMS parms;
+ tBTM_CHG_ESCO_PARAMS parms = {};
#endif
btm_cb.sco_cb.sco_disc_reason = hci_status;
diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc
index 60a3a17..b080901 100644
--- a/stack/btm/btm_sec.cc
+++ b/stack/btm/btm_sec.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,7 +58,6 @@
uint32_t mx_proto_id,
uint32_t mx_chan_id);
-static tBTM_STATUS btm_sec_execute_procedure(tBTM_SEC_DEV_REC* p_dev_rec);
static bool btm_sec_start_get_name(tBTM_SEC_DEV_REC* p_dev_rec);
static void btm_sec_start_authentication(tBTM_SEC_DEV_REC* p_dev_rec);
static void btm_sec_start_encryption(tBTM_SEC_DEV_REC* p_dev_rec);
@@ -223,7 +222,7 @@
* Returns true if registered OK, else false
*
******************************************************************************/
-bool BTM_SecRegister(tBTM_APPL_INFO* p_cb_info) {
+bool BTM_SecRegister(const tBTM_APPL_INFO* p_cb_info) {
BT_OCTET16 temp_value = {0};
BTM_TRACE_EVENT("%s application registered", __func__);
@@ -454,20 +453,8 @@
bool BTM_SetSecurityLevel(bool is_originator, const char* p_name,
uint8_t service_id, uint16_t sec_level, uint16_t psm,
uint32_t mx_proto_id, uint32_t mx_chan_id) {
-#if (L2CAP_UCD_INCLUDED == TRUE)
- CONNECTION_TYPE conn_type;
-
- if (is_originator)
- conn_type = CONN_ORIENT_ORIG;
- else
- conn_type = CONN_ORIENT_TERM;
-
- return (btm_sec_set_security_level(conn_type, p_name, service_id, sec_level,
- psm, mx_proto_id, mx_chan_id));
-#else
return (btm_sec_set_security_level(is_originator, p_name, service_id,
sec_level, psm, mx_proto_id, mx_chan_id));
-#endif
}
/*******************************************************************************
@@ -500,22 +487,7 @@
uint16_t first_unused_record = BTM_NO_AVAIL_SEC_SERVICES;
bool record_allocated = false;
bool is_originator;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- bool is_ucd;
-
- if (conn_type & CONNECTION_TYPE_ORIG_MASK)
- is_originator = true;
- else
- is_originator = false;
-
- if (conn_type & CONNECTION_TYPE_CONNLESS_MASK) {
- is_ucd = true;
- } else {
- is_ucd = false;
- }
-#else
is_originator = conn_type;
-#endif
BTM_TRACE_API("%s : sec: 0x%x", __func__, sec_level);
@@ -577,14 +549,6 @@
BTM_SEC_SERVICE_NAME_LEN + 1);
#endif
/* clear out the old setting, just in case it exists */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (is_ucd) {
- p_srec->ucd_security_flags &= ~(
- BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_ENCRYPT |
- BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_MITM | BTM_SEC_FORCE_MASTER |
- BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE);
- } else
-#endif
{
p_srec->security_flags &= ~(
BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_ENCRYPT |
@@ -610,12 +574,7 @@
/* outgoing connections usually set the security level right before
* the connection is initiated.
* set it to be the outgoing service */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (is_ucd == false)
-#endif
- {
btm_cb.p_out_serv = p_srec;
- }
} else {
p_srec->term_mx_chan_id = mx_chan_id;
#if BTM_SEC_SERVICE_NAME_LEN > 0
@@ -623,15 +582,6 @@
BTM_SEC_SERVICE_NAME_LEN + 1);
#endif
/* clear out the old setting, just in case it exists */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (is_ucd) {
- p_srec->ucd_security_flags &=
- ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT |
- BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_MITM | BTM_SEC_FORCE_MASTER |
- BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE |
- BTM_SEC_ATTEMPT_SLAVE | BTM_SEC_IN_MIN_16_DIGIT_PIN);
- } else
-#endif
{
p_srec->security_flags &=
~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT |
@@ -655,28 +605,6 @@
if (sec_level & BTM_SEC_IN_ENCRYPT) sec_level |= BTM_SEC_IN_AUTHENTICATE;
}
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (is_ucd) {
- p_srec->security_flags |= (uint16_t)(BTM_SEC_IN_USE);
- p_srec->ucd_security_flags |= (uint16_t)(sec_level | BTM_SEC_IN_USE);
- } else {
- p_srec->security_flags |= (uint16_t)(sec_level | BTM_SEC_IN_USE);
- }
-
- BTM_TRACE_API(
- "BTM_SEC_REG[%d]: id %d, conn_type 0x%x, psm 0x%04x, proto_id %d, "
- "chan_id %d",
- index, service_id, conn_type, psm, mx_proto_id, mx_chan_id);
-
- BTM_TRACE_API(
- " : security_flags: 0x%04x, ucd_security_flags: 0x%04x",
- p_srec->security_flags, p_srec->ucd_security_flags);
-
-#if BTM_SEC_SERVICE_NAME_LEN > 0
- BTM_TRACE_API(" : service name [%s] (up to %d chars saved)",
- p_name, BTM_SEC_SERVICE_NAME_LEN);
-#endif
-#else
p_srec->security_flags |= (uint16_t)(sec_level | BTM_SEC_IN_USE);
BTM_TRACE_API(
@@ -688,7 +616,6 @@
" : sec: 0x%x, service name [%s] (up to %d chars saved)",
p_srec->security_flags, p_name, BTM_SEC_SERVICE_NAME_LEN);
#endif
-#endif
return (record_allocated);
}
@@ -723,9 +650,6 @@
(!service_id || (service_id == p_srec->service_id))) {
BTM_TRACE_API("BTM_SEC_CLR[%d]: id %d", i, service_id);
p_srec->security_flags = 0;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- p_srec->ucd_security_flags = 0;
-#endif
num_freed++;
}
}
@@ -875,7 +799,7 @@
if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) &&
(p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE) &&
- (btm_cb.security_mode_changed == false)) {
+ (!btm_cb.security_mode_changed)) {
/* This is start of the dedicated bonding if local device is 2.0 */
btm_cb.pin_code_len = pin_len;
memcpy(btm_cb.pin_code, p_pin, pin_len);
@@ -948,7 +872,8 @@
tACL_CONN* p = btm_bda_to_acl(bd_addr, transport);
VLOG(1) << __func__ << " BDA: " << bd_addr;
- BTM_TRACE_DEBUG("btm_sec_bond_by_transport: Transport used %d", transport);
+ BTM_TRACE_DEBUG("%s: Transport used %d, bd_addr=%s", __func__, transport,
+ bd_addr.ToString().c_str());
/* Other security process is in progress */
if (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) {
@@ -1314,8 +1239,9 @@
tBTM_STATUS rc = 0;
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
- if (!p_dev_rec || (transport == BT_TRANSPORT_BR_EDR &&
- p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE) ||
+ if (!p_dev_rec ||
+ (transport == BT_TRANSPORT_BR_EDR &&
+ p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE) ||
(transport == BT_TRANSPORT_LE &&
p_dev_rec->ble_hci_handle == BTM_SEC_INVALID_HANDLE)) {
/* Connection should be up and runnning */
@@ -1360,9 +1286,9 @@
BTM_TRACE_API(
"Security Manager: BTM_SetEncryption Handle:%d State:%d Flags:0x%x "
- "Required:0x%x",
+ "Required:0x%x, p_dev_rec=%p, p_callback=%p",
p_dev_rec->hci_handle, p_dev_rec->sec_state, p_dev_rec->sec_flags,
- p_dev_rec->security_required);
+ p_dev_rec->security_required, p_dev_rec, p_callback);
if (transport == BT_TRANSPORT_LE) {
tACL_CONN* p = btm_bda_to_acl(bd_addr, transport);
@@ -1379,6 +1305,11 @@
if (rc != BTM_CMD_STARTED && rc != BTM_BUSY) {
if (p_callback) {
+ BTM_TRACE_DEBUG(
+ "%s: clearing p_callback=%p, p_dev_rec=%p, transport=%d, "
+ "bd_addr=%s",
+ __func__, p_callback, p_dev_rec, transport,
+ bd_addr.ToString().c_str());
p_dev_rec->p_callback = NULL;
(*p_callback)(&bd_addr, transport, p_dev_rec->p_ref_data, rc);
}
@@ -1949,7 +1880,7 @@
/* Only check if link key already exists */
if (!(p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)) return;
- if (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == true) {
+ if (btm_sec_is_upgrade_possible(p_dev_rec, is_originator)) {
BTM_TRACE_DEBUG("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags);
/* upgrade is possible: check if the application wants the upgrade.
* If the application is configured to use a global MITM flag,
@@ -2010,20 +1941,10 @@
BT_TRANSPORT_BR_EDR; /* should check PSM range in LE connection oriented
L2CAP connection */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (conn_type & CONNECTION_TYPE_ORIG_MASK)
- is_originator = true;
- else
- is_originator = false;
-
- BTM_TRACE_DEBUG("%s() conn_type: 0x%x, 0x%x", __func__, conn_type,
- p_ref_data);
-#else
is_originator = conn_type;
- BTM_TRACE_DEBUG("%s() is_originator:%d, 0x%x", __func__, is_originator,
- p_ref_data);
-#endif
+ BTM_TRACE_DEBUG("%s() is_originator:%d, 0x%x, psm=0x%04x", __func__,
+ is_originator, p_ref_data, psm);
/* Find or get oldest record */
p_dev_rec = btm_find_or_alloc_dev(bd_addr);
@@ -2047,68 +1968,11 @@
(*p_callback)(&bd_addr, transport, p_ref_data, BTM_SUCCESS_NO_SECURITY);
return (BTM_SUCCESS);
}
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (conn_type & CONNECTION_TYPE_CONNLESS_MASK) {
- if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
- security_required = btm_sec_set_serv_level4_flags(
- p_serv_rec->ucd_security_flags, is_originator);
- } else {
- security_required = p_serv_rec->ucd_security_flags;
- }
-
- rc = BTM_CMD_STARTED;
- if (is_originator) {
- if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) ==
- BTM_SEC_OUT_AUTHENTICATE) &&
- (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) ==
- (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) &&
- (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_FLAGS) &&
- (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED)))) {
- rc = BTM_SUCCESS;
- }
- } else {
- if (((security_required & BTM_SEC_IN_FLAGS) == 0) ||
- ((((security_required & BTM_SEC_IN_FLAGS) ==
- BTM_SEC_IN_AUTHENTICATE) &&
- (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
- ((((security_required & BTM_SEC_IN_FLAGS) ==
- (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) &&
- (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) ||
- ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_FLAGS) &&
- (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED)))) {
- // Check for 16 digits (or MITM)
- if (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == 0) ||
- (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) ==
- BTM_SEC_IN_MIN_16_DIGIT_PIN) &&
- btm_dev_16_digit_authenticated(p_dev_rec))) {
- rc = BTM_SUCCESS;
- }
- }
- }
-
- if ((rc == BTM_SUCCESS) && (security_required & BTM_SEC_MODE4_LEVEL4) &&
- (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- rc = BTM_CMD_STARTED;
- }
-
- if (rc == BTM_SUCCESS) {
- if (p_callback)
- (*p_callback)(&bd_addr, transport, (void*)p_ref_data, BTM_SUCCESS);
-
- return (BTM_SUCCESS);
- }
- } else
-#endif
- {
- if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
- security_required = btm_sec_set_serv_level4_flags(
- p_serv_rec->security_flags, is_originator);
- } else {
- security_required = p_serv_rec->security_flags;
- }
+ if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
+ security_required = btm_sec_set_serv_level4_flags(
+ p_serv_rec->security_flags, is_originator);
+ } else {
+ security_required = p_serv_rec->security_flags;
}
BTM_TRACE_DEBUG(
@@ -2151,7 +2015,7 @@
btm_cb.security_mode == BTM_SEC_MODE_LINK) ||
(BTM_SM4_KNOWN == p_dev_rec->sm4) ||
(BTM_SEC_IS_SM4(p_dev_rec->sm4) &&
- (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == false))) {
+ (!btm_sec_is_upgrade_possible(p_dev_rec, is_originator)))) {
/* legacy mode - local is legacy or local is lisbon/peer is legacy
* or SM4 with no possibility of link key upgrade */
if (is_originator) {
@@ -2258,22 +2122,9 @@
p_dev_rec->p_ref_data = p_ref_data;
p_dev_rec->is_originator = is_originator;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (conn_type & CONNECTION_TYPE_CONNLESS_MASK)
- p_dev_rec->is_ucd = true;
- else
- p_dev_rec->is_ucd = false;
-#endif
-
/* If there are multiple service records used through the same PSM */
/* leave security decision for the multiplexor on the top */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (((btm_sec_find_next_serv(p_serv_rec)) != NULL) &&
- (!(conn_type & CONNECTION_TYPE_CONNLESS_MASK))) /* if not UCD */
-#else
- if ((btm_sec_find_next_serv(p_serv_rec)) != NULL)
-#endif
- {
+ if ((btm_sec_find_next_serv(p_serv_rec)) != NULL) {
BTM_TRACE_DEBUG("no next_serv sm4:0x%x, chk:%d", p_dev_rec->sm4,
chk_acp_auth_done);
if (!BTM_SEC_IS_SM4(p_dev_rec->sm4)) {
@@ -2295,11 +2146,12 @@
* The layer above L2CAP needs to carry out the security requirement after
* L2CAP connect
* response is received */
- if (is_originator && ((btm_cb.security_mode == BTM_SEC_MODE_UNDEFINED ||
- btm_cb.security_mode == BTM_SEC_MODE_NONE ||
- btm_cb.security_mode == BTM_SEC_MODE_SERVICE ||
- btm_cb.security_mode == BTM_SEC_MODE_LINK) ||
- !BTM_SEC_IS_SM4(p_dev_rec->sm4)) &&
+ if (is_originator &&
+ ((btm_cb.security_mode == BTM_SEC_MODE_UNDEFINED ||
+ btm_cb.security_mode == BTM_SEC_MODE_NONE ||
+ btm_cb.security_mode == BTM_SEC_MODE_SERVICE ||
+ btm_cb.security_mode == BTM_SEC_MODE_LINK) ||
+ !BTM_SEC_IS_SM4(p_dev_rec->sm4)) &&
(psm >= 0x1001)) {
BTM_TRACE_EVENT(
"dynamic PSM:0x%x in legacy mode - postponed for upper layer", psm);
@@ -2379,6 +2231,8 @@
rc = btm_sec_execute_procedure(p_dev_rec);
if (rc != BTM_CMD_STARTED) {
+ BTM_TRACE_DEBUG("%s: p_dev_rec=%p, clearing callback. old p_callback=%p",
+ __func__, p_dev_rec, p_dev_rec->p_callback);
p_dev_rec->p_callback = NULL;
(*p_callback)(&bd_addr, transport, p_dev_rec->p_ref_data, (uint8_t)rc);
}
@@ -2466,7 +2320,7 @@
btm_cb.security_mode == BTM_SEC_MODE_LINK) ||
(BTM_SM4_KNOWN == p_dev_rec->sm4) ||
(BTM_SEC_IS_SM4(p_dev_rec->sm4) &&
- (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == false))) {
+ (!btm_sec_is_upgrade_possible(p_dev_rec, is_originator)))) {
/* legacy mode - local is legacy or local is lisbon/peer is legacy
* or SM4 with no possibility of link key upgrade */
if (is_originator) {
@@ -2898,6 +2752,9 @@
return;
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+
+ BTM_TRACE_DEBUG("%s: clearing callback. p_dev_rec=%p, p_callback=%p",
+ __func__, p_dev_rec, p_dev_rec->p_callback);
p_dev_rec->p_callback = NULL;
}
@@ -2922,9 +2779,8 @@
}
/* Make sure an L2cap link control block is available */
- if (!p_lcb &&
- (p_lcb = l2cu_allocate_lcb(p_dev_rec->bd_addr, true,
- BT_TRANSPORT_BR_EDR)) == NULL) {
+ if (!p_lcb && (p_lcb = l2cu_allocate_lcb(p_dev_rec->bd_addr, true,
+ BT_TRANSPORT_BR_EDR)) == NULL) {
LOG(WARNING) << "Security Manager: failed allocate LCB "
<< p_dev_rec->bd_addr;
@@ -2934,7 +2790,7 @@
/* set up the control block to indicated dedicated bonding */
btm_cb.pairing_flags |= BTM_PAIR_FLAGS_DISC_WHEN_DONE;
- if (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == false) {
+ if (!l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR)) {
LOG(WARNING) << "Security Manager: failed create allocate LCB "
<< p_dev_rec->bd_addr;
@@ -3599,8 +3455,7 @@
}
/* else BTM_NOT_AUTHORIZED means when the app wants to reject the req
* right now */
- } else if ((event == BTM_SP_CFM_REQ_EVT) &&
- (evt_data.cfm_req.just_works == true)) {
+ } else if ((event == BTM_SP_CFM_REQ_EVT) && (evt_data.cfm_req.just_works)) {
/* automatically reply with just works if no sp_cback */
status = BTM_SUCCESS;
}
@@ -3913,14 +3768,14 @@
bool are_bonding = false;
if (p_dev_rec) {
- VLOG(2) << __func__ << "Security Manager: in state: "
+ VLOG(2) << __func__ << ": Security Manager: in state: "
<< btm_pair_state_descr(btm_cb.pairing_state)
<< " handle:" << handle << " status:" << status
<< "dev->sec_state:" << p_dev_rec->sec_state
<< " bda:" << p_dev_rec->bd_addr
<< "RName:" << p_dev_rec->sec_bd_name;
} else {
- VLOG(2) << __func__ << "Security Manager: in state: "
+ VLOG(2) << __func__ << ": Security Manager: in state: "
<< btm_pair_state_descr(btm_cb.pairing_state)
<< " handle:" << handle << " status:" << status;
}
@@ -4187,6 +4042,8 @@
if (p_dev_rec->sec_state != BTM_SEC_STATE_ENCRYPTING) {
if (BTM_SEC_STATE_DELAY_FOR_ENC == p_dev_rec->sec_state) {
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+ BTM_TRACE_DEBUG("%s: clearing callback. p_dev_rec=%p, p_callback=%p",
+ __func__, p_dev_rec, p_dev_rec->p_callback);
p_dev_rec->p_callback = NULL;
l2cu_resubmit_pending_sec_req(&p_dev_rec->bd_addr);
}
@@ -4242,7 +4099,7 @@
* Function btm_sec_connected
*
* Description This function is when a connection to the peer device is
- * establsihed
+ * established
*
* Returns void
*
@@ -4258,16 +4115,16 @@
btm_acl_resubmit_page();
if (p_dev_rec) {
- VLOG(2) << __func__ << "Security Manager: in state: "
+ VLOG(2) << __func__ << ": Security Manager: in state: "
<< btm_pair_state_descr(btm_cb.pairing_state)
- << " handle:" << handle << " status:" << status
- << "enc_mode:" << enc_mode << " bda:" << bda
- << "RName:" << p_dev_rec->sec_bd_name;
+ << " handle:" << handle << " status:" << loghex(status)
+ << " enc_mode:" << loghex(enc_mode) << " bda:" << bda
+ << " RName:" << p_dev_rec->sec_bd_name;
} else {
- VLOG(2) << __func__ << "Security Manager: in state: "
+ VLOG(2) << __func__ << ": Security Manager: in state: "
<< btm_pair_state_descr(btm_cb.pairing_state)
- << " handle:" << handle << " status:" << status
- << "enc_mode:" << enc_mode << " bda:" << bda;
+ << " handle:" << handle << " status:" << loghex(status)
+ << " enc_mode:" << loghex(enc_mode) << " bda:" << bda;
}
if (!p_dev_rec) {
@@ -4438,6 +4295,15 @@
}
}
+ if (btm_cb.pairing_bda != bda) {
+ /* Don't callback unless this Connection-Complete-failure event has the
+ * same mac address as the bonding device */
+ VLOG(1) << __func__
+ << ": Different mac addresses: pairing_bda=" << btm_cb.pairing_bda
+ << ", bda=" << bda << ", do not callback";
+ return;
+ }
+
if (status == HCI_ERR_CONNECTION_TOUT ||
status == HCI_ERR_LMP_RESPONSE_TIMEOUT ||
status == HCI_ERR_UNSPECIFIED || status == HCI_ERR_PAGE_TIMEOUT)
@@ -4635,6 +4501,13 @@
(*btm_cb.api.p_auth_complete_callback)(p_dev_rec->bd_addr,
p_dev_rec->dev_class,
p_dev_rec->sec_bd_name, result);
+
+ // |btm_cb.api.p_auth_complete_callback| may cause |p_dev_rec| to be
+ // deallocated.
+ p_dev_rec = btm_find_dev_by_handle(handle);
+ if (!p_dev_rec) {
+ return;
+ }
}
}
@@ -4673,6 +4546,8 @@
/* if security is pending, send callback to clean up the security state */
if (p_callback) {
+ BTM_TRACE_DEBUG("%s: clearing callback. p_dev_rec=%p, p_callback=%p",
+ __func__, p_dev_rec, p_dev_rec->p_callback);
p_dev_rec->p_callback =
NULL; /* when the peer device time out the authentication before
we do, this call back must be reset here */
@@ -5037,7 +4912,8 @@
/* If pairing disabled OR (no PIN callback and not bonding) */
/* OR we could not allocate entry in the database reject pairing request */
else if (
- p_cb->pairing_disabled || (p_cb->api.p_pin_callback == NULL)
+ p_cb->pairing_disabled ||
+ (p_cb->api.p_pin_callback == NULL)
/* OR Microsoft keyboard can for some reason try to establish connection
*/
@@ -5137,7 +5013,7 @@
* BTM_NO_RESOURCES - permission declined
*
******************************************************************************/
-static tBTM_STATUS btm_sec_execute_procedure(tBTM_SEC_DEV_REC* p_dev_rec) {
+tBTM_STATUS btm_sec_execute_procedure(tBTM_SEC_DEV_REC* p_dev_rec) {
BTM_TRACE_EVENT(
"btm_sec_execute_procedure: Required:0x%x Flags:0x%x State:%d",
p_dev_rec->security_required, p_dev_rec->sec_flags, p_dev_rec->sec_state);
@@ -5173,12 +5049,6 @@
* authenticated connections, hence we cannot distinguish here.
*/
-#if (L2CAP_UCD_INCLUDED == TRUE)
- /* if incoming UCD packet, discard it */
- if (!p_dev_rec->is_originator && (p_dev_rec->is_ucd == true))
- return (BTM_FAILED_ON_SECURITY);
-#endif
-
BTM_TRACE_EVENT("Security Manager: Start authentication");
/*
@@ -5213,11 +5083,6 @@
(!p_dev_rec->is_originator &&
(p_dev_rec->security_required & BTM_SEC_IN_ENCRYPT))) &&
(p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)) {
-#if (L2CAP_UCD_INCLUDED == TRUE)
- /* if incoming UCD packet, discard it */
- if (!p_dev_rec->is_originator && (p_dev_rec->is_ucd == true))
- return (BTM_FAILED_ON_SECURITY);
-#endif
BTM_TRACE_EVENT("Security Manager: Start encryption");
@@ -5244,11 +5109,10 @@
"service id:%d, is trusted:%d", p_dev_rec->p_cur_service->service_id,
(BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask,
p_dev_rec->p_cur_service->service_id)));
- if ((btm_sec_are_all_trusted(p_dev_rec->trusted_mask) == false) &&
+ if ((!btm_sec_are_all_trusted(p_dev_rec->trusted_mask)) &&
(p_dev_rec->p_cur_service->service_id < BTM_SEC_MAX_SERVICES) &&
- (BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask,
- p_dev_rec->p_cur_service->service_id) ==
- false)) {
+ (!BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask,
+ p_dev_rec->p_cur_service->service_id))) {
BTM_TRACE_EVENT("Security Manager: Start authorization");
return (btm_sec_start_authorization(p_dev_rec));
}
@@ -5414,17 +5278,7 @@
uint16_t psm) {
tBTM_SEC_SERV_REC* p_serv_rec = &btm_cb.sec_serv_rec[0];
int i;
- bool is_originator;
-
-#if (L2CAP_UCD_INCLUDED == TRUE)
-
- if (conn_type & CONNECTION_TYPE_ORIG_MASK)
- is_originator = true;
- else
- is_originator = false;
-#else
- is_originator = conn_type;
-#endif
+ bool is_originator = conn_type;
if (is_originator && btm_cb.p_out_serv && btm_cb.p_out_serv->psm == psm) {
/* If this is outgoing connection and the PSM matches p_out_serv,
@@ -5530,11 +5384,11 @@
/*******************************************************************************
*
- * Function btm_sec_link_key_request
+ * Function btm_send_link_key_notif
*
- * Description This function is called when controller requests link key
+ * Description Call the link key callback.
*
- * Returns Pointer to the record or NULL
+ * Returns void
*
******************************************************************************/
static void btm_send_link_key_notif(tBTM_SEC_DEV_REC* p_dev_rec) {
@@ -5705,6 +5559,10 @@
bool is_le_transport) {
tBTM_SEC_CALLBACK* p_callback = p_dev_rec->p_callback;
+ BTM_TRACE_DEBUG("%s: p_callback=%p, is_le_transport=%d, res=%d, p_dev_rec=%p",
+ __func__, p_dev_rec->p_callback, is_le_transport, res,
+ p_dev_rec);
+
if (p_dev_rec->p_callback) {
p_dev_rec->p_callback = NULL;
@@ -5766,7 +5624,7 @@
"0x%02x",
__func__, major, minor);
- if (btm_cb.security_mode_changed == false) {
+ if (!btm_cb.security_mode_changed) {
btm_cb.security_mode_changed = true;
#ifdef APPL_AUTH_WRITE_EXCEPTION
if (!(APPL_AUTH_WRITE_EXCEPTION)(p_dev_rec->bd_addr))
diff --git a/stack/btu/btu_hcif.cc b/stack/btu/btu_hcif.cc
index ee40445..eac71a6 100644
--- a/stack/btu/btu_hcif.cc
+++ b/stack/btu/btu_hcif.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -588,6 +588,13 @@
handle = HCID_GET_HANDLE(handle);
+ if (status != HCI_SUCCESS) {
+ HCI_TRACE_DEBUG(
+ "%s: Connection failed: status=%d, handle=%d, link_type=%d, "
+ "enc_mode=%d",
+ __func__, status, handle, link_type, enc_mode);
+ }
+
if (link_type == HCI_LINK_TYPE_ACL) {
btm_sec_connected(bda, handle, status, enc_mode);
@@ -652,6 +659,13 @@
handle = HCID_GET_HANDLE(handle);
+ if ((reason != HCI_ERR_CONN_CAUSE_LOCAL_HOST) &&
+ (reason != HCI_ERR_PEER_USER)) {
+ /* Uncommon disconnection reasons */
+ HCI_TRACE_DEBUG("%s: Got Disconn Complete Event: reason=%d, handle=%d",
+ __func__, reason, handle);
+ }
+
#if (BTM_SCO_INCLUDED == TRUE)
/* If L2CAP doesn't know about it, send it to SCO */
if (!l2c_link_hci_disc_comp(handle, reason)) btm_sco_removed(handle, reason);
@@ -954,7 +968,13 @@
break;
case HCI_BLE_CREATE_LL_CONN:
- btm_ble_create_ll_conn_complete(*p);
+ case HCI_LE_EXTENDED_CREATE_CONNECTION:
+ // No command complete event for those commands according to spec
+ LOG(ERROR) << "No command complete expected, but received!";
+ break;
+
+ case HCI_BLE_CREATE_CONN_CANCEL:
+ btm_ble_create_conn_cancel_complete(p);
break;
case HCI_BLE_TRANSMITTER_TEST:
@@ -987,7 +1007,7 @@
#endif
default:
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC)
- btm_vsc_complete(p, opcode, evt_len, (tBTM_CMPL_CB*)p_cplt_cback);
+ btm_vsc_complete(p, opcode, evt_len, (tBTM_VSC_CMPL_CB*)p_cplt_cback);
break;
}
}
@@ -1129,6 +1149,7 @@
break;
case HCI_BLE_CREATE_LL_CONN:
+ case HCI_LE_EXTENDED_CREATE_CONNECTION:
btm_ble_create_ll_conn_complete(status);
break;
@@ -1160,14 +1181,14 @@
default:
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC)
btm_vsc_complete(&status, opcode, 1,
- (tBTM_CMPL_CB*)p_vsc_status_cback);
+ (tBTM_VSC_CMPL_CB*)p_vsc_status_cback);
break;
}
} else {
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC)
btm_vsc_complete(&status, opcode, 1,
- (tBTM_CMPL_CB*)p_vsc_status_cback);
+ (tBTM_VSC_CMPL_CB*)p_vsc_status_cback);
}
}
}
diff --git a/stack/btu/btu_init.cc b/stack/btu/btu_init.cc
index e383fd3..cad79df 100644
--- a/stack/btu/btu_init.cc
+++ b/stack/btu/btu_init.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2000-2012 Broadcom Corporation
+ * Copyright 2000-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,11 +87,13 @@
*****************************************************************************/
void btu_free_core(void) {
/* Free the mandatory core stack components */
+ gatt_free();
+
l2c_free();
sdp_free();
- gatt_free();
+ btm_free();
}
/*****************************************************************************
diff --git a/stack/btu/btu_task.cc b/stack/btu/btu_task.cc
index c0f374d..7d2527a 100644
--- a/stack/btu/btu_task.cc
+++ b/stack/btu/btu_task.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/gap/gap_ble.cc b/stack/gap/gap_ble.cc
index 2247a14..cce62d4 100644
--- a/stack/gap/gap_ble.cc
+++ b/stack/gap/gap_ble.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
#include "gatt_api.h"
using base::StringPrintf;
+using bluetooth::Uuid;
namespace {
@@ -122,7 +123,7 @@
for (const tGAP_ATTR& db_attr : gatt_attr) {
const tGAP_BLE_ATTR_VALUE& attr_value = db_attr.attr_value;
if (handle == db_attr.handle) {
- if (db_attr.uuid != GATT_UUID_GAP_DEVICE_NAME && is_long == true)
+ if (db_attr.uuid != GATT_UUID_GAP_DEVICE_NAME && is_long)
return GATT_NOT_LONG;
switch (db_attr.uuid) {
@@ -246,8 +247,7 @@
tGATT_READ_PARAM param;
memset(¶m, 0, sizeof(tGATT_READ_PARAM));
- param.service.uuid.len = LEN_UUID_16;
- param.service.uuid.uu.uuid16 = uuid;
+ param.service.uuid = Uuid::From16Bit(uuid);
param.service.s_handle = 1;
param.service.e_handle = 0xFFFF;
param.service.auth_req = 0;
@@ -393,23 +393,22 @@
*
******************************************************************************/
void gap_attr_db_init(void) {
- tBT_UUID app_uuid = {LEN_UUID_128, {0}};
uint16_t service_handle;
/* Fill our internal UUID with a fixed pattern 0x82 */
- memset(&app_uuid.uu.uuid128, 0x82, LEN_UUID_128);
+ std::array<uint8_t, Uuid::kNumBytes128> tmp;
+ tmp.fill(0x82);
+ Uuid app_uuid = Uuid::From128BitBE(tmp);
gatt_attr.fill({});
- gatt_if = GATT_Register(&app_uuid, &gap_cback);
+ gatt_if = GATT_Register(app_uuid, &gap_cback);
GATT_StartIf(gatt_if);
- bt_uuid_t svc_uuid, name_uuid, icon_uuid, pref_uuid, addr_res_uuid;
- uuid_128_from_16(&svc_uuid, UUID_SERVCLASS_GAP_SERVER);
- uuid_128_from_16(&name_uuid, GATT_UUID_GAP_DEVICE_NAME);
- uuid_128_from_16(&icon_uuid, GATT_UUID_GAP_ICON);
- uuid_128_from_16(&pref_uuid, GATT_UUID_GAP_PREF_CONN_PARAM);
- uuid_128_from_16(&addr_res_uuid, GATT_UUID_GAP_CENTRAL_ADDR_RESOL);
+ Uuid svc_uuid = Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER);
+ Uuid name_uuid = Uuid::From16Bit(GATT_UUID_GAP_DEVICE_NAME);
+ Uuid icon_uuid = Uuid::From16Bit(GATT_UUID_GAP_ICON);
+ Uuid addr_res_uuid = Uuid::From16Bit(GATT_UUID_GAP_CENTRAL_ADDR_RESOL);
btgatt_db_element_t service[] = {
{.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = svc_uuid},
@@ -428,7 +427,7 @@
#if (BTM_PERIPHERAL_ENABLED == TRUE) /* Only needed for peripheral testing */
,
{.type = BTGATT_DB_CHARACTERISTIC,
- .uuid = pref_uuid,
+ .uuid = Uuid::From16Bit(GATT_UUID_GAP_PREF_CONN_PARAM),
.properties = GATT_CHAR_PROP_BIT_READ,
.permissions = GATT_PERM_READ}
#endif
diff --git a/stack/gap/gap_conn.cc b/stack/gap/gap_conn.cc
index 7d75986..72183bb 100644
--- a/stack/gap/gap_conn.cc
+++ b/stack/gap/gap_conn.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
#include "bt_utils.h"
#include "btm_int.h"
#include "btu.h"
+#include "device/include/controller.h"
#include "gap_api.h"
#include "l2c_int.h"
#include "l2cdefs.h"
@@ -92,6 +93,9 @@
static void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg);
static void gap_congestion_ind(uint16_t lcid, bool is_congested);
static void gap_tx_complete_ind(uint16_t l2cap_cid, uint16_t sdu_sent);
+static void gap_credits_received_cb(uint16_t l2cap_cid,
+ uint16_t credits_received,
+ uint16_t credit_count);
static tGAP_CCB* gap_find_ccb_by_cid(uint16_t cid);
static tGAP_CCB* gap_find_ccb_by_handle(uint16_t handle);
@@ -122,6 +126,7 @@
conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind;
conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
conn.reg_info.pL2CA_TxComplete_Cb = gap_tx_complete_ind;
+ conn.reg_info.pL2CA_CreditsReceived_Cb = gap_credits_received_cb;
}
/*******************************************************************************
@@ -143,6 +148,7 @@
* remote BD Address, then NULL should be passed.
*
* psm - the PSM used for the connection
+ * le_mps - Maximum PDU Size for LE CoC
*
* p_config - Optional pointer to configuration structure.
* If NULL, the default GAP configuration will
@@ -161,9 +167,10 @@
******************************************************************************/
uint16_t GAP_ConnOpen(const char* p_serv_name, uint8_t service_id,
bool is_server, const RawAddress* p_rem_bda, uint16_t psm,
- tL2CAP_CFG_INFO* p_cfg, tL2CAP_ERTM_INFO* ertm_info,
- uint16_t security, uint8_t chan_mode_mask,
- tGAP_CONN_CALLBACK* p_cb, tBT_TRANSPORT transport) {
+ uint16_t le_mps, tL2CAP_CFG_INFO* p_cfg,
+ tL2CAP_ERTM_INFO* ertm_info, uint16_t security,
+ uint8_t chan_mode_mask, tGAP_CONN_CALLBACK* p_cb,
+ tBT_TRANSPORT transport) {
tGAP_CCB* p_ccb;
uint16_t cid;
@@ -203,9 +210,19 @@
/* Configure L2CAP COC, if transport is LE */
if (transport == BT_TRANSPORT_LE) {
- p_ccb->local_coc_cfg.credits = L2CAP_LE_DEFAULT_CREDIT;
+ p_ccb->local_coc_cfg.credits = L2CAP_LE_CREDIT_DEFAULT;
p_ccb->local_coc_cfg.mtu = p_cfg->mtu;
- p_ccb->local_coc_cfg.mps = L2CAP_LE_DEFAULT_MPS;
+
+ uint16_t max_mps = controller_get_interface()->get_acl_data_size_ble();
+ if (le_mps > max_mps) {
+ LOG(INFO) << "Limiting MPS to one buffer size - " << max_mps;
+ le_mps = max_mps;
+ }
+ p_ccb->local_coc_cfg.mps = le_mps;
+
+ VLOG(2) << __func__ << ": credits=" << p_ccb->local_coc_cfg.credits
+ << ", mps=" << p_ccb->local_coc_cfg.mps
+ << ", mtu=" << p_ccb->local_coc_cfg.mtu;
}
p_ccb->p_callback = p_cb;
@@ -391,8 +408,9 @@
mutex_global_unlock();
- DVLOG(1) << StringPrintf("GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
- p_ccb->rx_queue_size, *p_len);
+ DVLOG(1) << StringPrintf(
+ "GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
+ p_ccb->rx_queue_size, *p_len);
return (BT_PASS);
}
@@ -423,8 +441,8 @@
} else
rc = GAP_INVALID_HANDLE;
- DVLOG(1) << StringPrintf("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d", rc,
- *p_rx_queue_count);
+ DVLOG(1) << StringPrintf("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
+ rc, *p_rx_queue_count);
return (rc);
}
@@ -463,6 +481,25 @@
}
}
+/* Try to write the queued data to l2ca. Return true on success, or if queue is
+ * congested. False if error occured when writing. */
+static bool gap_try_write_queued_data(tGAP_CCB* p_ccb) {
+ if (p_ccb->is_congested) return true;
+
+ /* Send the buffer through L2CAP */
+ BT_HDR* p_buf;
+ while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) {
+ uint8_t status = L2CA_DATA_WRITE(p_ccb->connection_id, p_buf);
+
+ if (status == L2CAP_DW_CONGESTED) {
+ p_ccb->is_congested = true;
+ return true;
+ } else if (status != L2CAP_DW_SUCCESS)
+ return false;
+ }
+ return true;
+}
+
/*******************************************************************************
*
* Function GAP_ConnWriteData
@@ -471,9 +508,8 @@
* to send data to the connection.
*
* Parameters: handle - Handle of the connection returned in the Open
- * p_data - Data area
- * max_len - Byte count requested
- * p_len - Byte count received
+ * msg - pointer to single SDU to send. This function
+ * will take ownership of it.
*
* Returns BT_PASS - data read
* GAP_ERR_BAD_HANDLE - invalid handle
@@ -481,54 +517,30 @@
* GAP_CONGESTION - system is congested
*
******************************************************************************/
-uint16_t GAP_ConnWriteData(uint16_t gap_handle, uint8_t* p_data,
- uint16_t max_len, uint16_t* p_len) {
+uint16_t GAP_ConnWriteData(uint16_t gap_handle, BT_HDR* msg) {
tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
- BT_HDR* p_buf;
- *p_len = 0;
-
- if (!p_ccb) return (GAP_ERR_BAD_HANDLE);
-
- if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) return (GAP_ERR_BAD_STATE);
-
- while (max_len) {
- if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
- p_buf = (BT_HDR*)osi_malloc(L2CAP_FCR_ERTM_BUF_SIZE);
- else
- p_buf = (BT_HDR*)osi_malloc(GAP_DATA_BUF_SIZE);
-
- p_buf->offset = L2CAP_MIN_OFFSET;
- p_buf->len =
- (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len;
- p_buf->event = BT_EVT_TO_BTU_SP_DATA;
-
- memcpy((uint8_t*)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
-
- *p_len += p_buf->len;
- max_len -= p_buf->len;
- p_data += p_buf->len;
-
- DVLOG(1) << StringPrintf("GAP_WriteData %d bytes", p_buf->len);
-
- fixed_queue_enqueue(p_ccb->tx_queue, p_buf);
+ if (!p_ccb) {
+ osi_free(msg);
+ return GAP_ERR_BAD_HANDLE;
}
- if (p_ccb->is_congested) {
- return (BT_PASS);
+ if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) {
+ osi_free(msg);
+ return GAP_ERR_BAD_STATE;
}
- /* Send the buffer through L2CAP */
- while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) {
- uint8_t status = L2CA_DATA_WRITE(p_ccb->connection_id, p_buf);
-
- if (status == L2CAP_DW_CONGESTED) {
- p_ccb->is_congested = true;
- break;
- } else if (status != L2CAP_DW_SUCCESS)
- return (GAP_ERR_BAD_STATE);
+ if (msg->len > p_ccb->rem_mtu_size) {
+ osi_free(msg);
+ return GAP_ERR_ILL_PARM;
}
+ DVLOG(1) << StringPrintf("GAP_WriteData %d bytes", msg->len);
+
+ fixed_queue_enqueue(p_ccb->tx_queue, msg);
+
+ if (!gap_try_write_queued_data(p_ccb)) return GAP_ERR_BAD_STATE;
+
return (BT_PASS);
}
@@ -678,10 +690,20 @@
if ((p_ccb->con_state == GAP_CCB_STATE_CONNECTED) && (sdu_sent == 0xFFFF)) {
DVLOG(1) << StringPrintf("%s: GAP_EVT_TX_EMPTY", __func__);
- p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_TX_EMPTY);
+ p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_TX_EMPTY, nullptr);
}
}
+void gap_credits_received_cb(uint16_t l2cap_cid, uint16_t credits_received,
+ uint16_t credit_count) {
+ tGAP_CCB* p_ccb = gap_find_ccb_by_cid(l2cap_cid);
+ if (!p_ccb) return;
+
+ tGAP_CB_DATA data{.coc_credits = {.credits_received = credits_received,
+ .credit_count = credit_count}};
+ p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_LE_COC_CREDITS, &data);
+}
+
/*******************************************************************************
*
* Function gap_connect_ind
@@ -701,8 +723,7 @@
/* See if we have a CCB listening for the connection */
for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING) && (p_ccb->psm == psm) &&
- ((p_ccb->rem_addr_specified == false) ||
- (bd_addr == p_ccb->rem_dev_address)))
+ (!p_ccb->rem_addr_specified || (bd_addr == p_ccb->rem_dev_address)))
break;
}
@@ -745,7 +766,7 @@
}
DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x",
- p_ccb->connection_id);
+ p_ccb->connection_id);
/* Send a Configuration Request. */
if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
@@ -768,7 +789,7 @@
if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE) {
p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
- p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_OPENED);
+ p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_OPENED, nullptr);
}
}
@@ -850,7 +871,7 @@
} else {
/* Tell the user if he has a callback */
if (p_ccb->p_callback)
- (*p_ccb->p_callback)(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+ (*p_ccb->p_callback)(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
gap_release_ccb(p_ccb);
}
@@ -927,7 +948,7 @@
gap_checks_con_flags(p_ccb);
} else {
- p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+ p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
gap_release_ccb(p_ccb);
}
}
@@ -953,7 +974,7 @@
if (ack_needed) L2CA_DISCONNECT_RSP(l2cap_cid);
- p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+ p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
gap_release_ccb(p_ccb);
}
@@ -985,7 +1006,7 @@
p_ccb->rx_queue_size, p_msg->len);
*/
- p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL);
+ p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL, nullptr);
} else {
osi_free(p_msg);
}
@@ -1000,35 +1021,20 @@
*
******************************************************************************/
static void gap_congestion_ind(uint16_t lcid, bool is_congested) {
- tGAP_CCB* p_ccb;
- uint16_t event;
- BT_HDR* p_buf;
- uint8_t status;
-
DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
- is_congested, lcid);
+ is_congested, lcid);
- /* Find CCB based on CID */
- p_ccb = gap_find_ccb_by_cid(lcid);
- if (p_ccb == NULL) return;
+ tGAP_CCB* p_ccb = gap_find_ccb_by_cid(lcid); /* Find CCB based on CID */
+ if (!p_ccb) return;
p_ccb->is_congested = is_congested;
- event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED;
- p_ccb->p_callback(p_ccb->gap_handle, event);
+ p_ccb->p_callback(
+ p_ccb->gap_handle,
+ (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED,
+ nullptr);
- if (!is_congested) {
- while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) !=
- NULL) {
- status = L2CA_DATA_WRITE(p_ccb->connection_id, p_buf);
-
- if (status == L2CAP_DW_CONGESTED) {
- p_ccb->is_congested = true;
- break;
- } else if (status != L2CAP_DW_SUCCESS)
- break;
- }
- }
+ gap_try_write_queued_data(p_ccb);
}
/*******************************************************************************
@@ -1142,7 +1148,7 @@
if ((p_ccb_local->con_state != GAP_CCB_STATE_IDLE) &&
(p_ccb_local->psm == p_ccb->psm)) {
DVLOG(1) << __func__ << " : " << +p_ccb_local->psm
- << " PSM is still in use, do not deregister";
+ << " PSM is still in use, do not deregister";
return;
}
}
diff --git a/stack/gatt/att_protocol.cc b/stack/gatt/att_protocol.cc
index 82fa5a3..142216c 100644
--- a/stack/gatt/att_protocol.cc
+++ b/stack/gatt/att_protocol.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2014 Broadcom Corporation
+ * Copyright 2008-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
#define GATT_START_END_HANDLE_SIZE 4
using base::StringPrintf;
+using bluetooth::Uuid;
/**********************************************************************
* ATT protocl message building utility *
**********************************************************************/
@@ -124,9 +125,9 @@
*
******************************************************************************/
BT_HDR* attp_build_browse_cmd(uint8_t op_code, uint16_t s_hdl, uint16_t e_hdl,
- tBT_UUID uuid) {
+ const bluetooth::Uuid& uuid) {
const size_t payload_size =
- (GATT_OP_CODE_SIZE) + (GATT_START_END_HANDLE_SIZE) + (LEN_UUID_128);
+ (GATT_OP_CODE_SIZE) + (GATT_START_END_HANDLE_SIZE) + (Uuid::kNumBytes128);
BT_HDR* p_buf =
(BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
diff --git a/stack/gatt/gatt_api.cc b/stack/gatt/gatt_api.cc
index c77a4c5..b983318 100644
--- a/stack/gatt/gatt_api.cc
+++ b/stack/gatt/gatt_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
******************************************************************************/
#include "bt_target.h"
+#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>
#include <stdio.h>
#include <string.h>
@@ -34,6 +35,7 @@
#include "l2c_api.h"
using base::StringPrintf;
+using bluetooth::Uuid;
/**
* Add an service handle range to the list in decending order of the start
@@ -95,53 +97,6 @@
return status;
}
-static uint8_t BASE_UUID[16] = {0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-static int uuidType(unsigned char* p_uuid) {
- if (memcmp(p_uuid, BASE_UUID, 12) != 0) return LEN_UUID_128;
- if (memcmp(p_uuid + 14, BASE_UUID + 14, 2) != 0) return LEN_UUID_32;
-
- return LEN_UUID_16;
-}
-
-/*******************************************************************************
- * BTIF -> BTA conversion functions
- ******************************************************************************/
-
-static void btif_to_bta_uuid(tBT_UUID* p_dest, bt_uuid_t* p_src) {
- char* p_byte = (char*)p_src;
- int i = 0;
-
- p_dest->len = uuidType(p_src->uu);
-
- switch (p_dest->len) {
- case LEN_UUID_16:
- p_dest->uu.uuid16 = (p_src->uu[13] << 8) + p_src->uu[12];
- break;
-
- case LEN_UUID_32:
- p_dest->uu.uuid32 = (p_src->uu[15] << 24) + (p_src->uu[14] << 16) +
- (p_src->uu[13] << 8) + p_src->uu[12];
- break;
-
- case LEN_UUID_128:
- for (i = 0; i != 16; ++i) p_dest->uu.uuid128[i] = p_byte[i];
- break;
-
- default:
- LOG(ERROR) << __func__ << ": Unknown UUID length %d!" << +p_dest->len;
- break;
- }
-}
-
-void uuid_128_from_16(bt_uuid_t* uuid, uint16_t uuid16) {
- memcpy(uuid, &BASE_UUID, sizeof(bt_uuid_t));
-
- uuid->uu[13] = (uint8_t)((0xFF00 & uuid16) >> 8);
- uuid->uu[12] = (uint8_t)(0x00FF & uuid16);
-}
-
static uint16_t compute_service_size(btgatt_db_element_t* service, int count) {
int db_size = 0;
btgatt_db_element_t* el = service;
@@ -160,22 +115,23 @@
return db_size;
}
-static bool is_gatt_attr_type(const tBT_UUID& uuid) {
- if (uuid.len == LEN_UUID_16 && (uuid.uu.uuid16 == GATT_UUID_PRI_SERVICE ||
- uuid.uu.uuid16 == GATT_UUID_SEC_SERVICE ||
- uuid.uu.uuid16 == GATT_UUID_INCLUDE_SERVICE ||
- uuid.uu.uuid16 == GATT_UUID_CHAR_DECLARE)) {
+static bool is_gatt_attr_type(const Uuid& uuid) {
+ if (uuid == Uuid::From16Bit(GATT_UUID_PRI_SERVICE) ||
+ uuid == Uuid::From16Bit(GATT_UUID_SEC_SERVICE) ||
+ uuid == Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE) ||
+ uuid == Uuid::From16Bit(GATT_UUID_CHAR_DECLARE)) {
return true;
}
return false;
}
-/** Update the the last primary info for the service list info */
-static void gatt_update_last_pri_srv_info() {
- gatt_cb.last_primary_s_handle = 0;
+/** Update the the last service info for the service list info */
+static void gatt_update_last_srv_info() {
+ gatt_cb.last_service_handle = 0;
- for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info)
- if (el.is_primary) gatt_cb.last_primary_s_handle = el.s_hdl;
+ for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info) {
+ gatt_cb.last_service_handle = el.s_hdl;
+ }
}
/*******************************************************************************
@@ -198,28 +154,22 @@
uint16_t s_hdl = 0;
bool save_hdl = false;
tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
- tBT_UUID* p_app_uuid128;
bool is_pri = (service->type == BTGATT_DB_PRIMARY_SERVICE) ? true : false;
- tBT_UUID svc_uuid;
- btif_to_bta_uuid(&svc_uuid, &service->uuid);
+ Uuid svc_uuid = service->uuid;
LOG(INFO) << __func__;
- if (p_reg == NULL) {
+ if (!p_reg) {
LOG(ERROR) << "Inavlid gatt_if=" << +gatt_if;
return GATT_INTERNAL_ERROR;
}
- p_app_uuid128 = &p_reg->app_uuid128;
-
uint16_t num_handles = compute_service_size(service, count);
- if ((svc_uuid.len == LEN_UUID_16) &&
- (svc_uuid.uu.uuid16 == UUID_SERVCLASS_GATT_SERVER)) {
+ if (svc_uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) {
s_hdl = gatt_cb.hdl_cfg.gatt_start_hdl;
- } else if ((svc_uuid.len == LEN_UUID_16) &&
- (svc_uuid.uu.uuid16 == UUID_SERVCLASS_GAP_SERVER)) {
+ } else if (svc_uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) {
s_hdl = gatt_cb.hdl_cfg.gap_start_hdl;
} else {
if (!gatt_cb.hdl_list_info->empty()) {
@@ -241,7 +191,7 @@
}
tGATT_HDL_LIST_ELEM& list = gatt_add_an_item_to_list(s_hdl);
- list.asgn_range.app_uuid128 = *p_app_uuid128;
+ list.asgn_range.app_uuid128 = p_reg->app_uuid128;
list.asgn_range.svc_uuid = svc_uuid;
list.asgn_range.s_handle = s_hdl;
list.asgn_range.e_handle = s_hdl + num_handles - 1;
@@ -252,20 +202,18 @@
(*gatt_cb.cb_info.p_nv_save_callback)(true, &list.asgn_range);
}
- gatts_init_service_db(list.svc_db, &svc_uuid, is_pri, s_hdl, num_handles);
+ gatts_init_service_db(list.svc_db, svc_uuid, is_pri, s_hdl, num_handles);
VLOG(1) << StringPrintf(
- "%s: handles needed:%u s_hdl=%u e_hdl=%u %s[%x] is_primary=%d", __func__,
+ "%s: handles needed:%u s_hdl=%u e_hdl=%u %s is_primary=%d", __func__,
num_handles, list.asgn_range.s_handle, list.asgn_range.e_handle,
- ((list.asgn_range.svc_uuid.len == 2) ? "uuid16" : "uuid128"),
- list.asgn_range.svc_uuid.uu.uuid16, list.asgn_range.is_primary);
+ list.asgn_range.svc_uuid.ToString().c_str(), list.asgn_range.is_primary);
service->attribute_handle = s_hdl;
btgatt_db_element_t* el = service + 1;
for (int i = 0; i < count - 1; i++, el++) {
- tBT_UUID uuid;
- btif_to_bta_uuid(&uuid, &el->uuid);
+ const Uuid& uuid = el->uuid;
if (el->type == BTGATT_DB_CHARACTERISTIC) {
/* data validity checking */
@@ -282,8 +230,8 @@
if (is_gatt_attr_type(uuid)) {
LOG(ERROR) << StringPrintf(
"%s: attept to add characteristic with UUID equal to GATT "
- "Attribute Type 0x%04x ",
- __func__, uuid.uu.uuid16);
+ "Attribute Type %s ",
+ __func__, uuid.ToString().c_str());
return GATT_INTERNAL_ERROR;
}
@@ -293,8 +241,8 @@
if (is_gatt_attr_type(uuid)) {
LOG(ERROR) << StringPrintf(
"%s: attept to add descriptor with UUID equal to GATT "
- "Attribute Type 0x%04x ",
- __func__, uuid.uu.uuid16);
+ "Attribute Type %s",
+ __func__, uuid.ToString().c_str());
return GATT_INTERNAL_ERROR;
}
@@ -333,18 +281,18 @@
elem.p_db = &list.svc_db;
elem.is_primary = list.asgn_range.is_primary;
- memcpy(&elem.app_uuid, &list.asgn_range.app_uuid128, sizeof(tBT_UUID));
+ elem.app_uuid = list.asgn_range.app_uuid128;
elem.type = list.asgn_range.is_primary ? GATT_UUID_PRI_SERVICE
: GATT_UUID_SEC_SERVICE;
if (elem.type == GATT_UUID_PRI_SERVICE) {
- tBT_UUID* p_uuid = gatts_get_service_uuid(elem.p_db);
- elem.sdp_handle = gatt_add_sdp_record(p_uuid, elem.s_hdl, elem.e_hdl);
+ Uuid* p_uuid = gatts_get_service_uuid(elem.p_db);
+ elem.sdp_handle = gatt_add_sdp_record(*p_uuid, elem.s_hdl, elem.e_hdl);
} else {
elem.sdp_handle = 0;
}
- gatt_update_last_pri_srv_info();
+ gatt_update_last_srv_info();
VLOG(1) << StringPrintf(
"%s: allocated el: s_hdl=%d e_hdl=%d type=0x%x sdp_hdl=0x%x", __func__,
@@ -355,17 +303,14 @@
return GATT_SERVICE_STARTED;
}
-bool is_active_service(tBT_UUID* p_app_uuid128, tBT_UUID* p_svc_uuid,
+bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid,
uint16_t start_handle) {
for (auto& info : *gatt_cb.srv_list_info) {
- tBT_UUID* p_this_uuid = gatts_get_service_uuid(info.p_db);
+ Uuid* p_this_uuid = gatts_get_service_uuid(info.p_db);
- if (p_this_uuid && gatt_uuid_compare(*p_app_uuid128, info.app_uuid) &&
- gatt_uuid_compare(*p_svc_uuid, *p_this_uuid) &&
- (start_handle == info.s_hdl)) {
- LOG(ERROR) << "Active Service Found";
- gatt_dbg_display_uuid(*p_svc_uuid);
-
+ if (p_this_uuid && app_uuid128 == info.app_uuid &&
+ *p_svc_uuid == *p_this_uuid && (start_handle == info.s_hdl)) {
+ LOG(ERROR) << "Active Service Found: " << *p_svc_uuid;
return true;
}
}
@@ -386,7 +331,7 @@
* was not found.
*
******************************************************************************/
-bool GATTS_DeleteService(tGATT_IF gatt_if, tBT_UUID* p_svc_uuid,
+bool GATTS_DeleteService(tGATT_IF gatt_if, Uuid* p_svc_uuid,
uint16_t svc_inst) {
VLOG(1) << __func__;
@@ -396,8 +341,8 @@
return false;
}
- tBT_UUID* p_app_uuid128 = &p_reg->app_uuid128;
- auto it = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst);
+ auto it =
+ gatt_find_hdl_buffer_by_app_id(p_reg->app_uuid128, p_svc_uuid, svc_inst);
if (it == gatt_cb.hdl_list_info->end()) {
LOG(ERROR) << "No Service found";
return false;
@@ -405,7 +350,7 @@
gatt_proc_srv_chg();
- if (is_active_service(p_app_uuid128, p_svc_uuid, svc_inst)) {
+ if (is_active_service(p_reg->app_uuid128, p_svc_uuid, svc_inst)) {
GATTS_StopService(it->asgn_range.s_handle);
}
@@ -445,7 +390,7 @@
}
gatt_cb.srv_list_info->erase(it);
- gatt_update_last_pri_srv_info();
+ gatt_update_last_srv_info();
}
/*******************************************************************************
*
@@ -664,7 +609,6 @@
return attp_send_cl_msg(*p_clcb->p_tcb, p_clcb, GATT_REQ_MTU, &gatt_cl_msg);
}
-
/*******************************************************************************
*
* Function GATTC_Discover
@@ -699,7 +643,7 @@
if (!GATT_HANDLE_IS_VALID(p_param->s_handle) ||
!GATT_HANDLE_IS_VALID(p_param->e_handle) ||
/* search by type does not have a valid UUID param */
- (disc_type == GATT_DISC_SRVC_BY_UUID && p_param->service.len == 0)) {
+ (disc_type == GATT_DISC_SRVC_BY_UUID && p_param->service.IsEmpty())) {
return GATT_ILLEGAL_PARAMETER;
}
@@ -769,7 +713,7 @@
case GATT_READ_CHAR_VALUE:
p_clcb->s_handle = p_read->service.s_handle;
p_clcb->e_handle = p_read->service.e_handle;
- memcpy(&p_clcb->uuid, &p_read->service.uuid, sizeof(tBT_UUID));
+ p_clcb->uuid = p_read->service.uuid;
break;
case GATT_READ_MULTIPLE: {
p_clcb->s_handle = 0;
@@ -782,7 +726,7 @@
}
case GATT_READ_BY_HANDLE:
case GATT_READ_PARTIAL:
- memset(&p_clcb->uuid, 0, sizeof(tBT_UUID));
+ p_clcb->uuid = Uuid::kEmpty;
p_clcb->s_handle = p_read->by_handle.handle;
if (type == GATT_READ_PARTIAL) {
@@ -996,19 +940,16 @@
* with GATT
*
******************************************************************************/
-tGATT_IF GATT_Register(tBT_UUID* p_app_uuid128, tGATT_CBACK* p_cb_info) {
+tGATT_IF GATT_Register(const Uuid& app_uuid128, tGATT_CBACK* p_cb_info) {
tGATT_REG* p_reg;
uint8_t i_gatt_if = 0;
tGATT_IF gatt_if = 0;
- LOG(INFO) << __func__;
- gatt_dbg_display_uuid(*p_app_uuid128);
+ LOG(INFO) << __func__ << " " << app_uuid128;
for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
i_gatt_if++, p_reg++) {
- if (p_reg->in_use &&
- !memcmp(p_app_uuid128->uu.uuid128, p_reg->app_uuid128.uu.uuid128,
- LEN_UUID_128)) {
+ if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) {
LOG(ERROR) << "application already registered.";
return 0;
}
@@ -1019,7 +960,7 @@
if (!p_reg->in_use) {
memset(p_reg, 0, sizeof(tGATT_REG));
i_gatt_if++; /* one based number */
- p_reg->app_uuid128 = *p_app_uuid128;
+ p_reg->app_uuid128 = app_uuid128;
gatt_if = p_reg->gatt_if = (tGATT_IF)i_gatt_if;
p_reg->app_cb = *p_cb_info;
p_reg->in_use = true;
@@ -1069,7 +1010,7 @@
}
/* free all services db buffers if owned by this application */
- gatt_free_srvc_db_buffer_app_id(&p_reg->app_uuid128);
+ gatt_free_srvc_db_buffer_app_id(p_reg->app_uuid128);
/* When an application deregisters, check remove the link associated with the
* app */
diff --git a/stack/gatt/gatt_attr.cc b/stack/gatt/gatt_attr.cc
index f4e028a..75a8057 100644
--- a/stack/gatt/gatt_attr.cc
+++ b/stack/gatt/gatt_attr.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2012 Broadcom Corporation
+ * Copyright 2008-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,12 +26,12 @@
#include "bt_target.h"
#include "bt_utils.h"
-#include "btcore/include/uuid.h"
#include "gatt_api.h"
#include "gatt_int.h"
#include "osi/include/osi.h"
using base::StringPrintf;
+using bluetooth::Uuid;
#define GATTP_MAX_NUM_INC_SVR 0
#define GATTP_MAX_CHAR_NUM 2
@@ -84,6 +84,9 @@
uint16_t conn_id = GATT_INVALID_CONN_ID;
GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &conn_id,
BT_TRANSPORT_LE);
+ if (conn_id == GATT_INVALID_CONN_ID)
+ GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &conn_id,
+ BT_TRANSPORT_BR_EDR);
return conn_id;
}
@@ -210,17 +213,16 @@
case GATTS_REQ_TYPE_WRITE_EXEC:
case GATT_CMD_WRITE:
ignore = true;
- VLOG(1) << StringPrintf("Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD");
+ VLOG(1) << "Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD";
break;
case GATTS_REQ_TYPE_MTU:
- VLOG(1) << StringPrintf("Get MTU exchange new mtu size: %d", p_data->mtu);
+ VLOG(1) << "Get MTU exchange new mtu size: " << +p_data->mtu;
ignore = true;
break;
default:
- VLOG(1) << StringPrintf("Unknown/unexpected LE GAP ATT request: 0x%02x",
- type);
+ VLOG(1) << "Unknown/unexpected LE GAP ATT request: " << loghex(type);
break;
}
@@ -240,9 +242,8 @@
const RawAddress& bda, uint16_t conn_id,
bool connected, tGATT_DISCONN_REASON reason,
tBT_TRANSPORT transport) {
- VLOG(1) << __func__ << ": from " << bda
- << StringPrintf(" connected:%d conn_id=%d reason = 0x%04x", connected,
- conn_id, reason);
+ VLOG(1) << __func__ << ": from " << bda << " connected: " << connected
+ << ", conn_id: " << loghex(conn_id) << "reason: " << loghex(reason);
tGATT_PROFILE_CLCB* p_clcb =
gatt_profile_find_clcb_by_bd_addr(bda, transport);
@@ -269,21 +270,19 @@
*
******************************************************************************/
void gatt_profile_db_init(void) {
- tBT_UUID app_uuid = {LEN_UUID_128, {0}};
uint16_t service_handle = 0;
/* Fill our internal UUID with a fixed pattern 0x81 */
- memset(&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
+ std::array<uint8_t, Uuid::kNumBytes128> tmp;
+ tmp.fill(0x81);
/* Create a GATT profile service */
- gatt_cb.gatt_if = GATT_Register(&app_uuid, &gatt_profile_cback);
+ gatt_cb.gatt_if = GATT_Register(Uuid::From128BitBE(tmp), &gatt_profile_cback);
GATT_StartIf(gatt_cb.gatt_if);
- bt_uuid_t service_uuid;
- uuid_128_from_16(&service_uuid, UUID_SERVCLASS_GATT_SERVER);
+ Uuid service_uuid = Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER);
- bt_uuid_t char_uuid;
- uuid_128_from_16(&char_uuid, GATT_UUID_GATT_SRV_CHGD);
+ Uuid char_uuid = Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD);
btgatt_db_element_t service[] = {
{.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = service_uuid},
@@ -298,8 +297,7 @@
service_handle = service[0].attribute_handle;
gatt_cb.handle_of_h_r = service[1].attribute_handle;
- LOG(ERROR) << StringPrintf("gatt_profile_db_init: gatt_if=%d",
- gatt_cb.gatt_if);
+ VLOG(1) << __func__ << ": gatt_if=" << +gatt_cb.gatt_if;
}
/*******************************************************************************
@@ -329,7 +327,7 @@
break;
case GATT_DISC_CHAR_DSCPT: /* stage 3 */
- if (p_data->type.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG) {
+ if (p_data->type == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)) {
p_clcb->s_handle = p_data->handle;
p_clcb->ccc_result++;
}
@@ -352,14 +350,15 @@
if (p_clcb == NULL) return;
- if (status == GATT_SUCCESS && p_clcb->ccc_result > 0) {
- p_clcb->ccc_result = 0;
- p_clcb->ccc_stage++;
- gatt_cl_start_config_ccc(p_clcb);
- } else {
- LOG(ERROR) << StringPrintf(
- "%s() - Unable to register for service changed indication", __func__);
+ if (status != GATT_SUCCESS || p_clcb->ccc_result == 0) {
+ LOG(WARNING) << __func__
+ << ": Unable to register for service changed indication";
+ return;
}
+
+ p_clcb->ccc_result = 0;
+ p_clcb->ccc_stage++;
+ gatt_cl_start_config_ccc(p_clcb);
}
/*******************************************************************************
@@ -389,7 +388,7 @@
tGATT_DISC_PARAM srvc_disc_param;
tGATT_VALUE ccc_value;
- VLOG(1) << StringPrintf("%s() - stage: %d", __func__, p_clcb->ccc_stage);
+ VLOG(1) << __func__ << ": stage: " << +p_clcb->ccc_stage;
memset(&srvc_disc_param, 0, sizeof(tGATT_DISC_PARAM));
memset(&ccc_value, 0, sizeof(tGATT_VALUE));
@@ -398,16 +397,14 @@
case GATT_SVC_CHANGED_SERVICE: /* discover GATT service */
srvc_disc_param.s_handle = 1;
srvc_disc_param.e_handle = 0xffff;
- srvc_disc_param.service.len = 2;
- srvc_disc_param.service.uu.uuid16 = UUID_SERVCLASS_GATT_SERVER;
+ srvc_disc_param.service = Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER);
GATTC_Discover(p_clcb->conn_id, GATT_DISC_SRVC_BY_UUID, &srvc_disc_param);
break;
case GATT_SVC_CHANGED_CHARACTERISTIC: /* discover service change char */
srvc_disc_param.s_handle = 1;
srvc_disc_param.e_handle = p_clcb->e_handle;
- srvc_disc_param.service.len = 2;
- srvc_disc_param.service.uu.uuid16 = GATT_UUID_GATT_SRV_CHGD;
+ srvc_disc_param.service = Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD);
GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR, &srvc_disc_param);
break;
diff --git a/stack/gatt/gatt_auth.cc b/stack/gatt/gatt_auth.cc
index b91b56c..3794388 100644
--- a/stack/gatt/gatt_auth.cc
+++ b/stack/gatt/gatt_auth.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
index 9e77e15..dca4973 100644
--- a/stack/gatt/gatt_cl.cc
+++ b/stack/gatt/gatt_cl.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,6 +44,8 @@
#define GATT_READ_BY_TYPE_RSP_MIN_LEN 1
using base::StringPrintf;
+using bluetooth::Uuid;
+
/*******************************************************************************
* G L O B A L G A T T D A T A *
******************************************************************************/
@@ -78,46 +80,51 @@
******************************************************************************/
void gatt_act_discovery(tGATT_CLCB* p_clcb) {
uint8_t op_code = disc_type_to_att_opcode[p_clcb->op_subtype];
- tGATT_CL_MSG cl_req;
- tGATT_STATUS st;
- if (p_clcb->s_handle <= p_clcb->e_handle && p_clcb->s_handle != 0) {
- memset(&cl_req, 0, sizeof(tGATT_CL_MSG));
-
- cl_req.browse.s_handle = p_clcb->s_handle;
- cl_req.browse.e_handle = p_clcb->e_handle;
-
- if (disc_type_to_uuid[p_clcb->op_subtype] != 0) {
- cl_req.browse.uuid.len = 2;
- cl_req.browse.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
- }
-
- if (p_clcb->op_subtype ==
- GATT_DISC_SRVC_BY_UUID) /* fill in the FindByTypeValue request info*/
- {
- cl_req.find_type_value.uuid.len = 2;
- cl_req.find_type_value.uuid.uu.uuid16 =
- disc_type_to_uuid[p_clcb->op_subtype];
- cl_req.find_type_value.s_handle = p_clcb->s_handle;
- cl_req.find_type_value.e_handle = p_clcb->e_handle;
- cl_req.find_type_value.value_len = p_clcb->uuid.len;
- /* if service type is 32 bits UUID, convert it now */
- if (p_clcb->uuid.len == LEN_UUID_32) {
- cl_req.find_type_value.value_len = LEN_UUID_128;
- gatt_convert_uuid32_to_uuid128(cl_req.find_type_value.value,
- p_clcb->uuid.uu.uuid32);
- } else
- memcpy(cl_req.find_type_value.value, &p_clcb->uuid.uu,
- p_clcb->uuid.len);
- }
-
- st = attp_send_cl_msg(*p_clcb->p_tcb, p_clcb, op_code, &cl_req);
-
- if (st != GATT_SUCCESS && st != GATT_CMD_STARTED) {
- gatt_end_operation(p_clcb, GATT_ERROR, NULL);
- }
- } else /* end of handle range */
+ if (p_clcb->s_handle > p_clcb->e_handle || p_clcb->s_handle == 0) {
+ /* end of handle range */
gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
+ return;
+ }
+
+ tGATT_CL_MSG cl_req;
+ memset(&cl_req, 0, sizeof(tGATT_CL_MSG));
+
+ cl_req.browse.s_handle = p_clcb->s_handle;
+ cl_req.browse.e_handle = p_clcb->e_handle;
+
+ if (disc_type_to_uuid[p_clcb->op_subtype] != 0) {
+ cl_req.browse.uuid =
+ bluetooth::Uuid::From16Bit(disc_type_to_uuid[p_clcb->op_subtype]);
+ }
+
+ if (p_clcb->op_subtype ==
+ GATT_DISC_SRVC_BY_UUID) /* fill in the FindByTypeValue request info*/
+ {
+ cl_req.find_type_value.uuid =
+ bluetooth::Uuid::From16Bit(disc_type_to_uuid[p_clcb->op_subtype]);
+ cl_req.find_type_value.s_handle = p_clcb->s_handle;
+ cl_req.find_type_value.e_handle = p_clcb->e_handle;
+
+ size_t size = p_clcb->uuid.GetShortestRepresentationSize();
+ cl_req.find_type_value.value_len = size;
+ if (size == Uuid::kNumBytes16) {
+ uint8_t* p = cl_req.find_type_value.value;
+ UINT16_TO_STREAM(p, p_clcb->uuid.As16Bit());
+ } else if (size == Uuid::kNumBytes32) {
+ /* if service type is 32 bits UUID, convert it now */
+ memcpy(cl_req.find_type_value.value, p_clcb->uuid.To128BitLE().data(),
+ Uuid::kNumBytes128);
+ cl_req.find_type_value.value_len = Uuid::kNumBytes128;
+ } else
+ memcpy(cl_req.find_type_value.value, p_clcb->uuid.To128BitLE().data(),
+ size);
+ }
+
+ tGATT_STATUS st = attp_send_cl_msg(*p_clcb->p_tcb, p_clcb, op_code, &cl_req);
+ if (st != GATT_SUCCESS && st != GATT_CMD_STARTED) {
+ gatt_end_operation(p_clcb, GATT_ERROR, NULL);
+ }
}
/*******************************************************************************
@@ -144,10 +151,9 @@
msg.browse.s_handle = p_clcb->s_handle;
msg.browse.e_handle = p_clcb->e_handle;
if (p_clcb->op_subtype == GATT_READ_BY_TYPE)
- memcpy(&msg.browse.uuid, &p_clcb->uuid, sizeof(tBT_UUID));
+ msg.browse.uuid = p_clcb->uuid;
else {
- msg.browse.uuid.len = LEN_UUID_16;
- msg.browse.uuid.uu.uuid16 = GATT_UUID_CHAR_DECLARE;
+ msg.browse.uuid = bluetooth::Uuid::From16Bit(GATT_UUID_CHAR_DECLARE);
}
break;
@@ -376,15 +382,13 @@
return;
memset(&result, 0, sizeof(tGATT_DISC_RES));
- result.type.len = 2;
- result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE;
+ result.type = bluetooth::Uuid::From16Bit(GATT_UUID_PRI_SERVICE);
/* returns a series of handle ranges */
while (len >= 4) {
STREAM_TO_UINT16(result.handle, p);
STREAM_TO_UINT16(result.value.group_value.e_handle, p);
- memcpy(&result.value.group_value.service_type, &p_clcb->uuid,
- sizeof(tBT_UUID));
+ result.value.group_value.service_type = p_clcb->uuid;
len -= 4;
@@ -431,9 +435,9 @@
len -= 1;
if (type == GATT_INFO_TYPE_PAIR_16)
- uuid_len = LEN_UUID_16;
+ uuid_len = Uuid::kNumBytes16;
else if (type == GATT_INFO_TYPE_PAIR_128)
- uuid_len = LEN_UUID_128;
+ uuid_len = Uuid::kNumBytes128;
while (len >= uuid_len + 2) {
STREAM_TO_UINT16(result.handle, p);
@@ -441,7 +445,7 @@
if (uuid_len > 0) {
if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p)) break;
} else
- memcpy(&result.type, &p_clcb->uuid, sizeof(tBT_UUID));
+ result.type = p_clcb->uuid;
len -= (uuid_len + 2);
@@ -608,9 +612,11 @@
tGATT_REG* p_reg;
uint16_t conn_id;
tGATT_STATUS encrypt_status;
- uint8_t *p = p_data, i, event = (op_code == GATT_HANDLE_VALUE_NOTIF)
- ? GATTC_OPTYPE_NOTIFICATION
- : GATTC_OPTYPE_INDICATION;
+ uint8_t* p = p_data;
+ uint8_t i;
+ uint8_t event = (op_code == GATT_HANDLE_VALUE_NOTIF)
+ ? GATTC_OPTYPE_NOTIFICATION
+ : GATTC_OPTYPE_INDICATION;
VLOG(1) << __func__;
@@ -738,8 +744,8 @@
memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
result.handle = handle;
- result.type.len = 2;
- result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
+ result.type =
+ bluetooth::Uuid::From16Bit(disc_type_to_uuid[p_clcb->op_subtype]);
/* discover all services */
if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
@@ -772,8 +778,10 @@
}
if (value_len == 6) {
- STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
- record_value.incl_service.service_type.len = LEN_UUID_16;
+ uint16_t tmp;
+ STREAM_TO_UINT16(tmp, p);
+ record_value.incl_service.service_type =
+ bluetooth::Uuid::From16Bit(tmp);
} else if (value_len == 4) {
p_clcb->s_handle = record_value.incl_service.s_handle;
p_clcb->read_uuid128.wait_for_read_rsp = true;
@@ -827,10 +835,14 @@
}
/* UUID not matching */
- if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid)) {
+ if (!p_clcb->uuid.IsEmpty() &&
+ !record_value.dclr_value.char_uuid.IsEmpty() &&
+ record_value.dclr_value.char_uuid != p_clcb->uuid) {
len -= (value_len + 2);
continue; /* skip the result, and look for next one */
- } else if (p_clcb->operation == GATTC_OPTYPE_READ)
+ }
+
+ if (p_clcb->operation == GATTC_OPTYPE_READ)
/* UUID match for read characteristic value */
{
/* only read the first matching UUID characteristic value, and
@@ -926,12 +938,9 @@
p_clcb->read_uuid128.wait_for_read_rsp) {
p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
p_clcb->read_uuid128.wait_for_read_rsp = false;
- if (len == LEN_UUID_128) {
- memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu
- .uuid128,
- p, len);
- p_clcb->read_uuid128.result.value.incl_service.service_type.len =
- LEN_UUID_128;
+ if (len == Uuid::kNumBytes128) {
+ p_clcb->read_uuid128.result.value.incl_service.service_type =
+ bluetooth::Uuid::From128BitLE(p);
if (p_clcb->p_reg->app_cb.p_disc_res_cb)
(*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id,
p_clcb->op_subtype,
diff --git a/stack/gatt/gatt_db.cc b/stack/gatt/gatt_db.cc
index ac3d959..31a262d 100644
--- a/stack/gatt/gatt_db.cc
+++ b/stack/gatt/gatt_db.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,10 +35,12 @@
#include "osi/include/osi.h"
using base::StringPrintf;
+using bluetooth::Uuid;
+
/*******************************************************************************
* L O C A L F U N C T I O N P R O T O T Y P E S *
******************************************************************************/
-static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const tBT_UUID& uuid,
+static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const Uuid& uuid,
tGATT_PERM perm);
static tGATT_STATUS gatts_send_app_read_request(
tGATT_TCB& tcb, uint8_t op_code, uint16_t handle, uint16_t offset,
@@ -47,8 +49,8 @@
/**
* Initialize a memory space to be a service database.
*/
-void gatts_init_service_db(tGATT_SVC_DB& db, tBT_UUID* p_service, bool is_pri,
- uint16_t s_hdl, uint16_t num_handle) {
+void gatts_init_service_db(tGATT_SVC_DB& db, const Uuid& service_uuid,
+ bool is_pri, uint16_t s_hdl, uint16_t num_handle) {
db.attr_list.reserve(num_handle);
VLOG(1) << StringPrintf("%s: s_hdl= %d num_handle= %d", __func__, s_hdl,
@@ -59,14 +61,14 @@
db.end_handle = s_hdl + num_handle;
/* add service declration record */
- tBT_UUID uuid = {LEN_UUID_16, {0}};
- uuid.uu.uuid16 = is_pri ? GATT_UUID_PRI_SERVICE : GATT_UUID_SEC_SERVICE;
+ Uuid uuid =
+ Uuid::From16Bit(is_pri ? GATT_UUID_PRI_SERVICE : GATT_UUID_SEC_SERVICE);
tGATT_ATTR& attr = allocate_attr_in_db(db, uuid, GATT_PERM_READ);
- attr.p_value.reset((tGATT_ATTR_VALUE*)(new tBT_UUID));
- memcpy(&attr.p_value->uuid, p_service, sizeof(tBT_UUID));
+ attr.p_value.reset((tGATT_ATTR_VALUE*)(new Uuid));
+ attr.p_value->uuid = service_uuid;
}
-tBT_UUID* gatts_get_service_uuid(tGATT_SVC_DB* p_db) {
+Uuid* gatts_get_service_uuid(tGATT_SVC_DB* p_db) {
if (!p_db || p_db->attr_list.empty()) {
LOG(ERROR) << "service DB empty";
return NULL;
@@ -119,8 +121,8 @@
return GATT_INSUF_KEY_SIZE;
}
- if (read_long && attr.uuid.len == LEN_UUID_16) {
- switch (attr.uuid.uu.uuid16) {
+ if (read_long && attr.uuid.Is16Bit()) {
+ switch (attr.uuid.As16Bit()) {
case GATT_UUID_PRI_SERVICE:
case GATT_UUID_SEC_SERVICE:
case GATT_UUID_CHAR_DECLARE:
@@ -146,13 +148,13 @@
*
* Description Utility function to read an attribute value.
*
- * Parameter p_attr: pointer to the attribute to read.
+ * Parameter attr16: pointer to the attribute to read.
* offset: read offset.
- * p_value: output parameter to carry out the attribute value.
- * p_len: output parameter to carry out the attribute length.
+ * p_data: output parameter to carry out the attribute value.
* read_long: this is a read blob request.
* mtu: MTU
- * sec_flag: current link security status.
+ * p_len: output parameter to carry out the attribute length.
+ * sec_flag: current link security status.
* key_size: encryption key size.
*
* Returns status of operation.
@@ -162,75 +164,73 @@
uint8_t** p_data, bool read_long,
uint16_t mtu, uint16_t* p_len,
tGATT_SEC_FLAG sec_flag, uint8_t key_size) {
- uint16_t len = 0, uuid16 = 0;
uint8_t* p = *p_data;
- VLOG(1)
- << __func__
- << StringPrintf(
- " uuid=0x%04x perm=0x%02x sec_flag=0x%x offset=%d read_long=%d",
- attr16.uuid.uu.uuid16, attr16.permission, sec_flag, offset,
- read_long);
+ VLOG(1) << __func__ << " uuid=" << attr16.uuid
+ << StringPrintf(" perm=0x%02x sec_flag=0x%x offset=%d read_long=%d",
+ attr16.permission, sec_flag, offset, read_long);
tGATT_STATUS status = gatts_check_attr_readability(attr16, offset, read_long,
sec_flag, key_size);
-
if (status != GATT_SUCCESS) return status;
- if (attr16.uuid.len == LEN_UUID_16) uuid16 = attr16.uuid.uu.uuid16;
-
- status = GATT_NO_RESOURCES;
-
- if (uuid16 == GATT_UUID_PRI_SERVICE || uuid16 == GATT_UUID_SEC_SERVICE) {
- len = attr16.p_value->uuid.len;
- if (mtu >= attr16.p_value->uuid.len) {
- gatt_build_uuid_to_stream(&p, attr16.p_value->uuid);
- status = GATT_SUCCESS;
- }
- } else if (uuid16 == GATT_UUID_CHAR_DECLARE) {
- tGATT_ATTR* val_attr = &attr16 + 1;
- len = (val_attr->uuid.len == LEN_UUID_16) ? 5 : 19;
-
- if (mtu >= len) {
- UINT8_TO_STREAM(p, attr16.p_value->char_decl.property);
- UINT16_TO_STREAM(p, attr16.p_value->char_decl.char_val_handle);
-
- if (val_attr->uuid.len == LEN_UUID_16) {
- UINT16_TO_STREAM(p, val_attr->uuid.uu.uuid16);
- }
- /* convert a 32bits UUID to 128 bits */
- else if (val_attr->uuid.len == LEN_UUID_32) {
- gatt_convert_uuid32_to_uuid128(p, val_attr->uuid.uu.uuid32);
- p += LEN_UUID_128;
- } else {
- ARRAY_TO_STREAM(p, val_attr->uuid.uu.uuid128, LEN_UUID_128);
- }
- status = GATT_SUCCESS;
- }
-
- } else if (uuid16 == GATT_UUID_INCLUDE_SERVICE) {
- if (attr16.p_value->incl_handle.service_type.len == LEN_UUID_16)
- len = 6;
- else
- len = 4;
-
- if (mtu >= len) {
- UINT16_TO_STREAM(p, attr16.p_value->incl_handle.s_handle);
- UINT16_TO_STREAM(p, attr16.p_value->incl_handle.e_handle);
-
- if (attr16.p_value->incl_handle.service_type.len == LEN_UUID_16) {
- UINT16_TO_STREAM(p, attr16.p_value->incl_handle.service_type.uu.uuid16);
- }
- status = GATT_SUCCESS;
- }
- } else /* characteristic description or characteristic value */
- {
- status = GATT_PENDING;
+ if (!attr16.uuid.Is16Bit()) {
+ /* characteristic description or characteristic value */
+ return GATT_PENDING;
}
- *p_len = len;
- *p_data = p;
- return status;
+ uint16_t uuid16 = attr16.uuid.As16Bit();
+
+ if (uuid16 == GATT_UUID_PRI_SERVICE || uuid16 == GATT_UUID_SEC_SERVICE) {
+ *p_len = gatt_build_uuid_to_stream_len(attr16.p_value->uuid);
+ if (mtu < *p_len) return GATT_NO_RESOURCES;
+
+ gatt_build_uuid_to_stream(&p, attr16.p_value->uuid);
+ *p_data = p;
+ return GATT_SUCCESS;
+ }
+
+ if (uuid16 == GATT_UUID_CHAR_DECLARE) {
+ tGATT_ATTR* val_attr = &attr16 + 1;
+ uint8_t val_len = val_attr->uuid.GetShortestRepresentationSize();
+ *p_len = (val_len == Uuid::kNumBytes16) ? 5 : 19;
+
+ if (mtu < *p_len) return GATT_NO_RESOURCES;
+
+ UINT8_TO_STREAM(p, attr16.p_value->char_decl.property);
+ UINT16_TO_STREAM(p, attr16.p_value->char_decl.char_val_handle);
+
+ if (val_len == Uuid::kNumBytes16) {
+ UINT16_TO_STREAM(p, val_attr->uuid.As16Bit());
+ } else {
+ /* if 32 bit UUID, convert to 128 bit */
+ ARRAY_TO_STREAM(p, val_attr->uuid.To128BitLE(), (int)Uuid::kNumBytes128);
+ }
+ *p_data = p;
+ return GATT_SUCCESS;
+ }
+
+ if (uuid16 == GATT_UUID_INCLUDE_SERVICE) {
+ tGATT_INCL_SRVC& incl_handle = attr16.p_value->incl_handle;
+ if (incl_handle.service_type.Is16Bit())
+ *p_len = 6;
+ else
+ *p_len = 4;
+
+ if (mtu < *p_len) return GATT_NO_RESOURCES;
+
+ UINT16_TO_STREAM(p, incl_handle.s_handle);
+ UINT16_TO_STREAM(p, incl_handle.e_handle);
+
+ if (incl_handle.service_type.Is16Bit()) {
+ UINT16_TO_STREAM(p, incl_handle.service_type.As16Bit());
+ }
+ *p_data = p;
+ return GATT_SUCCESS;
+ }
+
+ /* characteristic description or characteristic value (again) */
+ return GATT_PENDING;
}
/*******************************************************************************
@@ -253,7 +253,7 @@
******************************************************************************/
tGATT_STATUS gatts_db_read_attr_value_by_type(
tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp,
- uint16_t s_handle, uint16_t e_handle, tBT_UUID type, uint16_t* p_len,
+ uint16_t s_handle, uint16_t e_handle, const Uuid& type, uint16_t* p_len,
tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id,
uint16_t* p_cur_handle) {
tGATT_STATUS status = GATT_NOT_FOUND;
@@ -262,9 +262,7 @@
if (p_db) {
for (tGATT_ATTR& attr : p_db->attr_list) {
- tBT_UUID attr_uuid = attr.uuid;
-
- if (attr.handle >= s_handle && gatt_uuid_compare(type, attr_uuid)) {
+ if (attr.handle >= s_handle && type == attr.uuid) {
if (*p_len <= 2) {
status = GATT_NO_RESOURCES;
break;
@@ -304,7 +302,7 @@
uint8_t flag = 0;
if (BTM_GetSecurityFlags(tcb.peer_bda, &flag)) {
if ((tcb.att_lcid == L2CAP_ATT_CID) && (status == GATT_PENDING) &&
- (type.uu.uuid16 == GATT_UUID_GAP_DEVICE_NAME)) {
+ (type.As16Bit() == GATT_UUID_GAP_DEVICE_NAME)) {
if ((flag & (BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_FLAG_ENCRYPTED)) ==
BTM_SEC_LINK_KEY_KNOWN) {
tACL_CONN* p = btm_bda_to_acl(tcb.peer_bda, BT_TRANSPORT_LE);
@@ -328,13 +326,14 @@
*
*/
uint16_t gatts_add_included_service(tGATT_SVC_DB& db, uint16_t s_handle,
- uint16_t e_handle, tBT_UUID service) {
- tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_INCLUDE_SERVICE}};
+ uint16_t e_handle, const Uuid& service) {
+ Uuid uuid = Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE);
- VLOG(1) << StringPrintf("%s: s_hdl = 0x%04x e_hdl = 0x%04x uuid = 0x%04x",
- __func__, s_handle, e_handle, service.uu.uuid16);
+ VLOG(1) << __func__
+ << StringPrintf(": s_hdl=0x%04x e_hdl=0x%04x ", s_handle, e_handle)
+ << "service uuid = " << service;
- if (service.len == 0 || s_handle == 0 || e_handle == 0) {
+ if (service.IsEmpty() || s_handle == 0 || e_handle == 0) {
LOG(ERROR) << __func__ << ": Illegal Params.";
return 0;
}
@@ -344,7 +343,7 @@
attr.p_value.reset((tGATT_ATTR_VALUE*)(new tGATT_INCL_SRVC));
attr.p_value->incl_handle.s_handle = s_handle;
attr.p_value->incl_handle.e_handle = e_handle;
- memcpy(&attr.p_value->incl_handle.service_type, &service, sizeof(tBT_UUID));
+ attr.p_value->incl_handle.service_type = service;
return attr.handle;
}
@@ -366,8 +365,8 @@
******************************************************************************/
uint16_t gatts_add_characteristic(tGATT_SVC_DB& db, tGATT_PERM perm,
tGATT_CHAR_PROP property,
- tBT_UUID& char_uuid) {
- tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
+ const Uuid& char_uuid) {
+ Uuid uuid = Uuid::From16Bit(GATT_UUID_CHAR_DECLARE);
VLOG(1) << StringPrintf("%s: perm=0x%0x property=0x%0x", __func__, perm,
property);
@@ -384,46 +383,6 @@
/*******************************************************************************
*
- * Function gatt_convertchar_descr_type
- *
- * Description Convert a char descript UUID into descriptor type.
- *
- * Returns descriptor type.
- *
- ******************************************************************************/
-uint8_t gatt_convertchar_descr_type(tBT_UUID* p_descr_uuid) {
- tBT_UUID std_descr = {LEN_UUID_16, {GATT_UUID_CHAR_EXT_PROP}};
-
- if (gatt_uuid_compare(std_descr, *p_descr_uuid))
- return GATT_DESCR_EXT_DSCPTOR;
-
- std_descr.uu.uuid16++;
- if (gatt_uuid_compare(std_descr, *p_descr_uuid))
- return GATT_DESCR_USER_DSCPTOR;
-
- std_descr.uu.uuid16++;
- if (gatt_uuid_compare(std_descr, *p_descr_uuid)) return GATT_DESCR_CLT_CONFIG;
-
- std_descr.uu.uuid16++;
- if (gatt_uuid_compare(std_descr, *p_descr_uuid)) return GATT_DESCR_SVR_CONFIG;
-
- std_descr.uu.uuid16++;
- if (gatt_uuid_compare(std_descr, *p_descr_uuid))
- return GATT_DESCR_PRES_FORMAT;
-
- std_descr.uu.uuid16++;
- if (gatt_uuid_compare(std_descr, *p_descr_uuid))
- return GATT_DESCR_AGGR_FORMAT;
-
- std_descr.uu.uuid16++;
- if (gatt_uuid_compare(std_descr, *p_descr_uuid))
- return GATT_DESCR_VALID_RANGE;
-
- return GATT_DESCR_UNKNOWN;
-}
-
-/*******************************************************************************
- *
* Function gatts_add_char_descr
*
* Description This function add a characteristics descriptor.
@@ -437,9 +396,9 @@
*
******************************************************************************/
uint16_t gatts_add_char_descr(tGATT_SVC_DB& db, tGATT_PERM perm,
- tBT_UUID& descr_uuid) {
- VLOG(1) << StringPrintf("gatts_add_char_descr uuid=0x%04x",
- descr_uuid.uu.uuid16);
+ const Uuid& descr_uuid) {
+ VLOG(1) << StringPrintf("gatts_add_char_descr uuid=%s",
+ descr_uuid.ToString().c_str());
/* Add characteristic descriptors */
tGATT_ATTR& char_dscptr = allocate_attr_in_db(db, descr_uuid, perm);
@@ -626,13 +585,14 @@
status = GATT_INSUF_AUTHENTICATION;
LOG(ERROR) << __func__
<< ": GATT_INSUF_AUTHENTICATION: LE security mode 2 required";
- } else /* writable: must be char value declaration or char descritpors
- */
+ } else /* writable: must be char value declaration or char descritpors */
{
uint16_t max_size = 0;
- if (p_attr->uuid.len == LEN_UUID_16) {
- switch (p_attr->uuid.uu.uuid16) {
+ if (p_attr->uuid.IsEmpty()) {
+ status = GATT_INVALID_PDU;
+ } else if (p_attr->uuid.Is16Bit()) {
+ switch (p_attr->uuid.As16Bit()) {
case GATT_UUID_CHAR_PRESENT_FORMAT: /* should be readable only */
case GATT_UUID_CHAR_EXT_PROP: /* should be readable only */
case GATT_UUID_CHAR_AGG_FORMAT: /* should be readable only */
@@ -650,31 +610,28 @@
status = GATT_SUCCESS;
break;
}
- } else if (p_attr->uuid.len == LEN_UUID_128 ||
- p_attr->uuid.len == LEN_UUID_32) {
+ } else { // 32 or 128 bit UUID
status = GATT_SUCCESS;
- } else {
- status = GATT_INVALID_PDU;
}
if (p_data == NULL && len > 0) {
- status = GATT_INVALID_PDU;
+ return GATT_INVALID_PDU;
}
+
/* these attribute does not allow write blob */
- else if ((p_attr->uuid.len == LEN_UUID_16) &&
- (p_attr->uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG ||
- p_attr->uuid.uu.uuid16 == GATT_UUID_CHAR_SRVR_CONFIG)) {
- if (op_code == GATT_REQ_PREPARE_WRITE &&
- offset != 0) /* does not allow write blob */
- {
+ if (p_attr->uuid.Is16Bit() &&
+ (p_attr->uuid.As16Bit() == GATT_UUID_CHAR_CLIENT_CONFIG ||
+ p_attr->uuid.As16Bit() == GATT_UUID_CHAR_SRVR_CONFIG)) {
+ if (op_code == GATT_REQ_PREPARE_WRITE && offset != 0) {
+ /* does not allow write blob */
status = GATT_NOT_LONG;
LOG(ERROR) << __func__ << ": GATT_NOT_LONG";
- } else if (len != max_size) /* data does not match the required format */
- {
+ } else if (len != max_size) {
+ /* data does not match the required format */
status = GATT_INVALID_ATTR_LEN;
LOG(ERROR) << __func__ << ": GATT_INVALID_PDU";
} else {
- status = GATT_SUCCESS;
+ return GATT_SUCCESS;
}
}
}
@@ -682,26 +639,6 @@
return status;
}
-static void uuid_to_str(const tBT_UUID bt_uuid, char* str_buf, size_t buf_len) {
- if (bt_uuid.len == LEN_UUID_16) {
- snprintf(str_buf, buf_len, "0x%04x", bt_uuid.uu.uuid16);
- } else if (bt_uuid.len == LEN_UUID_32) {
- snprintf(str_buf, buf_len, "0x%08x", bt_uuid.uu.uuid32);
- } else if (bt_uuid.len == LEN_UUID_128) {
- int x = snprintf(str_buf, buf_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-",
- bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14],
- bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12],
- bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10],
- bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]);
- snprintf(&str_buf[x], buf_len - x, "%02x%02x-%02x%02x%02x%02x%02x%02x",
- bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6],
- bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4],
- bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2],
- bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]);
- } else
- snprintf(str_buf, buf_len, "Unknown (len=%d)", bt_uuid.len);
-}
-
/**
* Description Allocate a memory space for a new attribute, and link this
* attribute into the database attribute list.
@@ -713,7 +650,7 @@
* Returns pointer to the newly allocated attribute.
*
*/
-static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const tBT_UUID& uuid,
+static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const Uuid& uuid,
tGATT_PERM perm) {
if (db.next_handle >= db.end_handle) {
LOG(FATAL) << __func__
@@ -726,10 +663,6 @@
attr.handle = db.next_handle++;
attr.uuid = uuid;
attr.permission = perm;
-
- char uuid_str[37];
- uuid_to_str(attr.uuid, uuid_str, sizeof(uuid_str));
-
return attr;
}
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index cb0ad3e..5052918 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -101,7 +101,7 @@
/* GATT client FIND_TYPE_VALUE_Request data */
typedef struct {
- tBT_UUID uuid; /* type of attribute to be found */
+ bluetooth::Uuid uuid; /* type of attribute to be found */
uint16_t s_handle; /* starting handle */
uint16_t e_handle; /* ending handle */
uint16_t value_len; /* length of the attribute value */
@@ -152,7 +152,7 @@
/* attribute value maintained in the server database
*/
typedef union {
- tBT_UUID uuid; /* service declaration */
+ bluetooth::Uuid uuid; /* service declaration */
tGATT_CHAR_DECL char_decl; /* characteristic declaration */
tGATT_INCL_SRVC incl_handle; /* included service */
} tGATT_ATTR_VALUE;
@@ -170,7 +170,7 @@
std::unique_ptr<tGATT_ATTR_VALUE> p_value;
tGATT_PERM permission;
uint16_t handle;
- tBT_UUID uuid;
+ bluetooth::Uuid uuid;
bt_gatt_db_attribute_type_t gatt_type;
} tGATT_ATTR;
@@ -188,7 +188,7 @@
/* attribute handle, service UUID and a set of GATT server callback. */
typedef struct {
- tBT_UUID app_uuid128;
+ bluetooth::Uuid app_uuid128;
tGATT_CBACK app_cb;
tGATT_IF gatt_if; /* one based */
bool in_use;
@@ -254,7 +254,7 @@
/* attribute handle, service UUID and a set of GATT server callback. */
typedef struct {
tGATT_SVC_DB* p_db; /* pointer to the service database */
- tBT_UUID app_uuid; /* applicatino UUID */
+ bluetooth::Uuid app_uuid; /* application UUID */
uint32_t sdp_handle; /* primamry service SDP handle */
uint16_t type; /* service type UUID, primary or secondary */
uint16_t s_hdl; /* service starting handle */
@@ -308,7 +308,7 @@
tGATT_REG* p_reg; /* owner of this CLCB */
uint8_t sccb_idx;
uint8_t* p_attr_buf; /* attribute buffer for read multiple, prepare write */
- tBT_UUID uuid;
+ bluetooth::Uuid uuid;
uint16_t conn_id; /* connection handle */
uint16_t s_handle; /* starting handle of the active request */
uint16_t e_handle; /* ending handle of the active request */
@@ -361,7 +361,7 @@
fixed_queue_t* sign_op_queue;
uint16_t next_handle; /* next available handle */
- uint16_t last_primary_s_handle; /* handle of last primary service */
+ uint16_t last_service_handle; /* handle of last service */
tGATT_SVC_CHG gattp_attr; /* GATT profile attribute service change */
tGATT_IF gatt_if;
std::list<tGATT_HDL_LIST_ELEM>* hdl_list_info;
@@ -432,14 +432,13 @@
/* utility functions */
extern uint8_t* gatt_dbg_op_name(uint8_t op_code);
-extern uint32_t gatt_add_sdp_record(tBT_UUID* p_uuid, uint16_t start_hdl,
- uint16_t end_hdl);
-extern bool gatt_parse_uuid_from_cmd(tBT_UUID* p_uuid, uint16_t len,
+extern uint32_t gatt_add_sdp_record(const bluetooth::Uuid& uuid,
+ uint16_t start_hdl, uint16_t end_hdl);
+extern bool gatt_parse_uuid_from_cmd(bluetooth::Uuid* p_uuid, uint16_t len,
uint8_t** p_data);
-extern uint8_t gatt_build_uuid_to_stream(uint8_t** p_dst, tBT_UUID uuid);
-extern bool gatt_uuid_compare(tBT_UUID src, tBT_UUID tar);
-extern void gatt_convert_uuid32_to_uuid128(uint8_t uuid_128[LEN_UUID_128],
- uint32_t uuid_32);
+extern uint8_t gatt_build_uuid_to_stream_len(const bluetooth::Uuid& uuid);
+extern uint8_t gatt_build_uuid_to_stream(uint8_t** p_dst,
+ const bluetooth::Uuid& uuid);
extern void gatt_sr_get_sec_info(const RawAddress& rem_bda,
tBT_TRANSPORT transport, uint8_t* p_sec_flag,
uint8_t* p_key_size);
@@ -452,7 +451,6 @@
extern tGATT_STATUS gatt_send_error_rsp(tGATT_TCB& tcb, uint8_t err_code,
uint8_t op_code, uint16_t handle,
bool deq);
-extern void gatt_dbg_display_uuid(tBT_UUID bt_uuid);
extern bool gatt_is_srv_chg_ind_pending(tGATT_TCB* p_tcb);
extern tGATTS_SRV_CHG* gatt_is_bda_in_the_srv_chg_clt_list(
@@ -464,12 +462,13 @@
extern void gatt_set_srv_chg(void);
extern void gatt_delete_dev_from_srv_chg_clt_list(const RawAddress& bd_addr);
extern tGATT_VALUE* gatt_add_pending_ind(tGATT_TCB* p_tcb, tGATT_VALUE* p_ind);
-extern void gatt_free_srvc_db_buffer_app_id(tBT_UUID* p_app_id);
+extern void gatt_free_srvc_db_buffer_app_id(const bluetooth::Uuid& app_id);
extern bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb);
/* reserved handle list */
extern std::list<tGATT_HDL_LIST_ELEM>::iterator gatt_find_hdl_buffer_by_app_id(
- tBT_UUID* p_app_uuid128, tBT_UUID* p_svc_uuid, uint16_t svc_inst);
+ const bluetooth::Uuid& app_uuid128, bluetooth::Uuid* p_svc_uuid,
+ uint16_t svc_inst);
extern tGATT_HDL_LIST_ELEM* gatt_find_hdl_buffer_by_handle(uint16_t handle);
extern tGATTS_SRV_CHG* gatt_add_srv_chg_clt(tGATTS_SRV_CHG* p_srv_chg);
@@ -486,9 +485,6 @@
/* server function */
extern std::list<tGATT_SRV_LIST_ELEM>::iterator gatt_sr_find_i_rcb_by_handle(
uint16_t handle);
-extern bool gatt_sr_find_i_rcb_by_app_id(tBT_UUID* p_app_uuid128,
- tBT_UUID* p_svc_uuid,
- uint16_t svc_inst);
extern tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if,
uint32_t trans_id, uint8_t op_code,
tGATT_STATUS status,
@@ -500,9 +496,8 @@
extern uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint8_t op_code,
uint16_t handle);
extern bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda);
-extern void gatt_notify_phy_updated(tGATT_TCB* p_tcb, uint8_t tx_phy,
- uint8_t rx_phy, uint8_t status);
-
+extern void gatt_notify_phy_updated(uint8_t status, uint16_t handle,
+ uint8_t tx_phy, uint8_t rx_phy);
/* */
extern tGATT_REG* gatt_get_regcb(tGATT_IF gatt_if);
@@ -560,21 +555,22 @@
extern void gatt_set_sec_act(tGATT_TCB* p_tcb, tGATT_SEC_ACTION sec_act);
/* gatt_db.cc */
-extern void gatts_init_service_db(tGATT_SVC_DB& db, tBT_UUID* p_service,
- bool is_pri, uint16_t s_hdl,
- uint16_t num_handle);
+extern void gatts_init_service_db(tGATT_SVC_DB& db,
+ const bluetooth::Uuid& service, bool is_pri,
+ uint16_t s_hdl, uint16_t num_handle);
extern uint16_t gatts_add_included_service(tGATT_SVC_DB& db, uint16_t s_handle,
- uint16_t e_handle, tBT_UUID service);
+ uint16_t e_handle,
+ const bluetooth::Uuid& service);
extern uint16_t gatts_add_characteristic(tGATT_SVC_DB& db, tGATT_PERM perm,
tGATT_CHAR_PROP property,
- tBT_UUID& char_uuid);
+ const bluetooth::Uuid& char_uuid);
extern uint16_t gatts_add_char_descr(tGATT_SVC_DB& db, tGATT_PERM perm,
- tBT_UUID& dscp_uuid);
+ const bluetooth::Uuid& dscp_uuid);
extern tGATT_STATUS gatts_db_read_attr_value_by_type(
tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp,
- uint16_t s_handle, uint16_t e_handle, tBT_UUID type, uint16_t* p_len,
- tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id,
- uint16_t* p_cur_handle);
+ uint16_t s_handle, uint16_t e_handle, const bluetooth::Uuid& type,
+ uint16_t* p_len, tGATT_SEC_FLAG sec_flag, uint8_t key_size,
+ uint32_t trans_id, uint16_t* p_cur_handle);
extern tGATT_STATUS gatts_read_attr_value_by_handle(
tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle,
uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu,
@@ -586,6 +582,6 @@
uint16_t handle,
tGATT_SEC_FLAG sec_flag,
uint8_t key_size);
-extern tBT_UUID* gatts_get_service_uuid(tGATT_SVC_DB* p_db);
+extern bluetooth::Uuid* gatts_get_service_uuid(tGATT_SVC_DB* p_db);
#endif
diff --git a/stack/gatt/gatt_main.cc b/stack/gatt/gatt_main.cc
index 3556b43..afae25f 100644
--- a/stack/gatt/gatt_main.cc
+++ b/stack/gatt/gatt_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2012 Broadcom Corporation
+ * Copyright 2008-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@
#define GATT_L2C_CFG_CFM_DONE (1 << 1)
/* minimum GATT MTU size over BR/EDR link
-*/
+ */
#define GATT_MIN_BR_MTU_SIZE 48
/******************************************************************************/
@@ -80,7 +80,8 @@
NULL,
gatt_l2cif_data_ind_cback,
gatt_l2cif_congest_cback,
- NULL};
+ NULL,
+ NULL /* tL2CA_CREDITS_RECEIVED_CB */};
tGATT_CB gatt_cb;
@@ -476,7 +477,7 @@
uint16_t conn_id;
/* if uncongested, check to see if there is any more pending data */
- if (p_tcb != NULL && congested == false) {
+ if (p_tcb != NULL && !congested) {
gatt_cl_send_next_cmd_inq(*p_tcb);
}
/* notifying all applications for the connection up event */
@@ -490,8 +491,18 @@
}
}
-void gatt_notify_phy_updated(tGATT_TCB* p_tcb, uint8_t tx_phy, uint8_t rx_phy,
- uint8_t status) {
+void gatt_notify_phy_updated(uint8_t status, uint16_t handle, uint8_t tx_phy,
+ uint8_t rx_phy) {
+ tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle);
+ if (!p_dev_rec) {
+ BTM_TRACE_WARNING("%s: No Device Found!", __func__);
+ return;
+ }
+
+ tGATT_TCB* p_tcb =
+ gatt_find_tcb_by_addr(p_dev_rec->ble.pseudo_addr, BT_TRANSPORT_LE);
+ if (p_tcb == NULL) return;
+
for (int i = 0; i < GATT_MAX_APPS; i++) {
tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
if (p_reg->in_use && p_reg->app_cb.p_phy_update_cb) {
@@ -956,8 +967,11 @@
pseudo_op_code = op_code & (~GATT_WRITE_CMD_MASK);
if (pseudo_op_code >= GATT_OP_CODE_MAX) {
- LOG(ERROR) << "ATT - Rcvd L2CAP data, unknown cmd: 0x" << std::hex
- << op_code;
+ /* Note: PTS: GATT/SR/UNS/BI-01-C mandates error on unsupported ATT request.
+ */
+ LOG(ERROR) << __func__
+ << ": ATT - Rcvd L2CAP data, unknown cmd: " << loghex(op_code);
+ gatt_send_error_rsp(tcb, GATT_REQ_NOT_SUPPORTED, op_code, 0, false);
return;
}
@@ -1075,7 +1089,7 @@
req.client_read_index = i;
status = (*gatt_cb.cb_info.p_srv_chg_callback)(
GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp);
- if (status == true) {
+ if (status) {
memcpy(&srv_chg_clt, &rsp.srv_chg, sizeof(tGATTS_SRV_CHG));
if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL) {
LOG(ERROR) << "Unable to add a service change client";
diff --git a/stack/gatt/gatt_sr.cc b/stack/gatt/gatt_sr.cc
index f9e8f53..b9921fe 100644
--- a/stack/gatt/gatt_sr.cc
+++ b/stack/gatt/gatt_sr.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2012 Broadcom Corporation
+ * Copyright 2008-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,8 @@
#define GATT_MTU_REQ_MIN_LEN 2
using base::StringPrintf;
+using bluetooth::Uuid;
+
/*******************************************************************************
*
* Function gatt_sr_enqueue_cmd
@@ -333,7 +335,7 @@
} else /* nothing needs to be executed , send response now */
{
LOG(ERROR) << "gatt_process_exec_write_req: no prepare write pending";
- gatt_send_error_rsp(tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, false);
+ gatt_send_error_rsp(tcb, GATT_INVALID_OFFSET, GATT_REQ_EXEC_WRITE, 0, false);
}
}
@@ -449,57 +451,59 @@
******************************************************************************/
static tGATT_STATUS gatt_build_primary_service_rsp(
BT_HDR* p_msg, tGATT_TCB& tcb, uint8_t op_code, uint16_t s_hdl,
- uint16_t e_hdl, UNUSED_ATTR uint8_t* p_data, tBT_UUID value) {
+ uint16_t e_hdl, UNUSED_ATTR uint8_t* p_data, const Uuid& value) {
tGATT_STATUS status = GATT_NOT_FOUND;
- uint8_t handle_len = 4, *p;
- tBT_UUID* p_uuid;
+ uint8_t handle_len = 4;
- p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
+ uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info) {
- if (el.s_hdl >= s_hdl && el.s_hdl <= e_hdl &&
- el.type == GATT_UUID_PRI_SERVICE) {
- p_uuid = gatts_get_service_uuid(el.p_db);
- if (p_uuid != NULL) {
- if (op_code == GATT_REQ_READ_BY_GRP_TYPE) handle_len = 4 + p_uuid->len;
+ if (el.s_hdl < s_hdl || el.s_hdl > e_hdl ||
+ el.type != GATT_UUID_PRI_SERVICE) {
+ continue;
+ }
- /* get the length byte in the repsonse */
- if (p_msg->offset == 0) {
- *p++ = op_code + 1;
- p_msg->len++;
- p_msg->offset = handle_len;
+ Uuid* p_uuid = gatts_get_service_uuid(el.p_db);
+ if (!p_uuid) continue;
- if (op_code == GATT_REQ_READ_BY_GRP_TYPE) {
- *p++ = (uint8_t)p_msg->offset; /* length byte */
- p_msg->len++;
- }
- }
+ if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
+ handle_len = 4 + gatt_build_uuid_to_stream_len(*p_uuid);
- if (p_msg->len + p_msg->offset <= tcb.payload_size &&
- handle_len == p_msg->offset) {
- if (op_code != GATT_REQ_FIND_TYPE_VALUE ||
- gatt_uuid_compare(value, *p_uuid)) {
- UINT16_TO_STREAM(p, el.s_hdl);
+ /* get the length byte in the repsonse */
+ if (p_msg->offset == 0) {
+ *p++ = op_code + 1;
+ p_msg->len++;
+ p_msg->offset = handle_len;
- if (gatt_cb.last_primary_s_handle &&
- gatt_cb.last_primary_s_handle == el.s_hdl) {
- VLOG(1) << "Use 0xFFFF for the last primary attribute";
- /* see GATT ERRATA 4065, 4063, ATT ERRATA 4062 */
- UINT16_TO_STREAM(p, 0xFFFF);
- } else {
- UINT16_TO_STREAM(p, el.e_hdl);
- }
-
- if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
- gatt_build_uuid_to_stream(&p, *p_uuid);
-
- status = GATT_SUCCESS;
- p_msg->len += p_msg->offset;
- }
- } else
- break;
+ if (op_code == GATT_REQ_READ_BY_GRP_TYPE) {
+ *p++ = (uint8_t)p_msg->offset; /* length byte */
+ p_msg->len++;
}
}
+
+ if (p_msg->len + p_msg->offset > tcb.payload_size ||
+ handle_len != p_msg->offset) {
+ break;
+ }
+
+ if (op_code == GATT_REQ_FIND_TYPE_VALUE && value != *p_uuid) continue;
+
+ UINT16_TO_STREAM(p, el.s_hdl);
+
+ if (gatt_cb.last_service_handle &&
+ gatt_cb.last_service_handle == el.s_hdl) {
+ VLOG(1) << "Use 0xFFFF for the last primary attribute";
+ /* see GATT ERRATA 4065, 4063, ATT ERRATA 4062 */
+ UINT16_TO_STREAM(p, 0xFFFF);
+ } else {
+ UINT16_TO_STREAM(p, el.e_hdl);
+ }
+
+ if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
+ gatt_build_uuid_to_stream(&p, *p_uuid);
+
+ status = GATT_SUCCESS;
+ p_msg->len += p_msg->offset;
}
p_msg->offset = L2CAP_MIN_OFFSET;
@@ -528,25 +532,25 @@
if (attr.handle < s_hdl) continue;
+ uint8_t uuid_len = attr.uuid.GetShortestRepresentationSize();
if (p_msg->offset == 0)
- p_msg->offset = (attr.uuid.len == LEN_UUID_16) ? GATT_INFO_TYPE_PAIR_16
- : GATT_INFO_TYPE_PAIR_128;
+ p_msg->offset = (uuid_len == Uuid::kNumBytes16) ? GATT_INFO_TYPE_PAIR_16
+ : GATT_INFO_TYPE_PAIR_128;
if (len < info_pair_len[p_msg->offset - 1]) return GATT_NO_RESOURCES;
if (p_msg->offset == GATT_INFO_TYPE_PAIR_16 &&
- attr.uuid.len == LEN_UUID_16) {
+ uuid_len == Uuid::kNumBytes16) {
UINT16_TO_STREAM(p, attr.handle);
- UINT16_TO_STREAM(p, attr.uuid.uu.uuid16);
+ UINT16_TO_STREAM(p, attr.uuid.As16Bit());
} else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 &&
- attr.uuid.len == LEN_UUID_128) {
+ uuid_len == Uuid::kNumBytes128) {
UINT16_TO_STREAM(p, attr.handle);
- ARRAY_TO_STREAM(p, attr.uuid.uu.uuid128, LEN_UUID_128);
+ ARRAY_TO_STREAM(p, attr.uuid.To128BitLE(), (int)Uuid::kNumBytes128);
} else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 &&
- attr.uuid.len == LEN_UUID_32) {
+ uuid_len == Uuid::kNumBytes32) {
UINT16_TO_STREAM(p, attr.handle);
- gatt_convert_uuid32_to_uuid128(p, attr.uuid.uu.uuid32);
- p += LEN_UUID_128;
+ ARRAY_TO_STREAM(p, attr.uuid.To128BitLE(), (int)Uuid::kNumBytes128);
} else {
LOG(ERROR) << "format mismatch";
return GATT_NO_RESOURCES;
@@ -571,14 +575,14 @@
if (s_hdl > e_hdl || !GATT_HANDLE_IS_VALID(s_hdl) ||
!GATT_HANDLE_IS_VALID(e_hdl)) {
- return GATT_INVALID_PDU;
+ return GATT_INVALID_HANDLE;
}
return GATT_SUCCESS;
}
static tGATT_STATUS gatts_validate_packet_format(uint8_t op_code, uint16_t& len,
- uint8_t*& p, tBT_UUID* p_uuid,
+ uint8_t*& p, Uuid* p_uuid,
uint16_t& s_hdl,
uint16_t& e_hdl) {
tGATT_STATUS ret = read_handles(len, p, s_hdl, e_hdl);
@@ -612,7 +616,7 @@
void gatts_process_primary_service_req(tGATT_TCB& tcb, uint8_t op_code,
uint16_t len, uint8_t* p_data) {
uint16_t s_hdl = 0, e_hdl = 0;
- tBT_UUID uuid;
+ Uuid uuid = Uuid::kEmpty;
uint8_t reason =
gatts_validate_packet_format(op_code, len, p_data, &uuid, s_hdl, e_hdl);
@@ -621,27 +625,25 @@
return;
}
- tBT_UUID primary_service = {LEN_UUID_16, {GATT_UUID_PRI_SERVICE}};
- if (!gatt_uuid_compare(uuid, primary_service)) {
+ if (uuid != Uuid::From16Bit(GATT_UUID_PRI_SERVICE)) {
if (op_code == GATT_REQ_READ_BY_GRP_TYPE) {
gatt_send_error_rsp(tcb, GATT_UNSUPPORT_GRP_TYPE, op_code, s_hdl, false);
- VLOG(1) << StringPrintf("unexpected ReadByGrpType Group: 0x%04x",
- uuid.uu.uuid16);
+ VLOG(1) << StringPrintf("unexpected ReadByGrpType Group: %s",
+ uuid.ToString().c_str());
return;
}
// we do not support ReadByTypeValue with any non-primamry_service type
gatt_send_error_rsp(tcb, GATT_NOT_FOUND, op_code, s_hdl, false);
- VLOG(1) << StringPrintf("unexpected ReadByTypeValue type: 0x%04x",
- uuid.uu.uuid16);
+ VLOG(1) << StringPrintf("unexpected ReadByTypeValue type: %s",
+ uuid.ToString().c_str());
return;
}
// TODO: we assume theh value is UUID, there is no such requirement in spec
- tBT_UUID value;
- memset(&value, 0, sizeof(tBT_UUID));
+ Uuid value = Uuid::kEmpty;
if (op_code == GATT_REQ_FIND_TYPE_VALUE) {
- if (gatt_parse_uuid_from_cmd(&value, len, &p_data) == false) {
+ if (!gatt_parse_uuid_from_cmd(&value, len, &p_data)) {
gatt_send_error_rsp(tcb, GATT_INVALID_PDU, op_code, s_hdl, false);
}
}
@@ -787,9 +789,8 @@
******************************************************************************/
void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint8_t op_code,
uint16_t len, uint8_t* p_data) {
- tBT_UUID uuid;
+ Uuid uuid = Uuid::kEmpty;
uint16_t s_hdl = 0, e_hdl = 0, err_hdl = 0;
- if (len < 4) android_errorWriteLog(0x534e4554, "73125709");
tGATT_STATUS reason =
gatts_validate_packet_format(op_code, len, p_data, &uuid, s_hdl, e_hdl);
diff --git a/stack/gatt/gatt_utils.cc b/stack/gatt/gatt_utils.cc
index e7cc762..9e8d3b9 100644
--- a/stack/gatt/gatt_utils.cc
+++ b/stack/gatt/gatt_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@
#include "sdp_api.h"
using base::StringPrintf;
+using bluetooth::Uuid;
/* check if [x, y] and [a, b] have overlapping range */
#define GATT_VALIDATE_HANDLE_RANGE(x, y, a, b) ((y) >= (a) && (x) <= (b))
@@ -76,10 +77,6 @@
"ATT_HANDLE_VALUE_CONF",
"ATT_OP_CODE_MAX"};
-static const uint8_t base_uuid[LEN_UUID_128] = {
- 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
/*******************************************************************************
*
* Function gatt_free_pending_ind
@@ -220,12 +217,12 @@
*
******************************************************************************/
std::list<tGATT_HDL_LIST_ELEM>::iterator gatt_find_hdl_buffer_by_app_id(
- tBT_UUID* p_app_uuid128, tBT_UUID* p_svc_uuid, uint16_t start_handle) {
+ const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) {
auto end_it = gatt_cb.hdl_list_info->end();
auto it = gatt_cb.hdl_list_info->begin();
for (; it != end_it; it++) {
- if (gatt_uuid_compare(*p_app_uuid128, it->asgn_range.app_uuid128) &&
- gatt_uuid_compare(*p_svc_uuid, it->asgn_range.svc_uuid) &&
+ if (app_uuid128 == it->asgn_range.app_uuid128 &&
+ *p_svc_uuid == it->asgn_range.svc_uuid &&
(start_handle == it->asgn_range.s_handle)) {
return it;
}
@@ -238,11 +235,11 @@
* free the service attribute database buffers by the owner of the service app
* ID.
*/
-void gatt_free_srvc_db_buffer_app_id(tBT_UUID* p_app_id) {
+void gatt_free_srvc_db_buffer_app_id(const Uuid& app_id) {
auto it = gatt_cb.hdl_list_info->begin();
auto end = gatt_cb.hdl_list_info->end();
while (it != end) {
- if (memcmp(p_app_id, &it->asgn_range.app_uuid128, sizeof(tBT_UUID)) == 0) {
+ if (app_id == it->asgn_range.app_uuid128) {
it = gatt_cb.hdl_list_info->erase(it);
} else {
it++;
@@ -291,27 +288,23 @@
*
******************************************************************************/
bool gatt_is_srv_chg_ind_pending(tGATT_TCB* p_tcb) {
- bool srv_chg_ind_pending = false;
-
VLOG(1) << __func__
<< " is_queue_empty=" << fixed_queue_is_empty(p_tcb->pending_ind_q);
- if (p_tcb->indicate_handle == gatt_cb.handle_of_h_r) {
- srv_chg_ind_pending = true;
- } else if (!fixed_queue_is_empty(p_tcb->pending_ind_q)) {
- list_t* list = fixed_queue_get_list(p_tcb->pending_ind_q);
- for (const list_node_t* node = list_begin(list); node != list_end(list);
- node = list_next(node)) {
- tGATT_VALUE* p_buf = (tGATT_VALUE*)list_node(node);
- if (p_buf->handle == gatt_cb.handle_of_h_r) {
- srv_chg_ind_pending = true;
- break;
- }
+ if (p_tcb->indicate_handle == gatt_cb.handle_of_h_r) return true;
+
+ if (fixed_queue_is_empty(p_tcb->pending_ind_q)) return false;
+
+ list_t* list = fixed_queue_get_list(p_tcb->pending_ind_q);
+ for (const list_node_t* node = list_begin(list); node != list_end(list);
+ node = list_next(node)) {
+ tGATT_VALUE* p_buf = (tGATT_VALUE*)list_node(node);
+ if (p_buf->handle == gatt_cb.handle_of_h_r) {
+ return true;
}
}
- VLOG(1) << __func__ << "srv_chg_ind_pending = %d", srv_chg_ind_pending;
- return srv_chg_ind_pending;
+ return false;
}
/*******************************************************************************
@@ -461,179 +454,59 @@
return NULL;
}
-/*******************************************************************************
- *
- * Function gatt_convert_uuid16_to_uuid128
- *
- * Description Convert a 16 bits UUID to be an standard 128 bits one.
- *
- * Returns true if two uuid match; false otherwise.
- *
- ******************************************************************************/
-void gatt_convert_uuid16_to_uuid128(uint8_t uuid_128[LEN_UUID_128],
- uint16_t uuid_16) {
- uint8_t* p = &uuid_128[LEN_UUID_128 - 4];
-
- memcpy(uuid_128, base_uuid, LEN_UUID_128);
-
- UINT16_TO_STREAM(p, uuid_16);
+/** gatt_build_uuid_to_stream will convert 32bit UUIDs to 128bit. This function
+ * will return lenght required to build uuid, either |UUID:kNumBytes16| or
+ * |UUID::kNumBytes128| */
+uint8_t gatt_build_uuid_to_stream_len(const Uuid& uuid) {
+ size_t len = uuid.GetShortestRepresentationSize();
+ return len == Uuid::kNumBytes32 ? Uuid::kNumBytes128 : len;
}
-/*******************************************************************************
- *
- * Function gatt_convert_uuid32_to_uuid128
- *
- * Description Convert a 32 bits UUID to be an standard 128 bits one.
- *
- * Returns true if two uuid match; false otherwise.
- *
- ******************************************************************************/
-void gatt_convert_uuid32_to_uuid128(uint8_t uuid_128[LEN_UUID_128],
- uint32_t uuid_32) {
- uint8_t* p = &uuid_128[LEN_UUID_128 - 4];
-
- memcpy(uuid_128, base_uuid, LEN_UUID_128);
-
- UINT32_TO_STREAM(p, uuid_32);
-}
-/*******************************************************************************
- *
- * Function gatt_uuid_compare
- *
- * Description Compare two UUID to see if they are the same.
- *
- * Returns true if two uuid match; false otherwise.
- *
- ******************************************************************************/
-bool gatt_uuid_compare(tBT_UUID src, tBT_UUID tar) {
- uint8_t su[LEN_UUID_128], tu[LEN_UUID_128];
- uint8_t *ps, *pt;
-
- /* any of the UUID is unspecified */
- if (src.len == 0 || tar.len == 0) {
- return true;
- }
-
- /* If both are 16-bit, we can do a simple compare */
- if (src.len == LEN_UUID_16 && tar.len == LEN_UUID_16) {
- return src.uu.uuid16 == tar.uu.uuid16;
- }
-
- /* If both are 32-bit, we can do a simple compare */
- if (src.len == LEN_UUID_32 && tar.len == LEN_UUID_32) {
- return src.uu.uuid32 == tar.uu.uuid32;
- }
-
- /* One or both of the UUIDs is 128-bit */
- if (src.len == LEN_UUID_16) {
- /* convert a 16 bits UUID to 128 bits value */
- gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
- ps = su;
- } else if (src.len == LEN_UUID_32) {
- gatt_convert_uuid32_to_uuid128(su, src.uu.uuid32);
- ps = su;
- } else
- ps = src.uu.uuid128;
-
- if (tar.len == LEN_UUID_16) {
- /* convert a 16 bits UUID to 128 bits value */
- gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
- pt = tu;
- } else if (tar.len == LEN_UUID_32) {
- /* convert a 32 bits UUID to 128 bits value */
- gatt_convert_uuid32_to_uuid128(tu, tar.uu.uuid32);
- pt = tu;
- } else
- pt = tar.uu.uuid128;
-
- return (memcmp(ps, pt, LEN_UUID_128) == 0);
-}
-
-/*******************************************************************************
- *
- * Function gatt_build_uuid_to_stream
- *
- * Description Add UUID into stream.
- *
- * Returns UUID length.
- *
- ******************************************************************************/
-uint8_t gatt_build_uuid_to_stream(uint8_t** p_dst, tBT_UUID uuid) {
+/** Add UUID into stream. Returns UUID length. */
+uint8_t gatt_build_uuid_to_stream(uint8_t** p_dst, const Uuid& uuid) {
uint8_t* p = *p_dst;
- uint8_t len = 0;
+ size_t len = uuid.GetShortestRepresentationSize();
- if (uuid.len == LEN_UUID_16) {
- UINT16_TO_STREAM(p, uuid.uu.uuid16);
- len = LEN_UUID_16;
- } else if (uuid.len ==
- LEN_UUID_32) /* always convert 32 bits into 128 bits as alwats */
- {
- gatt_convert_uuid32_to_uuid128(p, uuid.uu.uuid32);
- p += LEN_UUID_128;
- len = LEN_UUID_128;
- } else if (uuid.len == LEN_UUID_128) {
- ARRAY_TO_STREAM(p, uuid.uu.uuid128, LEN_UUID_128);
- len = LEN_UUID_128;
+ if (uuid.IsEmpty()) {
+ return 0;
+ }
+
+ if (len == Uuid::kNumBytes16) {
+ UINT16_TO_STREAM(p, uuid.As16Bit());
+ } else if (len == Uuid::kNumBytes32) {
+ /* always convert 32 bits into 128 bits */
+ ARRAY_TO_STREAM(p, uuid.To128BitLE(), (int)Uuid::kNumBytes128);
+ len = Uuid::kNumBytes128;
+ } else if (len == Uuid::kNumBytes128) {
+ ARRAY_TO_STREAM(p, uuid.To128BitLE(), (int)Uuid::kNumBytes128);
}
*p_dst = p;
return len;
}
-/*******************************************************************************
- *
- * Function gatt_parse_uuid_from_cmd
- *
- * Description Convert a 128 bits UUID into a 16 bits UUID.
- *
- * Returns true if command sent, otherwise false.
- *
- ******************************************************************************/
-bool gatt_parse_uuid_from_cmd(tBT_UUID* p_uuid_rec, uint16_t uuid_size,
+bool gatt_parse_uuid_from_cmd(Uuid* p_uuid_rec, uint16_t uuid_size,
uint8_t** p_data) {
- bool is_base_uuid, ret = true;
- uint8_t xx;
+ bool ret = true;
uint8_t* p_uuid = *p_data;
- memset(p_uuid_rec, 0, sizeof(tBT_UUID));
-
switch (uuid_size) {
- case LEN_UUID_16:
- p_uuid_rec->len = uuid_size;
- STREAM_TO_UINT16(p_uuid_rec->uu.uuid16, p_uuid);
- *p_data += LEN_UUID_16;
- break;
+ case Uuid::kNumBytes16: {
+ uint16_t val;
+ STREAM_TO_UINT16(val, p_uuid);
+ *p_uuid_rec = Uuid::From16Bit(val);
+ *p_data += Uuid::kNumBytes16;
+ return true;
+ }
- case LEN_UUID_128:
- /* See if we can compress his UUID down to 16 or 32bit UUIDs */
- is_base_uuid = true;
- for (xx = 0; xx < LEN_UUID_128 - 4; xx++) {
- if (p_uuid[xx] != base_uuid[xx]) {
- is_base_uuid = false;
- break;
- }
- }
- if (is_base_uuid) {
- if ((p_uuid[LEN_UUID_128 - 1] == 0) &&
- (p_uuid[LEN_UUID_128 - 2] == 0)) {
- p_uuid += (LEN_UUID_128 - 4);
- p_uuid_rec->len = LEN_UUID_16;
- STREAM_TO_UINT16(p_uuid_rec->uu.uuid16, p_uuid);
- } else {
- p_uuid += (LEN_UUID_128 - LEN_UUID_32);
- p_uuid_rec->len = LEN_UUID_32;
- STREAM_TO_UINT32(p_uuid_rec->uu.uuid32, p_uuid);
- }
- }
- if (!is_base_uuid) {
- p_uuid_rec->len = LEN_UUID_128;
- memcpy(p_uuid_rec->uu.uuid128, p_uuid, LEN_UUID_128);
- }
- *p_data += LEN_UUID_128;
- break;
+ case Uuid::kNumBytes128: {
+ *p_uuid_rec = Uuid::From128BitLE(p_uuid);
+ *p_data += Uuid::kNumBytes128;
+ return true;
+ }
/* do not allow 32 bits UUID in ATT PDU now */
- case LEN_UUID_32:
+ case Uuid::kNumBytes32:
LOG(ERROR) << "DO NOT ALLOW 32 BITS UUID IN ATT PDU";
return false;
case 0:
@@ -877,47 +750,43 @@
* Returns 0 if error else sdp handle for the record.
*
******************************************************************************/
-uint32_t gatt_add_sdp_record(tBT_UUID* p_uuid, uint16_t start_hdl,
+uint32_t gatt_add_sdp_record(const Uuid& uuid, uint16_t start_hdl,
uint16_t end_hdl) {
- tSDP_PROTOCOL_ELEM proto_elem_list[2];
- uint32_t sdp_handle;
- uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
uint8_t buff[60];
uint8_t* p = buff;
VLOG(1) << __func__
<< StringPrintf(" s_hdl=0x%x s_hdl=0x%x", start_hdl, end_hdl);
- sdp_handle = SDP_CreateRecord();
+ uint32_t sdp_handle = SDP_CreateRecord();
if (sdp_handle == 0) return 0;
- switch (p_uuid->len) {
- case LEN_UUID_16:
- SDP_AddServiceClassIdList(sdp_handle, 1, &p_uuid->uu.uuid16);
+ switch (uuid.GetShortestRepresentationSize()) {
+ case Uuid::kNumBytes16: {
+ uint16_t tmp = uuid.As16Bit();
+ SDP_AddServiceClassIdList(sdp_handle, 1, &tmp);
break;
+ }
- case LEN_UUID_32:
+ case Uuid::kNumBytes32: {
UINT8_TO_BE_STREAM(p, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
- UINT32_TO_BE_STREAM(p, p_uuid->uu.uuid32);
+ uint32_t tmp = uuid.As32Bit();
+ UINT32_TO_BE_STREAM(p, tmp);
SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST,
DATA_ELE_SEQ_DESC_TYPE, (uint32_t)(p - buff), buff);
break;
+ }
- case LEN_UUID_128:
+ case Uuid::kNumBytes128:
UINT8_TO_BE_STREAM(p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
- ARRAY_TO_BE_STREAM_REVERSE(p, p_uuid->uu.uuid128, LEN_UUID_128);
+ ARRAY_TO_BE_STREAM(p, uuid.To128BitBE().data(), (int)Uuid::kNumBytes128);
SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST,
DATA_ELE_SEQ_DESC_TYPE, (uint32_t)(p - buff), buff);
break;
-
- default:
- LOG(ERROR) << "inavlid UUID len=" << +p_uuid->len;
- SDP_DeleteRecord(sdp_handle);
- return 0;
- break;
}
/*** Fill out the protocol element sequence for SDP ***/
+ tSDP_PROTOCOL_ELEM proto_elem_list[2];
proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
proto_elem_list[0].num_params = 1;
proto_elem_list[0].params[0] = BT_PSM_ATT;
@@ -929,6 +798,7 @@
SDP_AddProtocolList(sdp_handle, 2, proto_elem_list);
/* Make the service browseable */
+ uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list);
return (sdp_handle);
@@ -945,8 +815,9 @@
*
******************************************************************************/
void gatt_set_err_rsp(bool enable, uint8_t req_op_code, uint8_t err_status) {
- VLOG(1) << __func__ << StringPrintf(" enable=%d op_code=%d, err_status=%d",
- enable, req_op_code, err_status);
+ VLOG(1) << __func__
+ << StringPrintf(" enable=%d op_code=%d, err_status=%d", enable,
+ req_op_code, err_status);
gatt_cb.enable_err_rsp = enable;
gatt_cb.req_op_code = req_op_code;
gatt_cb.err_status = err_status;
@@ -1234,24 +1105,19 @@
*
******************************************************************************/
bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) {
- tGATT_TCB* p_tcb = NULL;
- bool status = true;
+ tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bda, BT_TRANSPORT_LE);
+ if (!p_tcb) return true;
- p_tcb = gatt_find_tcb_by_addr(bda, BT_TRANSPORT_LE);
-
- if (p_tcb) {
- if (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
- LOG(ERROR) << __func__ << ": link connected Too late to cancel";
- status = false;
- } else {
- gatt_update_app_use_link_flag(gatt_if, p_tcb, false, false);
- if (p_tcb->app_hold_link.empty()) {
- gatt_disconnect(p_tcb);
- }
- }
+ if (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
+ LOG(ERROR) << __func__ << ": link connected Too late to cancel";
+ return false;
}
- return status;
+ gatt_update_app_use_link_flag(gatt_if, p_tcb, false, false);
+
+ if (p_tcb->app_hold_link.empty()) gatt_disconnect(p_tcb);
+
+ return true;
}
/** Enqueue this command */
@@ -1317,8 +1183,9 @@
uint16_t conn_id;
uint8_t operation;
- VLOG(1) << __func__ << StringPrintf(" status=%d op=%d subtype=%d", status,
- p_clcb->operation, p_clcb->op_subtype);
+ VLOG(1) << __func__
+ << StringPrintf(" status=%d op=%d subtype=%d", status,
+ p_clcb->operation, p_clcb->op_subtype);
memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
if (p_cmpl_cb != NULL && p_clcb->operation != 0) {
@@ -1440,40 +1307,6 @@
return (uint8_t*)"Op Code Exceed Max";
}
-/*******************************************************************************
- *
- * Function gatt_dbg_display_uuid
- *
- * Description Disaplay the UUID
- *
- * Returns None
- *
- ******************************************************************************/
-void gatt_dbg_display_uuid(tBT_UUID bt_uuid) {
- char str_buf[50];
-
- if (bt_uuid.len == LEN_UUID_16) {
- snprintf(str_buf, sizeof(str_buf), "0x%04x", bt_uuid.uu.uuid16);
- } else if (bt_uuid.len == LEN_UUID_32) {
- snprintf(str_buf, sizeof(str_buf), "0x%08x",
- (unsigned int)bt_uuid.uu.uuid32);
- } else if (bt_uuid.len == LEN_UUID_128) {
- int x = snprintf(
- str_buf, sizeof(str_buf), "0x%02x%02x%02x%02x%02x%02x%02x%02x",
- bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14], bt_uuid.uu.uuid128[13],
- bt_uuid.uu.uuid128[12], bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10],
- bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]);
- snprintf(
- &str_buf[x], sizeof(str_buf) - x, "%02x%02x%02x%02x%02x%02x%02x%02x",
- bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6], bt_uuid.uu.uuid128[5],
- bt_uuid.uu.uuid128[4], bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2],
- bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]);
- } else
- strlcpy(str_buf, "Unknown UUID 0", sizeof(str_buf));
-
- VLOG(1) << StringPrintf("UUID=[%s]", str_buf);
-}
-
/** Returns true if this is one of the background devices for the application,
* false otherwise */
bool gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV* p_dev, tGATT_IF gatt_if) {
@@ -1608,27 +1441,22 @@
******************************************************************************/
bool gatt_update_auto_connect_dev(tGATT_IF gatt_if, bool add,
const RawAddress& bd_addr) {
- bool ret = false;
- tGATT_REG* p_reg;
tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
VLOG(1) << __func__;
/* Make sure app is registered */
- p_reg = gatt_get_regcb(gatt_if);
- if (p_reg == NULL) {
+ tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
+ if (!p_reg) {
LOG(ERROR) << __func__ << " gatt_if is not registered " << +gatt_if;
return false;
}
- if (add) {
- ret = gatt_add_bg_dev_list(p_reg, bd_addr);
+ if (!add) return gatt_remove_bg_dev_from_list(p_reg, bd_addr);
- if (ret && p_tcb != NULL) {
- /* if a connected device, update the link holding number */
- gatt_update_app_use_link_flag(gatt_if, p_tcb, true, true);
- }
- } else {
- ret = gatt_remove_bg_dev_from_list(p_reg, bd_addr);
+ bool ret = gatt_add_bg_dev_list(p_reg, bd_addr);
+ if (ret && p_tcb != NULL) {
+ /* if a connected device, update the link holding number */
+ gatt_update_app_use_link_flag(gatt_if, p_tcb, true, true);
}
return ret;
}
diff --git a/stack/hcic/hciblecmds.cc b/stack/hcic/hciblecmds.cc
index 041d1e0..30d8d75 100644
--- a/stack/hcic/hciblecmds.cc
+++ b/stack/hcic/hciblecmds.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/hcic/hcicmds.cc b/stack/hcic/hcicmds.cc
index c132054..56ff381 100644
--- a/stack/hcic/hcicmds.cc
+++ b/stack/hcic/hcicmds.cc
@@ -1,20 +1,20 @@
/******************************************************************************
-*
-* Copyright (C) 1999-2012 Broadcom Corporation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at:
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************************/
+ *
+ * Copyright 1999-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
/******************************************************************************
*
diff --git a/stack/hid/hid_conn.h b/stack/hid/hid_conn.h
index 5e3ffe7..46a2850 100644
--- a/stack/hid/hid_conn.h
+++ b/stack/hid/hid_conn.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/hid/hidd_api.cc b/stack/hid/hidd_api.cc
index 8ae70c3..414cf74 100644
--- a/stack/hid/hidd_api.cc
+++ b/stack/hid/hidd_api.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,9 +34,7 @@
#include "hidd_int.h"
#include "hiddefs.h"
-#if HID_DYNAMIC_MEMORY == FALSE
tHID_DEV_CTB hd_cb;
-#endif
/*******************************************************************************
*
diff --git a/stack/hid/hidd_conn.cc b/stack/hid/hidd_conn.cc
index cb08715..e4525f9 100644
--- a/stack/hid/hidd_conn.cc
+++ b/stack/hid/hidd_conn.cc
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,17 +54,19 @@
static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR* p_msg);
static void hidd_l2cif_cong_ind(uint16_t cid, bool congested);
-static const tL2CAP_APPL_INFO dev_reg_info = {hidd_l2cif_connect_ind,
- hidd_l2cif_connect_cfm,
- NULL,
- hidd_l2cif_config_ind,
- hidd_l2cif_config_cfm,
- hidd_l2cif_disconnect_ind,
- hidd_l2cif_disconnect_cfm,
- NULL,
- hidd_l2cif_data_ind,
- hidd_l2cif_cong_ind,
- NULL};
+static const tL2CAP_APPL_INFO dev_reg_info = {
+ hidd_l2cif_connect_ind,
+ hidd_l2cif_connect_cfm,
+ NULL,
+ hidd_l2cif_config_ind,
+ hidd_l2cif_config_cfm,
+ hidd_l2cif_disconnect_ind,
+ hidd_l2cif_disconnect_cfm,
+ NULL,
+ hidd_l2cif_data_ind,
+ hidd_l2cif_cong_ind,
+ NULL,
+ NULL /* tL2CA_CREDITS_RECEIVED_CB */};
/*******************************************************************************
*
@@ -190,17 +192,6 @@
return;
}
- if (p_dev->in_use && bd_addr != p_dev->addr) {
- HIDD_TRACE_WARNING(
- "%s: incoming connections from different device, rejecting", __func__);
- L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
- return;
- } else if (!p_dev->in_use) {
- p_dev->in_use = TRUE;
- p_dev->addr = bd_addr;
- p_dev->state = HIDD_DEV_NO_CONN;
- }
-
p_hcon = &hd_cb.device.conn;
switch (psm) {
@@ -241,6 +232,12 @@
// for CTRL we need to go through security and we reply in callback from there
if (psm == HID_PSM_CONTROL) {
+ // We are ready to accept connection from this device, since we aren't
+ // connected to anything and are in the correct state.
+ p_dev->in_use = TRUE;
+ p_dev->addr = bd_addr;
+ p_dev->state = HIDD_DEV_NO_CONN;
+
p_hcon->conn_flags = 0;
p_hcon->ctrl_cid = cid;
p_hcon->ctrl_id = id;
diff --git a/stack/hid/hidd_int.h b/stack/hid/hidd_int.h
index 81e60ca..0981dcc 100644
--- a/stack/hid/hidd_int.h
+++ b/stack/hid/hidd_int.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -80,12 +80,7 @@
/******************************************************************************
* Main Control Block
******************************************************************************/
-#if HID_DYNAMIC_MEMORY == FALSE
extern tHID_DEV_CTB hd_cb;
-#else
-extern tHID_DEV_CTB* hidd_cb_ptr;
-#define hd_cb (*hidd_cb_ptr)
-#endif
#ifdef __cplusplus
}
diff --git a/stack/hid/hidh_api.cc b/stack/hid/hidh_api.cc
index adbc931..ad84daf 100644
--- a/stack/hid/hidh_api.cc
+++ b/stack/hid/hidh_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,8 @@
#include "hidh_api.h"
#include "hidh_int.h"
+using bluetooth::Uuid;
+
tHID_HOST_CTB hh_cb;
static void hidh_search_callback(uint16_t sdp_result);
@@ -51,14 +53,11 @@
tHID_STATUS HID_HostGetSDPRecord(const RawAddress& addr,
tSDP_DISCOVERY_DB* p_db, uint32_t db_len,
tHID_HOST_SDP_CALLBACK* sdp_cback) {
- tSDP_UUID uuid_list;
if (hh_cb.sdp_busy) return HID_ERR_SDP_BUSY;
- uuid_list.len = 2;
- uuid_list.uu.uuid16 = UUID_SERVCLASS_HUMAN_INTERFACE;
-
hh_cb.p_sdp_db = p_db;
+ Uuid uuid_list = Uuid::From16Bit(UUID_SERVCLASS_HUMAN_INTERFACE);
SDP_InitDiscoveryDb(p_db, db_len, 1, &uuid_list, 0, NULL);
if (SDP_ServiceSearchRequest(addr, p_db, hidh_search_callback)) {
@@ -92,12 +91,9 @@
tSDP_DISCOVERY_DB* p_db = hh_cb.p_sdp_db;
tSDP_DISC_REC* p_rec;
tSDP_DISC_ATTR *p_attr, *p_subattr1, *p_subattr2, *p_repdesc;
- tBT_UUID hid_uuid;
tHID_DEV_SDP_INFO* p_nvi = &hh_cb.sdp_rec;
uint16_t attr_mask = 0;
- hid_uuid.len = LEN_UUID_16;
- hid_uuid.uu.uuid16 = UUID_SERVCLASS_HUMAN_INTERFACE;
hh_cb.sdp_busy = false;
@@ -106,7 +102,8 @@
return;
}
- p_rec = SDP_FindServiceUUIDInDb(p_db, &hid_uuid, NULL);
+ Uuid hid_uuid = Uuid::From16Bit(UUID_SERVCLASS_HUMAN_INTERFACE);
+ p_rec = SDP_FindServiceUUIDInDb(p_db, hid_uuid, NULL);
if (p_rec == NULL) {
hh_cb.sdp_cback(HID_SDP_NO_SERV_UUID, 0, NULL);
return;
diff --git a/stack/hid/hidh_conn.cc b/stack/hid/hidh_conn.cc
index a41aa90..6f99c88 100644
--- a/stack/hid/hidh_conn.cc
+++ b/stack/hid/hidh_conn.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,8 +73,8 @@
NULL,
hidh_l2cif_data_ind,
hidh_l2cif_cong_ind,
- NULL /* tL2CA_TX_COMPLETE_CB */
-};
+ NULL, /* tL2CA_TX_COMPLETE_CB */
+ NULL /* tL2CA_CREDITS_RECEIVED_CB */};
/*******************************************************************************
*
diff --git a/stack/hid/hidh_int.h b/stack/hid/hidh_int.h
index c332403..8fa8ec8 100644
--- a/stack/hid/hidh_int.h
+++ b/stack/hid/hidh_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_aac.h b/stack/include/a2dp_aac.h
index 43f7965..29b2753 100644
--- a/stack/include/a2dp_aac.h
+++ b/stack/include/a2dp_aac.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,15 +25,31 @@
#include "a2dp_codec_api.h"
#include "avdt_api.h"
-class A2dpCodecConfigAac : public A2dpCodecConfig {
+class A2dpCodecConfigAacBase : public A2dpCodecConfig {
+ protected:
+ A2dpCodecConfigAacBase(btav_a2dp_codec_index_t codec_index,
+ const std::string& name,
+ btav_a2dp_codec_priority_t codec_priority,
+ bool is_source)
+ : A2dpCodecConfig(codec_index, name, codec_priority),
+ is_source_(is_source) {}
+ bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
+ uint8_t* p_result_codec_config) override;
+ bool setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) override;
+
+ private:
+ bool is_source_; // True if local is Source
+};
+
+class A2dpCodecConfigAacSource : public A2dpCodecConfigAacBase {
public:
- A2dpCodecConfigAac(btav_a2dp_codec_priority_t codec_priority);
- virtual ~A2dpCodecConfigAac();
+ A2dpCodecConfigAacSource(btav_a2dp_codec_priority_t codec_priority);
+ virtual ~A2dpCodecConfigAacSource();
bool init() override;
period_ms_t encoderIntervalMs() const override;
- bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
- uint8_t* p_result_codec_config) override;
+ int getEffectiveMtu() const override;
private:
bool useRtpHeaderMarkerBit() const override;
@@ -44,6 +60,23 @@
void debug_codec_dump(int fd) override;
};
+class A2dpCodecConfigAacSink : public A2dpCodecConfigAacBase {
+ public:
+ A2dpCodecConfigAacSink(btav_a2dp_codec_priority_t codec_priority);
+ virtual ~A2dpCodecConfigAacSink();
+
+ bool init() override;
+ period_ms_t encoderIntervalMs() const override;
+ int getEffectiveMtu() const override;
+
+ private:
+ bool useRtpHeaderMarkerBit() const override;
+ bool updateEncoderUserConfig(
+ const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
+ bool* p_restart_input, bool* p_restart_output,
+ bool* p_config_updated) override;
+};
+
// Checks whether the codec capabilities contain a valid A2DP AAC Source
// codec.
// NOTE: only codecs that are implemented are considered valid.
@@ -92,14 +125,6 @@
bool A2DP_UsesRtpHeaderAac(bool content_protection_enabled,
const uint8_t* p_codec_info);
-// Builds A2DP preferred AAC Sink capability from AAC Source capability.
-// |p_src_cap| is the Source capability to use.
-// |p_pref_cfg| is the result Sink capability to store.
-// Returns |A2DP_SUCCESS| on success, otherwise the corresponding A2DP error
-// status code.
-tA2DP_STATUS A2DP_BuildSrc2SinkConfigAac(const uint8_t* p_src_cap,
- uint8_t* p_pref_cfg);
-
// Gets the A2DP AAC codec name for a given |p_codec_info|.
const char* A2DP_CodecNameAac(const uint8_t* p_codec_info);
@@ -135,14 +160,6 @@
// contains invalid codec information.
int A2DP_GetSinkTrackChannelTypeAac(const uint8_t* p_codec_info);
-// Computes the number of frames to process in a time window for the A2DP
-// AAC sink codec. |time_interval_ms| is the time interval (in milliseconds).
-// |p_codec_info| is a pointer to the codec_info to decode.
-// Returns the number of frames to process on success, or -1 if |p_codec_info|
-// contains invalid codec information.
-int A2DP_GetSinkFramesCountToProcessAac(uint64_t time_interval_ms,
- const uint8_t* p_codec_info);
-
// Gets the object type code for the A2DP AAC codec.
// The actual value is codec-specific - see |A2DP_AAC_OBJECT_TYPE_*|.
// |p_codec_info| is a pointer to the AAC codec_info to decode.
@@ -195,10 +212,10 @@
bool A2DP_BuildCodecHeaderAac(const uint8_t* p_codec_info, BT_HDR* p_buf,
uint16_t frames_per_packet);
-// Decodes and displays A2DP AAC codec info when using |LOG_DEBUG|.
-// |p_codec_info| is a pointer to the AAC codec_info to decode and display.
-// Returns true if the codec information is valid, otherwise false.
-bool A2DP_DumpCodecInfoAac(const uint8_t* p_codec_info);
+// Decodes A2DP AAC codec info into a human readable string.
+// |p_codec_info| is a pointer to the AAC codec_info to decode.
+// Returns a string describing the codec information.
+std::string A2DP_CodecInfoStringAac(const uint8_t* p_codec_info);
// Gets the A2DP AAC encoder interface that can be used to encode and prepare
// A2DP packets for transmission - see |tA2DP_ENCODER_INTERFACE|.
@@ -208,6 +225,14 @@
const tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterfaceAac(
const uint8_t* p_codec_info);
+// Gets the current A2DP AAC decoder interface that can be used to decode
+// received A2DP packets - see |tA2DP_DECODER_INTERFACE|.
+// |p_codec_info| contains the codec information.
+// Returns the A2DP AAC decoder interface if the |p_codec_info| is valid and
+// supported, otherwise NULL.
+const tA2DP_DECODER_INTERFACE* A2DP_GetDecoderInterfaceAac(
+ const uint8_t* p_codec_info);
+
// Adjusts the A2DP AAC codec, based on local support and Bluetooth
// specification.
// |p_codec_info| contains the codec information to adjust.
@@ -219,11 +244,23 @@
// otherwise |BTAV_A2DP_CODEC_INDEX_MAX|.
btav_a2dp_codec_index_t A2DP_SourceCodecIndexAac(const uint8_t* p_codec_info);
+// Gets the A2DP AAC Sink codec index for a given |p_codec_info|.
+// Returns the corresponding |btav_a2dp_codec_index_t| on success,
+// otherwise |BTAV_A2DP_CODEC_INDEX_MAX|.
+btav_a2dp_codec_index_t A2DP_SinkCodecIndexAac(const uint8_t* p_codec_info);
+
// Gets the A2DP AAC Source codec name.
const char* A2DP_CodecIndexStrAac(void);
-// Initializes A2DP AAC Source codec information into |tAVDT_CFG|
+// Gets the A2DP AAC Sink codec name.
+const char* A2DP_CodecIndexStrAacSink(void);
+
+// Initializes A2DP AAC Source codec information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|.
-bool A2DP_InitCodecConfigAac(tAVDT_CFG* p_cfg);
+bool A2DP_InitCodecConfigAac(AvdtpSepConfig* p_cfg);
+
+// Initializes A2DP AAC Sink codec information into |AvdtpSepConfig|
+// configuration entry pointed by |p_cfg|.
+bool A2DP_InitCodecConfigAacSink(AvdtpSepConfig* p_cfg);
#endif // A2DP_AAC_H
diff --git a/stack/include/a2dp_aac_constants.h b/stack/include/a2dp_aac_constants.h
index 6102f92..b356556 100644
--- a/stack/include/a2dp_aac_constants.h
+++ b/stack/include/a2dp_aac_constants.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_aac_decoder.h b/stack/include/a2dp_aac_decoder.h
new file mode 100644
index 0000000..53ffc52
--- /dev/null
+++ b/stack/include/a2dp_aac_decoder.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Interface to the A2DP AAC Decoder
+//
+
+#ifndef A2DP_AAC_DECODER_H
+#define A2DP_AAC_DECODER_H
+
+#include "a2dp_codec_api.h"
+
+// Loads the A2DP AAC decoder.
+// Return true on success, otherwise false.
+bool A2DP_LoadDecoderAac(void);
+
+// Unloads the A2DP AAC decoder.
+void A2DP_UnloadDecoderAac(void);
+
+// Initialize the A2DP AAC decoder.
+bool a2dp_aac_decoder_init(decoded_data_callback_t decode_callback);
+
+// Cleanup the A2DP AAC decoder.
+void a2dp_aac_decoder_cleanup(void);
+
+// Decodes |p_buf|. Calls |decode_callback| passed into |a2dp_aac_decoder_init|
+// if decoded frames are available.
+bool a2dp_aac_decoder_decode_packet(BT_HDR* p_buf);
+
+#endif // A2DP_AAC_DECODER_H
diff --git a/stack/include/a2dp_aac_encoder.h b/stack/include/a2dp_aac_encoder.h
index e72b18c..e6b7323 100644
--- a/stack/include/a2dp_aac_encoder.h
+++ b/stack/include/a2dp_aac_encoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_api.h b/stack/include/a2dp_api.h
index ee215a9..56e259c 100644
--- a/stack/include/a2dp_api.h
+++ b/stack/include/a2dp_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2000-2012 Broadcom Corporation
+ * Copyright 2000-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,7 +82,8 @@
} tA2DP_Service;
/* This is the callback to notify the result of the SDP discovery process. */
-typedef void(tA2DP_FIND_CBACK)(bool found, tA2DP_Service* p_service);
+typedef void(tA2DP_FIND_CBACK)(bool found, tA2DP_Service* p_service,
+ const RawAddress& peer_address);
/*****************************************************************************
* external function declarations
diff --git a/stack/include/a2dp_codec_api.h b/stack/include/a2dp_codec_api.h
index cdc4721..9fdc13b 100644
--- a/stack/include/a2dp_codec_api.h
+++ b/stack/include/a2dp_codec_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,8 @@
#include "avdt_api.h"
#include "osi/include/time.h"
+class tBT_A2DP_OFFLOAD;
+
/**
* Structure used to initialize the A2DP encoder with A2DP peer information
*/
@@ -67,6 +69,15 @@
// Gets the current priority of the codec.
btav_a2dp_codec_priority_t codecPriority() const { return codec_priority_; }
+ // gets current OTA codec specific config to |p_a2dp_offload->codec_info|.
+ // Returns true if the current codec config is valid and copied,
+ // otherwise false.
+ bool getCodecSpecificConfig(tBT_A2DP_OFFLOAD* p_a2dp_offload);
+
+ // Gets the bitRate for the A2DP codec.
+ // Returns the bitrate of current codec configuration, or 0 if not configured
+ int getTrackBitRate() const;
+
// Copies out the current OTA codec config to |p_codec_info|.
// Returns true if the current codec config is valid and copied,
// otherwise false.
@@ -114,6 +125,11 @@
// the Marker bit in the header is set according to RFC 6416.
virtual bool useRtpHeaderMarkerBit() const = 0;
+ // Gets the effective MTU for the A2DP codec.
+ // Returns the effective MTU of current codec configuration, or 0 if not
+ // configured.
+ virtual int getEffectiveMtu() const = 0;
+
// Checks whether |codec_config| is empty and contains no configuration.
// Returns true if |codec_config| is empty, otherwise false.
static bool isCodecConfigEmpty(const btav_a2dp_codec_config_t& codec_config);
@@ -179,6 +195,12 @@
bool* p_restart_input, bool* p_restart_output,
bool* p_config_updated) = 0;
+ // Sets the codec capabilities for a peer.
+ // |p_peer_codec_capabiltities| is the peer codec capabilities to set.
+ // Returns true on success, otherwise false.
+ virtual bool setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) = 0;
+
// Constructor where |codec_index| is the unique index that identifies the
// codec. The user-friendly name is |name|.
// The default codec priority is |codec_priority|. If the value is
@@ -275,6 +297,11 @@
// Returns the Source codec if found, otherwise nullptr.
A2dpCodecConfig* findSourceCodecConfig(const uint8_t* p_codec_info);
+ // Finds the Sink codec that corresponds to the A2DP over-the-air
+ // |p_codec_info| information.
+ // Returns the Sink codec if found, otherwise nullptr.
+ A2dpCodecConfig* findSinkCodecConfig(const uint8_t* p_codec_info);
+
// Gets the codec config that is currently selected.
// Returns the codec config that is currently selected, or nullptr if
// no codec is selected.
@@ -331,6 +358,13 @@
uint8_t* p_result_codec_config,
bool select_current_codec);
+ // Sets the A2DP Sink codec configuration to be used with a peer Source
+ // device.
+ // [See setCodecConfig() for description]
+ bool setSinkCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
+ uint8_t* p_result_codec_config,
+ bool select_current_codec);
+
// Sets the user prefered codec configuration.
// |codec_user_config| contains the preferred codec configuration.
// |p_peer_params| contains the A2DP peer information.
@@ -390,6 +424,16 @@
uint8_t* p_result_codec_config, bool* p_restart_input,
bool* p_restart_output, bool* p_config_updated);
+ // Sets the codec capabilities for a Sink peer.
+ // |p_peer_codec_capabiltities| is the peer codec capabilities to set.
+ // Returns true on success, otherwise false.
+ bool setPeerSinkCodecCapabilities(const uint8_t* p_peer_codec_capabilities);
+
+ // Sets the codec capabilities for a Source peer.
+ // |p_peer_codec_capabiltities| is the peer codec capabilities to set.
+ // Returns true on success, otherwise false.
+ bool setPeerSourceCodecCapabilities(const uint8_t* p_peer_codec_capabilities);
+
// Gets the current codec configuration and the capabilities of
// all configured codecs.
// The current codec configuration is stored in |p_codec_config|.
@@ -453,8 +497,11 @@
// responsible for freeing |p_buf|.
// |frames_n| is the number of audio frames in |p_buf| - it is used for
// statistics purpose.
+// |num_bytes| is the number of audio bytes in |p_buf| - it is used for
+// delay reporting.
// Returns true if the packet was enqueued, otherwise false.
-typedef bool (*a2dp_source_enqueue_callback_t)(BT_HDR* p_buf, size_t frames_n);
+typedef bool (*a2dp_source_enqueue_callback_t)(BT_HDR* p_buf, size_t frames_n,
+ uint32_t num_bytes);
//
// A2DP encoder callbacks interface.
@@ -490,6 +537,27 @@
void (*set_transmit_queue_length)(size_t transmit_queue_length);
} tA2DP_ENCODER_INTERFACE;
+// Prototype for a callback to receive decoded audio data from a
+// tA2DP_DECODER_INTERFACE|.
+// |buf| is a pointer to the data.
+// |len| is the number of octets pointed to by |buf|.
+typedef void (*decoded_data_callback_t)(uint8_t* buf, uint32_t len);
+
+//
+// A2DP decoder callbacks interface.
+//
+typedef struct {
+ // Initialize the decoder. Can be called multiple times, will reinitalize.
+ bool (*decoder_init)(decoded_data_callback_t decode_callback);
+
+ // Cleanup the A2DP decoder.
+ void (*decoder_cleanup)();
+
+ // Decodes |p_buf| and calls |decode_callback| passed into init for the
+ // decoded data.
+ bool (*decode_packet)(BT_HDR* p_buf);
+} tA2DP_DECODER_INTERFACE;
+
// Gets the A2DP codec type.
// |p_codec_info| contains information about the codec capabilities.
tA2DP_CODEC_TYPE A2DP_GetCodecType(const uint8_t* p_codec_info);
@@ -536,14 +604,6 @@
// |p_codec_info|.
void A2DP_InitDefaultCodec(uint8_t* p_codec_info);
-// Builds A2DP preferred Sink capability from Source capability.
-// |p_src_cap| is the Source capability to use.
-// |p_pref_cfg| is the result Sink capability to store.
-// Returns |A2DP_SUCCESS| on success, otherwise the corresponding A2DP error
-// status code.
-tA2DP_STATUS A2DP_BuildSrc2SinkConfig(const uint8_t* p_src_cap,
- uint8_t* p_pref_cfg);
-
// Checks whether the A2DP data packets should contain RTP header.
// |content_protection_enabled| is true if Content Protection is
// enabled. |p_codec_info| contains information about the codec capabilities.
@@ -592,14 +652,6 @@
// contains invalid codec information.
int A2DP_GetSinkTrackChannelType(const uint8_t* p_codec_info);
-// Computes the number of frames to process in a time window for the A2DP
-// Sink codec. |time_interval_ms| is the time interval (in milliseconds).
-// |p_codec_info| is a pointer to the codec_info to decode.
-// Returns the number of frames to process on success, or -1 if |p_codec_info|
-// contains invalid codec information.
-int A2DP_GetSinkFramesCountToProcess(uint64_t time_interval_ms,
- const uint8_t* p_codec_info);
-
// Gets the A2DP audio data timestamp from an audio packet.
// |p_codec_info| contains the codec information.
// |p_data| contains the audio data.
@@ -624,6 +676,14 @@
const tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterface(
const uint8_t* p_codec_info);
+// Gets the A2DP decoder interface that can be used to decode received A2DP
+// packets - see |tA2DP_DECODER_INTERFACE|.
+// |p_codec_info| contains the codec information.
+// Returns the A2DP decoder interface if the |p_codec_info| is valid and
+// supported, otherwise NULL.
+const tA2DP_DECODER_INTERFACE* A2DP_GetDecoderInterface(
+ const uint8_t* p_codec_info);
+
// Adjusts the A2DP codec, based on local support and Bluetooth specification.
// |p_codec_info| contains the codec information to adjust.
// Returns true if |p_codec_info| is valid and supported, otherwise false.
@@ -634,45 +694,52 @@
// otherwise |BTAV_A2DP_CODEC_INDEX_MAX|.
btav_a2dp_codec_index_t A2DP_SourceCodecIndex(const uint8_t* p_codec_info);
+// Gets the A2DP Sink codec index for a given |p_codec_info|.
+// Returns the corresponding |btav_a2dp_codec_index_t| on success,
+// otherwise |BTAV_A2DP_CODEC_INDEX_MAX|.
+btav_a2dp_codec_index_t A2DP_SinkCodecIndex(const uint8_t* p_codec_info);
+
// Gets the A2DP codec name for a given |codec_index|.
const char* A2DP_CodecIndexStr(btav_a2dp_codec_index_t codec_index);
-// Initializes A2DP codec-specific information into |tAVDT_CFG| configuration
-// entry pointed by |p_cfg|. The selected codec is defined by |codec_index|.
+// Initializes A2DP codec-specific information into |AvdtpSepConfig|
+// configuration entry pointed by |p_cfg|. The selected codec is defined
+// by |codec_index|.
// Returns true on success, otherwise false.
bool A2DP_InitCodecConfig(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg);
+ AvdtpSepConfig* p_cfg);
-// Decodes and displays A2DP codec info when using |LOG_DEBUG|.
-// |p_codec_info| is a pointer to the codec_info to decode and display.
-// Returns true if the codec information is valid, otherwise false.
-bool A2DP_DumpCodecInfo(const uint8_t* p_codec_info);
+// Decodes A2DP codec info into a human readable string.
+// |p_codec_info| is a pointer to the codec_info to decode.
+// Returns a string describing the codec information.
+std::string A2DP_CodecInfoString(const uint8_t* p_codec_info);
// Add enum-based flag operators to the btav_a2dp_codec_config_t fields
#ifndef DEFINE_ENUM_FLAG_OPERATORS
+// Use NOLINT to suppress missing parentheses warnings around bitmask.
#define DEFINE_ENUM_FLAG_OPERATORS(bitmask) \
extern "C++" { \
- inline constexpr bitmask operator&(bitmask X, bitmask Y) { \
+ inline constexpr bitmask operator&(bitmask X, bitmask Y) { /* NOLINT */ \
return static_cast<bitmask>(static_cast<int>(X) & static_cast<int>(Y)); \
} \
- inline constexpr bitmask operator|(bitmask X, bitmask Y) { \
+ inline constexpr bitmask operator|(bitmask X, bitmask Y) { /* NOLINT */ \
return static_cast<bitmask>(static_cast<int>(X) | static_cast<int>(Y)); \
} \
- inline constexpr bitmask operator^(bitmask X, bitmask Y) { \
+ inline constexpr bitmask operator^(bitmask X, bitmask Y) { /* NOLINT */ \
return static_cast<bitmask>(static_cast<int>(X) ^ static_cast<int>(Y)); \
} \
- inline constexpr bitmask operator~(bitmask X) { \
+ inline constexpr bitmask operator~(bitmask X) { /* NOLINT */ \
return static_cast<bitmask>(~static_cast<int>(X)); \
} \
- inline bitmask& operator&=(bitmask& X, bitmask Y) { \
+ inline bitmask& operator&=(bitmask& X, bitmask Y) { /* NOLINT */ \
X = X & Y; \
return X; \
} \
- inline bitmask& operator|=(bitmask& X, bitmask Y) { \
+ inline bitmask& operator|=(bitmask& X, bitmask Y) { /* NOLINT */ \
X = X | Y; \
return X; \
} \
- inline bitmask& operator^=(bitmask& X, bitmask Y) { \
+ inline bitmask& operator^=(bitmask& X, bitmask Y) { /* NOLINT */ \
X = X ^ Y; \
return X; \
} \
diff --git a/stack/include/a2dp_constants.h b/stack/include/a2dp_constants.h
index 479d9e4..f0d7b22 100644
--- a/stack/include/a2dp_constants.h
+++ b/stack/include/a2dp_constants.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2000-2012 Broadcom Corporation
+ * Copyright 2000-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_error_codes.h b/stack/include/a2dp_error_codes.h
index 9983a03..0aa7105 100644
--- a/stack/include/a2dp_error_codes.h
+++ b/stack/include/a2dp_error_codes.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2000-2012 Broadcom Corporation
+ * Copyright 2000-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_sbc.h b/stack/include/a2dp_sbc.h
index a19dd20..0381d311 100644
--- a/stack/include/a2dp_sbc.h
+++ b/stack/include/a2dp_sbc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,15 +25,31 @@
#include "a2dp_sbc_constants.h"
#include "avdt_api.h"
-class A2dpCodecConfigSbc : public A2dpCodecConfig {
+class A2dpCodecConfigSbcBase : public A2dpCodecConfig {
+ protected:
+ A2dpCodecConfigSbcBase(btav_a2dp_codec_index_t codec_index,
+ const std::string& name,
+ btav_a2dp_codec_priority_t codec_priority,
+ bool is_source)
+ : A2dpCodecConfig(codec_index, name, codec_priority),
+ is_source_(is_source) {}
+ bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
+ uint8_t* p_result_codec_config) override;
+ bool setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) override;
+
+ private:
+ bool is_source_; // True if local is Source
+};
+
+class A2dpCodecConfigSbcSource : public A2dpCodecConfigSbcBase {
public:
- A2dpCodecConfigSbc(btav_a2dp_codec_priority_t codec_priority);
- virtual ~A2dpCodecConfigSbc();
+ A2dpCodecConfigSbcSource(btav_a2dp_codec_priority_t codec_priority);
+ virtual ~A2dpCodecConfigSbcSource();
bool init() override;
period_ms_t encoderIntervalMs() const override;
- bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
- uint8_t* p_result_codec_config) override;
+ int getEffectiveMtu() const override;
private:
bool useRtpHeaderMarkerBit() const override;
@@ -44,15 +60,14 @@
void debug_codec_dump(int fd) override;
};
-class A2dpCodecConfigSbcSink : public A2dpCodecConfig {
+class A2dpCodecConfigSbcSink : public A2dpCodecConfigSbcBase {
public:
A2dpCodecConfigSbcSink(btav_a2dp_codec_priority_t codec_priority);
virtual ~A2dpCodecConfigSbcSink();
bool init() override;
period_ms_t encoderIntervalMs() const override;
- bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
- uint8_t* p_result_codec_config) override;
+ int getEffectiveMtu() const override;
private:
bool useRtpHeaderMarkerBit() const override;
@@ -106,14 +121,6 @@
// |p_codec_info|.
void A2DP_InitDefaultCodecSbc(uint8_t* p_codec_info);
-// Builds A2DP preferred SBC Sink capability from SBC Source capability.
-// |p_src_cap| is the Source capability to use.
-// |p_pref_cfg| is the result Sink capability to store.
-// Returns |A2DP_SUCCESS| on success, otherwise the corresponding A2DP error
-// status code.
-tA2DP_STATUS A2DP_BuildSrc2SinkConfigSbc(const uint8_t* p_src_cap,
- uint8_t* p_pref_cfg);
-
// Gets the A2DP SBC codec name for a given |p_codec_info|.
const char* A2DP_CodecNameSbc(const uint8_t* p_codec_info);
@@ -196,14 +203,6 @@
// contains invalid codec information.
int A2DP_GetSinkTrackChannelTypeSbc(const uint8_t* p_codec_info);
-// Computes the number of frames to process in a time window for the A2DP
-// SBC sink codec. |time_interval_ms| is the time interval (in milliseconds).
-// |p_codec_info| is a pointer to the codec_info to decode.
-// Returns the number of frames to process on success, or -1 if |p_codec_info|
-// contains invalid codec information.
-int A2DP_GetSinkFramesCountToProcessSbc(uint64_t time_interval_ms,
- const uint8_t* p_codec_info);
-
// Gets the A2DP SBC audio data timestamp from an audio packet.
// |p_codec_info| contains the codec information.
// |p_data| contains the audio data.
@@ -220,10 +219,10 @@
bool A2DP_BuildCodecHeaderSbc(const uint8_t* p_codec_info, BT_HDR* p_buf,
uint16_t frames_per_packet);
-// Decodes and displays A2DP SBC codec info when using |LOG_DEBUG|.
-// |p_codec_info| is a pointer to the SBC codec_info to decode and display.
-// Returns true if the codec information is valid, otherwise false.
-bool A2DP_DumpCodecInfoSbc(const uint8_t* p_codec_info);
+// Decodes A2DP SBC codec info into a human readable string.
+// |p_codec_info| is a pointer to the SBC codec_info to decode.
+// Returns a string describing the codec information.
+std::string A2DP_CodecInfoStringSbc(const uint8_t* p_codec_info);
// Gets the A2DP SBC encoder interface that can be used to encode and prepare
// A2DP packets for transmission - see |tA2DP_ENCODER_INTERFACE|.
@@ -233,6 +232,14 @@
const tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterfaceSbc(
const uint8_t* p_codec_info);
+// Gets the A2DP SBC decoder interface that can be used to decode received A2DP
+// packets - see |tA2DP_DECODER_INTERFACE|.
+// |p_codec_info| contains the codec information.
+// Returns the A2DP SBC decoder interface if the |p_codec_info| is valid and
+// supported, otherwise NULL.
+const tA2DP_DECODER_INTERFACE* A2DP_GetDecoderInterfaceSbc(
+ const uint8_t* p_codec_info);
+
// Adjusts the A2DP SBC codec, based on local support and Bluetooth
// specification.
// |p_codec_info| contains the codec information to adjust.
@@ -244,18 +251,27 @@
// otherwise |BTAV_A2DP_CODEC_INDEX_MAX|.
btav_a2dp_codec_index_t A2DP_SourceCodecIndexSbc(const uint8_t* p_codec_info);
+// Gets the A2DP SBC Sink codec index for a given |p_codec_info|.
+// Returns the corresponding |btav_a2dp_codec_index_t| on success,
+// otherwise |BTAV_A2DP_CODEC_INDEX_MAX|.
+btav_a2dp_codec_index_t A2DP_SinkCodecIndexSbc(const uint8_t* p_codec_info);
+
// Gets the A2DP SBC Source codec name.
const char* A2DP_CodecIndexStrSbc(void);
// Gets the A2DP SBC Sink codec name.
const char* A2DP_CodecIndexStrSbcSink(void);
-// Initializes A2DP SBC Source codec information into |tAVDT_CFG| configuration
-// entry pointed by |p_cfg|.
-bool A2DP_InitCodecConfigSbc(tAVDT_CFG* p_cfg);
+// Initializes A2DP SBC Source codec information into |AvdtpSepConfig|
+// configuration entry pointed by |p_cfg|.
+bool A2DP_InitCodecConfigSbc(AvdtpSepConfig* p_cfg);
-// Initializes A2DP SBC Sink codec information into |tAVDT_CFG| configuration
-// entry pointed by |p_cfg|.
-bool A2DP_InitCodecConfigSbcSink(tAVDT_CFG* p_cfg);
+// Initializes A2DP SBC Sink codec information into |AvdtpSepConfig|
+// configuration entry pointed by |p_cfg|.
+bool A2DP_InitCodecConfigSbcSink(AvdtpSepConfig* p_cfg);
+
+// Get SBC bitrate
+// Returns |uint32_t| bitrate value in bits per second
+uint32_t A2DP_GetBitrateSbc();
#endif // A2DP_SBC_H
diff --git a/stack/include/a2dp_sbc_constants.h b/stack/include/a2dp_sbc_constants.h
index cb3b801..87b9eb9 100644
--- a/stack/include/a2dp_sbc_constants.h
+++ b/stack/include/a2dp_sbc_constants.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2000-2012 Broadcom Corporation
+ * Copyright 2000-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_sbc_decoder.h b/stack/include/a2dp_sbc_decoder.h
new file mode 100644
index 0000000..f5ac99a
--- /dev/null
+++ b/stack/include/a2dp_sbc_decoder.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Interface to the A2DP SBC Decoder
+//
+
+#ifndef A2DP_SBC_DECODER_H
+#define A2DP_SBC_DECODER_H
+
+#include "a2dp_codec_api.h"
+
+// Loads the A2DP SBC decoder.
+// Return true on success, otherwise false.
+bool A2DP_LoadDecoderSbc(void);
+
+// Unloads the A2DP SBC decoder.
+void A2DP_UnloadDecoderSbc(void);
+
+// Initialize the A2DP SBC decoder.
+bool a2dp_sbc_decoder_init(decoded_data_callback_t decode_callback);
+
+// Cleanup the A2DP SBC decoder.
+void a2dp_sbc_decoder_cleanup(void);
+
+// Decodes |p_buf|. Calls |decode_callback| passed into |a2dp_sbc_decoder_init|
+// if decoded frames are available.
+bool a2dp_sbc_decoder_decode_packet(BT_HDR* p_buf);
+
+#endif // A2DP_SBC_DECODER_H
diff --git a/stack/include/a2dp_sbc_encoder.h b/stack/include/a2dp_sbc_encoder.h
index 6ff1cf7..a853012 100644
--- a/stack/include/a2dp_sbc_encoder.h
+++ b/stack/include/a2dp_sbc_encoder.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,4 +60,7 @@
// |timestamp_us| is the current timestamp (in microseconds).
void a2dp_sbc_send_frames(uint64_t timestamp_us);
+// Get SBC bitrate
+// Returns |uint32_t| bitrate in bits per second
+uint32_t a2dp_sbc_get_bitrate();
#endif // A2DP_SBC_ENCODER_H
diff --git a/stack/include/a2dp_sbc_up_sample.h b/stack/include/a2dp_sbc_up_sample.h
index 234ce54..ac83961 100644
--- a/stack/include/a2dp_sbc_up_sample.h
+++ b/stack/include/a2dp_sbc_up_sample.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_vendor.h b/stack/include/a2dp_vendor.h
index 2b90041..0b5ba7c 100644
--- a/stack/include/a2dp_vendor.h
+++ b/stack/include/a2dp_vendor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -76,15 +76,6 @@
// device is supported, otherwise false.
bool A2DP_IsVendorPeerSourceCodecSupported(const uint8_t* p_codec_info);
-// Builds a vendor-specific A2DP preferred Sink capability from a vendor
-// Source capability.
-// |p_src_cap| is the Source capability to use.
-// |p_pref_cfg| is the result Sink capability to store.
-// Returns |A2DP_SUCCESS| on success, otherwise the corresponding A2DP error
-// status code.
-tA2DP_STATUS A2DP_VendorBuildSrc2SinkConfig(const uint8_t* p_src_cap,
- uint8_t* p_pref_cfg);
-
// Gets the Vendor ID for the vendor-specific A2DP codec.
// |p_codec_info| contains information about the codec capabilities.
// Returns the Vendor ID for the vendor-specific A2DP codec.
@@ -132,6 +123,12 @@
// contains invalid codec information.
int A2DP_VendorGetTrackChannelCount(const uint8_t* p_codec_info);
+// Gets the bitrate for the A2DP vendor-specific codec.
+// |p_codec_info| is a pointer to the vendor-specific codec_info to decode.
+// Returns the channel count on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_VendorGetBitRate(const uint8_t* p_codec_info);
+
// Gets the channel type for the A2DP vendor-specific Sink codec:
// 1 for mono, or 3 for dual/stereo/joint.
// |p_codec_info| is a pointer to the vendor-specific codec_info to decode.
@@ -139,15 +136,6 @@
// contains invalid codec information.
int A2DP_VendorGetSinkTrackChannelType(const uint8_t* p_codec_info);
-// Computes the number of frames to process in a time window for the A2DP
-// vendor-specific Sink codec. |time_interval_ms| is the time interval
-// (in milliseconds).
-// |p_codec_info| is a pointer to the codec_info to decode.
-// Returns the number of frames to process on success, or -1 if |p_codec_info|
-// contains invalid codec information.
-int A2DP_VendorGetSinkFramesCountToProcess(uint64_t time_interval_ms,
- const uint8_t* p_codec_info);
-
// Gets the A2DP codec-specific audio data timestamp from an audio packet.
// |p_codec_info| contains the codec information.
// |p_data| contains the audio data.
@@ -173,6 +161,14 @@
const tA2DP_ENCODER_INTERFACE* A2DP_VendorGetEncoderInterface(
const uint8_t* p_codec_info);
+// Gets the current A2DP vendor decoder interface that can be used to decode
+// received A2DP packets - see |tA2DP_DECODER_INTERFACE|.
+// |p_codec_info| contains the codec information.
+// Returns the A2DP vendor decoder interface if the |p_codec_info| is valid and
+// supported, otherwise NULL.
+const tA2DP_DECODER_INTERFACE* A2DP_VendorGetDecoderInterface(
+ const uint8_t* p_codec_info);
+
// Adjusts the A2DP vendor-specific codec, based on local support and Bluetooth
// specification.
// |p_codec_info| contains the codec information to adjust.
@@ -185,19 +181,24 @@
btav_a2dp_codec_index_t A2DP_VendorSourceCodecIndex(
const uint8_t* p_codec_info);
+// Gets the A2DP vendor Sink codec index for a given |p_codec_info|.
+// Returns the corresponding |btav_a2dp_codec_index_t| on success,
+// otherwise |BTAV_A2DP_CODEC_INDEX_MAX|.
+btav_a2dp_codec_index_t A2DP_VendorSinkCodecIndex(const uint8_t* p_codec_info);
+
// Gets the A2DP vendor codec name for a given |codec_index|.
const char* A2DP_VendorCodecIndexStr(btav_a2dp_codec_index_t codec_index);
-// Initializes A2DP vendor codec-specific information into |tAVDT_CFG|
+// Initializes A2DP vendor codec-specific information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|. The selected codec is defined by
// |codec_index|.
// Returns true on success, otherwise false.
bool A2DP_VendorInitCodecConfig(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg);
+ AvdtpSepConfig* p_cfg);
-// Decodes and displays A2DP vendor codec info when using |LOG_DEBUG|.
-// |p_codec_info| is a pointer to the codec_info to decode and display.
-// Returns true if the codec information is valid, otherwise false.
-bool A2DP_VendorDumpCodecInfo(const uint8_t* p_codec_info);
+// Decodes A2DP vendor codec info into a human readable string.
+// |p_codec_info| is a pointer to the codec_info to decode.
+// Returns a string describing the codec information.
+std::string A2DP_VendorCodecInfoString(const uint8_t* p_codec_info);
#endif // A2DP_VENDOR_H
diff --git a/stack/include/a2dp_vendor_aptx.h b/stack/include/a2dp_vendor_aptx.h
index b1bebf0..38a1245 100644
--- a/stack/include/a2dp_vendor_aptx.h
+++ b/stack/include/a2dp_vendor_aptx.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,8 +32,11 @@
bool init() override;
period_ms_t encoderIntervalMs() const override;
+ int getEffectiveMtu() const override;
bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
uint8_t* p_result_codec_config) override;
+ bool setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) override;
private:
bool useRtpHeaderMarkerBit() const override;
@@ -88,6 +91,12 @@
// contains invalid codec information.
int A2DP_VendorGetTrackSampleRateAptx(const uint8_t* p_codec_info);
+// Gets the track bitrate value for the A2DP aptX codec.
+// |p_codec_info| is a pointer to the aptX codec_info to decode.
+// Returns the track sample rate on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_VendorGetBitRateAptx(const uint8_t* p_codec_info);
+
// Gets the channel count for the A2DP aptX codec.
// |p_codec_info| is a pointer to the aptX codec_info to decode.
// Returns the channel count on success, or -1 if |p_codec_info|
@@ -111,10 +120,10 @@
bool A2DP_VendorBuildCodecHeaderAptx(const uint8_t* p_codec_info, BT_HDR* p_buf,
uint16_t frames_per_packet);
-// Decodes and displays A2DP aptX codec info when using |LOG_DEBUG|.
-// |p_codec_info| is a pointer to the aptX codec_info to decode and display.
-// Returns true if the codec information is valid, otherwise false.
-bool A2DP_VendorDumpCodecInfoAptx(const uint8_t* p_codec_info);
+// Decodes A2DP aptX codec info into a human readable string.
+// |p_codec_info| is a pointer to the aptX codec_info to decode.
+// Returns a string describing the codec information.
+std::string A2DP_VendorCodecInfoStringAptx(const uint8_t* p_codec_info);
// Gets the A2DP aptX encoder interface that can be used to encode and prepare
// A2DP packets for transmission - see |tA2DP_ENCODER_INTERFACE|.
@@ -139,8 +148,8 @@
// Gets the A2DP aptX Source codec name.
const char* A2DP_VendorCodecIndexStrAptx(void);
-// Initializes A2DP aptX Source codec information into |tAVDT_CFG|
+// Initializes A2DP aptX Source codec information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|.
-bool A2DP_VendorInitCodecConfigAptx(tAVDT_CFG* p_cfg);
+bool A2DP_VendorInitCodecConfigAptx(AvdtpSepConfig* p_cfg);
#endif // A2DP_VENDOR_APTX_H
diff --git a/stack/include/a2dp_vendor_aptx_constants.h b/stack/include/a2dp_vendor_aptx_constants.h
index 0f2c7c6..d9e86cc 100644
--- a/stack/include/a2dp_vendor_aptx_constants.h
+++ b/stack/include/a2dp_vendor_aptx_constants.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_vendor_aptx_encoder.h b/stack/include/a2dp_vendor_aptx_encoder.h
index 7a67307..7deaca3 100644
--- a/stack/include/a2dp_vendor_aptx_encoder.h
+++ b/stack/include/a2dp_vendor_aptx_encoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_vendor_aptx_hd.h b/stack/include/a2dp_vendor_aptx_hd.h
index 5a4a748..05ca16f 100644
--- a/stack/include/a2dp_vendor_aptx_hd.h
+++ b/stack/include/a2dp_vendor_aptx_hd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,8 +32,11 @@
bool init() override;
period_ms_t encoderIntervalMs() const override;
+ int getEffectiveMtu() const override;
bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
uint8_t* p_result_codec_config) override;
+ bool setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) override;
private:
bool useRtpHeaderMarkerBit() const override;
@@ -88,6 +91,12 @@
// contains invalid codec information.
int A2DP_VendorGetTrackSampleRateAptxHd(const uint8_t* p_codec_info);
+// Gets the track bitrate value for the A2DP aptX-HD codec.
+// |p_codec_info| is a pointer to the aptX-HD codec_info to decode.
+// Returns the track sample rate on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_VendorGetBitRateAptxHd(const uint8_t* p_codec_info);
+
// Gets the channel count for the A2DP aptX-HD codec.
// |p_codec_info| is a pointer to the aptX-HD codec_info to decode.
// Returns the channel count on success, or -1 if |p_codec_info|
@@ -112,10 +121,10 @@
BT_HDR* p_buf,
uint16_t frames_per_packet);
-// Decodes and displays A2DP aptX-HD codec info when using |LOG_DEBUG|.
-// |p_codec_info| is a pointer to the aptX-HD codec_info to decode and display.
-// Returns true if the codec information is valid, otherwise false.
-bool A2DP_VendorDumpCodecInfoAptxHd(const uint8_t* p_codec_info);
+// Decodes A2DP aptX-HD codec info into a human readable string.
+// |p_codec_info| is a pointer to the aptX-HD codec_info to decode.
+// Returns a string describing the codec information.
+std::string A2DP_VendorCodecInfoStringAptxHd(const uint8_t* p_codec_info);
// Gets the A2DP aptX-HD encoder interface that can be used to encode and
// prepare A2DP packets for transmission - see |tA2DP_ENCODER_INTERFACE|.
@@ -140,8 +149,8 @@
// Gets the A2DP aptX-HD Source codec name.
const char* A2DP_VendorCodecIndexStrAptxHd(void);
-// Initializes A2DP aptX-HD Source codec information into |tAVDT_CFG|
+// Initializes A2DP aptX-HD Source codec information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|.
-bool A2DP_VendorInitCodecConfigAptxHd(tAVDT_CFG* p_cfg);
+bool A2DP_VendorInitCodecConfigAptxHd(AvdtpSepConfig* p_cfg);
#endif // A2DP_VENDOR_APTX_HD_H
diff --git a/stack/include/a2dp_vendor_aptx_hd_constants.h b/stack/include/a2dp_vendor_aptx_hd_constants.h
index 40ac8b5..e4d8ff8 100644
--- a/stack/include/a2dp_vendor_aptx_hd_constants.h
+++ b/stack/include/a2dp_vendor_aptx_hd_constants.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_vendor_aptx_hd_encoder.h b/stack/include/a2dp_vendor_aptx_hd_encoder.h
index b662e8e..53e7d02 100644
--- a/stack/include/a2dp_vendor_aptx_hd_encoder.h
+++ b/stack/include/a2dp_vendor_aptx_hd_encoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_vendor_ldac.h b/stack/include/a2dp_vendor_ldac.h
index 5302c07..ccb5d1e 100644
--- a/stack/include/a2dp_vendor_ldac.h
+++ b/stack/include/a2dp_vendor_ldac.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,8 +32,11 @@
bool init() override;
period_ms_t encoderIntervalMs() const override;
+ int getEffectiveMtu() const override;
bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
uint8_t* p_result_codec_config) override;
+ bool setPeerCodecCapabilities(
+ const uint8_t* p_peer_codec_capabilities) override;
private:
bool useRtpHeaderMarkerBit() const override;
@@ -88,6 +91,12 @@
// contains invalid codec information.
int A2DP_VendorGetTrackSampleRateLdac(const uint8_t* p_codec_info);
+// Gets the track bitrate value for the A2DP LDAC codec.
+// |p_codec_info| is a pointer to the LDAC codec_info to decode.
+// Returns the track sample rate on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_VendorGetBitRateLdac(const uint8_t* p_codec_info);
+
// Gets the channel count for the A2DP LDAC codec.
// |p_codec_info| is a pointer to the LDAC codec_info to decode.
// Returns the channel count on success, or -1 if |p_codec_info|
@@ -118,10 +127,10 @@
bool A2DP_VendorBuildCodecHeaderLdac(const uint8_t* p_codec_info, BT_HDR* p_buf,
uint16_t frames_per_packet);
-// Decodes and displays A2DP LDAC codec info when using |LOG_DEBUG|.
-// |p_codec_info| is a pointer to the LDAC codec_info to decode and display.
-// Returns true if the codec information is valid, otherwise false.
-bool A2DP_VendorDumpCodecInfoLdac(const uint8_t* p_codec_info);
+// Decodes A2DP LDAC codec info into a human readable string.
+// |p_codec_info| is a pointer to the LDAC codec_info to decode.
+// Returns a string describing the codec information.
+std::string A2DP_VendorCodecInfoStringLdac(const uint8_t* p_codec_info);
// Gets the A2DP LDAC encoder interface that can be used to encode and prepare
// A2DP packets for transmission - see |tA2DP_ENCODER_INTERFACE|.
@@ -146,8 +155,8 @@
// Gets the A2DP LDAC Source codec name.
const char* A2DP_VendorCodecIndexStrLdac(void);
-// Initializes A2DP LDAC Source codec information into |tAVDT_CFG|
+// Initializes A2DP LDAC Source codec information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|.
-bool A2DP_VendorInitCodecConfigLdac(tAVDT_CFG* p_cfg);
+bool A2DP_VendorInitCodecConfigLdac(AvdtpSepConfig* p_cfg);
#endif // A2DP_VENDOR_LDAC_H
diff --git a/stack/include/a2dp_vendor_ldac_abr.h b/stack/include/a2dp_vendor_ldac_abr.h
index 157dbba..e479ac7 100644
--- a/stack/include/a2dp_vendor_ldac_abr.h
+++ b/stack/include/a2dp_vendor_ldac_abr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/a2dp_vendor_ldac_constants.h b/stack/include/a2dp_vendor_ldac_constants.h
index 6242add..9cb9200 100644
--- a/stack/include/a2dp_vendor_ldac_constants.h
+++ b/stack/include/a2dp_vendor_ldac_constants.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,8 @@
#define A2DP_LDAC_QUALITY_MID 1 // Equal to LDACBT_EQMID_SQ 660kbps
#define A2DP_LDAC_QUALITY_LOW 2 // Equal to LDACBT_EQMID_MQ 330kbps
#define A2DP_LDAC_QUALITY_ABR 3 // ABR mode, range: 990,660,492,396,330(kbps)
+// ABR mode in offload, range: 990,660,492,396,330(kbps)
+#define A2DP_LDAC_QUALITY_ABR_OFFLOAD 0x7F
// Length of the LDAC Media Payload header
#define A2DP_LDAC_MPL_HDR_LEN 1
diff --git a/stack/include/a2dp_vendor_ldac_encoder.h b/stack/include/a2dp_vendor_ldac_encoder.h
index 45694f0..810f03b 100644
--- a/stack/include/a2dp_vendor_ldac_encoder.h
+++ b/stack/include/a2dp_vendor_ldac_encoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/advertise_data_parser.h b/stack/include/advertise_data_parser.h
index 473b979..b62dbb3 100644
--- a/stack/include/advertise_data_parser.h
+++ b/stack/include/advertise_data_parser.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -57,12 +57,7 @@
// end of the packet. Otherwise i.e. gluing scan response to advertise
// data will result in data with zero padding in the middle.
if (len == 0) {
- size_t zeros_start = position;
- for (size_t i = position + 1; i < ad_len; i++) {
- if (ad[i] != 0) return;
- }
-
- ad.erase(ad.begin() + zeros_start, ad.end());
+ ad.erase(ad.begin() + position, ad.end());
return;
}
diff --git a/stack/include/avct_api.h b/stack/include/avct_api.h
index a0380b3..21a880a 100644
--- a/stack/include/avct_api.h
+++ b/stack/include/avct_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/avdt_api.h b/stack/include/avdt_api.h
index 6fb1441..fd0721c 100644
--- a/stack/include/avdt_api.h
+++ b/stack/include/avdt_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,11 +31,10 @@
/*****************************************************************************
* Constants
****************************************************************************/
-#ifndef AVDT_VERSION
-#define AVDT_VERSION 0x0102
-#endif
#define AVDT_VERSION_1_3 0x0103
+#define AVDTP_VERSION_CONFIG_KEY "AvdtpVersion"
+
/* Maximum size in bytes of the codec capabilities information element. */
#define AVDT_CODEC_SIZE 20
@@ -236,11 +235,6 @@
/* PSM for AVDT */
#define AVDT_PSM 0x0019
-/* Nonsupported protocol command messages. This value is used in tAVDT_CS */
-#define AVDT_NSC_SUSPEND 0x01 /* Suspend command not supported */
-#define AVDT_NSC_RECONFIG 0x02 /* Reconfigure command not supported */
-#define AVDT_NSC_SECURITY 0x04 /* Security command not supported */
-
/*****************************************************************************
* Type Definitions
****************************************************************************/
@@ -270,14 +264,36 @@
uint8_t cname[AVDT_MAX_CNAME_SIZE + 1];
} tAVDT_REPORT_DATA;
-/* This structure contains parameters which are set at registration. */
-typedef struct {
+/**
+ * AVDTP Registration Control Block.
+ */
+class AvdtpRcb {
+ public:
+ AvdtpRcb()
+ : ctrl_mtu(0),
+ ret_tout(0),
+ sig_tout(0),
+ idle_tout(0),
+ sec_mask(0),
+ scb_index(0) {}
+ AvdtpRcb& operator=(const AvdtpRcb&) = default;
+
+ void Reset() {
+ ctrl_mtu = 0;
+ ret_tout = 0;
+ sig_tout = 0;
+ idle_tout = 0;
+ sec_mask = 0;
+ scb_index = 0;
+ }
+
uint16_t ctrl_mtu; /* L2CAP MTU of the AVDTP signaling channel */
uint8_t ret_tout; /* AVDTP signaling retransmission timeout */
uint8_t sig_tout; /* AVDTP signaling message timeout */
uint8_t idle_tout; /* AVDTP idle signaling channel timeout */
uint8_t sec_mask; /* Security mask for BTM_SetSecurityLevel() */
-} tAVDT_REG;
+ uint8_t scb_index; /* The Stream Control Block index */
+};
/* This structure contains the SEP information. This information is
* transferred during the discovery procedure.
@@ -289,8 +305,35 @@
uint8_t tsep; /* SEP type */
} tAVDT_SEP_INFO;
-/* This structure contains the SEP configuration. */
-typedef struct {
+/**
+ * AVDTP SEP Configuration.
+ */
+class AvdtpSepConfig {
+ public:
+ AvdtpSepConfig()
+ : codec_info{},
+ protect_info{},
+ num_codec(0),
+ num_protect(0),
+ psc_mask(0),
+ recov_type(0),
+ recov_mrws(0),
+ recov_mnmp(0),
+ hdrcmp_mask(0) {}
+ AvdtpSepConfig& operator=(const AvdtpSepConfig&) = default;
+
+ void Reset() {
+ memset(codec_info, 0, sizeof(codec_info));
+ memset(protect_info, 0, sizeof(protect_info));
+ num_codec = 0;
+ num_protect = 0;
+ psc_mask = 0;
+ recov_type = 0;
+ recov_mrws = 0;
+ recov_mnmp = 0;
+ hdrcmp_mask = 0;
+ }
+
uint8_t codec_info[AVDT_CODEC_SIZE]; /* Codec capabilities array */
uint8_t protect_info[AVDT_PROTECT_SIZE]; /* Content protection capabilities */
uint8_t num_codec; /* Number of media codec information elements */
@@ -300,7 +343,7 @@
uint8_t recov_mrws; /* Maximum recovery window size */
uint8_t recov_mnmp; /* Recovery maximum number of media packets */
uint8_t hdrcmp_mask; /* Header compression capabilities */
-} tAVDT_CFG;
+};
/* Header structure for callback event parameters. */
typedef struct {
@@ -318,13 +361,13 @@
*/
typedef struct {
tAVDT_EVT_HDR hdr; /* Event header */
- tAVDT_CFG* p_cfg; /* Pointer to configuration for this SEP */
+ AvdtpSepConfig* p_cfg; /* Pointer to configuration for this SEP */
} tAVDT_CONFIG;
/* This data structure is associated with the AVDT_CONFIG_IND_EVT. */
typedef struct {
tAVDT_EVT_HDR hdr; /* Event header */
- tAVDT_CFG* p_cfg; /* Pointer to configuration for this SEP */
+ AvdtpSepConfig* p_cfg; /* Pointer to configuration for this SEP */
uint8_t int_seid; /* Stream endpoint ID of stream initiating the operation */
} tAVDT_SETCONFIG;
@@ -384,8 +427,9 @@
* endpoints and for the AVDT_DiscoverReq() and AVDT_GetCapReq() functions.
*
*/
-typedef void(tAVDT_CTRL_CBACK)(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
+typedef void(tAVDT_CTRL_CBACK)(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index);
/* This is the data callback function. It is executed when AVDTP has a media
* packet ready for the application. This function is required for SNK
@@ -394,34 +438,64 @@
typedef void(tAVDT_SINK_DATA_CBACK)(uint8_t handle, BT_HDR* p_pkt,
uint32_t time_stamp, uint8_t m_pt);
-#if (AVDT_REPORTING == TRUE)
/* This is the report callback function. It is executed when AVDTP has a
* reporting packet ready for the application. This function is required for
* streams created with AVDT_PSC_REPORT.
*/
typedef void(tAVDT_REPORT_CBACK)(uint8_t handle, AVDT_REPORT_TYPE type,
tAVDT_REPORT_DATA* p_data);
-#endif
-typedef uint16_t(tAVDT_GETCAP_REQ)(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback);
+/**
+ * AVDTP Stream Configuration.
+ * The information is used when a stream is created.
+ */
+class AvdtpStreamConfig {
+ public:
+ //
+ // Non-supported protocol command messages
+ //
+ // Suspend command not supported
+ static constexpr int AVDT_NSC_SUSPEND = 0x01;
+ // Reconfigure command not supported
+ static constexpr int AVDT_NSC_RECONFIG = 0x02;
+ // Security command not supported
+ static constexpr int AVDT_NSC_SECURITY = 0x04;
-/* This structure contains information required when a stream is created.
- * It is passed to the AVDT_CreateStream() function.
-*/
-typedef struct {
- tAVDT_CFG cfg; /* SEP configuration */
- tAVDT_CTRL_CBACK* p_ctrl_cback; /* Control callback function */
- tAVDT_SINK_DATA_CBACK* p_sink_data_cback; /* Sink data callback function */
-#if (AVDT_REPORTING == TRUE)
- tAVDT_REPORT_CBACK* p_report_cback; /* Report callback function. */
-#endif
- uint16_t mtu; /* The L2CAP MTU of the transport channel */
- uint16_t flush_to; /* The L2CAP flush timeout of the transport channel */
- uint8_t tsep; /* SEP type */
- uint8_t media_type; /* Media type: AVDT_MEDIA_TYPE_* */
- uint16_t nsc_mask; /* Nonsupported protocol command messages */
-} tAVDT_CS;
+ AvdtpStreamConfig()
+ : p_avdt_ctrl_cback(nullptr),
+ scb_index(0),
+ p_sink_data_cback(nullptr),
+ p_report_cback(nullptr),
+ mtu(0),
+ flush_to(0),
+ tsep(0),
+ media_type(0),
+ nsc_mask(0) {}
+
+ void Reset() {
+ cfg.Reset();
+ p_avdt_ctrl_cback = nullptr;
+ scb_index = 0;
+ p_sink_data_cback = nullptr;
+ p_report_cback = nullptr;
+ mtu = 0;
+ flush_to = 0;
+ tsep = 0;
+ media_type = 0;
+ nsc_mask = 0;
+ }
+
+ AvdtpSepConfig cfg; // SEP configuration
+ tAVDT_CTRL_CBACK* p_avdt_ctrl_cback; // Control callback function
+ uint8_t scb_index; // The index to the bta_av_cb.p_scb[] entry
+ tAVDT_SINK_DATA_CBACK* p_sink_data_cback; // Sink data callback function
+ tAVDT_REPORT_CBACK* p_report_cback; // Report callback function
+ uint16_t mtu; // The L2CAP MTU of the transport channel
+ uint16_t flush_to; // The L2CAP flush timeout of the transport channel
+ uint8_t tsep; // SEP type
+ uint8_t media_type; // Media type: AVDT_MEDIA_TYPE_*
+ uint16_t nsc_mask; // Nonsupported protocol command messages
+};
/* AVDT data option mask is used in the write request */
#define AVDT_DATA_OPT_NONE 0x00 /* No option still add RTP header */
@@ -447,7 +521,7 @@
* Returns void
*
******************************************************************************/
-extern void AVDT_Register(tAVDT_REG* p_reg, tAVDT_CTRL_CBACK* p_cback);
+extern void AVDT_Register(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback);
/*******************************************************************************
*
@@ -489,7 +563,8 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-extern uint16_t AVDT_CreateStream(uint8_t* p_handle, tAVDT_CS* p_cs);
+extern uint16_t AVDT_CreateStream(uint8_t peer_id, uint8_t* p_handle,
+ const AvdtpStreamConfig& avdtp_stream_config);
/*******************************************************************************
*
@@ -534,6 +609,7 @@
*
******************************************************************************/
extern uint16_t AVDT_DiscoverReq(const RawAddress& bd_addr,
+ uint8_t channel_index,
tAVDT_SEP_INFO* p_sep_info, uint8_t max_seps,
tAVDT_CTRL_CBACK* p_cback);
@@ -561,35 +637,9 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-extern uint16_t AVDT_GetCapReq(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback);
-
-/*******************************************************************************
- *
- * Function AVDT_GetAllCapReq
- *
- * Description This function initiates a connection to the AVDTP service
- * on the peer device, if not already present, and gets the
- * capabilities of a stream endpoint on the peer device.
- * This function can be called at any time regardless of
- * whether there is an AVDTP connection to the peer device.
- *
- * When the procedure is complete, an AVDT_GETCAP_CFM_EVT is
- * sent to the application via its callback function. The
- * application must not call AVDT_GetCapReq() or
- * AVDT_DiscoverReq() again until the procedure is complete.
- *
- * The memory pointed to by p_cfg is allocated by the
- * application. This memory is written to by AVDTP as part
- * of the get capabilities procedure. This memory must
- * remain accessible until the application receives
- * the AVDT_GETCAP_CFM_EVT.
- *
- * Returns AVDT_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern uint16_t AVDT_GetAllCapReq(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback);
+extern uint16_t AVDT_GetCapReq(const RawAddress& bd_addr, uint8_t channel_index,
+ uint8_t seid, AvdtpSepConfig* p_cfg,
+ tAVDT_CTRL_CBACK* p_cback, bool get_all_cap);
/*******************************************************************************
*
@@ -619,7 +669,8 @@
*
******************************************************************************/
extern uint16_t AVDT_OpenReq(uint8_t handle, const RawAddress& bd_addr,
- uint8_t seid, tAVDT_CFG* p_cfg);
+ uint8_t channel_index, uint8_t seid,
+ AvdtpSepConfig* p_cfg);
/*******************************************************************************
*
@@ -703,7 +754,7 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-extern uint16_t AVDT_ReconfigReq(uint8_t handle, tAVDT_CFG* p_cfg);
+extern uint16_t AVDT_ReconfigReq(uint8_t handle, AvdtpSepConfig* p_cfg);
/*******************************************************************************
*
@@ -845,7 +896,8 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-extern uint16_t AVDT_ConnectReq(const RawAddress& bd_addr, uint8_t sec_mask,
+extern uint16_t AVDT_ConnectReq(const RawAddress& bd_addr,
+ uint8_t channel_index, uint8_t sec_mask,
tAVDT_CTRL_CBACK* p_cback);
/*******************************************************************************
@@ -924,4 +976,12 @@
*****************************************************************************/
extern uint8_t AVDT_SetTraceLevel(uint8_t new_level);
+/**
+ * Dump debug-related information for the Stack AVDTP module.
+ *
+ * @param fd the file descriptor to use for writing the ASCII formatted
+ * information
+ */
+void stack_debug_avdtp_api_dump(int fd);
+
#endif /* AVDT_API_H */
diff --git a/stack/include/avdtc_api.h b/stack/include/avdtc_api.h
index 60a7c5f..6948f83 100644
--- a/stack/include/avdtc_api.h
+++ b/stack/include/avdtc_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -107,7 +107,7 @@
*
******************************************************************************/
extern void AVDTC_GetCapRsp(const RawAddress& bd_addr, uint8_t label,
- tAVDT_CFG* p_cap);
+ AvdtpSepConfig* p_cap);
/*******************************************************************************
*
@@ -119,7 +119,7 @@
*
******************************************************************************/
extern void AVDTC_GetAllCapRsp(const RawAddress& bd_addr, uint8_t label,
- tAVDT_CFG* p_cap);
+ AvdtpSepConfig* p_cap);
/*******************************************************************************
*
@@ -141,7 +141,8 @@
* Returns void
*
******************************************************************************/
-extern void AVDTC_GetConfigRsp(uint8_t handle, uint8_t label, tAVDT_CFG* p_cfg);
+extern void AVDTC_GetConfigRsp(uint8_t handle, uint8_t label,
+ AvdtpSepConfig* p_cfg);
/*******************************************************************************
*
diff --git a/stack/include/avrc_api.h b/stack/include/avrc_api.h
index cfac8d7..1aa8ea4 100644
--- a/stack/include/avrc_api.h
+++ b/stack/include/avrc_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2012 Broadcom Corporation
+ * Copyright 2006-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,9 @@
******************************************************************************/
#ifndef AVRC_API_H
#define AVRC_API_H
+
+#include <base/bind.h>
+
#include "avct_api.h"
#include "avrc_defs.h"
#include "bt_target.h"
@@ -161,23 +164,24 @@
* implementation of this callback function must copy the p_service_name
* and p_provider_name parameters passed to it as they are not guaranteed
* to remain after the callback function exits. */
-typedef void(tAVRC_FIND_CBACK)(uint16_t status);
+using tAVRC_FIND_CBACK = base::Callback<void(uint16_t status)>;
/* This is the control callback function. This function passes events
* listed in Table 20 to the application. */
-typedef void(tAVRC_CTRL_CBACK)(uint8_t handle, uint8_t event, uint16_t result,
- const RawAddress* peer_addr);
+using tAVRC_CTRL_CBACK =
+ base::Callback<void(uint8_t handle, uint8_t event, uint16_t result,
+ const RawAddress* peer_addr)>;
/* This is the message callback function. It is executed when AVCTP has
* a message packet ready for the application. The implementation of this
* callback function must copy the tAVRC_MSG structure passed to it as it
* is not guaranteed to remain after the callback function exits. */
-typedef void(tAVRC_MSG_CBACK)(uint8_t handle, uint8_t label, uint8_t opcode,
- tAVRC_MSG* p_msg);
+using tAVRC_MSG_CBACK = base::Callback<void(uint8_t handle, uint8_t label,
+ uint8_t opcode, tAVRC_MSG* p_msg)>;
typedef struct {
- tAVRC_CTRL_CBACK* p_ctrl_cback; /* pointer to application control callback */
- tAVRC_MSG_CBACK* p_msg_cback; /* pointer to application message callback */
+ tAVRC_CTRL_CBACK ctrl_cback; /* application control callback */
+ tAVRC_MSG_CBACK msg_cback; /* application message callback */
uint32_t company_id; /* the company ID */
uint8_t conn; /* Connection role (Initiator/acceptor) */
uint8_t control; /* Control role (Control/Target) */
@@ -274,7 +278,7 @@
extern uint16_t AVRC_FindService(uint16_t service_uuid,
const RawAddress& bd_addr,
tAVRC_SDP_DB_PARAMS* p_db,
- tAVRC_FIND_CBACK* p_cback);
+ const tAVRC_FIND_CBACK& cback);
/******************************************************************************
*
diff --git a/stack/include/avrc_defs.h b/stack/include/avrc_defs.h
index 9fe4397..d1c844f 100644
--- a/stack/include/avrc_defs.h
+++ b/stack/include/avrc_defs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2016 Broadcom Corporation
+ * Copyright 2006-2016 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/ble_advertiser.h b/stack/include/ble_advertiser.h
index 69305c0..f4fc81c 100644
--- a/stack/include/ble_advertiser.h
+++ b/stack/include/ble_advertiser.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
#define BLE_ADVERTISER_H
#include <base/bind.h>
+#include <base/memory/weak_ptr.h>
#include <vector>
#include "btm_ble_api.h"
@@ -72,7 +73,7 @@
static void Initialize(BleAdvertiserHciInterface* interface);
static void CleanUp();
static bool IsInitialized();
- static BleAdvertisingManager* Get();
+ static base::WeakPtr<BleAdvertisingManager> Get();
/* Register an advertising instance, status will be returned in |cb|
* callback, with assigned id, if operation succeeds. Instance is freed when
diff --git a/stack/include/bnep_api.h b/stack/include/bnep_api.h
index 4116ac9..03b72e4 100644
--- a/stack/include/bnep_api.h
+++ b/stack/include/bnep_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2001-2012 Broadcom Corporation
+ * Copyright 2001-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,7 +91,8 @@
* use BNEP_ConnectResp call to accept or reject the request
*/
typedef void(tBNEP_CONNECT_IND_CB)(uint16_t handle, const RawAddress& bd_addr,
- tBT_UUID* remote_uuid, tBT_UUID* local_uuid,
+ const bluetooth::Uuid& remote_uuid,
+ const bluetooth::Uuid& local_uuid,
bool is_role_change);
/* Data buffer received indication callback prototype. Parameters are
@@ -190,8 +191,8 @@
uint16_t sent_mcast_filters;
uint16_t rcvd_num_filters;
uint16_t rcvd_mcast_filters;
- tBT_UUID src_uuid;
- tBT_UUID dst_uuid;
+ bluetooth::Uuid src_uuid;
+ bluetooth::Uuid dst_uuid;
} tBNEP_STATUS;
@@ -246,7 +247,8 @@
*
******************************************************************************/
extern tBNEP_RESULT BNEP_Connect(const RawAddress& p_rem_bda,
- tBT_UUID* src_uuid, tBT_UUID* dst_uuid,
+ const bluetooth::Uuid& src_uuid,
+ const bluetooth::Uuid& dst_uuid,
uint16_t* p_handle);
/*******************************************************************************
diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h
index 380e8cd..54a2eb2 100644
--- a/stack/include/bt_types.h
+++ b/stack/include/bt_types.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -324,10 +324,10 @@
for (ijk = 0; ijk < (len); ijk++) *(p)++ = (uint8_t)(a)[(len)-1 - ijk]; \
}
-#define STREAM_TO_INT8(u8, p) \
- { \
- (u8) = (*((int8_t*)p)); \
- (p) += 1; \
+#define STREAM_TO_INT8(u8, p) \
+ { \
+ (u8) = (*((int8_t*)(p))); \
+ (p) += 1; \
}
#define STREAM_TO_UINT8(u8, p) \
{ \
@@ -352,6 +352,17 @@
((((uint32_t)(*((p) + 3)))) << 24)); \
(p) += 4; \
}
+#define STREAM_TO_UINT64(u64, p) \
+ { \
+ (u64) = (((uint64_t)(*(p))) + ((((uint64_t)(*((p) + 1)))) << 8) + \
+ ((((uint64_t)(*((p) + 2)))) << 16) + \
+ ((((uint64_t)(*((p) + 3)))) << 24) + \
+ ((((uint64_t)(*((p) + 4)))) << 32) + \
+ ((((uint64_t)(*((p) + 5)))) << 40) + \
+ ((((uint64_t)(*((p) + 6)))) << 48) + \
+ ((((uint64_t)(*((p) + 7)))) << 56)); \
+ (p) += 8; \
+ }
#define STREAM_TO_ARRAY32(a, p) \
{ \
int ijk; \
@@ -527,7 +538,8 @@
#define BD_ADDR_LEN 6 /* Device address length */
#ifdef __cplusplus
-#include <hardware/bluetooth.h>
+#include <bluetooth/uuid.h>
+#include <include/hardware/bluetooth.h>
inline void BDADDR_TO_STREAM(uint8_t*& p, const RawAddress& a) {
for (int ijk = 0; ijk < BD_ADDR_LEN; ijk++)
@@ -639,23 +651,6 @@
#define BT_1SEC_TIMEOUT_MS (1 * 1000) /* 1 second */
-/* Maximum UUID size - 16 bytes, and structure to hold any type of UUID. */
-#define MAX_UUID_SIZE 16
-typedef struct {
-#define LEN_UUID_16 2
-#define LEN_UUID_32 4
-#define LEN_UUID_128 16
-
- uint16_t len;
-
- union {
- uint16_t uuid16;
- uint32_t uuid32;
- uint8_t uuid128[MAX_UUID_SIZE];
- } uu;
-
-} tBT_UUID;
-
#define BT_EIR_FLAGS_TYPE 0x01
#define BT_EIR_MORE_16BITS_UUID_TYPE 0x02
#define BT_EIR_COMPLETE_16BITS_UUID_TYPE 0x03
@@ -728,6 +723,7 @@
#define BLE_ADDR_RANDOM 0x01
#define BLE_ADDR_PUBLIC_ID 0x02
#define BLE_ADDR_RANDOM_ID 0x03
+#define BLE_ADDR_ANONYMOUS 0xFF
typedef uint8_t tBLE_ADDR_TYPE;
#define BLE_ADDR_TYPE_MASK (BLE_ADDR_RANDOM | BLE_ADDR_PUBLIC)
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index 3dd5567..6ffc0f9 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1218,7 +1218,7 @@
* Returns true if registered OK, else false
*
******************************************************************************/
-extern bool BTM_SecRegister(tBTM_APPL_INFO* p_cb_info);
+extern bool BTM_SecRegister(const tBTM_APPL_INFO* p_cb_info);
/*******************************************************************************
*
@@ -1776,7 +1776,7 @@
*
******************************************************************************/
extern tBTM_STATUS BTM_SetPowerMode(uint8_t pm_id, const RawAddress& remote_bda,
- tBTM_PM_PWR_MD* p_mode);
+ const tBTM_PM_PWR_MD* p_mode);
/*******************************************************************************
*
@@ -1880,7 +1880,7 @@
* false - if not found
*
******************************************************************************/
-extern bool BTM_HasEirService(uint32_t* p_eir_uuid, uint16_t uuid16);
+extern bool BTM_HasEirService(const uint32_t* p_eir_uuid, uint16_t uuid16);
/*******************************************************************************
*
@@ -1957,7 +1957,8 @@
*
* Parameters p_eir - EIR
* eirl_len - EIR len
- * uuid_size - LEN_UUID_16, LEN_UUID_32, LEN_UUID_128
+ * uuid_size - Uuid::kNumBytes16, Uuid::kNumBytes32,
+ * Uuid::kNumBytes128
* p_num_uuid - return number of UUID in found list
* p_uuid_list - return UUID 16-bit list
* max_num_uuid - maximum number of UUID to be returned
diff --git a/stack/include/btm_api_types.h b/stack/include/btm_api_types.h
index 058aabc..df7b64d 100644
--- a/stack/include/btm_api_types.h
+++ b/stack/include/btm_api_types.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,17 +56,6 @@
typedef uint8_t tBTM_STATUS;
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
-typedef enum {
- BTM_BR_ONE, /*0 First state or BR/EDR scan 1*/
- BTM_BLE_ONE, /*1BLE scan 1*/
- BTM_BR_TWO, /*2 BR/EDR scan 2*/
- BTM_BLE_TWO, /*3 BLE scan 2*/
- BTM_FINISH, /*4 End of Interleave Scan, or normal scan*/
- BTM_NO_INTERLEAVING /*5 No Interleaving*/
-} btm_inq_state;
-#endif
-
/*************************
* Device Control Types
*************************/
@@ -608,10 +597,6 @@
*/
uint8_t filter_cond_type; /* new devices, BD ADDR, COD, or No filtering */
tBTM_INQ_FILT_COND filter_cond; /* filter value based on filter cond type */
-#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- uint8_t intl_duration
- [4]; /*duration array storing the interleave scan's time portions*/
-#endif
} tBTM_INQ_PARMS;
#define BTM_INQ_RESULT_BR 0x01
@@ -1602,7 +1587,7 @@
typedef uint8_t tBTM_LE_KEY_TYPE;
#define BTM_LE_AUTH_REQ_NO_BOND SMP_AUTH_NO_BOND /* 0 */
-#define BTM_LE_AUTH_REQ_BOND SMP_AUTH_GEN_BOND /* 1 << 0 */
+#define BTM_LE_AUTH_REQ_BOND SMP_AUTH_BOND /* 1 << 0 */
#define BTM_LE_AUTH_REQ_MITM SMP_AUTH_YN_BIT /* 1 << 2 */
typedef uint8_t tBTM_LE_AUTH_REQ;
#define BTM_LE_SC_SUPPORT_BIT SMP_SC_SUPPORT_BIT /* (1 << 3) */
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index 36c8128..f0fb9e6 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -763,33 +763,9 @@
/**
* This functions are called to configure the adv data payload filter condition
*/
-extern void BTM_LE_PF_srvc_data(tBTM_BLE_SCAN_COND_OP action,
- tBTM_BLE_PF_FILT_INDEX filt_index);
-extern void BTM_LE_PF_addr_filter(tBTM_BLE_SCAN_COND_OP action,
- tBTM_BLE_PF_FILT_INDEX filt_index,
- tBLE_BD_ADDR addr, tBTM_BLE_PF_CFG_CBACK cb);
-extern void BTM_LE_PF_local_name(tBTM_BLE_SCAN_COND_OP action,
- tBTM_BLE_PF_FILT_INDEX filt_index,
- std::vector<uint8_t> name,
- tBTM_BLE_PF_CFG_CBACK cb);
-extern void BTM_LE_PF_uuid_filter(tBTM_BLE_SCAN_COND_OP action,
- tBTM_BLE_PF_FILT_INDEX filt_index,
- tBTM_BLE_PF_COND_TYPE filter_type,
- tBT_UUID uuid,
- tBTM_BLE_PF_LOGIC_TYPE cond_logic,
- tBTM_BLE_PF_COND_MASK* p_uuid_mask,
- tBTM_BLE_PF_CFG_CBACK cb);
-extern void BTM_LE_PF_manu_data(tBTM_BLE_SCAN_COND_OP action,
- tBTM_BLE_PF_FILT_INDEX filt_index,
- uint16_t company_id, uint16_t company_id_mask,
- std::vector<uint8_t> data,
- std::vector<uint8_t> data_mask,
- tBTM_BLE_PF_CFG_CBACK cb);
-extern void BTM_LE_PF_srvc_data_pattern(tBTM_BLE_SCAN_COND_OP action,
- tBTM_BLE_PF_FILT_INDEX filt_index,
- std::vector<uint8_t> data,
- std::vector<uint8_t> data_mask,
- tBTM_BLE_PF_CFG_CBACK cb);
+extern void BTM_LE_PF_set(tBTM_BLE_PF_FILT_INDEX filt_index,
+ std::vector<ApcfCommand> commands,
+ tBTM_BLE_PF_CFG_CBACK cb);
extern void BTM_LE_PF_clear(tBTM_BLE_PF_FILT_INDEX filt_index,
tBTM_BLE_PF_CFG_CBACK cb);
diff --git a/stack/include/btm_ble_api_types.h b/stack/include/btm_ble_api_types.h
index 57ef0d1..327a2e6 100644
--- a/stack/include/btm_ble_api_types.h
+++ b/stack/include/btm_ble_api_types.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -197,6 +197,12 @@
#define BTM_BLE_CONN_INT_MIN_LIMIT 0x0009
#endif
+/* minimum acceptable connection interval when there is bonded Hearing Aid
+ * device */
+#ifndef BTM_BLE_CONN_INT_MIN_HEARINGAID
+#define BTM_BLE_CONN_INT_MIN_HEARINGAID 0x0010
+#endif
+
#define BTM_BLE_DIR_CONN_FALLBACK_UNDIR 1
#define BTM_BLE_DIR_CONN_FALLBACK_NO_ADV 2
@@ -331,14 +337,6 @@
#define BTM_BLE_DATA_TX_TIME_MIN 0x0148
#define BTM_BLE_DATA_TX_TIME_MAX 0x0848
-/* adv tx power level */
-#define BTM_BLE_ADV_TX_POWER_MIN 0 /* minimum tx power */
-#define BTM_BLE_ADV_TX_POWER_LOW 1 /* low tx power */
-#define BTM_BLE_ADV_TX_POWER_MID 2 /* middle tx power */
-#define BTM_BLE_ADV_TX_POWER_UPPER 3 /* upper tx power */
-#define BTM_BLE_ADV_TX_POWER_MAX 4 /* maximum tx power */
-typedef uint8_t tBTM_BLE_ADV_TX_POWER;
-
/* adv tx power in dBm */
typedef struct {
uint8_t adv_inst_max; /* max adv instance supported in controller */
@@ -459,12 +457,6 @@
using tBTM_BLE_PF_PARAM_CB = base::Callback<void(
uint8_t /* avbl_space */, uint8_t /* action */, uint8_t /* status */)>;
-typedef union {
- uint16_t uuid16_mask;
- uint32_t uuid32_mask;
- uint8_t uuid128_mask[LEN_UUID_128];
-} tBTM_BLE_PF_COND_MASK;
-
/* per device filter + one generic filter indexed by 0 */
#define BTM_BLE_MAX_FILTER_COUNTER (BTM_BLE_MAX_ADDR_FILTER + 1)
diff --git a/stack/include/btu.h b/stack/include/btu.h
index a69ad41..5841efa 100644
--- a/stack/include/btu.h
+++ b/stack/include/btu.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/gap_api.h b/stack/include/gap_api.h
index d9a7217..9293378 100644
--- a/stack/include/gap_api.h
+++ b/stack/include/gap_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -77,6 +77,7 @@
#define GAP_EVT_CONN_CONGESTED 0x0103
#define GAP_EVT_CONN_UNCONGESTED 0x0104
#define GAP_EVT_TX_EMPTY 0x0105
+#define GAP_EVT_LE_COC_CREDITS 0x0106
/* Values for 'chan_mode_mask' field */
/* GAP_ConnOpen() - optional channels to negotiate */
@@ -105,13 +106,24 @@
#define GAP_PREFER_CONN_SP_TOUT 2000
#endif
+struct tGAP_COC_CREDITS {
+ uint16_t gap_handle;
+ uint16_t credits_received;
+ uint16_t credit_count;
+};
+
+union tGAP_CB_DATA {
+ tGAP_COC_CREDITS coc_credits;
+};
+
/*****************************************************************************
* Type Definitions
****************************************************************************/
/*
* Callback function for connection services
*/
-typedef void(tGAP_CONN_CALLBACK)(uint16_t gap_handle, uint16_t event);
+typedef void(tGAP_CONN_CALLBACK)(uint16_t gap_handle, uint16_t event,
+ tGAP_CB_DATA* data);
/*
* Define the callback function prototypes. Parameters are specific
@@ -163,7 +175,8 @@
******************************************************************************/
extern uint16_t GAP_ConnOpen(const char* p_serv_name, uint8_t service_id,
bool is_server, const RawAddress* p_rem_bda,
- uint16_t psm, tL2CAP_CFG_INFO* p_cfg,
+ uint16_t psm, uint16_t le_mps,
+ tL2CAP_CFG_INFO* p_cfg,
tL2CAP_ERTM_INFO* ertm_info, uint16_t security,
uint8_t chan_mode_mask, tGAP_CONN_CALLBACK* p_cb,
tBT_TRANSPORT transport);
@@ -238,8 +251,7 @@
* GAP_CONGESTION - system is congested
*
******************************************************************************/
-extern uint16_t GAP_ConnWriteData(uint16_t gap_handle, uint8_t* p_data,
- uint16_t max_len, uint16_t* p_len);
+extern uint16_t GAP_ConnWriteData(uint16_t gap_handle, BT_HDR* msg);
/*******************************************************************************
*
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index 48ca8e3..f9c0642 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,6 +63,9 @@
#define GATT_NOT_ENCRYPTED 0x8e
#define GATT_CONGESTED 0x8f
+#define GATT_DUP_REG 0x90 /* 0x90 */
+#define GATT_ALREADY_OPEN 0x91 /* 0x91 */
+#define GATT_CANCEL 0x92 /* 0x92 */
/* 0xE0 ~ 0xFC reserved for future use */
/* Client Characteristic Configuration Descriptor Improperly Configured */
@@ -290,7 +293,6 @@
#define GATT_CLT_CONFIG_NONE 0x0000
#define GATT_CLT_CONFIG_NOTIFICATION 0x0001
#define GATT_CLT_CONFIG_INDICATION 0x0002
-typedef uint16_t tGATT_CLT_CHAR_CONFIG;
/* characteristic descriptor: server configuration value
*/
@@ -411,7 +413,7 @@
/* Discover parameters of different discovery types
*/
typedef struct {
- tBT_UUID service;
+ bluetooth::Uuid service;
uint16_t s_handle;
uint16_t e_handle;
} tGATT_DISC_PARAM;
@@ -434,7 +436,7 @@
tGATT_AUTH_REQ auth_req;
uint16_t s_handle;
uint16_t e_handle;
- tBT_UUID uuid;
+ bluetooth::Uuid uuid;
} tGATT_READ_BY_TYPE;
/* GATT_READ_MULTIPLE request data
@@ -499,20 +501,20 @@
typedef struct {
tGATT_CHAR_PROP char_prop; /* characterisitc properties */
uint16_t val_handle; /* characteristic value attribute handle */
- tBT_UUID char_uuid; /* characteristic UUID type */
+ bluetooth::Uuid char_uuid; /* characteristic UUID type */
} tGATT_CHAR_DCLR_VAL;
/* primary service group data
*/
typedef struct {
uint16_t e_handle; /* ending handle of the group */
- tBT_UUID service_type; /* group type */
+ bluetooth::Uuid service_type; /* group type */
} tGATT_GROUP_VALUE;
/* included service attribute value
*/
typedef struct {
- tBT_UUID service_type; /* included service UUID */
+ bluetooth::Uuid service_type; /* included service UUID */
uint16_t s_handle; /* starting handle */
uint16_t e_handle; /* ending handle */
} tGATT_INCL_SRVC;
@@ -535,7 +537,7 @@
/* discover result record
*/
typedef struct {
- tBT_UUID type;
+ bluetooth::Uuid type;
uint16_t handle;
tGATT_DISC_VALUE value;
} tGATT_DISC_RES;
@@ -605,8 +607,8 @@
/***************** Start Handle Management Definitions *********************/
typedef struct {
- tBT_UUID app_uuid128;
- tBT_UUID svc_uuid;
+ bluetooth::Uuid app_uuid128;
+ bluetooth::Uuid svc_uuid;
uint16_t s_handle;
uint16_t e_handle;
bool is_primary; /* primary service or secondary */
@@ -687,10 +689,6 @@
******************************************************************************/
extern bool GATTS_NVRegister(tGATT_APPL_INFO* p_cb_info);
-/* Converts 16bit uuid to bt_uuid_t that can be used when adding
- * service/characteristic/descriptor with GATTS_AddService */
-void uuid_128_from_16(bt_uuid_t* uuid, uint16_t uuid16);
-
/*******************************************************************************
*
* Function BTA_GATTS_AddService
@@ -725,7 +723,7 @@
* Returns true if operation succeed, else false
*
******************************************************************************/
-extern bool GATTS_DeleteService(tGATT_IF gatt_if, tBT_UUID* p_svc_uuid,
+extern bool GATTS_DeleteService(tGATT_IF gatt_if, bluetooth::Uuid* p_svc_uuid,
uint16_t svc_inst);
/*******************************************************************************
@@ -931,7 +929,8 @@
* with GATT
*
******************************************************************************/
-extern tGATT_IF GATT_Register(tBT_UUID* p_app_uuid128, tGATT_CBACK* p_cb_info);
+extern tGATT_IF GATT_Register(const bluetooth::Uuid& p_app_uuid128,
+ tGATT_CBACK* p_cb_info);
/*******************************************************************************
*
diff --git a/stack/include/gattdefs.h b/stack/include/gattdefs.h
index de968a8..5f5093d 100644
--- a/stack/include/gattdefs.h
+++ b/stack/include/gattdefs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index c015b97..8f91743 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2014 Broadcom Corporation
+ * Copyright 1999-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -358,6 +358,7 @@
#define HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL (0x002C | HCI_GRP_BLE_CMDS)
#define HCI_BLE_SET_ADDR_RESOLUTION_ENABLE (0x002D | HCI_GRP_BLE_CMDS)
#define HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT (0x002E | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_MAXIMUM_DATA_LENGTH (0x002F | HCI_GRP_BLE_CMDS)
#define HCI_BLE_READ_PHY (0x0030 | HCI_GRP_BLE_CMDS)
#define HCI_BLE_SET_DEFAULT_PHY (0x0031 | HCI_GRP_BLE_CMDS)
#define HCI_BLE_SET_PHY (0x0032 | HCI_GRP_BLE_CMDS)
@@ -379,6 +380,20 @@
#define HCI_LE_SET_EXTENDED_SCAN_PARAMETERS (0x0041 | HCI_GRP_BLE_CMDS)
#define HCI_LE_SET_EXTENDED_SCAN_ENABLE (0x0042 | HCI_GRP_BLE_CMDS)
#define HCI_LE_EXTENDED_CREATE_CONNECTION (0x0043 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_PERIODIC_ADVERTISING_CREATE_SYNC (0x0044 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL \
+ (0x0045 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_PERIODIC_ADVERTISING_TERMINATE_SYNC \
+ (0x0046 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_ADD_DEVICE_TO_PERIODIC_ADVERTISING_LIST \
+ (0x0047 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_RM_DEVICE_FROM_PERIODIC_ADVERTISING_LIST \
+ (0x0048 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_CLEAR_PERIODIC_ADVERTISING_LIST (0x0049 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_PERIODIC_ADVERTISING_LIST_SIZE (0x004A | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_TRANSMIT_POWER (0x004B | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_RF_COMPENS_POWER (0x004C | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_WRITE_RF_COMPENS_POWER (0x004D | HCI_GRP_BLE_CMDS)
#define HCI_BLE_SET_PRIVACY_MODE (0x004E | HCI_GRP_BLE_CMDS)
/* LE Get Vendor Capabilities Command OCF */
@@ -405,6 +420,9 @@
/* Controller debug info OCF */
#define HCI_CONTROLLER_DEBUG_INFO_OCF (0x015B | HCI_GRP_VENDOR_SPECIFIC)
+/* A2DP offload OCF */
+#define HCI_CONTROLLER_A2DP_OPCODE_OCF (0x015D | HCI_GRP_VENDOR_SPECIFIC)
+
/* subcode for multi adv feature */
#define BTM_BLE_MULTI_ADV_SET_PARAM 0x01
#define BTM_BLE_MULTI_ADV_WRITE_ADV_DATA 0x02
@@ -572,7 +590,12 @@
#define HCI_BLE_DIRECT_ADV_EVT 0x0b
#define HCI_BLE_PHY_UPDATE_COMPLETE_EVT 0x0c
#define HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT 0x0D
+#define HCI_BLE_PERIODIC_ADV_SYNC_EST_EVT 0x0E
+#define HCI_BLE_PERIODIC_ADV_REPORT_EVT 0x0F
+#define HCI_BLE_PERIODIC_ADV_SYNC_LOST_EVT 0x10
+#define HCI_BLE_SCAN_TIMEOUT_EVT 0x11
#define HCI_LE_ADVERTISING_SET_TERMINATED_EVT 0x12
+#define HCI_BLE_SCAN_REQ_RX_EVT 0x13
/* Definitions for LE Channel Map */
#define HCI_BLE_CHNL_MAP_SIZE 5
@@ -647,9 +670,10 @@
#define HCI_ERR_REJ_NO_SUITABLE_CHANNEL 0x39
#define HCI_ERR_CONTROLLER_BUSY 0x3A
#define HCI_ERR_UNACCEPT_CONN_INTERVAL 0x3B
-#define HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT 0x3C
+#define HCI_ERR_ADVERTISING_TIMEOUT 0x3C
#define HCI_ERR_CONN_TOUT_DUE_TO_MIC_FAILURE 0x3D
#define HCI_ERR_CONN_FAILED_ESTABLISHMENT 0x3E
+#define HCI_ERR_LIMIT_REACHED 0x43
#define HCI_ERR_MAC_CONNECTION_FAILED 0x3F
/* ConnectionLess Broadcast errors */
@@ -1242,6 +1266,8 @@
#define LMP_TESTCTL_POWCTL_FIXEDTX_OP 0
#define LMP_TESTCTL_POWCTL_ADAPTIVE 1
+#define LMP_COMPID_GOOGLE 0xE0
+
// TODO(zachoverflow): remove this once broadcom specific hacks are removed
#define LMP_COMPID_BROADCOM 15
diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h
index da6be9b..a909751 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/hidd_api.h b/stack/include/hidd_api.h
index 85785e8..145c0f1 100644
--- a/stack/include/hidd_api.h
+++ b/stack/include/hidd_api.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2016 The Android Open Source Project
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/hiddefs.h b/stack/include/hiddefs.h
index 55f7e55..8df616c 100644
--- a/stack/include/hiddefs.h
+++ b/stack/include/hiddefs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/hidh_api.h b/stack/include/hidh_api.h
index 5b43b44..37b5205 100644
--- a/stack/include/hidh_api.h
+++ b/stack/include/hidh_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2002-2012 Broadcom Corporation
+ * Copyright 2002-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 6d7f423..88121af5 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -1,20 +1,20 @@
/******************************************************************************
-*
-* Copyright (C) 1999-2012 Broadcom Corporation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at:
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************************/
+ *
+ * Copyright 1999-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
/******************************************************************************
*
@@ -43,6 +43,8 @@
#define L2CAP_LCC_OFFSET \
(L2CAP_MIN_OFFSET + L2CAP_LCC_SDU_LENGTH) /* plus SDU length(2) */
+#define L2CAP_FCS_LENGTH 2
+
/* ping result codes */
#define L2CAP_PING_RESULT_OK 0 /* Ping reply received OK */
#define L2CAP_PING_RESULT_NO_LINK 1 /* Link could not be setup */
@@ -284,6 +286,15 @@
*/
typedef void(tL2CA_TX_COMPLETE_CB)(uint16_t, uint16_t);
+/* Callback for receiving credits from the remote device.
+ * |credit_received| parameter represents number of credits received in "LE Flow
+ * Control Credit" packet from the remote. |credit_count| parameter represents
+ * the total available credits, including |credit_received|.
+ */
+typedef void(tL2CA_CREDITS_RECEIVED_CB)(uint16_t local_cid,
+ uint16_t credits_received,
+ uint16_t credit_count);
+
/* Define the structure that applications use to register with
* L2CAP. This structure includes callback functions. All functions
* MUST be provided, with the exception of the "connect pending"
@@ -301,7 +312,7 @@
tL2CA_DATA_IND_CB* pL2CA_DataInd_Cb;
tL2CA_CONGESTION_STATUS_CB* pL2CA_CongestionStatus_Cb;
tL2CA_TX_COMPLETE_CB* pL2CA_TxComplete_Cb;
-
+ tL2CA_CREDITS_RECEIVED_CB* pL2CA_CreditsReceived_Cb;
} tL2CAP_APPL_INFO;
/* Define the structure that applications use to create or accept
@@ -379,6 +390,29 @@
/*******************************************************************************
*
+ * Function L2CA_AllocateLePSM
+ *
+ * Description Other layers call this function to find an unused LE PSM for
+ * L2CAP services.
+ *
+ * Returns LE_PSM to use if success. Otherwise returns 0.
+ *
+ ******************************************************************************/
+extern uint16_t L2CA_AllocateLePSM(void);
+
+/*******************************************************************************
+ *
+ * Function L2CA_FreeLePSM
+ *
+ * Description Free an assigned LE PSM.
+ *
+ * Returns void
+ *
+ ******************************************************************************/
+extern void L2CA_FreeLePSM(uint16_t psm);
+
+/*******************************************************************************
+ *
* Function L2CA_ConnectReq
*
* Description Higher layers call this function to create an L2CAP
@@ -1200,6 +1234,10 @@
extern bool L2CA_UpdateBleConnParams(const RawAddress& rem_bdRa,
uint16_t min_int, uint16_t max_int,
uint16_t latency, uint16_t timeout);
+extern bool L2CA_UpdateBleConnParams(const RawAddress& rem_bda,
+ uint16_t min_int, uint16_t max_int,
+ uint16_t latency, uint16_t timeout,
+ uint16_t min_ce_len, uint16_t max_ce_len);
/*******************************************************************************
*
@@ -1242,4 +1280,7 @@
extern uint16_t L2CA_GetDisconnectReason(const RawAddress& remote_bda,
tBT_TRANSPORT transport);
+extern void L2CA_AdjustConnectionIntervals(uint16_t* min_interval,
+ uint16_t* max_interval,
+ uint16_t floor_interval);
#endif /* L2C_API_H */
diff --git a/stack/include/l2cap_client.h b/stack/include/l2cap_client.h
index fb4e922..edb204e 100644
--- a/stack/include/l2cap_client.h
+++ b/stack/include/l2cap_client.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/l2cdefs.h b/stack/include/l2cdefs.h
index 592d7b3..4f4c894 100644
--- a/stack/include/l2cdefs.h
+++ b/stack/include/l2cdefs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -322,13 +322,14 @@
(L2CAP_PKT_OVERHEAD + L2CAP_EXT_CONTROL_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + \
L2CAP_FCS_LEN)
-/* To optimize this, it must be a multiple of the L2CAP PDU length AND match
- * the 3DH5 air including the l2cap headers in each packet. To match the latter,
- * the -5 is added.
- * Changed it to 8087 to have same value between BTIF and L2cap layers
+/* TODO: This value can probably be optimized per transport, and per L2CAP
+ * socket type, but this should not bring any big performance improvements. For
+ * LE CoC, it should be biggest multiple of "PDU length" smaller than 0xffff (so
+ * depend on controller buffer size), for Classic, making it multiple of PDU
+ * length and also of the 3DH5 air including the l2cap headers in each packet.
*/
-#define L2CAP_MAX_SDU_LENGTH (8080 + 26 - (L2CAP_MIN_OFFSET + 6))
-#define L2CAP_MAX_BUF_SIZE (10240 + 24)
+#define L2CAP_SDU_LENGTH_MAX (8080 + 26 - (L2CAP_MIN_OFFSET + 6))
+constexpr uint16_t L2CAP_SDU_LENGTH_LE_MAX = 0xffff;
/* Part of L2CAP_MIN_OFFSET that is not part of L2CAP
*/
diff --git a/stack/include/mca_api.h b/stack/include/mca_api.h
index 3c962d0..539d6c2 100644
--- a/stack/include/mca_api.h
+++ b/stack/include/mca_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/mca_defs.h b/stack/include/mca_defs.h
index a442471..7b6d3c2 100644
--- a/stack/include/mca_defs.h
+++ b/stack/include/mca_defs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/pan_api.h b/stack/include/pan_api.h
index d46aa3f..0f9bab1 100644
--- a/stack/include/pan_api.h
+++ b/stack/include/pan_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2001-2012 Broadcom Corporation
+ * Copyright 2001-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/port_api.h b/stack/include/port_api.h
index 7971235..aedbe74 100644
--- a/stack/include/port_api.h
+++ b/stack/include/port_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/port_ext.h b/stack/include/port_ext.h
index ec8eb94..ba31cf0 100644
--- a/stack/include/port_ext.h
+++ b/stack/include/port_ext.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/profiles_api.h b/stack/include/profiles_api.h
index aa3b884..f91826d 100644
--- a/stack/include/profiles_api.h
+++ b/stack/include/profiles_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2013 Broadcom Corporation
+ * Copyright 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/rfcdefs.h b/stack/include/rfcdefs.h
index ab3ceb6..ca9b3ce 100644
--- a/stack/include/rfcdefs.h
+++ b/stack/include/rfcdefs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/sdp_api.h b/stack/include/sdp_api.h
index 72ccd0e..7752fd6 100644
--- a/stack/include/sdp_api.h
+++ b/stack/include/sdp_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,9 +52,6 @@
/* Define the PSM that SDP uses */
#define SDP_PSM 0x0001
-/* Legacy #define to avoid code changes - SDP UUID is same as BT UUID */
-#define tSDP_UUID tBT_UUID
-
/* Masks for attr_value field of tSDP_DISC_ATTR */
#define SDP_DISC_ATTR_LEN_MASK 0x0FFF
#define SDP_DISC_ATTR_TYPE(len_type) ((len_type) >> 12)
@@ -120,7 +117,7 @@
uint32_t mem_free; /* Memory still available */
tSDP_DISC_REC* p_first_rec; /* Addr of first record in DB */
uint16_t num_uuid_filters; /* Number of UUIds to filter */
- tSDP_UUID uuid_filters[SDP_MAX_UUID_FILTERS]; /* UUIDs to filter */
+ bluetooth::Uuid uuid_filters[SDP_MAX_UUID_FILTERS]; /* UUIDs to filter */
uint16_t num_attr_filters; /* Number of attribute filters */
uint16_t attr_filters[SDP_MAX_ATTR_FILTERS]; /* Attributes to filter */
uint8_t* p_free_mem; /* Pointer to free memory */
@@ -176,7 +173,7 @@
*
******************************************************************************/
bool SDP_InitDiscoveryDb(tSDP_DISCOVERY_DB* p_db, uint32_t len,
- uint16_t num_uuid, tSDP_UUID* p_uuid_list,
+ uint16_t num_uuid, const bluetooth::Uuid* p_uuid_list,
uint16_t num_attr, uint16_t* p_attr_list);
/*******************************************************************************
@@ -295,13 +292,13 @@
*
* NOTE the only difference between this function and the previous
* function "SDP_FindServiceInDb()" is that this function takes
- * a tBT_UUID input.
+ * a Uuid input.
*
* Returns Pointer to record containing service class, or NULL
*
******************************************************************************/
tSDP_DISC_REC* SDP_FindServiceUUIDInDb(tSDP_DISCOVERY_DB* p_db,
- tBT_UUID* p_uuid,
+ const bluetooth::Uuid& uuid,
tSDP_DISC_REC* p_start_rec);
/*******************************************************************************
@@ -317,7 +314,8 @@
* Returns true if found, otherwise false.
*
******************************************************************************/
-bool SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC* p_rec, tBT_UUID* p_uuid);
+bool SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC* p_rec,
+ bluetooth::Uuid* p_uuid);
/*******************************************************************************
*
@@ -636,11 +634,6 @@
* Returns true if found, otherwise false.
*
******************************************************************************/
-bool SDP_FindServiceUUIDInRec(tSDP_DISC_REC* p_rec, tBT_UUID* p_uuid);
-
-// Converts UUID-16 to UUID-128 by including the base UUID.
-// |uuid16| is the 2-byte UUID to convert.
-// The result with the expanded 128-bit UUID is stored in |p_uuid128|.
-void sdpu_uuid16_to_uuid128(uint16_t uuid16, uint8_t* p_uuid128);
+bool SDP_FindServiceUUIDInRec(tSDP_DISC_REC* p_rec, bluetooth::Uuid* p_uuid);
#endif /* SDP_API_H */
diff --git a/stack/include/sdpdefs.h b/stack/include/sdpdefs.h
index ad0e611..05b3cc1 100644
--- a/stack/include/sdpdefs.h
+++ b/stack/include/sdpdefs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index 10cff74..816407d 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/include/smp_api_types.h b/stack/include/smp_api_types.h
index a21af4b..fad8b75 100644
--- a/stack/include/smp_api_types.h
+++ b/stack/include/smp_api_types.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -122,7 +122,7 @@
typedef uint8_t tSMP_OOB_DATA_TYPE;
#define SMP_AUTH_NO_BOND 0x00
-#define SMP_AUTH_GEN_BOND 0x01 // todo sdh change GEN_BOND to BOND
+#define SMP_AUTH_BOND 0x01
/* SMP Authentication requirement */
#define SMP_AUTH_YN_BIT (1 << 2)
@@ -130,11 +130,9 @@
#define SMP_KP_SUPPORT_BIT (1 << 4)
#define SMP_H7_SUPPORT_BIT (1 << 5)
-#define SMP_AUTH_MASK \
- (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT | SMP_SC_SUPPORT_BIT | \
- SMP_KP_SUPPORT_BIT | SMP_H7_SUPPORT_BIT)
-
-#define SMP_AUTH_BOND SMP_AUTH_GEN_BOND
+#define SMP_AUTH_MASK \
+ (SMP_AUTH_BOND | SMP_AUTH_YN_BIT | SMP_SC_SUPPORT_BIT | SMP_KP_SUPPORT_BIT | \
+ SMP_H7_SUPPORT_BIT)
/* no MITM, No Bonding, encryption only */
#define SMP_AUTH_NB_ENC_ONLY 0x00 //(SMP_AUTH_MASK | BTM_AUTH_SP_NO)
@@ -143,27 +141,25 @@
#define SMP_AUTH_NB_IOCAP (SMP_AUTH_NO_BOND | SMP_AUTH_YN_BIT)
/* No MITM, General Bonding, Encryption only */
-#define SMP_AUTH_GB_ENC_ONLY (SMP_AUTH_GEN_BOND)
+#define SMP_AUTH_GB_ENC_ONLY SMP_AUTH_BOND
/* MITM, General Bonding, Use IO Capability to determine authentication
* procedure */
-#define SMP_AUTH_GB_IOCAP (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT)
+#define SMP_AUTH_GB_IOCAP (SMP_AUTH_BOND | SMP_AUTH_YN_BIT)
/* Secure Connections, no MITM, no Bonding */
#define SMP_AUTH_SC_ENC_ONLY (SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT)
/* Secure Connections, no MITM, Bonding */
-#define SMP_AUTH_SC_GB \
- (SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT | SMP_AUTH_GEN_BOND)
+#define SMP_AUTH_SC_GB (SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT | SMP_AUTH_BOND)
/* Secure Connections, MITM, no Bonding */
#define SMP_AUTH_SC_MITM_NB \
(SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_NO_BOND)
/* Secure Connections, MITM, Bonding */
-#define SMP_AUTH_SC_MITM_GB \
- (SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | \
- SMP_AUTH_GEN_BOND)
+#define SMP_AUTH_SC_MITM_GB \
+ (SMP_H7_SUPPORT_BIT | SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_BOND)
/* All AuthReq RFU bits are set to 1 - NOTE: reserved bit in Bonding_Flags is
* not set */
diff --git a/stack/include/srvc_api.h b/stack/include/srvc_api.h
index 9f0e1aa..e968998 100644
--- a/stack/include/srvc_api.h
+++ b/stack/include/srvc_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2013 Broadcom Corporation
+ * Copyright 1999-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/l2cap/l2c_api.cc b/stack/l2cap/l2c_api.cc
index 809199f..951a45b 100644
--- a/stack/l2cap/l2c_api.cc
+++ b/stack/l2cap/l2c_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -194,6 +194,75 @@
/*******************************************************************************
*
+ * Function L2CA_AllocateLePSM
+ *
+ * Description To find an unused LE PSM for L2CAP services.
+ *
+ * Returns LE_PSM to use if success. Otherwise returns 0.
+ *
+ ******************************************************************************/
+uint16_t L2CA_AllocateLePSM(void) {
+ bool done = false;
+ uint16_t psm = l2cb.le_dyn_psm;
+ uint16_t count = 0;
+
+ L2CAP_TRACE_API("%s: last psm=%d", __func__, psm);
+ while (!done) {
+ count++;
+ if (count > LE_DYNAMIC_PSM_RANGE) {
+ L2CAP_TRACE_ERROR("%s: Out of free BLE PSM", __func__);
+ return 0;
+ }
+
+ psm++;
+ if (psm > LE_DYNAMIC_PSM_END) {
+ psm = LE_DYNAMIC_PSM_START;
+ }
+
+ if (!l2cb.le_dyn_psm_assigned[psm - LE_DYNAMIC_PSM_START]) {
+ /* make sure the newly allocated psm is not used right now */
+ if (l2cu_find_ble_rcb_by_psm(psm)) {
+ L2CAP_TRACE_WARNING("%s: supposedly-free PSM=%d have allocated rcb!",
+ __func__, psm);
+ continue;
+ }
+
+ l2cb.le_dyn_psm_assigned[psm - LE_DYNAMIC_PSM_START] = true;
+ L2CAP_TRACE_DEBUG("%s: assigned PSM=%d", __func__, psm);
+ done = true;
+ break;
+ }
+ }
+ l2cb.le_dyn_psm = psm;
+
+ return (psm);
+}
+
+/*******************************************************************************
+ *
+ * Function L2CA_FreeLePSM
+ *
+ * Description Free an assigned LE PSM.
+ *
+ * Returns void
+ *
+ ******************************************************************************/
+void L2CA_FreeLePSM(uint16_t psm) {
+ L2CAP_TRACE_API("%s: to free psm=%d", __func__, psm);
+
+ if ((psm < LE_DYNAMIC_PSM_START) || (psm > LE_DYNAMIC_PSM_END)) {
+ L2CAP_TRACE_ERROR("%s: Invalid PSM=%d value!", __func__, psm);
+ return;
+ }
+
+ if (!l2cb.le_dyn_psm_assigned[psm - LE_DYNAMIC_PSM_START]) {
+ L2CAP_TRACE_WARNING("%s: PSM=%d was not allocated!", __func__, psm);
+ }
+ l2cb.le_dyn_psm_assigned[psm - LE_DYNAMIC_PSM_START] = false;
+}
+
+/*******************************************************************************
+ *
* Function L2CA_ConnectReq
*
* Description Higher layers call this function to create an L2CAP
@@ -256,8 +325,7 @@
/* No link. Get an LCB and start link establishment */
p_lcb = l2cu_allocate_lcb(p_bd_addr, false, BT_TRANSPORT_BR_EDR);
/* currently use BR/EDR for ERTM mode l2cap connection */
- if ((p_lcb == NULL) ||
- (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == false)) {
+ if ((p_lcb == NULL) || (!l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR))) {
L2CAP_TRACE_WARNING(
"L2CAP - conn not started for PSM: 0x%04x p_lcb: 0x%08x", psm,
p_lcb);
@@ -359,10 +427,12 @@
/* Check if this is a registration for an outgoing-only connection to */
/* a dynamic PSM. If so, allocate a "virtual" PSM for the app to use. */
- if ((psm >= 0x0080) && (p_cb_info->pL2CA_ConnectInd_Cb == NULL)) {
- for (vpsm = 0x0080; vpsm < 0x0100; vpsm++) {
- p_rcb = l2cu_find_ble_rcb_by_psm(vpsm);
- if (p_rcb == NULL) break;
+ if ((psm >= LE_DYNAMIC_PSM_START) &&
+ (p_cb_info->pL2CA_ConnectInd_Cb == NULL)) {
+ vpsm = L2CA_AllocateLePSM();
+ if (vpsm == 0) {
+ L2CAP_TRACE_ERROR("%s: Out of free BLE PSM", __func__);
+ return 0;
}
L2CAP_TRACE_API("%s Real PSM: 0x%04x Virtual PSM: 0x%04x", __func__, psm,
@@ -372,6 +442,7 @@
/* If registration block already there, just overwrite it */
p_rcb = l2cu_find_ble_rcb_by_psm(vpsm);
if (p_rcb == NULL) {
+ L2CAP_TRACE_API("%s Allocate rcp for Virtual PSM: 0x%04x", __func__, vpsm);
p_rcb = l2cu_allocate_ble_rcb(vpsm);
if (p_rcb == NULL) {
L2CAP_TRACE_WARNING("%s No BLE RCB available, PSM: 0x%04x vPSM: 0x%04x",
@@ -401,7 +472,8 @@
tL2C_RCB* p_rcb = l2cu_find_ble_rcb_by_psm(psm);
if (p_rcb == NULL) {
- L2CAP_TRACE_WARNING("%s PSM: 0x%04x not found for deregistration", psm);
+ L2CAP_TRACE_WARNING("%s PSM: 0x%04x not found for deregistration", __func__,
+ psm);
return;
}
@@ -420,7 +492,7 @@
l2c_csm_execute(p_ccb, L2CEVT_L2CA_DISCONNECT_REQ, NULL);
}
- l2cu_release_rcb(p_rcb);
+ l2cu_release_ble_rcb(p_rcb);
}
/*******************************************************************************
@@ -465,7 +537,7 @@
p_lcb = l2cu_allocate_lcb(p_bd_addr, false, BT_TRANSPORT_LE);
if ((p_lcb == NULL)
/* currently use BR/EDR for ERTM mode l2cap connection */
- || (l2cu_create_conn(p_lcb, BT_TRANSPORT_LE) == false)) {
+ || (!l2cu_create_conn(p_lcb, BT_TRANSPORT_LE))) {
L2CAP_TRACE_WARNING("%s conn not started for PSM: 0x%04x p_lcb: 0x%08x",
__func__, psm, p_lcb);
return 0;
@@ -483,7 +555,10 @@
p_ccb->p_rcb = p_rcb;
/* Save the configuration */
- if (p_cfg) memcpy(&p_ccb->local_conn_cfg, p_cfg, sizeof(tL2CAP_LE_CFG_INFO));
+ if (p_cfg) {
+ memcpy(&p_ccb->local_conn_cfg, p_cfg, sizeof(tL2CAP_LE_CFG_INFO));
+ p_ccb->remote_credit_count = p_cfg->credits;
+ }
/* If link is up, start the L2CAP connection */
if (p_lcb->link_state == LST_CONNECTED) {
@@ -553,7 +628,10 @@
return false;
}
- if (p_cfg) memcpy(&p_ccb->local_conn_cfg, p_cfg, sizeof(tL2CAP_LE_CFG_INFO));
+ if (p_cfg) {
+ memcpy(&p_ccb->local_conn_cfg, p_cfg, sizeof(tL2CAP_LE_CFG_INFO));
+ p_ccb->remote_credit_count = p_cfg->credits;
+ }
if (result == L2CAP_CONN_OK)
l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP, NULL);
@@ -904,7 +982,7 @@
L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_ping");
return (false);
}
- if (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == false) {
+ if (!l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR)) {
return (false);
}
@@ -1214,7 +1292,8 @@
*
******************************************************************************/
bool L2CA_SetAclPriority(const RawAddress& bd_addr, uint8_t priority) {
- VLOG(1) << __func__ << " BDA: " << bd_addr << ", priority: " << priority;
+ VLOG(1) << __func__ << " BDA: " << bd_addr
+ << ", priority: " << std::to_string(priority);
return (l2cu_set_acl_priority(bd_addr, priority, false));
}
@@ -2124,7 +2203,7 @@
* controller */
if ((HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures())) &&
(BTM_GetNumScoLinks() == 0)) {
- if (l2cb.is_flush_active == false) {
+ if (!l2cb.is_flush_active) {
l2cb.is_flush_active = true;
/* The only packet type defined - 0 - Automatically-Flushable Only */
diff --git a/stack/l2cap/l2c_ble.cc b/stack/l2cap/l2c_ble.cc
index 078f75f..5fc01f9 100644
--- a/stack/l2cap/l2c_ble.cc
+++ b/stack/l2cap/l2c_ble.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
#include <string.h>
#include "bt_target.h"
#include "bt_utils.h"
+#include "bta_hearing_aid_api.h"
#include "btm_int.h"
#include "btu.h"
#include "device/include/controller.h"
@@ -99,7 +100,8 @@
******************************************************************************/
bool L2CA_UpdateBleConnParams(const RawAddress& rem_bda, uint16_t min_int,
uint16_t max_int, uint16_t latency,
- uint16_t timeout) {
+ uint16_t timeout, uint16_t min_ce_len,
+ uint16_t max_ce_len) {
tL2C_LCB* p_lcb;
tACL_CONN* p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
@@ -117,17 +119,30 @@
return (false);
}
+ VLOG(2) << __func__ << ": BD_ADDR=" << rem_bda << ", min_int=" << min_int
+ << ", max_int=" << max_int << ", min_ce_len=" << min_ce_len
+ << ", max_ce_len=" << max_ce_len;
+
p_lcb->min_interval = min_int;
p_lcb->max_interval = max_int;
p_lcb->latency = latency;
p_lcb->timeout = timeout;
p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
+ p_lcb->min_ce_len = min_ce_len;
+ p_lcb->max_ce_len = max_ce_len;
l2cble_start_conn_update(p_lcb);
return (true);
}
+bool L2CA_UpdateBleConnParams(const RawAddress& rem_bda, uint16_t min_int,
+ uint16_t max_int, uint16_t latency,
+ uint16_t timeout) {
+ return L2CA_UpdateBleConnParams(rem_bda, min_int, max_int, latency, timeout,
+ 0, 0);
+}
+
/*******************************************************************************
*
* Function L2CA_EnableUpdateBleConnParams
@@ -469,6 +484,10 @@
p_lcb->min_interval > BTM_BLE_CONN_INT_MIN) {
/* use 7.5 ms as fast connection parameter, 0 slave latency */
min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
+
+ L2CA_AdjustConnectionIntervals(&min_conn_int, &max_conn_int,
+ BTM_BLE_CONN_INT_MIN);
+
slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF;
supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
@@ -504,7 +523,8 @@
) {
btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
p_lcb->max_interval, p_lcb->latency,
- p_lcb->timeout, 0, 0);
+ p_lcb->timeout, p_lcb->min_ce_len,
+ p_lcb->max_ce_len);
p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
} else {
l2cu_send_peer_ble_par_req(p_lcb, p_lcb->min_interval,
@@ -617,15 +637,8 @@
STREAM_TO_UINT16(timeout, p); /* 0x000A - 0x0C80 */
/* If we are a master, the slave wants to update the parameters */
if (p_lcb->link_role == HCI_ROLE_MASTER) {
- if (min_interval < BTM_BLE_CONN_INT_MIN_LIMIT)
- min_interval = BTM_BLE_CONN_INT_MIN_LIMIT;
-
- // While this could result in connection parameters that fall
- // outside fo the range requested, this will allow the connection
- // to remain established.
- // In other words, this is a workaround for certain peripherals.
- if (max_interval < BTM_BLE_CONN_INT_MIN_LIMIT)
- max_interval = BTM_BLE_CONN_INT_MIN_LIMIT;
+ L2CA_AdjustConnectionIntervals(&min_interval, &max_interval,
+ BTM_BLE_CONN_INT_MIN_LIMIT);
if (min_interval < BTM_BLE_CONN_INT_MIN ||
min_interval > BTM_BLE_CONN_INT_MAX ||
@@ -1361,7 +1374,8 @@
uint8_t sec_act;
if (!p_lcb) {
- L2CAP_TRACE_WARNING("%s security complete for unknown device", __func__);
+ L2CAP_TRACE_WARNING("%s: security complete for unknown device. bda=%s",
+ __func__, bda->ToString().c_str());
return;
}
@@ -1466,3 +1480,37 @@
return status;
}
+
+/* This function is called to adjust the connection intervals based on various
+ * constraints. For example, when there is at least one Hearing Aid device
+ * bonded, the minimum interval is raised. On return, min_interval and
+ * max_interval are updated. */
+void L2CA_AdjustConnectionIntervals(uint16_t* min_interval,
+ uint16_t* max_interval,
+ uint16_t floor_interval) {
+ uint16_t phone_min_interval = floor_interval;
+
+ if (HearingAid::GetDeviceCount() > 0) {
+ // When there are bonded Hearing Aid devices, we will constrained this
+ // minimum interval.
+ phone_min_interval = BTM_BLE_CONN_INT_MIN_HEARINGAID;
+ L2CAP_TRACE_DEBUG("%s: Have Hearing Aids. Min. interval is set to %d",
+ __func__, phone_min_interval);
+ }
+
+ if (*min_interval < phone_min_interval) {
+ L2CAP_TRACE_DEBUG("%s: requested min_interval=%d too small. Set to %d",
+ __func__, *min_interval, phone_min_interval);
+ *min_interval = phone_min_interval;
+ }
+
+ // While this could result in connection parameters that fall
+ // outside fo the range requested, this will allow the connection
+ // to remain established.
+ // In other words, this is a workaround for certain peripherals.
+ if (*max_interval < phone_min_interval) {
+ L2CAP_TRACE_DEBUG("%s: requested max_interval=%d too small. Set to %d",
+ __func__, *max_interval, phone_min_interval);
+ *max_interval = phone_min_interval;
+ }
+}
diff --git a/stack/l2cap/l2c_csm.cc b/stack/l2cap/l2c_csm.cc
index 66033ee..bb89eac 100644
--- a/stack/l2cap/l2c_csm.cc
+++ b/stack/l2cap/l2c_csm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -138,16 +138,6 @@
return;
}
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (local_cid == L2CAP_CONNECTIONLESS_CID) {
- /* check if this event can be processed by UCD */
- if (l2c_ucd_process_event(p_ccb, event, p_data)) {
- /* The event is processed by UCD state machine */
- return;
- }
- }
-#endif
-
disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
@@ -195,22 +185,21 @@
true, &l2c_link_sec_comp2, p_ccb);
} else {
/* Cancel sniff mode if needed */
- {
- tBTM_PM_PWR_MD settings;
- memset((void*)&settings, 0, sizeof(settings));
- settings.mode = BTM_PM_MD_ACTIVE;
+ tBTM_PM_PWR_MD settings;
+ memset((void*)&settings, 0, sizeof(settings));
+ settings.mode = BTM_PM_MD_ACTIVE;
- BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
- &settings);
- }
+ BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
+ &settings);
/* If sec access does not result in started SEC_COM or COMP_NEG are
* already processed */
if (btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr,
p_ccb->p_rcb->psm, p_ccb->p_lcb->handle,
true, &l2c_link_sec_comp,
- p_ccb) == BTM_CMD_STARTED)
+ p_ccb) == BTM_CMD_STARTED) {
p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
+ }
}
break;
@@ -290,11 +279,6 @@
case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
l2cu_release_ccb(p_ccb);
break;
-
- case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
- case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
- osi_free(p_data);
- break;
}
}
@@ -315,18 +299,11 @@
tL2CA_CONNECT_CFM_CB* connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
uint16_t local_cid = p_ccb->local_cid;
- L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: ORIG_W4_SEC_COMP evt: %s",
- p_ccb->local_cid, l2c_csm_get_event_name(event));
-
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (local_cid == L2CAP_CONNECTIONLESS_CID) {
- /* check if this event can be processed by UCD */
- if (l2c_ucd_process_event(p_ccb, event, p_data)) {
- /* The event is processed by UCD state machine */
- return;
- }
- }
-#endif
+ L2CAP_TRACE_EVENT(
+ "%s: %sL2CAP - LCID: 0x%04x st: ORIG_W4_SEC_COMP evt: %s", __func__,
+ ((p_ccb->p_lcb) && (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)) ? "LE "
+ : "",
+ p_ccb->local_cid, l2c_csm_get_event_name(event));
switch (event) {
case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
@@ -418,16 +395,6 @@
L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: TERM_W4_SEC_COMP evt: %s",
p_ccb->local_cid, l2c_csm_get_event_name(event));
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
- /* check if this event can be processed by UCD */
- if (l2c_ucd_process_event(p_ccb, event, p_data)) {
- /* The event is processed by UCD state machine */
- return;
- }
- }
-#endif
-
switch (event) {
case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
/* Tell security manager to abort */
@@ -584,16 +551,16 @@
break;
case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer rejected connection */
- L2CAP_TRACE_API(
- "L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Failure Code: %d",
- p_ccb->local_cid, p_ci->l2cap_result);
+ LOG(WARNING) << __func__ << ": L2CAP connection rejected, lcid="
+ << loghex(p_ccb->local_cid)
+ << ", reason=" << loghex(p_ci->l2cap_result);
l2cu_release_ccb(p_ccb);
(*connect_cfm)(local_cid, p_ci->l2cap_result);
break;
case L2CEVT_TIMEOUT:
- L2CAP_TRACE_API("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Timeout",
- p_ccb->local_cid);
+ LOG(WARNING) << __func__ << ": L2CAP connection timeout, lcid="
+ << loghex(p_ccb->local_cid);
l2cu_release_ccb(p_ccb);
(*connect_cfm)(local_cid, L2CAP_CONN_TIMEOUT);
break;
@@ -635,11 +602,6 @@
l2cu_send_peer_connect_req(p_ccb); /* Start Connection */
}
break;
-
- case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
- case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
- osi_free(p_data);
- break;
}
}
@@ -861,7 +823,7 @@
alarm_cancel(p_ccb->l2c_ccb_timer);
/* If failure was channel mode try to renegotiate */
- if (l2c_fcr_renegotiate_chan(p_ccb, p_cfg) == false) {
+ if (!l2c_fcr_renegotiate_chan(p_ccb, p_cfg)) {
L2CAP_TRACE_API(
"L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x, Failure: %d",
p_ccb->local_cid, p_cfg->result);
@@ -1014,16 +976,6 @@
L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: OPEN evt: %s", p_ccb->local_cid,
l2c_csm_get_event_name(event));
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (local_cid == L2CAP_CONNECTIONLESS_CID) {
- /* check if this event can be processed by UCD */
- if (l2c_ucd_process_event(p_ccb, event, p_data)) {
- /* The event is processed by UCD state machine */
- return;
- }
- }
-#endif
-
switch (event) {
case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
L2CAP_TRACE_API(
@@ -1047,7 +999,7 @@
tempstate = p_ccb->chnl_state;
tempcfgdone = p_ccb->config_done;
p_ccb->chnl_state = CST_CONFIG;
- p_ccb->config_done &= ~CFG_DONE_MASK;
+ p_ccb->config_done &= ~IB_CFG_DONE;
alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
l2c_ccb_timer_timeout, p_ccb);
@@ -1156,13 +1108,19 @@
case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
credit = (uint16_t*)p_data;
L2CAP_TRACE_DEBUG("%s Credits received %d", __func__, *credit);
- if ((p_ccb->peer_conn_cfg.credits + *credit) > L2CAP_LE_MAX_CREDIT) {
+ if ((p_ccb->peer_conn_cfg.credits + *credit) > L2CAP_LE_CREDIT_MAX) {
/* we have received credits more than max coc credits,
* so disconnecting the Le Coc Channel
*/
l2cble_send_peer_disc_req(p_ccb);
} else {
p_ccb->peer_conn_cfg.credits += *credit;
+
+ tL2CA_CREDITS_RECEIVED_CB* cr_cb =
+ p_ccb->p_rcb->api.pL2CA_CreditsReceived_Cb;
+ if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE && (cr_cb)) {
+ (*cr_cb)(p_ccb->local_cid, *credit, p_ccb->peer_conn_cfg.credits);
+ }
l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
}
break;
@@ -1223,11 +1181,6 @@
case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
osi_free(p_data);
break;
-
- case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
- case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
- osi_free(p_data);
- break;
}
}
diff --git a/stack/l2cap/l2c_fcr.cc b/stack/l2cap/l2c_fcr.cc
index 0e5a84a..b20b9c1 100644
--- a/stack/l2cap/l2c_fcr.cc
+++ b/stack/l2cap/l2c_fcr.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2004-2012 Broadcom Corporation
+ * Copyright 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
******************************************************************************/
#include <base/logging.h>
+#include <log/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -375,7 +376,7 @@
CHECK(p_ccb != NULL);
if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
/* Check if remote side flowed us off or the transmit window is full */
- if ((p_ccb->fcrb.remote_busy == true) ||
+ if ((p_ccb->fcrb.remote_busy) ||
(fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q) >=
p_ccb->peer_cfg.fcr.tx_win_sz)) {
#if (L2CAP_ERTM_STATS == TRUE)
@@ -802,8 +803,7 @@
/* If a window has opened, check if we can send any more packets */
if ((!fixed_queue_is_empty(p_ccb->fcrb.retrans_q) ||
!fixed_queue_is_empty(p_ccb->xmit_hold_q)) &&
- (p_ccb->fcrb.wait_ack == false) &&
- (l2c_fcr_is_flow_controlled(p_ccb) == false)) {
+ (!p_ccb->fcrb.wait_ack) && (!l2c_fcr_is_flow_controlled(p_ccb))) {
l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
}
}
@@ -841,7 +841,7 @@
return;
}
- p_data = (BT_HDR*)osi_malloc(L2CAP_MAX_BUF_SIZE);
+ p_data = (BT_HDR*)osi_malloc(BT_HDR_SIZE + sdu_length);
if (p_data == NULL) {
osi_free(p_buf);
return;
@@ -855,8 +855,24 @@
p_buf->offset += sizeof(sdu_length);
p_data->offset = 0;
- } else
+ } else {
p_data = p_ccb->ble_sdu;
+ if (p_buf->len > (p_ccb->ble_sdu_length - p_data->len)) {
+ L2CAP_TRACE_ERROR("%s: buffer length=%d too big. max=%d. Dropped",
+ __func__, p_data->len,
+ (p_ccb->ble_sdu_length - p_data->len));
+ android_errorWriteWithInfoLog(0x534e4554, "75298652", -1, NULL, 0);
+ osi_free(p_buf);
+
+ /* Throw away all pending fragments and disconnects */
+ p_ccb->is_first_seg = true;
+ osi_free(p_ccb->ble_sdu);
+ p_ccb->ble_sdu = NULL;
+ p_ccb->ble_sdu_length = 0;
+ l2cu_disconnect_chnl(p_ccb);
+ return;
+ }
+ }
memcpy((uint8_t*)(p_data + 1) + p_data->offset + p_data->len,
(uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len);
@@ -869,9 +885,6 @@
p_ccb->ble_sdu_length = 0;
} else if (p_data->len < p_ccb->ble_sdu_length) {
p_ccb->is_first_seg = false;
- } else {
- L2CAP_TRACE_ERROR("%s Length in the SDU messed up", __func__);
- // TODO: reset every thing may be???
}
osi_free(p_buf);
@@ -1453,7 +1466,8 @@
p_fcrb->rx_sdu_len, p_fcrb->rx_sdu_len);
packet_ok = false;
} else {
- p_fcrb->p_rx_sdu = (BT_HDR*)osi_malloc(L2CAP_MAX_BUF_SIZE);
+ p_fcrb->p_rx_sdu = (BT_HDR*)osi_malloc(
+ BT_HDR_SIZE + OBX_BUF_MIN_OFFSET + p_fcrb->rx_sdu_len);
p_fcrb->p_rx_sdu->offset = OBX_BUF_MIN_OFFSET;
p_fcrb->p_rx_sdu->len = 0;
}
@@ -1489,7 +1503,7 @@
}
}
- if (packet_ok == false) {
+ if (!packet_ok) {
osi_free(p_buf);
} else if (p_buf != NULL) {
#if (L2CAP_NUM_FIXED_CHNLS > 0)
@@ -1790,77 +1804,45 @@
return (p_xmit);
}
-/*******************************************************************************
- *
- * Function l2c_lcc_get_next_xmit_sdu_seg
- *
- * Description Get the next SDU segment to transmit for LE connection
- * oriented channel
- *
- * Returns pointer to buffer with segment or NULL
- *
- ******************************************************************************/
+/** Get the next PDU to transmit for LE connection oriented channel. Returns
+ * pointer to buffer with PDU. |last_piece_of_sdu| will be set to true, if
+ * returned PDU is last piece from this SDU.*/
BT_HDR* l2c_lcc_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb,
- uint16_t max_packet_length) {
- bool first_seg = false; /* The segment is the first part of data */
- bool last_seg = false; /* The segment is the last part of data */
- uint16_t no_of_bytes_to_send = 0;
- uint16_t sdu_len = 0;
- BT_HDR *p_buf, *p_xmit;
- uint8_t* p;
- uint16_t max_pdu = p_ccb->peer_conn_cfg.mps;
+ bool* last_piece_of_sdu) {
+ uint16_t max_pdu = p_ccb->peer_conn_cfg.mps - 4 /* Length and CID */;
- p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->xmit_hold_q);
+ BT_HDR* p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->xmit_hold_q);
+ bool first_pdu = (p_buf->event == 0) ? true : false;
- /* We are using the "event" field to tell is if we already started
- * segmentation */
- if (p_buf->event == 0) {
- first_seg = true;
- sdu_len = p_buf->len;
- if (p_buf->len <= (max_pdu - L2CAP_LCC_SDU_LENGTH)) {
- last_seg = true;
- no_of_bytes_to_send = p_buf->len;
- } else
- no_of_bytes_to_send = max_pdu - L2CAP_LCC_SDU_LENGTH;
- } else if (p_buf->len <= max_pdu) {
- last_seg = true;
- no_of_bytes_to_send = p_buf->len;
- } else {
- /* Middle Packet */
- no_of_bytes_to_send = max_pdu;
- }
+ uint16_t no_of_bytes_to_send = std::min(
+ p_buf->len,
+ (uint16_t)(first_pdu ? (max_pdu - L2CAP_LCC_SDU_LENGTH) : max_pdu));
+ bool last_pdu = (no_of_bytes_to_send == p_buf->len);
/* Get a new buffer and copy the data that can be sent in a PDU */
- if (first_seg == true)
- p_xmit = l2c_fcr_clone_buf(p_buf, L2CAP_LCC_OFFSET, no_of_bytes_to_send);
- else
- p_xmit = l2c_fcr_clone_buf(p_buf, L2CAP_MIN_OFFSET, no_of_bytes_to_send);
+ BT_HDR* p_xmit =
+ l2c_fcr_clone_buf(p_buf, first_pdu ? L2CAP_LCC_OFFSET : L2CAP_MIN_OFFSET,
+ no_of_bytes_to_send);
- if (p_xmit != NULL) {
- p_buf->event = p_ccb->local_cid;
- p_xmit->event = p_ccb->local_cid;
+ p_buf->event = p_ccb->local_cid;
+ p_xmit->event = p_ccb->local_cid;
- if (first_seg == true) {
- p_xmit->offset -= L2CAP_LCC_SDU_LENGTH; /* for writing the SDU length. */
- p = (uint8_t*)(p_xmit + 1) + p_xmit->offset;
- UINT16_TO_STREAM(p, sdu_len);
- p_xmit->len += L2CAP_LCC_SDU_LENGTH;
- }
-
- p_buf->len -= no_of_bytes_to_send;
- p_buf->offset += no_of_bytes_to_send;
-
- /* copy PBF setting */
- p_xmit->layer_specific = p_buf->layer_specific;
-
- } else /* Should never happen if the application has configured buffers
- correctly */
- {
- L2CAP_TRACE_ERROR("L2CAP - cannot get buffer, for segmentation");
- return (NULL);
+ if (first_pdu) {
+ p_xmit->offset -= L2CAP_LCC_SDU_LENGTH; /* for writing the SDU length. */
+ uint8_t* p = (uint8_t*)(p_xmit + 1) + p_xmit->offset;
+ UINT16_TO_STREAM(p, p_buf->len);
+ p_xmit->len += L2CAP_LCC_SDU_LENGTH;
}
- if (last_seg == true) {
+ p_buf->len -= no_of_bytes_to_send;
+ p_buf->offset += no_of_bytes_to_send;
+
+ /* copy PBF setting */
+ p_xmit->layer_specific = p_buf->layer_specific;
+
+ if (last_piece_of_sdu) *last_piece_of_sdu = last_pdu;
+
+ if (last_pdu) {
p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
osi_free(p_buf);
}
@@ -1870,7 +1852,7 @@
p_xmit->len += L2CAP_PKT_OVERHEAD;
/* Set the pointer to the beginning of the data */
- p = (uint8_t*)(p_xmit + 1) + p_xmit->offset;
+ uint8_t* p = (uint8_t*)(p_xmit + 1) + p_xmit->offset;
/* Note: if FCS has to be included then the length is recalculated later */
UINT16_TO_STREAM(p, p_xmit->len - L2CAP_PKT_OVERHEAD);
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 14eb1e5..421e34d 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,14 +37,21 @@
#define L2CAP_MIN_MTU 48 /* Minimum acceptable MTU is 48 bytes */
/* LE credit based L2CAP connection parameters */
-#define L2CAP_LE_MIN_MTU 23
-#define L2CAP_LE_MIN_MPS 23
-#define L2CAP_LE_MAX_MPS 65533
-#define L2CAP_LE_MIN_CREDIT 0
-#define L2CAP_LE_MAX_CREDIT 65535
-#define L2CAP_LE_DEFAULT_MTU 512
-#define L2CAP_LE_DEFAULT_MPS 23
-#define L2CAP_LE_DEFAULT_CREDIT 1
+constexpr uint16_t L2CAP_LE_MIN_MTU = 23; // Minimum SDU size
+constexpr uint16_t L2CAP_LE_MIN_MPS = 23;
+constexpr uint16_t L2CAP_LE_MAX_MPS = 65533;
+constexpr uint16_t L2CAP_LE_CREDIT_MAX = 65535;
+
+// This is initial amout of credits we send, and amount to which we increase
+// credits once they fall below threshold
+constexpr uint16_t L2CAP_LE_CREDIT_DEFAULT = 0xffff;
+
+// If credit count on remote fall below this value, we send back credits to
+// reach default value.
+constexpr uint16_t L2CAP_LE_CREDIT_THRESHOLD = 0x0040;
+
+static_assert(L2CAP_LE_CREDIT_THRESHOLD < L2CAP_LE_CREDIT_DEFAULT,
+ "Threshold must be smaller then default credits");
/*
* Timeout values (in milliseconds).
@@ -147,6 +154,11 @@
*/
#define L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT 36 /* Peer credit packet */
+/* Constants for LE Dynamic PSM values */
+#define LE_DYNAMIC_PSM_START 0x0080
+#define LE_DYNAMIC_PSM_END 0x00FF
+#define LE_DYNAMIC_PSM_RANGE (LE_DYNAMIC_PSM_END - LE_DYNAMIC_PSM_START + 1)
+
/* Bitmask to skip over Broadcom feature reserved (ID) to avoid sending two
successive ID values, '0' id only or both */
#define L2CAP_ADJ_BRCM_ID 0x1
@@ -224,31 +236,11 @@
#endif
} tL2C_FCRB;
-/* Define a registration control block. Every application (e.g. RFCOMM, SDP,
- * TCS etc) that registers with L2CAP is assigned one of these.
-*/
-#if (L2CAP_UCD_INCLUDED == TRUE)
-#define L2C_UCD_RCB_ID 0x00
-#define L2C_UCD_STATE_UNUSED 0x00
-#define L2C_UCD_STATE_W4_DATA 0x01
-#define L2C_UCD_STATE_W4_RECEPTION 0x02
-#define L2C_UCD_STATE_W4_MTU 0x04
-
-typedef struct {
- uint8_t state;
- tL2CAP_UCD_CB_INFO cb_info;
-} tL2C_UCD_REG;
-#endif
-
typedef struct {
bool in_use;
uint16_t psm;
uint16_t real_psm; /* This may be a dummy RCB for an o/b connection but */
/* this is the real PSM that we need to connect to */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- tL2C_UCD_REG ucd;
-#endif
-
tL2CAP_APPL_INFO api;
} tL2C_RCB;
@@ -340,10 +332,14 @@
bool is_flushable; /* true if channel is flushable */
#endif
-#if (L2CAP_NUM_FIXED_CHNLS > 0 || L2CAP_UCD_INCLUDED == TRUE)
+#if (L2CAP_NUM_FIXED_CHNLS > 0)
uint16_t fixed_chnl_idle_tout; /* Idle timeout to use for the fixed channel */
#endif
uint16_t tx_data_len;
+
+ /* Number of LE frames that the remote can send to us (credit count in
+ * remote). Valid only for LE CoC */
+ uint16_t remote_credit_count;
} tL2C_CCB;
/***********************************************************************
@@ -415,13 +411,6 @@
list_t* link_xmit_data_q; /* Link transmit data buffer queue */
uint8_t peer_chnl_mask[L2CAP_FIXED_CHNL_ARRAY_SIZE];
-#if (L2CAP_UCD_INCLUDED == TRUE)
- uint16_t ucd_mtu; /* peer MTU on UCD */
- fixed_queue_t*
- ucd_out_sec_pending_q; /* Security pending outgoing UCD packet */
- fixed_queue_t*
- ucd_in_sec_pending_q; /* Security pending incoming UCD packet */
-#endif
BT_HDR* p_hcit_rcv_acl; /* Current HCIT ACL buf being rcvd */
uint16_t idle_timeout_sv; /* Save current Idle timeout */
@@ -454,6 +443,8 @@
uint16_t max_interval;
uint16_t latency;
uint16_t timeout;
+ uint16_t min_ce_len;
+ uint16_t max_ce_len;
#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
/* each priority group is limited burst transmission */
@@ -530,6 +521,10 @@
#endif /* (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == TRUE) */
uint16_t dyn_psm;
+
+ uint16_t le_dyn_psm; /* Next LE dynamic PSM value to try to assign */
+ bool le_dyn_psm_assigned[LE_DYNAMIC_PSM_RANGE]; /* Table of assigned LE PSM */
+
} tL2C_CB;
/* Define a structure that contains the information about a connection.
@@ -667,23 +662,6 @@
extern void l2cu_process_fixed_chnl_resp(tL2C_LCB* p_lcb);
extern bool l2cu_is_ccb_active(tL2C_CCB* p_ccb);
-/* Functions provided by l2c_ucd.cc
- ***********************************
-*/
-#if (L2CAP_UCD_INCLUDED == TRUE)
-void l2c_ucd_delete_sec_pending_q(tL2C_LCB* p_lcb);
-void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB* p_ccb, void* p_data);
-bool l2c_ucd_check_pending_info_req(tL2C_CCB* p_ccb);
-bool l2c_ucd_check_pending_out_sec_q(tL2C_CCB* p_ccb);
-void l2c_ucd_send_pending_out_sec_q(tL2C_CCB* p_ccb);
-void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB* p_ccb);
-bool l2c_ucd_check_pending_in_sec_q(tL2C_CCB* p_ccb);
-void l2c_ucd_send_pending_in_sec_q(tL2C_CCB* p_ccb);
-void l2c_ucd_discard_pending_in_sec_q(tL2C_CCB* p_ccb);
-bool l2c_ucd_check_rx_pkts(tL2C_LCB* p_lcb, BT_HDR* p_msg);
-bool l2c_ucd_process_event(tL2C_CCB* p_ccb, uint16_t event, void* p_data);
-#endif
-
/* Functions provided for Broadcom Aware
***************************************
*/
@@ -696,6 +674,7 @@
extern tL2C_RCB* l2cu_allocate_rcb(uint16_t psm);
extern tL2C_RCB* l2cu_find_rcb_by_psm(uint16_t psm);
extern void l2cu_release_rcb(tL2C_RCB* p_rcb);
+extern void l2cu_release_ble_rcb(tL2C_RCB* p_rcb);
extern tL2C_RCB* l2cu_allocate_ble_rcb(uint16_t psm);
extern tL2C_RCB* l2cu_find_ble_rcb_by_psm(uint16_t psm);
@@ -785,7 +764,7 @@
extern void l2c_fcr_start_timer(tL2C_CCB* p_ccb);
extern void l2c_lcc_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf);
extern BT_HDR* l2c_lcc_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb,
- uint16_t max_packet_length);
+ bool* last_piece_of_sdu);
/* Configuration negotiation */
extern uint8_t l2c_fcr_chk_chan_modes(tL2C_CCB* p_ccb);
diff --git a/stack/l2cap/l2c_link.cc b/stack/l2cap/l2c_link.cc
index bd4a610..db7e613 100644
--- a/stack/l2cap/l2c_link.cc
+++ b/stack/l2cap/l2c_link.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -285,7 +285,8 @@
tL2C_CCB* p_next_ccb;
uint8_t event;
- L2CAP_TRACE_DEBUG("l2c_link_sec_comp: %d, 0x%x", status, p_ref_data);
+ L2CAP_TRACE_DEBUG("%s: status=%d, p_ref_data=%p, BD_ADDR=%s", __func__,
+ status, p_ref_data, p_bda.ToString().c_str());
if (status == BTM_SUCCESS_NO_SECURITY) status = BTM_SUCCESS;
@@ -396,19 +397,19 @@
if (p_lcb->ccb_queue.p_first_ccb != NULL || p_lcb->p_pending_ccb) {
L2CAP_TRACE_DEBUG(
"l2c_link_hci_disc_comp: Restarting pending ACL request");
+ /* Release any held buffers */
+ while (!list_is_empty(p_lcb->link_xmit_data_q)) {
+ BT_HDR* p_buf =
+ static_cast<BT_HDR*>(list_front(p_lcb->link_xmit_data_q));
+ list_remove(p_lcb->link_xmit_data_q, p_buf);
+ osi_free(p_buf);
+ }
transport = p_lcb->transport;
/* for LE link, always drop and re-open to ensure to get LE remote feature
*/
if (p_lcb->transport == BT_TRANSPORT_LE) {
l2cb.is_ble_connecting = false;
btm_acl_removed(p_lcb->remote_bd_addr, p_lcb->transport);
- /* Release any held buffers */
- BT_HDR* p_buf;
- while (!list_is_empty(p_lcb->link_xmit_data_q)) {
- p_buf = static_cast<BT_HDR*>(list_front(p_lcb->link_xmit_data_q));
- list_remove(p_lcb->link_xmit_data_q, p_buf);
- osi_free(p_buf);
- }
} else {
#if (L2CAP_NUM_FIXED_CHNLS > 0)
/* If we are going to re-use the LCB without dropping it, release all
@@ -523,7 +524,7 @@
p_ccb = pn;
}
- if (p_lcb->link_state == LST_CONNECTING && l2cb.is_ble_connecting == true) {
+ if (p_lcb->link_state == LST_CONNECTING && l2cb.is_ble_connecting) {
L2CA_CancelBleConnectReq(l2cb.ble_connecting_bda);
}
/* Release the LCB */
diff --git a/stack/l2cap/l2c_main.cc b/stack/l2cap/l2c_main.cc
index 19ce0a4..eae77a6 100644
--- a/stack/l2cap/l2c_main.cc
+++ b/stack/l2cap/l2c_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,71 +62,23 @@
******************************************************************************/
void l2c_rcv_acl_data(BT_HDR* p_msg) {
uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
- uint16_t handle, hci_len;
- uint8_t pkt_type;
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb = NULL;
- uint16_t l2cap_len, rcv_cid;
- uint16_t credit;
/* Extract the handle */
+ uint16_t handle;
STREAM_TO_UINT16(handle, p);
- pkt_type = HCID_GET_EVENT(handle);
+ uint8_t pkt_type = HCID_GET_EVENT(handle);
handle = HCID_GET_HANDLE(handle);
/* Since the HCI Transport is putting segmented packets back together, we */
/* should never get a valid packet with the type set to "continuation" */
- if (pkt_type != L2CAP_PKT_CONTINUE) {
- /* Find the LCB based on the handle */
- p_lcb = l2cu_find_lcb_by_handle(handle);
- if (p_lcb == NULL) {
- uint8_t cmd_code;
-
- /* There is a slight possibility (specifically with USB) that we get an */
- /* L2CAP connection request before we get the HCI connection complete. */
- /* So for these types of messages, hold them for up to 2 seconds. */
- STREAM_TO_UINT16(hci_len, p);
- STREAM_TO_UINT16(l2cap_len, p);
- STREAM_TO_UINT16(rcv_cid, p);
- STREAM_TO_UINT8(cmd_code, p);
-
- if ((p_msg->layer_specific == 0) && (rcv_cid == L2CAP_SIGNALLING_CID) &&
- (cmd_code == L2CAP_CMD_INFO_REQ || cmd_code == L2CAP_CMD_CONN_REQ)) {
- L2CAP_TRACE_WARNING(
- "L2CAP - holding ACL for unknown handle:%d ls:%d"
- " cid:%d opcode:%d cur count:%d",
- handle, p_msg->layer_specific, rcv_cid, cmd_code,
- list_length(l2cb.rcv_pending_q));
- p_msg->layer_specific = 2;
- list_append(l2cb.rcv_pending_q, p_msg);
-
- if (list_length(l2cb.rcv_pending_q) == 1) {
- alarm_set_on_mloop(l2cb.receive_hold_timer, BT_1SEC_TIMEOUT_MS,
- l2c_receive_hold_timer_timeout, NULL);
- }
-
- return;
- } else {
- L2CAP_TRACE_ERROR(
- "L2CAP - rcvd ACL for unknown handle:%d ls:%d cid:%d"
- " opcode:%d cur count:%d",
- handle, p_msg->layer_specific, rcv_cid, cmd_code,
- list_length(l2cb.rcv_pending_q));
- }
- osi_free(p_msg);
- return;
- }
- } else {
- L2CAP_TRACE_WARNING("L2CAP - expected pkt start or complete, got: %d",
- pkt_type);
+ if (pkt_type == L2CAP_PKT_CONTINUE) {
+ L2CAP_TRACE_WARNING("L2CAP - received packet continuation");
osi_free(p_msg);
return;
}
- /* Extract the length and update the buffer header */
+ uint16_t hci_len;
STREAM_TO_UINT16(hci_len, p);
- p_msg->offset += 4;
-
if (hci_len < L2CAP_PKT_OVERHEAD) {
/* Must receive at least the L2CAP length and CID */
L2CAP_TRACE_WARNING("L2CAP - got incorrect hci header");
@@ -134,22 +86,68 @@
return;
}
- /* Extract the length and CID */
+ uint16_t l2cap_len, rcv_cid;
STREAM_TO_UINT16(l2cap_len, p);
STREAM_TO_UINT16(rcv_cid, p);
+ /* Find the LCB based on the handle */
+ tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
+ if (!p_lcb) {
+ /* There is a slight possibility (specifically with USB) that we get an */
+ /* L2CAP connection request before we get the HCI connection complete. */
+ /* So for these types of messages, hold them for up to 2 seconds. */
+ uint8_t cmd_code;
+ STREAM_TO_UINT8(cmd_code, p);
+
+ if ((p_msg->layer_specific != 0) || (rcv_cid != L2CAP_SIGNALLING_CID) ||
+ (cmd_code != L2CAP_CMD_INFO_REQ && cmd_code != L2CAP_CMD_CONN_REQ)) {
+ bool qcom_debug_log =
+ (handle == 3804 && cmd_code == 10 && p_msg->layer_specific == 0);
+
+ if (!qcom_debug_log) {
+ L2CAP_TRACE_ERROR(
+ "L2CAP - rcvd ACL for unknown handle:%d ls:%d cid:%d opcode:%d cur "
+ "count:%d",
+ handle, p_msg->layer_specific, rcv_cid, cmd_code,
+ list_length(l2cb.rcv_pending_q));
+ }
+
+ osi_free(p_msg);
+ return;
+ }
+
+ L2CAP_TRACE_WARNING(
+ "L2CAP - holding ACL for unknown handle:%d ls:%d cid:%d opcode:%d cur "
+ "count:%d",
+ handle, p_msg->layer_specific, rcv_cid, cmd_code,
+ list_length(l2cb.rcv_pending_q));
+ p_msg->layer_specific = 2;
+ list_append(l2cb.rcv_pending_q, p_msg);
+
+ if (list_length(l2cb.rcv_pending_q) == 1) {
+ alarm_set_on_mloop(l2cb.receive_hold_timer, BT_1SEC_TIMEOUT_MS,
+ l2c_receive_hold_timer_timeout, NULL);
+ }
+ return;
+ }
+
+ /* Update the buffer header */
+ p_msg->offset += 4;
+
/* for BLE channel, always notify connection when ACL data received on the
* link */
if (p_lcb && p_lcb->transport == BT_TRANSPORT_LE &&
- p_lcb->link_state != LST_DISCONNECTING)
+ p_lcb->link_state != LST_DISCONNECTING) {
/* only process fixed channel data as channel open indication when link is
* not in disconnecting mode */
l2cble_notify_le_connection(p_lcb->remote_bd_addr);
+ }
/* Find the CCB for this CID */
+ tL2C_CCB* p_ccb = NULL;
if (rcv_cid >= L2CAP_BASE_APPL_CID) {
p_ccb = l2cu_find_ccb_by_cid(p_lcb, rcv_cid);
- if (p_ccb == NULL) {
+ if (!p_ccb) {
L2CAP_TRACE_WARNING("L2CAP - unknown CID: 0x%04x", rcv_cid);
osi_free(p_msg);
return;
@@ -162,7 +160,6 @@
if (l2cap_len != p_msg->len) {
L2CAP_TRACE_WARNING("L2CAP - bad length in pkt. Exp: %d Act: %d",
l2cap_len, p_msg->len);
-
osi_free(p_msg);
return;
}
@@ -171,67 +168,78 @@
if (rcv_cid == L2CAP_SIGNALLING_CID) {
process_l2cap_cmd(p_lcb, p, l2cap_len);
osi_free(p_msg);
- } else if (rcv_cid == L2CAP_CONNECTIONLESS_CID) {
- /* process_connectionless_data (p_lcb); */
+ return;
+ }
-#if (L2CAP_UCD_INCLUDED == TRUE)
- /* if it is not broadcast, check UCD registration */
- if (l2c_ucd_check_rx_pkts(p_lcb, p_msg)) {
- /* nothing to do */
- } else
-#endif
- osi_free(p_msg);
- } else if (rcv_cid == L2CAP_BLE_SIGNALLING_CID) {
+ if (rcv_cid == L2CAP_CONNECTIONLESS_CID) {
+ /* process_connectionless_data (p_lcb); */
+ osi_free(p_msg);
+ return;
+ }
+
+ if (rcv_cid == L2CAP_BLE_SIGNALLING_CID) {
l2cble_process_sig_cmd(p_lcb, p, l2cap_len);
osi_free(p_msg);
+ return;
}
-#if (L2CAP_NUM_FIXED_CHNLS > 0)
- else if ((rcv_cid >= L2CAP_FIRST_FIXED_CHNL) &&
- (rcv_cid <= L2CAP_LAST_FIXED_CHNL) &&
- (l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL]
- .pL2CA_FixedData_Cb != NULL)) {
- /* If no CCB for this channel, allocate one */
- if (p_lcb &&
- /* only process fixed channel data when link is open or wait for data
- indication */
- (p_lcb->link_state != LST_DISCONNECTING) &&
- l2cu_initialize_fixed_ccb(
- p_lcb, rcv_cid, &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL]
- .fixed_chnl_opts)) {
- p_ccb = p_lcb->p_fixed_ccbs[rcv_cid - L2CAP_FIRST_FIXED_CHNL];
- if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
- l2c_fcr_proc_pdu(p_ccb, p_msg);
- else
- (*l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(
- rcv_cid, p_lcb->remote_bd_addr, p_msg);
- } else
+#if (L2CAP_NUM_FIXED_CHNLS > 0)
+ if ((rcv_cid >= L2CAP_FIRST_FIXED_CHNL) &&
+ (rcv_cid <= L2CAP_LAST_FIXED_CHNL) &&
+ (l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb !=
+ NULL)) {
+ /* only process fixed channel data when link is open or wait for data
+ * indication */
+ if (!p_lcb || p_lcb->link_state == LST_DISCONNECTING ||
+ !l2cu_initialize_fixed_ccb(
+ p_lcb, rcv_cid,
+ &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL]
+ .fixed_chnl_opts)) {
osi_free(p_msg);
+ return;
+ }
+
+ /* If no CCB for this channel, allocate one */
+ p_ccb = p_lcb->p_fixed_ccbs[rcv_cid - L2CAP_FIRST_FIXED_CHNL];
+
+ if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
+ l2c_fcr_proc_pdu(p_ccb, p_msg);
+ else
+ (*l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(
+ rcv_cid, p_lcb->remote_bd_addr, p_msg);
+ return;
}
#endif
- else {
- if (p_ccb == NULL)
- osi_free(p_msg);
+ if (!p_ccb) {
+ osi_free(p_msg);
+ return;
+ }
+
+ if (p_lcb->transport == BT_TRANSPORT_LE) {
+ l2c_lcc_proc_pdu(p_ccb, p_msg);
+
+ /* The remote device has one less credit left */
+ --p_ccb->remote_credit_count;
+
+ /* If the credits left on the remote device are getting low, send some */
+ if (p_ccb->remote_credit_count <= L2CAP_LE_CREDIT_THRESHOLD) {
+ uint16_t credits = L2CAP_LE_CREDIT_DEFAULT - p_ccb->remote_credit_count;
+ p_ccb->remote_credit_count = L2CAP_LE_CREDIT_DEFAULT;
+
+ /* Return back credits */
+ l2c_csm_execute(p_ccb, L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT, &credits);
+ }
+ } else {
+ /* Basic mode packets go straight to the state machine */
+ if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE)
+ l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);
else {
- if (p_lcb->transport == BT_TRANSPORT_LE) {
- l2c_lcc_proc_pdu(p_ccb, p_msg);
- // Got a pkt, valid send out credits to the peer device
- credit = L2CAP_LE_DEFAULT_CREDIT;
- l2c_csm_execute(p_ccb, L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT, &credit);
- } else {
- /* Basic mode packets go straight to the state machine */
- if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE)
- l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);
- else {
- /* eRTM or streaming mode, so we need to validate states first */
- if ((p_ccb->chnl_state == CST_OPEN) ||
- (p_ccb->chnl_state == CST_CONFIG))
- l2c_fcr_proc_pdu(p_ccb, p_msg);
- else
- osi_free(p_msg);
- }
- }
+ /* eRTM or streaming mode, so we need to validate states first */
+ if ((p_ccb->chnl_state == CST_OPEN) || (p_ccb->chnl_state == CST_CONFIG))
+ l2c_fcr_proc_pdu(p_ccb, p_msg);
+ else
+ osi_free(p_msg);
}
}
}
@@ -247,38 +255,27 @@
*
******************************************************************************/
static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
- uint8_t *p_pkt_end, *p_next_cmd, *p_cfg_end, *p_cfg_start;
- uint8_t cmd_code, cfg_code, cfg_len, id;
tL2C_CONN_INFO con_info;
- tL2CAP_CFG_INFO cfg_info;
- uint16_t rej_reason, rej_mtu, lcid, rcid, info_type;
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
- bool cfg_rej, pkt_size_rej = false;
- uint16_t cfg_rej_len, cmd_len;
- uint16_t result;
- tL2C_CONN_INFO ci;
/* if l2cap command received in CID 1 on top of an LE link, ignore this
* command */
if (p_lcb->transport == BT_TRANSPORT_LE) return;
/* Reject the packet if it exceeds the default Signalling Channel MTU */
+ bool pkt_size_rej = false;
if (pkt_len > L2CAP_DEFAULT_MTU) {
/* Core Spec requires a single response to the first command found in a
- *multi-command
- ** L2cap packet. If only responses in the packet, then it will be ignored.
- ** Here we simply mark the bad packet and decide which cmd ID to reject
- *later
- */
+ * multi-command L2cap packet. If only responses in the packet, then it
+ * will be ignored. Here we simply mark the bad packet and decide which cmd
+ * ID to reject later */
pkt_size_rej = true;
- L2CAP_TRACE_ERROR("L2CAP SIG MTU Pkt Len Exceeded (672) -> pkt_len: %d",
- pkt_len);
+ L2CAP_TRACE_ERROR("L2CAP SIG MTU pkt_len=%d Exceeded 672", pkt_len);
}
- p_next_cmd = p;
- p_pkt_end = p + pkt_len;
+ uint8_t* p_next_cmd = p;
+ uint8_t* p_pkt_end = p + pkt_len;
+ tL2CAP_CFG_INFO cfg_info;
memset(&cfg_info, 0, sizeof(cfg_info));
/* An L2CAP packet may contain multiple commands */
@@ -287,6 +284,8 @@
p = p_next_cmd;
if (p > (p_pkt_end - 4)) break;
+ uint8_t cmd_code, id;
+ uint16_t cmd_len;
STREAM_TO_UINT8(cmd_code, p);
STREAM_TO_UINT8(id, p);
STREAM_TO_UINT16(cmd_len, p);
@@ -307,7 +306,7 @@
L2CAP_TRACE_DEBUG("cmd_code: %d, id:%d, cmd_len:%d", cmd_code, id, cmd_len);
- /* Bad L2CAP packet length, look or cmd to reject */
+ /* Bad L2CAP packet length, look for cmd to reject */
if (pkt_size_rej) {
/* If command found rejected it and we're done, otherwise keep looking */
if (l2c_is_cmd_rejected(cmd_code, id, p_lcb))
@@ -318,30 +317,22 @@
switch (cmd_code) {
case L2CAP_CMD_REJECT:
- if (p + 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ uint16_t rej_reason;
+ if (p + 2 > p_next_cmd) return;
STREAM_TO_UINT16(rej_reason, p);
if (rej_reason == L2CAP_CMD_REJ_MTU_EXCEEDED) {
- if (p + 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ uint16_t rej_mtu;
+ if (p + 2 > p_next_cmd) return;
STREAM_TO_UINT16(rej_mtu, p);
/* What to do with the MTU reject ? We have negotiated an MTU. For now
+ * we will ignore it and let a higher protocol timeout take care of it
*/
- /* we will ignore it and let a higher protocol timeout take care of it
- */
-
L2CAP_TRACE_WARNING("L2CAP - MTU rej Handle: %d MTU: %d",
p_lcb->handle, rej_mtu);
}
if (rej_reason == L2CAP_CMD_REJ_INVALID_CID) {
- if (p + 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ uint16_t lcid, rcid;
+ if (p + 4 > p_next_cmd) return;
STREAM_TO_UINT16(rcid, p);
STREAM_TO_UINT16(lcid, p);
@@ -350,7 +341,7 @@
rcid);
/* Remote CID invalid. Treat as a disconnect */
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
+ tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
if ((p_ccb != NULL) && (p_ccb->remote_cid == rcid)) {
/* Fake link disconnect - no reply is generated */
l2c_csm_execute(p_ccb, L2CEVT_LP_DISCONNECT_IND, NULL);
@@ -363,26 +354,25 @@
alarm_cancel(p_lcb->info_resp_timer);
p_lcb->w4_info_rsp = false;
+ tL2C_CONN_INFO ci;
ci.status = HCI_SUCCESS;
ci.bd_addr = p_lcb->remote_bd_addr;
/* For all channels, send the event through their FSMs */
- for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
+ for (tL2C_CCB* p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
p_ccb = p_ccb->p_next_ccb) {
l2c_csm_execute(p_ccb, L2CEVT_L2CAP_INFO_RSP, &ci);
}
}
break;
- case L2CAP_CMD_CONN_REQ:
- if (p + 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ case L2CAP_CMD_CONN_REQ: {
+ uint16_t rcid;
+ if (p + 4 > p_next_cmd) return;
STREAM_TO_UINT16(con_info.psm, p);
STREAM_TO_UINT16(rcid, p);
- p_rcb = l2cu_find_rcb_by_psm(con_info.psm);
- if (p_rcb == NULL) {
+ tL2C_RCB* p_rcb = l2cu_find_rcb_by_psm(con_info.psm);
+ if (!p_rcb) {
L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for unknown PSM: %d",
con_info.psm);
l2cu_reject_connection(p_lcb, rcid, id, L2CAP_CONN_NO_PSM);
@@ -396,8 +386,8 @@
break;
}
}
- p_ccb = l2cu_allocate_ccb(p_lcb, 0);
- if (p_ccb == NULL) {
+ tL2C_CCB* p_ccb = l2cu_allocate_ccb(p_lcb, 0);
+ if (!p_ccb) {
L2CAP_TRACE_ERROR("L2CAP - unable to allocate CCB");
l2cu_reject_connection(p_lcb, rcid, id, L2CAP_CONN_NO_RESOURCES);
break;
@@ -408,19 +398,18 @@
l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
break;
+ }
- case L2CAP_CMD_CONN_RSP:
- if (p + 8 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ case L2CAP_CMD_CONN_RSP: {
+ uint16_t lcid;
+ if (p + 8 > p_next_cmd) return;
STREAM_TO_UINT16(con_info.remote_cid, p);
STREAM_TO_UINT16(lcid, p);
STREAM_TO_UINT16(con_info.l2cap_result, p);
STREAM_TO_UINT16(con_info.l2cap_status, p);
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
- if (p_ccb == NULL) {
+ tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
+ if (!p_ccb) {
L2CAP_TRACE_WARNING("L2CAP - no CCB for conn rsp, LCID: %d RCID: %d",
lcid, con_info.remote_cid);
break;
@@ -439,58 +428,46 @@
l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
break;
+ }
- case L2CAP_CMD_CONFIG_REQ:
- p_cfg_end = p + cmd_len;
- cfg_rej = false;
- cfg_rej_len = 0;
+ case L2CAP_CMD_CONFIG_REQ: {
+ uint8_t* p_cfg_end = p + cmd_len;
+ bool cfg_rej = false;
+ uint16_t cfg_rej_len = 0;
- if (p + 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ uint16_t lcid;
+ if (p + 4 > p_next_cmd) return;
STREAM_TO_UINT16(lcid, p);
STREAM_TO_UINT16(cfg_info.flags, p);
- p_cfg_start = p;
+ uint8_t* p_cfg_start = p;
cfg_info.flush_to_present = cfg_info.mtu_present =
cfg_info.qos_present = cfg_info.fcr_present = cfg_info.fcs_present =
false;
while (p < p_cfg_end) {
- if (p + 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ uint8_t cfg_code, cfg_len;
+ if (p + 2 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_code, p);
STREAM_TO_UINT8(cfg_len, p);
switch (cfg_code & 0x7F) {
case L2CAP_CFG_TYPE_MTU:
cfg_info.mtu_present = true;
- if (p + 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 2 > p_next_cmd) return;
STREAM_TO_UINT16(cfg_info.mtu, p);
break;
case L2CAP_CFG_TYPE_FLUSH_TOUT:
cfg_info.flush_to_present = true;
- if (p + 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 2 > p_next_cmd) return;
STREAM_TO_UINT16(cfg_info.flush_to, p);
break;
case L2CAP_CFG_TYPE_QOS:
cfg_info.qos_present = true;
- if (p + 2 + 5 * 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 2 + 5 * 4 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_info.qos.qos_flags, p);
STREAM_TO_UINT8(cfg_info.qos.service_type, p);
STREAM_TO_UINT32(cfg_info.qos.token_rate, p);
@@ -502,10 +479,7 @@
case L2CAP_CFG_TYPE_FCR:
cfg_info.fcr_present = true;
- if (p + 3 + 3 * 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 3 + 3 * 2 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_info.fcr.mode, p);
STREAM_TO_UINT8(cfg_info.fcr.tx_win_sz, p);
STREAM_TO_UINT8(cfg_info.fcr.max_transmit, p);
@@ -516,19 +490,13 @@
case L2CAP_CFG_TYPE_FCS:
cfg_info.fcs_present = true;
- if (p + 1 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 1 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_info.fcs, p);
break;
case L2CAP_CFG_TYPE_EXT_FLOW:
cfg_info.ext_flow_spec_present = true;
- if (p + 2 + 2 + 3 * 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 2 + 2 + 3 * 4 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_info.ext_flow_spec.id, p);
STREAM_TO_UINT8(cfg_info.ext_flow_spec.stype, p);
STREAM_TO_UINT16(cfg_info.ext_flow_spec.max_sdu_size, p);
@@ -540,10 +508,7 @@
default:
/* sanity check option length */
if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= cmd_len) {
- if (p + cfg_len > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "79488381");
- return;
- }
+ if (p + cfg_len > p_next_cmd) return;
p += cfg_len;
if ((cfg_code & 0x80) == 0) {
cfg_rej_len += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
@@ -559,8 +524,8 @@
}
}
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
- if (p_ccb != NULL) {
+ tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
+ if (p_ccb) {
p_ccb->remote_id = id;
if (cfg_rej) {
l2cu_send_peer_config_rej(
@@ -574,13 +539,12 @@
l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_INVALID_CID, id, 0, 0);
}
break;
+ }
- case L2CAP_CMD_CONFIG_RSP:
- p_cfg_end = p + cmd_len;
- if (p + 6 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ case L2CAP_CMD_CONFIG_RSP: {
+ uint8_t* p_cfg_end = p + cmd_len;
+ uint16_t lcid;
+ if (p + 6 > p_next_cmd) return;
STREAM_TO_UINT16(lcid, p);
STREAM_TO_UINT16(cfg_info.flags, p);
STREAM_TO_UINT16(cfg_info.result, p);
@@ -590,38 +554,27 @@
false;
while (p < p_cfg_end) {
- if (p + 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ uint8_t cfg_code, cfg_len;
+ if (p + 2 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_code, p);
STREAM_TO_UINT8(cfg_len, p);
switch (cfg_code & 0x7F) {
case L2CAP_CFG_TYPE_MTU:
cfg_info.mtu_present = true;
- if (p + 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 2 > p_next_cmd) return;
STREAM_TO_UINT16(cfg_info.mtu, p);
break;
case L2CAP_CFG_TYPE_FLUSH_TOUT:
cfg_info.flush_to_present = true;
- if (p + 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 2 > p_next_cmd) return;
STREAM_TO_UINT16(cfg_info.flush_to, p);
break;
case L2CAP_CFG_TYPE_QOS:
cfg_info.qos_present = true;
- if (p + 2 + 5 * 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 2 + 5 * 4 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_info.qos.qos_flags, p);
STREAM_TO_UINT8(cfg_info.qos.service_type, p);
STREAM_TO_UINT32(cfg_info.qos.token_rate, p);
@@ -633,10 +586,7 @@
case L2CAP_CFG_TYPE_FCR:
cfg_info.fcr_present = true;
- if (p + 3 + 3 * 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 3 + 3 * 2 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_info.fcr.mode, p);
STREAM_TO_UINT8(cfg_info.fcr.tx_win_sz, p);
STREAM_TO_UINT8(cfg_info.fcr.max_transmit, p);
@@ -647,19 +597,13 @@
case L2CAP_CFG_TYPE_FCS:
cfg_info.fcs_present = true;
- if (p + 1 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 1 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_info.fcs, p);
break;
case L2CAP_CFG_TYPE_EXT_FLOW:
cfg_info.ext_flow_spec_present = true;
- if (p + 2 + 2 + 3 * 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 2 + 2 + 3 * 4 > p_next_cmd) return;
STREAM_TO_UINT8(cfg_info.ext_flow_spec.id, p);
STREAM_TO_UINT8(cfg_info.ext_flow_spec.stype, p);
STREAM_TO_UINT16(cfg_info.ext_flow_spec.max_sdu_size, p);
@@ -670,8 +614,8 @@
}
}
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
- if (p_ccb != NULL) {
+ tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
+ if (p_ccb) {
if (p_ccb->local_id != id) {
L2CAP_TRACE_WARNING("L2CAP - cfg rsp - bad ID. Exp: %d Got: %d",
p_ccb->local_id, id);
@@ -687,17 +631,16 @@
lcid);
}
break;
+ }
- case L2CAP_CMD_DISC_REQ:
- if (p + 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ case L2CAP_CMD_DISC_REQ: {
+ uint16_t lcid, rcid;
+ if (p + 4 > p_next_cmd) return;
STREAM_TO_UINT16(lcid, p);
STREAM_TO_UINT16(rcid, p);
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
- if (p_ccb != NULL) {
+ tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
+ if (p_ccb) {
if (p_ccb->remote_cid == rcid) {
p_ccb->remote_id = id;
l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, &con_info);
@@ -706,22 +649,22 @@
l2cu_send_peer_disc_rsp(p_lcb, id, lcid, rcid);
break;
+ }
- case L2CAP_CMD_DISC_RSP:
- if (p + 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ case L2CAP_CMD_DISC_RSP: {
+ uint16_t lcid, rcid;
+ if (p + 4 > p_next_cmd) return;
STREAM_TO_UINT16(rcid, p);
STREAM_TO_UINT16(lcid, p);
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
- if (p_ccb != NULL) {
+ tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
+ if (p_ccb) {
if ((p_ccb->remote_cid == rcid) && (p_ccb->local_id == id)) {
l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_RSP, &con_info);
}
}
break;
+ }
case L2CAP_CMD_ECHO_REQ:
l2cu_send_peer_echo_rsp(p_lcb, id, p, cmd_len);
@@ -738,14 +681,13 @@
}
break;
- case L2CAP_CMD_INFO_REQ:
- if (p + 2 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ case L2CAP_CMD_INFO_REQ: {
+ uint16_t info_type;
+ if (p + 2 > p_next_cmd) return;
STREAM_TO_UINT16(info_type, p);
l2cu_send_peer_info_rsp(p_lcb, id, info_type);
break;
+ }
case L2CAP_CMD_INFO_RSP:
/* Stop the link connect timer if sent before L2CAP connection is up */
@@ -754,10 +696,8 @@
p_lcb->w4_info_rsp = false;
}
- if (p + 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ uint16_t info_type, result;
+ if (p + 4 > p_next_cmd) return;
STREAM_TO_UINT16(info_type, p);
STREAM_TO_UINT16(result, p);
@@ -765,10 +705,7 @@
if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
(result == L2CAP_INFO_RESP_RESULT_SUCCESS)) {
- if (p + 4 > p_next_cmd) {
- android_errorWriteLog(0x534e4554, "74202041");
- return;
- }
+ if (p + 4 > p_next_cmd) return;
STREAM_TO_UINT32(p_lcb->peer_ext_fea, p);
#if (L2CAP_NUM_FIXED_CHNLS > 0)
@@ -790,17 +727,10 @@
l2cu_process_fixed_chnl_resp(p_lcb);
}
#endif
-#if (L2CAP_UCD_INCLUDED == TRUE)
- else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
- if (result == L2CAP_INFO_RESP_RESULT_SUCCESS) {
- STREAM_TO_UINT16(p_lcb->ucd_mtu, p);
- }
- }
-#endif
-
+ tL2C_CONN_INFO ci;
ci.status = HCI_SUCCESS;
ci.bd_addr = p_lcb->remote_bd_addr;
- for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
+ for (tL2C_CCB* p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
p_ccb = p_ccb->p_next_ccb) {
l2c_csm_execute(p_ccb, L2CEVT_L2CAP_INFO_RSP, &ci);
}
@@ -872,6 +802,9 @@
/* the psm is increased by 2 before being used */
l2cb.dyn_psm = 0xFFF;
+ /* the LE PSM is increased by 1 before being used */
+ l2cb.le_dyn_psm = LE_DYNAMIC_PSM_START - 1;
+
/* Put all the channel control blocks on the free queue */
for (xx = 0; xx < MAX_L2CAP_CHANNELS - 1; xx++) {
l2cb.ccb_pool[xx].p_next_ccb = &l2cb.ccb_pool[xx + 1];
@@ -961,19 +894,18 @@
*
******************************************************************************/
uint8_t l2c_data_write(uint16_t cid, BT_HDR* p_data, uint16_t flags) {
- tL2C_CCB* p_ccb;
/* Find the channel control block. We don't know the link it is on. */
- p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
- if (p_ccb == NULL) {
+ tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
+ if (!p_ccb) {
L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_DataWrite, CID: %d", cid);
osi_free(p_data);
return (L2CAP_DW_FAILED);
}
-#ifndef TESTER /* Tester may send any amount of data. otherwise sending \
- message \
- bigger than mtu size of peer is a violation of protocol */
+#ifndef TESTER
+ /* Tester may send any amount of data. otherwise sending message bigger than
+ * mtu size of peer is a violation of protocol */
uint16_t mtu;
if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
diff --git a/stack/l2cap/l2c_ucd.cc b/stack/l2cap/l2c_ucd.cc
deleted file mode 100644
index 2216368..0000000
--- a/stack/l2cap/l2c_ucd.cc
+++ /dev/null
@@ -1,1110 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 1999-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * This file contains the L2CAP UCD code
- *
- ******************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "bt_common.h"
-#include "bt_types.h"
-#include "btm_api.h"
-#include "btm_int.h"
-#include "btu.h"
-#include "hcidefs.h"
-#include "hcimsgs.h"
-#include "l2c_int.h"
-#include "l2cdefs.h"
-
-#if (L2CAP_UCD_INCLUDED == TRUE)
-
-static bool l2c_ucd_connect(const RawAddress& rem_bda);
-
-/*******************************************************************************
- *
- * Function l2c_ucd_discover_cback
- *
- * Description UCD Discover callback
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_discover_cback(const RawAddress& rem_bda, uint8_t info_type,
- uint32_t data) {
- tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
- uint16_t xx;
-
- L2CAP_TRACE_DEBUG("L2CAP - l2c_ucd_discover_cback");
-
- for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
- if (p_rcb->in_use) {
- /* if this application is waiting UCD reception info */
- if ((info_type == L2CAP_UCD_INFO_TYPE_RECEPTION) &&
- (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION)) {
- p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(rem_bda, info_type, data);
- p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_RECEPTION);
- }
-
- /* if this application is waiting UCD MTU info */
- if ((info_type == L2CAP_UCD_INFO_TYPE_MTU) &&
- (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU)) {
- p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(rem_bda, info_type, data);
- p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_MTU);
- }
- }
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_data_ind_cback
- *
- * Description UCD Data callback
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_data_ind_cback(const RawAddress& rem_bda, BT_HDR* p_buf) {
- uint8_t* p;
- uint16_t psm;
- tL2C_RCB* p_rcb;
-
- L2CAP_TRACE_DEBUG("L2CAP - l2c_ucd_data_ind_cback");
-
- p = (uint8_t*)(p_buf + 1) + p_buf->offset;
- STREAM_TO_UINT16(psm, p)
-
- p_buf->offset += L2CAP_UCD_OVERHEAD;
- p_buf->len -= L2CAP_UCD_OVERHEAD;
-
- p_rcb = l2cu_find_rcb_by_psm(psm);
- if (p_rcb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - no RCB for l2c_ucd_data_ind_cback, PSM: 0x%04x",
- psm);
- osi_free(p_buf);
- } else {
- p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(rem_bda, p_buf);
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_congestion_status_cback
- *
- * Description UCD Congestion Status callback
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_congestion_status_cback(const RawAddress& rem_bda,
- bool is_congested) {
- tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
- uint16_t xx;
-
- L2CAP_TRACE_DEBUG("L2CAP - l2c_ucd_congestion_status_cback");
-
- for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
- if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED)) {
- if (p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
- L2CAP_TRACE_DEBUG(
- "L2CAP - Calling UCDCongestionStatus_Cb (%d), PSM=0x%04x, BDA: "
- "%08x%04x,",
- is_congested, p_rcb->psm, (rem_bda[0] << 24) + (rem_bda[1] << 16) +
- (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(rem_bda,
- is_congested);
- }
- }
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_disconnect_ind_cback
- *
- * Description UCD disconnect callback (Prevent to access null pointer)
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_disconnect_ind_cback(uint16_t cid, bool result) {
- /* do nothing */
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_config_ind_cback
- *
- * Description UCD config callback (This prevent to access null pointer)
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_config_ind_cback(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
- /* do nothing */
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_config_cfm_cback
- *
- * Description UCD config callback (This prevent to access null pointer)
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_config_cfm_cback(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
- /* do nothing */
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdRegister
- *
- * Description Register PSM on UCD.
- *
- * Parameters: tL2CAP_UCD_CB_INFO
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-bool L2CA_UcdRegister(uint16_t psm, tL2CAP_UCD_CB_INFO* p_cb_info) {
- tL2C_RCB* p_rcb;
-
- L2CAP_TRACE_API("L2CA_UcdRegister() PSM: 0x%04x", psm);
-
- if ((!p_cb_info->pL2CA_UCD_Discover_Cb) || (!p_cb_info->pL2CA_UCD_Data_Cb)) {
- L2CAP_TRACE_ERROR("L2CAP - no callback registering PSM(0x%04x) on UCD",
- psm);
- return (false);
- }
-
- p_rcb = l2cu_find_rcb_by_psm(psm);
- if (p_rcb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - no RCB for L2CA_UcdRegister, PSM: 0x%04x", psm);
- return (false);
- }
-
- p_rcb->ucd.state = L2C_UCD_STATE_W4_DATA;
- p_rcb->ucd.cb_info = *p_cb_info;
-
- /* check if master rcb is created for UCD */
- p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID);
- if (p_rcb == NULL) {
- p_rcb = l2cu_allocate_rcb(L2C_UCD_RCB_ID);
- if (p_rcb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - no RCB available for L2CA_UcdRegister");
- return (false);
- } else {
- /* these callback functions will forward data to each UCD application */
- p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb = l2c_ucd_discover_cback;
- p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb = l2c_ucd_data_ind_cback;
- p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb =
- l2c_ucd_congestion_status_cback;
-
- memset(&p_rcb->api, 0, sizeof(tL2CAP_APPL_INFO));
- p_rcb->api.pL2CA_DisconnectInd_Cb = l2c_ucd_disconnect_ind_cback;
-
- /* This will make L2CAP check UCD congestion callback */
- p_rcb->api.pL2CA_CongestionStatus_Cb = NULL;
-
- /* do nothing but prevent crash */
- p_rcb->api.pL2CA_ConfigInd_Cb = l2c_ucd_config_ind_cback;
- p_rcb->api.pL2CA_ConfigCfm_Cb = l2c_ucd_config_cfm_cback;
- }
- }
-
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdDeregister
- *
- * Description Deregister PSM on UCD.
- *
- * Parameters: PSM
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-bool L2CA_UcdDeregister(uint16_t psm) {
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
- uint16_t xx;
-
- L2CAP_TRACE_API("L2CA_UcdDeregister() PSM: 0x%04x", psm);
-
- p_rcb = l2cu_find_rcb_by_psm(psm);
- if (p_rcb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - no RCB for L2CA_UcdDeregister, PSM: 0x%04x",
- psm);
- return (false);
- }
-
- p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
-
- /* check this was the last UCD registration */
- p_rcb = &l2cb.rcb_pool[0];
-
- for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
- if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED))
- return (true);
- }
-
- /* delete master rcb for UCD */
- p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID);
- if (p_rcb != NULL) {
- l2cu_release_rcb(p_rcb);
- }
-
- /* delete CCB for UCD */
- p_ccb = l2cb.ccb_pool;
- for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++) {
- if ((p_ccb->in_use) && (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)) {
- l2cu_release_ccb(p_ccb);
- }
- p_ccb++;
- }
-
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdDiscover
- *
- * Description Discover UCD of remote device.
- *
- * Parameters: PSM
- * BD_ADDR of remote device
- * info_type : L2CAP_UCD_INFO_TYPE_RECEPTION
- * L2CAP_UCD_INFO_TYPE_MTU
- *
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-bool L2CA_UcdDiscover(uint16_t psm, const RawAddress& rem_bda,
- uint8_t info_type) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
-
- L2CAP_TRACE_API(
- "L2CA_UcdDiscover() PSM: 0x%04x BDA: %08x%04x, InfoType=0x%02x", psm,
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5], info_type);
-
- /* Fail if the PSM is not registered */
- if (((p_rcb = l2cu_find_rcb_by_psm(psm)) == NULL) ||
- (p_rcb->ucd.state == L2C_UCD_STATE_UNUSED)) {
- L2CAP_TRACE_WARNING("L2CAP - no RCB for L2CA_UcdDiscover, PSM: 0x%04x",
- psm);
- return (false);
- }
-
- /* First, see if we already have a link to the remote */
- /* then find the channel control block for UCD. */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
- NULL)) {
- if (l2c_ucd_connect(rem_bda) == false) {
- return (false);
- }
- }
-
- /* set waiting flags in rcb */
-
- if (info_type & L2CAP_UCD_INFO_TYPE_RECEPTION)
- p_rcb->ucd.state |= L2C_UCD_STATE_W4_RECEPTION;
-
- if (info_type & L2CAP_UCD_INFO_TYPE_MTU)
- p_rcb->ucd.state |= L2C_UCD_STATE_W4_MTU;
-
- /* if link is already established */
- if ((p_lcb) && (p_lcb->link_state == LST_CONNECTED)) {
- if (!p_ccb) {
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID);
- }
- l2c_ucd_check_pending_info_req(p_ccb);
- }
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdDataWrite
- *
- * Description Send UCD to remote device
- *
- * Parameters: PSM
- * BD Address of remote
- * Pointer to buffer of type BT_HDR
- * flags : L2CAP_FLUSHABLE_CH_BASED
- * L2CAP_FLUSHABLE_PKT
- * L2CAP_NON_FLUSHABLE_PKT
- *
- * Return value L2CAP_DW_SUCCESS, if data accepted
- * L2CAP_DW_FAILED, if error
- *
- ******************************************************************************/
-uint16_t L2CA_UcdDataWrite(uint16_t psm, const RawAddress& rem_bda,
- BT_HDR* p_buf, uint16_t flags) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
- uint8_t* p;
-
- L2CAP_TRACE_API(
- "L2CA_UcdDataWrite() PSM: 0x%04x BDA: %08x%04x", psm,
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- /* Fail if the PSM is not registered */
- if (((p_rcb = l2cu_find_rcb_by_psm(psm)) == NULL) ||
- (p_rcb->ucd.state == L2C_UCD_STATE_UNUSED)) {
- L2CAP_TRACE_WARNING("L2CAP - no RCB for L2CA_UcdDataWrite, PSM: 0x%04x",
- psm);
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
-
- /* First, see if we already have a link to the remote */
- /* then find the channel control block for UCD */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
- NULL)) {
- if (l2c_ucd_connect(rem_bda) == false) {
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
-
- /* If we still don't have lcb and ccb after connect attempt, then can't
- * proceed */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
- NULL)) {
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
- }
-
- /* write PSM */
- p_buf->offset -= L2CAP_UCD_OVERHEAD;
- p_buf->len += L2CAP_UCD_OVERHEAD;
- p = (uint8_t*)(p_buf + 1) + p_buf->offset;
-
- UINT16_TO_STREAM(p, psm);
-
- /* UCD MTU check */
- if ((p_lcb->ucd_mtu) && (p_buf->len > p_lcb->ucd_mtu)) {
- L2CAP_TRACE_WARNING(
- "L2CAP - Handle: 0x%04x UCD bigger than peer's UCD mtu size cannot be "
- "sent",
- p_lcb->handle);
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
-
- /* If already congested, do not accept any more packets */
- if (p_ccb->cong_sent) {
- L2CAP_TRACE_ERROR(
- "L2CAP - Handle: 0x%04x UCD cannot be sent, already congested count: "
- "%u buff_quota: %u",
- p_lcb->handle, (fixed_queue_length(p_ccb->xmit_hold_q) +
- fixed_queue_length(p_lcb->ucd_out_sec_pending_q)),
- p_ccb->buff_quota);
-
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
-
- /* channel based, packet based flushable or non-flushable */
- p_buf->layer_specific = flags;
-
- l2c_csm_execute(p_ccb, L2CEVT_L2CA_DATA_WRITE, p_buf);
-
- if (p_ccb->cong_sent)
- return (L2CAP_DW_CONGESTED);
- else
- return (L2CAP_DW_SUCCESS);
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdSetIdleTimeout
- *
- * Description Set UCD Idle timeout.
- *
- * Parameters: BD Addr
- * Timeout in second
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-bool L2CA_UcdSetIdleTimeout(const RawAddress& rem_bda, uint16_t timeout) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
-
- L2CAP_TRACE_API(
- "L2CA_UcdSetIdleTimeout() Timeout: 0x%04x BDA: %08x%04x", timeout,
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- /* First, see if we already have a link to the remote */
- /* then find the channel control block. */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
- NULL)) {
- L2CAP_TRACE_WARNING("L2CAP - no UCD channel");
- return (false);
- } else {
- p_ccb->fixed_chnl_idle_tout = timeout;
- return (true);
- }
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UCDSetTxPriority
- *
- * Description Sets the transmission priority for a connectionless channel.
- *
- * Returns true if a valid channel, else false
- *
- ******************************************************************************/
-bool L2CA_UCDSetTxPriority(const RawAddress& rem_bda,
- tL2CAP_CHNL_PRIORITY priority) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
-
- L2CAP_TRACE_API(
- "L2CA_UCDSetTxPriority() priority: 0x%02x BDA: %08x%04x", priority,
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR);
- if (p_lcb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_UCDSetTxPriority");
- return (false);
- }
-
- /* Find the channel control block */
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID);
- if (p_ccb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_UCDSetTxPriority");
- return (false);
- }
-
- /* it will update the order of CCB in LCB by priority and update round robin
- * service variables */
- l2cu_change_pri_ccb(p_ccb, priority);
-
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_connect
- *
- * Description Connect UCD to remote device.
- *
- * Parameters: BD_ADDR of remote device
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-static bool l2c_ucd_connect(const RawAddress& rem_bda) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
-
- L2CAP_TRACE_DEBUG(
- "l2c_ucd_connect() BDA: %08x%04x",
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- /* Fail if we have not established communications with the controller */
- if (!BTM_IsDeviceUp()) {
- L2CAP_TRACE_WARNING("l2c_ucd_connect - BTU not ready");
- return (false);
- }
-
- /* First, see if we already have a link to the remote */
- p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR);
- if (p_lcb == NULL) {
- /* No link. Get an LCB and start link establishment */
- if (((p_lcb = l2cu_allocate_lcb(rem_bda, false, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == false)) {
- L2CAP_TRACE_WARNING("L2CAP - conn not started l2c_ucd_connect");
- return (false);
- }
- } else if (p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE)) {
- if (!(p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) {
- L2CAP_TRACE_WARNING(
- "L2CAP - UCD is not supported by peer, l2c_ucd_connect");
- return (false);
- }
- }
-
- /* Find the channel control block. */
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID);
- if (p_ccb == NULL) {
- /* Allocate a channel control block */
- p_ccb = l2cu_allocate_ccb(p_lcb, 0);
- if (p_ccb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no CCB for l2c_ucd_connect");
- return (false);
- } else {
- /* Set CID for the connection */
- p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
- p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
-
- /* Set the default idle timeout value to use */
- p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
-
- /* Set the default channel priority value to use */
- l2cu_change_pri_ccb(p_ccb, L2CAP_UCD_CH_PRIORITY);
-
- p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID);
- if (p_rcb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no UCD registered, l2c_ucd_connect");
- return (false);
- }
- /* Save UCD registration info */
- p_ccb->p_rcb = p_rcb;
-
- /* There is no configuration, so if the link is up, the channel is up */
- if (p_lcb->link_state == LST_CONNECTED) {
- p_ccb->chnl_state = CST_OPEN;
- }
- }
- }
-
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_delete_sec_pending_q
- *
- * Description discard all of UCD packets in security pending queue
- *
- * Returns None
- *
- ******************************************************************************/
-void l2c_ucd_delete_sec_pending_q(tL2C_LCB* p_lcb) {
- /* clean up any security pending UCD */
- while (!fixed_queue_is_empty(p_lcb->ucd_out_sec_pending_q))
- osi_free(fixed_queue_try_dequeue(p_lcb->ucd_out_sec_pending_q));
- fixed_queue_free(p_lcb->ucd_out_sec_pending_q, NULL);
- p_lcb->ucd_out_sec_pending_q = NULL;
-
- while (!fixed_queue_is_empty(p_lcb->ucd_in_sec_pending_q))
- osi_free(fixed_queue_try_dequeue(p_lcb->ucd_in_sec_pending_q));
- fixed_queue_free(p_lcb->ucd_in_sec_pending_q);
- p_lcb->ucd_in_sec_pending_q = NULL;
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_check_pending_info_req
- *
- * Description check if any application is waiting for UCD information
- *
- * Return true if any pending UCD info request
- *
- ******************************************************************************/
-bool l2c_ucd_check_pending_info_req(tL2C_CCB* p_ccb) {
- tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
- uint16_t xx;
- bool pending = false;
-
- if (p_ccb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - NULL p_ccb in l2c_ucd_check_pending_info_req");
- return (false);
- }
-
- for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
- if (p_rcb->in_use) {
- /* if application is waiting UCD reception info */
- if (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION) {
- /* if this information is available */
- if (p_ccb->p_lcb->info_rx_bits &
- (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE)) {
- if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) {
- L2CAP_TRACE_WARNING(
- "L2CAP - UCD is not supported by peer, "
- "l2c_ucd_check_pending_info_req");
-
- l2c_ucd_delete_sec_pending_q(p_ccb->p_lcb);
- l2cu_release_ccb(p_ccb);
- }
-
- p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(
- p_ccb->p_lcb->remote_bd_addr, L2CAP_UCD_INFO_TYPE_RECEPTION,
- p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION);
- } else {
- pending = true;
- if (p_ccb->p_lcb->w4_info_rsp == false) {
- l2cu_send_peer_info_req(p_ccb->p_lcb,
- L2CAP_EXTENDED_FEATURES_INFO_TYPE);
- }
- }
- }
-
- /* if application is waiting for UCD MTU */
- if (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU) {
- /* if this information is available */
- if (p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_CONNLESS_MTU_INFO_TYPE)) {
- p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(
- p_ccb->p_lcb->remote_bd_addr, L2CAP_UCD_INFO_TYPE_MTU,
- p_ccb->p_lcb->ucd_mtu);
- } else {
- pending = true;
- if (p_ccb->p_lcb->w4_info_rsp == false) {
- l2cu_send_peer_info_req(p_ccb->p_lcb, L2CAP_CONNLESS_MTU_INFO_TYPE);
- }
- }
- }
- }
- }
- return (pending);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_enqueue_pending_out_sec_q
- *
- * Description enqueue outgoing UCD packet into security pending queue
- * and check congestion
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB* p_ccb, void* p_data) {
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_out_sec_pending_q, p_data);
- l2cu_check_channel_congestion(p_ccb);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_check_pending_out_sec_q
- *
- * Description check outgoing security
- *
- * Return true if any UCD packet for security
- *
- ******************************************************************************/
-bool l2c_ucd_check_pending_out_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_peek_first(p_ccb->p_lcb->ucd_out_sec_pending_q);
-
- if (p_buf != NULL) {
- uint16_t psm;
- uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
-
- STREAM_TO_UINT16(psm, p)
-
- p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
- btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, psm,
- p_ccb->p_lcb->handle, CONNLESS_ORIG,
- &l2c_link_sec_comp, p_ccb);
-
- return (true);
- }
- return (false);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_send_pending_out_sec_q
- *
- * Description dequeue UCD packet from security pending queue and
- * enqueue it into CCB
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_send_pending_out_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
-
- if (p_buf != NULL) {
- l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_buf);
- l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_discard_pending_out_sec_q
- *
- * Description dequeue UCD packet from security pending queue and
- * discard it.
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
-
- /* we may need to report to application */
- osi_free(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_check_pending_in_sec_q
- *
- * Description check incoming security
- *
- * Return true if any UCD packet for security
- *
- ******************************************************************************/
-bool l2c_ucd_check_pending_in_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
-
- if (p_buf != NULL) {
- uint16_t psm;
- uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
- STREAM_TO_UINT16(psm, p)
-
- p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
- btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, psm,
- p_ccb->p_lcb->handle, CONNLESS_TERM,
- &l2c_link_sec_comp, p_ccb);
-
- return (true);
- }
- return (false);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_send_pending_in_sec_q
- *
- * Description dequeue UCD packet from security pending queue and
- * send it to application
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_send_pending_in_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q)
-
- if (p_buf != NULL) {
- p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(p_ccb->p_lcb->remote_bd_addr,
- (BT_HDR*)p_buf);
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_discard_pending_in_sec_q
- *
- * Description dequeue UCD packet from security pending queue and
- * discard it.
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_discard_pending_in_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
- osi_free(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_check_rx_pkts
- *
- * Description Check if UCD reception is registered.
- * Process received UCD packet if application is expecting.
- *
- * Return true if UCD reception is registered
- *
- ******************************************************************************/
-bool l2c_ucd_check_rx_pkts(tL2C_LCB* p_lcb, BT_HDR* p_msg) {
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
-
- if (((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) !=
- NULL) ||
- ((p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID)) != NULL)) {
- if (p_ccb == NULL) {
- /* Allocate a channel control block */
- p_ccb = l2cu_allocate_ccb(p_lcb, 0);
- if (p_ccb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no CCB for UCD reception");
- osi_free(p_msg);
- return true;
- } else {
- /* Set CID for the connection */
- p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
- p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
-
- /* Set the default idle timeout value to use */
- p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
-
- /* Set the default channel priority value to use */
- l2cu_change_pri_ccb(p_ccb, L2CAP_UCD_CH_PRIORITY);
-
- /* Save registration info */
- p_ccb->p_rcb = p_rcb;
-
- p_ccb->chnl_state = CST_OPEN;
- }
- }
- l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);
- return true;
- } else
- return false;
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_process_event
- *
- * Description This is called from main state machine when LCID is
- * connectionless. Process the event if it is for UCD.
- *
- * Return true if the event is consumed by UCD
- * false if the event needs to be processed by the main state
- * machine
- *
- ******************************************************************************/
-bool l2c_ucd_process_event(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
- /* if the event is not processed by this function, this variable will be set
- * to false */
- bool done = true;
-
- switch (p_ccb->chnl_state) {
- case CST_CLOSED:
- switch (event) {
- case L2CEVT_LP_CONNECT_CFM: /* Link came up */
- /* check if waiting for UCD info */
- if (!l2c_ucd_check_pending_info_req(p_ccb)) {
- /* check if any outgoing UCD packet is waiting security check */
- if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
- p_ccb->chnl_state = CST_OPEN;
- }
- }
- break;
-
- case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
- break;
-
- case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
- l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
- break;
-
- case L2CEVT_L2CAP_INFO_RSP:
- /* check if waiting for UCD info */
- if (!l2c_ucd_check_pending_info_req(p_ccb)) {
- /* check if any outgoing UCD packet is waiting security check */
- if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
- p_ccb->chnl_state = CST_OPEN;
- }
- }
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
- break;
-
- case CST_ORIG_W4_SEC_COMP:
- switch (event) {
- case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
- /* check if any outgoing UCD packet is waiting security check */
- if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
- p_ccb->chnl_state = CST_OPEN;
- }
- break;
-
- case L2CEVT_SEC_COMP: /* Security completed success */
- p_ccb->chnl_state = CST_OPEN;
- l2c_ucd_send_pending_out_sec_q(p_ccb);
-
- if (!fixed_queue_is_empty(p_ccb->p_lcb->ucd_out_sec_pending_q)) {
- /* start a timer to send next UCD packet in OPEN state */
- /* it will prevent stack overflow */
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 0, l2c_ccb_timer_timeout,
- p_ccb);
- } else {
- /* start a timer for idle timeout of UCD */
- period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, timeout_ms,
- l2c_ccb_timer_timeout, p_ccb);
- }
- break;
-
- case L2CEVT_SEC_COMP_NEG:
- p_ccb->chnl_state = CST_OPEN;
- l2c_ucd_discard_pending_out_sec_q(p_ccb);
-
- /* start a timer for idle timeout of UCD */
- period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, timeout_ms,
- l2c_ccb_timer_timeout, p_ccb);
- break;
-
- case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
- l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
- break;
-
- case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
- break;
-
- case L2CEVT_L2CAP_INFO_RSP:
- /* check if waiting for UCD info */
- l2c_ucd_check_pending_info_req(p_ccb);
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
- break;
-
- case CST_TERM_W4_SEC_COMP:
- switch (event) {
- case L2CEVT_SEC_COMP:
- p_ccb->chnl_state = CST_OPEN;
- l2c_ucd_send_pending_in_sec_q(p_ccb);
-
- if (!fixed_queue_is_empty(p_ccb->p_lcb->ucd_in_sec_pending_q)) {
- /* start a timer to check next UCD packet in OPEN state */
- /* it will prevent stack overflow */
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 0, l2c_ccb_timer_timeout,
- p_ccb);
- } else {
- /* start a timer for idle timeout of UCD */
- period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, timeout_ms,
- l2c_ccb_timer_timeout, p_ccb);
- }
- break;
-
- case L2CEVT_SEC_COMP_NEG:
- if (((tL2C_CONN_INFO*)p_data)->status == BTM_DELAY_CHECK) {
- done = false;
- break;
- }
- p_ccb->chnl_state = CST_OPEN;
- l2c_ucd_discard_pending_in_sec_q(p_ccb);
-
- /* start a timer for idle timeout of UCD */
- period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, timeout_ms,
- l2c_ccb_timer_timeout, p_ccb);
- break;
-
- case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
- l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
- break;
-
- case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
- break;
-
- case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
- /* check if any incoming UCD packet is waiting security check */
- if (!l2c_ucd_check_pending_in_sec_q(p_ccb)) {
- p_ccb->chnl_state = CST_OPEN;
- }
- break;
-
- case L2CEVT_L2CAP_INFO_RSP:
- /* check if waiting for UCD info */
- l2c_ucd_check_pending_info_req(p_ccb);
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
- break;
-
- case CST_OPEN:
- switch (event) {
- case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
- /* stop idle timer of UCD */
- alarm_cancel(p_ccb->l2c_ccb_timer);
-
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
- l2c_ucd_check_pending_in_sec_q(p_ccb);
- break;
-
- case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
- /* stop idle timer of UCD */
- alarm_cancel(p_ccb->l2c_ccb_timer);
-
- l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
-
- /* success changes state, failure stays in current state */
- l2c_ucd_check_pending_out_sec_q(p_ccb);
- break;
-
- case L2CEVT_TIMEOUT:
- /* check if any UCD packet is waiting security check */
- if ((!l2c_ucd_check_pending_in_sec_q(p_ccb)) &&
- (!l2c_ucd_check_pending_out_sec_q(p_ccb))) {
- l2cu_release_ccb(p_ccb);
- }
- break;
-
- case L2CEVT_L2CAP_INFO_RSP:
- /* check if waiting for UCD info */
- l2c_ucd_check_pending_info_req(p_ccb);
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
-
- return done;
-}
-#endif /* (L2CAP_UCD_INCLUDED == TRUE) */
diff --git a/stack/l2cap/l2c_utils.cc b/stack/l2cap/l2c_utils.cc
index f07f4e3..337e076 100644
--- a/stack/l2cap/l2c_utils.cc
+++ b/stack/l2cap/l2c_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -98,10 +98,6 @@
l2cb.num_links_active++;
l2c_link_adjust_allocation();
}
-#if (L2CAP_UCD_INCLUDED == TRUE)
- p_lcb->ucd_out_sec_pending_q = fixed_queue_new(SIZE_MAX);
- p_lcb->ucd_in_sec_pending_q = fixed_queue_new(SIZE_MAX);
-#endif
p_lcb->link_xmit_data_q = list_new(NULL);
return (p_lcb);
}
@@ -176,7 +172,8 @@
}
// Reset BLE connecting flag only if the address matches
- if (l2cb.ble_connecting_bda == p_lcb->remote_bd_addr)
+ if (p_lcb->transport == BT_TRANSPORT_LE &&
+ l2cb.ble_connecting_bda == p_lcb->remote_bd_addr)
l2cb.is_ble_connecting = false;
#if (L2CAP_NUM_FIXED_CHNLS > 0)
@@ -205,11 +202,6 @@
p_lcb->link_xmit_data_q = NULL;
}
-#if (L2CAP_UCD_INCLUDED == TRUE)
- /* clean up any security pending UCD */
- l2c_ucd_delete_sec_pending_q(p_lcb);
-#endif
-
/* Re-adjust flow control windows make sure it does not go negative */
if (p_lcb->transport == BT_TRANSPORT_LE) {
if (l2cb.num_ble_links_active >= 1) l2cb.num_ble_links_active--;
@@ -1162,7 +1154,7 @@
#endif
} else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
- UINT16_TO_STREAM(p, L2CAP_UCD_MTU);
+ UINT16_TO_STREAM(p, L2CAP_MTU_SIZE);
} else {
UINT16_TO_STREAM(
p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */
@@ -1190,9 +1182,8 @@
if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue;
if ((!p_ccb->in_use) || (p_q == NULL)) {
- L2CAP_TRACE_ERROR(
- "l2cu_enqueue_ccb CID: 0x%04x ERROR in_use: %u p_lcb: 0x%08x",
- p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
+ L2CAP_TRACE_ERROR("%s: CID: 0x%04x ERROR in_use: %u p_lcb: %p", __func__,
+ p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
return;
}
@@ -1604,11 +1595,7 @@
l2c_fcr_cleanup(p_ccb);
/* Channel may not be assigned to any LCB if it was just pre-reserved */
- if ((p_lcb) && ((p_ccb->local_cid >= L2CAP_BASE_APPL_CID)
-#if (L2CAP_UCD_INCLUDED == TRUE)
- || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)
-#endif
- )) {
+ if ((p_lcb) && ((p_ccb->local_cid >= L2CAP_BASE_APPL_CID))) {
l2cu_dequeue_ccb(p_ccb);
/* Delink the CCB from the LCB */
@@ -1691,9 +1678,6 @@
if (!p_rcb->in_use) {
p_rcb->in_use = true;
p_rcb->psm = psm;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
-#endif
return (p_rcb);
}
}
@@ -1720,9 +1704,6 @@
if (!p_rcb->in_use) {
p_rcb->in_use = true;
p_rcb->psm = psm;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
-#endif
return (p_rcb);
}
}
@@ -1747,6 +1728,21 @@
/*******************************************************************************
*
+ * Function l2cu_release_ble_rcb
+ *
+ * Description Mark an LE RCB as no longer in use
+ *
+ * Returns void
+ *
+ ******************************************************************************/
+void l2cu_release_ble_rcb(tL2C_RCB* p_rcb) {
+ L2CA_FreeLePSM(p_rcb->psm);
+ p_rcb->in_use = false;
+ p_rcb->psm = 0;
+}
+
+/*******************************************************************************
+ *
* Function l2cu_disconnect_chnl
*
* Description Disconnect a channel. Typically, this is due to either
@@ -1854,7 +1850,7 @@
/* Make sure MTU is at least the minimum */
if (p_cfg->mtu >= L2CAP_MIN_MTU) {
/* In basic mode, limit the MTU to our buffer size */
- if ((p_cfg->fcr_present == false) && (p_cfg->mtu > L2CAP_MTU_SIZE))
+ if ((!p_cfg->fcr_present) && (p_cfg->mtu > L2CAP_MTU_SIZE))
p_cfg->mtu = L2CAP_MTU_SIZE;
/* Save the accepted value in case of renegotiation */
@@ -2158,9 +2154,9 @@
L2CAP_TRACE_API(
"l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s",
- (is_sco_active == true) ? "true" : "false");
+ (is_sco_active) ? "true" : "false");
- if (is_sco_active == true)
+ if (is_sco_active)
continue; /* No Master Slave switch not allowed when SCO Active */
#endif
/*4_1_TODO check if btm_cb.devcb.local_features to be used instead */
@@ -3060,10 +3056,6 @@
******************************************************************************/
tL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* p_lcb, uint16_t local_cid) {
tL2C_CCB* p_ccb = NULL;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- uint8_t xx;
-#endif
-
if (local_cid >= L2CAP_BASE_APPL_CID) {
/* find the associated CCB by "index" */
local_cid -= L2CAP_BASE_APPL_CID;
@@ -3081,21 +3073,6 @@
p_ccb = NULL;
}
}
-#if (L2CAP_UCD_INCLUDED == TRUE)
- else {
- /* searching fixed channel */
- p_ccb = l2cb.ccb_pool;
- for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++) {
- if ((p_ccb->local_cid == local_cid) && (p_ccb->in_use) &&
- (p_lcb == p_ccb->p_lcb))
- break;
- else
- p_ccb++;
- }
- if (xx >= MAX_L2CAP_CHANNELS) return NULL;
- }
-#endif
-
return (p_ccb);
}
@@ -3323,10 +3300,16 @@
L2CAP_TRACE_DEBUG("%s No credits to send packets", __func__);
return NULL;
}
- p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, 0);
- if (p_buf == NULL) return (NULL);
+ bool last_piece_of_sdu = false;
+ p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, &last_piece_of_sdu);
p_ccb->peer_conn_cfg.credits--;
+
+ if (last_piece_of_sdu) {
+ // TODO: send callback up the stack. Investigate setting p_cbi->cb to
+ // notify after controller ack send.
+ }
+
} else {
if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
@@ -3409,113 +3392,55 @@
p_buf->len += HCI_DATA_PREAMBLE_SIZE;
}
-/******************************************************************************
- *
- * Function l2cu_check_channel_congestion
- *
- * Description check if any change in congestion status
- *
- * Returns None
- *
- ******************************************************************************/
-void l2cu_check_channel_congestion(tL2C_CCB* p_ccb) {
- size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
+static void send_congestion_status_to_all_clients(tL2C_CCB* p_ccb,
+ bool status) {
+ p_ccb->cong_sent = status;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
- q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q);
+ if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
+ L2CAP_TRACE_DEBUG(
+ "L2CAP - Calling CongestionStatus_Cb (%d), CID: 0x%04x "
+ "xmit_hold_q.count: %u buff_quota: %u",
+ status, p_ccb->local_cid, fixed_queue_length(p_ccb->xmit_hold_q),
+ p_ccb->buff_quota);
+
+ /* Prevent recursive calling */
+ if (status == false) l2cb.is_cong_cback_context = true;
+
+ (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, status);
+
+ if (status == false) l2cb.is_cong_cback_context = false;
}
-#endif
- /* If the CCB queue limit is subject to a quota, check for congestion */
- /* if this channel has outgoing traffic */
- if (p_ccb->buff_quota != 0) {
- /* If this channel was congested */
- if (p_ccb->cong_sent) {
- /* If the channel is not congested now, tell the app */
- if (q_count <= (p_ccb->buff_quota / 2)) {
- p_ccb->cong_sent = false;
- if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
- L2CAP_TRACE_DEBUG(
- "L2CAP - Calling CongestionStatus_Cb (false), CID: 0x%04x "
- "xmit_hold_q.count: %u buff_quota: %u",
- p_ccb->local_cid, q_count, p_ccb->buff_quota);
-
- /* Prevent recursive calling */
- l2cb.is_cong_cback_context = true;
- (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid,
- false);
- l2cb.is_cong_cback_context = false;
- }
-#if (L2CAP_UCD_INCLUDED == TRUE)
- else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
- if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
- L2CAP_TRACE_DEBUG(
- "L2CAP - Calling UCD CongestionStatus_Cb (false), "
- "SecPendingQ:%u,XmitQ:%u,Quota:%u",
- fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
- fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota);
- p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(
- p_ccb->p_lcb->remote_bd_addr, false);
- }
- }
-#endif
#if (L2CAP_NUM_FIXED_CHNLS > 0)
- else {
- uint8_t xx;
- for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
- if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
- if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
- (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(
- p_ccb->p_lcb->remote_bd_addr, false);
- break;
- }
- }
- }
-#endif
- }
- } else {
- /* If this channel was not congested but it is congested now, tell the app
- */
- if (q_count > p_ccb->buff_quota) {
- p_ccb->cong_sent = true;
- if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
- L2CAP_TRACE_DEBUG(
- "L2CAP - Calling CongestionStatus_Cb "
- "(true),CID:0x%04x,XmitQ:%u,Quota:%u",
- p_ccb->local_cid, q_count, p_ccb->buff_quota);
-
- (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid,
- true);
- }
-#if (L2CAP_UCD_INCLUDED == TRUE)
- else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
- if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
- L2CAP_TRACE_DEBUG(
- "L2CAP - Calling UCD CongestionStatus_Cb (true), "
- "SecPendingQ:%u,XmitQ:%u,Quota:%u",
- fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
- fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota);
- p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(
- p_ccb->p_lcb->remote_bd_addr, true);
- }
- }
-#endif
-#if (L2CAP_NUM_FIXED_CHNLS > 0)
- else {
- uint8_t xx;
- for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
- if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
- if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
- (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(
- p_ccb->p_lcb->remote_bd_addr, true);
- break;
- }
- }
- }
-#endif
+ else {
+ for (uint8_t xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
+ if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
+ if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
+ (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr,
+ status);
+ break;
}
}
}
+#endif
+}
+
+/* check if any change in congestion status */
+void l2cu_check_channel_congestion(tL2C_CCB* p_ccb) {
+ /* If the CCB queue limit is subject to a quota, check for congestion if this
+ * channel has outgoing traffic */
+ if (p_ccb->buff_quota == 0) return;
+
+ size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
+
+ if (p_ccb->cong_sent) {
+ /* if channel was congested, but is not congested now, tell the app */
+ if (q_count <= (p_ccb->buff_quota / 2))
+ send_congestion_status_to_all_clients(p_ccb, false);
+ } else {
+ /* if channel was not congested, but is congested now, tell the app */
+ if (q_count > p_ccb->buff_quota)
+ send_congestion_status_to_all_clients(p_ccb, true);
+ }
}
/*******************************************************************************
diff --git a/stack/l2cap/l2cap_client.cc b/stack/l2cap/l2cap_client.cc
index 6ccf8c5..76e4138 100644
--- a/stack/l2cap/l2cap_client.cc
+++ b/stack/l2cap/l2cap_client.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/mcap/mca_api.cc b/stack/mcap/mca_api.cc
index 44ab256..578d53e 100644
--- a/stack/mcap/mca_api.cc
+++ b/stack/mcap/mca_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/mcap/mca_cact.cc b/stack/mcap/mca_cact.cc
index f0759ac..48d0c0a 100644
--- a/stack/mcap/mca_cact.cc
+++ b/stack/mcap/mca_cact.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/mcap/mca_csm.cc b/stack/mcap/mca_csm.cc
index 9ff1915..4b3a4a0 100644
--- a/stack/mcap/mca_csm.cc
+++ b/stack/mcap/mca_csm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/mcap/mca_dact.cc b/stack/mcap/mca_dact.cc
index d05f3cd..8ee3ac1 100644
--- a/stack/mcap/mca_dact.cc
+++ b/stack/mcap/mca_dact.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -111,7 +111,7 @@
*
******************************************************************************/
void mca_dcb_do_disconn(tMCA_DCB* p_dcb, UNUSED_ATTR tMCA_DCB_EVT* p_data) {
- if ((p_dcb->lcid == 0) || (L2CA_DisconnectReq(p_dcb->lcid) == false)) {
+ if ((p_dcb->lcid == 0) || (!L2CA_DisconnectReq(p_dcb->lcid))) {
tMCA_CLOSE close;
close.param = MCA_INT;
close.reason = L2CAP_DISC_OK;
diff --git a/stack/mcap/mca_dsm.cc b/stack/mcap/mca_dsm.cc
index 3494448..0d26931 100644
--- a/stack/mcap/mca_dsm.cc
+++ b/stack/mcap/mca_dsm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/mcap/mca_int.h b/stack/mcap/mca_int.h
index 55765fd..9ae5d57 100644
--- a/stack/mcap/mca_int.h
+++ b/stack/mcap/mca_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/mcap/mca_l2c.cc b/stack/mcap/mca_l2c.cc
index 78a17ae..e0540fa 100644
--- a/stack/mcap/mca_l2c.cc
+++ b/stack/mcap/mca_l2c.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,17 +33,19 @@
#include "osi/include/osi.h"
/* L2CAP callback function structure */
-const tL2CAP_APPL_INFO mca_l2c_int_appl = {NULL,
- mca_l2c_connect_cfm_cback,
- NULL,
- mca_l2c_config_ind_cback,
- mca_l2c_config_cfm_cback,
- mca_l2c_disconnect_ind_cback,
- mca_l2c_disconnect_cfm_cback,
- NULL,
- mca_l2c_data_ind_cback,
- mca_l2c_congestion_ind_cback,
- NULL};
+const tL2CAP_APPL_INFO mca_l2c_int_appl = {
+ NULL,
+ mca_l2c_connect_cfm_cback,
+ NULL,
+ mca_l2c_config_ind_cback,
+ mca_l2c_config_cfm_cback,
+ mca_l2c_disconnect_ind_cback,
+ mca_l2c_disconnect_cfm_cback,
+ NULL,
+ mca_l2c_data_ind_cback,
+ mca_l2c_congestion_ind_cback,
+ NULL,
+ NULL /* tL2CA_CREDITS_RECEIVED_CB */};
/* Control channel eL2CAP default options */
const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def = {
diff --git a/stack/mcap/mca_main.cc b/stack/mcap/mca_main.cc
index 1cc8e75..0185721 100644
--- a/stack/mcap/mca_main.cc
+++ b/stack/mcap/mca_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -444,17 +444,17 @@
p_buf->layer_specific = rej_rsp_code;
/* forward the request/response to state machine */
mca_ccb_event(p_ccb, event, (tMCA_CCB_EVT*)p_buf);
- } /* got a valid ccb */
- else
+ } else {
osi_free(p_buf);
- }
- /* else send event to dcb */
- else {
+ }
+ } else {
+ /* send event to dcb */
p_dcb = mca_dcb_by_hdl(p_tbl->cb_idx);
if (p_dcb != NULL) {
mca_dcb_event(p_dcb, MCA_DCB_TC_DATA_EVT, (tMCA_DCB_EVT*)p_buf);
- } else
+ } else {
osi_free(p_buf);
+ }
}
}
diff --git a/stack/pan/pan_api.cc b/stack/pan/pan_api.cc
index a36793c..ea7791b 100644
--- a/stack/pan/pan_api.cc
+++ b/stack/pan/pan_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,8 @@
#include "sdp_api.h"
#include "sdpdefs.h"
+using bluetooth::Uuid;
+
/*******************************************************************************
*
* Function PAN_Register
@@ -266,9 +268,6 @@
******************************************************************************/
tPAN_RESULT PAN_Connect(const RawAddress& rem_bda, uint8_t src_role,
uint8_t dst_role, uint16_t* handle) {
- tPAN_CONN* pcb;
- tBNEP_RESULT result;
- tBT_UUID src_uuid, dst_uuid;
uint32_t mx_chan_id;
/*
@@ -294,8 +293,9 @@
}
/* Check if connection exists for this remote device */
- pcb = pan_get_pcb_by_addr(rem_bda);
+ tPAN_CONN* pcb = pan_get_pcb_by_addr(rem_bda);
+ uint16_t src_uuid, dst_uuid;
/* If we are PANU for this role validate destination role */
if (src_role == PAN_ROLE_CLIENT) {
if ((pan_cb.num_conns > 1) || (pan_cb.num_conns && (!pcb))) {
@@ -310,15 +310,15 @@
return PAN_INVALID_SRC_ROLE;
}
- src_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
+ src_uuid = UUID_SERVCLASS_PANU;
if (dst_role == PAN_ROLE_CLIENT) {
- dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
+ dst_uuid = UUID_SERVCLASS_PANU;
} else if (dst_role == PAN_ROLE_GN_SERVER) {
- dst_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
+ dst_uuid = UUID_SERVCLASS_GN;
} else {
- dst_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
+ dst_uuid = UUID_SERVCLASS_NAP;
}
- mx_chan_id = dst_uuid.uu.uuid16;
+ mx_chan_id = dst_uuid;
}
/* If destination is PANU role validate source role */
else if (dst_role == PAN_ROLE_CLIENT) {
@@ -327,13 +327,13 @@
return PAN_INVALID_SRC_ROLE;
}
- dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
+ dst_uuid = UUID_SERVCLASS_PANU;
if (src_role == PAN_ROLE_GN_SERVER) {
- src_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
+ src_uuid = UUID_SERVCLASS_GN;
} else {
- src_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
+ src_uuid = UUID_SERVCLASS_NAP;
}
- mx_chan_id = src_uuid.uu.uuid16;
+ mx_chan_id = src_uuid;
}
/* The role combination is not valid */
else {
@@ -364,16 +364,14 @@
pcb->prv_src_uuid = pcb->src_uuid;
pcb->prv_dst_uuid = pcb->dst_uuid;
- pcb->src_uuid = src_uuid.uu.uuid16;
- pcb->dst_uuid = dst_uuid.uu.uuid16;
+ pcb->src_uuid = src_uuid;
+ pcb->dst_uuid = dst_uuid;
- src_uuid.len = 2;
- dst_uuid.len = 2;
-
- result = BNEP_Connect(rem_bda, &src_uuid, &dst_uuid, &(pcb->handle));
- if (result != BNEP_SUCCESS) {
+ tBNEP_RESULT ret = BNEP_Connect(rem_bda, Uuid::From16Bit(src_uuid),
+ Uuid::From16Bit(dst_uuid), &(pcb->handle));
+ if (ret != BNEP_SUCCESS) {
pan_release_pcb(pcb);
- return result;
+ return ret;
}
PAN_TRACE_DEBUG("PAN_Connect() current active role set to %d", src_role);
diff --git a/stack/pan/pan_int.h b/stack/pan/pan_int.h
index 27fe666..1f76628 100644
--- a/stack/pan/pan_int.h
+++ b/stack/pan/pan_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2001-2012 Broadcom Corporation
+ * Copyright 2001-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -98,7 +98,8 @@
/******************************************************************************/
extern void pan_register_with_bnep(void);
extern void pan_conn_ind_cb(uint16_t handle, const RawAddress& p_bda,
- tBT_UUID* remote_uuid, tBT_UUID* local_uuid,
+ const bluetooth::Uuid& remote_uuid,
+ const bluetooth::Uuid& local_uuid,
bool is_role_change);
extern void pan_connect_state_cb(uint16_t handle, const RawAddress& rem_bda,
tBNEP_RESULT result, bool is_role_change);
diff --git a/stack/pan/pan_main.cc b/stack/pan/pan_main.cc
index d7cd27b..21bd1c9 100644
--- a/stack/pan/pan_main.cc
+++ b/stack/pan/pan_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,11 +36,9 @@
#include "sdp_api.h"
#include "sdpdefs.h"
-tPAN_CB pan_cb;
+using bluetooth::Uuid;
-#define UUID_CONSTANT_PART 12
-uint8_t constant_pan_uuid[UUID_CONSTANT_PART] = {
- 0, 0, 0x10, 0, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+tPAN_CB pan_cb;
/*******************************************************************************
*
@@ -90,127 +88,62 @@
*
******************************************************************************/
void pan_conn_ind_cb(uint16_t handle, const RawAddress& p_bda,
- tBT_UUID* remote_uuid, tBT_UUID* local_uuid,
+ const Uuid& remote_uuid, const Uuid& local_uuid,
bool is_role_change) {
- tPAN_CONN* pcb;
- uint8_t req_role;
- bool wrong_uuid;
+ /* If we are in GN or NAP role and have one or more active connections and the
+ * received connection is for user role reject it. If we are in user role with
+ * one connection active reject the connection. Allocate PCB and store the
+ * parameters. Make bridge request to the host system if connection is for NAP
+ */
- /*
- ** If we are in GN or NAP role and have one or more
- ** active connections and the received connection is
- ** for user role reject it.
- ** If we are in user role with one connection active
- ** reject the connection.
- ** Allocate PCB and store the parameters
- ** Make bridge request to the host system if connection
- ** is for NAP
- */
- wrong_uuid = false;
- if (remote_uuid->len == 16) {
- /*
- ** If the UUID is 16 bytes forst two bytes should be zeros
- ** and last 12 bytes should match the spec defined constant value
- */
- if (memcmp(constant_pan_uuid, remote_uuid->uu.uuid128 + 4,
- UUID_CONSTANT_PART))
- wrong_uuid = true;
-
- if (remote_uuid->uu.uuid128[0] || remote_uuid->uu.uuid128[1])
- wrong_uuid = true;
-
- /* Extract the 16 bit equivalent of the UUID */
- remote_uuid->uu.uuid16 = (uint16_t)((remote_uuid->uu.uuid128[2] << 8) |
- remote_uuid->uu.uuid128[3]);
- remote_uuid->len = 2;
- }
- if (remote_uuid->len == 4) {
- /* First two bytes should be zeros */
- if (remote_uuid->uu.uuid32 & 0xFFFF0000) wrong_uuid = true;
-
- remote_uuid->uu.uuid16 = (uint16_t)remote_uuid->uu.uuid32;
- remote_uuid->len = 2;
- }
-
- if (wrong_uuid) {
+ if (!remote_uuid.Is16Bit()) {
PAN_TRACE_ERROR("PAN Connection failed because of wrong remote UUID ");
BNEP_ConnectResp(handle, BNEP_CONN_FAILED_SRC_UUID);
return;
}
- wrong_uuid = false;
- if (local_uuid->len == 16) {
- /*
- ** If the UUID is 16 bytes forst two bytes should be zeros
- ** and last 12 bytes should match the spec defined constant value
- */
- if (memcmp(constant_pan_uuid, local_uuid->uu.uuid128 + 4,
- UUID_CONSTANT_PART))
- wrong_uuid = true;
-
- if (local_uuid->uu.uuid128[0] || local_uuid->uu.uuid128[1])
- wrong_uuid = true;
-
- /* Extract the 16 bit equivalent of the UUID */
- local_uuid->uu.uuid16 = (uint16_t)((local_uuid->uu.uuid128[2] << 8) |
- local_uuid->uu.uuid128[3]);
- local_uuid->len = 2;
- }
- if (local_uuid->len == 4) {
- /* First two bytes should be zeros */
- if (local_uuid->uu.uuid32 & 0xFFFF0000) wrong_uuid = true;
-
- local_uuid->uu.uuid16 = (uint16_t)local_uuid->uu.uuid32;
- local_uuid->len = 2;
- }
-
- if (wrong_uuid) {
+ if (!local_uuid.Is16Bit()) {
PAN_TRACE_ERROR("PAN Connection failed because of wrong local UUID ");
BNEP_ConnectResp(handle, BNEP_CONN_FAILED_DST_UUID);
return;
}
+ uint16_t remote_uuid16 = remote_uuid.As16Bit();
+ uint16_t local_uuid16 = local_uuid.As16Bit();
+
PAN_TRACE_EVENT(
- "pan_conn_ind_cb - for handle %d, current role %d, dst uuid 0x%x, src "
- "uuid 0x%x, role change %s",
- handle, pan_cb.role, local_uuid->uu.uuid16, remote_uuid->uu.uuid16,
+ "%s - handle %d, current role %d, dst uuid 0x%x, src uuid 0x%x, role "
+ "change %s",
+ __func__, handle, pan_cb.role, local_uuid16, remote_uuid16,
is_role_change ? "YES" : "NO");
- /* The acceptable UUID size is only 2 */
- if (remote_uuid->len != 2) {
- PAN_TRACE_ERROR("PAN Connection failed because of wrong UUID size %d",
- remote_uuid->len);
- BNEP_ConnectResp(handle, BNEP_CONN_FAILED_UUID_SIZE);
- return;
- }
/* Check if the source UUID is a valid one */
- if (remote_uuid->uu.uuid16 != UUID_SERVCLASS_PANU &&
- remote_uuid->uu.uuid16 != UUID_SERVCLASS_NAP &&
- remote_uuid->uu.uuid16 != UUID_SERVCLASS_GN) {
- PAN_TRACE_ERROR("Src UUID 0x%x is not valid", remote_uuid->uu.uuid16);
+ if (remote_uuid16 != UUID_SERVCLASS_PANU &&
+ remote_uuid16 != UUID_SERVCLASS_NAP &&
+ remote_uuid16 != UUID_SERVCLASS_GN) {
+ PAN_TRACE_ERROR("Src UUID 0x%x is not valid", remote_uuid16);
BNEP_ConnectResp(handle, BNEP_CONN_FAILED_SRC_UUID);
return;
}
/* Check if the destination UUID is a valid one */
- if (local_uuid->uu.uuid16 != UUID_SERVCLASS_PANU &&
- local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP &&
- local_uuid->uu.uuid16 != UUID_SERVCLASS_GN) {
- PAN_TRACE_ERROR("Dst UUID 0x%x is not valid", remote_uuid->uu.uuid16);
+ if (local_uuid16 != UUID_SERVCLASS_PANU &&
+ local_uuid16 != UUID_SERVCLASS_NAP && local_uuid16 != UUID_SERVCLASS_GN) {
+ PAN_TRACE_ERROR("Dst UUID 0x%x is not valid", local_uuid16);
BNEP_ConnectResp(handle, BNEP_CONN_FAILED_DST_UUID);
return;
}
/* Check if currently we support the destination role requested */
if (((!(pan_cb.role & UUID_SERVCLASS_PANU)) &&
- local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) ||
+ local_uuid16 == UUID_SERVCLASS_PANU) ||
((!(pan_cb.role & UUID_SERVCLASS_GN)) &&
- local_uuid->uu.uuid16 == UUID_SERVCLASS_GN) ||
+ local_uuid16 == UUID_SERVCLASS_GN) ||
((!(pan_cb.role & UUID_SERVCLASS_NAP)) &&
- local_uuid->uu.uuid16 == UUID_SERVCLASS_NAP)) {
+ local_uuid16 == UUID_SERVCLASS_NAP)) {
PAN_TRACE_ERROR(
"PAN Connection failed because of unsupported destination UUID 0x%x",
- local_uuid->uu.uuid16);
+ local_uuid16);
BNEP_ConnectResp(handle, BNEP_CONN_FAILED_DST_UUID);
return;
}
@@ -221,11 +154,10 @@
* Note: the remote is the initiator.
*/
bool is_valid_interaction = false;
- switch (remote_uuid->uu.uuid16) {
+ switch (remote_uuid16) {
case UUID_SERVCLASS_NAP:
case UUID_SERVCLASS_GN:
- if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
- is_valid_interaction = true;
+ if (local_uuid16 == UUID_SERVCLASS_PANU) is_valid_interaction = true;
break;
case UUID_SERVCLASS_PANU:
is_valid_interaction = true;
@@ -235,23 +167,24 @@
* Explicitly disable connections to the local PANU if the remote is
* not PANU.
*/
- if ((local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) &&
- (remote_uuid->uu.uuid16 != UUID_SERVCLASS_PANU)) {
+ if ((local_uuid16 == UUID_SERVCLASS_PANU) &&
+ (remote_uuid16 != UUID_SERVCLASS_PANU)) {
is_valid_interaction = false;
}
if (!is_valid_interaction) {
PAN_TRACE_ERROR(
"PAN Connection failed because of invalid PAN profile roles "
"interaction: Remote UUID 0x%x Local UUID 0x%x",
- remote_uuid->uu.uuid16, local_uuid->uu.uuid16);
+ remote_uuid16, local_uuid16);
BNEP_ConnectResp(handle, BNEP_CONN_FAILED_SRC_UUID);
return;
}
+ uint8_t req_role;
/* Requested destination role is */
- if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
+ if (local_uuid16 == UUID_SERVCLASS_PANU)
req_role = PAN_ROLE_CLIENT;
- else if (local_uuid->uu.uuid16 == UUID_SERVCLASS_GN)
+ else if (local_uuid16 == UUID_SERVCLASS_GN)
req_role = PAN_ROLE_GN_SERVER;
else
req_role = PAN_ROLE_NAP_SERVER;
@@ -259,9 +192,9 @@
/* If the connection indication is for the existing connection
** Check if the new destination role is acceptable
*/
- pcb = pan_get_pcb_by_handle(handle);
+ tPAN_CONN* pcb = pan_get_pcb_by_handle(handle);
if (pcb) {
- if (pan_cb.num_conns > 1 && local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) {
+ if (pan_cb.num_conns > 1 && local_uuid16 == UUID_SERVCLASS_PANU) {
/* There are connections other than this one
** so we cann't accept PANU role. Reject
*/
@@ -274,14 +207,14 @@
/* If it is already in connected state check for bridging status */
if (pcb->con_state == PAN_STATE_CONNECTED) {
- PAN_TRACE_EVENT("PAN Role changing New Src 0x%x Dst 0x%x",
- remote_uuid->uu.uuid16, local_uuid->uu.uuid16);
+ PAN_TRACE_EVENT("PAN Role changing New Src 0x%x Dst 0x%x", remote_uuid16,
+ local_uuid16);
pcb->prv_src_uuid = pcb->src_uuid;
pcb->prv_dst_uuid = pcb->dst_uuid;
if (pcb->src_uuid == UUID_SERVCLASS_NAP &&
- local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP) {
+ local_uuid16 != UUID_SERVCLASS_NAP) {
/* Remove bridging */
if (pan_cb.pan_bridge_req_cb)
(*pan_cb.pan_bridge_req_cb)(pcb->rem_bda, false);
@@ -289,8 +222,8 @@
}
/* Set the latest active PAN role */
pan_cb.active_role = req_role;
- pcb->src_uuid = local_uuid->uu.uuid16;
- pcb->dst_uuid = remote_uuid->uu.uuid16;
+ pcb->src_uuid = local_uuid16;
+ pcb->dst_uuid = remote_uuid16;
BNEP_ConnectResp(handle, BNEP_SUCCESS);
return;
} else {
@@ -298,7 +231,7 @@
** we already have a connection then reject the request.
** If we have a connection in PANU role then reject it
*/
- if (pan_cb.num_conns && (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU ||
+ if (pan_cb.num_conns && (local_uuid16 == UUID_SERVCLASS_PANU ||
pan_cb.active_role == PAN_ROLE_CLIENT)) {
PAN_TRACE_ERROR("PAN already have a connection and can't be user");
BNEP_ConnectResp(handle, BNEP_CONN_FAILED_DST_UUID);
@@ -315,12 +248,11 @@
return;
}
- PAN_TRACE_EVENT("PAN connection destination UUID is 0x%x",
- local_uuid->uu.uuid16);
+ PAN_TRACE_EVENT("PAN connection destination UUID is 0x%x", local_uuid16);
/* Set the latest active PAN role */
pan_cb.active_role = req_role;
- pcb->src_uuid = local_uuid->uu.uuid16;
- pcb->dst_uuid = remote_uuid->uu.uuid16;
+ pcb->src_uuid = local_uuid16;
+ pcb->dst_uuid = remote_uuid16;
pcb->con_state = PAN_STATE_CONN_START;
pan_cb.num_conns++;
@@ -595,12 +527,11 @@
if (pan_cb.pan_data_buf_ind_cb)
(*pan_cb.pan_data_buf_ind_cb)(pcb->handle, src, dst, protocol, p_buf,
ext, forward);
- else if (pan_cb.pan_data_ind_cb) {
+ else if (pan_cb.pan_data_ind_cb)
(*pan_cb.pan_data_ind_cb)(pcb->handle, src, dst, protocol, p_data, len,
ext, forward);
- osi_free(p_buf);
- }
+ osi_free(p_buf);
return;
}
@@ -625,13 +556,10 @@
if (pan_cb.pan_data_buf_ind_cb)
(*pan_cb.pan_data_buf_ind_cb)(pcb->handle, src, dst, protocol, p_buf, ext,
forward);
- else if (pan_cb.pan_data_ind_cb) {
+ else if (pan_cb.pan_data_ind_cb)
(*pan_cb.pan_data_ind_cb)(pcb->handle, src, dst, protocol, p_data, len, ext,
forward);
- osi_free(p_buf);
- } else
- osi_free(p_buf);
-
+ osi_free(p_buf);
return;
}
diff --git a/stack/pan/pan_utils.cc b/stack/pan/pan_utils.cc
index b2eed2d..fa76200 100644
--- a/stack/pan/pan_utils.cc
+++ b/stack/pan/pan_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/rfcomm/port_api.cc b/stack/rfcomm/port_api.cc
index 808b567..1ae8667 100644
--- a/stack/rfcomm/port_api.cc
+++ b/stack/rfcomm/port_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -115,44 +115,45 @@
int RFCOMM_CreateConnection(uint16_t uuid, uint8_t scn, bool is_server,
uint16_t mtu, const RawAddress& bd_addr,
uint16_t* p_handle, tPORT_CALLBACK* p_mgmt_cb) {
- tPORT* p_port;
- uint8_t dlci;
- tRFC_MCB* p_mcb = port_find_mcb(bd_addr);
- uint16_t rfcomm_mtu;
-
- VLOG(0) << __func__ << " BDA: " << bd_addr;
-
*p_handle = 0;
if ((scn == 0) || (scn >= PORT_MAX_RFC_PORTS)) {
/* Server Channel Number(SCN) should be in range 1...30 */
- RFCOMM_TRACE_ERROR("RFCOMM_CreateConnection - invalid SCN");
+ LOG(ERROR) << __func__ << ": Invalid SCN, bd_addr=" << bd_addr
+ << ", scn=" << static_cast<int>(scn)
+ << ", is_server=" << is_server
+ << ", mtu=" << static_cast<int>(mtu)
+ << ", uuid=" << loghex(uuid);
return (PORT_INVALID_SCN);
}
/* For client that originate connection on the existing none initiator */
/* multiplexer channel DLCI should be odd */
- if (p_mcb && !p_mcb->is_initiator && !is_server)
- dlci = (scn << 1) + 1;
- else
+ uint8_t dlci;
+ tRFC_MCB* p_mcb = port_find_mcb(bd_addr);
+ if (p_mcb && !p_mcb->is_initiator && !is_server) {
+ dlci = static_cast<uint8_t>((scn << 1) + 1);
+ } else {
dlci = (scn << 1);
- RFCOMM_TRACE_API(
- "RFCOMM_CreateConnection(): scn:%d, dlci:%d, is_server:%d mtu:%d, "
- "p_mcb:%p",
- scn, dlci, is_server, mtu, p_mcb);
+ }
/* For the server side always allocate a new port. On the client side */
/* do not allow the same (dlci, bd_addr) to be opened twice by application */
+ tPORT* p_port;
if (!is_server) {
p_port = port_find_port(dlci, bd_addr);
- if (p_port != NULL) {
+ if (p_port != nullptr) {
/* if existing port is also a client port */
- if (p_port->is_server == false) {
- RFCOMM_TRACE_ERROR(
- "RFCOMM_CreateConnection - already opened state:%d, RFC state:%d, "
- "MCB state:%d",
- p_port->state, p_port->rfc.state,
- p_port->rfc.p_mcb ? p_port->rfc.p_mcb->state : 0);
+ if (!p_port->is_server) {
+ LOG(ERROR) << __func__ << ": already at opened state "
+ << static_cast<int>(p_port->state)
+ << ", RFC_state=" << static_cast<int>(p_port->rfc.state)
+ << ", MCB_state="
+ << (p_port->rfc.p_mcb ? p_port->rfc.p_mcb->state : 0)
+ << ", bd_addr=" << bd_addr << ", scn=" << std::to_string(scn)
+ << ", is_server=" << is_server << ", mtu=" << mtu
+ << ", uuid=" << loghex(uuid) << ", dlci=" << +dlci
+ << ", p_mcb=" << p_mcb << ", port=" << +p_port->inx;
*p_handle = p_port->inx;
return (PORT_ALREADY_OPENED);
}
@@ -160,17 +161,13 @@
}
p_port = port_allocate_port(dlci, bd_addr);
- if (p_port == NULL) {
- RFCOMM_TRACE_WARNING("RFCOMM_CreateConnection - no resources");
+ if (p_port == nullptr) {
+ LOG(ERROR) << __func__ << ": no resources, bd_addr=" << bd_addr
+ << ", scn=" << std::to_string(scn) << ", is_server=" << is_server
+ << ", mtu=" << mtu << ", uuid=" << loghex(uuid)
+ << ", dlci=" << +dlci;
return (PORT_NO_RESOURCES);
}
- RFCOMM_TRACE_API(
- "RFCOMM_CreateConnection(): scn:%d, dlci:%d, is_server:%d mtu:%d, "
- "p_mcb:%p, p_port:%p",
- scn, dlci, is_server, mtu, p_mcb, p_port);
-
- p_port->default_signal_state =
- (PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);
switch (uuid) {
case UUID_PROTOCOL_OBEX:
@@ -186,11 +183,12 @@
case UUID_SERVCLASS_FAX:
p_port->default_signal_state = PORT_DUN_DEFAULT_SIGNAL_STATE;
break;
+ default:
+ p_port->default_signal_state =
+ (PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);
+ break;
}
- RFCOMM_TRACE_EVENT("RFCOMM_CreateConnection dlci:%d signal state:0x%x", dlci,
- p_port->default_signal_state);
-
*p_handle = p_port->inx;
p_port->state = PORT_STATE_OPENING;
@@ -205,12 +203,13 @@
* will know for sure our prefered MTU
*/
- rfcomm_mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
+ uint16_t rfcomm_mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
- if (mtu)
+ if (mtu) {
p_port->mtu = (mtu < rfcomm_mtu) ? mtu : rfcomm_mtu;
- else
+ } else {
p_port->mtu = rfcomm_mtu;
+ }
/* server doesn't need to release port when closing */
if (is_server) {
@@ -228,6 +227,13 @@
p_port->bd_addr = bd_addr;
+ LOG(INFO) << __func__ << ": bd_addr=" << bd_addr
+ << ", scn=" << std::to_string(scn) << ", is_server=" << is_server
+ << ", mtu=" << mtu << ", uuid=" << loghex(uuid)
+ << ", dlci=" << std::to_string(dlci)
+ << ", signal_state=" << loghex(p_port->default_signal_state)
+ << ", p_port=" << p_port;
+
/* If this is not initiator of the connection need to just wait */
if (p_port->is_server) {
return (PORT_SUCCESS);
@@ -1422,9 +1428,9 @@
}
int available = 0;
// if(ioctl(fd, FIONREAD, &available) < 0)
- if (p_port->p_data_co_callback(
- handle, (uint8_t*)&available, sizeof(available),
- DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE) == false) {
+ if (!p_port->p_data_co_callback(handle, (uint8_t*)&available,
+ sizeof(available),
+ DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE)) {
RFCOMM_TRACE_ERROR(
"p_data_co_callback DATA_CO_CALLBACK_TYPE_INCOMING_SIZE failed, "
"available:%d",
@@ -1447,9 +1453,9 @@
(((int)p_buf->len + available) <= (int)length)) {
// if(recv(fd, (uint8_t *)(p_buf + 1) + p_buf->offset + p_buf->len,
// available, 0) != available)
- if (p_port->p_data_co_callback(
+ if (!p_port->p_data_co_callback(
handle, (uint8_t*)(p_buf + 1) + p_buf->offset + p_buf->len,
- available, DATA_CO_CALLBACK_TYPE_OUTGOING) == false)
+ available, DATA_CO_CALLBACK_TYPE_OUTGOING))
{
error(
@@ -1503,9 +1509,9 @@
// memcpy ((uint8_t *)(p_buf + 1) + p_buf->offset, p_data, length);
// if(recv(fd, (uint8_t *)(p_buf + 1) + p_buf->offset, (int)length, 0) !=
// (int)length)
- if (p_port->p_data_co_callback(
- handle, (uint8_t*)(p_buf + 1) + p_buf->offset, length,
- DATA_CO_CALLBACK_TYPE_OUTGOING) == false) {
+ if (!p_port->p_data_co_callback(handle,
+ (uint8_t*)(p_buf + 1) + p_buf->offset,
+ length, DATA_CO_CALLBACK_TYPE_OUTGOING)) {
error(
"p_data_co_callback DATA_CO_CALLBACK_TYPE_OUTGOING failed, length:%d",
length);
diff --git a/stack/rfcomm/port_int.h b/stack/rfcomm/port_int.h
index 018a9fad..db7d0fd 100644
--- a/stack/rfcomm/port_int.h
+++ b/stack/rfcomm/port_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/rfcomm/port_rfc.cc b/stack/rfcomm/port_rfc.cc
index f4e84ae..5ec5631 100644
--- a/stack/rfcomm/port_rfc.cc
+++ b/stack/rfcomm/port_rfc.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -282,14 +282,18 @@
/* This can be a first request for this port */
p_port = port_find_dlci_port(dlci);
if (!p_port) {
+ LOG(ERROR) << __func__ << ": Disconnect RFCOMM, port not found, dlci="
+ << std::to_string(dlci) << ", p_mcb=" << p_mcb
+ << ", bd_addr=" << p_mcb->bd_addr;
/* If the port cannot be opened, send a DM. Per Errata 1205 */
rfc_send_dm(p_mcb, dlci, false);
/* check if this is the last port open, some headsets have
problem, they don't disconnect if we send DM */
rfc_check_mcb_active(p_mcb);
- RFCOMM_TRACE_EVENT("PORT_ParNegInd: port not found");
return;
}
+ RFCOMM_TRACE_EVENT("%s: port_inx[dlci:%d]:%d->%d", __func__, dlci,
+ p_mcb->port_inx[dlci], p_port->inx);
p_mcb->port_inx[dlci] = p_port->inx;
}
diff --git a/stack/rfcomm/port_utils.cc b/stack/rfcomm/port_utils.cc
index 1390e60..e9a9036 100644
--- a/stack/rfcomm/port_utils.cc
+++ b/stack/rfcomm/port_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,7 +91,7 @@
}
/* If here, no free PORT found */
- return (NULL);
+ return nullptr;
}
/*******************************************************************************
@@ -104,7 +104,7 @@
******************************************************************************/
void port_set_defaults(tPORT* p_port) {
p_port->ev_mask = 0;
- p_port->p_callback = NULL;
+ p_port->p_callback = nullptr;
p_port->port_ctrl = 0;
p_port->error = 0;
p_port->line_status = 0;
@@ -207,12 +207,16 @@
mutex_global_lock();
BT_HDR* p_buf;
- while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->rx.queue)) != NULL)
+ while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->rx.queue)) !=
+ nullptr) {
osi_free(p_buf);
+ }
p_port->rx.queue_size = 0;
- while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL)
+ while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->tx.queue)) !=
+ nullptr) {
osi_free(p_buf);
+ }
p_port->tx.queue_size = 0;
mutex_global_unlock();
@@ -231,10 +235,10 @@
rfc_port_timer_stop(p_port);
mutex_global_lock();
- fixed_queue_free(p_port->tx.queue, NULL);
- p_port->tx.queue = NULL;
- fixed_queue_free(p_port->rx.queue, NULL);
- p_port->rx.queue = NULL;
+ fixed_queue_free(p_port->tx.queue, nullptr);
+ p_port->tx.queue = nullptr;
+ fixed_queue_free(p_port->rx.queue, nullptr);
+ p_port->rx.queue = nullptr;
mutex_global_unlock();
if (p_port->keep_port_handle) {
@@ -254,7 +258,7 @@
p_port->mtu = p_port->keep_mtu;
p_port->state = PORT_STATE_OPENING;
- p_port->rfc.p_mcb = NULL;
+ p_port->rfc.p_mcb = nullptr;
if (p_port->is_server) p_port->dlci &= 0xfe;
p_port->local_ctrl.modem_signal = p_port->default_signal_state;
@@ -276,21 +280,16 @@
*
******************************************************************************/
tRFC_MCB* port_find_mcb(const RawAddress& bd_addr) {
- int i;
-
- for (i = 0; i < MAX_BD_CONNECTIONS; i++) {
- if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE) &&
- rfc_cb.port.rfc_mcb[i].bd_addr == bd_addr) {
+ for (tRFC_MCB& mcb : rfc_cb.port.rfc_mcb) {
+ if ((mcb.state != RFC_MX_STATE_IDLE) && (mcb.bd_addr == bd_addr)) {
/* Multiplexer channel found do not change anything */
- VLOG(1) << __func__ << ": found bd_addr:" << bd_addr;
- RFCOMM_TRACE_DEBUG(
- "port_find_mcb: rfc_cb.port.rfc_mcb:index:%d, %p, lcid:%d", i,
- &rfc_cb.port.rfc_mcb[i], rfc_cb.port.rfc_mcb[i].lcid);
- return (&rfc_cb.port.rfc_mcb[i]);
+ VLOG(1) << __func__ << ": found bd_addr=" << bd_addr
+ << ", rfc_mcb=" << &mcb << ", lcid=" << loghex(mcb.lcid);
+ return &mcb;
}
}
VLOG(1) << __func__ << ": not found, bd_addr:" << bd_addr;
- return (NULL);
+ return nullptr;
}
/*******************************************************************************
@@ -306,20 +305,26 @@
*
******************************************************************************/
tPORT* port_find_mcb_dlci_port(tRFC_MCB* p_mcb, uint8_t dlci) {
- uint8_t inx;
+ if (!p_mcb) {
+ LOG(ERROR) << __func__ << ": p_mcb is null, dlci=" << std::to_string(dlci);
+ return nullptr;
+ }
- if (!p_mcb) return (NULL);
+ if (dlci > RFCOMM_MAX_DLCI) {
+ LOG(WARNING) << __func__ << ": DLCI " << std::to_string(dlci)
+ << " is too large, bd_addr=" << p_mcb->bd_addr
+ << ", p_mcb=" << p_mcb;
+ return nullptr;
+ }
- if (dlci > RFCOMM_MAX_DLCI) return (NULL);
-
- inx = p_mcb->port_inx[dlci];
+ uint8_t inx = p_mcb->port_inx[dlci];
if (inx == 0) {
- RFCOMM_TRACE_DEBUG(
- "port_find_mcb_dlci_port: p_mcb:%p, port_inx[dlci:%d] is 0", p_mcb,
- dlci);
- return (NULL);
- } else
- return (&rfc_cb.port.port[inx - 1]);
+ LOG(INFO) << __func__ << ": Cannot find allocated RFCOMM app port for DLCI "
+ << std::to_string(dlci) << " on " << p_mcb->bd_addr
+ << ", p_mcb=" << p_mcb;
+ return nullptr;
+ }
+ return &rfc_cb.port.port[inx - 1];
}
/*******************************************************************************
@@ -332,22 +337,17 @@
*
******************************************************************************/
tPORT* port_find_dlci_port(uint8_t dlci) {
- uint16_t i;
- tPORT* p_port;
-
- for (i = 0; i < MAX_RFC_PORTS; i++) {
- p_port = &rfc_cb.port.port[i];
-
- if (p_port->in_use && (p_port->rfc.p_mcb == NULL)) {
- if (p_port->dlci == dlci) {
- return (p_port);
- } else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1))) {
- p_port->dlci++;
- return (p_port);
+ for (tPORT& port : rfc_cb.port.port) {
+ if (port.in_use && (port.rfc.p_mcb == nullptr)) {
+ if (port.dlci == dlci) {
+ return &port;
+ } else if ((dlci & 0x01) && (port.dlci == (dlci - 1))) {
+ port.dlci++;
+ return &port;
}
}
}
- return (NULL);
+ return nullptr;
}
/*******************************************************************************
@@ -360,17 +360,12 @@
*
******************************************************************************/
tPORT* port_find_port(uint8_t dlci, const RawAddress& bd_addr) {
- uint16_t i;
- tPORT* p_port;
-
- for (i = 0; i < MAX_RFC_PORTS; i++) {
- p_port = &rfc_cb.port.port[i];
- if (p_port->in_use && (p_port->dlci == dlci) &&
- p_port->bd_addr == bd_addr) {
- return (p_port);
+ for (tPORT& port : rfc_cb.port.port) {
+ if (port.in_use && (port.dlci == dlci) && (port.bd_addr == bd_addr)) {
+ return &port;
}
}
- return (NULL);
+ return nullptr;
}
/*******************************************************************************
diff --git a/stack/rfcomm/rfc_int.h b/stack/rfcomm/rfc_int.h
index 93da38a..05afa9d 100644
--- a/stack/rfcomm/rfc_int.h
+++ b/stack/rfcomm/rfc_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,10 +62,7 @@
extern void RFCOMM_TestReq(uint8_t* p_data, uint16_t len);
-#define RFCOMM_FLOW_STATE_DISABLE 0
-#define RFCOMM_FLOW_STATE_ENABLE 1
-
-extern void RFCOMM_FlowReq(tRFC_MCB* p_mcb, uint8_t dlci, uint8_t state);
+extern void RFCOMM_FlowReq(tRFC_MCB* p_mcb, uint8_t dlci, bool state);
extern void RFCOMM_PortNegReq(tRFC_MCB* p_mcb, uint8_t dlci,
tPORT_STATE* p_pars);
diff --git a/stack/rfcomm/rfc_l2cap_if.cc b/stack/rfcomm/rfc_l2cap_if.cc
index f90f8da..a20f399 100644
--- a/stack/rfcomm/rfc_l2cap_if.cc
+++ b/stack/rfcomm/rfc_l2cap_if.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -147,9 +147,6 @@
/* if peer rejects our connect request but peer's connect request is pending
*/
if (result != L2CAP_CONN_OK) {
- uint16_t i;
- uint8_t idx;
-
RFCOMM_TRACE_DEBUG(
"RFCOMM_ConnectCnf retry as acceptor on pending LCID(0x%x)",
p_mcb->pending_lcid);
@@ -165,13 +162,13 @@
rfc_save_lcid_mcb(p_mcb, p_mcb->lcid);
/* update direction bit */
- for (i = 0; i < RFCOMM_MAX_DLCI; i += 2) {
- idx = p_mcb->port_inx[i];
+ for (int i = 0; i < RFCOMM_MAX_DLCI; i += 2) {
+ uint8_t idx = p_mcb->port_inx[i];
if (idx != 0) {
p_mcb->port_inx[i] = 0;
p_mcb->port_inx[i + 1] = idx;
rfc_cb.port.port[idx - 1].dlci += 1;
- RFCOMM_TRACE_DEBUG("RFCOMM MX - DLCI:%d -> %d", i,
+ RFCOMM_TRACE_DEBUG("RFCOMM MX, port_handle=%d, DLCI[%d->%d]", idx, i,
rfc_cb.port.port[idx - 1].dlci);
}
}
@@ -268,7 +265,7 @@
return;
}
- rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_DISC_IND, NULL);
+ rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_DISC_IND, nullptr);
}
/*******************************************************************************
@@ -283,24 +280,27 @@
******************************************************************************/
void RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf) {
tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
- tPORT* p_port;
- uint8_t event;
if (!p_mcb) {
- RFCOMM_TRACE_WARNING("RFCOMM_BufDataInd LCID:0x%x", lcid);
+ LOG(WARNING) << __func__ << ": Cannot find RFCOMM multiplexer for lcid "
+ << loghex(lcid);
osi_free(p_buf);
return;
}
- event = rfc_parse_data(p_mcb, &rfc_cb.rfc.rx_frame, p_buf);
+ uint8_t event = rfc_parse_data(p_mcb, &rfc_cb.rfc.rx_frame, p_buf);
/* If the frame did not pass validation just ignore it */
if (event == RFC_EVENT_BAD_FRAME) {
+ LOG(WARNING) << __func__ << ": Bad RFCOMM frame from lcid=" << loghex(lcid)
+ << ", bd_addr=" << p_mcb->bd_addr << ", p_mcb=" << p_mcb;
osi_free(p_buf);
return;
}
if (rfc_cb.rfc.rx_frame.dlci == RFCOMM_MX_DLCI) {
+ RFCOMM_TRACE_DEBUG("%s: Handle multiplexer event %d, p_mcb=%p", __func__,
+ event, p_mcb);
/* Take special care of the Multiplexer Control Messages */
if (event == RFC_EVENT_UIH) {
rfc_process_mx_message(p_mcb, p_buf);
@@ -308,47 +308,62 @@
}
/* Other multiplexer events go to state machine */
- rfc_mx_sm_execute(p_mcb, event, NULL);
+ rfc_mx_sm_execute(p_mcb, event, nullptr);
osi_free(p_buf);
return;
}
/* The frame was received on the data channel DLCI, verify that DLC exists */
- if (((p_port = port_find_mcb_dlci_port(p_mcb, rfc_cb.rfc.rx_frame.dlci)) ==
- NULL) ||
- (!p_port->rfc.p_mcb)) {
- /* If this is a SABME on the new port, check if any appl is waiting for it
- */
+ tPORT* p_port = port_find_mcb_dlci_port(p_mcb, rfc_cb.rfc.rx_frame.dlci);
+ if (p_port == nullptr || !p_port->rfc.p_mcb) {
+ /* If this is a SABME on new port, check if any app is waiting for it */
if (event != RFC_EVENT_SABME) {
+ LOG(WARNING) << __func__
+ << ": no for none-SABME event, lcid=" << loghex(lcid)
+ << ", bd_addr=" << p_mcb->bd_addr << ", p_mcb=" << p_mcb;
if ((p_mcb->is_initiator && !rfc_cb.rfc.rx_frame.cr) ||
- (!p_mcb->is_initiator && rfc_cb.rfc.rx_frame.cr))
+ (!p_mcb->is_initiator && rfc_cb.rfc.rx_frame.cr)) {
+ LOG(ERROR) << __func__
+ << ": Disconnecting RFCOMM, lcid=" << loghex(lcid)
+ << ", bd_addr=" << p_mcb->bd_addr << ", p_mcb=" << p_mcb;
rfc_send_dm(p_mcb, rfc_cb.rfc.rx_frame.dlci, rfc_cb.rfc.rx_frame.pf);
+ }
osi_free(p_buf);
return;
}
p_port = port_find_dlci_port(rfc_cb.rfc.rx_frame.dlci);
- if (p_port == NULL) {
+ if (p_port == nullptr) {
+ LOG(ERROR) << __func__ << ":Disconnecting RFCOMM, no port for dlci "
+ << +rfc_cb.rfc.rx_frame.dlci << ", lcid=" << loghex(lcid)
+ << ", bd_addr=" << p_mcb->bd_addr << ", p_mcb=" << p_mcb;
rfc_send_dm(p_mcb, rfc_cb.rfc.rx_frame.dlci, true);
osi_free(p_buf);
return;
}
+ RFCOMM_TRACE_DEBUG("%s: port_inx[dlci=%d]:%d->%d, p_mcb=%p", __func__,
+ rfc_cb.rfc.rx_frame.dlci,
+ p_mcb->port_inx[rfc_cb.rfc.rx_frame.dlci], p_port->inx);
p_mcb->port_inx[rfc_cb.rfc.rx_frame.dlci] = p_port->inx;
p_port->rfc.p_mcb = p_mcb;
}
if (event == RFC_EVENT_UIH) {
- if (p_buf->len > 0)
+ RFCOMM_TRACE_DEBUG("%s: Handling UIH event, buf_len=%u, credit=%u",
+ __func__, p_buf->len, rfc_cb.rfc.rx_frame.credit);
+ if (p_buf->len > 0) {
rfc_port_sm_execute(p_port, event, p_buf);
- else
+ } else {
osi_free(p_buf);
+ }
- if (rfc_cb.rfc.rx_frame.credit != 0)
+ if (rfc_cb.rfc.rx_frame.credit != 0) {
rfc_inc_credit(p_port, rfc_cb.rfc.rx_frame.credit);
+ }
return;
}
- rfc_port_sm_execute(p_port, event, NULL);
+ rfc_port_sm_execute(p_port, event, nullptr);
osi_free(p_buf);
}
@@ -380,23 +395,20 @@
*
******************************************************************************/
tRFC_MCB* rfc_find_lcid_mcb(uint16_t lcid) {
- tRFC_MCB* p_mcb;
-
if (lcid - L2CAP_BASE_APPL_CID >= MAX_L2CAP_CHANNELS) {
RFCOMM_TRACE_ERROR("rfc_find_lcid_mcb LCID:0x%x", lcid);
- return (NULL);
+ return nullptr;
} else {
- p_mcb = rfc_cb.rfc.p_rfc_lcid_mcb[lcid - L2CAP_BASE_APPL_CID];
- if (p_mcb != NULL) {
+ tRFC_MCB* p_mcb = rfc_cb.rfc.p_rfc_lcid_mcb[lcid - L2CAP_BASE_APPL_CID];
+ if (p_mcb != nullptr) {
if (p_mcb->lcid != lcid) {
- RFCOMM_TRACE_WARNING(
- "rfc_find_lcid_mcb LCID reused LCID:0x%x current:0x%x", lcid,
- p_mcb->lcid);
- return (NULL);
+ LOG(WARNING) << __func__ << "LCID reused lcid=:" << loghex(lcid)
+ << ", current_lcid=" << loghex(p_mcb->lcid);
+ return nullptr;
}
}
+ return p_mcb;
}
- return (p_mcb);
}
/*******************************************************************************
diff --git a/stack/rfcomm/rfc_mx_fsm.cc b/stack/rfcomm/rfc_mx_fsm.cc
index 4f2785e..dfab62f 100644
--- a/stack/rfcomm/rfc_mx_fsm.cc
+++ b/stack/rfcomm/rfc_mx_fsm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/rfcomm/rfc_port_fsm.cc b/stack/rfcomm/rfc_port_fsm.cc
index 5157a75..4ff4628 100644
--- a/stack/rfcomm/rfc_port_fsm.cc
+++ b/stack/rfcomm/rfc_port_fsm.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -554,15 +554,22 @@
PORT_ParNegInd(p_mcb, dlci, p_frame->u.pn.mtu, p_frame->u.pn.conv_layer,
p_frame->u.pn.k);
} else {
+ LOG(WARNING) << __func__
+ << ": MX PN while disconnecting, bd_addr=" << p_mcb->bd_addr
+ << ", p_mcb=" << p_mcb;
rfc_send_dm(p_mcb, dlci, false);
- RFCOMM_TRACE_WARNING("***** MX PN while disconnecting *****");
}
return;
}
/* If we are not awaiting response just ignore it */
p_port = port_find_mcb_dlci_port(p_mcb, dlci);
- if ((p_port == NULL) || !(p_port->rfc.expected_rsp & RFC_RSP_PN)) return;
+ if ((p_port == nullptr) || !(p_port->rfc.expected_rsp & RFC_RSP_PN)) {
+ LOG(WARNING) << ": Ignore unwanted response, p_mcb=" << p_mcb
+ << ", bd_addr=" << p_mcb->bd_addr
+ << ", dlci=" << std::to_string(dlci);
+ return;
+ }
p_port->rfc.expected_rsp &= ~RFC_RSP_PN;
@@ -586,7 +593,7 @@
tPORT* p_port;
p_port = port_find_mcb_dlci_port(p_mcb, p_frame->dlci);
- if (p_port == NULL) {
+ if (p_port == nullptr) {
/* This is the first command on the port */
if (is_command) {
memset(&port_pars, 0, sizeof(tPORT_STATE));
@@ -600,7 +607,6 @@
if (is_command && is_request) {
/* This is the special situation when peer just request local pars */
- port_pars = p_port->peer_port_pars;
rfc_send_rpn(p_mcb, p_frame->dlci, false, &p_port->peer_port_pars, 0);
return;
}
@@ -617,9 +623,12 @@
/* If we are not awaiting response just ignore it */
p_port = port_find_mcb_dlci_port(p_mcb, p_frame->dlci);
- if ((p_port == NULL) ||
- !(p_port->rfc.expected_rsp & (RFC_RSP_RPN | RFC_RSP_RPN_REPLY)))
+ if ((p_port == nullptr) ||
+ !(p_port->rfc.expected_rsp & (RFC_RSP_RPN | RFC_RSP_RPN_REPLY))) {
+ LOG(WARNING) << __func__ << ": ignore DLC parameter negotiation as we are"
+ << " not waiting for any";
return;
+ }
/* If we sent a request for port parameters to the peer he is replying with */
/* mask 0. */
@@ -842,14 +851,11 @@
p_mcb->l2cap_congested = is_congested;
if (!is_congested) {
- rfc_check_send_cmd(p_mcb, NULL);
+ rfc_check_send_cmd(p_mcb, nullptr);
}
if (!rfc_cb.rfc.peer_rx_disabled) {
- if (!is_congested)
- PORT_FlowInd(p_mcb, 0, true);
- else
- PORT_FlowInd(p_mcb, 0, false);
+ PORT_FlowInd(p_mcb, 0, !is_congested);
}
}
diff --git a/stack/rfcomm/rfc_port_if.cc b/stack/rfcomm/rfc_port_if.cc
index 4f8f38a..2ce5f9e 100644
--- a/stack/rfcomm/rfc_port_if.cc
+++ b/stack/rfcomm/rfc_port_if.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
*
*****************************************************************************/
-#include <string.h>
+#include <cstring>
#include "bt_common.h"
#include "bt_target.h"
#include "bt_utils.h"
@@ -47,7 +47,7 @@
*
******************************************************************************/
void RFCOMM_StartReq(tRFC_MCB* p_mcb) {
- rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_START_REQ, NULL);
+ rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_START_REQ, nullptr);
}
/*******************************************************************************
@@ -82,12 +82,12 @@
}
tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
- if (p_port == NULL) {
+ if (p_port == nullptr) {
RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
return;
}
- rfc_port_sm_execute(p_port, RFC_EVENT_OPEN, NULL);
+ rfc_port_sm_execute(p_port, RFC_EVENT_OPEN, nullptr);
}
/*******************************************************************************
@@ -106,7 +106,7 @@
}
tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
- if (p_port == NULL) {
+ if (p_port == nullptr) {
RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
return;
}
@@ -130,7 +130,7 @@
uint8_t k;
tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
- if (p_port == NULL) {
+ if (p_port == nullptr) {
RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
return;
}
@@ -193,12 +193,12 @@
******************************************************************************/
void RFCOMM_PortNegReq(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars) {
if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
- PORT_PortNegCnf(p_mcb, dlci, NULL, RFCOMM_ERROR);
+ PORT_PortNegCnf(p_mcb, dlci, nullptr, RFCOMM_ERROR);
return;
}
tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
- if (p_port == NULL) {
+ if (p_port == nullptr) {
RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
return;
}
@@ -238,7 +238,7 @@
******************************************************************************/
void RFCOMM_ControlReq(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars) {
tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
- if (p_port == NULL) {
+ if (p_port == nullptr) {
RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
return;
}
@@ -264,9 +264,9 @@
* port can accept more data.
*
******************************************************************************/
-void RFCOMM_FlowReq(tRFC_MCB* p_mcb, uint8_t dlci, uint8_t enable) {
+void RFCOMM_FlowReq(tRFC_MCB* p_mcb, uint8_t dlci, bool enable) {
tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
- if (p_port == NULL) {
+ if (p_port == nullptr) {
RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
return;
}
@@ -293,7 +293,7 @@
******************************************************************************/
void RFCOMM_LineStatusReq(tRFC_MCB* p_mcb, uint8_t dlci, uint8_t status) {
tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
- if (p_port == NULL) {
+ if (p_port == nullptr) {
RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
return;
}
@@ -316,7 +316,8 @@
*
******************************************************************************/
void RFCOMM_DlcReleaseReq(tRFC_MCB* p_mcb, uint8_t dlci) {
- rfc_port_sm_execute(port_find_mcb_dlci_port(p_mcb, dlci), RFC_EVENT_CLOSE, 0);
+ rfc_port_sm_execute(port_find_mcb_dlci_port(p_mcb, dlci), RFC_EVENT_CLOSE,
+ nullptr);
}
/*******************************************************************************
diff --git a/stack/rfcomm/rfc_ts_frames.cc b/stack/rfcomm/rfc_ts_frames.cc
index 93a8592..baf5614 100644
--- a/stack/rfcomm/rfc_ts_frames.cc
+++ b/stack/rfcomm/rfc_ts_frames.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -626,7 +626,9 @@
p_rx_frame->type = *p_data++ & ~(RFCOMM_CR_MASK | RFCOMM_EA_MASK);
if (!p_rx_frame->ea || !length) {
- RFCOMM_TRACE_ERROR("Illegal MX Frame ea:%d len:%d", p_rx_frame->ea, length);
+ LOG(ERROR) << __func__
+ << ": Invalid MX frame ea=" << std::to_string(p_rx_frame->ea)
+ << ", len=" << length << ", bd_addr=" << p_mcb->bd_addr;
osi_free(p_buf);
return;
}
@@ -646,14 +648,21 @@
}
if (mx_len != length) {
- RFCOMM_TRACE_ERROR("Bad MX frame");
+ LOG(ERROR) << __func__ << ": Bad MX frame, p_mcb=" << p_mcb
+ << ", bd_addr=" << p_mcb->bd_addr;
osi_free(p_buf);
return;
}
+ RFCOMM_TRACE_DEBUG("%s: type=%d, p_mcb=%p", __func__, p_rx_frame->type,
+ p_mcb);
switch (p_rx_frame->type) {
case RFCOMM_MX_PN:
- if (length != RFCOMM_MX_PN_LEN) break;
+ if (length != RFCOMM_MX_PN_LEN) {
+ LOG(ERROR) << __func__ << ": Invalid PN length, p_mcb=" << p_mcb
+ << ", bd_addr=" << p_mcb->bd_addr;
+ break;
+ }
p_rx_frame->dlci = *p_data++ & RFCOMM_PN_DLCI_MASK;
p_rx_frame->u.pn.frame_type = *p_data & RFCOMM_PN_FRAME_TYPE_MASK;
@@ -668,7 +677,8 @@
if (!p_rx_frame->dlci || !RFCOMM_VALID_DLCI(p_rx_frame->dlci) ||
(p_rx_frame->u.pn.mtu < RFCOMM_MIN_MTU) ||
(p_rx_frame->u.pn.mtu > RFCOMM_MAX_MTU)) {
- RFCOMM_TRACE_ERROR("Bad PN frame");
+ LOG(ERROR) << __func__ << ": Bad PN frame, p_mcb=" << p_mcb
+ << ", bd_addr=" << p_mcb->bd_addr;
break;
}
diff --git a/stack/rfcomm/rfc_utils.cc b/stack/rfcomm/rfc_utils.cc
index baf9aa0..74e336a 100644
--- a/stack/rfcomm/rfc_utils.cc
+++ b/stack/rfcomm/rfc_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -380,8 +380,7 @@
RFCOMM_TRACE_EVENT("rfc_inc_credit:%d", p_port->credit_tx);
- if (p_port->tx.peer_fc == true)
- PORT_FlowInd(p_port->rfc.p_mcb, p_port->dlci, true);
+ if (p_port->tx.peer_fc) PORT_FlowInd(p_port->rfc.p_mcb, p_port->dlci, true);
}
}
@@ -426,7 +425,7 @@
}
/* handle queue if L2CAP not congested */
- while (p_mcb->l2cap_congested == false) {
+ while (!p_mcb->l2cap_congested) {
BT_HDR* p = (BT_HDR*)fixed_queue_try_dequeue(p_mcb->cmd_q);
if (p == NULL) break;
L2CA_DataWrite(p_mcb->lcid, p);
diff --git a/stack/sdp/sdp_api.cc b/stack/sdp/sdp_api.cc
index c89eca5..6e5f6f1 100644
--- a/stack/sdp/sdp_api.cc
+++ b/stack/sdp/sdp_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,6 +39,8 @@
#include "osi/include/osi.h"
+using bluetooth::Uuid;
+
/**********************************************************************
* C L I E N T F U N C T I O N P R O T O T Y P E S *
**********************************************************************/
@@ -66,7 +68,7 @@
*
******************************************************************************/
bool SDP_InitDiscoveryDb(tSDP_DISCOVERY_DB* p_db, uint32_t len,
- uint16_t num_uuid, tSDP_UUID* p_uuid_list,
+ uint16_t num_uuid, const Uuid* p_uuid_list,
uint16_t num_attr, uint16_t* p_attr_list) {
uint16_t xx;
@@ -289,7 +291,7 @@
* Returns true if found, otherwise false.
*
******************************************************************************/
-bool SDP_FindServiceUUIDInRec(tSDP_DISC_REC* p_rec, tBT_UUID* p_uuid) {
+bool SDP_FindServiceUUIDInRec(tSDP_DISC_REC* p_rec, Uuid* p_uuid) {
tSDP_DISC_ATTR *p_attr, *p_sattr, *p_extra_sattr;
p_attr = p_rec->p_first_attr;
@@ -300,18 +302,14 @@
for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
p_sattr = p_sattr->p_next_attr) {
if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) {
- if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == LEN_UUID_16) {
- p_uuid->len = LEN_UUID_16;
- p_uuid->uu.uuid16 = p_sattr->attr_value.v.u16;
+ if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == Uuid::kNumBytes16) {
+ *p_uuid = Uuid::From16Bit(p_sattr->attr_value.v.u16);
} else if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) ==
- LEN_UUID_128) {
- p_uuid->len = LEN_UUID_128;
- for (uint8_t i = 0; i != LEN_UUID_128; ++i)
- p_uuid->uu.uuid128[i] =
- p_sattr->attr_value.v.array[LEN_UUID_128 - i - 1];
- } else if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == LEN_UUID_32) {
- p_uuid->len = LEN_UUID_32;
- p_uuid->uu.uuid32 = p_sattr->attr_value.v.u32;
+ Uuid::kNumBytes128) {
+ *p_uuid = Uuid::From128BitBE(p_sattr->attr_value.v.array);
+ } else if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) ==
+ Uuid::kNumBytes32) {
+ *p_uuid = Uuid::From32Bit(p_sattr->attr_value.v.u32);
}
return (true);
@@ -332,8 +330,7 @@
UUID_DESC_TYPE)
/* only support 16 bits UUID for now */
&& (SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2)) {
- p_uuid->len = 2;
- p_uuid->uu.uuid16 = p_extra_sattr->attr_value.v.u16;
+ *p_uuid = Uuid::From16Bit(p_extra_sattr->attr_value.v.u16);
return (true);
}
}
@@ -345,8 +342,7 @@
if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE)
/* only support 16 bits UUID for now */
&& (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2)) {
- p_uuid->len = 2;
- p_uuid->uu.uuid16 = p_attr->attr_value.v.u16;
+ *p_uuid = Uuid::From16Bit(p_attr->attr_value.v.u16);
return (true);
}
}
@@ -368,7 +364,7 @@
* Returns true if found, otherwise false.
*
******************************************************************************/
-bool SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC* p_rec, tBT_UUID* p_uuid) {
+bool SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC* p_rec, Uuid* p_uuid) {
tSDP_DISC_ATTR* p_attr = p_rec->p_first_attr;
while (p_attr) {
if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
@@ -378,10 +374,7 @@
if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) {
/* only support 128 bits UUID for now */
if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 16) {
- p_uuid->len = LEN_UUID_128;
- for (uint8_t i = 0; i != LEN_UUID_128; ++i)
- p_uuid->uu.uuid128[i] =
- p_sattr->attr_value.v.array[LEN_UUID_128 - i - 1];
+ *p_uuid = Uuid::From128BitBE(p_sattr->attr_value.v.array);
}
return (true);
}
@@ -393,10 +386,7 @@
if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE)
/* only support 128 bits UUID for now */
&& (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 16)) {
- p_uuid->len = LEN_UUID_128;
- for (uint8_t i = 0; i != LEN_UUID_128; ++i)
- p_uuid->uu.uuid128[i] =
- p_attr->attr_value.v.array[LEN_UUID_128 - i - 1];
+ *p_uuid = Uuid::From128BitBE(p_attr->attr_value.v.array);
return (true);
}
}
@@ -573,13 +563,13 @@
*
* NOTE the only difference between this function and the previous
* function "SDP_FindServiceInDb()" is that this function takes
- * a tBT_UUID input
+ * a Uuid input
*
* Returns Pointer to record containing service class, or NULL
*
******************************************************************************/
tSDP_DISC_REC* SDP_FindServiceUUIDInDb(tSDP_DISCOVERY_DB* p_db,
- tBT_UUID* p_uuid,
+ const Uuid& uuid,
tSDP_DISC_REC* p_start_rec) {
tSDP_DISC_REC* p_rec;
tSDP_DISC_ATTR *p_attr, *p_sattr;
@@ -601,13 +591,13 @@
for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
p_sattr = p_sattr->p_next_attr) {
if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) {
- if (sdpu_compare_uuid_with_attr(p_uuid, p_sattr)) return (p_rec);
+ if (sdpu_compare_uuid_with_attr(uuid, p_sattr)) return (p_rec);
}
}
break;
} else if (p_attr->attr_id == ATTR_ID_SERVICE_ID) {
if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE) {
- if (sdpu_compare_uuid_with_attr(p_uuid, p_attr)) return (p_rec);
+ if (sdpu_compare_uuid_with_attr(uuid, p_attr)) return (p_rec);
}
}
@@ -730,7 +720,7 @@
if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) ==
DATA_ELE_SEQ_DESC_TYPE) {
ret = sdp_fill_proto_elem(p_sattr, layer_uuid, p_elem);
- if (ret == true) break;
+ if (ret) break;
}
}
return ret;
@@ -829,9 +819,7 @@
uint16_t di_uuid = UUID_SERVCLASS_PNP_INFORMATION;
/* build uuid for db init */
- tSDP_UUID init_uuid;
- init_uuid.len = 2;
- init_uuid.uu.uuid16 = di_uuid;
+ Uuid init_uuid = Uuid::From16Bit(di_uuid);
if (SDP_InitDiscoveryDb(p_db, len, num_uuids, &init_uuid, 0, NULL))
if (SDP_ServiceSearchRequest(remote_device, p_db, p_cb))
@@ -1011,8 +999,7 @@
if (p_device_info == NULL) return SDP_ILLEGAL_PARAMETER;
/* if record is to be primary record, get handle to replace old primary */
- if (p_device_info->primary_record == true &&
- sdp_cb.server_db.di_primary_handle)
+ if (p_device_info->primary_record && sdp_cb.server_db.di_primary_handle)
handle = sdp_cb.server_db.di_primary_handle;
else {
handle = SDP_CreateRecord();
@@ -1023,7 +1010,7 @@
/* build the SDP entry */
/* Add the UUID to the Service Class ID List */
- if ((SDP_AddServiceClassIdList(handle, 1, &di_uuid)) == false)
+ if (!(SDP_AddServiceClassIdList(handle, 1, &di_uuid)))
result = SDP_DI_REG_FAILED;
/* mandatory */
@@ -1120,7 +1107,7 @@
if (result != SDP_SUCCESS)
SDP_DeleteRecord(handle);
- else if (p_device_info->primary_record == true)
+ else if (p_device_info->primary_record)
sdp_cb.server_db.di_primary_handle = handle;
return result;
diff --git a/stack/sdp/sdp_db.cc b/stack/sdp/sdp_db.cc
index 49f4269..d8cee9a 100644
--- a/stack/sdp/sdp_db.cc
+++ b/stack/sdp/sdp_db.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/sdp/sdp_discovery.cc b/stack/sdp/sdp_discovery.cc
index bf6f43b..365a70c 100644
--- a/stack/sdp/sdp_discovery.cc
+++ b/stack/sdp/sdp_discovery.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,8 @@
#include "sdp_api.h"
#include "sdpint.h"
+using bluetooth::Uuid;
+
#ifndef SDP_DEBUG_RAW
#define SDP_DEBUG_RAW false
#endif
@@ -72,7 +74,7 @@
*
******************************************************************************/
static uint8_t* sdpu_build_uuid_seq(uint8_t* p_out, uint16_t num_uuids,
- tSDP_UUID* p_uuid_list) {
+ Uuid* p_uuid_list) {
uint16_t xx;
uint8_t* p_len;
@@ -85,18 +87,19 @@
/* Now, loop through and put in all the UUID(s) */
for (xx = 0; xx < num_uuids; xx++, p_uuid_list++) {
- if (p_uuid_list->len == LEN_UUID_16) {
+ int len = p_uuid_list->GetShortestRepresentationSize();
+ if (len == Uuid::kNumBytes16) {
UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
- UINT16_TO_BE_STREAM(p_out, p_uuid_list->uu.uuid16);
- } else if (p_uuid_list->len == LEN_UUID_32) {
+ UINT16_TO_BE_STREAM(p_out, p_uuid_list->As16Bit());
+ } else if (len == Uuid::kNumBytes32) {
UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
- UINT32_TO_BE_STREAM(p_out, p_uuid_list->uu.uuid32);
- } else if (p_uuid_list->len == LEN_UUID_128) {
+ UINT32_TO_BE_STREAM(p_out, p_uuid_list->As32Bit());
+ } else if (len == Uuid::kNumBytes128) {
UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
- ARRAY_TO_BE_STREAM(p_out, p_uuid_list->uu.uuid128, p_uuid_list->len);
+ ARRAY_TO_BE_STREAM(p_out, p_uuid_list->To128BitBE(),
+ (int)Uuid::kNumBytes128);
} else {
- SDP_TRACE_ERROR("SDP: Passed UUID has invalid length %x",
- p_uuid_list->len);
+ DCHECK(0) << "SDP: Passed UUID has invalid length " << len;
}
}
@@ -914,12 +917,12 @@
(p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 2;
p += 2;
BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
- p += MAX_UUID_SIZE - 4;
+ p += Uuid::kNumBytes128 - 4;
} else {
p_attr->attr_len_type =
(p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 4;
BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
- p += MAX_UUID_SIZE - 4;
+ p += Uuid::kNumBytes128 - 4;
}
} else {
BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array,
diff --git a/stack/sdp/sdp_main.cc b/stack/sdp/sdp_main.cc
index 8f72aaa..3df37c5 100644
--- a/stack/sdp/sdp_main.cc
+++ b/stack/sdp/sdp_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -519,18 +519,19 @@
/* Allocate a new CCB. Return if none available. */
p_ccb = sdpu_allocate_ccb();
if (p_ccb == NULL) {
- SDP_TRACE_WARNING("SDP - no spare CCB for orig");
+ SDP_TRACE_WARNING("%s: no spare CCB for peer %s", __func__,
+ p_bd_addr.ToString().c_str());
return (NULL);
}
- SDP_TRACE_EVENT("SDP - Originate started");
+ SDP_TRACE_EVENT("%s: SDP - Originate started for peer %s", __func__,
+ p_bd_addr.ToString().c_str());
/* We are the originator of this connection */
p_ccb->con_flags |= SDP_FLAGS_IS_ORIG;
/* Save the BD Address and Channel ID. */
p_ccb->device_address = p_bd_addr;
- ;
/* Transition to the next appropriate state, waiting for connection confirm.
*/
@@ -539,15 +540,14 @@
cid = L2CA_ConnectReq(SDP_PSM, p_bd_addr);
/* Check if L2CAP started the connection process */
- if (cid != 0) {
- p_ccb->connection_id = cid;
-
- return (p_ccb);
- } else {
- SDP_TRACE_WARNING("SDP - Originate failed");
+ if (cid == 0) {
+ SDP_TRACE_WARNING("%s: SDP - Originate failed for peer %s", __func__,
+ p_bd_addr.ToString().c_str());
sdpu_release_ccb(p_ccb);
return (NULL);
}
+ p_ccb->connection_id = cid;
+ return (p_ccb);
}
/*******************************************************************************
diff --git a/stack/sdp/sdp_server.cc b/stack/sdp/sdp_server.cc
index 510b8dc..386f62f 100644
--- a/stack/sdp/sdp_server.cc
+++ b/stack/sdp/sdp_server.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -635,7 +635,7 @@
p_rec; p_rec = sdp_db_service_search(p_rec, &uid_seq)) {
/* Allow space for attribute sequence type and length */
p_seq_start = p_rsp;
- if (p_ccb->cont_info.last_attr_seq_desc_sent == false) {
+ if (!p_ccb->cont_info.last_attr_seq_desc_sent) {
/* See if there is enough room to include a new service in the current
* response */
rem_len = max_list_len - (int16_t)(p_rsp - &p_ccb->rsp_list[0]);
@@ -717,7 +717,7 @@
}
/* Go back and put the type and length into the buffer */
- if (p_ccb->cont_info.last_attr_seq_desc_sent == false) {
+ if (!p_ccb->cont_info.last_attr_seq_desc_sent) {
seq_len = sdpu_get_attrib_seq_len(p_rec, &attr_seq_sav);
if (seq_len != 0) {
UINT8_TO_BE_STREAM(p_seq_start,
diff --git a/stack/sdp/sdp_utils.cc b/stack/sdp/sdp_utils.cc
index e6589d4..c57a499 100644
--- a/stack/sdp/sdp_utils.cc
+++ b/stack/sdp/sdp_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@
#include "btu.h"
+using bluetooth::Uuid;
static const uint8_t sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
0x5F, 0x9B, 0x34, 0xFB};
@@ -593,7 +594,7 @@
bool sdpu_is_base_uuid(uint8_t* p_uuid) {
uint16_t xx;
- for (xx = 4; xx < MAX_UUID_SIZE; xx++)
+ for (xx = 4; xx < Uuid::kNumBytes128; xx++)
if (p_uuid[xx] != sdp_base_uuid[xx]) return (false);
/* If here, matched */
@@ -614,8 +615,8 @@
******************************************************************************/
bool sdpu_compare_uuid_arrays(uint8_t* p_uuid1, uint32_t len1, uint8_t* p_uuid2,
uint16_t len2) {
- uint8_t nu1[MAX_UUID_SIZE];
- uint8_t nu2[MAX_UUID_SIZE];
+ uint8_t nu1[Uuid::kNumBytes128];
+ uint8_t nu2[Uuid::kNumBytes128];
if (((len1 != 2) && (len1 != 4) && (len1 != 16)) ||
((len2 != 2) && (len2 != 4) && (len2 != 16))) {
@@ -639,15 +640,15 @@
(p_uuid1[2] == p_uuid2[0]) && (p_uuid1[3] == p_uuid2[1]));
} else {
/* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */
- memcpy(nu1, p_uuid1, MAX_UUID_SIZE);
- memcpy(nu2, sdp_base_uuid, MAX_UUID_SIZE);
+ memcpy(nu1, p_uuid1, Uuid::kNumBytes128);
+ memcpy(nu2, sdp_base_uuid, Uuid::kNumBytes128);
if (len2 == 4)
memcpy(nu2, p_uuid2, len2);
else if (len2 == 2)
memcpy(nu2 + 2, p_uuid2, len2);
- return (memcmp(nu1, nu2, MAX_UUID_SIZE) == 0);
+ return (memcmp(nu1, nu2, Uuid::kNumBytes128) == 0);
}
} else {
/* len2 is greater than len1 */
@@ -657,47 +658,21 @@
(p_uuid2[2] == p_uuid1[0]) && (p_uuid2[3] == p_uuid1[1]));
} else {
/* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */
- memcpy(nu2, p_uuid2, MAX_UUID_SIZE);
- memcpy(nu1, sdp_base_uuid, MAX_UUID_SIZE);
+ memcpy(nu2, p_uuid2, Uuid::kNumBytes128);
+ memcpy(nu1, sdp_base_uuid, Uuid::kNumBytes128);
if (len1 == 4)
memcpy(nu1, p_uuid1, (size_t)len1);
else if (len1 == 2)
memcpy(nu1 + 2, p_uuid1, (size_t)len1);
- return (memcmp(nu1, nu2, MAX_UUID_SIZE) == 0);
+ return (memcmp(nu1, nu2, Uuid::kNumBytes128) == 0);
}
}
}
/*******************************************************************************
*
- * Function sdpu_compare_bt_uuids
- *
- * Description This function compares 2 BT UUID structures.
- *
- * NOTE it is assumed that BT UUID structures are compressed to the
- * smallest possible UUIDs (by removing the base SDP UUID)
- *
- * Returns true if matched, else false
- *
- ******************************************************************************/
-bool sdpu_compare_bt_uuids(tBT_UUID* p_uuid1, tBT_UUID* p_uuid2) {
- /* Lengths must match for BT UUIDs to match */
- if (p_uuid1->len == p_uuid2->len) {
- if (p_uuid1->len == 2)
- return (p_uuid1->uu.uuid16 == p_uuid2->uu.uuid16);
- else if (p_uuid1->len == 4)
- return (p_uuid1->uu.uuid32 == p_uuid2->uu.uuid32);
- else if (!memcmp(p_uuid1->uu.uuid128, p_uuid2->uu.uuid128, 16))
- return (true);
- }
-
- return (false);
-}
-
-/*******************************************************************************
- *
* Function sdpu_compare_uuid_with_attr
*
* Description This function compares a BT UUID structure with the UUID in
@@ -712,18 +687,12 @@
* Returns true if matched, else false
*
******************************************************************************/
-bool sdpu_compare_uuid_with_attr(tBT_UUID* p_btuuid, tSDP_DISC_ATTR* p_attr) {
- uint16_t attr_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
-
- /* Since both UUIDs are compressed, lengths must match */
- if (p_btuuid->len != attr_len) return (false);
-
- if (p_btuuid->len == 2)
- return (bool)(p_btuuid->uu.uuid16 == p_attr->attr_value.v.u16);
- else if (p_btuuid->len == 4)
- return (bool)(p_btuuid->uu.uuid32 == p_attr->attr_value.v.u32);
- else if (!memcmp(p_btuuid->uu.uuid128, (void*)p_attr->attr_value.v.array,
- MAX_UUID_SIZE))
+bool sdpu_compare_uuid_with_attr(const Uuid& uuid, tSDP_DISC_ATTR* p_attr) {
+ int len = uuid.GetShortestRepresentationSize();
+ if (len == 2) return uuid.As16Bit() == p_attr->attr_value.v.u16;
+ if (len == 4) return uuid.As32Bit() == p_attr->attr_value.v.u32;
+ if (memcmp(uuid.To128BitBE().data(), (void*)p_attr->attr_value.v.array,
+ Uuid::kNumBytes128) == 0)
return (true);
return (false);
@@ -811,7 +780,7 @@
uint16_t start_id = 0, end_id = 0;
for (xx = 0; xx < attr_seq->num_attr; xx++) {
- if (is_range == false) {
+ if (!is_range) {
start_id = attr_seq->attr_entry[xx].start;
end_id = attr_seq->attr_entry[xx].end;
}
@@ -927,25 +896,3 @@
osi_free(p_attr_buff);
return p_out;
}
-
-/*******************************************************************************
- *
- * Function sdpu_uuid16_to_uuid128
- *
- * Description This function converts UUID-16 to UUID-128 by including the
- * base UUID
- *
- * uuid16: 2-byte UUID
- * p_uuid128: Expanded 128-bit UUID
- *
- * Returns None
- *
- ******************************************************************************/
-void sdpu_uuid16_to_uuid128(uint16_t uuid16, uint8_t* p_uuid128) {
- uint16_t uuid16_bo;
- memset(p_uuid128, 0, 16);
-
- memcpy(p_uuid128, sdp_base_uuid, MAX_UUID_SIZE);
- uuid16_bo = ntohs(uuid16);
- memcpy(p_uuid128 + 2, &uuid16_bo, sizeof(uint16_t));
-}
diff --git a/stack/sdp/sdpint.h b/stack/sdp/sdpint.h
index a2d5089..0d44c9d 100644
--- a/stack/sdp/sdpint.h
+++ b/stack/sdp/sdpint.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#ifndef SDP_INT_H
#define SDP_INT_H
+#include "bluetooth/uuid.h"
#include "bt_target.h"
#include "l2c_api.h"
#include "osi/include/alarm.h"
@@ -65,7 +66,7 @@
#define SDP_DEVICE_NOTI_FLAG 0x03
/* Define the Protocol Data Unit (PDU) types.
-*/
+ */
#define SDP_PDU_ERROR_RESPONSE 0x01
#define SDP_PDU_SERVICE_SEARCH_REQ 0x02
#define SDP_PDU_SERVICE_SEARCH_RSP 0x03
@@ -88,7 +89,7 @@
/* Internal UUID sequence representation */
typedef struct {
uint16_t len;
- uint8_t value[MAX_UUID_SIZE];
+ uint8_t value[bluetooth::Uuid::kNumBytes128];
} tUID_ENT;
typedef struct {
@@ -230,7 +231,7 @@
#endif
/* Functions provided by sdp_conn.cc
-*/
+ */
extern void sdp_conn_rcv_l2e_conn_ind(BT_HDR* p_msg);
extern void sdp_conn_rcv_l2e_conn_cfm(BT_HDR* p_msg);
extern void sdp_conn_rcv_l2e_disc(BT_HDR* p_msg);
@@ -245,7 +246,7 @@
extern tCONN_CB* sdp_conn_originate(const RawAddress& p_bd_addr);
/* Functions provided by sdp_utils.cc
-*/
+ */
extern tCONN_CB* sdpu_find_ccb_by_cid(uint16_t cid);
extern tCONN_CB* sdpu_find_ccb_by_db(tSDP_DISCOVERY_DB* p_db);
extern tCONN_CB* sdpu_allocate_ccb(void);
@@ -267,8 +268,7 @@
extern bool sdpu_is_base_uuid(uint8_t* p_uuid);
extern bool sdpu_compare_uuid_arrays(uint8_t* p_uuid1, uint32_t len1,
uint8_t* p_uuid2, uint16_t len2);
-extern bool sdpu_compare_bt_uuids(tBT_UUID* p_uuid1, tBT_UUID* p_uuid2);
-extern bool sdpu_compare_uuid_with_attr(tBT_UUID* p_btuuid,
+extern bool sdpu_compare_uuid_with_attr(const bluetooth::Uuid& uuid,
tSDP_DISC_ATTR* p_attr);
extern void sdpu_sort_attr_list(uint16_t num_attr, tSDP_DISCOVERY_DB* p_db);
@@ -282,7 +282,7 @@
uint16_t len, uint16_t* offset);
/* Functions provided by sdp_db.cc
-*/
+ */
extern tSDP_RECORD* sdp_db_service_search(tSDP_RECORD* p_rec,
tSDP_UUID_SEQ* p_seq);
extern tSDP_RECORD* sdp_db_find_record(uint32_t handle);
@@ -291,7 +291,7 @@
uint16_t end_attr);
/* Functions provided by sdp_server.cc
-*/
+ */
#if (SDP_SERVER_ENABLED == TRUE)
extern void sdp_server_handle_client_req(tCONN_CB* p_ccb, BT_HDR* p_msg);
#else
@@ -299,7 +299,7 @@
#endif
/* Functions provided by sdp_discovery.cc
-*/
+ */
extern void sdp_disc_connected(tCONN_CB* p_ccb);
extern void sdp_disc_server_rsp(tCONN_CB* p_ccb, BT_HDR* p_msg);
diff --git a/stack/smp/p_256_curvepara.cc b/stack/smp/p_256_curvepara.cc
index d9bee31..5fb71a3 100644
--- a/stack/smp/p_256_curvepara.cc
+++ b/stack/smp/p_256_curvepara.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2015 Broadcom Corporation
+ * Copyright 2006-2015 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/smp/p_256_ecc_pp.cc b/stack/smp/p_256_ecc_pp.cc
index b416e1d..ff5dbde 100644
--- a/stack/smp/p_256_ecc_pp.cc
+++ b/stack/smp/p_256_ecc_pp.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2015 Broadcom Corporation
+ * Copyright 2006-2015 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -245,3 +245,25 @@
multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, keyLength);
multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength);
}
+
+bool ECC_ValidatePoint(const Point& pt) {
+ const size_t kl = KEY_LENGTH_DWORDS_P256;
+ p_256_init_curve(kl);
+
+ // Ensure y^2 = x^3 + a*x + b (mod p); a = -3
+
+ // y^2 mod p
+ uint32_t y2_mod[kl] = {0};
+ multiprecision_mersenns_squa_mod(y2_mod, (uint32_t*)pt.y, kl);
+
+ // Right hand side calculation
+ uint32_t rhs[kl] = {0};
+ multiprecision_mersenns_squa_mod(rhs, (uint32_t*)pt.x, kl);
+ uint32_t three[kl] = {0};
+ three[0] = 3;
+ multiprecision_sub_mod(rhs, rhs, three, kl);
+ multiprecision_mersenns_mult_mod(rhs, rhs, (uint32_t*)pt.x, kl);
+ multiprecision_add_mod(rhs, rhs, curve_p256.b, kl);
+
+ return multiprecision_compare(rhs, y2_mod, kl) == 0;
+}
diff --git a/stack/smp/p_256_ecc_pp.h b/stack/smp/p_256_ecc_pp.h
index dcc4211..b49b72a 100644
--- a/stack/smp/p_256_ecc_pp.h
+++ b/stack/smp/p_256_ecc_pp.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2015 Broadcom Corporation
+ * Copyright 2006-2015 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#pragma once
+#include <cstdbool>
#include "p_256_multprecision.h"
typedef struct {
@@ -55,6 +56,8 @@
extern elliptic_curve_t curve;
extern elliptic_curve_t curve_p256;
+bool ECC_ValidatePoint(const Point& p);
+
void ECC_PointMult_Bin_NAF(Point* q, Point* p, uint32_t* n, uint32_t keyLength);
#define ECC_PointMult(q, p, n, keyLength) \
diff --git a/stack/smp/p_256_multprecision.cc b/stack/smp/p_256_multprecision.cc
index a44ea0c..286aca1 100644
--- a/stack/smp/p_256_multprecision.cc
+++ b/stack/smp/p_256_multprecision.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2015 Broadcom Corporation
+ * Copyright 2006-2015 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/smp/p_256_multprecision.h b/stack/smp/p_256_multprecision.h
index ca5311b..fbbd88d 100644
--- a/stack/smp/p_256_multprecision.h
+++ b/stack/smp/p_256_multprecision.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2006-2015 Broadcom Corporation
+ * Copyright 2006-2015 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/smp/smp_act.cc b/stack/smp/smp_act.cc
index df9fab9..be340ec 100644
--- a/stack/smp/smp_act.cc
+++ b/stack/smp/smp_act.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,17 +19,21 @@
#include <string.h>
#include "btif_common.h"
#include "device/include/interop.h"
-#include "include/bt_target.h"
+#include "internal_include/bt_target.h"
#include "stack/btm/btm_int.h"
#include "stack/include/l2c_api.h"
+#include "stack/smp/p_256_ecc_pp.h"
#include "stack/smp/smp_int.h"
#include "utils/include/bt_utils.h"
#define SMP_KEY_DIST_TYPE_MAX 4
-const tSMP_ACT smp_distribute_act[] = {smp_generate_ltk, smp_send_id_info,
- smp_generate_csrk,
- smp_set_derive_link_key};
+const tSMP_ACT smp_distribute_act[] = {
+ smp_generate_ltk, /* SMP_SEC_KEY_TYPE_ENC - '1' bit index */
+ smp_send_id_info, /* SMP_SEC_KEY_TYPE_ID - '1' bit index */
+ smp_generate_csrk, /* SMP_SEC_KEY_TYPE_CSRK - '1' bit index */
+ smp_set_derive_link_key /* SMP_SEC_KEY_TYPE_LK - '1' bit index */
+};
static bool lmp_version_below(const RawAddress& bda, uint8_t version) {
tACL_CONN* acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE);
@@ -47,7 +51,9 @@
if (reason == SMP_PAIR_AUTH_FAIL || reason == SMP_PAIR_FAIL_UNKNOWN ||
reason == SMP_PAIR_NOT_SUPPORT || reason == SMP_PASSKEY_ENTRY_FAIL ||
reason == SMP_REPEATED_ATTEMPTS) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = reason;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return true;
}
return false;
@@ -160,15 +166,17 @@
p_cb->secure_connections_only_mode_required =
(btm_cb.security_mode == BTM_SEC_MODE_SC) ? true : false;
-
+ /* just for PTS, force SC bit */
if (p_cb->secure_connections_only_mode_required) {
p_cb->loc_auth_req |= SMP_SC_SUPPORT_BIT;
}
- if (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) ||
- lmp_version_below(p_cb->pairing_bda, HCI_PROTO_VERSION_4_2) ||
- interop_match_addr(INTEROP_DISABLE_LE_SECURE_CONNECTIONS,
- (const RawAddress*)&p_cb->pairing_bda)) {
+ if (!p_cb->secure_connections_only_mode_required &&
+ (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) ||
+ lmp_version_below(p_cb->pairing_bda, HCI_PROTO_VERSION_4_2) ||
+ interop_match_addr(INTEROP_DISABLE_LE_SECURE_CONNECTIONS,
+ (const RawAddress*)&p_cb->pairing_bda))) {
+ p_cb->loc_auth_req &= ~SMP_SC_SUPPORT_BIT;
p_cb->loc_auth_req &= ~SMP_KP_SUPPORT_BIT;
p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
@@ -219,8 +227,8 @@
* Description pairing failure to peer device if needed.
******************************************************************************/
void smp_send_pair_fail(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- p_cb->status = *(uint8_t*)p_data;
- p_cb->failure = *(uint8_t*)p_data;
+ p_cb->status = p_data->status;
+ p_cb->failure = p_data->status;
SMP_TRACE_DEBUG("%s: status=%d failure=%d ", __func__, p_cb->status,
p_cb->failure);
@@ -324,7 +332,7 @@
* Description send Keypress Notification command to the peer
******************************************************************************/
void smp_send_keypress_notification(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- p_cb->local_keypress_notification = *(uint8_t*)p_data;
+ p_cb->local_keypress_notification = p_data->status;
smp_send_cmd(SMP_OPCODE_PAIR_KEYPR_NOTIF, p_cb);
}
@@ -415,7 +423,6 @@
void smp_proc_sec_req(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
tBTM_LE_AUTH_REQ auth_req = *(tBTM_LE_AUTH_REQ*)p_data;
tBTM_BLE_SEC_REQ_ACT sec_req_act;
- uint8_t reason;
SMP_TRACE_DEBUG("%s: auth_req=0x%x", __func__, auth_req);
@@ -438,8 +445,9 @@
/* respond to non SC pairing request as failure in SC only mode */
if (p_cb->secure_connections_only_mode_required &&
(auth_req & SMP_SC_SUPPORT_BIT) == 0) {
- reason = SMP_PAIR_AUTH_FAIL;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_AUTH_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
} else {
/* initialize local i/r key to be default keys */
p_cb->peer_auth_req = auth_req;
@@ -463,7 +471,7 @@
* Description process security grant.
******************************************************************************/
void smp_proc_sec_grant(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t res = *(uint8_t*)p_data;
+ uint8_t res = p_data->status;
SMP_TRACE_DEBUG("%s", __func__);
if (res != SMP_SUCCESS) {
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, p_data);
@@ -480,7 +488,7 @@
******************************************************************************/
void smp_proc_pair_fail(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
SMP_TRACE_DEBUG("%s", __func__);
- p_cb->status = *(uint8_t*)p_data;
+ p_cb->status = p_data->status;
/* Cancel pending auth complete timer if set */
alarm_cancel(p_cb->delayed_auth_timer_ent);
@@ -491,11 +499,12 @@
* Description Process the SMP pairing request/response from peer device
******************************************************************************/
void smp_proc_pair_cmd(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
- uint8_t reason = SMP_ENC_KEY_SIZE;
+ uint8_t* p = p_data->p_data;
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_cb->pairing_bda);
- SMP_TRACE_DEBUG("%s", __func__);
+ SMP_TRACE_DEBUG("%s: pairing_bda=%s", __func__,
+ p_cb->pairing_bda.ToString().c_str());
+
/* erase all keys if it is slave proc pairing req */
if (p_dev_rec && (p_cb->role == HCI_ROLE_SLAVE))
btm_sec_clear_ble_keys(p_dev_rec);
@@ -510,8 +519,9 @@
STREAM_TO_UINT8(p_cb->peer_r_key, p);
if (smp_command_has_invalid_parameters(p_cb)) {
- reason = SMP_INVALID_PARAMETERS;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -539,8 +549,9 @@
SMP_TRACE_ERROR(
"%s: pairing failed - slave requires secure connection only mode",
__func__);
- reason = SMP_PAIR_AUTH_FAIL;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_AUTH_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -560,8 +571,9 @@
SMP_TRACE_ERROR(
"Master requires secure connection only mode "
"but it can't be provided -> Master fails pairing");
- reason = SMP_PAIR_AUTH_FAIL;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_AUTH_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -578,13 +590,14 @@
* Description process pairing confirm from peer device
******************************************************************************/
void smp_proc_confirm(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
- uint8_t reason = SMP_INVALID_PARAMETERS;
+ uint8_t* p = p_data->p_data;
SMP_TRACE_DEBUG("%s", __func__);
if (smp_command_has_invalid_parameters(p_cb)) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -601,13 +614,14 @@
* Description process pairing initializer from peer device
******************************************************************************/
void smp_proc_init(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
- uint8_t reason = SMP_INVALID_PARAMETERS;
+ uint8_t* p = p_data->p_data;
SMP_TRACE_DEBUG("%s", __func__);
if (smp_command_has_invalid_parameters(p_cb)) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -620,13 +634,14 @@
* Description process pairing random (nonce) from peer device
******************************************************************************/
void smp_proc_rand(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
- uint8_t reason = SMP_INVALID_PARAMETERS;
+ uint8_t* p = p_data->p_data;
SMP_TRACE_DEBUG("%s", __func__);
if (smp_command_has_invalid_parameters(p_cb)) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -643,18 +658,32 @@
*
******************************************************************************/
void smp_process_pairing_public_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
- uint8_t reason = SMP_INVALID_PARAMETERS;
+ uint8_t* p = p_data->p_data;
SMP_TRACE_DEBUG("%s", __func__);
if (smp_command_has_invalid_parameters(p_cb)) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
STREAM_TO_ARRAY(p_cb->peer_publ_key.x, p, BT_OCTET32_LEN);
STREAM_TO_ARRAY(p_cb->peer_publ_key.y, p, BT_OCTET32_LEN);
+
+ Point pt;
+ memcpy(pt.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN);
+ memcpy(pt.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN);
+
+ if (!ECC_ValidatePoint(pt)) {
+ android_errorWriteLog(0x534e4554, "72377774");
+ tSMP_INT_DATA smp;
+ smp.status = SMP_PAIR_AUTH_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp);
+ return;
+ }
+
p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY;
smp_wait_for_both_public_keys(p_cb, NULL);
@@ -665,13 +694,14 @@
* Description process pairing commitment from peer device
******************************************************************************/
void smp_process_pairing_commitment(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
- uint8_t reason = SMP_INVALID_PARAMETERS;
+ uint8_t* p = p_data->p_data;
SMP_TRACE_DEBUG("%s", __func__);
if (smp_command_has_invalid_parameters(p_cb)) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -687,13 +717,14 @@
* Description process DHKey Check from peer device
******************************************************************************/
void smp_process_dhkey_check(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
- uint8_t reason = SMP_INVALID_PARAMETERS;
+ uint8_t* p = p_data->p_data;
SMP_TRACE_DEBUG("%s", __func__);
if (smp_command_has_invalid_parameters(p_cb)) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -709,14 +740,15 @@
* Description process pairing keypress notification from peer device
******************************************************************************/
void smp_process_keypress_notification(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
- uint8_t reason = SMP_INVALID_PARAMETERS;
+ uint8_t* p = p_data->p_data;
SMP_TRACE_DEBUG("%s", __func__);
- p_cb->status = *(uint8_t*)p_data;
+ p_cb->status = p_data->status;
if (smp_command_has_invalid_parameters(p_cb)) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -734,15 +766,15 @@
* BR/EDR transport.
******************************************************************************/
void smp_br_process_pairing_command(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
- uint8_t reason = SMP_ENC_KEY_SIZE;
+ uint8_t* p = p_data->p_data;
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_cb->pairing_bda);
SMP_TRACE_DEBUG("%s", __func__);
/* rejecting BR pairing request over non-SC BR link */
if (!p_dev_rec->new_encryption_key_is_p256 && p_cb->role == HCI_ROLE_SLAVE) {
- reason = SMP_XTRANS_DERIVE_NOT_ALLOW;
- smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_XTRANS_DERIVE_NOT_ALLOW;
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -760,8 +792,9 @@
STREAM_TO_UINT8(p_cb->peer_r_key, p);
if (smp_command_has_invalid_parameters(p_cb)) {
- reason = SMP_INVALID_PARAMETERS;
- smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -793,9 +826,8 @@
* Description process security grant in case of pairing over BR/EDR transport.
******************************************************************************/
void smp_br_process_security_grant(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t res = *(uint8_t*)p_data;
SMP_TRACE_DEBUG("%s", __func__);
- if (res != SMP_SUCCESS) {
+ if (p_data->status != SMP_SUCCESS) {
smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, p_data);
} else {
/* otherwise, start pairing; send IO request callback */
@@ -809,8 +841,6 @@
* before starting the distribution/derivation
******************************************************************************/
void smp_br_check_authorization_request(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t reason = SMP_SUCCESS;
-
SMP_TRACE_DEBUG("%s rcvs i_keys=0x%x r_keys=0x%x (i-initiator r-responder)",
__func__, p_cb->local_i_key, p_cb->local_r_key);
@@ -844,7 +874,9 @@
if (p_cb->role == HCI_ROLE_MASTER && p_cb->local_r_key == 0)
smp_key_distribution_by_transport(p_cb, NULL);
} else {
- smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_SUCCESS;
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
}
}
@@ -854,7 +886,6 @@
* used.
******************************************************************************/
void smp_br_select_next_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t reason = SMP_SUCCESS;
SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x", __func__,
p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
@@ -866,10 +897,13 @@
if (!p_cb->local_i_key && !p_cb->local_r_key) {
/* state check to prevent re-entrance */
if (smp_get_br_state() == SMP_BR_STATE_BOND_PENDING) {
- if (p_cb->total_tx_unacked == 0)
- smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
- else
+ if (p_cb->total_tx_unacked == 0) {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_SUCCESS;
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
+ } else {
p_cb->wait_for_authorization_complete = true;
+ }
}
}
}
@@ -879,7 +913,7 @@
* Description process encryption information from peer device
******************************************************************************/
void smp_proc_enc_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
+ uint8_t* p = p_data->p_data;
SMP_TRACE_DEBUG("%s", __func__);
STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN);
@@ -891,7 +925,7 @@
* Description process master ID from slave device
******************************************************************************/
void smp_proc_master_id(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
+ uint8_t* p = p_data->p_data;
tBTM_LE_PENC_KEYS le_key;
SMP_TRACE_DEBUG("%s", __func__);
@@ -918,7 +952,7 @@
* Description process identity information from peer device
******************************************************************************/
void smp_proc_id_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
+ uint8_t* p = p_data->p_data;
SMP_TRACE_DEBUG("%s", __func__);
STREAM_TO_ARRAY(p_cb->tk, p, BT_OCTET16_LEN); /* reuse TK for IRK */
@@ -930,7 +964,7 @@
* Description process identity address from peer device
******************************************************************************/
void smp_proc_id_addr(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t* p = (uint8_t*)p_data;
+ uint8_t* p = p_data->p_data;
tBTM_LE_PID_KEYS pid_key;
SMP_TRACE_DEBUG("%s", __func__);
@@ -967,7 +1001,7 @@
le_key.sec_level = p_cb->sec_level;
/* get peer CSRK */
- maybe_non_aligned_memcpy(le_key.csrk, p_data, BT_OCTET16_LEN);
+ maybe_non_aligned_memcpy(le_key.csrk, p_data->p_data, BT_OCTET16_LEN);
/* initialize the peer counter */
le_key.counter = 0;
@@ -984,8 +1018,6 @@
* Description process compare value
******************************************************************************/
void smp_proc_compare(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t reason;
-
SMP_TRACE_DEBUG("%s", __func__);
if (!memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN)) {
/* compare the max encryption key size, and save the smaller one for the
@@ -1004,8 +1036,10 @@
}
} else {
- reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
+ p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
}
}
@@ -1033,7 +1067,6 @@
******************************************************************************/
void smp_start_enc(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
tBTM_STATUS cmd;
- uint8_t reason = SMP_ENC_FAIL;
SMP_TRACE_DEBUG("%s", __func__);
if (p_data != NULL)
@@ -1041,8 +1074,11 @@
else
cmd = btm_ble_start_encrypt(p_cb->pairing_bda, false, NULL);
- if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY)
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY) {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_ENC_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+ }
}
/*******************************************************************************
@@ -1060,11 +1096,12 @@
* Description encryption success
******************************************************************************/
void smp_enc_cmpl(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t enc_enable = *(uint8_t*)p_data;
- uint8_t reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+ uint8_t enc_enable = p_data->status;
SMP_TRACE_DEBUG("%s", __func__);
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
}
/*******************************************************************************
@@ -1072,8 +1109,7 @@
* Description check authentication request
******************************************************************************/
void smp_check_auth_req(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t enc_enable = *(uint8_t*)p_data;
- uint8_t reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+ uint8_t enc_enable = p_data->status;
SMP_TRACE_DEBUG(
"%s rcvs enc_enable=%d i_keys=0x%x r_keys=0x%x (i-initiator r-responder)",
@@ -1110,16 +1146,21 @@
(p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
(p_cb->local_i_key || p_cb->local_r_key)) {
smp_sm_event(p_cb, SMP_BOND_REQ_EVT, NULL);
- } else
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ } else {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+ }
} else if (enc_enable == 0) {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
/* if failed for encryption after pairing, send callback */
if (p_cb->flags & SMP_PAIR_FLAG_ENC_AFTER_PAIR)
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
/* if enc failed for old security information */
/* if master device, clean up and abck to idle; slave device do nothing */
else if (p_cb->role == HCI_ROLE_MASTER) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
}
}
}
@@ -1194,10 +1235,8 @@
*
******************************************************************************/
void smp_decide_association_model(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t failure = SMP_UNKNOWN_IO_CAP;
uint8_t int_evt = 0;
- tSMP_KEY key;
- tSMP_INT_DATA* p = NULL;
+ tSMP_INT_DATA smp_int_data;
SMP_TRACE_DEBUG("%s Association Model = %d", __func__,
p_cb->selected_association_model);
@@ -1209,17 +1248,17 @@
((p_cb->loc_auth_req & SMP_AUTH_YN_BIT) == 0)) {
SMP_TRACE_ERROR(
"IO capability does not meet authentication requirement");
- failure = SMP_PAIR_AUTH_FAIL;
- p = (tSMP_INT_DATA*)&failure;
+ smp_int_data.status = SMP_PAIR_AUTH_FAIL;
int_evt = SMP_AUTH_CMPL_EVT;
} else {
p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
SMP_TRACE_EVENT("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) ",
p_cb->sec_level);
+ tSMP_KEY key;
key.key_type = SMP_KEY_TYPE_TK;
key.p_data = p_cb->tk;
- p = (tSMP_INT_DATA*)&key;
+ smp_int_data.key = key;
memset(p_cb->tk, 0, BT_OCTET16_LEN);
/* TK, ready */
@@ -1264,7 +1303,7 @@
case SMP_MODEL_OUT_OF_RANGE:
SMP_TRACE_ERROR("Association Model = SMP_MODEL_OUT_OF_RANGE (failed)");
- p = (tSMP_INT_DATA*)&failure;
+ smp_int_data.status = SMP_UNKNOWN_IO_CAP;
int_evt = SMP_AUTH_CMPL_EVT;
break;
@@ -1272,12 +1311,12 @@
SMP_TRACE_ERROR(
"Association Model = %d (SOMETHING IS WRONG WITH THE CODE)",
p_cb->selected_association_model);
- p = (tSMP_INT_DATA*)&failure;
+ smp_int_data.status = SMP_UNKNOWN_IO_CAP;
int_evt = SMP_AUTH_CMPL_EVT;
}
SMP_TRACE_EVENT("sec_level=%d ", p_cb->sec_level);
- if (int_evt) smp_sm_event(p_cb, int_evt, p);
+ if (int_evt) smp_sm_event(p_cb, int_evt, &smp_int_data);
}
/*******************************************************************************
@@ -1285,7 +1324,6 @@
* Description process IO response for a slave device.
******************************************************************************/
void smp_process_io_response(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t reason = SMP_PAIR_AUTH_FAIL;
SMP_TRACE_DEBUG("%s", __func__);
if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
@@ -1303,7 +1341,9 @@
SMP_TRACE_ERROR(
"Slave requires secure connection only mode "
"but it can't be provided -> Slave fails pairing");
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_AUTH_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -1528,15 +1568,15 @@
* Note It is supposed to be called in SC phase1.
******************************************************************************/
void smp_process_peer_nonce(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t reason;
-
SMP_TRACE_DEBUG("%s start ", __func__);
// PTS Testing failure modes
if (p_cb->cert_failure == SMP_CONFIRM_VALUE_ERR) {
SMP_TRACE_ERROR("%s failure case = %d", __func__, p_cb->cert_failure);
- reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
+ p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
// PTS Testing failure modes (for LT)
@@ -1544,8 +1584,10 @@
(p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS) &&
(p_cb->role == HCI_ROLE_SLAVE)) {
SMP_TRACE_ERROR("%s failure case = %d", __func__, p_cb->cert_failure);
- reason = p_cb->failure = SMP_NUMERIC_COMPAR_FAIL;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL;
+ p_cb->failure = SMP_NUMERIC_COMPAR_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -1555,8 +1597,10 @@
/* in these models only master receives commitment */
if (p_cb->role == HCI_ROLE_MASTER) {
if (!smp_check_commitment(p_cb)) {
- reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
+ p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
break;
}
} else {
@@ -1577,8 +1621,10 @@
case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
if (!smp_check_commitment(p_cb) &&
p_cb->cert_failure != SMP_NUMERIC_COMPAR_FAIL) {
- reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
+ p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
break;
}
@@ -1617,14 +1663,15 @@
* received from the peer DHKey check value.
******************************************************************************/
void smp_match_dhkey_checks(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- uint8_t reason = SMP_DHKEY_CHK_FAIL;
SMP_TRACE_DEBUG("%s", __func__);
if (memcmp(p_data->key.p_data, p_cb->remote_dhkey_check, BT_OCTET16_LEN)) {
SMP_TRACE_WARNING("dhkey chcks do no match");
- p_cb->failure = reason;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_DHKEY_CHK_FAIL;
+ p_cb->failure = SMP_DHKEY_CHK_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -1741,11 +1788,12 @@
memcpy(p_cb->remote_commitment, p_sc_oob_data->peer_oob_data.commitment,
sizeof(p_cb->remote_commitment));
- uint8_t reason = SMP_CONFIRM_VALUE_ERR;
/* check commitment */
if (!smp_check_commitment(p_cb)) {
- p_cb->failure = reason;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
+ p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -1847,7 +1895,9 @@
btm_ble_update_sec_key_size(bda, p_cb->loc_enc_size);
}
- smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = encr_enable;
+ smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &smp_int_data);
}
}
@@ -1938,7 +1988,9 @@
SMP_TRACE_DEBUG("%s", __func__);
if (!smp_calculate_link_key_from_long_term_key(p_cb)) {
SMP_TRACE_ERROR("%s failed", __func__);
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = status;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
}
@@ -1960,10 +2012,20 @@
SMP_TRACE_DEBUG("%s", __func__);
if (!smp_calculate_long_term_key_from_link_key(p_cb)) {
SMP_TRACE_ERROR("%s: failed", __func__);
- smp_sm_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = status;
+ smp_sm_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
return;
}
+ tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_cb->pairing_bda);
+ if (p_dev_rec) {
+ SMP_TRACE_DEBUG("%s: dev_type = %d ", __func__, p_dev_rec->device_type);
+ p_dev_rec->device_type |= BT_DEVICE_TYPE_BLE;
+ } else {
+ SMP_TRACE_ERROR("%s failed to find Security Record", __func__);
+ }
+
SMP_TRACE_DEBUG("%s: LTK derivation from LK successfully completed",
__func__);
smp_save_secure_connections_long_term_key(p_cb);
diff --git a/stack/smp/smp_api.cc b/stack/smp/smp_api.cc
index f6a87dd..d096da5 100644
--- a/stack/smp/smp_api.cc
+++ b/stack/smp/smp_api.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2012 Broadcom Corporation
+ * Copyright 2008-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -132,10 +132,11 @@
******************************************************************************/
tSMP_STATUS SMP_Pair(const RawAddress& bd_addr) {
tSMP_CB* p_cb = &smp_cb;
- uint8_t status = SMP_PAIR_INTERNAL_ERR;
- SMP_TRACE_EVENT("%s state=%d br_state=%d flag=0x%x ", __func__, p_cb->state,
- p_cb->br_state, p_cb->flags);
+ SMP_TRACE_EVENT("%s: state=%d br_state=%d flag=0x%x, bd_addr=%s", __func__,
+ p_cb->state, p_cb->br_state, p_cb->flags,
+ bd_addr.ToString().c_str());
+
if (p_cb->state != SMP_STATE_IDLE ||
p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD || p_cb->smp_over_br) {
/* pending security on going, reject this one */
@@ -145,9 +146,11 @@
p_cb->pairing_bda = bd_addr;
if (!L2CA_ConnectFixedChnl(L2CAP_SMP_CID, bd_addr)) {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_INTERNAL_ERR;
SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __func__);
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
- return status;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+ return SMP_PAIR_INTERNAL_ERR;
}
return SMP_STARTED;
@@ -169,10 +172,10 @@
******************************************************************************/
tSMP_STATUS SMP_BR_PairWith(const RawAddress& bd_addr) {
tSMP_CB* p_cb = &smp_cb;
- uint8_t status = SMP_PAIR_INTERNAL_ERR;
- SMP_TRACE_EVENT("%s state=%d br_state=%d flag=0x%x ", __func__, p_cb->state,
- p_cb->br_state, p_cb->flags);
+ SMP_TRACE_EVENT("%s: state=%d br_state=%d flag=0x%x, bd_addr=%s", __func__,
+ p_cb->state, p_cb->br_state, p_cb->flags,
+ bd_addr.ToString().c_str());
if (p_cb->state != SMP_STATE_IDLE || p_cb->smp_over_br ||
p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
@@ -187,8 +190,10 @@
if (!L2CA_ConnectFixedChnl(L2CAP_SMP_BR_CID, bd_addr)) {
SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __func__);
- smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
- return status;
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_INTERNAL_ERR;
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
+ return SMP_PAIR_INTERNAL_ERR;
}
return SMP_STARTED;
@@ -208,7 +213,6 @@
bool SMP_PairCancel(const RawAddress& bd_addr) {
tSMP_CB* p_cb = &smp_cb;
uint8_t err_code = SMP_PAIR_FAIL_UNKNOWN;
- bool status = false;
// PTS SMP failure test cases
if (p_cb->cert_failure == SMP_PASSKEY_ENTRY_FAIL ||
@@ -220,11 +224,13 @@
if (p_cb->state != SMP_STATE_IDLE && p_cb->pairing_bda == bd_addr) {
p_cb->is_pair_cancel = true;
SMP_TRACE_DEBUG("Cancel Pairing: set fail reason Unknown");
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &err_code);
- status = true;
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+ return true;
}
- return status;
+ return false;
}
/*******************************************************************************
*
@@ -252,7 +258,10 @@
/* clear the SMP_SEC_REQUEST_EVT event after get grant */
/* avoid generating duplicate pair request */
smp_cb.cb_evt = 0;
- smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT, &res);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = res;
+ smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT,
+ &smp_int_data);
return;
}
@@ -262,7 +271,9 @@
/* clear the SMP_SEC_REQUEST_EVT event after get grant */
/* avoid generate duplicate pair request */
smp_cb.cb_evt = 0;
- smp_sm_event(&smp_cb, SMP_API_SEC_GRANT_EVT, &res);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = res;
+ smp_sm_event(&smp_cb, SMP_API_SEC_GRANT_EVT, &smp_int_data);
}
/*******************************************************************************
@@ -283,7 +294,6 @@
void SMP_PasskeyReply(const RawAddress& bd_addr, uint8_t res,
uint32_t passkey) {
tSMP_CB* p_cb = &smp_cb;
- uint8_t failure = SMP_PASSKEY_ENTRY_FAIL;
SMP_TRACE_EVENT("SMP_PasskeyReply: Key: %d Result:%d", passkey, res);
@@ -308,11 +318,15 @@
"SMP_PasskeyReply() - Wrong key len: %d or passkey entry fail",
passkey);
/* send pairing failure */
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PASSKEY_ENTRY_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
} else if (p_cb->selected_association_model ==
SMP_MODEL_SEC_CONN_PASSKEY_ENT) {
- smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &passkey);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.passkey = passkey;
+ smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &smp_int_data);
} else {
smp_convert_string_to_tk(p_cb->tk, passkey);
}
@@ -334,7 +348,6 @@
******************************************************************************/
void SMP_ConfirmReply(const RawAddress& bd_addr, uint8_t res) {
tSMP_CB* p_cb = &smp_cb;
- uint8_t failure = SMP_NUMERIC_COMPAR_FAIL;
SMP_TRACE_EVENT("%s: Result:%d", __func__, res);
@@ -357,7 +370,9 @@
if (res != SMP_SUCCESS) {
SMP_TRACE_WARNING("%s() - Numeric Comparison fails", __func__);
/* send pairing failure */
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
} else {
smp_sm_event(p_cb, SMP_SC_NC_OK_EVT, NULL);
}
@@ -378,7 +393,6 @@
void SMP_OobDataReply(const RawAddress& bd_addr, tSMP_STATUS res, uint8_t len,
uint8_t* p_data) {
tSMP_CB* p_cb = &smp_cb;
- uint8_t failure = SMP_OOB_FAIL;
tSMP_KEY key;
SMP_TRACE_EVENT("%s State: %d res:%d", __func__, smp_cb.state, res);
@@ -388,7 +402,9 @@
return;
if (res != SMP_SUCCESS || len == 0 || !p_data) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_OOB_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
} else {
if (len > BT_OCTET16_LEN) len = BT_OCTET16_LEN;
@@ -397,7 +413,9 @@
key.key_type = SMP_KEY_TYPE_TK;
key.p_data = p_cb->tk;
- smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &key);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.key = key;
+ smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &smp_int_data);
}
}
@@ -414,11 +432,12 @@
void SMP_SecureConnectionOobDataReply(uint8_t* p_data) {
tSMP_CB* p_cb = &smp_cb;
- uint8_t failure = SMP_OOB_FAIL;
tSMP_SC_OOB_DATA* p_oob = (tSMP_SC_OOB_DATA*)p_data;
if (!p_oob) {
SMP_TRACE_ERROR("%s received no data", __func__);
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_OOB_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -450,14 +469,17 @@
break;
}
+ tSMP_INT_DATA smp_int_data;
if (data_missing) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ smp_int_data.status = SMP_OOB_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
p_cb->sc_oob_data = *p_oob;
- smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, p_data);
+ smp_int_data.p_data = p_data;
+ smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, &smp_int_data);
}
/*******************************************************************************
@@ -526,7 +548,9 @@
return;
}
- smp_sm_event(p_cb, SMP_KEYPRESS_NOTIFICATION_EVENT, &value);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = value;
+ smp_sm_event(p_cb, SMP_KEYPRESS_NOTIFICATION_EVENT, &smp_int_data);
}
/*******************************************************************************
diff --git a/stack/smp/smp_br_main.cc b/stack/smp/smp_br_main.cc
index 55405cc..b06055f 100644
--- a/stack/smp/smp_br_main.cc
+++ b/stack/smp/smp_br_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014-2015 Broadcom Corporation
+ * Copyright 2014-2015 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -72,23 +72,25 @@
SMP_BR_SM_NO_ACTION
};
-static const tSMP_ACT smp_br_sm_action[] = {smp_send_pair_req,
- smp_br_send_pair_response,
- smp_send_pair_fail,
- smp_send_id_info,
- smp_br_process_pairing_command,
- smp_proc_pair_fail,
- smp_proc_id_info,
- smp_proc_id_addr,
- smp_proc_srk_info,
- smp_br_process_security_grant,
- smp_br_process_slave_keys_response,
- smp_br_select_next_key,
- smp_br_pairing_complete,
- smp_send_app_cback,
- smp_br_check_authorization_request,
- smp_pair_terminate,
- smp_idle_terminate};
+static const tSMP_ACT smp_br_sm_action[] = {
+ smp_send_pair_req, /* SMP_SEND_PAIR_REQ */
+ smp_br_send_pair_response, /* SMP_BR_SEND_PAIR_RSP */
+ smp_send_pair_fail, /* SMP_SEND_PAIR_FAIL */
+ smp_send_id_info, /* SMP_SEND_ID_INFO */
+ smp_br_process_pairing_command, /* SMP_BR_PROC_PAIR_CMD */
+ smp_proc_pair_fail, /* SMP_PROC_PAIR_FAIL */
+ smp_proc_id_info, /* SMP_PROC_ID_INFO */
+ smp_proc_id_addr, /* SMP_PROC_ID_ADDR */
+ smp_proc_srk_info, /* SMP_PROC_SRK_INFO */
+ smp_br_process_security_grant, /* SMP_BR_PROC_SEC_GRANT */
+ smp_br_process_slave_keys_response, /* SMP_BR_PROC_SL_KEYS_RSP */
+ smp_br_select_next_key, /* SMP_BR_KEY_DISTRIBUTION */
+ smp_br_pairing_complete, /* SMP_BR_PAIRING_COMPLETE */
+ smp_send_app_cback, /* SMP_SEND_APP_CBACK */
+ smp_br_check_authorization_request, /* SMP_BR_CHECK_AUTH_REQ */
+ smp_pair_terminate, /* SMP_PAIR_TERMINATE */
+ smp_idle_terminate /* SMP_IDLE_TERMINATE */
+};
static const uint8_t smp_br_all_table[][SMP_BR_SM_NUM_COLS] = {
/* Event Action Next State */
@@ -297,7 +299,7 @@
*
******************************************************************************/
void smp_br_state_machine_event(tSMP_CB* p_cb, tSMP_BR_EVENT event,
- void* p_data) {
+ tSMP_INT_DATA* p_data) {
tSMP_BR_STATE curr_state = p_cb->br_state;
tSMP_BR_SM_TBL state_table;
uint8_t action, entry;
@@ -350,7 +352,7 @@
for (uint8_t i = 0; i < SMP_BR_NUM_ACTIONS; i++) {
action = state_table[entry - 1][i];
if (action != SMP_BR_SM_NO_ACTION) {
- (*smp_br_sm_action[action])(p_cb, (tSMP_INT_DATA*)p_data);
+ (*smp_br_sm_action[action])(p_cb, p_data);
} else {
break;
}
diff --git a/stack/smp/smp_cmac.cc b/stack/smp/smp_cmac.cc
index 876c420..42f91a0 100644
--- a/stack/smp/smp_cmac.cc
+++ b/stack/smp/smp_cmac.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2012 Broadcom Corporation
+ * Copyright 2008-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index fc8717f..1685ffe 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -221,6 +221,7 @@
typedef union {
uint8_t* p_data; /* uint8_t type data pointer */
tSMP_KEY key;
+ uint8_t status;
uint16_t reason;
uint32_t passkey;
tSMP_OOB_DATA_TYPE req_oob_type;
@@ -341,7 +342,8 @@
extern void smp_init(void);
/* smp main */
-extern void smp_sm_event(tSMP_CB* p_cb, tSMP_EVENT event, void* p_data);
+extern void smp_sm_event(tSMP_CB* p_cb, tSMP_EVENT event,
+ tSMP_INT_DATA* p_data);
extern void smp_proc_sec_request(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
extern void smp_set_fail_nc(bool enable);
@@ -366,14 +368,12 @@
extern void smp_f6_calc_chk(uint8_t* w, uint8_t* n1, uint8_t* n2, uint8_t* r,
uint8_t* iocap, uint8_t* a1, uint8_t* a2,
uint8_t* mac);
-/* smp_main */
-extern void smp_sm_event(tSMP_CB* p_cb, tSMP_EVENT event, void* p_data);
extern tSMP_STATE smp_get_state(void);
extern void smp_set_state(tSMP_STATE state);
/* smp_br_main */
extern void smp_br_state_machine_event(tSMP_CB* p_cb, tSMP_BR_EVENT event,
- void* p_data);
+ tSMP_INT_DATA* p_data);
extern tSMP_BR_STATE smp_get_br_state(void);
extern void smp_set_br_state(tSMP_BR_STATE state);
diff --git a/stack/smp/smp_keys.cc b/stack/smp/smp_keys.cc
index 06e4d87..6be1da4 100644
--- a/stack/smp/smp_keys.cc
+++ b/stack/smp/smp_keys.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -172,7 +172,6 @@
******************************************************************************/
void smp_proc_passkey(tSMP_CB* p_cb, BT_OCTET8 rand) {
uint8_t* tt = p_cb->tk;
- tSMP_KEY key;
uint32_t passkey; /* 19655 test number; */
uint8_t* pp = rand;
@@ -187,18 +186,24 @@
memset(p_cb->tk, 0, BT_OCTET16_LEN);
UINT32_TO_STREAM(tt, passkey);
- key.key_type = SMP_KEY_TYPE_TK;
- key.p_data = p_cb->tk;
-
if (p_cb->p_callback) {
+ tSMP_EVT_DATA smp_evt_data;
+ smp_evt_data.passkey = passkey;
(*p_cb->p_callback)(SMP_PASSKEY_NOTIF_EVT, p_cb->pairing_bda,
- (tSMP_EVT_DATA*)&passkey);
+ &smp_evt_data);
}
if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_DISP) {
- smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &passkey);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.passkey = passkey;
+ smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &smp_int_data);
} else {
- smp_sm_event(p_cb, SMP_KEY_READY_EVT, (tSMP_INT_DATA*)&key);
+ tSMP_KEY key;
+ key.key_type = SMP_KEY_TYPE_TK;
+ key.p_data = p_cb->tk;
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.key = key;
+ smp_sm_event(p_cb, SMP_KEY_READY_EVT, &smp_int_data);
}
}
@@ -230,7 +235,6 @@
******************************************************************************/
void smp_generate_stk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
tSMP_ENC output;
- tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
SMP_TRACE_DEBUG("%s", __func__);
@@ -242,7 +246,9 @@
memcpy(output.param_buf, p_cb->ltk, SMP_ENCRYT_DATA_SIZE);
} else if (!smp_calculate_legacy_short_term_key(p_cb, &output)) {
SMP_TRACE_ERROR("%s failed", __func__);
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
@@ -258,7 +264,6 @@
uint16_t r = 1;
uint8_t* p = buffer;
tSMP_ENC output;
- tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
p_cb->div = div;
@@ -270,10 +275,12 @@
if (!SMP_Encrypt(er, BT_OCTET16_LEN, buffer, 4, &output)) {
SMP_TRACE_ERROR("smp_generate_csrk failed");
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
if (p_cb->smp_over_br) {
- smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
} else {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
}
} else {
memcpy((void*)p_cb->csrk, output.param_buf, BT_OCTET16_LEN);
@@ -481,7 +488,9 @@
tSMP_ENC output;
tSMP_STATUS status = smp_calculate_comfirm(p_cb, p_cb->rand, &output);
if (status != SMP_SUCCESS) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = status;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
tSMP_KEY key;
@@ -490,7 +499,9 @@
16);
key.key_type = SMP_KEY_TYPE_CFM;
key.p_data = output.param_buf;
- smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.key = key;
+ smp_sm_event(p_cb, SMP_KEY_READY_EVT, &smp_int_data);
}
/*******************************************************************************
@@ -541,7 +552,9 @@
tSMP_ENC output;
tSMP_STATUS status = smp_calculate_comfirm(p_cb, p_cb->rrand, &output);
if (status != SMP_SUCCESS) {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = status;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
tSMP_KEY key;
@@ -549,7 +562,9 @@
"Remote Confirm generated", 16);
key.key_type = SMP_KEY_TYPE_CMP;
key.p_data = output.param_buf;
- smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.key = key;
+ smp_sm_event(p_cb, SMP_KEY_READY_EVT, &smp_int_data);
}
/*******************************************************************************
@@ -574,7 +589,9 @@
key.key_type = SMP_KEY_TYPE_STK;
key.p_data = p->param_buf;
- smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.key = key;
+ smp_sm_event(p_cb, SMP_KEY_READY_EVT, &smp_int_data);
}
/**
@@ -595,7 +612,9 @@
key.key_type = SMP_KEY_TYPE_LTK;
key.p_data = p->param_buf;
- smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.key = key;
+ smp_sm_event(p_cb, SMP_KEY_READY_EVT, &smp_int_data);
}
/**
@@ -611,8 +630,9 @@
tSMP_ENC output;
if (!SMP_Encrypt(dhk, BT_OCTET16_LEN, rand, BT_OCTET8_LEN, &output)) {
SMP_TRACE_ERROR("%s failed", __func__);
- tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
} else {
smp_process_ediv(p_cb, &output);
}
@@ -633,8 +653,9 @@
if (!SMP_Encrypt(er, BT_OCTET16_LEN, (uint8_t*)&p_cb->div, sizeof(uint16_t),
&output)) {
SMP_TRACE_ERROR("%s failed", __func__);
- tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
} else {
/* mask the LTK */
smp_mask_enc_key(p_cb->loc_enc_size, output.param_buf);
@@ -1052,16 +1073,19 @@
}
if (p_cb->number_to_display >= (BTM_MAX_PASSKEY_VAL + 1)) {
- uint8_t reason;
- reason = p_cb->failure = SMP_PAIR_FAIL_UNKNOWN;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
+ p_cb->failure = SMP_PAIR_FAIL_UNKNOWN;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
return;
}
SMP_TRACE_EVENT("Number to display in numeric comparison = %d",
p_cb->number_to_display);
p_cb->cb_evt = SMP_NC_REQ_EVT;
- smp_sm_event(p_cb, SMP_SC_DSPL_NC_EVT, &p_cb->number_to_display);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.passkey = p_cb->number_to_display;
+ smp_sm_event(p_cb, SMP_SC_DSPL_NC_EVT, &smp_int_data);
return;
}
@@ -1503,7 +1527,6 @@
BT_OCTET16 param_buf;
bool ret;
tSMP_KEY key;
- tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
SMP_TRACE_DEBUG("%s", __func__);
@@ -1522,10 +1545,14 @@
#endif
key.key_type = SMP_KEY_TYPE_PEER_DHK_CHCK;
key.p_data = param_buf;
- smp_sm_event(p_cb, SMP_SC_KEY_READY_EVT, &key);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.key = key;
+ smp_sm_event(p_cb, SMP_SC_KEY_READY_EVT, &smp_int_data);
} else {
SMP_TRACE_EVENT("peer DHKey check calculation failed");
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
}
}
diff --git a/stack/smp/smp_l2c.cc b/stack/smp/smp_l2c.cc
index 6111f10..1e0cb71 100644
--- a/stack/smp/smp_l2c.cc
+++ b/stack/smp/smp_l2c.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -94,7 +94,9 @@
tSMP_CB* p_cb = &smp_cb;
tSMP_INT_DATA int_data;
- SMP_TRACE_EVENT("SMDBG l2c %s", __func__);
+ SMP_TRACE_EVENT("%s: SMDBG l2c: bd_addr=%s, p_cb->pairing_bda=%s", __func__,
+ bd_addr.ToString().c_str(),
+ p_cb->pairing_bda.ToString().c_str());
if (transport == BT_TRANSPORT_BR_EDR || bd_addr.IsEmpty()) return;
@@ -138,10 +140,11 @@
tSMP_CB* p_cb = &smp_cb;
uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
uint8_t cmd;
- SMP_TRACE_EVENT("SMDBG l2c %s", __func__);
STREAM_TO_UINT8(cmd, p);
+ SMP_TRACE_EVENT("%s: SMDBG l2c, cmd=0x%x", __func__, cmd);
+
/* sanity check */
if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd)) {
SMP_TRACE_WARNING("Ignore received command with RESERVED code 0x%02x", cmd);
@@ -183,7 +186,9 @@
p_cb->rcvd_cmd_code = cmd;
p_cb->rcvd_cmd_len = (uint8_t)p_buf->len;
- smp_sm_event(p_cb, cmd, p);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.p_data = p;
+ smp_sm_event(p_cb, cmd, &smp_int_data);
}
osi_free(p_buf);
@@ -204,12 +209,14 @@
else
SMP_TRACE_ERROR("Unexpected %s: num_pkt = %d", __func__, num_pkt);
- uint8_t reason = SMP_SUCCESS;
if (p_cb->total_tx_unacked == 0 && p_cb->wait_for_authorization_complete) {
- if (cid == L2CAP_SMP_CID)
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
- else
- smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_SUCCESS;
+ if (cid == L2CAP_SMP_CID) {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+ } else {
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
+ }
}
}
@@ -236,11 +243,12 @@
return;
}
- if (bd_addr != p_cb->pairing_bda) return;
-
VLOG(1) << __func__ << " for pairing BDA: " << bd_addr
+ << ", pairing_bda:" << p_cb->pairing_bda
<< " Event: " << ((connected) ? "connected" : "disconnected");
+ if (bd_addr != p_cb->pairing_bda) return;
+
if (connected) {
if (!p_cb->connect_initialized) {
p_cb->connect_initialized = true;
@@ -304,7 +312,9 @@
p_cb->rcvd_cmd_code = cmd;
p_cb->rcvd_cmd_len = (uint8_t)p_buf->len;
- smp_br_state_machine_event(p_cb, cmd, p);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.p_data = p;
+ smp_br_state_machine_event(p_cb, cmd, &smp_int_data);
}
osi_free(p_buf);
diff --git a/stack/smp/smp_main.cc b/stack/smp/smp_main.cc
index 49e2ece..9c4334a 100644
--- a/stack/smp/smp_main.cc
+++ b/stack/smp/smp_main.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -951,7 +951,7 @@
* Returns void.
*
******************************************************************************/
-void smp_sm_event(tSMP_CB* p_cb, tSMP_EVENT event, void* p_data) {
+void smp_sm_event(tSMP_CB* p_cb, tSMP_EVENT event, tSMP_INT_DATA* p_data) {
uint8_t curr_state = p_cb->state;
tSMP_SM_TBL state_table;
uint8_t action, entry, i;
@@ -1005,7 +1005,7 @@
for (i = 0; i < SMP_NUM_ACTIONS; i++) {
action = state_table[entry - 1][i];
if (action != SMP_SM_NO_ACTION) {
- (*smp_sm_action[action])(p_cb, (tSMP_INT_DATA*)p_data);
+ (*smp_sm_action[action])(p_cb, p_data);
} else {
break;
}
diff --git a/stack/smp/smp_utils.cc b/stack/smp/smp_utils.cc
index 8bdce6b..2bd0b24 100644
--- a/stack/smp/smp_utils.cc
+++ b/stack/smp/smp_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -315,8 +315,7 @@
l2cap_ret = L2CA_SendFixedChnlData(fixed_cid, rem_bda, p_toL2CAP);
if (l2cap_ret == L2CAP_DW_FAILED) {
smp_cb.total_tx_unacked -= 1;
- SMP_TRACE_ERROR("SMP failed to pass msg:0x%0x to L2CAP",
- *((uint8_t*)(p_toL2CAP + 1) + p_toL2CAP->offset));
+ SMP_TRACE_ERROR("SMP failed to pass msg to L2CAP");
return false;
} else
return true;
@@ -332,8 +331,10 @@
bool smp_send_cmd(uint8_t cmd_code, tSMP_CB* p_cb) {
BT_HDR* p_buf;
bool sent = false;
- uint8_t failure = SMP_PAIR_INTERNAL_ERR;
- SMP_TRACE_EVENT("smp_send_cmd on l2cap cmd_code=0x%x", cmd_code);
+
+ SMP_TRACE_EVENT("%s: on l2cap cmd_code=0x%x, pairing_bda=%s", __func__,
+ cmd_code, p_cb->pairing_bda.ToString().c_str());
+
if (cmd_code <= (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */) &&
smp_cmd_build_act[cmd_code] != NULL) {
p_buf = (*smp_cmd_build_act[cmd_code])(cmd_code, p_cb);
@@ -346,10 +347,12 @@
}
if (!sent) {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_PAIR_INTERNAL_ERR;
if (p_cb->smp_over_br) {
- smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &failure);
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
} else {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
}
}
return sent;
@@ -366,15 +369,16 @@
******************************************************************************/
void smp_rsp_timeout(UNUSED_ATTR void* data) {
tSMP_CB* p_cb = &smp_cb;
- uint8_t failure = SMP_RSP_TIMEOUT;
SMP_TRACE_EVENT("%s state:%d br_state:%d", __func__, p_cb->state,
p_cb->br_state);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_RSP_TIMEOUT;
if (p_cb->smp_over_br) {
- smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &failure);
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
} else {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
}
}
@@ -394,9 +398,10 @@
* the state is still in bond pending.
*/
if (smp_get_state() == SMP_STATE_BOND_PENDING) {
- uint8_t reason = SMP_SUCCESS;
SMP_TRACE_EVENT("%s sending delayed auth complete.", __func__);
- smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &reason);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_SUCCESS;
+ smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
}
}
@@ -788,7 +793,9 @@
key.key_type = SMP_KEY_TYPE_TK;
key.p_data = tk;
- smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &key);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.key = key;
+ smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &smp_int_data);
}
/*******************************************************************************
@@ -916,7 +923,8 @@
tSMP_EVT_DATA evt_data = {0};
tSMP_CALLBACK* p_callback = p_cb->p_callback;
- SMP_TRACE_DEBUG("smp_proc_pairing_cmpl ");
+ SMP_TRACE_DEBUG("%s: pairing_bda=%s", __func__,
+ p_cb->pairing_bda.ToString().c_str());
evt_data.cmplt.reason = p_cb->status;
evt_data.cmplt.smp_over_br = p_cb->smp_over_br;
@@ -1523,7 +1531,9 @@
p_cb->req_oob_type = req_oob_type;
p_cb->cb_evt = SMP_SC_OOB_REQ_EVT;
- smp_sm_event(p_cb, SMP_TK_REQ_EVT, &req_oob_type);
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.req_oob_type = req_oob_type;
+ smp_sm_event(p_cb, SMP_TK_REQ_EVT, &smp_int_data);
return true;
}
diff --git a/stack/srvc/srvc_battery.cc b/stack/srvc/srvc_battery.cc
index 2d9fe18..8b5d93e 100644
--- a/stack/srvc/srvc_battery.cc
+++ b/stack/srvc/srvc_battery.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2013 Broadcom Corporation
+ * Copyright 1999-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
#include "bt_target.h"
#include "bt_utils.h"
-#include "btcore/include/uuid.h"
#include "gatt_api.h"
#include "gatt_int.h"
#include "osi/include/osi.h"
@@ -185,13 +184,13 @@
btgatt_db_element_t service[BA_MAX_ATTR_NUM] = {};
- bt_uuid_t service_uuid;
- uuid_128_from_16(&service_uuid, UUID_SERVCLASS_BATTERY);
+ bluetooth::Uuid service_uuid =
+ bluetooth::Uuid::From16Bit(UUID_SERVCLASS_BATTERY);
service[0].type = /* p_reg_info->is_pri */ BTGATT_DB_PRIMARY_SERVICE;
service[0].uuid = service_uuid;
- bt_uuid_t char_uuid;
- uuid_128_from_16(&char_uuid, GATT_UUID_BATTERY_LEVEL);
+ bluetooth::Uuid char_uuid =
+ bluetooth::Uuid::From16Bit(GATT_UUID_BATTERY_LEVEL);
service[1].type = BTGATT_DB_CHARACTERISTIC;
service[1].uuid = char_uuid;
service[1].properties = GATT_CHAR_PROP_BIT_READ;
@@ -200,8 +199,8 @@
int i = 2;
if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) {
- bt_uuid_t desc_uuid;
- uuid_128_from_16(&desc_uuid, GATT_UUID_CHAR_CLIENT_CONFIG);
+ bluetooth::Uuid desc_uuid =
+ bluetooth::Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG);
service[i].type = BTGATT_DB_DESCRIPTOR;
service[i].uuid = desc_uuid;
@@ -211,8 +210,8 @@
/* need presentation format descriptor? */
if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) {
- bt_uuid_t desc_uuid;
- uuid_128_from_16(&desc_uuid, GATT_UUID_CHAR_PRESENT_FORMAT);
+ bluetooth::Uuid desc_uuid =
+ bluetooth::Uuid::From16Bit(GATT_UUID_CHAR_PRESENT_FORMAT);
service[i].type = BTGATT_DB_DESCRIPTOR;
service[i].uuid = desc_uuid;
@@ -222,8 +221,8 @@
/* need presentation format descriptor? */
if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) {
- bt_uuid_t desc_uuid;
- uuid_128_from_16(&desc_uuid, GATT_UUID_RPT_REF_DESCR);
+ bluetooth::Uuid desc_uuid =
+ bluetooth::Uuid::From16Bit(GATT_UUID_RPT_REF_DESCR);
service[i].type = BTGATT_DB_DESCRIPTOR;
service[i].uuid = desc_uuid;
diff --git a/stack/srvc/srvc_battery_int.h b/stack/srvc/srvc_battery_int.h
index fc191e8..2ffb85a 100644
--- a/stack/srvc/srvc_battery_int.h
+++ b/stack/srvc/srvc_battery_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/srvc/srvc_dis.cc b/stack/srvc/srvc_dis.cc
index 85de4b4..3ca2e33 100644
--- a/stack/srvc/srvc_dis.cc
+++ b/stack/srvc/srvc_dis.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2013 Broadcom Corporation
+ * Copyright 1999-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@
#include "bt_target.h"
#include "bt_utils.h"
-#include "btcore/include/uuid.h"
#include "gatt_api.h"
#include "gatt_int.h"
#include "osi/include/log.h"
@@ -50,18 +49,6 @@
*(p)++ = (uint8_t)((u64) >> 56); \
}
-#define STREAM_TO_UINT64(u64, p) \
- { \
- (u64) = (((uint64_t)(*(p))) + ((((uint64_t)(*((p) + 1)))) << 8) + \
- ((((uint64_t)(*((p) + 2)))) << 16) + \
- ((((uint64_t)(*((p) + 3)))) << 24) + \
- ((((uint64_t)(*((p) + 4)))) << 32) + \
- ((((uint64_t)(*((p) + 5)))) << 40) + \
- ((((uint64_t)(*((p) + 6)))) << 48) + \
- ((((uint64_t)(*((p) + 7)))) << 56)); \
- (p) += 8; \
- }
-
static const uint16_t dis_attr_uuid[DIS_MAX_CHAR_NUM] = {
GATT_UUID_SYSTEM_ID,
GATT_UUID_MODEL_NUMBER_STR,
@@ -137,7 +124,7 @@
if (handle == p_db_attr->handle) {
if ((p_db_attr->uuid == GATT_UUID_PNP_ID ||
p_db_attr->uuid == GATT_UUID_SYSTEM_ID) &&
- is_long == true) {
+ is_long) {
st = GATT_NOT_LONG;
break;
}
@@ -232,7 +219,6 @@
memset(¶m, 0, sizeof(tGATT_READ_PARAM));
- param.service.uuid.len = LEN_UUID_16;
param.service.s_handle = 1;
param.service.e_handle = 0xFFFF;
param.service.auth_req = 0;
@@ -240,13 +226,14 @@
while (dis_cb.dis_read_uuid_idx < DIS_MAX_CHAR_NUM) {
if (dis_uuid_to_attr(dis_attr_uuid[dis_cb.dis_read_uuid_idx]) &
dis_cb.request_mask) {
- param.service.uuid.uu.uuid16 = dis_attr_uuid[dis_cb.dis_read_uuid_idx];
+ param.service.uuid =
+ bluetooth::Uuid::From16Bit(dis_attr_uuid[dis_cb.dis_read_uuid_idx]);
if (GATTC_Read(conn_id, GATT_READ_BY_TYPE, ¶m) == GATT_SUCCESS)
return true;
- LOG(ERROR) << "Read DISInfo: 0x" << std::hex
- << param.service.uuid.uu.uuid16 << "GATT_Read Failed";
+ LOG(ERROR) << "Read DISInfo: " << param.service.uuid
+ << " GATT_Read Failed";
}
dis_cb.dis_read_uuid_idx++;
@@ -350,16 +337,16 @@
btgatt_db_element_t service[DIS_MAX_ATTR_NUM] = {};
- bt_uuid_t svc_uuid;
- uuid_128_from_16(&svc_uuid, UUID_SERVCLASS_DEVICE_INFO);
+ bluetooth::Uuid svc_uuid =
+ bluetooth::Uuid::From16Bit(UUID_SERVCLASS_DEVICE_INFO);
service[0].type = BTGATT_DB_PRIMARY_SERVICE;
service[0].uuid = svc_uuid;
for (int i = 0; dis_attr_mask != 0 && i < DIS_MAX_CHAR_NUM; i++) {
dis_cb.dis_attr[i].uuid = dis_attr_uuid[i];
- bt_uuid_t char_uuid;
- uuid_128_from_16(&char_uuid, dis_cb.dis_attr[i].uuid);
+ bluetooth::Uuid char_uuid =
+ bluetooth::Uuid::From16Bit(dis_cb.dis_attr[i].uuid);
/* index 0 is service, so characteristics start from 1 */
service[i + 1].type = BTGATT_DB_CHARACTERISTIC;
service[i + 1].uuid = char_uuid;
diff --git a/stack/srvc/srvc_dis_int.h b/stack/srvc/srvc_dis_int.h
index 880f068..422f649 100644
--- a/stack/srvc/srvc_dis_int.h
+++ b/stack/srvc/srvc_dis_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/srvc/srvc_eng.cc b/stack/srvc/srvc_eng.cc
index f054f67..af57ff1 100644
--- a/stack/srvc/srvc_eng.cc
+++ b/stack/srvc/srvc_eng.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2013 Broadcom Corporation
+ * Copyright 1999-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -402,7 +402,6 @@
*
******************************************************************************/
tGATT_STATUS srvc_eng_init(void) {
- tBT_UUID app_uuid = {LEN_UUID_16, {UUID_SERVCLASS_DEVICE_INFO}};
if (srvc_eng_cb.enabled) {
LOG(ERROR) << "DIS already initalized";
@@ -410,7 +409,9 @@
memset(&srvc_eng_cb, 0, sizeof(tSRVC_ENG_CB));
/* Create a GATT profile service */
- srvc_eng_cb.gatt_if = GATT_Register(&app_uuid, &srvc_gatt_cback);
+ bluetooth::Uuid app_uuid =
+ bluetooth::Uuid::From16Bit(UUID_SERVCLASS_DEVICE_INFO);
+ srvc_eng_cb.gatt_if = GATT_Register(app_uuid, &srvc_gatt_cback);
GATT_StartIf(srvc_eng_cb.gatt_if);
VLOG(1) << "Srvc_Init: gatt_if=" << +srvc_eng_cb.gatt_if;
diff --git a/stack/srvc/srvc_eng_int.h b/stack/srvc/srvc_eng_int.h
index 7608355..9ea2d0b 100644
--- a/stack/srvc/srvc_eng_int.h
+++ b/stack/srvc/srvc_eng_int.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2013 Broadcom Corporation
+ * Copyright 1999-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/test/ad_parser_unittest.cc b/stack/test/ad_parser_unittest.cc
index 643ed34..36cc7f2 100644
--- a/stack/test/ad_parser_unittest.cc
+++ b/stack/test/ad_parser_unittest.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -137,15 +137,41 @@
0x02, 0x01, 0x02, 0x11, 0x06, 0x66, 0x9a, 0x0c, 0x20, 0x00, 0x08,
0x37, 0xa8, 0xe5, 0x11, 0x81, 0x8b, 0xd0, 0xf0, 0xf0, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- const std::vector<uint8_t> podo_scan_resp{
+ std::vector<uint8_t> podo_scan_resp{
0x03, 0x19, 0x00, 0x80, 0x09, 0x09, 0x50, 0x6f, 0x64, 0x6f, 0x51,
0x35, 0x56, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
AdvertiseDataParser::RemoveTrailingZeros(podo_ad_data);
+ AdvertiseDataParser::RemoveTrailingZeros(podo_scan_resp);
std::vector<uint8_t> glued(podo_ad_data);
- glued.insert(glued.end(), podo_ad_data.begin(), podo_ad_data.end());
+ glued.insert(glued.end(), podo_scan_resp.begin(), podo_scan_resp.end());
+
+ EXPECT_TRUE(AdvertiseDataParser::IsValid(glued));
+}
+
+// This test makes sure that RemoveTrailingZeros is removing all bytes after
+// first zero length field. It does run the RemoveTrailingZeros for data with
+// non-zero bytes after zero length field, then glue scan response at end of it,
+// and checks that the resulting data is good. Note: specification requires all
+// bytes after zero length field to be zero padding, but many legacy devices got
+// this wrong, causing us to have this workaround.
+TEST(AdvertiseDataParserTest, RemoveTrailingZerosMalformed) {
+ std::vector<uint8_t> ad_data{0x02, 0x01, 0x02, 0x11, 0x06, 0x66, 0x9a, 0x0c,
+ 0x20, 0x00, 0x08, 0x37, 0xa8, 0xe5, 0x11, 0x81,
+ 0x8b, 0xd0, 0xf0, 0xf0, 0xf0, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ std::vector<uint8_t> scan_resp{0x03, 0x19, 0x00, 0x80, 0x09, 0x09, 0x50, 0x6f,
+ 0x64, 0x6f, 0x51, 0x35, 0x56, 0x47, 0x00, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+ AdvertiseDataParser::RemoveTrailingZeros(ad_data);
+ AdvertiseDataParser::RemoveTrailingZeros(scan_resp);
+
+ std::vector<uint8_t> glued(ad_data);
+ glued.insert(glued.end(), scan_resp.begin(), scan_resp.end());
EXPECT_TRUE(AdvertiseDataParser::IsValid(glued));
}
\ No newline at end of file
diff --git a/stack/test/ble_advertiser_test.cc b/stack/test/ble_advertiser_test.cc
index 4f389e4..65a30d5 100644
--- a/stack/test/ble_advertiser_test.cc
+++ b/stack/test/ble_advertiser_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1064,6 +1064,53 @@
remove_cb.Run(0);
}
+/* This test verifies that stack cleanup, and shutdown happening while there is
+ * outstanding HCI command is not triggering the callback */
+TEST_F(BleAdvertisingManagerTest, test_cleanup_during_execution) {
+ std::vector<uint8_t> adv_data;
+ std::vector<uint8_t> scan_resp;
+ tBTM_BLE_ADV_PARAMS params;
+ tBLE_PERIODIC_ADV_PARAMS periodic_params;
+ periodic_params.enable = false;
+ std::vector<uint8_t> periodic_data;
+
+ parameters_cb set_params_cb;
+ status_cb set_address_cb;
+ status_cb set_data_cb;
+ EXPECT_CALL(*hci_mock, SetParameters1(_, _, _, _, _, _, _, _, _)).Times(1);
+ EXPECT_CALL(*hci_mock, SetParameters2(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(SaveArg<7>(&set_params_cb));
+ EXPECT_CALL(*hci_mock, SetRandomAddress(_, _, _))
+ .Times(1)
+ .WillOnce(SaveArg<2>(&set_address_cb));
+ EXPECT_CALL(*hci_mock, SetAdvertisingData(_, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(SaveArg<5>(&set_data_cb));
+
+ BleAdvertisingManager::Get()->StartAdvertisingSet(
+ Bind(&BleAdvertisingManagerTest::StartAdvertisingSetCb,
+ base::Unretained(this)),
+ ¶ms, adv_data, scan_resp, &periodic_params, periodic_data,
+ 0 /* duration */, 0 /* maxExtAdvEvents */, Bind(DoNothing2));
+
+ // we are a truly gracious fake controller, let the commands succeed!
+ int selected_tx_power = -15;
+ set_params_cb.Run(0, selected_tx_power);
+ set_address_cb.Run(0);
+
+ // Someone shut down the stack in the middle of flow, when the HCI Set
+ // Advertise Data was scheduled!
+ BleAdvertisingManager::Get()->CleanUp();
+
+ // The HCI call returns with status, and tries to execute the callback. This
+ // should just silently drop the call. If it got executed, we would get crash,
+ // because BleAdvertisingManager object was already deleted.
+ set_data_cb.Run(0);
+
+ ::testing::Mock::VerifyAndClearExpectations(hci_mock.get());
+}
+
extern void testRecomputeTimeout1();
extern void testRecomputeTimeout2();
extern void testRecomputeTimeout3();
diff --git a/stack/test/common/mock_btm_layer.cc b/stack/test/common/mock_btm_layer.cc
new file mode 100644
index 0000000..1405c55
--- /dev/null
+++ b/stack/test/common/mock_btm_layer.cc
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "mock_btm_layer.h"
+
+static bluetooth::manager::MockBtmSecurityInternalInterface*
+ btm_security_internal_interface = nullptr;
+
+void bluetooth::manager::SetMockSecurityInternalInterface(
+ MockBtmSecurityInternalInterface* mock_btm_security_internal_interface) {
+ btm_security_internal_interface = mock_btm_security_internal_interface;
+}
+
+void btm_sec_abort_access_req(const RawAddress& bd_addr) {
+ btm_security_internal_interface->AbortAccessRequest(bd_addr);
+}
+
+tBTM_STATUS btm_sec_mx_access_request(const RawAddress& bd_addr, uint16_t psm,
+ bool is_originator, uint32_t mx_proto_id,
+ uint32_t mx_chan_id,
+ tBTM_SEC_CALLBACK* p_callback,
+ void* p_ref_data) {
+ return btm_security_internal_interface->MultiplexingProtocolAccessRequest(
+ bd_addr, psm, is_originator, mx_proto_id, mx_chan_id, p_callback,
+ p_ref_data);
+}
+
+uint16_t btm_get_max_packet_size(const RawAddress& addr) {
+ return RFCOMM_DEFAULT_MTU;
+}
\ No newline at end of file
diff --git a/stack/test/common/mock_btm_layer.h b/stack/test/common/mock_btm_layer.h
new file mode 100644
index 0000000..45f32d1
--- /dev/null
+++ b/stack/test/common/mock_btm_layer.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "btm_int.h"
+
+namespace bluetooth {
+namespace manager {
+
+class BtmSecurityInternalInterface {
+ public:
+ virtual void AbortAccessRequest(const RawAddress& bd_addr) = 0;
+ virtual tBTM_STATUS MultiplexingProtocolAccessRequest(
+ const RawAddress& bd_addr, uint16_t psm, bool is_originator,
+ uint32_t mx_proto_id, uint32_t mx_chan_id, tBTM_SEC_CALLBACK* p_callback,
+ void* p_ref_data) = 0;
+ virtual ~BtmSecurityInternalInterface() = default;
+};
+
+class MockBtmSecurityInternalInterface : public BtmSecurityInternalInterface {
+ public:
+ MOCK_METHOD1(AbortAccessRequest, void(const RawAddress& bd_addr));
+ MOCK_METHOD7(MultiplexingProtocolAccessRequest,
+ tBTM_STATUS(const RawAddress& bd_addr, uint16_t psm,
+ bool is_originator, uint32_t mx_proto_id,
+ uint32_t mx_chan_id, tBTM_SEC_CALLBACK* p_callback,
+ void* p_ref_data));
+};
+
+/**
+ * Set the {@link MockBtmSecurityInternalInterface} for testing
+ *
+ * @param mock_btm_security_internal_interface pointer to mock btm security
+ * internal interface, could be null
+ */
+void SetMockSecurityInternalInterface(
+ MockBtmSecurityInternalInterface* mock_btm_security_internal_interface);
+
+} // namespace manager
+} // namespace bluetooth
\ No newline at end of file
diff --git a/include/bt_common.h b/stack/test/common/mock_btu_layer.cc
similarity index 81%
copy from include/bt_common.h
copy to stack/test/common/mock_btu_layer.cc
index 9680792..f5bbf7a 100644
--- a/include/bt_common.h
+++ b/stack/test/common/mock_btu_layer.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,6 @@
*
******************************************************************************/
-#pragma once
+#include <base/message_loop/message_loop.h>
-#include "bt_target.h"
-#include "bt_types.h"
-#include "osi/include/allocator.h"
-#include "osi/include/compat.h"
+base::MessageLoop* get_message_loop() { return nullptr; }
\ No newline at end of file
diff --git a/stack/test/common/mock_l2cap_layer.cc b/stack/test/common/mock_l2cap_layer.cc
new file mode 100644
index 0000000..9f08d56
--- /dev/null
+++ b/stack/test/common/mock_l2cap_layer.cc
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#include "mock_l2cap_layer.h"
+
+static bluetooth::l2cap::MockL2capInterface* l2cap_interface = nullptr;
+
+void bluetooth::l2cap::SetMockInterface(
+ MockL2capInterface* mock_l2cap_interface) {
+ l2cap_interface = mock_l2cap_interface;
+}
+
+uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) {
+ VLOG(1) << __func__ << ": psm=" << psm << ", p_cb_info=" << p_cb_info;
+ return l2cap_interface->Register(psm, p_cb_info);
+}
+
+uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& bd_addr) {
+ return l2cap_interface->ConnectRequest(psm, bd_addr);
+}
+
+bool L2CA_ConnectRsp(const RawAddress& bd_addr, uint8_t id, uint16_t lcid,
+ uint16_t result, uint16_t status) {
+ return l2cap_interface->ConnectResponse(bd_addr, id, lcid, result, status);
+}
+
+bool L2CA_DisconnectReq(uint16_t cid) {
+ return l2cap_interface->DisconnectRequest(cid);
+}
+
+bool L2CA_DisconnectRsp(uint16_t cid) {
+ return l2cap_interface->DisconnectResponse(cid);
+}
+
+bool L2CA_ConfigReq(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
+ return l2cap_interface->ConfigRequest(cid, p_cfg);
+}
+
+bool L2CA_ConfigRsp(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
+ return l2cap_interface->ConfigResponse(cid, p_cfg);
+}
+
+uint8_t L2CA_DataWrite(uint16_t cid, BT_HDR* p_data) {
+ return l2cap_interface->DataWrite(cid, p_data);
+}
diff --git a/stack/test/common/mock_l2cap_layer.h b/stack/test/common/mock_l2cap_layer.h
new file mode 100644
index 0000000..78c8a9c
--- /dev/null
+++ b/stack/test/common/mock_l2cap_layer.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "l2c_api.h"
+
+namespace bluetooth {
+namespace l2cap {
+
+class L2capInterface {
+ public:
+ virtual uint16_t Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) = 0;
+ virtual uint16_t ConnectRequest(uint16_t psm, const RawAddress& bd_addr) = 0;
+ virtual bool ConnectResponse(const RawAddress& bd_addr, uint8_t id,
+ uint16_t lcid, uint16_t result,
+ uint16_t status) = 0;
+ virtual bool DisconnectRequest(uint16_t cid) = 0;
+ virtual bool DisconnectResponse(uint16_t cid) = 0;
+ virtual bool ConfigRequest(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) = 0;
+ virtual bool ConfigResponse(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) = 0;
+ virtual uint8_t DataWrite(uint16_t cid, BT_HDR* p_data) = 0;
+ virtual ~L2capInterface() = default;
+};
+
+class MockL2capInterface : public L2capInterface {
+ public:
+ MOCK_METHOD2(Register, uint16_t(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info));
+ MOCK_METHOD2(ConnectRequest,
+ uint16_t(uint16_t psm, const RawAddress& bd_addr));
+ MOCK_METHOD5(ConnectResponse,
+ bool(const RawAddress& bd_addr, uint8_t id, uint16_t lcid,
+ uint16_t result, uint16_t status));
+ MOCK_METHOD1(DisconnectRequest, bool(uint16_t cid));
+ MOCK_METHOD1(DisconnectResponse, bool(uint16_t cid));
+ MOCK_METHOD2(ConfigRequest, bool(uint16_t cid, tL2CAP_CFG_INFO* p_cfg));
+ MOCK_METHOD2(ConfigResponse, bool(uint16_t cid, tL2CAP_CFG_INFO* p_cfg));
+ MOCK_METHOD2(DataWrite, uint8_t(uint16_t cid, BT_HDR* p_data));
+};
+
+/**
+ * Set the {@link MockL2capInterface} for testing
+ *
+ * @param mock_l2cap_interface pointer to mock l2cap interface, could be null
+ */
+void SetMockInterface(MockL2capInterface* mock_l2cap_interface);
+
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/stack/test/common/stack_test_packet_utils.cc b/stack/test/common/stack_test_packet_utils.cc
new file mode 100644
index 0000000..74fc57d
--- /dev/null
+++ b/stack/test/common/stack_test_packet_utils.cc
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "hci_layer.h"
+#include "l2c_api.h"
+#include "osi/include/allocator.h"
+
+#include "stack_test_packet_utils.h"
+
+namespace bluetooth {
+
+std::vector<uint8_t> CreateL2capDataPacket(uint16_t lcid,
+ const std::vector<uint8_t>& data) {
+ // Data in little endian order
+ std::vector<uint8_t> result;
+ auto data_size = static_cast<uint16_t>(data.size());
+ result.push_back(static_cast<uint8_t>(data_size));
+ result.push_back(static_cast<uint8_t>(data_size >> 8));
+ result.push_back(static_cast<uint8_t>(lcid));
+ result.push_back(static_cast<uint8_t>(lcid >> 8));
+ result.insert(result.end(), data.begin(), data.end());
+ return result;
+}
+
+std::vector<uint8_t> CreateAclPacket(uint16_t handle, uint8_t pb, uint8_t bc,
+ const std::vector<uint8_t>& data) {
+ // Data in little endian order
+ std::vector<uint8_t> result;
+ result.push_back(static_cast<uint8_t>(handle & 0x0F));
+ uint8_t second_byte = 0;
+ second_byte |= (bc << 6) & 0b11000000;
+ second_byte |= (pb << 4) & 0b00110000;
+ second_byte |= (handle >> 8) & 0b00001111;
+ result.push_back(second_byte);
+ auto data_size = static_cast<uint16_t>(data.size());
+ result.push_back(static_cast<uint8_t>(data_size));
+ result.push_back(static_cast<uint8_t>(data_size >> 8));
+ result.insert(result.end(), data.begin(), data.end());
+ return result;
+}
+
+BT_HDR* AllocateWrappedIncomingL2capAclPacket(const uint8_t* acl_packet_bytes,
+ size_t buffer_length) {
+ size_t packet_size = buffer_length + BT_HDR_SIZE;
+ auto packet = reinterpret_cast<BT_HDR*>(osi_malloc(packet_size));
+ // Add ACL packet overhead + L2CAP packet overhead
+ packet->offset = 4 + L2CAP_PKT_OVERHEAD;
+ packet->len = static_cast<uint16_t>(buffer_length - 4 - L2CAP_PKT_OVERHEAD);
+ packet->layer_specific = 0;
+ packet->event = MSG_HC_TO_STACK_HCI_ACL;
+ memcpy(packet->data, acl_packet_bytes, buffer_length);
+ return packet;
+}
+
+BT_HDR* AllocateWrappedIncomingL2capAclPacket(
+ const std::vector<uint8_t>& buffer) {
+ return AllocateWrappedIncomingL2capAclPacket(buffer.data(), buffer.size());
+}
+
+BT_HDR* AllocateWrappedOutgoingL2capAclPacket(const uint8_t* acl_packet_bytes,
+ size_t buffer_length) {
+ size_t acl_l2cap_header_size = 4 + L2CAP_PKT_OVERHEAD;
+ CHECK_GE(L2CAP_MIN_OFFSET, static_cast<int>(acl_l2cap_header_size));
+ size_t packet_size =
+ BT_HDR_SIZE + L2CAP_MIN_OFFSET + buffer_length - acl_l2cap_header_size;
+ auto packet = reinterpret_cast<BT_HDR*>(osi_malloc(packet_size));
+ packet->offset = L2CAP_MIN_OFFSET;
+ packet->len = static_cast<uint16_t>(buffer_length - acl_l2cap_header_size);
+ packet->layer_specific = 0;
+ packet->event = 0;
+ memcpy(packet->data + packet->offset - acl_l2cap_header_size,
+ acl_packet_bytes, buffer_length);
+ return packet;
+}
+
+BT_HDR* AllocateWrappedOutgoingL2capAclPacket(
+ const std::vector<uint8_t>& buffer) {
+ return AllocateWrappedOutgoingL2capAclPacket(buffer.data(), buffer.size());
+}
+
+} // namespace bluetooth
\ No newline at end of file
diff --git a/stack/test/common/stack_test_packet_utils.h b/stack/test/common/stack_test_packet_utils.h
new file mode 100644
index 0000000..fcbc5a9
--- /dev/null
+++ b/stack/test/common/stack_test_packet_utils.h
@@ -0,0 +1,78 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#pragma once
+
+#include "bt_types.h"
+
+namespace bluetooth {
+
+/**
+ * Create L2CAP data packet
+ *
+ * @param lcid
+ * @param data
+ * @return vector of bytes
+ */
+std::vector<uint8_t> CreateL2capDataPacket(uint16_t lcid,
+ const std::vector<uint8_t>& data);
+
+/**
+ * Create ACL data packet
+ *
+ * @param handle ACL connection hanle
+ * @param pb pb byte
+ * @param bc bc byte
+ * @param data frame data
+ * @return vector of bytes
+ */
+std::vector<uint8_t> CreateAclPacket(uint16_t handle, uint8_t pb, uint8_t bc,
+ const std::vector<uint8_t>& data);
+
+/**
+ * Given an array of ACL packet bytes from BTSNOOP log, allocate an OSI
+ * allocated BT_HDR pointer to a packet that can be processed by L2CAP
+ * application layer
+ *
+ * Note: BT_HDR offset is configured for incoming packets
+ *
+ * @param acl_packet_bytes pointer to array of ACL packet bytes
+ * @param buffer_length length of the packet buffer
+ * @return BT_HDR pointer to an OSI heap allocated packet
+ */
+BT_HDR* AllocateWrappedIncomingL2capAclPacket(const uint8_t* acl_packet_bytes,
+ size_t buffer_length);
+BT_HDR* AllocateWrappedIncomingL2capAclPacket(
+ const std::vector<uint8_t>& buffer);
+
+/**
+ * Given an array of ACL packet bytes from BTSNOOP log, allocate an OSI
+ * allocated BT_HDR pointer to a packet that can be processed by L2CAP
+ * application layer
+ *
+ * Note: BT_HDR offset is configured for outgoing packets
+ *
+ * @param acl_packet_bytes pointer to array of ACL packet bytes
+ * @param buffer_length length of the packet buffer
+ * @return BT_HDR pointer to an OSI heap allocated packet
+ */
+BT_HDR* AllocateWrappedOutgoingL2capAclPacket(const uint8_t* acl_packet_bytes,
+ size_t buffer_length);
+BT_HDR* AllocateWrappedOutgoingL2capAclPacket(
+ const std::vector<uint8_t>& buffer);
+
+} // namespace bluetooth
diff --git a/stack/test/rfcomm/stack_rfcomm_test.cc b/stack/test/rfcomm/stack_rfcomm_test.cc
new file mode 100644
index 0000000..3d9da3f
--- /dev/null
+++ b/stack/test/rfcomm/stack_rfcomm_test.cc
@@ -0,0 +1,892 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <base/logging.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "bt_types.h"
+#include "btm_api.h"
+#include "l2c_api.h"
+#include "osi/include/osi.h"
+#include "port_api.h"
+
+#include "btm_int.h"
+#include "rfc_int.h"
+
+#include "mock_btm_layer.h"
+#include "mock_l2cap_layer.h"
+#include "stack_rfcomm_test_utils.h"
+#include "stack_test_packet_utils.h"
+
+std::string DumpByteBufferToString(uint8_t* p_data, size_t len) {
+ std::stringstream str;
+ str.setf(std::ios_base::hex, std::ios::basefield);
+ str.setf(std::ios_base::uppercase);
+ str.fill('0');
+ for (size_t i = 0; i < len; ++i) {
+ str << std::setw(2) << static_cast<uint16_t>(p_data[i]);
+ str << " ";
+ }
+ return str.str();
+}
+
+std::string DumpBtHdrToString(BT_HDR* p_hdr) {
+ uint8_t* p_hdr_data = p_hdr->data + p_hdr->offset;
+ return DumpByteBufferToString(p_hdr_data, p_hdr->len);
+}
+
+void PrintTo(BT_HDR* value, ::std::ostream* os) {
+ *os << DumpBtHdrToString(value);
+}
+
+void PrintTo(tL2CAP_CFG_INFO* value, ::std::ostream* os) {
+ *os << DumpByteBufferToString((uint8_t*)value, sizeof(tL2CAP_CFG_INFO));
+}
+
+namespace {
+
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+using testing::Test;
+using testing::StrictMock;
+using testing::SaveArg;
+using testing::SaveArgPointee;
+using testing::Pointee;
+using testing::StrEq;
+using testing::NotNull;
+
+using bluetooth::CreateL2capDataPacket;
+using bluetooth::CreateAclPacket;
+using bluetooth::AllocateWrappedIncomingL2capAclPacket;
+using bluetooth::AllocateWrappedOutgoingL2capAclPacket;
+
+using bluetooth::rfcomm::GetDlci;
+using bluetooth::rfcomm::GetAddressField;
+using bluetooth::rfcomm::GetControlField;
+using bluetooth::rfcomm::CreateMccPnFrame;
+using bluetooth::rfcomm::CreateMccMscFrame;
+using bluetooth::rfcomm::CreateMultiplexerControlFrame;
+using bluetooth::rfcomm::CreateRfcommPacket;
+using bluetooth::rfcomm::CreateQuickDataPacket;
+using bluetooth::rfcomm::CreateQuickPnPacket;
+using bluetooth::rfcomm::CreateQuickSabmPacket;
+using bluetooth::rfcomm::CreateQuickUaPacket;
+using bluetooth::rfcomm::CreateQuickMscPacket;
+
+MATCHER_P(PointerMemoryEqual, ptr,
+ DumpByteBufferToString((uint8_t*)ptr, sizeof(*ptr))) {
+ return memcmp(arg, ptr, sizeof(*ptr)) == 0;
+}
+
+MATCHER_P(BtHdrEqual, expected, DumpBtHdrToString(expected)) {
+ auto arg_hdr = static_cast<BT_HDR*>(arg);
+ uint8_t* arg_data = arg_hdr->data + arg_hdr->offset;
+ auto expected_hdr = static_cast<BT_HDR*>(expected);
+ uint8_t* expected_data = expected_hdr->data + expected_hdr->offset;
+ return memcmp(arg_data, expected_data, expected_hdr->len) == 0;
+}
+
+bluetooth::rfcomm::MockRfcommCallback* rfcomm_callback = nullptr;
+
+void port_mgmt_cback_0(uint32_t code, uint16_t port_handle) {
+ rfcomm_callback->PortManagementCallback(code, port_handle, 0);
+}
+
+void port_mgmt_cback_1(uint32_t code, uint16_t port_handle) {
+ rfcomm_callback->PortManagementCallback(code, port_handle, 1);
+}
+
+void port_event_cback_0(uint32_t code, uint16_t port_handle) {
+ rfcomm_callback->PortEventCallback(code, port_handle, 0);
+}
+
+void port_event_cback_1(uint32_t code, uint16_t port_handle) {
+ rfcomm_callback->PortEventCallback(code, port_handle, 1);
+}
+
+RawAddress GetTestAddress(int index) {
+ CHECK_LT(index, UINT8_MAX);
+ RawAddress result = {
+ {0xAA, 0x00, 0x11, 0x22, 0x33, static_cast<uint8_t>(index)}};
+ return result;
+}
+
+class StackRfcommTest : public Test {
+ public:
+ void StartServerPort(uint16_t uuid, uint8_t scn, uint16_t mtu,
+ tPORT_CALLBACK* management_callback,
+ tPORT_CALLBACK* event_callback,
+ uint16_t* server_handle) {
+ VLOG(1) << "Step 1";
+ ASSERT_EQ(RFCOMM_CreateConnection(uuid, scn, true, mtu, RawAddress::kAny,
+ server_handle, management_callback),
+ PORT_SUCCESS);
+ ASSERT_EQ(PORT_SetEventMask(*server_handle, PORT_EV_RXCHAR), PORT_SUCCESS);
+ ASSERT_EQ(PORT_SetEventCallback(*server_handle, event_callback),
+ PORT_SUCCESS);
+ }
+
+ void ConnectServerL2cap(const RawAddress& peer_addr, uint16_t acl_handle,
+ uint16_t lcid) {
+ VLOG(1) << "Step 1";
+ // Remote device connect to this channel, we shall accept
+ static const uint8_t cmd_id = 0x07;
+ EXPECT_CALL(l2cap_interface_,
+ ConnectResponse(peer_addr, cmd_id, lcid, L2CAP_CONN_OK, 0));
+ tL2CAP_CFG_INFO cfg_req = {.mtu_present = true, .mtu = L2CAP_MTU_SIZE};
+ EXPECT_CALL(l2cap_interface_,
+ ConfigRequest(lcid, PointerMemoryEqual(&cfg_req)))
+ .WillOnce(Return(true));
+ l2cap_appl_info_.pL2CA_ConnectInd_Cb(peer_addr, lcid, BT_PSM_RFCOMM,
+ cmd_id);
+
+ VLOG(1) << "Step 2";
+ // MTU configuration is done
+ cfg_req.mtu_present = false;
+ l2cap_appl_info_.pL2CA_ConfigCfm_Cb(lcid, &cfg_req);
+
+ VLOG(1) << "Step 3";
+ // Remote device also ask to configure MTU size
+ EXPECT_CALL(l2cap_interface_,
+ ConfigResponse(lcid, PointerMemoryEqual(&cfg_req)))
+ .WillOnce(Return(true));
+ l2cap_appl_info_.pL2CA_ConfigInd_Cb(lcid, &cfg_req);
+
+ VLOG(1) << "Step 4";
+ // Remote device connect to server channel 0
+ BT_HDR* sabm_channel_0 = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickSabmPacket(RFCOMM_MX_DLCI, lcid, acl_handle));
+ BT_HDR* ua_channel_0 = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickUaPacket(RFCOMM_MX_DLCI, lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_, DataWrite(lcid, BtHdrEqual(ua_channel_0)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ // Packet should be freed by RFCOMM
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, sabm_channel_0);
+ osi_free(ua_channel_0);
+ }
+
+ void ConnectServerPort(const RawAddress& peer_addr, uint16_t port_handle,
+ uint8_t scn, uint16_t mtu, uint16_t acl_handle,
+ uint16_t lcid, int port_callback_index) {
+ VLOG(1) << "Step 1";
+ // Negotiate parameters on scn
+ BT_HDR* uih_pn_cmd_from_peer = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickPnPacket(true, GetDlci(false, scn), true, mtu,
+ RFCOMM_PN_CONV_LAYER_CBFC_I >> 4, 0, RFCOMM_K_MAX,
+ lcid, acl_handle));
+ BT_HDR* uih_pn_rsp_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickPnPacket(false, GetDlci(false, scn), false, mtu,
+ RFCOMM_PN_CONV_LAYER_CBFC_R >> 4, 0, RFCOMM_K_MAX,
+ lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(lcid, BtHdrEqual(uih_pn_rsp_to_peer)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ // uih_pn_cmd_from_peer should be freed by this method
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, uih_pn_cmd_from_peer);
+ osi_free(uih_pn_rsp_to_peer);
+
+ VLOG(1) << "Step 2";
+ // Remote device connect to scn
+ tBTM_SEC_CALLBACK* security_callback = nullptr;
+ void* p_port = nullptr;
+ BT_HDR* sabm_channel_dlci = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickSabmPacket(GetDlci(false, scn), lcid, acl_handle));
+ EXPECT_CALL(btm_security_internal_interface_,
+ MultiplexingProtocolAccessRequest(peer_addr, BT_PSM_RFCOMM,
+ false, BTM_SEC_PROTO_RFCOMM,
+ scn, NotNull(), NotNull()))
+ .WillOnce(DoAll(SaveArg<5>(&security_callback), SaveArg<6>(&p_port),
+ Return(BTM_SUCCESS)));
+ // sabm_channel_dlci should be freed by this method
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, sabm_channel_dlci);
+
+ VLOG(1) << "Step 3";
+ // Confirm security check should trigger port as connected
+ EXPECT_CALL(
+ rfcomm_callback_,
+ PortManagementCallback(PORT_SUCCESS, port_handle, port_callback_index));
+ BT_HDR* ua_channel_dlci = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickUaPacket(GetDlci(false, scn), lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_, DataWrite(lcid, BtHdrEqual(ua_channel_dlci)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ ASSERT_TRUE(security_callback);
+ security_callback(&peer_addr, BT_TRANSPORT_BR_EDR, p_port, BTM_SUCCESS);
+ osi_free(ua_channel_dlci);
+
+ VLOG(1) << "Step 4";
+ // Remote also need to configure its modem signal before we can send data
+ BT_HDR* uih_msc_cmd_from_peer = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickMscPacket(true, GetDlci(false, scn), lcid, acl_handle, true,
+ false, true, true, false, true));
+ BT_HDR* uih_msc_response_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickMscPacket(false, GetDlci(false, scn), lcid, acl_handle,
+ false, false, true, true, false, true));
+ // We also have to do modem configuration ourself
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(lcid, BtHdrEqual(uih_msc_response_to_peer)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ BT_HDR* uih_msc_cmd_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickMscPacket(false, GetDlci(false, scn), lcid, acl_handle, true,
+ false, true, true, false, true));
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(lcid, BtHdrEqual(uih_msc_cmd_to_peer)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ // uih_msc_cmd_from_peer should be freed by this method
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, uih_msc_cmd_from_peer);
+ osi_free(uih_msc_response_to_peer);
+
+ VLOG(1) << "Step 5";
+ // modem configuration is done
+ BT_HDR* uih_msc_response_from_peer = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickMscPacket(true, GetDlci(false, scn), lcid, acl_handle, false,
+ false, true, true, false, true));
+ // uih_msc_response_from_peer should be freed by this method
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, uih_msc_response_from_peer);
+ }
+
+ void StartClientPort(const RawAddress& peer_bd_addr, uint16_t uuid,
+ uint8_t scn, uint16_t mtu,
+ tPORT_CALLBACK* management_callback,
+ tPORT_CALLBACK* event_callback, uint16_t lcid,
+ uint16_t acl_handle, uint16_t* client_handle,
+ bool is_first_connection) {
+ VLOG(1) << "Step 1";
+ BT_HDR* uih_pn_channel_3 =
+ AllocateWrappedOutgoingL2capAclPacket(CreateQuickPnPacket(
+ true, GetDlci(false, scn), true, mtu, RFCOMM_PN_CONV_LAYER_TYPE_1,
+ RFCOMM_PN_PRIORITY_0, RFCOMM_K, lcid, acl_handle));
+ if (is_first_connection) {
+ EXPECT_CALL(l2cap_interface_, ConnectRequest(BT_PSM_RFCOMM, peer_bd_addr))
+ .WillOnce(Return(lcid));
+ } else {
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(lcid, BtHdrEqual(uih_pn_channel_3)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ }
+ ASSERT_EQ(RFCOMM_CreateConnection(uuid, scn, false, mtu, peer_bd_addr,
+ client_handle, management_callback),
+ PORT_SUCCESS);
+ ASSERT_EQ(PORT_SetEventMask(*client_handle, PORT_EV_RXCHAR), PORT_SUCCESS);
+ ASSERT_EQ(PORT_SetEventCallback(*client_handle, event_callback),
+ PORT_SUCCESS);
+ osi_free(uih_pn_channel_3);
+ }
+
+ void TestConnectClientPortL2cap(uint16_t acl_handle, uint16_t lcid) {
+ VLOG(1) << "Step 1";
+ // Send configuration request when L2CAP connect is succsseful
+ tL2CAP_CFG_INFO cfg_req = {.mtu_present = true, .mtu = L2CAP_MTU_SIZE};
+ EXPECT_CALL(l2cap_interface_,
+ ConfigRequest(lcid, PointerMemoryEqual(&cfg_req)))
+ .WillOnce(Return(true));
+ l2cap_appl_info_.pL2CA_ConnectCfm_Cb(lcid, L2CAP_CONN_OK);
+
+ VLOG(1) << "Step 2";
+ // Remote device confirms our configuration request
+ cfg_req.mtu_present = false;
+ l2cap_appl_info_.pL2CA_ConfigCfm_Cb(lcid, &cfg_req);
+
+ VLOG(1) << "Step 3";
+ // Remote device also asks to configure MTU
+ // Once configuration is done, we connect to multiplexer control channel 0
+ EXPECT_CALL(l2cap_interface_,
+ ConfigResponse(lcid, PointerMemoryEqual(&cfg_req)))
+ .WillOnce(Return(true));
+ // multiplexer control channel's DLCI is always 0
+ BT_HDR* sabm_channel_0 = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickSabmPacket(RFCOMM_MX_DLCI, lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_, DataWrite(lcid, BtHdrEqual(sabm_channel_0)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ l2cap_appl_info_.pL2CA_ConfigInd_Cb(lcid, &cfg_req);
+ osi_free(sabm_channel_0);
+ }
+
+ void ConnectClientPort(const RawAddress& peer_addr, uint16_t port_handle,
+ uint8_t scn, uint16_t mtu, uint16_t acl_handle,
+ uint16_t lcid, int port_callback_index,
+ bool is_first_connection) {
+ VLOG(1) << "Step 1";
+ if (is_first_connection) {
+ VLOG(1) << "Step 1.5";
+ // Once remote accept multiplexer control channel 0
+ // We change to desired channel on non-initiating device (remote device)
+ BT_HDR* ua_channel_0 = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickUaPacket(RFCOMM_MX_DLCI, lcid, acl_handle));
+ BT_HDR* uih_pn_channel_3 =
+ AllocateWrappedOutgoingL2capAclPacket(CreateQuickPnPacket(
+ true, GetDlci(false, scn), true, mtu,
+ RFCOMM_PN_CONV_LAYER_CBFC_I >> 4, RFCOMM_PN_PRIORITY_0,
+ RFCOMM_K_MAX, lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(lcid, BtHdrEqual(uih_pn_channel_3)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, ua_channel_0);
+ osi_free(uih_pn_channel_3);
+ }
+
+ VLOG(1) << "Step 2";
+ // Once remote accept service channel change, we start security procedure
+ BT_HDR* uih_pn_channel_3_accept =
+ AllocateWrappedIncomingL2capAclPacket(CreateQuickPnPacket(
+ false, GetDlci(false, scn), false, mtu,
+ RFCOMM_PN_CONV_LAYER_CBFC_I >> 4, RFCOMM_PN_PRIORITY_0,
+ RFCOMM_K_MAX, lcid, acl_handle));
+ tBTM_SEC_CALLBACK* security_callback = nullptr;
+ void* p_port = nullptr;
+ EXPECT_CALL(btm_security_internal_interface_,
+ MultiplexingProtocolAccessRequest(peer_addr, BT_PSM_RFCOMM,
+ true, BTM_SEC_PROTO_RFCOMM,
+ scn, NotNull(), NotNull()))
+ .WillOnce(DoAll(SaveArg<5>(&security_callback), SaveArg<6>(&p_port),
+ Return(BTM_SUCCESS)));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, uih_pn_channel_3_accept);
+
+ VLOG(1) << "Step 3";
+ // Once security procedure is done, we officially connect to target scn
+ BT_HDR* sabm_channel_3 = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickSabmPacket(GetDlci(false, scn), lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_, DataWrite(lcid, BtHdrEqual(sabm_channel_3)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ ASSERT_TRUE(security_callback);
+ security_callback(&peer_addr, BT_TRANSPORT_BR_EDR, p_port, BTM_SUCCESS);
+ osi_free(sabm_channel_3);
+
+ VLOG(1) << "Step 4";
+ // When target scn is accepted by remote, we need to configure modem signal
+ // state beofre using the port
+ EXPECT_CALL(
+ rfcomm_callback_,
+ PortManagementCallback(PORT_SUCCESS, port_handle, port_callback_index));
+ BT_HDR* uih_msc_cmd = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickMscPacket(true, GetDlci(false, scn), lcid, acl_handle, true,
+ false, true, true, false, true));
+ EXPECT_CALL(l2cap_interface_, DataWrite(lcid, BtHdrEqual(uih_msc_cmd)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ BT_HDR* ua_channel_3 = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickUaPacket(GetDlci(false, scn), lcid, acl_handle));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, ua_channel_3);
+ osi_free(uih_msc_cmd);
+
+ VLOG(1) << "Step 5";
+ // modem configuration is done
+ BT_HDR* uih_msc_response = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickMscPacket(false, GetDlci(false, scn), lcid, acl_handle,
+ false, false, true, true, false, true));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, uih_msc_response);
+
+ VLOG(1) << "Step 6";
+ // Remote also need to configure its modem signal before we can send data
+ BT_HDR* uih_msc_cmd_from_peer = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickMscPacket(false, GetDlci(false, scn), lcid, acl_handle, true,
+ false, true, true, false, true));
+ BT_HDR* uih_msc_response_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickMscPacket(true, GetDlci(false, scn), lcid, acl_handle, false,
+ false, true, true, false, true));
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(lcid, BtHdrEqual(uih_msc_response_to_peer)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, uih_msc_cmd_from_peer);
+ osi_free(uih_msc_response_to_peer);
+ }
+
+ void SendAndVerifyOutgoingTransmission(uint16_t port_handle,
+ bool is_initiator, uint8_t scn,
+ bool cr, const std::string& message,
+ int credits, uint16_t acl_handle,
+ uint16_t lcid) {
+ VLOG(1) << "Step 1";
+ BT_HDR* data_packet = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickDataPacket(GetDlci(is_initiator, scn), cr, lcid, acl_handle,
+ credits, message));
+ uint16_t transmitted_length = 0;
+ EXPECT_CALL(l2cap_interface_, DataWrite(lcid, BtHdrEqual(data_packet)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ ASSERT_EQ(PORT_WriteData(port_handle, message.data(), message.size(),
+ &transmitted_length),
+ PORT_SUCCESS);
+ ASSERT_EQ(transmitted_length, message.size());
+ }
+
+ void ReceiveAndVerifyIncomingTransmission(uint16_t port_handle,
+ bool is_initiator, uint8_t scn,
+ bool cr, const std::string& message,
+ int credits, uint16_t acl_handle,
+ uint16_t lcid,
+ int port_callback_index) {
+ VLOG(1) << "Step 1";
+ BT_HDR* data_packet = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickDataPacket(GetDlci(is_initiator, scn), cr, lcid, acl_handle,
+ credits, message));
+ EXPECT_CALL(rfcomm_callback_,
+ PortEventCallback(_, port_handle, port_callback_index));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(lcid, data_packet);
+
+ VLOG(1) << "Step 2";
+ char buffer[L2CAP_MTU_SIZE] = {};
+ uint16_t length = 0;
+ int status = PORT_ReadData(port_handle, buffer, L2CAP_MTU_SIZE, &length);
+ ASSERT_EQ(status, PORT_SUCCESS);
+ ASSERT_THAT(buffer, StrEq(message));
+ }
+
+ protected:
+ void SetUp() override {
+ Test::SetUp();
+ bluetooth::manager::SetMockSecurityInternalInterface(
+ &btm_security_internal_interface_);
+ bluetooth::l2cap::SetMockInterface(&l2cap_interface_);
+ rfcomm_callback = &rfcomm_callback_;
+ EXPECT_CALL(l2cap_interface_, Register(BT_PSM_RFCOMM, _))
+ .WillOnce(
+ DoAll(SaveArgPointee<1>(&l2cap_appl_info_), Return(BT_PSM_RFCOMM)));
+ RFCOMM_Init();
+ rfc_cb.trace_level = BT_TRACE_LEVEL_DEBUG;
+ }
+
+ void TearDown() override {
+ rfcomm_callback = nullptr;
+ bluetooth::l2cap::SetMockInterface(nullptr);
+ bluetooth::manager::SetMockSecurityInternalInterface(nullptr);
+ testing::Test::TearDown();
+ }
+ StrictMock<bluetooth::manager::MockBtmSecurityInternalInterface>
+ btm_security_internal_interface_;
+ StrictMock<bluetooth::l2cap::MockL2capInterface> l2cap_interface_;
+ StrictMock<bluetooth::rfcomm::MockRfcommCallback> rfcomm_callback_;
+ tL2CAP_APPL_INFO l2cap_appl_info_;
+};
+
+TEST_F(StackRfcommTest, SingleServerConnectionHelloWorld) {
+ // Prepare a server channel at kTestChannelNumber0
+ static const uint16_t acl_handle = 0x0009;
+ static const uint16_t lcid = 0x0054;
+ static const uint16_t test_uuid = 0x1112;
+ static const uint8_t test_scn = 8;
+ static const uint16_t test_mtu = 1600;
+ static const RawAddress test_address = GetTestAddress(0);
+ uint16_t server_handle = 0;
+ ASSERT_NO_FATAL_FAILURE(StartServerPort(test_uuid, test_scn, test_mtu,
+ port_mgmt_cback_0, port_event_cback_0,
+ &server_handle));
+ ASSERT_NO_FATAL_FAILURE(ConnectServerL2cap(test_address, acl_handle, lcid));
+ ASSERT_NO_FATAL_FAILURE(ConnectServerPort(
+ test_address, server_handle, test_scn, test_mtu, acl_handle, lcid, 0));
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ server_handle, false, test_scn, true, "Hello World!\r", 50, acl_handle,
+ lcid, 0));
+ ASSERT_NO_FATAL_FAILURE(
+ SendAndVerifyOutgoingTransmission(server_handle, false, test_scn, false,
+ "\r!dlroW olleH", 4, acl_handle, lcid));
+}
+
+TEST_F(StackRfcommTest, MultiServerPortSameDeviceHelloWorld) {
+ // Prepare a server channel at kTestChannelNumber0
+ static const uint16_t acl_handle = 0x0009;
+ static const uint16_t lcid = 0x0054;
+ static const uint16_t test_mtu = 1600;
+ static const RawAddress test_address = GetTestAddress(0);
+
+ // Service 0
+ uint16_t server_handle_0 = 0;
+ static const uint8_t test_scn_0 = 8;
+ static const uint16_t test_uuid_0 = 0x1112;
+ ASSERT_NO_FATAL_FAILURE(StartServerPort(test_uuid_0, test_scn_0, test_mtu,
+ port_mgmt_cback_0, port_event_cback_0,
+ &server_handle_0));
+ ASSERT_NO_FATAL_FAILURE(ConnectServerL2cap(test_address, acl_handle, lcid));
+ ASSERT_NO_FATAL_FAILURE(ConnectServerPort(test_address, server_handle_0,
+ test_scn_0, test_mtu, acl_handle,
+ lcid, 0));
+
+ // Service 1
+ uint16_t server_handle_1 = 0;
+ static const uint8_t test_scn_1 = 10;
+ static const uint16_t test_uuid_1 = 0x111F;
+ ASSERT_NE(test_scn_1, test_scn_0);
+ ASSERT_NE(test_uuid_1, test_uuid_0);
+ ASSERT_NO_FATAL_FAILURE(StartServerPort(test_uuid_1, test_scn_1, test_mtu,
+ port_mgmt_cback_1, port_event_cback_1,
+ &server_handle_1));
+ // No L2CAP setup for 2nd device
+ ASSERT_NO_FATAL_FAILURE(ConnectServerPort(test_address, server_handle_1,
+ test_scn_1, test_mtu, acl_handle,
+ lcid, 1));
+
+ // Use service 0
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ server_handle_0, false, test_scn_0, true, "Hello World0!\r", 50,
+ acl_handle, lcid, 0));
+ ASSERT_NO_FATAL_FAILURE(SendAndVerifyOutgoingTransmission(
+ server_handle_0, false, test_scn_0, false, "\r!0dlroW olleH", 4,
+ acl_handle, lcid));
+ // Use service 1
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ server_handle_1, false, test_scn_1, true, "Hello World1!\r", 50,
+ acl_handle, lcid, 1));
+ ASSERT_NO_FATAL_FAILURE(SendAndVerifyOutgoingTransmission(
+ server_handle_1, false, test_scn_1, false, "\r!1dlroW olleH", 4,
+ acl_handle, lcid));
+}
+
+TEST_F(StackRfcommTest, SameServerPortMultiDeviceHelloWorld) {
+ // Prepare a server channel at kTestChannelNumber0
+ static const uint16_t test_mtu = 1600;
+ static const uint8_t test_scn = 3;
+ static const uint16_t test_uuid = 0x1112;
+
+ // Service 0
+ static const RawAddress test_address_0 = GetTestAddress(0);
+ static const uint16_t acl_handle_0 = 0x0009;
+ static const uint16_t lcid_0 = 0x0054;
+ uint16_t server_handle_0 = 0;
+ ASSERT_NO_FATAL_FAILURE(StartServerPort(test_uuid, test_scn, test_mtu,
+ port_mgmt_cback_0, port_event_cback_0,
+ &server_handle_0));
+ ASSERT_NO_FATAL_FAILURE(
+ ConnectServerL2cap(test_address_0, acl_handle_0, lcid_0));
+ ASSERT_NO_FATAL_FAILURE(ConnectServerPort(test_address_0, server_handle_0,
+ test_scn, test_mtu, acl_handle_0,
+ lcid_0, 0));
+
+ // Service 1
+ static const RawAddress test_address_1 = GetTestAddress(1);
+ static const uint16_t acl_handle_1 = 0x0012;
+ static const uint16_t lcid_1 = 0x0045;
+ uint16_t server_handle_1 = 0;
+ ASSERT_NO_FATAL_FAILURE(StartServerPort(test_uuid, test_scn, test_mtu,
+ port_mgmt_cback_1, port_event_cback_1,
+ &server_handle_1));
+ ASSERT_NO_FATAL_FAILURE(
+ ConnectServerL2cap(test_address_1, acl_handle_1, lcid_1));
+ ASSERT_NO_FATAL_FAILURE(ConnectServerPort(test_address_1, server_handle_1,
+ test_scn, test_mtu, acl_handle_1,
+ lcid_1, 1));
+
+ // Use service 0
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ server_handle_0, false, test_scn, true, "Hello World0!\r", 50,
+ acl_handle_0, lcid_0, 0));
+ ASSERT_NO_FATAL_FAILURE(SendAndVerifyOutgoingTransmission(
+ server_handle_0, false, test_scn, false, "\r!0dlroW olleH", 4,
+ acl_handle_0, lcid_0));
+ // Use service 1
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ server_handle_1, false, test_scn, true, "Hello World1!\r", 50,
+ acl_handle_1, lcid_1, 1));
+ ASSERT_NO_FATAL_FAILURE(SendAndVerifyOutgoingTransmission(
+ server_handle_1, false, test_scn, false, "\r!1dlroW olleH", 4,
+ acl_handle_1, lcid_1));
+}
+
+TEST_F(StackRfcommTest, SingleClientConnectionHelloWorld) {
+ static const uint16_t acl_handle = 0x0009;
+ static const uint16_t lcid = 0x0054;
+ static const uint16_t test_uuid = 0x1112;
+ static const uint8_t test_scn = 8;
+ static const uint16_t test_mtu = 1600;
+ static const RawAddress test_address = GetTestAddress(0);
+ uint16_t client_handle = 0;
+ ASSERT_NO_FATAL_FAILURE(StartClientPort(
+ test_address, test_uuid, test_scn, test_mtu, port_mgmt_cback_0,
+ port_event_cback_0, lcid, acl_handle, &client_handle, true));
+ ASSERT_NO_FATAL_FAILURE(TestConnectClientPortL2cap(acl_handle, lcid));
+ ASSERT_NO_FATAL_FAILURE(ConnectClientPort(test_address, client_handle,
+ test_scn, test_mtu, acl_handle,
+ lcid, 0, true));
+ ASSERT_NO_FATAL_FAILURE(SendAndVerifyOutgoingTransmission(
+ client_handle, false, test_scn, true, "\r!dlroW olleH", -1, acl_handle,
+ lcid));
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ client_handle, false, test_scn, false, "Hello World!\r", -1, acl_handle,
+ lcid, 0));
+}
+
+TEST_F(StackRfcommTest, MultiClientPortSameDeviceHelloWorld) {
+ static const uint16_t acl_handle = 0x0009;
+ static const uint16_t lcid = 0x0054;
+ static const uint16_t test_mtu = 1600;
+ static const RawAddress test_address = GetTestAddress(0);
+
+ // Connection 0
+ static const uint16_t test_uuid_0 = 0x1112;
+ static const uint8_t test_scn_0 = 8;
+ uint16_t client_handle_0 = 0;
+ ASSERT_NO_FATAL_FAILURE(StartClientPort(
+ test_address, test_uuid_0, test_scn_0, test_mtu, port_mgmt_cback_0,
+ port_event_cback_0, lcid, acl_handle, &client_handle_0, true));
+ ASSERT_NO_FATAL_FAILURE(TestConnectClientPortL2cap(acl_handle, lcid));
+ ASSERT_NO_FATAL_FAILURE(ConnectClientPort(test_address, client_handle_0,
+ test_scn_0, test_mtu, acl_handle,
+ lcid, 0, true));
+
+ // Connection 1
+ static const uint16_t test_uuid_1 = 0x111F;
+ static const uint8_t test_scn_1 = 10;
+ uint16_t client_handle_1 = 0;
+ ASSERT_NO_FATAL_FAILURE(StartClientPort(
+ test_address, test_uuid_1, test_scn_1, test_mtu, port_mgmt_cback_1,
+ port_event_cback_1, lcid, acl_handle, &client_handle_1, false));
+ ASSERT_NO_FATAL_FAILURE(ConnectClientPort(test_address, client_handle_1,
+ test_scn_1, test_mtu, acl_handle,
+ lcid, 1, false));
+
+ // Use connection 0
+ ASSERT_NO_FATAL_FAILURE(SendAndVerifyOutgoingTransmission(
+ client_handle_0, false, test_scn_0, true, "\r!dlroW olleH", -1,
+ acl_handle, lcid));
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ client_handle_0, false, test_scn_0, false, "Hello World!\r", -1,
+ acl_handle, lcid, 0));
+
+ // Use connection 1
+ ASSERT_NO_FATAL_FAILURE(SendAndVerifyOutgoingTransmission(
+ client_handle_1, false, test_scn_1, true, "\r!dlroW olleH", -1,
+ acl_handle, lcid));
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ client_handle_1, false, test_scn_1, false, "Hello World!\r", -1,
+ acl_handle, lcid, 1));
+}
+
+TEST_F(StackRfcommTest, SameClientPortMultiDeviceHelloWorld) {
+ static const uint16_t test_uuid = 0x1112;
+ static const uint8_t test_scn = 8;
+ static const uint16_t test_mtu = 1600;
+
+ // Connection 0
+ static const RawAddress test_address_0 = GetTestAddress(0);
+ static const uint16_t acl_handle_0 = 0x0009;
+ static const uint16_t lcid_0 = 0x0054;
+ uint16_t client_handle_0 = 0;
+ ASSERT_NO_FATAL_FAILURE(StartClientPort(
+ test_address_0, test_uuid, test_scn, test_mtu, port_mgmt_cback_0,
+ port_event_cback_0, lcid_0, acl_handle_0, &client_handle_0, true));
+ ASSERT_NO_FATAL_FAILURE(TestConnectClientPortL2cap(acl_handle_0, lcid_0));
+ ASSERT_NO_FATAL_FAILURE(ConnectClientPort(test_address_0, client_handle_0,
+ test_scn, test_mtu, acl_handle_0,
+ lcid_0, 0, true));
+
+ // Connection 1
+ static const RawAddress test_address_1 = GetTestAddress(1);
+ static const uint16_t acl_handle_1 = 0x0012;
+ static const uint16_t lcid_1 = 0x0045;
+ uint16_t client_handle_1 = 0;
+ ASSERT_NO_FATAL_FAILURE(StartClientPort(
+ test_address_1, test_uuid, test_scn, test_mtu, port_mgmt_cback_1,
+ port_event_cback_1, lcid_1, acl_handle_1, &client_handle_1, true));
+ ASSERT_NO_FATAL_FAILURE(TestConnectClientPortL2cap(acl_handle_1, lcid_1));
+ ASSERT_NO_FATAL_FAILURE(ConnectClientPort(test_address_1, client_handle_1,
+ test_scn, test_mtu, acl_handle_1,
+ lcid_1, 1, true));
+
+ // Use connection 0
+ ASSERT_NO_FATAL_FAILURE(SendAndVerifyOutgoingTransmission(
+ client_handle_0, false, test_scn, true, "\r!dlroW olleH", -1,
+ acl_handle_0, lcid_0));
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ client_handle_0, false, test_scn, false, "Hello World!\r", -1,
+ acl_handle_0, lcid_0, 0));
+
+ // Use connection 1
+ ASSERT_NO_FATAL_FAILURE(SendAndVerifyOutgoingTransmission(
+ client_handle_1, false, test_scn, true, "\r!dlroW olleH", -1,
+ acl_handle_1, lcid_1));
+ ASSERT_NO_FATAL_FAILURE(ReceiveAndVerifyIncomingTransmission(
+ client_handle_1, false, test_scn, false, "Hello World!\r", -1,
+ acl_handle_1, lcid_1, 1));
+}
+
+TEST_F(StackRfcommTest, TestConnectionCollision) {
+ static const uint16_t acl_handle = 0x0008;
+ static const uint16_t old_lcid = 0x004a;
+ static const uint16_t new_lcid = 0x005c;
+ static const uint16_t test_uuid = 0x1112;
+ static const uint8_t test_server_scn = 3;
+ static const uint8_t test_peer_scn = 10;
+ // Must be smaller than L2CAP_MTU_SIZE by at least 4 bytes
+ static const uint16_t test_mtu = 1000;
+ static const RawAddress test_address = GetTestAddress(0);
+ uint16_t server_handle = 0;
+ VLOG(1) << "Step 1";
+ // Prepare a server port
+ int status = RFCOMM_CreateConnection(test_uuid, test_server_scn, true,
+ test_mtu, RawAddress::kAny,
+ &server_handle, port_mgmt_cback_0);
+ ASSERT_EQ(status, PORT_SUCCESS);
+ status = PORT_SetEventMask(server_handle, PORT_EV_RXCHAR);
+ ASSERT_EQ(status, PORT_SUCCESS);
+ status = PORT_SetEventCallback(server_handle, port_event_cback_0);
+ ASSERT_EQ(status, PORT_SUCCESS);
+
+ VLOG(1) << "Step 2";
+ // Try to connect to a client port
+ uint16_t client_handle_1 = 0;
+ EXPECT_CALL(l2cap_interface_, ConnectRequest(BT_PSM_RFCOMM, test_address))
+ .Times(1)
+ .WillOnce(Return(old_lcid));
+ status = RFCOMM_CreateConnection(test_uuid, test_peer_scn, false, test_mtu,
+ test_address, &client_handle_1,
+ port_mgmt_cback_1);
+ ASSERT_EQ(status, PORT_SUCCESS);
+ status = PORT_SetEventMask(client_handle_1, PORT_EV_RXCHAR);
+ ASSERT_EQ(status, PORT_SUCCESS);
+ status = PORT_SetEventCallback(client_handle_1, port_event_cback_1);
+ ASSERT_EQ(status, PORT_SUCCESS);
+
+ VLOG(1) << "Step 3";
+ // While our connection is pending, remote device tries to connect to
+ // new_lcid, with L2CAP command id: pending_cmd_id
+ static const uint8_t pending_cmd_id = 0x05;
+ // RFCOMM starts timer for collision:
+ l2cap_appl_info_.pL2CA_ConnectInd_Cb(test_address, new_lcid, BT_PSM_RFCOMM,
+ pending_cmd_id);
+
+ VLOG(1) << "Step 4";
+ // Remote reject our connection request saying PSM not allowed
+ // This should trigger RFCOMM to accept remote L2CAP connection at new_lcid
+ EXPECT_CALL(l2cap_interface_, ConnectResponse(test_address, pending_cmd_id,
+ new_lcid, L2CAP_CONN_OK, 0))
+ .WillOnce(Return(true));
+ // Followed by configure request for MTU size
+ tL2CAP_CFG_INFO our_cfg_req = {.mtu_present = true, .mtu = L2CAP_MTU_SIZE};
+ EXPECT_CALL(l2cap_interface_,
+ ConfigRequest(new_lcid, PointerMemoryEqual(&our_cfg_req)))
+ .WillOnce(Return(true));
+ l2cap_appl_info_.pL2CA_ConnectCfm_Cb(old_lcid, L2CAP_CONN_NO_PSM);
+
+ VLOG(1) << "Step 5";
+ // Remote device also ask to configure MTU size as well
+ tL2CAP_CFG_INFO peer_cfg_req = {.mtu_present = true, .mtu = test_mtu};
+ // We responded by saying OK
+ tL2CAP_CFG_INFO our_cfg_rsp = {.result = L2CAP_CFG_OK,
+ .mtu = peer_cfg_req.mtu};
+ EXPECT_CALL(l2cap_interface_,
+ ConfigResponse(new_lcid, PointerMemoryEqual(&our_cfg_rsp)))
+ .WillOnce(Return(true));
+ l2cap_appl_info_.pL2CA_ConfigInd_Cb(new_lcid, &peer_cfg_req);
+
+ VLOG(1) << "Step 6";
+ // Remote device accepted our MTU size
+ tL2CAP_CFG_INFO peer_cfg_rsp = {.mtu_present = true, .mtu = L2CAP_MTU_SIZE};
+ l2cap_appl_info_.pL2CA_ConfigCfm_Cb(new_lcid, &peer_cfg_rsp);
+
+ // L2CAP collision and connection setup done
+
+ VLOG(1) << "Step 7";
+ // Remote device connect multiplexer channel
+ BT_HDR* sabm_channel_0 = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickSabmPacket(RFCOMM_MX_DLCI, new_lcid, acl_handle));
+ // We accept
+ BT_HDR* ua_channel_0 = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickUaPacket(RFCOMM_MX_DLCI, new_lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_, DataWrite(new_lcid, BtHdrEqual(ua_channel_0)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ // And immediately try to configure test_peer_scn
+ BT_HDR* uih_pn_cmd_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickPnPacket(false, GetDlci(true, test_peer_scn), true, test_mtu,
+ RFCOMM_PN_CONV_LAYER_CBFC_I >> 4, 0, RFCOMM_K_MAX,
+ new_lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(new_lcid, BtHdrEqual(uih_pn_cmd_to_peer)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ // Packet should be freed by this method
+ l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, sabm_channel_0);
+ osi_free(ua_channel_0);
+ osi_free(uih_pn_cmd_to_peer);
+
+ VLOG(1) << "Step 8";
+ // Peer tries to configure test_server_scn
+ BT_HDR* uih_pn_cmd_from_peer = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickPnPacket(true, GetDlci(false, test_server_scn), true, test_mtu,
+ RFCOMM_PN_CONV_LAYER_CBFC_I >> 4, 0, RFCOMM_K_MAX,
+ new_lcid, acl_handle));
+ // We, as acceptor, must accept
+ BT_HDR* uih_pn_rsp_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickPnPacket(false, GetDlci(false, test_server_scn), false,
+ test_mtu, RFCOMM_PN_CONV_LAYER_CBFC_R >> 4, 0,
+ RFCOMM_K_MAX, new_lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(new_lcid, BtHdrEqual(uih_pn_rsp_to_peer)))
+ .Times(1)
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, uih_pn_cmd_from_peer);
+ osi_free(uih_pn_rsp_to_peer);
+
+ VLOG(1) << "Step 9";
+ // Remote never replies our configuration request for test_peer_scn
+ // But instead connect to test_server_scn directly
+ BT_HDR* sabm_server_scn =
+ AllocateWrappedIncomingL2capAclPacket(CreateQuickSabmPacket(
+ GetDlci(false, test_server_scn), new_lcid, acl_handle));
+ // We must do security check first
+ tBTM_SEC_CALLBACK* security_callback = nullptr;
+ void* p_port = nullptr;
+ EXPECT_CALL(btm_security_internal_interface_,
+ MultiplexingProtocolAccessRequest(
+ test_address, BT_PSM_RFCOMM, false, BTM_SEC_PROTO_RFCOMM,
+ test_server_scn, NotNull(), NotNull()))
+ .WillOnce(DoAll(SaveArg<5>(&security_callback), SaveArg<6>(&p_port),
+ Return(BTM_SUCCESS)));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, sabm_server_scn);
+
+ VLOG(1) << "Step 10";
+ // After security check, we accept the connection
+ ASSERT_TRUE(security_callback);
+ BT_HDR* ua_server_scn =
+ AllocateWrappedOutgoingL2capAclPacket(CreateQuickUaPacket(
+ GetDlci(false, test_server_scn), new_lcid, acl_handle));
+ EXPECT_CALL(l2cap_interface_, DataWrite(new_lcid, BtHdrEqual(ua_server_scn)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ // Callback should come from server port instead, client port will timeout
+ // in 20 seconds
+ EXPECT_CALL(rfcomm_callback_,
+ PortManagementCallback(PORT_SUCCESS, server_handle, 0));
+ security_callback(&test_address, BT_TRANSPORT_BR_EDR, p_port, BTM_SUCCESS);
+ osi_free(ua_server_scn);
+
+ VLOG(1) << "Step 11";
+ // MPX_CTRL Modem Status Command (MSC)
+ BT_HDR* uih_msc_cmd_from_peer = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickMscPacket(true, GetDlci(false, test_server_scn), new_lcid,
+ acl_handle, true, false, true, true, false, true));
+ BT_HDR* uih_msc_rsp_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickMscPacket(false, GetDlci(false, test_server_scn), new_lcid,
+ acl_handle, false, false, true, true, false, true));
+ // MPX_CTRL Modem Status Response (MSC)
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(new_lcid, BtHdrEqual(uih_msc_rsp_to_peer)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ BT_HDR* uih_msc_cmd_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+ CreateQuickMscPacket(false, GetDlci(false, test_server_scn), new_lcid,
+ acl_handle, true, false, true, true, false, true));
+ EXPECT_CALL(l2cap_interface_,
+ DataWrite(new_lcid, BtHdrEqual(uih_msc_cmd_to_peer)))
+ .WillOnce(Return(L2CAP_DW_SUCCESS));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, uih_msc_cmd_from_peer);
+ osi_free(uih_msc_rsp_to_peer);
+ osi_free(uih_msc_cmd_to_peer);
+
+ VLOG(1) << "Step 12";
+ BT_HDR* uih_msc_rsp_from_peer = AllocateWrappedIncomingL2capAclPacket(
+ CreateQuickMscPacket(true, GetDlci(false, test_server_scn), new_lcid,
+ acl_handle, false, false, true, true, false, true));
+ l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, uih_msc_rsp_from_peer);
+}
+
+} // namespace
diff --git a/stack/test/rfcomm/stack_rfcomm_test_main.cc b/stack/test/rfcomm/stack_rfcomm_test_main.cc
new file mode 100644
index 0000000..b6a7b25
--- /dev/null
+++ b/stack/test/rfcomm/stack_rfcomm_test_main.cc
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <base/command_line.h>
+#include <base/logging.h>
+#include <base/strings/string_piece.h>
+#include <base/strings/string_util.h>
+#include <gtest/gtest.h>
+
+#include <string>
+
+#include "bt_trace.h"
+
+// Override LogMsg method so that we can output log via VLOG(1)
+void LogMsg(uint32_t trace_set_mask, const char* fmt_str, ...) {
+ char buffer[256];
+ va_list args;
+ va_start(args, fmt_str);
+ vsnprintf(buffer, 256, fmt_str, args);
+ VLOG(1) << buffer;
+ va_end(args);
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ if (base::CommandLine::InitializedForCurrentProcess()) {
+ LOG(FATAL) << "base::CommandLine::Init should not be called twice";
+ return 1;
+ }
+
+ const char* log_level_arg = nullptr;
+ for (int i = 0; i < argc; ++i) {
+ if (base::StartsWith(base::StringPiece(argv[i]), base::StringPiece("--v="),
+ base::CompareCase::INSENSITIVE_ASCII)) {
+ log_level_arg = argv[i];
+ }
+ }
+ if (log_level_arg == nullptr) {
+ log_level_arg = "--v=0";
+ }
+ const char* logging_argv[] = {"bt_stack", log_level_arg};
+ // Init command line object with logging switches
+ if (!base::CommandLine::Init(2, logging_argv)) {
+ LOG(FATAL) << "base::CommandLine::Init failed, arg0=" << logging_argv[0]
+ << ", arg1=" << logging_argv[1];
+ return 1;
+ }
+
+ logging::LoggingSettings log_settings;
+ if (!logging::InitLogging(log_settings)) {
+ LOG(ERROR) << "Failed to set up logging";
+ }
+
+ // Android already logs thread_id, proc_id, timestamp, so disable those.
+ logging::SetLogItems(false, false, false, false);
+
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/stack/test/rfcomm/stack_rfcomm_test_utils.cc b/stack/test/rfcomm/stack_rfcomm_test_utils.cc
new file mode 100644
index 0000000..f7745c9
--- /dev/null
+++ b/stack/test/rfcomm/stack_rfcomm_test_utils.cc
@@ -0,0 +1,223 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <bitset>
+#include <string>
+#include <vector>
+
+#include "rfc_int.h"
+#include "stack_test_packet_utils.h"
+
+#include "stack_rfcomm_test_utils.h"
+
+namespace bluetooth {
+namespace rfcomm {
+
+uint8_t GetDlci(bool on_originator_side, uint8_t scn) {
+ return static_cast<uint8_t>((scn << 1) + (on_originator_side ? 1 : 0));
+}
+
+uint8_t GetAddressField(bool ea, bool cr, uint8_t dlci) {
+ std::bitset<8> address;
+ address.set(0, ea);
+ // For UIH frame, cr for initiating device is 1, otherwise 0
+ // Otherwise:
+ // Command: Initiator -> Responder: 1
+ // Command: Responder -> Initiator 0
+ // Response: Initiator -> Responder 0
+ // Response: Responder -> Initiator 1
+ // Initiator is defined by the one who send SABM=1 command
+ address.set(1, cr);
+ address |= dlci << 2;
+ return static_cast<uint8_t>(address.to_ulong());
+}
+
+uint8_t GetControlField(bool pf, uint8_t frame_type) {
+ std::bitset<8> control;
+ control |= frame_type;
+ control.set(4, pf);
+ return static_cast<uint8_t>(control.to_ulong());
+}
+
+uint8_t GetFrameTypeFromControlField(uint8_t control_field) {
+ return static_cast<uint8_t>(control_field & ~(0b10000));
+}
+
+std::vector<uint8_t> CreateMccPnFrame(uint8_t dlci, uint8_t i_bits,
+ uint8_t cl_bits, uint8_t priority,
+ uint8_t timer_value, uint16_t rfcomm_mtu,
+ uint8_t max_num_retransmission,
+ uint8_t err_recovery_window_k) {
+ // Data in little endian order
+ std::vector<uint8_t> result;
+ result.push_back(static_cast<uint8_t>(dlci & 0b00111111));
+ result.push_back(static_cast<uint8_t>((cl_bits << 4) | (i_bits & 0x0F)));
+ result.push_back(static_cast<uint8_t>(priority & 0b00111111));
+ result.push_back(timer_value);
+ result.push_back(static_cast<uint8_t>(rfcomm_mtu));
+ result.push_back(static_cast<uint8_t>(rfcomm_mtu >> 8));
+ result.push_back(max_num_retransmission);
+ result.push_back(static_cast<uint8_t>(err_recovery_window_k & 0b111));
+ return result;
+}
+
+std::vector<uint8_t> CreateMccMscFrame(uint8_t dlci, bool fc, bool rtc,
+ bool rtr, bool ic, bool dv) {
+ // Data in little endian order
+ std::vector<uint8_t> result;
+ result.push_back(static_cast<uint8_t>((dlci << 2) | 0b11));
+ std::bitset<8> v24_signals;
+ // EA = 1, single byte
+ v24_signals.set(0, true);
+ v24_signals.set(1, fc);
+ v24_signals.set(2, rtc);
+ v24_signals.set(3, rtr);
+ v24_signals.set(6, ic);
+ v24_signals.set(7, dv);
+ result.push_back(static_cast<uint8_t>(v24_signals.to_ulong()));
+ return result;
+}
+
+std::vector<uint8_t> CreateMultiplexerControlFrame(
+ uint8_t command_type, bool cr, const std::vector<uint8_t>& data) {
+ // Data in little endian order
+ std::vector<uint8_t> result;
+ std::bitset<8> header;
+ header.set(0, true); // EA is always 1
+ header.set(1, cr);
+ header |= command_type << 2;
+ result.push_back(static_cast<uint8_t>(header.to_ulong()));
+ // 7 bit length + EA(1)
+ result.push_back(static_cast<uint8_t>((data.size() << 1) + 1));
+ result.insert(result.end(), data.begin(), data.end());
+ return result;
+}
+
+std::vector<uint8_t> CreateRfcommPacket(uint8_t address, uint8_t control,
+ int credits,
+ const std::vector<uint8_t>& data) {
+ // Data in little endian order
+ std::vector<uint8_t> result;
+ result.push_back(address);
+ result.push_back(control);
+ size_t length = data.size();
+ if ((length & 0b1000000) != 0) {
+ // 15 bits of length in little endian order + EA(0)
+ // Lower 7 bits + EA(0)
+ result.push_back(static_cast<uint8_t>(length) << 1);
+ // Upper 8 bits
+ result.push_back(static_cast<uint8_t>(length >> 8));
+ } else {
+ // 7 bits of length + EA(1)
+ result.push_back(static_cast<uint8_t>((length << 1) + 1));
+ }
+ if (credits > 0) {
+ result.push_back(static_cast<uint8_t>(credits));
+ }
+ result.insert(result.end(), data.begin(), data.end());
+ if (GetFrameTypeFromControlField(control) == RFCOMM_UIH) {
+ result.push_back(rfc_calc_fcs(2, result.data()));
+ } else {
+ result.push_back(
+ rfc_calc_fcs(static_cast<uint16_t>(result.size()), result.data()));
+ }
+ return result;
+}
+
+std::vector<uint8_t> CreateQuickUaPacket(uint8_t dlci, uint16_t l2cap_lcid,
+ uint16_t acl_handle) {
+ uint8_t address_field = GetAddressField(true, true, dlci);
+ uint8_t control_field = GetControlField(true, RFCOMM_UA);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, {});
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(l2cap_lcid, rfcomm_packet);
+ return CreateAclPacket(acl_handle, 0b10, 0b00, l2cap_packet);
+}
+
+std::vector<uint8_t> CreateQuickSabmPacket(uint8_t dlci, uint16_t l2cap_lcid,
+ uint16_t acl_handle) {
+ uint8_t address_field = GetAddressField(true, true, dlci);
+ uint8_t control_field = GetControlField(true, RFCOMM_SABME);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, {});
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(l2cap_lcid, rfcomm_packet);
+ return CreateAclPacket(acl_handle, 0b10, 0b00, l2cap_packet);
+}
+
+std::vector<uint8_t> CreateQuickPnPacket(bool rfc_cr, uint8_t target_dlci,
+ bool mx_cr, uint16_t rfc_mtu,
+ uint8_t cl, uint8_t priority,
+ uint8_t k, uint16_t l2cap_lcid,
+ uint16_t acl_handle) {
+ uint8_t address_field = GetAddressField(true, rfc_cr, RFCOMM_MX_DLCI);
+ uint8_t control_field = GetControlField(false, RFCOMM_UIH);
+ std::vector<uint8_t> mcc_pn_data = CreateMccPnFrame(
+ target_dlci, 0x0, cl, priority, RFCOMM_T1_DSEC, rfc_mtu, RFCOMM_N2, k);
+ std::vector<uint8_t> mcc_payload =
+ CreateMultiplexerControlFrame(0x20, mx_cr, mcc_pn_data);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, mcc_payload);
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(l2cap_lcid, rfcomm_packet);
+ return CreateAclPacket(acl_handle, 0b10, 0b00, l2cap_packet);
+}
+
+std::vector<uint8_t> CreateQuickMscPacket(bool rfc_cr, uint8_t dlci,
+ uint16_t l2cap_lcid,
+ uint16_t acl_handle, bool mx_cr,
+ bool fc, bool rtc, bool rtr, bool ic,
+ bool dv) {
+ uint8_t address_field = GetAddressField(true, rfc_cr, RFCOMM_MX_DLCI);
+ uint8_t control_field = GetControlField(false, RFCOMM_UIH);
+ std::vector<uint8_t> mcc_msc_data =
+ CreateMccMscFrame(dlci, fc, rtc, rtr, ic, dv);
+ std::vector<uint8_t> mcc_payload =
+ CreateMultiplexerControlFrame(0x38, mx_cr, mcc_msc_data);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, mcc_payload);
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(l2cap_lcid, rfcomm_packet);
+ return CreateAclPacket(acl_handle, 0b10, 0b00, l2cap_packet);
+}
+
+std::vector<uint8_t> CreateQuickDataPacket(uint8_t dlci, bool cr,
+ uint16_t l2cap_lcid,
+ uint16_t acl_handle, int credits,
+ const std::vector<uint8_t>& data) {
+ uint8_t address_field = GetAddressField(true, cr, dlci);
+ uint8_t control_field =
+ GetControlField(credits > 0 ? true : false, RFCOMM_UIH);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, credits, data);
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(l2cap_lcid, rfcomm_packet);
+ return CreateAclPacket(acl_handle, 0b10, 0b00, l2cap_packet);
+}
+
+std::vector<uint8_t> CreateQuickDataPacket(uint8_t dlci, bool cr,
+ uint16_t l2cap_lcid,
+ uint16_t acl_handle, int credits,
+ const std::string& str) {
+ std::vector<uint8_t> data(str.begin(), str.end());
+ return CreateQuickDataPacket(dlci, cr, l2cap_lcid, acl_handle, credits, data);
+}
+
+} // namespace rfcomm
+} // namespace bluetooth
\ No newline at end of file
diff --git a/stack/test/rfcomm/stack_rfcomm_test_utils.h b/stack/test/rfcomm/stack_rfcomm_test_utils.h
new file mode 100644
index 0000000..c7fee43
--- /dev/null
+++ b/stack/test/rfcomm/stack_rfcomm_test_utils.h
@@ -0,0 +1,232 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#pragma once
+
+#include <vector>
+
+#include <gmock/gmock.h>
+
+#include "bt_types.h"
+
+namespace bluetooth {
+namespace rfcomm {
+
+class RfcommCallback {
+ public:
+ virtual void PortManagementCallback(uint32_t code, uint16_t port_handle,
+ uint16_t callback_index) = 0;
+ virtual void PortEventCallback(uint32_t code, uint16_t port_handle,
+ uint16_t callback_index) = 0;
+ virtual ~RfcommCallback() = default;
+};
+
+class MockRfcommCallback : public RfcommCallback {
+ public:
+ MOCK_METHOD3(PortManagementCallback, void(uint32_t code, uint16_t port_handle,
+ uint16_t callback_index));
+ MOCK_METHOD3(PortEventCallback, void(uint32_t code, uint16_t port_handle,
+ uint16_t callback_index));
+};
+
+/**
+ * Create DLCI using direction of service channel number
+ *
+ * @param on_originator_side is this a channel on initiator side
+ * @param scn service channel number
+ * @return DLCI
+ */
+uint8_t GetDlci(bool on_originator_side, uint8_t scn);
+
+/**
+ * Create address field in RFCOMM packet
+ *
+ * @param ea end of field byte, true if field only has 1 byte, false otherwise
+ * @param cr command and response bit, true if packet is from initiator,
+ * false otherwise, not actual "command" and "response"
+ * @param dlci DLCI of this pcaket, RFCOMM_MX_DLCI for multiplexer control
+ * @return address field
+ */
+uint8_t GetAddressField(bool ea, bool cr, uint8_t dlci);
+
+/**
+ * Create control field in RFCOMM packet
+ *
+ * @param pf Poll/Finish bit, normally 1 for multiplexer control channel
+ * @param frame_type frame type
+ * @return control field
+ */
+uint8_t GetControlField(bool pf, uint8_t frame_type);
+
+/**
+ * Create Multiplexer control channel parameter negotiation frame
+ *
+ * @param dlci DLCI to be configured
+ * @param i_bits i bits
+ * @param cl_bits cl bits
+ * @param priority priority
+ * @param timer_value timer value
+ * @param rfcomm_mtu rfcomm mtu
+ * @param max_num_retransmission maximum number of retransmission
+ * @param err_recovery_window_k error recovery window k
+ * @return vector of bytes of this frame
+ */
+std::vector<uint8_t> CreateMccPnFrame(uint8_t dlci, uint8_t i_bits,
+ uint8_t cl_bits, uint8_t priority,
+ uint8_t timer_value, uint16_t rfcomm_mtu,
+ uint8_t max_num_retransmission,
+ uint8_t err_recovery_window_k);
+/**
+ * Create Multiplexer Control Modem Status Configuration Frame
+ *
+ * @param dlci DLCI to be configured
+ * @param fc flow control
+ * @param rtc ready to communicate
+ * @param rtr ready to receive
+ * @param ic incoming call indicator
+ * @param dv is data valid
+ * @return vector of bytes
+ */
+std::vector<uint8_t> CreateMccMscFrame(uint8_t dlci, bool fc, bool rtc,
+ bool rtr, bool ic, bool dv);
+
+/**
+ * Create Multiplexer Control Frame
+ *
+ * @param command_type type of command
+ * @param cr command or response flag, true when this is a command, false when
+ * this is a response, regardless of connection direction
+ * @param data frame data
+ * @return vector of bytes
+ */
+std::vector<uint8_t> CreateMultiplexerControlFrame(
+ uint8_t command_type, bool cr, const std::vector<uint8_t>& data);
+
+/**
+ * Create a general RFCOMM packet
+ *
+ * @param address address byte
+ * @param control control byte
+ * @param credits number of credits, <= 0 will cause this to be ignored
+ * @param data frame data
+ * @return vector of bytes
+ */
+std::vector<uint8_t> CreateRfcommPacket(uint8_t address, uint8_t control,
+ int credits,
+ const std::vector<uint8_t>& data);
+/*
+ * Various shortcut for getting frequently used packets
+ */
+
+/**
+ * Create SABM packet that is used to connect to a service channel number in a
+ * multiplexer
+ *
+ * @param dlci DLCI to be connected
+ * @param l2cap_lcid L2CAP channel ID
+ * @param acl_handle ACL handle
+ * @return vector of bytes of unwrapped ACL packet
+ */
+std::vector<uint8_t> CreateQuickSabmPacket(uint8_t dlci, uint16_t l2cap_lcid,
+ uint16_t acl_handle);
+
+/**
+ * Create UA packet that is used to acknowledge service channel connection
+ *
+ * @param dlci DLCI to be connected
+ * @param l2cap_lcid L2CAP channel ID
+ * @param acl_handle ACL handle
+ * @return vector of bytes of unwrapped ACL packet
+ */
+std::vector<uint8_t> CreateQuickUaPacket(uint8_t dlci, uint16_t l2cap_lcid,
+ uint16_t acl_handle);
+
+/**
+ * Create parameter negotiation packet used to setup parameters for a DLCI
+ *
+ * @param rfc_cr RFCOMM command/response bit, true of initiator
+ * @param target_dlci DLCI to be configured
+ * @param mx_cr multiplexer command or reponse, regardless of initiator
+ * @param rfc_mtu RFCOMM mtu to be used for DLCI
+ * @param cl CL bit
+ * @param priority prirority
+ * @param k error recovery window k
+ * @param l2cap_lcid L2CAP channel ID
+ * @param acl_handle ACL handle
+ * @return vector of bytes of unwrapped ACL packet
+ */
+std::vector<uint8_t> CreateQuickPnPacket(bool rfc_cr, uint8_t target_dlci,
+ bool mx_cr, uint16_t rfc_mtu,
+ uint8_t cl, uint8_t priority,
+ uint8_t k, uint16_t l2cap_lcid,
+ uint16_t acl_handle);
+
+/**
+ * Create modem signal control packet
+ *
+ * @param rfc_cr RFCOMM command/response bit, true of initiator
+ * @param dlci DLCI to be configured
+ * @param l2cap_lcid L2CAP channel ID
+ * @param acl_handle ACL handle
+ * @param mx_cr multiplexer command or reponse, regardless of initiator
+ * @param fc flow control
+ * @param rtc ready to communicate
+ * @param rtr ready to receive
+ * @param ic incoming call indicator
+ * @param dv data valid
+ * @return vector of bytes of unwrapped ACL packet
+ */
+std::vector<uint8_t> CreateQuickMscPacket(bool rfc_cr, uint8_t dlci,
+ uint16_t l2cap_lcid,
+ uint16_t acl_handle, bool mx_cr,
+ bool fc, bool rtc, bool rtr, bool ic,
+ bool dv);
+
+/**
+ * Create a quick RFCOMM data packet
+ *
+ * @param dlci DLCI of this packet
+ * @param cr command or control, true for initiator
+ * @param l2cap_lcid L2CAP channel ID
+ * @param acl_handle ACL handle
+ * @param credits number of credits
+ * @param data data bytes
+ * @return vector of bytes of unwrapped ACL packet
+ */
+std::vector<uint8_t> CreateQuickDataPacket(uint8_t dlci, bool cr,
+ uint16_t l2cap_lcid,
+ uint16_t acl_handle, int credits,
+ const std::vector<uint8_t>& data);
+
+/**
+ * Create a quick RFCOMM data packet
+ *
+ * @param dlci DLCI of this packet
+ * @param cr command or control, true for initiator
+ * @param l2cap_lcid L2CAP channel ID
+ * @param acl_handle ACL handle
+ * @param credits number of credits
+ * @param str message in string format
+ * @return vector of bytes of unwrapped ACL packet
+ */
+std::vector<uint8_t> CreateQuickDataPacket(uint8_t dlci, bool cr,
+ uint16_t l2cap_lcid,
+ uint16_t acl_handle, int credits,
+ const std::string& str);
+
+} // namespace rfcomm
+} // namespace bluetooth
\ No newline at end of file
diff --git a/stack/test/rfcomm/stack_rfcomm_test_utils_test.cc b/stack/test/rfcomm/stack_rfcomm_test_utils_test.cc
new file mode 100644
index 0000000..3d9a2d5
--- /dev/null
+++ b/stack/test/rfcomm/stack_rfcomm_test_utils_test.cc
@@ -0,0 +1,246 @@
+/******************************************************************************
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <string>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "rfcdefs.h"
+#include "stack_rfcomm_test_utils.h"
+#include "stack_test_packet_utils.h"
+
+namespace {
+
+using testing::ElementsAreArray;
+
+using bluetooth::CreateL2capDataPacket;
+using bluetooth::CreateAclPacket;
+using bluetooth::AllocateWrappedIncomingL2capAclPacket;
+
+using bluetooth::rfcomm::GetDlci;
+using bluetooth::rfcomm::GetAddressField;
+using bluetooth::rfcomm::GetControlField;
+using bluetooth::rfcomm::CreateMccPnFrame;
+using bluetooth::rfcomm::CreateMccMscFrame;
+using bluetooth::rfcomm::CreateMultiplexerControlFrame;
+using bluetooth::rfcomm::CreateRfcommPacket;
+using bluetooth::rfcomm::CreateQuickDataPacket;
+using bluetooth::rfcomm::CreateQuickPnPacket;
+using bluetooth::rfcomm::CreateQuickSabmPacket;
+using bluetooth::rfcomm::CreateQuickUaPacket;
+using bluetooth::rfcomm::CreateQuickMscPacket;
+
+const uint8_t kIncomingSabmChannel0[] = {0x08, 0x20, 0x08, 0x00, 0x04, 0x00,
+ 0x5c, 0x00, 0x03, 0x3f, 0x01, 0x1c};
+
+TEST(RfcommTestPacketGeneratorTest, TestGenerateSabmChannel0Packet) {
+ uint8_t dlci = GetDlci(false, 0);
+ EXPECT_EQ(dlci, 0);
+ uint8_t address_field = GetAddressField(true, true, dlci);
+ EXPECT_EQ(address_field, 0x03);
+ uint8_t control_field = GetControlField(true, RFCOMM_SABME);
+ EXPECT_EQ(control_field, 0x3F);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, {});
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(0x005c, rfcomm_packet);
+ std::vector<uint8_t> acl_packet =
+ CreateAclPacket(0x0008, 0b10, 0b00, l2cap_packet);
+ EXPECT_THAT(acl_packet, ElementsAreArray(kIncomingSabmChannel0));
+}
+
+TEST(RfcommTestPacketGeneratorTest, TestQuickGenerateSabmChannel0Packet) {
+ EXPECT_THAT(CreateQuickSabmPacket(RFCOMM_MX_DLCI, 0x005c, 0x0008),
+ ElementsAreArray(kIncomingSabmChannel0));
+}
+
+const uint8_t kOutgoingUaChannel0[] = {0x08, 0x20, 0x08, 0x00, 0x04, 0x00,
+ 0x00, 0x17, 0x03, 0x73, 0x01, 0xd7};
+
+TEST(RfcommTestPacketGeneratorTest, TestGenerateUaPacket) {
+ uint8_t dlci = GetDlci(false, 0);
+ EXPECT_EQ(dlci, 0);
+ uint8_t address_field = GetAddressField(true, true, dlci);
+ EXPECT_EQ(address_field, 0x03);
+ uint8_t control_field = GetControlField(true, RFCOMM_UA);
+ EXPECT_EQ(control_field, 0x73);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, {});
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(0x1700, rfcomm_packet);
+ std::vector<uint8_t> acl_packet =
+ CreateAclPacket(0x0008, 0b10, 0b00, l2cap_packet);
+ EXPECT_THAT(acl_packet, ElementsAreArray(kOutgoingUaChannel0));
+}
+
+TEST(RfcommTestPacketGeneratorTest, TestQuickGenerateUaPacket) {
+ EXPECT_THAT(CreateQuickUaPacket(RFCOMM_MX_DLCI, 0x1700, 0x0008),
+ ElementsAreArray(kOutgoingUaChannel0));
+}
+
+const uint8_t kIncomingUihPnSetChannelTo3[] = {
+ 0x08, 0x20, 0x12, 0x00, 0x0e, 0x00, 0x5c, 0x00, 0x03, 0xef, 0x15,
+ 0x83, 0x11, 0x06, 0xf0, 0x00, 0x00, 0x74, 0x03, 0x00, 0x01, 0x70};
+
+TEST(RfcommTestPacketGeneratorTest, TestGenerateUihPnSetChannel3Packet) {
+ uint8_t dlci = GetDlci(false, 0);
+ EXPECT_EQ(dlci, 0);
+ uint8_t address_field = GetAddressField(true, true, dlci);
+ EXPECT_EQ(address_field, 0x03);
+ uint8_t control_field = GetControlField(false, RFCOMM_UIH);
+ EXPECT_EQ(control_field, 0xEF);
+ uint8_t new_dlci = GetDlci(false, 3);
+ EXPECT_EQ(new_dlci, 6);
+ std::vector<uint8_t> mcc_pn_data =
+ CreateMccPnFrame(new_dlci, 0x0, 0xF, 0, 0, 884, 0, 1);
+ std::vector<uint8_t> mcc_payload =
+ CreateMultiplexerControlFrame(0x20, true, mcc_pn_data);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, mcc_payload);
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(0x005c, rfcomm_packet);
+ std::vector<uint8_t> acl_packet =
+ CreateAclPacket(0x0008, 0b10, 0b00, l2cap_packet);
+ EXPECT_THAT(acl_packet, ElementsAreArray(kIncomingUihPnSetChannelTo3));
+}
+
+TEST(RfcommTestPacketGeneratorTest, TestQuickGenerateUihPnSetChannel3Packet) {
+ EXPECT_THAT(CreateQuickPnPacket(true, GetDlci(false, 3), true, 884, 0xF, 0, 1,
+ 0x005c, 0x0008),
+ ElementsAreArray(kIncomingUihPnSetChannelTo3));
+}
+
+const uint8_t kIncomingSabmChannel3[] = {0x08, 0x20, 0x08, 0x00, 0x04, 0x00,
+ 0x5c, 0x00, 0x1b, 0x3f, 0x01, 0xd3};
+
+TEST(RfcommTestPacketGeneratorTest, TestGenerateSabmChannel3Packet) {
+ uint8_t dlci = GetDlci(false, 3);
+ EXPECT_EQ(dlci, 6);
+ uint8_t address_field = GetAddressField(true, true, dlci);
+ EXPECT_EQ(address_field, 0x1b);
+ uint8_t control_field = GetControlField(true, RFCOMM_SABME);
+ EXPECT_EQ(control_field, 0x3F);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, {});
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(0x005c, rfcomm_packet);
+ std::vector<uint8_t> acl_packet =
+ CreateAclPacket(0x0008, 0b10, 0b00, l2cap_packet);
+ EXPECT_THAT(acl_packet, ElementsAreArray(kIncomingSabmChannel3));
+}
+
+TEST(RfcommTestPacketGeneratorTest, TestGenerateQuickSabmChannel3Packet) {
+ EXPECT_THAT(CreateQuickSabmPacket(GetDlci(false, 3), 0x005c, 0x0008),
+ ElementsAreArray(kIncomingSabmChannel3));
+}
+
+const uint8_t kIncomingUihMscCmdFrame[] = {0x08, 0x20, 0x0c, 0x00, 0x08, 0x00,
+ 0x5c, 0x00, 0x03, 0xef, 0x09, 0xe3,
+ 0x05, 0x1b, 0x8d, 0x70};
+
+TEST(RfcommTestPacketGeneratorTest, TestGenerateUihMscCmdPacket) {
+ uint8_t dlci = GetDlci(false, 0);
+ EXPECT_EQ(dlci, 0);
+ uint8_t address_field = GetAddressField(true, true, dlci);
+ EXPECT_EQ(address_field, 0x03);
+ uint8_t control_field = GetControlField(false, RFCOMM_UIH);
+ EXPECT_EQ(control_field, 0xEF);
+ uint8_t new_dlci = GetDlci(false, 3);
+ EXPECT_EQ(new_dlci, 6);
+ std::vector<uint8_t> mcc_msc_data =
+ CreateMccMscFrame(new_dlci, false, true, true, false, true);
+ std::vector<uint8_t> mcc_payload =
+ CreateMultiplexerControlFrame(0x38, true, mcc_msc_data);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, mcc_payload);
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(0x005c, rfcomm_packet);
+ std::vector<uint8_t> acl_packet =
+ CreateAclPacket(0x0008, 0b10, 0b00, l2cap_packet);
+ EXPECT_THAT(acl_packet, ElementsAreArray(kIncomingUihMscCmdFrame));
+}
+
+TEST(RfcommTestPacketGeneratorTest, TestQuickGenerateUihMscCmdPacket) {
+ EXPECT_THAT(CreateQuickMscPacket(true, GetDlci(false, 3), 0x005c, 0x0008,
+ true, false, true, true, false, true),
+ ElementsAreArray(kIncomingUihMscCmdFrame));
+}
+
+const uint8_t kIncomingUihMscResponseFrame[] = {
+ 0x08, 0x20, 0x0c, 0x00, 0x08, 0x00, 0x5c, 0x00,
+ 0x03, 0xef, 0x09, 0xe1, 0x05, 0x1b, 0x8d, 0x70};
+
+TEST(RfcommTestPacketGeneratorTest, TestGenerateUihMscResponsePacket) {
+ uint8_t dlci = GetDlci(false, 0);
+ EXPECT_EQ(dlci, 0);
+ uint8_t address_field = GetAddressField(true, true, dlci);
+ EXPECT_EQ(address_field, 0x03);
+ uint8_t control_field = GetControlField(false, RFCOMM_UIH);
+ EXPECT_EQ(control_field, 0xEF);
+ uint8_t new_dlci = GetDlci(false, 3);
+ EXPECT_EQ(new_dlci, 6);
+ std::vector<uint8_t> mcc_msc_data =
+ CreateMccMscFrame(new_dlci, false, true, true, false, true);
+ std::vector<uint8_t> mcc_payload =
+ CreateMultiplexerControlFrame(0x38, false, mcc_msc_data);
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, -1, mcc_payload);
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(0x005c, rfcomm_packet);
+ std::vector<uint8_t> acl_packet =
+ CreateAclPacket(0x0008, 0b10, 0b00, l2cap_packet);
+ EXPECT_THAT(acl_packet, ElementsAreArray(kIncomingUihMscResponseFrame));
+}
+
+TEST(RfcommTestPacketGeneratorTest, TestQuickGenerateUihMscResponsePacket) {
+ EXPECT_THAT(CreateQuickMscPacket(true, GetDlci(false, 3), 0x005c, 0x0008,
+ false, false, true, true, false, true),
+ ElementsAreArray(kIncomingUihMscResponseFrame));
+}
+
+const uint8_t kIncomingBrsfFrame[] = {0x08, 0x20, 0x15, 0x00, 0x11, 0x00, 0x5c,
+ 0x00, 0x1b, 0xff, 0x19, 0x06, 0x41, 0x54,
+ 0x2b, 0x42, 0x52, 0x53, 0x46, 0x3d, 0x39,
+ 0x35, 0x39, 0x0d, 0x93};
+
+TEST(RfcommTestPacketGeneratorTest, TestGenerateDataPacket) {
+ uint8_t dlci = GetDlci(false, 3);
+ EXPECT_EQ(dlci, 6);
+ uint8_t address_field = GetAddressField(true, true, dlci);
+ EXPECT_EQ(address_field, 0x1B);
+ uint8_t control_field = GetControlField(true, RFCOMM_UIH);
+ EXPECT_EQ(control_field, 0xFF);
+ const std::string data_str = "AT+BRSF=959\r";
+ const std::vector<uint8_t> data(data_str.begin(), data_str.end());
+ std::vector<uint8_t> rfcomm_packet =
+ CreateRfcommPacket(address_field, control_field, 6, data);
+ std::vector<uint8_t> l2cap_packet =
+ CreateL2capDataPacket(0x005c, rfcomm_packet);
+ std::vector<uint8_t> acl_packet =
+ CreateAclPacket(0x0008, 0b10, 0b00, l2cap_packet);
+ EXPECT_THAT(acl_packet, ElementsAreArray(kIncomingBrsfFrame));
+}
+
+TEST(RfcommTestPacketGeneratorTest, TestQuickGenerateDataPacket) {
+ EXPECT_THAT(CreateQuickDataPacket(GetDlci(false, 3), true, 0x005c, 0x0008, 6,
+ "AT+BRSF=959\r"),
+ ElementsAreArray(kIncomingBrsfFrame));
+}
+
+} // namespace
\ No newline at end of file
diff --git a/stack/test/stack_a2dp_test.cc b/stack/test/stack_a2dp_test.cc
index 3808df4..63dfb28 100644
--- a/stack/test/stack_a2dp_test.cc
+++ b/stack/test/stack_a2dp_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -220,6 +220,9 @@
case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
supported = true;
break;
+ case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
+ supported = true;
+ break;
case BTAV_A2DP_CODEC_INDEX_MAX:
// Needed to avoid using "default:" case so we can capture when
// a new codec is added, and it can be included here.
@@ -310,10 +313,10 @@
TEST_F(StackA2dpTest, test_a2dp_is_codec_valid_aac) {
EXPECT_TRUE(A2DP_IsSourceCodecValid(codec_info_aac));
EXPECT_TRUE(A2DP_IsSourceCodecValid(codec_info_aac_capability));
- EXPECT_FALSE(A2DP_IsPeerSourceCodecValid(codec_info_aac));
- EXPECT_FALSE(A2DP_IsPeerSourceCodecValid(codec_info_aac_capability));
+ EXPECT_TRUE(A2DP_IsPeerSourceCodecValid(codec_info_aac));
+ EXPECT_TRUE(A2DP_IsPeerSourceCodecValid(codec_info_aac_capability));
- EXPECT_FALSE(A2DP_IsSinkCodecValid(codec_info_aac_sink_capability));
+ EXPECT_TRUE(A2DP_IsSinkCodecValid(codec_info_aac_sink_capability));
EXPECT_TRUE(A2DP_IsPeerSinkCodecValid(codec_info_aac_sink_capability));
// Test with invalid AAC codecs
@@ -349,8 +352,11 @@
EXPECT_FALSE(A2DP_IsSinkCodecSupported(codec_info_sbc_capability));
EXPECT_FALSE(A2DP_IsSinkCodecSupported(codec_info_sbc_sink_capability));
- EXPECT_FALSE(A2DP_IsSinkCodecSupported(codec_info_aac));
- EXPECT_FALSE(A2DP_IsSinkCodecSupported(codec_info_aac_capability));
+ EXPECT_TRUE(A2DP_IsSinkCodecSupported(codec_info_aac));
+ // NOTE: The test below should be EXPECT_FALSE.
+ // However, codec_info_aac_capability is practically same as codec_info_aac,
+ // therefore we cannot differentiate it as a capability.
+ EXPECT_TRUE(A2DP_IsSinkCodecSupported(codec_info_aac_capability));
EXPECT_FALSE(A2DP_IsSinkCodecSupported(codec_info_aac_sink_capability));
EXPECT_FALSE(A2DP_IsSinkCodecSupported(codec_info_non_a2dp));
@@ -361,9 +367,9 @@
EXPECT_TRUE(A2DP_IsPeerSourceCodecSupported(codec_info_sbc_capability));
EXPECT_TRUE(A2DP_IsPeerSourceCodecSupported(codec_info_sbc_sink_capability));
- EXPECT_FALSE(A2DP_IsPeerSourceCodecSupported(codec_info_aac));
- EXPECT_FALSE(A2DP_IsPeerSourceCodecSupported(codec_info_aac_capability));
- EXPECT_FALSE(A2DP_IsPeerSourceCodecSupported(codec_info_aac_sink_capability));
+ EXPECT_TRUE(A2DP_IsPeerSourceCodecSupported(codec_info_aac));
+ EXPECT_TRUE(A2DP_IsPeerSourceCodecSupported(codec_info_aac_capability));
+ EXPECT_TRUE(A2DP_IsPeerSourceCodecSupported(codec_info_aac_sink_capability));
EXPECT_FALSE(A2DP_IsPeerSourceCodecSupported(codec_info_non_a2dp));
}
@@ -380,45 +386,6 @@
}
}
-TEST_F(StackA2dpTest, test_build_src2sink_config) {
- uint8_t codec_info_result[AVDT_CODEC_SIZE];
-
- memset(codec_info_result, 0, sizeof(codec_info_result));
- EXPECT_EQ(A2DP_BuildSrc2SinkConfig(codec_info_sbc, codec_info_result),
- A2DP_SUCCESS);
- // Compare the result codec with the local test codec info
- for (size_t i = 0; i < codec_info_sbc[0] + 1; i++) {
- EXPECT_EQ(codec_info_result[i], codec_info_sbc[i]);
- }
-
- // Include extra (less preferred) capabilities and test again - SBC
- uint8_t codec_info_sbc_test1[AVDT_CODEC_SIZE];
- memcpy(codec_info_sbc_test1, codec_info_sbc, sizeof(codec_info_sbc));
- codec_info_sbc_test1[3] |= (A2DP_SBC_IE_CH_MD_STEREO |
- A2DP_SBC_IE_CH_MD_DUAL | A2DP_SBC_IE_CH_MD_MONO);
- codec_info_sbc_test1[4] |=
- (A2DP_SBC_IE_BLOCKS_12 | A2DP_SBC_IE_BLOCKS_8 | A2DP_SBC_IE_BLOCKS_4);
- codec_info_sbc_test1[4] |= A2DP_SBC_IE_SUBBAND_4;
- codec_info_sbc_test1[4] |= A2DP_SBC_IE_ALLOC_MD_S;
- memset(codec_info_result, 0, sizeof(codec_info_result));
- EXPECT_EQ(A2DP_BuildSrc2SinkConfig(codec_info_sbc_test1, codec_info_result),
- A2DP_SUCCESS);
- // Compare the result codec with the local test codec info
- for (size_t i = 0; i < codec_info_sbc[0] + 1; i++) {
- EXPECT_EQ(codec_info_result[i], codec_info_sbc[i]);
- }
-
- memset(codec_info_result, 0, sizeof(codec_info_result));
- EXPECT_NE(A2DP_BuildSrc2SinkConfig(codec_info_aac, codec_info_result),
- A2DP_SUCCESS);
-
- // Test invalid codec info
- memset(codec_info_result, 0, sizeof(codec_info_result));
- memset(codec_info_sbc_test1, 0, sizeof(codec_info_sbc_test1));
- EXPECT_NE(A2DP_BuildSrc2SinkConfig(codec_info_sbc_test1, codec_info_result),
- A2DP_SUCCESS);
-}
-
TEST_F(StackA2dpTest, test_a2dp_uses_rtp_header) {
EXPECT_TRUE(A2DP_UsesRtpHeader(true, codec_info_sbc));
EXPECT_TRUE(A2DP_UsesRtpHeader(false, codec_info_sbc));
@@ -607,16 +574,10 @@
TEST_F(StackA2dpTest, test_a2dp_get_sink_track_channel_type) {
EXPECT_EQ(A2DP_GetSinkTrackChannelType(codec_info_sbc), 3);
- EXPECT_EQ(A2DP_GetSinkTrackChannelType(codec_info_aac), -1);
+ EXPECT_EQ(A2DP_GetSinkTrackChannelType(codec_info_aac), 3);
EXPECT_EQ(A2DP_GetSinkTrackChannelType(codec_info_non_a2dp), -1);
}
-TEST_F(StackA2dpTest, test_a2dp_get_sink_frames_count_to_process) {
- EXPECT_EQ(A2DP_GetSinkFramesCountToProcess(20, codec_info_sbc), 7);
- EXPECT_EQ(A2DP_GetSinkFramesCountToProcess(20, codec_info_aac), -1);
- EXPECT_EQ(A2DP_GetSinkFramesCountToProcess(20, codec_info_non_a2dp), -1);
-}
-
TEST_F(StackA2dpTest, test_a2dp_get_object_type_code_aac) {
EXPECT_EQ(A2DP_GetObjectTypeCodeAac(codec_info_sbc), -1);
EXPECT_EQ(A2DP_GetObjectTypeCodeAac(codec_info_aac), 0x80);
@@ -737,7 +698,7 @@
}
TEST_F(StackA2dpTest, test_a2dp_source_codec_index) {
- // Explicit tests for known codecs
+ // Explicit tests for known Source codecs
EXPECT_EQ(A2DP_SourceCodecIndex(codec_info_sbc),
BTAV_A2DP_CODEC_INDEX_SOURCE_SBC);
EXPECT_EQ(A2DP_SourceCodecIndex(codec_info_sbc_capability),
@@ -754,6 +715,24 @@
BTAV_A2DP_CODEC_INDEX_MAX);
}
+TEST_F(StackA2dpTest, test_a2dp_sink_codec_index) {
+ // Explicit tests for known Sink codecs
+ EXPECT_EQ(A2DP_SinkCodecIndex(codec_info_sbc),
+ BTAV_A2DP_CODEC_INDEX_SINK_SBC);
+ EXPECT_EQ(A2DP_SinkCodecIndex(codec_info_sbc_capability),
+ BTAV_A2DP_CODEC_INDEX_SINK_SBC);
+ EXPECT_EQ(A2DP_SinkCodecIndex(codec_info_sbc_sink_capability),
+ BTAV_A2DP_CODEC_INDEX_SINK_SBC);
+ EXPECT_EQ(A2DP_SinkCodecIndex(codec_info_aac),
+ BTAV_A2DP_CODEC_INDEX_SINK_AAC);
+ EXPECT_EQ(A2DP_SinkCodecIndex(codec_info_aac_capability),
+ BTAV_A2DP_CODEC_INDEX_SINK_AAC);
+ EXPECT_EQ(A2DP_SinkCodecIndex(codec_info_aac_sink_capability),
+ BTAV_A2DP_CODEC_INDEX_SINK_AAC);
+ EXPECT_EQ(A2DP_SinkCodecIndex(codec_info_non_a2dp),
+ BTAV_A2DP_CODEC_INDEX_MAX);
+}
+
TEST_F(StackA2dpTest, test_a2dp_codec_index_str) {
// Explicit tests for known codecs
EXPECT_STREQ(A2DP_CodecIndexStr(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC), "SBC");
@@ -773,7 +752,7 @@
}
TEST_F(StackA2dpTest, test_a2dp_init_codec_config) {
- tAVDT_CFG avdt_cfg;
+ AvdtpSepConfig avdt_cfg;
//
// Test for SBC Source
@@ -917,6 +896,70 @@
}
EXPECT_TRUE(codec_config->useRtpHeaderMarkerBit());
+ // Create the codec capability - SBC Sink
+ memset(codec_info_result, 0, sizeof(codec_info_result));
+ peer_codec_index = A2DP_SinkCodecIndex(codec_info_sbc_capability);
+ EXPECT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
+ codec_config = a2dp_codecs->findSinkCodecConfig(codec_info_sbc_capability);
+ EXPECT_NE(codec_config, nullptr);
+ EXPECT_TRUE(a2dp_codecs->setSinkCodecConfig(
+ codec_info_sbc_capability, true /* is_capability */, codec_info_result,
+ true /* select_current_codec */));
+ EXPECT_EQ(a2dp_codecs->getCurrentCodecConfig(), codec_config);
+ // Compare the result codec with the local test codec info
+ for (size_t i = 0; i < codec_info_sbc[0] + 1; i++) {
+ EXPECT_EQ(codec_info_result[i], codec_info_sbc[i]);
+ }
+ EXPECT_EQ(codec_config->getAudioBitsPerSample(), 16);
+
+ // Create the codec capability - AAC Sink
+ memset(codec_info_result, 0, sizeof(codec_info_result));
+ peer_codec_index = A2DP_SinkCodecIndex(codec_info_aac_capability);
+ EXPECT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
+ codec_config = a2dp_codecs->findSinkCodecConfig(codec_info_aac_capability);
+ EXPECT_NE(codec_config, nullptr);
+ EXPECT_TRUE(a2dp_codecs->setSinkCodecConfig(
+ codec_info_aac_capability, true /* is_capability */, codec_info_result,
+ true /* select_current_codec */));
+ EXPECT_EQ(a2dp_codecs->getCurrentCodecConfig(), codec_config);
+ // Compare the result codec with the local test codec info
+ for (size_t i = 0; i < codec_info_aac[0] + 1; i++) {
+ EXPECT_EQ(codec_info_result[i], codec_info_aac[i]);
+ }
+ EXPECT_EQ(codec_config->getAudioBitsPerSample(), 16);
+
+ // Create the codec config - SBC Sink
+ memset(codec_info_result, 0, sizeof(codec_info_result));
+ peer_codec_index = A2DP_SinkCodecIndex(codec_info_sbc);
+ EXPECT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
+ codec_config = a2dp_codecs->findSinkCodecConfig(codec_info_sbc);
+ EXPECT_NE(codec_config, nullptr);
+ EXPECT_TRUE(a2dp_codecs->setSinkCodecConfig(
+ codec_info_sbc, false /* is_capability */, codec_info_result,
+ true /* select_current_codec */));
+ EXPECT_EQ(a2dp_codecs->getCurrentCodecConfig(), codec_config);
+ // Compare the result codec with the local test codec info
+ for (size_t i = 0; i < codec_info_sbc[0] + 1; i++) {
+ EXPECT_EQ(codec_info_result[i], codec_info_sbc[i]);
+ }
+ EXPECT_EQ(codec_config->getAudioBitsPerSample(), 16);
+
+ // Create the codec config - AAC Sink
+ memset(codec_info_result, 0, sizeof(codec_info_result));
+ peer_codec_index = A2DP_SinkCodecIndex(codec_info_aac);
+ EXPECT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
+ codec_config = a2dp_codecs->findSinkCodecConfig(codec_info_aac);
+ EXPECT_NE(codec_config, nullptr);
+ EXPECT_TRUE(a2dp_codecs->setSinkCodecConfig(
+ codec_info_aac, false /* is_capability */, codec_info_result,
+ true /* select_current_codec */));
+ EXPECT_EQ(a2dp_codecs->getCurrentCodecConfig(), codec_config);
+ // Compare the result codec with the local test codec info
+ for (size_t i = 0; i < codec_info_aac[0] + 1; i++) {
+ EXPECT_EQ(codec_info_result[i], codec_info_aac[i]);
+ }
+ EXPECT_EQ(codec_config->getAudioBitsPerSample(), 16);
+
// Test invalid codec info
uint8_t codec_info_sbc_test1[AVDT_CODEC_SIZE];
memset(codec_info_result, 0, sizeof(codec_info_result));
diff --git a/stack/test/stack_btu_test.cc b/stack/test/stack_btu_test.cc
index 49dc52e..97e95d2 100644
--- a/stack/test/stack_btu_test.cc
+++ b/stack/test/stack_btu_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stack/test/stack_smp_test.cc b/stack/test/stack_smp_test.cc
index 2391012..12c10f6 100644
--- a/stack/test/stack_smp_test.cc
+++ b/stack/test/stack_smp_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
#include "bt_trace.h"
#include "hcidefs.h"
#include "stack/include/smp_api.h"
+#include "stack/smp/p_256_ecc_pp.h"
#include "stack/smp/smp_int.h"
/*
@@ -224,4 +225,87 @@
dump_uint128_reverse(output.param_buf, confirm_str);
ASSERT_THAT(confirm_str, StrEq(expected_confirm_str));
}
+
+// Test ECC point validation
+TEST(SmpEccValidationTest, test_valid_points) {
+ Point p;
+
+ // Test data from Bluetooth Core Specification
+ // Version 5.0 | Vol 2, Part G | 7.1.2
+
+ // Sample 1
+ p.x[7] = 0x20b003d2;
+ p.x[6] = 0xf297be2c;
+ p.x[5] = 0x5e2c83a7;
+ p.x[4] = 0xe9f9a5b9;
+ p.x[3] = 0xeff49111;
+ p.x[2] = 0xacf4fddb;
+ p.x[1] = 0xcc030148;
+ p.x[0] = 0x0e359de6;
+
+ p.y[7] = 0xdc809c49;
+ p.y[6] = 0x652aeb6d;
+ p.y[5] = 0x63329abf;
+ p.y[4] = 0x5a52155c;
+ p.y[3] = 0x766345c2;
+ p.y[2] = 0x8fed3024;
+ p.y[1] = 0x741c8ed0;
+ p.y[0] = 0x1589d28b;
+
+ EXPECT_TRUE(ECC_ValidatePoint(p));
+
+ // Sample 2
+ p.x[7] = 0x2c31a47b;
+ p.x[6] = 0x5779809e;
+ p.x[5] = 0xf44cb5ea;
+ p.x[4] = 0xaf5c3e43;
+ p.x[3] = 0xd5f8faad;
+ p.x[2] = 0x4a8794cb;
+ p.x[1] = 0x987e9b03;
+ p.x[0] = 0x745c78dd;
+
+ p.y[7] = 0x91951218;
+ p.y[6] = 0x3898dfbe;
+ p.y[5] = 0xcd52e240;
+ p.y[4] = 0x8e43871f;
+ p.y[3] = 0xd0211091;
+ p.y[2] = 0x17bd3ed4;
+ p.y[1] = 0xeaf84377;
+ p.y[0] = 0x43715d4f;
+
+ EXPECT_TRUE(ECC_ValidatePoint(p));
+}
+
+TEST(SmpEccValidationTest, test_invalid_points) {
+ Point p;
+ multiprecision_init(p.x, 8);
+ multiprecision_init(p.y, 8);
+
+ EXPECT_FALSE(ECC_ValidatePoint(p));
+
+ // Sample 1
+ p.x[7] = 0x20b003d2;
+ p.x[6] = 0xf297be2c;
+ p.x[5] = 0x5e2c83a7;
+ p.x[4] = 0xe9f9a5b9;
+ p.x[3] = 0xeff49111;
+ p.x[2] = 0xacf4fddb;
+ p.x[1] = 0xcc030148;
+ p.x[0] = 0x0e359de6;
+
+ EXPECT_FALSE(ECC_ValidatePoint(p));
+
+ p.y[7] = 0xdc809c49;
+ p.y[6] = 0x652aeb6d;
+ p.y[5] = 0x63329abf;
+ p.y[4] = 0x5a52155c;
+ p.y[3] = 0x766345c2;
+ p.y[2] = 0x8fed3024;
+ p.y[1] = 0x741c8ed0;
+ p.y[0] = 0x1589d28b;
+
+ p.y[0]--;
+
+ EXPECT_FALSE(ECC_ValidatePoint(p));
+}
} // namespace testing
diff --git a/test/rootcanal/Android.bp b/test/rootcanal/Android.bp
index d5a6b9f..7371c99 100644
--- a/test/rootcanal/Android.bp
+++ b/test/rootcanal/Android.bp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2017 The Android Open Source Project
+// Copyright 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -22,12 +22,12 @@
"service.cc",
],
+ header_libs: ["libbluetooth_headers"],
shared_libs: [
"android.hardware.bluetooth@1.0",
"libbase",
"libchrome",
"libcutils",
- "libhardware",
"libhwbinder",
"libhidlbase",
"libhidltransport",
@@ -50,8 +50,47 @@
include_dirs: [
"system/bt",
"system/bt/hci/include",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/stack/include",
],
init_rc: ["android.hardware.bluetooth@1.0-service.sim.rc"],
}
+
+cc_library_shared {
+ name: "android.hardware.bluetooth@1.0-impl-sim",
+ proprietary: true,
+ relative_install_path: "hw",
+ srcs: [
+ "bluetooth_hci.cc",
+ ],
+
+ header_libs: ["libbluetooth_headers"],
+ shared_libs: [
+ "android.hardware.bluetooth@1.0",
+ "libbase",
+ "libchrome",
+ "libcutils",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-DHAS_NO_BDROID_BUILDCFG",
+ ],
+ static_libs: [
+ "libbluetooth-types",
+ "android.hardware.bluetooth-async",
+ "android.hardware.bluetooth-hci",
+ "libbt-rootcanal",
+ ],
+ include_dirs: [
+ "system/bt",
+ "system/bt/hci/include",
+ "system/bt/internal_include",
+ "system/bt/stack/include",
+ ],
+}
diff --git a/test/rootcanal/android.hardware.bluetooth@1.0-service.sim.rc b/test/rootcanal/android.hardware.bluetooth@1.0-service.sim.rc
index 2f53e5d..9d99c8a 100644
--- a/test/rootcanal/android.hardware.bluetooth@1.0-service.sim.rc
+++ b/test/rootcanal/android.hardware.bluetooth@1.0-service.sim.rc
@@ -1,4 +1,4 @@
-service bluetooth-1-0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service.sim
+service vendor.bluetooth-1-0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service.sim
class hal
user bluetooth
group bluetooth
diff --git a/test/rootcanal/bluetooth_hci.cc b/test/rootcanal/bluetooth_hci.cc
index 413b31b..b0281a0 100644
--- a/test/rootcanal/bluetooth_hci.cc
+++ b/test/rootcanal/bluetooth_hci.cc
@@ -22,7 +22,10 @@
#include <string.h>
#include <utils/Log.h>
+#include "acl_packet.h"
+#include "event_packet.h"
#include "hci_internals.h"
+#include "sco_packet.h"
namespace android {
namespace hardware {
@@ -31,11 +34,13 @@
namespace sim {
using android::hardware::hidl_vec;
+using test_vendor_lib::AclPacket;
using test_vendor_lib::AsyncManager;
using test_vendor_lib::AsyncTaskId;
using test_vendor_lib::CommandPacket;
using test_vendor_lib::DualModeController;
using test_vendor_lib::EventPacket;
+using test_vendor_lib::ScoPacket;
using test_vendor_lib::TaskCallback;
using test_vendor_lib::TestChannelTransport;
@@ -92,10 +97,24 @@
cb->hciEventReceived(hci_event);
});
- /* RegisterAcl and RegisterSco
- cb->aclDataReceived(hci_packet);
- cb->scoDataReceived(hci_packet);
- */
+ controller_.RegisterAclChannel([cb](std::unique_ptr<AclPacket> packet) {
+ std::vector<uint8_t> acl_vector = packet->GetPacket();
+ hidl_vec<uint8_t> acl_packet = acl_vector;
+
+ cb->aclDataReceived(acl_packet);
+ });
+
+ controller_.RegisterScoChannel([cb](std::unique_ptr<ScoPacket> packet) {
+ size_t header_bytes = packet->GetHeaderSize();
+ size_t payload_bytes = packet->GetPayloadSize();
+ hidl_vec<uint8_t> sco_packet;
+ sco_packet.resize(header_bytes + payload_bytes);
+ memcpy(sco_packet.data(), packet->GetHeader().data(), header_bytes);
+ memcpy(sco_packet.data() + header_bytes, packet->GetPayload().data(),
+ payload_bytes);
+
+ cb->scoDataReceived(sco_packet);
+ });
controller_.RegisterTaskScheduler(
[this](std::chrono::milliseconds delay, const TaskCallback& task) {
@@ -142,13 +161,36 @@
return Void();
}
-Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& /* packet */) {
- CHECK(false) << __func__ << " not yet implemented";
+Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& packet) {
+ async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() {
+ uint16_t channel = (packet[0] | (packet[1] << 8)) & 0xfff;
+ AclPacket::PacketBoundaryFlags boundary_flags =
+ static_cast<AclPacket::PacketBoundaryFlags>((packet[1] & 0x30) >> 4);
+ AclPacket::BroadcastFlags broadcast_flags =
+ static_cast<AclPacket::BroadcastFlags>((packet[1] & 0xC0) >> 6);
+
+ std::unique_ptr<AclPacket> acl = std::unique_ptr<AclPacket>(
+ new AclPacket(channel, boundary_flags, broadcast_flags));
+ for (size_t i = 4; i < packet.size(); i++)
+ acl->AddPayloadOctets1(packet[i]);
+
+ controller_.HandleAcl(std::move(acl));
+ });
return Void();
}
-Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& /* packet */) {
- CHECK(false) << __func__ << " not yet implemented";
+Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& packet) {
+ async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() {
+ uint16_t channel = (packet[0] | (packet[1] << 8)) & 0xfff;
+ ScoPacket::PacketStatusFlags packet_status =
+ static_cast<ScoPacket::PacketStatusFlags>((packet[1] & 0x30) >> 4);
+ std::unique_ptr<ScoPacket> sco =
+ std::unique_ptr<ScoPacket>(new ScoPacket(channel, packet_status));
+ for (size_t i = 3; i < packet.size(); i++)
+ sco->AddPayloadOctets1(packet[i]);
+
+ controller_.HandleSco(std::move(sco));
+ });
return Void();
}
@@ -176,6 +218,11 @@
});
}
+/* Fallback to shared library if there is no service. */
+IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* /* name */) {
+ return new BluetoothHci();
+}
+
} // namespace gce
} // namespace V1_0
} // namespace bluetooth
diff --git a/test/rootcanal/bluetooth_hci.h b/test/rootcanal/bluetooth_hci.h
index 2ddf8ee..05ec206 100644
--- a/test/rootcanal/bluetooth_hci.h
+++ b/test/rootcanal/bluetooth_hci.h
@@ -72,6 +72,8 @@
test_vendor_lib::TestChannelTransport test_channel_transport_;
};
+extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name);
+
} // namespace sim
} // namespace V1_0
} // namespace bluetooth
diff --git a/test/run_host_unit_tests.py b/test/run_host_unit_tests.py
new file mode 100755
index 0000000..a99140e
--- /dev/null
+++ b/test/run_host_unit_tests.py
@@ -0,0 +1,207 @@
+#!/usr/bin/env python
+#
+# Copyright 2017, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import sys
+import subprocess
+import os
+import argparse
+
+# Registered host based unit tests
+# Must have 'host_supported: true'
+HOST_TESTS = [
+ 'bluetoothtbd_test',
+ 'net_test_avrcp',
+ 'net_test_btif_state_machine',
+ 'net_test_btcore',
+ 'net_test_types',
+ 'net_test_btpackets',
+]
+
+SOONG_UI_BASH = 'build/soong/soong_ui.bash'
+
+def str2bool(argument, default=False):
+ """ Convert a string to a booleen value. """
+ argument = str(argument)
+ if argument.lower() in ['0', 'f', 'false', 'off', 'no', 'n']:
+ return False
+ elif argument.lower() in ['1', 't', 'true', 'on', 'yes', 'y']:
+ return True
+ return default
+
+
+def check_dir_exists(dir, dirname):
+ if not os.path.isdir(dir):
+ print "Couldn't find %s (%s)!" % (dirname, dir)
+ sys.exit(0)
+
+
+def get_output_from_command(cmd):
+ try:
+ return subprocess.check_output(cmd).strip()
+ except subprocess.CalledProcessError as e:
+ print 'Failed to call {cmd}, return code {code}'.format(cmd=cmd,
+ code=e.returncode)
+ print e
+ return None
+
+
+def get_android_root_or_die():
+ value = os.environ.get('ANDROID_BUILD_TOP')
+ if not value:
+ # Try to find build/soong/soong_ui.bash upwards until root directory
+ current_path = os.path.abspath(os.getcwd())
+ while current_path and os.path.isdir(current_path):
+ soong_ui_bash_path = os.path.join(current_path, SOONG_UI_BASH)
+ if os.path.isfile(soong_ui_bash_path):
+ # Use value returned from Soong UI instead in case definition to TOP
+ # changes in the future
+ value = get_output_from_command((soong_ui_bash_path,
+ '--dumpvar-mode',
+ '--abs',
+ 'TOP'))
+ break
+ parent_path = os.path.abspath(os.path.join(current_path, os.pardir))
+ if parent_path == current_path:
+ current_path = None
+ else:
+ current_path = parent_path
+ if not value:
+ print 'Cannot determine ANDROID_BUILD_TOP'
+ sys.exit(1)
+ check_dir_exists(value, '$ANDROID_BUILD_TOP')
+ return value
+
+
+def get_android_host_out_or_die():
+ value = os.environ.get('ANDROID_HOST_OUT')
+ if not value:
+ ANDROID_BUILD_TOP = get_android_root_or_die()
+ value = get_output_from_command((os.path.join(ANDROID_BUILD_TOP,
+ SOONG_UI_BASH),
+ '--dumpvar-mode',
+ '--abs',
+ 'HOST_OUT'))
+ if not value:
+ print 'Cannot determine ANDROID_HOST_OUT'
+ sys.exit(1)
+ check_dir_exists(value, '$ANDROID_HOST_OUT')
+ return value
+
+
+def get_android_dist_dir_or_die():
+ # Check if $DIST_DIR is predefined as environment variable
+ value = os.environ.get('DIST_DIR')
+ if not value:
+ # If not use the default path
+ ANDROID_BUILD_TOP = get_android_root_or_die()
+ value = os.path.join(os.path.join(ANDROID_BUILD_TOP, 'out'), 'dist')
+ if not os.path.isdir(value):
+ if os.path.exists(value):
+ print '%s is not a directory!' % (value)
+ sys.exit(1)
+ os.makedirs(value)
+ return value
+
+
+def get_native_test_root_or_die():
+ android_host_out = get_android_host_out_or_die()
+ test_root = os.path.join(android_host_out, 'nativetest64')
+ if not os.path.isdir(test_root):
+ test_root = os.path.join(android_host_out, 'nativetest')
+ if not os.path.isdir(test_root):
+ print 'Neither nativetest64 nor nativetest directory exist,' \
+ ' please compile first'
+ sys.exit(1)
+ return test_root
+
+
+def get_test_cmd_or_die(test_root, test_name, enable_xml, test_filter):
+ test_path = os.path.join(os.path.join(test_root, test_name), test_name)
+ if not os.path.isfile(test_path):
+ print 'Cannot find: ' + test_path
+ sys.exit(1)
+ cmd = [test_path]
+ if enable_xml:
+ dist_dir = get_android_dist_dir_or_die()
+ log_output_path = os.path.join(dist_dir, 'gtest/{0}_test_details.xml'
+ .format(test_name))
+ cmd.append('--gtest_output=xml:{0}'.format(log_output_path))
+ if test_filter:
+ cmd.append('--gtest_filter=%s' % test_filter)
+ return cmd
+
+
+# path is relative to Android build top
+def build_target(target, num_tasks):
+ ANDROID_BUILD_TOP = get_android_root_or_die()
+ build_cmd = [SOONG_UI_BASH, '--make-mode']
+ if num_tasks > 1:
+ build_cmd.append('-j' + str(num_tasks))
+ build_cmd.append(target)
+ p = subprocess.Popen(build_cmd, cwd=ANDROID_BUILD_TOP, env=os.environ.copy())
+ return_code = p.wait()
+ if return_code != 0:
+ print 'BUILD FAILED, return code: {0}'.format(str(return_code))
+ sys.exit(1)
+ return
+
+
+def main():
+ """ run_host_unit_tests.py - Run registered host based unit tests
+ """
+ parser = argparse.ArgumentParser(description='Run host based unit tests.')
+ parser.add_argument(
+ '--enable_xml',
+ type=str2bool,
+ dest='enable_xml',
+ nargs='?',
+ const=True,
+ default=False,
+ help=
+ 'Whether to output structured XML log output in out/dist/gtest directory')
+ parser.add_argument(
+ '-j',
+ type=int,
+ nargs='?',
+ dest='num_tasks',
+ const=-1,
+ default=-1,
+ help='Number of tasks to run at the same time')
+ parser.add_argument(
+ 'rest',
+ nargs=argparse.REMAINDER,
+ help='-- args, other gtest arguments for each individual test')
+ args = parser.parse_args()
+
+ build_target('MODULES-IN-system-bt', args.num_tasks)
+ TEST_ROOT = get_native_test_root_or_die()
+ test_results = []
+ for test in HOST_TESTS:
+ test_cmd = get_test_cmd_or_die(TEST_ROOT, test, args.enable_xml, args.rest)
+ if subprocess.call(test_cmd) != 0:
+ test_results.append(False)
+ else:
+ test_results.append(True)
+ if not all(test_results):
+ failures = [i for i, x in enumerate(test_results) if not x]
+ for index in failures:
+ print 'TEST FAILLED: ' + HOST_TESTS[index]
+ sys.exit(0)
+ print 'TEST PASSED ' + str(len(test_results)) + ' tests were run'
+ sys.exit(0)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/run_unit_tests.sh b/test/run_unit_tests.sh
index ab9ecc2..066e8e1 100755
--- a/test/run_unit_tests.sh
+++ b/test/run_unit_tests.sh
@@ -3,11 +3,13 @@
known_tests=(
bluetoothtbd_test
net_test_audio_a2dp_hw
+ net_test_avrcp
net_test_bluetooth
net_test_btcore
net_test_bta
net_test_btif
net_test_btif_profile_queue
+ net_test_btif_state_machine
net_test_device
net_test_hci
net_test_stack
@@ -17,11 +19,12 @@
net_test_types
net_test_btu_message_loop
net_test_osi
- performance_test
+ net_test_performance
+ net_test_stack_rfcomm
)
known_remote_tests=(
- net_test_rfcomm
+ net_test_rfcomm_suite
)
@@ -102,11 +105,18 @@
adb+=( "-s" "${device}" )
fi
+source ${ANDROID_BUILD_TOP}/build/envsetup.sh
+target_arch=$(gettargetarch)
+
failed_tests=()
for spec in "${tests[@]}"
do
name="${spec%%.*}"
- binary="/data/nativetest/${name}/${name}"
+ if [[ $target_arch == *"64"* ]]; then
+ binary="/data/nativetest64/${name}/${name}"
+ else
+ binary="/data/nativetest/${name}/${name}"
+ fi
push_command=( "${adb[@]}" push {"${ANDROID_PRODUCT_OUT}",}"${binary}" )
test_command=( "${adb[@]}" shell "${binary}" )
diff --git a/test/suite/Android.bp b/test/suite/Android.bp
index e4d3a2b..ed5b531 100644
--- a/test/suite/Android.bp
+++ b/test/suite/Android.bp
@@ -11,9 +11,9 @@
"gatt/gatt_test.cc",
"gatt/gatt_unittest.cc",
],
+ header_libs: ["libhardware_headers"],
shared_libs: [
"liblog",
- "libhardware",
"libcutils",
],
static_libs: [
@@ -28,7 +28,7 @@
// Bluetooth test suite for target
// ========================================================
cc_test {
- name: "net_test_rfcomm",
+ name: "net_test_rfcomm_suite",
defaults: ["fluoride_defaults"],
include_dirs: ["system/bt"],
srcs: [
@@ -36,9 +36,9 @@
"rfcomm/rfcomm_test.cc",
"rfcomm/rfcomm_unittest.cc",
],
+ header_libs: [ "libhardware_headers" ],
shared_libs: [
"liblog",
- "libhardware",
"libcutils",
],
static_libs: [
@@ -53,7 +53,7 @@
// Bluetooth test suite for target
// ========================================================
cc_test {
- name: "performance_test",
+ name: "net_test_performance",
defaults: ["fluoride_defaults"],
include_dirs: ["system/bt"],
srcs: [
diff --git a/test/suite/AndroidTest.xml b/test/suite/AndroidTest.xml
index eee642a..d7778e1 100644
--- a/test/suite/AndroidTest.xml
+++ b/test/suite/AndroidTest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/test/suite/BUILD.gn b/test/suite/BUILD.gn
index d481000..7e68a1a 100644
--- a/test/suite/BUILD.gn
+++ b/test/suite/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
deps = [
"//btcore",
- "//main:bluetooth.default",
+ "//main:bluetooth",
"//service:service",
"//service:service_unittests",
"//types:types_unittests",
diff --git a/test/suite/adapter/adapter_unittest.cc b/test/suite/adapter/adapter_unittest.cc
index 730ac5a..24ca3e5 100644
--- a/test/suite/adapter/adapter_unittest.cc
+++ b/test/suite/adapter/adapter_unittest.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,7 +82,8 @@
property_free(new_name);
new_name = property_new_name("BluetoothTestName2");
}
- std::string old_name((const char*)property_as_name(name_property)->name);
+ std::string old_name((const char*)property_as_name(name_property)->name,
+ name_property->len);
EXPECT_EQ(bt_interface()->set_adapter_property(new_name), BT_STATUS_SUCCESS);
semaphore_wait(adapter_properties_callback_sem_);
diff --git a/test/suite/adapter/bluetooth_test.cc b/test/suite/adapter/bluetooth_test.cc
index dcb95d1..02132f1 100644
--- a/test/suite/adapter/bluetooth_test.cc
+++ b/test/suite/adapter/bluetooth_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/suite/adapter/bluetooth_test.h b/test/suite/adapter/bluetooth_test.h
index 52b8518..e35811d 100644
--- a/test/suite/adapter/bluetooth_test.h
+++ b/test/suite/adapter/bluetooth_test.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
#include <hardware/bt_gatt.h>
#include <hardware/bt_pan.h>
#include <hardware/bt_sock.h>
-#include <hardware/hardware.h>
#include <signal.h>
#include <time.h>
#include <map>
diff --git a/test/suite/gatt/gatt_test.cc b/test/suite/gatt/gatt_test.cc
index 8f3ff61..e3546d3 100644
--- a/test/suite/gatt/gatt_test.cc
+++ b/test/suite/gatt/gatt_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,7 +91,7 @@
void GattTest::RegisterClientCallback(
bluetooth::hal::BluetoothGattInterface* /* unused */, int status,
- int clientIf, const bt_uuid_t& app_uuid) {
+ int clientIf, const bluetooth::Uuid& app_uuid) {
status_ = status;
client_interface_id_ = clientIf;
semaphore_post(register_client_callback_sem_);
@@ -106,7 +106,7 @@
// GATT server callbacks
void GattTest::RegisterServerCallback(
bluetooth::hal::BluetoothGattInterface* /* unused */, int status,
- int server_if, const bt_uuid_t& uuid) {
+ int server_if, const bluetooth::Uuid& uuid) {
status_ = status;
server_interface_id_ = server_if;
semaphore_post(register_server_callback_sem_);
diff --git a/test/suite/gatt/gatt_test.h b/test/suite/gatt/gatt_test.h
index 29e0c24..6005346 100644
--- a/test/suite/gatt/gatt_test.h
+++ b/test/suite/gatt/gatt_test.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@
// bluetooth::hal::BluetoothGattInterface::ClientObserver overrides
void RegisterClientCallback(
bluetooth::hal::BluetoothGattInterface* /* unused */, int status,
- int clientIf, const bt_uuid_t& app_uuid) override;
+ int clientIf, const bluetooth::Uuid& app_uuid) override;
void ScanResultCallback(bluetooth::hal::BluetoothGattInterface* /* unused */,
const RawAddress& bda, int rssi,
std::vector<uint8_t> adv_data) override;
@@ -67,7 +67,7 @@
// bluetooth::hal::BluetoothGattInterface::ServerObserver overrides
void RegisterServerCallback(
bluetooth::hal::BluetoothGattInterface* /* unused */, int status,
- int server_if, const bt_uuid_t& uuid) override;
+ int server_if, const bluetooth::Uuid& uuid) override;
void ServiceAddedCallback(
bluetooth::hal::BluetoothGattInterface* /* unused */, int status,
int server_if, std::vector<btgatt_db_element_t> service) override;
diff --git a/test/suite/gatt/gatt_unittest.cc b/test/suite/gatt/gatt_unittest.cc
index bc4c29e..26fd850 100644
--- a/test/suite/gatt/gatt_unittest.cc
+++ b/test/suite/gatt/gatt_unittest.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2015 Google, Inc.
+ * Copyright 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,25 +22,11 @@
#include "gatt/gatt_test.h"
-#define DEFAULT_RANDOM_SEED 42
-
-namespace {
-
-static void create_random_uuid(bt_uuid_t* uuid, int seed) {
- srand(seed < 0 ? time(NULL) : seed);
- for (int i = 0; i < 16; ++i) {
- uuid->uu[i] = (uint8_t)(rand() % 256);
- }
-}
-
-} // namespace
-
namespace bttest {
TEST_F(GattTest, GattClientRegister) {
// Registers gatt client.
- bt_uuid_t gatt_client_uuid;
- create_random_uuid(&gatt_client_uuid, DEFAULT_RANDOM_SEED);
+ bluetooth::Uuid gatt_client_uuid = bluetooth::Uuid::GetRandom();
gatt_client_interface()->register_client(gatt_client_uuid);
semaphore_wait(register_client_callback_sem_);
EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
@@ -52,8 +38,7 @@
TEST_F(GattTest, GattServerRegister) {
// Registers gatt server.
- bt_uuid_t gatt_server_uuid;
- create_random_uuid(&gatt_server_uuid, DEFAULT_RANDOM_SEED);
+ bluetooth::Uuid gatt_server_uuid = bluetooth::Uuid::GetRandom();
gatt_server_interface()->register_server(gatt_server_uuid);
semaphore_wait(register_server_callback_sem_);
EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
@@ -65,24 +50,20 @@
TEST_F(GattTest, GattServerBuild) {
// Registers gatt server.
- bt_uuid_t gatt_server_uuid;
- create_random_uuid(&gatt_server_uuid, DEFAULT_RANDOM_SEED);
+ bluetooth::Uuid gatt_server_uuid = bluetooth::Uuid::GetRandom();
gatt_server_interface()->register_server(gatt_server_uuid);
semaphore_wait(register_server_callback_sem_);
EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
<< "Error registering GATT server app callback.";
// Service UUID.
- bt_uuid_t srvc_uuid;
- create_random_uuid(&srvc_uuid, -1);
+ bluetooth::Uuid srvc_uuid = bluetooth::Uuid::GetRandom();
// Characteristics UUID.
- bt_uuid_t char_uuid;
- create_random_uuid(&char_uuid, -1);
+ bluetooth::Uuid char_uuid = bluetooth::Uuid::GetRandom();
// Descriptor UUID.
- bt_uuid_t desc_uuid;
- create_random_uuid(&desc_uuid, -1);
+ bluetooth::Uuid desc_uuid = bluetooth::Uuid::GetRandom();
// Adds service.
int server_if = server_interface_id();
diff --git a/test/suite/rfcomm/rfcomm_test.cc b/test/suite/rfcomm/rfcomm_test.cc
index 194320d..01d9fed 100644
--- a/test/suite/rfcomm/rfcomm_test.cc
+++ b/test/suite/rfcomm/rfcomm_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,13 +19,11 @@
#include "rfcomm/rfcomm_test.h"
#include "adapter/bluetooth_test.h"
-#include "btcore/include/uuid.h"
+using bluetooth::Uuid;
namespace bttest {
-const bt_uuid_t RFCommTest::HFP_UUID = {{0x00, 0x00, 0x11, 0x1E, 0x00, 0x00,
- 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
- 0x5F, 0x9B, 0x34, 0xFB}};
+const Uuid RFCommTest::HFP_UUID = Uuid::From16Bit(0x111E);
void RFCommTest::SetUp() {
BluetoothTest::SetUp();
@@ -40,7 +38,6 @@
// Find a bonded device that supports HFP
bt_remote_bdaddr_ = RawAddress::kEmpty;
- char value[1280];
bt_property_t* bonded_devices_prop =
GetProperty(BT_PROPERTY_ADAPTER_BONDED_DEVICES);
@@ -55,12 +52,11 @@
bt_property_t* uuid_prop =
GetRemoteDeviceProperty(&devices[i], BT_PROPERTY_UUIDS);
if (uuid_prop == nullptr) continue;
- bt_uuid_t* uuids = (bt_uuid_t*)uuid_prop->val;
- int num_uuids = uuid_prop->len / sizeof(bt_uuid_t);
+ Uuid* uuids = reinterpret_cast<Uuid*>(uuid_prop->val);
+ int num_uuids = uuid_prop->len / sizeof(Uuid);
for (int j = 0; j < num_uuids; j++) {
- uuid_to_string(&uuids[j], (uuid_string_t*)value);
- if (!memcmp(uuids + j, &HFP_UUID, sizeof(bt_uuid_t))) {
+ if (!memcmp(uuids + j, &HFP_UUID, sizeof(Uuid))) {
bt_remote_bdaddr_ = *(devices + i);
break;
}
diff --git a/test/suite/rfcomm/rfcomm_test.h b/test/suite/rfcomm/rfcomm_test.h
index 03d2730..52f7f55 100644
--- a/test/suite/rfcomm/rfcomm_test.h
+++ b/test/suite/rfcomm/rfcomm_test.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@
RawAddress bt_remote_bdaddr_;
- static const bt_uuid_t HFP_UUID;
+ static const bluetooth::Uuid HFP_UUID;
private:
const btsock_interface_t* socket_interface_;
diff --git a/test/suite/rfcomm/rfcomm_unittest.cc b/test/suite/rfcomm/rfcomm_unittest.cc
index eabe73c..357f1aa 100644
--- a/test/suite/rfcomm/rfcomm_unittest.cc
+++ b/test/suite/rfcomm/rfcomm_unittest.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,8 +34,7 @@
size_t len = 0;
error = socket_interface()->connect(&bt_remote_bdaddr_, BTSOCK_RFCOMM,
- (const uint8_t*)&HFP_UUID, 0, &fd, 0,
- getuid());
+ &HFP_UUID, 0, &fd, 0, getuid());
EXPECT_TRUE(error == BT_STATUS_SUCCESS) << "Error creating RFCOMM socket: "
<< error;
EXPECT_TRUE(fd != -1) << "Error creating RFCOMM socket: invalid fd";
@@ -76,8 +75,7 @@
size_t len = 0;
error = socket_interface()->connect(&bt_remote_bdaddr_, BTSOCK_RFCOMM,
- (const uint8_t*)&HFP_UUID, 0, &fd, 0,
- getuid());
+ &HFP_UUID, 0, &fd, 0, getuid());
ASSERT_TRUE(error == BT_STATUS_SUCCESS) << "Error creating RFCOMM socket: "
<< error;
ASSERT_TRUE(fd != -1) << "Error creating RFCOMM socket: invalid fd";
diff --git a/tools/Android.bp b/tools/Android.bp
index 1357a93..9f75ba7 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/bdtool/Android.mk.disabled b/tools/bdtool/Android.mk.disabled
index fa616e5..4c8321e 100644
--- a/tools/bdtool/Android.mk.disabled
+++ b/tools/bdtool/Android.mk.disabled
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2014 The Android Open Source Project
+# Copyright 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/tools/bdtool/adapter.c b/tools/bdtool/adapter.c
index c7067fc..a85e3d0 100644
--- a/tools/bdtool/adapter.c
+++ b/tools/bdtool/adapter.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -205,7 +205,7 @@
case BT_PROPERTY_UUIDS: {
size_t num_uuid;
- const bt_uuid_t* uuid = property_as_uuids(property, &num_uuid);
+ const Uuid* uuid = property_as_uuids(property, &num_uuid);
if (uuid) {
for (size_t i = 0; i < num_uuid; i++) {
fprintf(stdout, " uuid:%zd: ", i);
diff --git a/tools/bdtool/bdtool.c b/tools/bdtool/bdtool.c
index d37d3d3..44d11ff 100644
--- a/tools/bdtool/bdtool.c
+++ b/tools/bdtool/bdtool.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2014 Google, Inc.
+ * Copyright 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,12 +26,12 @@
#include "test/suite/support/callbacks.h"
#include "test/suite/support/hal.h"
-static const bt_uuid_t HFP_UUID = {{0x00, 0x00, 0x11, 0x1E, 0x00, 0x00, 0x10,
- 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B,
- 0x34, 0xFB}};
-static const bt_uuid_t HFP_AG_UUID = {{0x00, 0x00, 0x11, 0x1F, 0x00, 0x00, 0x10,
- 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B,
- 0x34, 0xFB}};
+static const Uuid HFP_UUID =
+ Uuid::From128BitBE({{0x00, 0x00, 0x11, 0x1E, 0x00, 0x00, 0x10, 0x00, 0x80,
+ 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}});
+static const Uuid HFP_AG_UUID =
+ Uuid::From128BitBE({{0x00, 0x00, 0x11, 0x1F, 0x00, 0x00, 0x10, 0x00, 0x80,
+ 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}});
const bt_interface_t* bt_interface;
diff --git a/tools/hci/Android.mk.disabled b/tools/hci/Android.mk.disabled
index 3e2286a..6439dfc 100644
--- a/tools/hci/Android.mk.disabled
+++ b/tools/hci/Android.mk.disabled
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2014 The Android Open Source Project
+# Copyright 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/tools/mcap_tool/Android.bp b/tools/mcap_tool/Android.bp
index aca07dd..eec750c 100644
--- a/tools/mcap_tool/Android.bp
+++ b/tools/mcap_tool/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
],
include_dirs: [
"system/bt",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/stack/include",
"system/bt/btcore/include",
],
@@ -33,7 +33,6 @@
shared_libs: [
"libcutils",
"libutils",
- "libhardware",
],
static_libs: [
"libbtcore",
diff --git a/tools/mcap_tool/BUILD.gn b/tools/mcap_tool/BUILD.gn
index a3f18eb..d41ed56 100644
--- a/tools/mcap_tool/BUILD.gn
+++ b/tools/mcap_tool/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2017 Google, Inc.
+# Copyright 2017 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
]
include_dirs = [
"//",
- "//include",
+ "//internal_include",
"//stack/include",
"//btif/include",
"//btcore/include",
diff --git a/tools/mcap_tool/mcap_test_app.cc b/tools/mcap_tool/mcap_test_app.cc
index f0c1b4f..9515f20 100644
--- a/tools/mcap_tool/mcap_test_app.cc
+++ b/tools/mcap_tool/mcap_test_app.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/mcap_tool/mcap_test_app.h b/tools/mcap_tool/mcap_test_app.h
index 691b1f6..db81657 100644
--- a/tools/mcap_tool/mcap_test_app.h
+++ b/tools/mcap_tool/mcap_test_app.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/mcap_tool/mcap_test_mcl.cc b/tools/mcap_tool/mcap_test_mcl.cc
index 629350a..53cc329 100644
--- a/tools/mcap_tool/mcap_test_mcl.cc
+++ b/tools/mcap_tool/mcap_test_mcl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/mcap_tool/mcap_test_mcl.h b/tools/mcap_tool/mcap_test_mcl.h
index 01a8aa6..6700fb1 100644
--- a/tools/mcap_tool/mcap_test_mcl.h
+++ b/tools/mcap_tool/mcap_test_mcl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/mcap_tool/mcap_test_mdep.cc b/tools/mcap_tool/mcap_test_mdep.cc
index 1fb6412..bd2ce23 100644
--- a/tools/mcap_tool/mcap_test_mdep.cc
+++ b/tools/mcap_tool/mcap_test_mdep.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/mcap_tool/mcap_test_mdep.h b/tools/mcap_tool/mcap_test_mdep.h
index a852d52..2278781 100644
--- a/tools/mcap_tool/mcap_test_mdep.h
+++ b/tools/mcap_tool/mcap_test_mdep.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/mcap_tool/mcap_test_mdl.cc b/tools/mcap_tool/mcap_test_mdl.cc
index e7b8083..f0cd572 100644
--- a/tools/mcap_tool/mcap_test_mdl.cc
+++ b/tools/mcap_tool/mcap_test_mdl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/mcap_tool/mcap_test_mdl.h b/tools/mcap_tool/mcap_test_mdl.h
index 7dadc34..56d8d8c 100644
--- a/tools/mcap_tool/mcap_test_mdl.h
+++ b/tools/mcap_tool/mcap_test_mdl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/mcap_tool/mcap_tool.cc b/tools/mcap_tool/mcap_tool.cc
index fad3378..6ed26aa 100644
--- a/tools/mcap_tool/mcap_tool.cc
+++ b/tools/mcap_tool/mcap_tool.cc
@@ -1,10 +1,10 @@
/******************************************************************************
*
- * Copyright (C) 2015, The linux Foundation. All rights reserved.
+ * Copyright 2015, The linux Foundation. All rights reserved.
*
* Not a Contribution.
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,7 +42,6 @@
#include <unistd.h>
#include <hardware/bluetooth.h>
-#include <hardware/hardware.h>
#ifndef OS_GENERIC
#include <private/android_filesystem_config.h>
#endif
@@ -53,9 +52,7 @@
#include "mca_api.h"
#include "mca_defs.h"
#include "osi/include/compat.h"
-#if defined(OS_GENERIC)
#include "hal_util.h"
-#endif
#include "mcap_test_app.h"
#include "mcap_test_mcl.h"
#include "mcap_test_mdep.h"
@@ -98,7 +95,6 @@
static bool global_strict_mode = false;
/* Device and Profile Interfaces */
-static bluetooth_device_t* sBtDevice = nullptr;
const bt_interface_t* sBtInterface = nullptr;
static btmcap_test_interface_t* sMcapTestInterface = nullptr;
static McapTestApp* sMcapTestApp = nullptr;
@@ -353,23 +349,15 @@
*******************************************************************************/
int HAL_load(void) {
- int err = 0;
- hw_module_t* module;
- hw_device_t* device;
LOG(INFO) << "Loading HAL library and extensions";
-#if defined(OS_GENERIC)
- err = hal_util_load_bt_library((hw_module_t const**)&module);
-#else
- err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
-#endif
- if (!err) {
- err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
- if (!err) {
- sBtDevice = (bluetooth_device_t*)device;
- sBtInterface = sBtDevice->get_bluetooth_interface();
- }
+ bt_interface_t* interface;
+ int err = hal_util_load_bt_library((const bt_interface_t**)&interface);
+ if (err) {
+ LOG(ERROR) << "Error loading HAL library: " << strerror(err);
+ return err;
}
- LOG(INFO) << "HAL library loaded, status: " << strerror(err);
+ sBtInterface = interface;
+ LOG(INFO) << "HAL library loaded";
return err;
}
diff --git a/types/Android.bp b/types/Android.bp
index cd7d96b..5867d63 100644
--- a/types/Android.bp
+++ b/types/Android.bp
@@ -1,4 +1,11 @@
// Bluetooth types
+cc_library_headers {
+ name: "libbluetooth-types-header",
+ export_include_dirs: ["./"],
+ vendor_available: true,
+ host_supported: true,
+}
+
cc_library_static {
name: "libbluetooth-types",
vendor_available: true,
@@ -10,8 +17,10 @@
host_supported: true,
srcs: [
"raw_address.cc",
+ "bluetooth/uuid.cc",
],
- export_include_dirs: ["./"],
+ header_libs: ["libbluetooth-types-header"],
+ export_header_lib_headers: ["libbluetooth-types-header"],
}
// ========================================================
@@ -22,5 +31,6 @@
host_supported: true,
srcs: [
"test/raw_address_unittest.cc",
+ "test/bluetooth/uuid_unittest.cc",
],
}
diff --git a/types/BUILD.gn b/types/BUILD.gn
index 6b18806..617bbb6 100644
--- a/types/BUILD.gn
+++ b/types/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2017 Google, Inc.
+# Copyright 2017 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
sources = [
"raw_address.cc",
+ "bluetooth/uuid.cc",
]
include_dirs = [
@@ -36,6 +37,7 @@
testonly = true
sources = [
"test/raw_address_unittest.cc",
+ "test/bluetooth/uuid_unittest.cc",
]
include_dirs = [
diff --git a/types/bluetooth/uuid.cc b/types/bluetooth/uuid.cc
new file mode 100644
index 0000000..4e7d544
--- /dev/null
+++ b/types/bluetooth/uuid.cc
@@ -0,0 +1,172 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "uuid.h"
+
+#include <base/rand_util.h>
+#include <base/strings/stringprintf.h>
+#include <algorithm>
+
+namespace bluetooth {
+
+static_assert(sizeof(Uuid) == 16, "Uuid must be 16 bytes long!");
+
+using UUID128Bit = Uuid::UUID128Bit;
+
+const Uuid Uuid::kEmpty = Uuid::From128BitBE(UUID128Bit{{0x00}});
+
+namespace {
+constexpr Uuid kBase = Uuid::From128BitBE(
+ UUID128Bit{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
+ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}});
+} // namespace
+
+size_t Uuid::GetShortestRepresentationSize() const {
+ if (memcmp(uu.data() + kNumBytes32, kBase.uu.data() + kNumBytes32,
+ kNumBytes128 - kNumBytes32) != 0) {
+ return kNumBytes128;
+ }
+
+ if (uu[0] == 0 && uu[1] == 0) return kNumBytes16;
+
+ return kNumBytes32;
+}
+
+bool Uuid::Is16Bit() const {
+ return GetShortestRepresentationSize() == kNumBytes16;
+}
+
+uint16_t Uuid::As16Bit() const { return (((uint16_t)uu[2]) << 8) + uu[3]; }
+
+uint32_t Uuid::As32Bit() const {
+ return (((uint32_t)uu[0]) << 24) + (((uint32_t)uu[1]) << 16) +
+ (((uint32_t)uu[2]) << 8) + uu[3];
+}
+
+Uuid Uuid::FromString(const std::string& uuid, bool* is_valid) {
+ if (is_valid) *is_valid = false;
+ Uuid ret = kBase;
+
+ if (uuid.empty()) return ret;
+
+ uint8_t* p = ret.uu.data();
+ if (uuid.size() == kString128BitLen) {
+ if (uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' ||
+ uuid[23] != '-') {
+ return ret;
+ }
+
+ int c;
+ int rc =
+ sscanf(uuid.c_str(),
+ "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx"
+ "-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%n",
+ &p[0], &p[1], &p[2], &p[3], &p[4], &p[5], &p[6], &p[7], &p[8],
+ &p[9], &p[10], &p[11], &p[12], &p[13], &p[14], &p[15], &c);
+ if (rc != 16) return ret;
+ if (c != kString128BitLen) return ret;
+
+ if (is_valid) *is_valid = true;
+ } else if (uuid.size() == 8) {
+ int c;
+ int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%02hhx%02hhx%n", &p[0], &p[1],
+ &p[2], &p[3], &c);
+ if (rc != 4) return ret;
+ if (c != 8) return ret;
+
+ if (is_valid) *is_valid = true;
+ } else if (uuid.size() == 4) {
+ int c;
+ int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%n", &p[2], &p[3], &c);
+ if (rc != 2) return ret;
+ if (c != 4) return ret;
+
+ if (is_valid) *is_valid = true;
+ }
+
+ return ret;
+}
+
+Uuid Uuid::From16Bit(uint16_t uuid16) {
+ Uuid u = kBase;
+
+ u.uu[2] = (uint8_t)((0xFF00 & uuid16) >> 8);
+ u.uu[3] = (uint8_t)(0x00FF & uuid16);
+ return u;
+}
+
+Uuid Uuid::From32Bit(uint32_t uuid32) {
+ Uuid u = kBase;
+
+ u.uu[0] = (uint8_t)((0xFF000000 & uuid32) >> 24);
+ u.uu[1] = (uint8_t)((0x00FF0000 & uuid32) >> 16);
+ u.uu[2] = (uint8_t)((0x0000FF00 & uuid32) >> 8);
+ u.uu[3] = (uint8_t)(0x000000FF & uuid32);
+ return u;
+}
+
+Uuid Uuid::From128BitBE(const uint8_t* uuid) {
+ UUID128Bit tmp;
+ memcpy(tmp.data(), uuid, kNumBytes128);
+ return From128BitBE(tmp);
+}
+
+Uuid Uuid::From128BitLE(const UUID128Bit& uuid) {
+ Uuid u;
+ std::reverse_copy(uuid.data(), uuid.data() + kNumBytes128, u.uu.begin());
+ return u;
+}
+
+Uuid Uuid::From128BitLE(const uint8_t* uuid) {
+ UUID128Bit tmp;
+ memcpy(tmp.data(), uuid, kNumBytes128);
+ return From128BitLE(tmp);
+}
+
+const UUID128Bit Uuid::To128BitLE() const {
+ UUID128Bit le;
+ std::reverse_copy(uu.data(), uu.data() + kNumBytes128, le.begin());
+ return le;
+}
+
+const UUID128Bit& Uuid::To128BitBE() const { return uu; }
+
+Uuid Uuid::GetRandom() {
+ Uuid uuid;
+ base::RandBytes(uuid.uu.data(), uuid.uu.size());
+ return uuid;
+}
+
+bool Uuid::IsEmpty() const { return *this == kEmpty; }
+
+bool Uuid::operator<(const Uuid& rhs) const {
+ return std::lexicographical_compare(uu.begin(), uu.end(), rhs.uu.begin(),
+ rhs.uu.end());
+}
+
+bool Uuid::operator==(const Uuid& rhs) const { return uu == rhs.uu; }
+
+bool Uuid::operator!=(const Uuid& rhs) const { return uu != rhs.uu; }
+
+std::string Uuid::ToString() const {
+ return base::StringPrintf(
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], uu[8], uu[9],
+ uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
+}
+} // namespace bluetooth
\ No newline at end of file
diff --git a/types/bluetooth/uuid.h b/types/bluetooth/uuid.h
new file mode 100644
index 0000000..9fda6b6
--- /dev/null
+++ b/types/bluetooth/uuid.h
@@ -0,0 +1,140 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <stdint.h>
+#include <array>
+#include <string>
+
+namespace bluetooth {
+
+// This class is representing Bluetooth UUIDs across whole stack.
+// Here are some general endianness rules:
+// 1. UUID is internally kept as as Big Endian.
+// 2. Bytes representing UUID coming from upper layers, Java or Binder, are Big
+// Endian.
+// 3. Bytes representing UUID coming from lower layer, HCI packets, are Little
+// Endian.
+// 4. UUID in storage is always string.
+class Uuid final {
+ public:
+ static constexpr size_t kNumBytes128 = 16;
+ static constexpr size_t kNumBytes32 = 4;
+ static constexpr size_t kNumBytes16 = 2;
+
+ static constexpr size_t kString128BitLen = 36;
+
+ static const Uuid kEmpty; // 00000000-0000-0000-0000-000000000000
+
+ using UUID128Bit = std::array<uint8_t, kNumBytes128>;
+
+ Uuid() = default;
+
+ // Creates and returns a random 128-bit UUID.
+ static Uuid GetRandom();
+
+ // Returns the shortest possible representation of this UUID in bytes. Either
+ // kNumBytes16, kNumBytes32, or kNumBytes128
+ size_t GetShortestRepresentationSize() const;
+
+ // Returns true if this UUID can be represented as 16 bit.
+ bool Is16Bit() const;
+
+ // Returns 16 bit Little Endian representation of this UUID. Use
+ // GetShortestRepresentationSize() or Is16Bit() before using this method.
+ uint16_t As16Bit() const;
+
+ // Returns 32 bit Little Endian representation of this UUID. Use
+ // GetShortestRepresentationSize() before using this method.
+ uint32_t As32Bit() const;
+
+ // Converts string representing 128, 32, or 16 bit UUID in
+ // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, xxxxxxxx, or xxxx format to UUID. If
+ // set, optional is_valid parameter will be set to true if conversion is
+ // successfull, false otherwise.
+ static Uuid FromString(const std::string& uuid, bool* is_valid = nullptr);
+
+ // Converts 16bit Little Endian representation of UUID to UUID
+ static Uuid From16Bit(uint16_t uuid16bit);
+
+ // Converts 32bit Little Endian representation of UUID to UUID
+ static Uuid From32Bit(uint32_t uuid32bit);
+
+ // Converts 128 bit Big Endian array representing UUID to UUID.
+ static constexpr Uuid From128BitBE(const UUID128Bit& uuid) {
+ Uuid u(uuid);
+ return u;
+ }
+
+ // Converts 128 bit Big Endian array representing UUID to UUID. |uuid| points
+ // to beginning of array.
+ static Uuid From128BitBE(const uint8_t* uuid);
+
+ // Converts 128 bit Little Endian array representing UUID to UUID.
+ static Uuid From128BitLE(const UUID128Bit& uuid);
+
+ // Converts 128 bit Little Endian array representing UUID to UUID. |uuid|
+ // points to beginning of array.
+ static Uuid From128BitLE(const uint8_t* uuid);
+
+ // Returns 128 bit Little Endian representation of this UUID
+ const UUID128Bit To128BitLE() const;
+
+ // Returns 128 bit Big Endian representation of this UUID
+ const UUID128Bit& To128BitBE() const;
+
+ // Returns string representing this UUID in
+ // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format, lowercase.
+ std::string ToString() const;
+
+ // Returns true if this UUID is equal to kEmpty
+ bool IsEmpty() const;
+
+ bool operator<(const Uuid& rhs) const;
+ bool operator==(const Uuid& rhs) const;
+ bool operator!=(const Uuid& rhs) const;
+
+ private:
+ constexpr Uuid(const UUID128Bit& val) : uu{val} {};
+
+ // Network-byte-ordered ID (Big Endian).
+ UUID128Bit uu;
+};
+} // namespace bluetooth
+
+inline std::ostream& operator<<(std::ostream& os, const bluetooth::Uuid& a) {
+ os << a.ToString();
+ return os;
+}
+
+// Custom std::hash specialization so that bluetooth::UUID can be used as a key
+// in std::unordered_map.
+namespace std {
+
+template <>
+struct hash<bluetooth::Uuid> {
+ std::size_t operator()(const bluetooth::Uuid& key) const {
+ const auto& uuid_bytes = key.To128BitBE();
+ std::hash<std::string> hash_fn;
+ return hash_fn(std::string(reinterpret_cast<const char*>(uuid_bytes.data()),
+ uuid_bytes.size()));
+ }
+};
+
+} // namespace std
diff --git a/types/raw_address.cc b/types/raw_address.cc
index 22c1081..b39e4552e 100644
--- a/types/raw_address.cc
+++ b/types/raw_address.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,6 +62,11 @@
return true;
}
+size_t RawAddress::FromOctets(const uint8_t* from) {
+ std::copy(from, from + kLength, address);
+ return kLength;
+};
+
bool RawAddress::IsValidAddress(const std::string& address) {
RawAddress tmp;
return RawAddress::FromString(address, tmp);
diff --git a/types/raw_address.h b/types/raw_address.h
index 0b42c04..49443a8 100644
--- a/types/raw_address.h
+++ b/types/raw_address.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,6 +50,10 @@
// returns false. Otherwise, it returns true.
static bool FromString(const std::string& from, RawAddress& to);
+ // Copies |from| raw Bluetooth address octets to the local object.
+ // Returns the number of copied octets - should be always RawAddress::kLength
+ size_t FromOctets(const uint8_t* from);
+
static bool IsValidAddress(const std::string& address);
static const RawAddress kEmpty; // 00:00:00:00:00:00
diff --git a/types/test/bluetooth/uuid_unittest.cc b/types/test/bluetooth/uuid_unittest.cc
new file mode 100644
index 0000000..2cdaf54
--- /dev/null
+++ b/types/test/bluetooth/uuid_unittest.cc
@@ -0,0 +1,170 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2017 Google, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <bluetooth/uuid.h>
+#include <gtest/gtest.h>
+
+using bluetooth::Uuid;
+
+static const Uuid ONES = Uuid::From128BitBE(
+ Uuid::UUID128Bit{{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}});
+
+static const Uuid SEQUENTIAL = Uuid::From128BitBE(
+ Uuid::UUID128Bit{{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xab,
+ 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89}});
+
+constexpr Uuid kBase = Uuid::From128BitBE(
+ Uuid::UUID128Bit{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80,
+ 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}});
+
+TEST(UuidTest, IsEmpty) {
+ EXPECT_TRUE(Uuid::kEmpty.IsEmpty());
+ EXPECT_FALSE(kBase.IsEmpty());
+}
+
+TEST(UuidTest, GetShortestRepresentationSize) {
+ EXPECT_TRUE(Uuid::kNumBytes16 == kBase.GetShortestRepresentationSize());
+ EXPECT_TRUE(Uuid::kNumBytes32 ==
+ Uuid::From32Bit(0x01234567).GetShortestRepresentationSize());
+ EXPECT_TRUE(Uuid::kNumBytes128 ==
+ Uuid::kEmpty.GetShortestRepresentationSize());
+}
+
+TEST(UuidTest, As16Bit) {
+ // Even though this is is not 16bit UUID, we should be able to get proper bits
+ EXPECT_EQ((uint16_t)0x1111, ONES.As16Bit());
+ EXPECT_EQ((uint16_t)0x4567, SEQUENTIAL.As16Bit());
+ EXPECT_EQ((uint16_t)0x0000, kBase.As16Bit());
+}
+
+TEST(UuidTest, As32Bit) {
+ // Even though this is is not 32bit UUID, we should be able to get proper bits
+ EXPECT_EQ((uint32_t)0x11111111, ONES.As32Bit());
+ EXPECT_EQ((uint32_t)0x01234567, SEQUENTIAL.As32Bit());
+ EXPECT_EQ((uint32_t)0x00000000, kBase.As32Bit());
+ EXPECT_EQ((uint32_t)0x12345678, Uuid::From32Bit(0x12345678).As32Bit());
+}
+
+TEST(UuidTest, Is16Bit) {
+ EXPECT_FALSE(ONES.Is16Bit());
+ EXPECT_FALSE(SEQUENTIAL.Is16Bit());
+ EXPECT_TRUE(kBase.Is16Bit());
+ EXPECT_TRUE(Uuid::FromString("1ae8").Is16Bit());
+}
+
+TEST(UuidTest, From16Bit) {
+ EXPECT_EQ(Uuid::From16Bit(0x0000), kBase);
+
+ const uint8_t u2[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ Uuid uuid = Uuid::From16Bit(0x0001);
+ EXPECT_TRUE(memcmp(&uuid, u2, sizeof(u2)) == 0);
+
+ const uint8_t u3[] = {0x00, 0x00, 0x55, 0x3e, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ uuid = Uuid::From16Bit(0x553e);
+ EXPECT_TRUE(memcmp(&uuid, u3, sizeof(u3)) == 0);
+
+ const uint8_t u4[] = {0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ uuid = Uuid::From16Bit(0xffff);
+ EXPECT_TRUE(memcmp(&uuid, u4, sizeof(u4)) == 0);
+}
+
+TEST(UuidTest, From32Bit) {
+ EXPECT_EQ(Uuid::From32Bit(0x00000000), kBase);
+
+ const uint8_t u2[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ Uuid uuid = Uuid::From32Bit(0x00000001);
+ EXPECT_TRUE(memcmp(&uuid, u2, sizeof(u2)) == 0);
+
+ const uint8_t u3[] = {0x33, 0x44, 0x55, 0x3e, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ uuid = Uuid::From32Bit(0x3344553e);
+ EXPECT_TRUE(memcmp(&uuid, u3, sizeof(u3)) == 0);
+
+ const uint8_t u4[] = {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ uuid = Uuid::From32Bit(0xffffffff);
+ EXPECT_TRUE(memcmp(&uuid, u4, sizeof(u4)) == 0);
+}
+
+TEST(UuidTest, ToString) {
+ const std::string UUID_BASE_STR = "00000000-0000-1000-8000-00805f9b34fb";
+ const std::string UUID_EMP_STR = "00000000-0000-0000-0000-000000000000";
+ const std::string UUID_ONES_STR = "11111111-1111-1111-1111-111111111111";
+ const std::string UUID_SEQ_STR = "01234567-89ab-cdef-abcd-ef0123456789";
+
+ EXPECT_EQ(UUID_BASE_STR, kBase.ToString());
+ EXPECT_EQ(UUID_EMP_STR, Uuid::kEmpty.ToString());
+ EXPECT_EQ(UUID_ONES_STR, ONES.ToString());
+ EXPECT_EQ(UUID_SEQ_STR, SEQUENTIAL.ToString());
+
+ Uuid uuid = Uuid::From32Bit(0x12345678);
+ EXPECT_EQ("12345678-0000-1000-8000-00805f9b34fb", uuid.ToString());
+}
+
+TEST(BtifStorageTest, test_string_to_uuid) {
+ const uint8_t u1[] = {0xe3, 0x9c, 0x62, 0x85, 0x86, 0x7f, 0x4b, 0x1d,
+ 0x9d, 0xb0, 0x35, 0xfb, 0xd9, 0xae, 0xbf, 0x22};
+ bool is_valid = false;
+ Uuid uuid =
+ Uuid::FromString("e39c6285-867f-4b1d-9db0-35fbd9aebf22", &is_valid);
+ EXPECT_TRUE(is_valid);
+ EXPECT_TRUE(memcmp(&uuid, u1, sizeof(u1)) == 0);
+
+ const uint8_t u2[] = {0x00, 0x00, 0x1a, 0xe8, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ is_valid = false;
+ uuid = Uuid::FromString("1Ae8", &is_valid);
+ EXPECT_TRUE(is_valid);
+ EXPECT_TRUE(memcmp(&uuid, u2, sizeof(u2)) == 0);
+
+ const uint8_t u3[] = {0x12, 0x34, 0x11, 0x28, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ is_valid = false;
+ uuid = Uuid::FromString("12341128", &is_valid);
+ EXPECT_TRUE(is_valid);
+ EXPECT_TRUE(memcmp(&uuid, u3, sizeof(u3)) == 0);
+}
+
+TEST(BtifStorageTest, test_string_to_uuid_invalid) {
+ bool is_valid = false;
+ Uuid uuid = Uuid::FromString("This is not a UUID", &is_valid);
+ EXPECT_FALSE(is_valid);
+
+ uuid = Uuid::FromString("11212", &is_valid);
+ EXPECT_FALSE(is_valid);
+
+ uuid = Uuid::FromString("1121 ", &is_valid);
+ EXPECT_FALSE(is_valid);
+
+ uuid = Uuid::FromString("AGFE", &is_valid);
+ EXPECT_FALSE(is_valid);
+
+ uuid = Uuid::FromString("ABFG", &is_valid);
+ EXPECT_FALSE(is_valid);
+
+ uuid = Uuid::FromString("e39c6285867f14b1d9db035fbd9aebf22", &is_valid);
+ EXPECT_FALSE(is_valid);
+
+ uuid = Uuid::FromString("12234567-89ab-cdef-abcd-ef01234567ZZ", &is_valid);
+ EXPECT_FALSE(is_valid);
+}
diff --git a/types/test/raw_address_unittest.cc b/types/test/raw_address_unittest.cc
index dcfab85..4ff31e5 100644
--- a/types/test/raw_address_unittest.cc
+++ b/types/test/raw_address_unittest.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,21 @@
static const char* test_addr = "12:34:56:78:9a:bc";
static const char* test_addr2 = "cb:a9:87:65:43:21";
+TEST(RawAddressUnittest, test_constructor_array) {
+ RawAddress bdaddr({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc});
+
+ ASSERT_EQ(0x12, bdaddr.address[0]);
+ ASSERT_EQ(0x34, bdaddr.address[1]);
+ ASSERT_EQ(0x56, bdaddr.address[2]);
+ ASSERT_EQ(0x78, bdaddr.address[3]);
+ ASSERT_EQ(0x9A, bdaddr.address[4]);
+ ASSERT_EQ(0xBC, bdaddr.address[5]);
+
+ std::string ret = bdaddr.ToString();
+
+ ASSERT_STREQ(test_addr, ret.c_str());
+}
+
TEST(RawAddressUnittest, test_is_empty) {
RawAddress empty;
RawAddress::FromString("00:00:00:00:00:00", empty);
@@ -49,6 +64,25 @@
ASSERT_STREQ(test_addr, ret.c_str());
}
+TEST(RawAddressUnittest, test_from_octets) {
+ static const uint8_t test_addr_array[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
+
+ RawAddress bdaddr;
+ size_t expected_result = RawAddress::kLength;
+ ASSERT_EQ(expected_result, bdaddr.FromOctets(test_addr_array));
+
+ ASSERT_EQ(0x12, bdaddr.address[0]);
+ ASSERT_EQ(0x34, bdaddr.address[1]);
+ ASSERT_EQ(0x56, bdaddr.address[2]);
+ ASSERT_EQ(0x78, bdaddr.address[3]);
+ ASSERT_EQ(0x9A, bdaddr.address[4]);
+ ASSERT_EQ(0xBC, bdaddr.address[5]);
+
+ std::string ret = bdaddr.ToString();
+
+ ASSERT_STREQ(test_addr, ret.c_str());
+}
+
TEST(RawAddressTest, test_equals) {
RawAddress bdaddr1;
RawAddress bdaddr2;
diff --git a/udrv/Android.bp b/udrv/Android.bp
index a571478..9bf1d83 100644
--- a/udrv/Android.bp
+++ b/udrv/Android.bp
@@ -6,7 +6,7 @@
],
include_dirs: [
"system/bt",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/utils/include",
"system/bt/stack/include",
],
diff --git a/udrv/BUILD.gn b/udrv/BUILD.gn
index 679d469..8a0fc92 100644
--- a/udrv/BUILD.gn
+++ b/udrv/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
"include",
"uipc",
"//",
- "//include",
+ "//internal_include",
"//stack/include",
"//utils/include",
]
diff --git a/udrv/include/uipc.h b/udrv/include/uipc.h
index 62fadf1..78c6ed3 100644
--- a/udrv/include/uipc.h
+++ b/udrv/include/uipc.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2007-2012 Broadcom Corporation
+ * Copyright 2007-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@
#ifndef UIPC_H
#define UIPC_H
+#include <mutex>
+
#define UIPC_CH_ID_AV_CTRL 0
#define UIPC_CH_ID_AV_AUDIO 1
#define UIPC_CH_NUM 2
@@ -55,72 +57,85 @@
const char* dump_uipc_event(tUIPC_EVENT event);
-/*******************************************************************************
- *
- * Function UIPC_Init
- *
- * Description Initialize UIPC module
- *
- * Returns void
- *
- ******************************************************************************/
-void UIPC_Init(void*);
+typedef struct {
+ int srvfd;
+ int fd;
+ int read_poll_tmo_ms;
+ int task_evt_flags; /* event flags pending to be processed in read task */
+ tUIPC_RCV_CBACK* cback;
+} tUIPC_CHAN;
-/*******************************************************************************
- *
- * Function UIPC_Open
- *
- * Description Open UIPC interface
- *
- * Returns void
- *
- ******************************************************************************/
-bool UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK* p_cback);
+struct tUIPC_STATE {
+ pthread_t tid; /* main thread id */
+ int running;
+ std::recursive_mutex mutex;
-/*******************************************************************************
- *
- * Function UIPC_Close
- *
- * Description Close UIPC interface
- *
- * Returns void
- *
- ******************************************************************************/
-void UIPC_Close(tUIPC_CH_ID ch_id);
+ fd_set active_set;
+ fd_set read_set;
+ int max_fd;
+ int signal_fds[2];
-/*******************************************************************************
- *
- * Function UIPC_Send
- *
- * Description Called to transmit a message over UIPC.
- *
- * Returns void
- *
- ******************************************************************************/
-bool UIPC_Send(tUIPC_CH_ID ch_id, uint16_t msg_evt, const uint8_t* p_buf,
- uint16_t msglen);
+ tUIPC_CHAN ch[UIPC_CH_NUM];
+};
-/*******************************************************************************
+/**
+ * Initialize UIPC module
*
- * Function UIPC_Read
- *
- * Description Called to read a message from UIPC.
- *
- * Returns void
- *
- ******************************************************************************/
-uint32_t UIPC_Read(tUIPC_CH_ID ch_id, uint16_t* p_msg_evt, uint8_t* p_buf,
- uint32_t len);
+ * @param user User ID who uses UIPC
+ */
+std::unique_ptr<tUIPC_STATE> UIPC_Init();
-/*******************************************************************************
+/**
+ * Open a UIPC channel
*
- * Function UIPC_Ioctl
+ * @param ch_id Channel ID
+ * @param p_cback Callback handler
+ * @param socket_path Path to the socket
+ * @return true on success, otherwise false
+ */
+bool UIPC_Open(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK* p_cback,
+ const char* socket_path);
+
+/**
+ * Closes a channel in UIPC or the entire UIPC module
*
- * Description Called to control UIPC.
+ * @param ch_id Channel ID; if ch_id is UIPC_CH_ID_ALL, then cleanup UIPC
+ */
+void UIPC_Close(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id);
+
+/**
+ * Send a message over UIPC
*
- * Returns void
+ * @param ch_id Channel ID
+ * @param msg_evt Message event type
+ * @param p_buf Buffer for the message
+ * @param msglen Message length
+ * @return true on success, otherwise false
+ */
+bool UIPC_Send(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, uint16_t msg_evt,
+ const uint8_t* p_buf, uint16_t msglen);
+
+/**
+ * Read a message from UIPC
*
- ******************************************************************************/
-bool UIPC_Ioctl(tUIPC_CH_ID ch_id, uint32_t request, void* param);
+ * @param ch_id Channel ID
+ * @param p_msg_evt Message event type
+ * @param p_buf Buffer for the message
+ * @param len Bytes to read
+ * @return true on success, otherwise false
+ */
+uint32_t UIPC_Read(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, uint16_t* p_msg_evt,
+ uint8_t* p_buf, uint32_t len);
+
+/**
+ * Control the UIPC parameter
+ *
+ * @param ch_id Channel ID
+ * @param request Request type
+ * @param param Optional parameters
+ * @return true on success, otherwise false
+ */
+bool UIPC_Ioctl(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, uint32_t request,
+ void* param);
#endif /* UIPC_H */
diff --git a/udrv/ulinux/uipc.cc b/udrv/ulinux/uipc.cc
index 4f7d126..e2f2950 100644
--- a/udrv/ulinux/uipc.cc
+++ b/udrv/ulinux/uipc.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@
#include <sys/un.h>
#include <unistd.h>
#include <mutex>
+#include <set>
#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
#include "bt_common.h"
@@ -74,38 +75,10 @@
UIPC_TASK_FLAG_DISCONNECT_CHAN = 0x1,
} tUIPC_TASK_FLAGS;
-typedef struct {
- int srvfd;
- int fd;
- int read_poll_tmo_ms;
- int task_evt_flags; /* event flags pending to be processed in read task */
- tUIPC_RCV_CBACK* cback;
-} tUIPC_CHAN;
-
-typedef struct {
- pthread_t tid; /* main thread id */
- int running;
- std::recursive_mutex mutex;
-
- fd_set active_set;
- fd_set read_set;
- int max_fd;
- int signal_fds[2];
-
- tUIPC_CHAN ch[UIPC_CH_NUM];
-} tUIPC_MAIN;
-
-/*****************************************************************************
- * Static variables
- *****************************************************************************/
-
-static tUIPC_MAIN uipc_main;
-
/*****************************************************************************
* Static functions
*****************************************************************************/
-
-static int uipc_close_ch_locked(tUIPC_CH_ID ch_id);
+static int uipc_close_ch_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id);
/*****************************************************************************
* Externs
@@ -205,29 +178,29 @@
*
****************************************************************************/
-static int uipc_main_init(void) {
+static int uipc_main_init(tUIPC_STATE& uipc) {
int i;
BTIF_TRACE_EVENT("### uipc_main_init ###");
- uipc_main.tid = 0;
- uipc_main.running = 0;
- memset(&uipc_main.active_set, 0, sizeof(uipc_main.active_set));
- memset(&uipc_main.read_set, 0, sizeof(uipc_main.read_set));
- uipc_main.max_fd = 0;
- memset(&uipc_main.signal_fds, 0, sizeof(uipc_main.signal_fds));
- memset(&uipc_main.ch, 0, sizeof(uipc_main.ch));
+ uipc.tid = 0;
+ uipc.running = 0;
+ memset(&uipc.active_set, 0, sizeof(uipc.active_set));
+ memset(&uipc.read_set, 0, sizeof(uipc.read_set));
+ uipc.max_fd = 0;
+ memset(&uipc.signal_fds, 0, sizeof(uipc.signal_fds));
+ memset(&uipc.ch, 0, sizeof(uipc.ch));
/* setup interrupt socket pair */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, uipc_main.signal_fds) < 0) {
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, uipc.signal_fds) < 0) {
return -1;
}
- FD_SET(uipc_main.signal_fds[0], &uipc_main.active_set);
- uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.signal_fds[0]);
+ FD_SET(uipc.signal_fds[0], &uipc.active_set);
+ uipc.max_fd = MAX(uipc.max_fd, uipc.signal_fds[0]);
for (i = 0; i < UIPC_CH_NUM; i++) {
- tUIPC_CHAN* p = &uipc_main.ch[i];
+ tUIPC_CHAN* p = &uipc.ch[i];
p->srvfd = UIPC_DISCONNECTED;
p->fd = UIPC_DISCONNECTED;
p->task_evt_flags = 0;
@@ -237,105 +210,104 @@
return 0;
}
-void uipc_main_cleanup(void) {
+void uipc_main_cleanup(tUIPC_STATE& uipc) {
int i;
BTIF_TRACE_EVENT("uipc_main_cleanup");
- close(uipc_main.signal_fds[0]);
- close(uipc_main.signal_fds[1]);
+ close(uipc.signal_fds[0]);
+ close(uipc.signal_fds[1]);
/* close any open channels */
- for (i = 0; i < UIPC_CH_NUM; i++) uipc_close_ch_locked(i);
+ for (i = 0; i < UIPC_CH_NUM; i++) uipc_close_ch_locked(uipc, i);
}
/* check pending events in read task */
-static void uipc_check_task_flags_locked(void) {
+static void uipc_check_task_flags_locked(tUIPC_STATE& uipc) {
int i;
for (i = 0; i < UIPC_CH_NUM; i++) {
- if (uipc_main.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN) {
- uipc_main.ch[i].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN;
- uipc_close_ch_locked(i);
+ if (uipc.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN) {
+ uipc.ch[i].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN;
+ uipc_close_ch_locked(uipc, i);
}
/* add here */
}
}
-static int uipc_check_fd_locked(tUIPC_CH_ID ch_id) {
+static int uipc_check_fd_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
if (ch_id >= UIPC_CH_NUM) return -1;
- // BTIF_TRACE_EVENT("CHECK SRVFD %d (ch %d)", uipc_main.ch[ch_id].srvfd,
+ // BTIF_TRACE_EVENT("CHECK SRVFD %d (ch %d)", uipc.ch[ch_id].srvfd,
// ch_id);
- if (SAFE_FD_ISSET(uipc_main.ch[ch_id].srvfd, &uipc_main.read_set)) {
+ if (SAFE_FD_ISSET(uipc.ch[ch_id].srvfd, &uipc.read_set)) {
BTIF_TRACE_EVENT("INCOMING CONNECTION ON CH %d", ch_id);
// Close the previous connection
- if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED) {
- BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc_main.ch[ch_id].fd);
- close(uipc_main.ch[ch_id].fd);
- FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
- uipc_main.ch[ch_id].fd = UIPC_DISCONNECTED;
+ if (uipc.ch[ch_id].fd != UIPC_DISCONNECTED) {
+ BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc.ch[ch_id].fd);
+ close(uipc.ch[ch_id].fd);
+ FD_CLR(uipc.ch[ch_id].fd, &uipc.active_set);
+ uipc.ch[ch_id].fd = UIPC_DISCONNECTED;
}
- uipc_main.ch[ch_id].fd = accept_server_socket(uipc_main.ch[ch_id].srvfd);
+ uipc.ch[ch_id].fd = accept_server_socket(uipc.ch[ch_id].srvfd);
- BTIF_TRACE_EVENT("NEW FD %d", uipc_main.ch[ch_id].fd);
+ BTIF_TRACE_EVENT("NEW FD %d", uipc.ch[ch_id].fd);
- if ((uipc_main.ch[ch_id].fd >= 0) && uipc_main.ch[ch_id].cback) {
+ if ((uipc.ch[ch_id].fd >= 0) && uipc.ch[ch_id].cback) {
/* if we have a callback we should add this fd to the active set
and notify user with callback event */
- BTIF_TRACE_EVENT("ADD FD %d TO ACTIVE SET", uipc_main.ch[ch_id].fd);
- FD_SET(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
- uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.ch[ch_id].fd);
+ BTIF_TRACE_EVENT("ADD FD %d TO ACTIVE SET", uipc.ch[ch_id].fd);
+ FD_SET(uipc.ch[ch_id].fd, &uipc.active_set);
+ uipc.max_fd = MAX(uipc.max_fd, uipc.ch[ch_id].fd);
}
- if (uipc_main.ch[ch_id].fd < 0) {
+ if (uipc.ch[ch_id].fd < 0) {
BTIF_TRACE_ERROR("FAILED TO ACCEPT CH %d", ch_id);
return -1;
}
- if (uipc_main.ch[ch_id].cback)
- uipc_main.ch[ch_id].cback(ch_id, UIPC_OPEN_EVT);
+ if (uipc.ch[ch_id].cback) uipc.ch[ch_id].cback(ch_id, UIPC_OPEN_EVT);
}
- // BTIF_TRACE_EVENT("CHECK FD %d (ch %d)", uipc_main.ch[ch_id].fd, ch_id);
+ // BTIF_TRACE_EVENT("CHECK FD %d (ch %d)", uipc.ch[ch_id].fd, ch_id);
- if (SAFE_FD_ISSET(uipc_main.ch[ch_id].fd, &uipc_main.read_set)) {
+ if (SAFE_FD_ISSET(uipc.ch[ch_id].fd, &uipc.read_set)) {
// BTIF_TRACE_EVENT("INCOMING DATA ON CH %d", ch_id);
- if (uipc_main.ch[ch_id].cback)
- uipc_main.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT);
+ if (uipc.ch[ch_id].cback)
+ uipc.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT);
}
return 0;
}
-static void uipc_check_interrupt_locked(void) {
- if (SAFE_FD_ISSET(uipc_main.signal_fds[0], &uipc_main.read_set)) {
+static void uipc_check_interrupt_locked(tUIPC_STATE& uipc) {
+ if (SAFE_FD_ISSET(uipc.signal_fds[0], &uipc.read_set)) {
char sig_recv = 0;
- OSI_NO_INTR(recv(uipc_main.signal_fds[0], &sig_recv, sizeof(sig_recv),
- MSG_WAITALL));
+ OSI_NO_INTR(
+ recv(uipc.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL));
}
}
-static inline void uipc_wakeup_locked(void) {
+static inline void uipc_wakeup_locked(tUIPC_STATE& uipc) {
char sig_on = 1;
BTIF_TRACE_EVENT("UIPC SEND WAKE UP");
- OSI_NO_INTR(send(uipc_main.signal_fds[1], &sig_on, sizeof(sig_on), 0));
+ OSI_NO_INTR(send(uipc.signal_fds[1], &sig_on, sizeof(sig_on), 0));
}
-static int uipc_setup_server_locked(tUIPC_CH_ID ch_id, const char* name,
- tUIPC_RCV_CBACK* cback) {
+static int uipc_setup_server_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
+ const char* name, tUIPC_RCV_CBACK* cback) {
int fd;
BTIF_TRACE_EVENT("SETUP CHANNEL SERVER %d", ch_id);
if (ch_id >= UIPC_CH_NUM) return -1;
- std::lock_guard<std::recursive_mutex> guard(uipc_main.mutex);
+ std::lock_guard<std::recursive_mutex> guard(uipc.mutex);
fd = create_server_socket(name);
@@ -345,27 +317,27 @@
}
BTIF_TRACE_EVENT("ADD SERVER FD TO ACTIVE SET %d", fd);
- FD_SET(fd, &uipc_main.active_set);
- uipc_main.max_fd = MAX(uipc_main.max_fd, fd);
+ FD_SET(fd, &uipc.active_set);
+ uipc.max_fd = MAX(uipc.max_fd, fd);
- uipc_main.ch[ch_id].srvfd = fd;
- uipc_main.ch[ch_id].cback = cback;
- uipc_main.ch[ch_id].read_poll_tmo_ms = DEFAULT_READ_POLL_TMO_MS;
+ uipc.ch[ch_id].srvfd = fd;
+ uipc.ch[ch_id].cback = cback;
+ uipc.ch[ch_id].read_poll_tmo_ms = DEFAULT_READ_POLL_TMO_MS;
/* trigger main thread to update read set */
- uipc_wakeup_locked();
+ uipc_wakeup_locked(uipc);
return 0;
}
-static void uipc_flush_ch_locked(tUIPC_CH_ID ch_id) {
+static void uipc_flush_ch_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
char buf[UIPC_FLUSH_BUFFER_SIZE];
struct pollfd pfd;
pfd.events = POLLIN;
- pfd.fd = uipc_main.ch[ch_id].fd;
+ pfd.fd = uipc.ch[ch_id].fd;
- if (uipc_main.ch[ch_id].fd == UIPC_DISCONNECTED) {
+ if (uipc.ch[ch_id].fd == UIPC_DISCONNECTED) {
BTIF_TRACE_EVENT("%s() - fd disconnected. Exiting", __func__);
return;
}
@@ -397,65 +369,65 @@
}
}
-static void uipc_flush_locked(tUIPC_CH_ID ch_id) {
+static void uipc_flush_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
if (ch_id >= UIPC_CH_NUM) return;
switch (ch_id) {
case UIPC_CH_ID_AV_CTRL:
- uipc_flush_ch_locked(UIPC_CH_ID_AV_CTRL);
+ uipc_flush_ch_locked(uipc, UIPC_CH_ID_AV_CTRL);
break;
case UIPC_CH_ID_AV_AUDIO:
- uipc_flush_ch_locked(UIPC_CH_ID_AV_AUDIO);
+ uipc_flush_ch_locked(uipc, UIPC_CH_ID_AV_AUDIO);
break;
}
}
-static int uipc_close_ch_locked(tUIPC_CH_ID ch_id) {
+static int uipc_close_ch_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
int wakeup = 0;
BTIF_TRACE_EVENT("CLOSE CHANNEL %d", ch_id);
if (ch_id >= UIPC_CH_NUM) return -1;
- if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED) {
- BTIF_TRACE_EVENT("CLOSE SERVER (FD %d)", uipc_main.ch[ch_id].srvfd);
- close(uipc_main.ch[ch_id].srvfd);
- FD_CLR(uipc_main.ch[ch_id].srvfd, &uipc_main.active_set);
- uipc_main.ch[ch_id].srvfd = UIPC_DISCONNECTED;
+ if (uipc.ch[ch_id].srvfd != UIPC_DISCONNECTED) {
+ BTIF_TRACE_EVENT("CLOSE SERVER (FD %d)", uipc.ch[ch_id].srvfd);
+ close(uipc.ch[ch_id].srvfd);
+ FD_CLR(uipc.ch[ch_id].srvfd, &uipc.active_set);
+ uipc.ch[ch_id].srvfd = UIPC_DISCONNECTED;
wakeup = 1;
}
- if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED) {
- BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc_main.ch[ch_id].fd);
- close(uipc_main.ch[ch_id].fd);
- FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
- uipc_main.ch[ch_id].fd = UIPC_DISCONNECTED;
+ if (uipc.ch[ch_id].fd != UIPC_DISCONNECTED) {
+ BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc.ch[ch_id].fd);
+ close(uipc.ch[ch_id].fd);
+ FD_CLR(uipc.ch[ch_id].fd, &uipc.active_set);
+ uipc.ch[ch_id].fd = UIPC_DISCONNECTED;
wakeup = 1;
}
/* notify this connection is closed */
- if (uipc_main.ch[ch_id].cback)
- uipc_main.ch[ch_id].cback(ch_id, UIPC_CLOSE_EVT);
+ if (uipc.ch[ch_id].cback) uipc.ch[ch_id].cback(ch_id, UIPC_CLOSE_EVT);
/* trigger main thread update if something was updated */
- if (wakeup) uipc_wakeup_locked();
+ if (wakeup) uipc_wakeup_locked(uipc);
return 0;
}
-void uipc_close_locked(tUIPC_CH_ID ch_id) {
- if (uipc_main.ch[ch_id].srvfd == UIPC_DISCONNECTED) {
+void uipc_close_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
+ if (uipc.ch[ch_id].srvfd == UIPC_DISCONNECTED) {
BTIF_TRACE_EVENT("CHANNEL %d ALREADY CLOSED", ch_id);
return;
}
/* schedule close on this channel */
- uipc_main.ch[ch_id].task_evt_flags |= UIPC_TASK_FLAG_DISCONNECT_CHAN;
- uipc_wakeup_locked();
+ uipc.ch[ch_id].task_evt_flags |= UIPC_TASK_FLAG_DISCONNECT_CHAN;
+ uipc_wakeup_locked(uipc);
}
-static void* uipc_read_task(UNUSED_ATTR void* arg) {
+static void* uipc_read_task(void* arg) {
+ tUIPC_STATE& uipc = *((tUIPC_STATE*)arg);
int ch_id;
int result;
@@ -463,11 +435,10 @@
raise_priority_a2dp(TASK_UIPC_READ);
- while (uipc_main.running) {
- uipc_main.read_set = uipc_main.active_set;
+ while (uipc.running) {
+ uipc.read_set = uipc.active_set;
- result =
- select(uipc_main.max_fd + 1, &uipc_main.read_set, NULL, NULL, NULL);
+ result = select(uipc.max_fd + 1, &uipc.read_set, NULL, NULL, NULL);
if (result == 0) {
BTIF_TRACE_EVENT("select timeout");
@@ -481,40 +452,40 @@
}
{
- std::lock_guard<std::recursive_mutex> guard(uipc_main.mutex);
+ std::lock_guard<std::recursive_mutex> guard(uipc.mutex);
/* clear any wakeup interrupt */
- uipc_check_interrupt_locked();
+ uipc_check_interrupt_locked(uipc);
/* check pending task events */
- uipc_check_task_flags_locked();
+ uipc_check_task_flags_locked(uipc);
/* make sure we service audio channel first */
- uipc_check_fd_locked(UIPC_CH_ID_AV_AUDIO);
+ uipc_check_fd_locked(uipc, UIPC_CH_ID_AV_AUDIO);
/* check for other connections */
for (ch_id = 0; ch_id < UIPC_CH_NUM; ch_id++) {
- if (ch_id != UIPC_CH_ID_AV_AUDIO) uipc_check_fd_locked(ch_id);
+ if (ch_id != UIPC_CH_ID_AV_AUDIO) uipc_check_fd_locked(uipc, ch_id);
}
}
}
BTIF_TRACE_EVENT("UIPC READ THREAD EXITING");
- uipc_main_cleanup();
+ uipc_main_cleanup(uipc);
- uipc_main.tid = 0;
+ uipc.tid = 0;
BTIF_TRACE_EVENT("UIPC READ THREAD DONE");
return nullptr;
}
-int uipc_start_main_server_thread(void) {
- uipc_main.running = 1;
+int uipc_start_main_server_thread(tUIPC_STATE& uipc) {
+ uipc.running = 1;
- if (pthread_create(&uipc_main.tid, (const pthread_attr_t*)NULL,
- uipc_read_task, nullptr) < 0) {
+ if (pthread_create(&uipc.tid, (const pthread_attr_t*)NULL, uipc_read_task,
+ &uipc) < 0) {
BTIF_TRACE_ERROR("uipc_thread_create pthread_create failed:%d", errno);
return -1;
}
@@ -523,19 +494,19 @@
}
/* blocking call */
-void uipc_stop_main_server_thread(void) {
+void uipc_stop_main_server_thread(tUIPC_STATE& uipc) {
/* request shutdown of read thread */
{
- std::lock_guard<std::recursive_mutex> lock(uipc_main.mutex);
- uipc_main.running = 0;
- uipc_wakeup_locked();
+ std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
+ uipc.running = 0;
+ uipc_wakeup_locked(uipc);
}
/* wait until read thread is fully terminated */
/* tid might hold pointer value where it's value
is negative vaule with singed bit is set, so
corrected the logic to check zero or non zero */
- if (uipc_main.tid) pthread_join(uipc_main.tid, NULL);
+ if (uipc.tid) pthread_join(uipc.tid, NULL);
}
/*******************************************************************************
@@ -547,12 +518,16 @@
** Returns void
**
******************************************************************************/
-
-void UIPC_Init(UNUSED_ATTR void* p_data) {
+std::unique_ptr<tUIPC_STATE> UIPC_Init() {
+ std::unique_ptr<tUIPC_STATE> uipc = std::make_unique<tUIPC_STATE>();
BTIF_TRACE_DEBUG("UIPC_Init");
- uipc_main_init();
- uipc_start_main_server_thread();
+ std::lock_guard<std::recursive_mutex> lock(uipc->mutex);
+
+ uipc_main_init(*uipc);
+ uipc_start_main_server_thread(*uipc);
+
+ return uipc;
}
/*******************************************************************************
@@ -564,29 +539,22 @@
** Returns true in case of success, false in case of failure.
**
******************************************************************************/
-bool UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK* p_cback) {
+bool UIPC_Open(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK* p_cback,
+ const char* socket_path) {
BTIF_TRACE_DEBUG("UIPC_Open : ch_id %d, p_cback %x", ch_id, p_cback);
- std::lock_guard<std::recursive_mutex> lock(uipc_main.mutex);
+ std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
if (ch_id >= UIPC_CH_NUM) {
return false;
}
- if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED) {
+ if (uipc.ch[ch_id].srvfd != UIPC_DISCONNECTED) {
BTIF_TRACE_EVENT("CHANNEL %d ALREADY OPEN", ch_id);
return 0;
}
- switch (ch_id) {
- case UIPC_CH_ID_AV_CTRL:
- uipc_setup_server_locked(ch_id, A2DP_CTRL_PATH, p_cback);
- break;
-
- case UIPC_CH_ID_AV_AUDIO:
- uipc_setup_server_locked(ch_id, A2DP_DATA_PATH, p_cback);
- break;
- }
+ uipc_setup_server_locked(uipc, ch_id, socket_path, p_cback);
return true;
}
@@ -600,18 +568,18 @@
** Returns void
**
******************************************************************************/
-
-void UIPC_Close(tUIPC_CH_ID ch_id) {
+void UIPC_Close(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
BTIF_TRACE_DEBUG("UIPC_Close : ch_id %d", ch_id);
/* special case handling uipc shutdown */
if (ch_id != UIPC_CH_ID_ALL) {
- std::lock_guard<std::recursive_mutex> lock(uipc_main.mutex);
- uipc_close_locked(ch_id);
+ std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
+ uipc_close_locked(uipc, ch_id);
return;
}
+
BTIF_TRACE_DEBUG("UIPC_Close : waiting for shutdown to complete");
- uipc_stop_main_server_thread();
+ uipc_stop_main_server_thread(uipc);
BTIF_TRACE_DEBUG("UIPC_Close : shutdown complete");
}
@@ -624,14 +592,15 @@
** Returns true in case of success, false in case of failure.
**
******************************************************************************/
-bool UIPC_Send(tUIPC_CH_ID ch_id, UNUSED_ATTR uint16_t msg_evt,
- const uint8_t* p_buf, uint16_t msglen) {
+bool UIPC_Send(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
+ UNUSED_ATTR uint16_t msg_evt, const uint8_t* p_buf,
+ uint16_t msglen) {
BTIF_TRACE_DEBUG("UIPC_Send : ch_id:%d %d bytes", ch_id, msglen);
- std::lock_guard<std::recursive_mutex> lock(uipc_main.mutex);
+ std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
ssize_t ret;
- OSI_NO_INTR(ret = write(uipc_main.ch[ch_id].fd, p_buf, msglen));
+ OSI_NO_INTR(ret = write(uipc.ch[ch_id].fd, p_buf, msglen));
if (ret < 0) {
BTIF_TRACE_ERROR("failed to write (%s)", strerror(errno));
}
@@ -649,10 +618,11 @@
**
******************************************************************************/
-uint32_t UIPC_Read(tUIPC_CH_ID ch_id, UNUSED_ATTR uint16_t* p_msg_evt,
- uint8_t* p_buf, uint32_t len) {
+uint32_t UIPC_Read(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
+ UNUSED_ATTR uint16_t* p_msg_evt, uint8_t* p_buf,
+ uint32_t len) {
int n_read = 0;
- int fd = uipc_main.ch[ch_id].fd;
+ int fd = uipc.ch[ch_id].fd;
struct pollfd pfd;
if (ch_id >= UIPC_CH_NUM) {
@@ -673,10 +643,10 @@
a read for more than poll timeout */
int poll_ret;
- OSI_NO_INTR(poll_ret = poll(&pfd, 1, uipc_main.ch[ch_id].read_poll_tmo_ms));
+ OSI_NO_INTR(poll_ret = poll(&pfd, 1, uipc.ch[ch_id].read_poll_tmo_ms));
if (poll_ret == 0) {
BTIF_TRACE_WARNING("poll timeout (%d ms)",
- uipc_main.ch[ch_id].read_poll_tmo_ms);
+ uipc.ch[ch_id].read_poll_tmo_ms);
break;
}
if (poll_ret < 0) {
@@ -689,8 +659,8 @@
if (pfd.revents & (POLLHUP | POLLNVAL)) {
BTIF_TRACE_WARNING("poll : channel detached remotely");
- std::lock_guard<std::recursive_mutex> lock(uipc_main.mutex);
- uipc_close_locked(ch_id);
+ std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
+ uipc_close_locked(uipc, ch_id);
return 0;
}
@@ -701,8 +671,8 @@
if (n == 0) {
BTIF_TRACE_WARNING("UIPC_Read : channel detached remotely");
- std::lock_guard<std::recursive_mutex> lock(uipc_main.mutex);
- uipc_close_locked(ch_id);
+ std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
+ uipc_close_locked(uipc, ch_id);
return 0;
}
@@ -727,37 +697,38 @@
*
******************************************************************************/
-extern bool UIPC_Ioctl(tUIPC_CH_ID ch_id, uint32_t request, void* param) {
+extern bool UIPC_Ioctl(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, uint32_t request,
+ void* param) {
BTIF_TRACE_DEBUG("#### UIPC_Ioctl : ch_id %d, request %d ####", ch_id,
request);
- std::lock_guard<std::recursive_mutex> lock(uipc_main.mutex);
+ std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
switch (request) {
case UIPC_REQ_RX_FLUSH:
- uipc_flush_locked(ch_id);
+ uipc_flush_locked(uipc, ch_id);
break;
case UIPC_REG_CBACK:
// BTIF_TRACE_EVENT("register callback ch %d srvfd %d, fd %d", ch_id,
- // uipc_main.ch[ch_id].srvfd, uipc_main.ch[ch_id].fd);
- uipc_main.ch[ch_id].cback = (tUIPC_RCV_CBACK*)param;
+ // uipc.ch[ch_id].srvfd, uipc.ch[ch_id].fd);
+ uipc.ch[ch_id].cback = (tUIPC_RCV_CBACK*)param;
break;
case UIPC_REG_REMOVE_ACTIVE_READSET:
/* user will read data directly and not use select loop */
- if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED) {
+ if (uipc.ch[ch_id].fd != UIPC_DISCONNECTED) {
/* remove this channel from active set */
- FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
+ FD_CLR(uipc.ch[ch_id].fd, &uipc.active_set);
/* refresh active set */
- uipc_wakeup_locked();
+ uipc_wakeup_locked(uipc);
}
break;
case UIPC_SET_READ_POLL_TMO:
- uipc_main.ch[ch_id].read_poll_tmo_ms = (intptr_t)param;
+ uipc.ch[ch_id].read_poll_tmo_ms = (intptr_t)param;
BTIF_TRACE_EVENT("UIPC_SET_READ_POLL_TMO : CH %d, TMO %d ms", ch_id,
- uipc_main.ch[ch_id].read_poll_tmo_ms);
+ uipc.ch[ch_id].read_poll_tmo_ms);
break;
default:
diff --git a/utils/BUILD.gn b/utils/BUILD.gn
index 13d57a1..c6e7dab 100644
--- a/utils/BUILD.gn
+++ b/utils/BUILD.gn
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2015 Google, Inc.
+# Copyright 2015 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/utils/include/bt_utils.h b/utils/include/bt_utils.h
index 2b1a7b1..821e51c 100644
--- a/utils/include/bt_utils.h
+++ b/utils/include/bt_utils.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2009-2012 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/utils/src/bt_utils.cc b/utils/src/bt_utils.cc
index 65bd7af..6d93ac4 100644
--- a/utils/src/bt_utils.cc
+++ b/utils/src/bt_utils.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2012 Broadcom Corporation
+ * Copyright 2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/vendor_libs/Android.mk b/vendor_libs/Android.mk
deleted file mode 100644
index 31d6e6b..0000000
--- a/vendor_libs/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Common C/C++ compiler flags for test-vendor lib
-#
-# -Wno-gnu-variable-sized-type-not-at-end is needed, because struct BT_HDR
-# is defined as a variable-size header in a struct.
-# -Wno-typedef-redefinition is needed because of the way the struct typedef
-# is done in osi/include header files. This issue can be obsoleted by
-# switching to C11 or C++.
-# -Wno-unused-parameter is needed, because there are too many unused
-# parameters in all the code.
-#
-test-vendor_CFLAGS += \
- -fvisibility=hidden \
- -Wall \
- -Wextra \
- -Werror \
- -Wno-gnu-variable-sized-type-not-at-end \
- -Wno-typedef-redefinition \
- -Wno-unused-parameter \
- -DLOG_NDEBUG=1 \
- -DEXPORT_SYMBOL="__attribute__((visibility(\"default\")))"
-
-test-vendor_CONLYFLAGS += -std=c99
-
-include $(call all-subdir-makefiles)
-
-# Cleanup our locals
-test-vendor_CFLAGS :=
-test-vendor_CONLYFLAGS :=
diff --git a/vendor_libs/linux/interface/Android.bp b/vendor_libs/linux/interface/Android.bp
index 56baf9e..8d6caa4 100644
--- a/vendor_libs/linux/interface/Android.bp
+++ b/vendor_libs/linux/interface/Android.bp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2017 The Android Open Source Project
+// Copyright 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -24,11 +24,12 @@
"async_fd_watcher.cc",
"service.cc"
],
+ cflags: ["-Wall", "-Werror"],
+ header_libs: ["libbluetooth_headers"],
shared_libs: [
"android.hardware.bluetooth@1.0",
"libbase",
"libcutils",
- "libhardware",
"libhidlbase",
"libhidltransport",
"liblog",
diff --git a/vendor_libs/linux/sepolicy/hal_bluetooth_btlinux.te b/vendor_libs/linux/sepolicy/hal_bluetooth_btlinux.te
index 32349b9..22d9cf0 100644
--- a/vendor_libs/linux/sepolicy/hal_bluetooth_btlinux.te
+++ b/vendor_libs/linux/sepolicy/hal_bluetooth_btlinux.te
@@ -1,5 +1,5 @@
type hal_bluetooth_btlinux, domain;
-type hal_bluetooth_btlinux_exec, exec_type, file_type;
+type hal_bluetooth_btlinux_exec, exec_type, file_type, vendor_file_type;
hal_server_domain(hal_bluetooth_btlinux, hal_bluetooth)
init_daemon_domain(hal_bluetooth_btlinux)
diff --git a/vendor_libs/test_vendor_lib/Android.bp b/vendor_libs/test_vendor_lib/Android.bp
index 18498ed..ef927f4 100644
--- a/vendor_libs/test_vendor_lib/Android.bp
+++ b/vendor_libs/test_vendor_lib/Android.bp
@@ -2,22 +2,34 @@
// ========================================================
cc_library_static {
name: "libbt-rootcanal",
+ defaults: ["libchrome_support_defaults"],
proprietary: true,
srcs: [
+ "src/acl_packet.cc",
"src/async_manager.cc",
+ "src/beacon.cc",
+ "src/beacon_swarm.cc",
+ "src/broken_adv.cc",
"src/bt_address.cc",
+ "src/classic.cc",
"src/command_packet.cc",
+ "src/connection.cc",
+ "src/device.cc",
+ "src/device_factory.cc",
+ "src/device_properties.cc",
"src/dual_mode_controller.cc",
"src/event_packet.cc",
+ "src/hci_packet.cc",
+ "src/keyboard.cc",
+ "src/l2cap_packet.cc",
+ "src/l2cap_sdu.cc",
"src/packet.cc",
"src/packet_stream.cc",
+ "src/sco_packet.cc",
"src/test_channel_transport.cc",
],
cflags: [
"-fvisibility=hidden",
- "-Wall",
- "-Wextra",
- "-Werror",
"-DHAS_NO_BDROID_BUILDCFG",
],
local_include_dirs: [
@@ -25,18 +37,17 @@
],
export_include_dirs: ["include"],
header_libs: [
- "libhardware_headers",
+ "libbluetooth_headers",
],
include_dirs: [
"system/bt",
"system/bt/utils/include",
"system/bt/hci/include",
- "system/bt/include",
+ "system/bt/internal_include",
"system/bt/stack/include",
],
shared_libs: [
"libbase",
- "libchrome",
"liblog",
],
static_libs: [
@@ -48,9 +59,11 @@
// ========================================================
cc_test_host {
name: "test-vendor_test_host",
+ defaults: ["libchrome_support_defaults"],
srcs: [
"src/async_manager.cc",
"src/bt_address.cc",
+ "src/hci_packet.cc",
"src/command_packet.cc",
"src/event_packet.cc",
"src/packet.cc",
@@ -60,9 +73,13 @@
"test/async_manager_unittest.cc",
"test/bt_address_unittest.cc",
"test/packet_stream_unittest.cc",
+ "test/iterator_test.cc",
"test/l2cap_test.cc",
"test/l2cap_sdu_test.cc",
],
+ header_libs: [
+ "libbluetooth_headers",
+ ],
local_include_dirs: [
"include",
],
@@ -74,21 +91,12 @@
],
shared_libs: [
"liblog",
- "libchrome",
],
static_libs: [
"libbluetooth-types",
],
cflags: [
"-fvisibility=hidden",
- "-Wall",
- "-Wextra",
- "-Werror",
"-DLOG_NDEBUG=1",
],
- target: {
- darwin: {
- enabled: false,
- }
- },
}
diff --git a/vendor_libs/test_vendor_lib/include/acl_packet.h b/vendor_libs/test_vendor_lib/include/acl_packet.h
new file mode 100644
index 0000000..30f3389
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/acl_packet.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace test_vendor_lib {
+
+// ACL data packets are specified in the Bluetooth Core Specification Version
+// 4.2, Volume 2, Part E, Section 5.4.2
+class AclPacket {
+ public:
+ typedef enum {
+ FirstNonAutomaticallyFlushable,
+ Continuing,
+ FirstAutomaticallyFlushable,
+ Complete
+ } PacketBoundaryFlags;
+ typedef enum {
+ PointToPoint,
+ ActiveSlaveBroadcast,
+ ParkedSlaveBroadcast,
+ Reserved
+ } BroadcastFlags;
+
+ virtual ~AclPacket() = default;
+
+ uint16_t GetChannel() const {
+ return (raw_packet_[0] | (raw_packet_[1] << 8)) & 0xfff;
+ }
+
+ PacketBoundaryFlags GetPacketBoundaryFlags() const {
+ return static_cast<PacketBoundaryFlags>((raw_packet_[1] & 0x30) >> 4);
+ }
+
+ BroadcastFlags GetBroadcastFlags() const {
+ return static_cast<BroadcastFlags>((raw_packet_[1] & 0xC0) >> 6);
+ }
+
+ explicit AclPacket(uint16_t channel,
+ AclPacket::PacketBoundaryFlags boundary_flags,
+ AclPacket::BroadcastFlags broadcast);
+
+ size_t GetPacketSize() const;
+
+ const std::vector<uint8_t>& GetPacket() const;
+
+ void AddPayloadOctets(size_t octets, const std::vector<uint8_t>& bytes);
+
+ private:
+ // Add |octets| bytes to the payload.
+ void AddPayloadOctets(size_t octets, uint64_t value);
+
+ static const size_t kHeaderSize = 4;
+
+ public:
+ // Add type-checking versions
+ void AddPayloadOctets1(uint8_t value) { AddPayloadOctets(1, value); }
+ void AddPayloadOctets2(uint16_t value) { AddPayloadOctets(2, value); }
+ void AddPayloadOctets3(uint32_t value) { AddPayloadOctets(3, value); }
+ void AddPayloadOctets4(uint32_t value) { AddPayloadOctets(4, value); }
+ void AddPayloadOctets6(uint64_t value) { AddPayloadOctets(6, value); }
+ void AddPayloadOctets8(uint64_t value) { AddPayloadOctets(8, value); }
+
+ private:
+ std::vector<uint8_t> raw_packet_;
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/async_manager.h b/vendor_libs/test_vendor_lib/include/async_manager.h
index 6eaddcd..1e94edf 100644
--- a/vendor_libs/test_vendor_lib/include/async_manager.h
+++ b/vendor_libs/test_vendor_lib/include/async_manager.h
@@ -109,5 +109,5 @@
std::mutex synchronization_mutex_;
};
-}
+} // namespace test_vendor_lib
#endif // TEST_VENDOR_LIB_ASYNC_MANAGER_H_
diff --git a/vendor_libs/test_vendor_lib/include/beacon.h b/vendor_libs/test_vendor_lib/include/beacon.h
new file mode 100644
index 0000000..8943b96
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/beacon.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "bt_address.h"
+#include "device.h"
+#include "stack/include/btm_ble_api.h"
+
+namespace test_vendor_lib {
+
+// A simple device that advertises periodically and is not connectable.
+class Beacon : public Device {
+ public:
+ Beacon();
+ virtual ~Beacon() = default;
+
+ // Return a string representation of the type of device.
+ virtual std::string GetTypeString() const override { return "beacon"; }
+
+ // Set the address and advertising interval from string args.
+ virtual void Initialize(const std::vector<std::string>& args) override;
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/beacon_swarm.h b/vendor_libs/test_vendor_lib/include/beacon_swarm.h
new file mode 100644
index 0000000..e07ae55
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/beacon_swarm.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "bt_address.h"
+#include "device.h"
+#include "stack/include/btm_ble_api.h"
+
+namespace test_vendor_lib {
+
+// Pretend to be a lot of beacons by changing the advertising address.
+class BeaconSwarm : public Device {
+ public:
+ BeaconSwarm();
+ virtual ~BeaconSwarm() = default;
+
+ // Set the address and advertising interval from string args.
+ virtual void Initialize(const std::vector<std::string>& args) override;
+
+ // Return a string representation of the type of device.
+ virtual std::string GetTypeString() const override { return "beacon_swarm"; }
+
+ void TimerTick() override;
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/broken_adv.h b/vendor_libs/test_vendor_lib/include/broken_adv.h
new file mode 100644
index 0000000..9f7cd87
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/broken_adv.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "bt_address.h"
+#include "device.h"
+
+namespace test_vendor_lib {
+
+class BrokenAdv : public Device {
+ public:
+ BrokenAdv();
+ ~BrokenAdv() = default;
+
+ // Initialize the device based on the values of |args|.
+ virtual void Initialize(const std::vector<std::string>& args) override;
+
+ // Return a string representation of the type of device.
+ virtual std::string GetTypeString() const override { return "broken_adv"; }
+
+ // Return the string representation of the device.
+ virtual std::string ToString() const override;
+
+ // Use the timer tick to update advertisements.
+ void TimerTick() override;
+
+ // Change which advertisements are broken and the address of the device.
+ void UpdateAdvertisement();
+
+ // Change which data is broken and the address of the device.
+ void UpdatePageScan();
+
+ private:
+ std::vector<uint8_t> constant_adv_data_;
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/bt_address.h b/vendor_libs/test_vendor_lib/include/bt_address.h
index c37624f..d656c34 100644
--- a/vendor_libs/test_vendor_lib/include/bt_address.h
+++ b/vendor_libs/test_vendor_lib/include/bt_address.h
@@ -1,18 +1,18 @@
-//
-// Copyright 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#pragma once
@@ -41,22 +41,22 @@
// - each remaining character is a hexadecimal digit
static bool IsValid(const std::string& addr);
- inline bool operator==(const BtAddress& right) {
+ inline bool operator==(const BtAddress& right) const {
return address_ == right.address_;
}
- inline bool operator!=(const BtAddress& right) {
+ inline bool operator!=(const BtAddress& right) const {
return address_ != right.address_;
}
- inline bool operator<(const BtAddress& right) {
+ inline bool operator<(const BtAddress& right) const {
return address_ < right.address_;
}
- inline bool operator>(const BtAddress& right) {
+ inline bool operator>(const BtAddress& right) const {
return address_ > right.address_;
}
- inline bool operator<=(const BtAddress& right) {
+ inline bool operator<=(const BtAddress& right) const {
return address_ <= right.address_;
}
- inline bool operator>=(const BtAddress& right) {
+ inline bool operator>=(const BtAddress& right) const {
return address_ >= right.address_;
}
diff --git a/vendor_libs/test_vendor_lib/include/classic.h b/vendor_libs/test_vendor_lib/include/classic.h
new file mode 100644
index 0000000..0aeba2f
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/classic.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "bt_address.h"
+#include "device.h"
+
+namespace test_vendor_lib {
+
+class Classic : public Device {
+ public:
+ Classic();
+ ~Classic() = default;
+
+ // Initialize the device based on the values of |args|.
+ virtual void Initialize(const std::vector<std::string>& args) override;
+
+ // Return a string representation of the type of device.
+ virtual std::string GetTypeString() const override { return "classic"; }
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/command_packet.h b/vendor_libs/test_vendor_lib/include/command_packet.h
index 3f7debb..36ab8d2 100644
--- a/vendor_libs/test_vendor_lib/include/command_packet.h
+++ b/vendor_libs/test_vendor_lib/include/command_packet.h
@@ -1,18 +1,18 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#pragma once
diff --git a/vendor_libs/test_vendor_lib/include/connection.h b/vendor_libs/test_vendor_lib/include/connection.h
new file mode 100644
index 0000000..2a4f662
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/connection.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "async_manager.h"
+#include "device.h"
+
+#include "hci/include/hci_hal.h"
+
+namespace test_vendor_lib {
+
+// Model the connection of a device to the controller.
+class Connection {
+ public:
+ Connection(std::shared_ptr<Device> dev, uint16_t handle)
+ : dev_(dev), handle_(handle), connected_(true), encrypted_(false) {}
+
+ virtual ~Connection() = default;
+
+ // Return a string representing the connection for logging.
+ const std::string ToString();
+
+ // Return a pointer to the device in the connection.
+ std::shared_ptr<Device> GetDevice() { return dev_; }
+
+ // Return true if the handle matches and the device is connected.
+ inline bool operator==(uint16_t handle) {
+ return (handle_ == handle) && connected_;
+ }
+
+ // Return true if the handle doesn't match or the device is not connected.
+ inline bool operator!=(uint16_t handle) {
+ return (handle_ != handle) || !connected_;
+ }
+
+ void Disconnect() { connected_ = false; };
+ bool Connected() { return connected_; };
+
+ void Encrypt() { encrypted_ = true; };
+ bool Encrypted() { return encrypted_; };
+
+ // Add an action to the connection queue.
+ void AddAction(const TaskCallback& task);
+
+ // Execute the next action in the connection queue to simulate packet
+ // exchange.
+ void SendToDevice();
+
+ // Add a message from the device.
+ void AddMessage(const std::vector<uint8_t>& message);
+
+ // Receive data from the device to simulate packet exchange.
+ bool ReceiveFromDevice(std::vector<uint8_t>& data);
+
+ private:
+ // A shared pointer to the connected device
+ std::shared_ptr<Device> dev_;
+
+ // The connection handle
+ uint16_t handle_;
+
+ // State variables
+ bool connected_;
+ bool encrypted_;
+
+ // Actions for the next packet exchange.
+ std::queue<TaskCallback> actions_;
+
+ // Messages from the device for the next packet exchange.
+ std::queue<std::vector<uint8_t>> messages_;
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/device.h b/vendor_libs/test_vendor_lib/include/device.h
new file mode 100644
index 0000000..e2924c4
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/device.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "bt_address.h"
+
+#include "hci/include/hci_hal.h"
+#include "stack/include/btm_ble_api.h"
+
+namespace test_vendor_lib {
+
+// Represent a Bluetooth Device
+// - Provide Get*() and Set*() functions for device attributes.
+class Device {
+ public:
+ Device() : time_stamp_(std::chrono::steady_clock::now()) {}
+ virtual ~Device() = default;
+
+ // Initialize the device based on the values of |args|.
+ virtual void Initialize(const std::vector<std::string>& args) = 0;
+
+ // Return a string representation of the type of device.
+ virtual std::string GetTypeString() const = 0;
+
+ // Return the string representation of the device.
+ virtual std::string ToString() const;
+
+ // Return a reference to the address.
+ const BtAddress& GetBtAddress() const { return address_; }
+
+ // Set the address to the |addr|.
+ void SetBtAddress(const BtAddress& addr) { address_ = addr; }
+
+ // Return the address type.
+ uint8_t GetAddressType() const { return address_type_; }
+
+ // Decide whether to accept a connection request
+ // May need to be extended to check peer address & type, and other
+ // connection parameters.
+ // Return true if the device accepts the connection request.
+ virtual bool LeConnect() { return false; }
+
+ // Return the advertisement data.
+ const std::vector<uint8_t>& GetAdvertisement() const { return adv_data_; }
+
+ // Return the advertisement type.
+ uint8_t GetAdvertisementType() const { return advertising_type_; }
+
+ // Set the advertisement interval in milliseconds.
+ void SetAdvertisementInterval(std::chrono::milliseconds ms) {
+ advertising_interval_ms_ = ms;
+ }
+
+ // Return true if there is a scan response (allows for empty responses).
+ bool HasScanResponse() const { return scan_response_present_; }
+
+ // Return the scan response data.
+ const std::vector<uint8_t>& GetScanResponse() const { return scan_data_; }
+
+ // Returns true if the host could see an advertisement in the next
+ // |scan_time| milliseconds.
+ virtual bool IsAdvertisementAvailable(
+ std::chrono::milliseconds scan_time) const;
+
+ // Returns true if the host could see a page scan now.
+ virtual bool IsPageScanAvailable() const;
+
+ // Return the device class.
+ // The device class is a 3-byte value. Look for DEV_CLASS in
+ // stack/include/bt_types.h
+ uint32_t GetDeviceClass() const { return device_class_; }
+
+ // Return the clock offset, which is a defined in the Spec as:
+ // (CLKN_16-2 slave - CLKN_16-2 master ) mod 2**15.
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part C, Section 4.3.2
+ uint16_t GetClockOffset() const { return clock_offset_; }
+
+ // Set the clock offset.
+ void SetClockOffset(uint16_t offset) { clock_offset_ = offset; }
+
+ // Return the page scan repetition mode.
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part B, Section 8.3.1
+ // The values are:
+ // 0 - R0 T_page_scan <= 1.28s and T_page_scan == T_window and
+ // 1 - R1 T_page_scan <= 1.28s
+ // 2 - R2 T_page_scan <= 2.56s
+ uint8_t GetPageScanRepetitionMode() const {
+ return page_scan_repetition_mode_;
+ }
+
+ // Return the extended inquiry data.
+ const std::vector<uint8_t>& GetExtendedInquiryData() const {
+ return extended_inquiry_data_;
+ }
+
+ // Let the device know that time has passed.
+ virtual void TimerTick() {}
+
+ protected:
+ BtAddress address_;
+
+ // Address type is defined in the spec:
+ // 0x00 Public Device Address
+ // 0x01 Random Device Address
+ // 0x02 Public Identity Address
+ // 0x03 Random (static) Identity Address
+ // 0x04 – 0xFF Reserved for future use
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.12
+ uint8_t address_type_;
+
+ std::chrono::steady_clock::time_point time_stamp_;
+
+ // Return the device class.
+ // The device class is a 3-byte value. Look for DEV_CLASS in
+ // stack/include/bt_types.h
+ uint32_t device_class_;
+
+ // Return the page scan repetition mode.
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part B, Section 8.3.1
+ // The values are:
+ // 0 - R0 T_page_scan <= 1.28s and T_page_scan == T_window and
+ // 1 - R1 T_page_scan <= 1.28s
+ // 2 - R2 T_page_scan <= 2.56s
+ uint8_t page_scan_repetition_mode_;
+
+ // The time between page scans.
+ std::chrono::milliseconds page_scan_delay_ms_;
+
+ std::vector<uint8_t> extended_inquiry_data_;
+
+ // Classic Bluetooth CLKN_slave[16..2] - CLKN_master[16..2]
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part C, Section 4.3.2
+ uint16_t clock_offset_;
+
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.5
+ uint8_t advertising_type_;
+
+ // The spec defines the advertising interval as a 16-bit value, but since it
+ // is never sent in packets, we use std::chrono::milliseconds.
+ std::chrono::milliseconds advertising_interval_ms_;
+
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.7
+
+ // Bluetooth Core Specification Version 4.2, Volume 3, Part C, Section
+ // 11.1
+ // https://www.bluetooth.com/specifications/assigned-numbers
+ // Supplement to Bluetooth Core Specification | CSSv6, Part A
+ std::vector<uint8_t> adv_data_ = {0x07, // Length
+ BTM_BLE_AD_TYPE_NAME_CMPL,
+ 'd',
+ 'e',
+ 'v',
+ 'i',
+ 'c',
+ 'e'};
+
+ bool scan_response_present_ = true;
+ std::vector<uint8_t> scan_data_ = {0x04, // Length
+ BTM_BLE_AD_TYPE_NAME_SHORT, 'd', 'e', 'v'};
+
+ public:
+ static const uint8_t kBtAddressTypePublic = 0x00;
+ static const uint8_t kBtAddressTypeRandom = 0x01;
+ static const uint8_t kBtAddressTypePublicIdentity = 0x02;
+ static const uint8_t kBtAddressTypeRandomIdentity = 0x03;
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/device_factory.h b/vendor_libs/test_vendor_lib/include/device_factory.h
new file mode 100644
index 0000000..a66a2e0
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/device_factory.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "device.h"
+
+namespace test_vendor_lib {
+
+// Encapsulate the details of supported devices to hide them from the
+// Controller.
+class DeviceFactory {
+ public:
+ DeviceFactory();
+ virtual ~DeviceFactory() = default;
+
+ // Call the constructor for the matching device type (arg[0]) and then call
+ // the matching Initialize() function with args.
+ static std::shared_ptr<Device> Create(const std::vector<std::string>& args);
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/device_properties.h b/vendor_libs/test_vendor_lib/include/device_properties.h
new file mode 100644
index 0000000..98876d5
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/device_properties.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "acl_packet.h"
+#include "async_manager.h"
+#include "base/json/json_value_converter.h"
+#include "base/time/time.h"
+#include "bt_address.h"
+
+namespace test_vendor_lib {
+
+// Emulates a dual mode BR/EDR + LE controller by maintaining the link layer
+// state machine detailed in the Bluetooth Core Specification Version 4.2,
+// Volume 6, Part B, Section 1.1 (page 30). Provides methods corresponding to
+// commands sent by the HCI. These methods will be registered as callbacks from
+// a controller instance with the HciHandler. To implement a new Bluetooth
+// command, simply add the method declaration below, with return type void and a
+// single const std::vector<uint8_t>& argument. After implementing the
+// method, simply register it with the HciHandler using the SET_HANDLER macro in
+// the controller's default constructor. Be sure to name your method after the
+// corresponding Bluetooth command in the Core Specification with the prefix
+// "Hci" to distinguish it as a controller command.
+class DeviceProperties {
+ public:
+ explicit DeviceProperties(const std::string& file_name);
+
+ // Access private configuration data
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.4.1
+ const std::vector<uint8_t>& GetLocalVersionInformation() const;
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.4.2
+ const std::vector<uint8_t>& GetLocalSupportedCommands() const {
+ return local_supported_commands_;
+ }
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.4.3
+ uint64_t GetLocalSupportedFeatures() const {
+ return local_extended_features_[0];
+ };
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.4.4
+ uint8_t GetLocalExtendedFeaturesMaximumPageNumber() const {
+ return local_extended_features_.size() - 1;
+ };
+
+ uint64_t GetLocalExtendedFeatures(uint8_t page_number) const {
+ CHECK(page_number < local_extended_features_.size());
+ return local_extended_features_[page_number];
+ };
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.4.5
+ uint16_t GetAclDataPacketSize() const { return acl_data_packet_size_; }
+
+ uint8_t GetSynchronousDataPacketSize() const { return sco_data_packet_size_; }
+
+ uint16_t GetTotalNumAclDataPackets() const { return num_acl_data_packets_; }
+
+ uint16_t GetTotalNumSynchronousDataPackets() const {
+ return num_sco_data_packets_;
+ }
+
+ const BtAddress& GetAddress() const { return address_; }
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.4.8
+ const std::vector<uint8_t>& GetSupportedCodecs() const {
+ return supported_codecs_;
+ }
+
+ const std::vector<uint32_t>& GetVendorSpecificCodecs() const {
+ return vendor_specific_codecs_;
+ }
+
+ const std::string& GetLocalName() const { return local_name_; }
+
+ uint8_t GetVersion() const { return version_; }
+
+ uint16_t GetRevision() const { return revision_; }
+
+ uint8_t GetLmpPalVersion() const { return lmp_pal_version_; }
+
+ uint16_t GetLmpPalSubversion() const { return lmp_pal_subversion_; }
+
+ uint16_t GetManufacturerName() const { return manufacturer_name_; }
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.8.2
+ uint16_t GetLeDataPacketLength() const { return le_data_packet_length_; }
+
+ uint8_t GetTotalNumLeDataPackets() const { return num_le_data_packets_; }
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.8.3
+ uint64_t GetLeLocalSupportedFeatures() const {
+ return le_supported_features_;
+ }
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.8.14
+ uint8_t GetLeWhiteListSize() const { return le_white_list_size_; }
+
+ // Specification Version 4.2, Volume 2, Part E, Section 7.8.27
+ uint64_t GetLeSupportedStates() const { return le_supported_states_; }
+
+ // Vendor-specific commands (see hcidefs.h)
+ const std::vector<uint8_t>& GetLeVendorCap() const { return le_vendor_cap_; }
+
+ static void RegisterJSONConverter(
+ base::JSONValueConverter<DeviceProperties>* converter);
+
+ private:
+ uint16_t acl_data_packet_size_;
+ uint8_t sco_data_packet_size_;
+ uint16_t num_acl_data_packets_;
+ uint16_t num_sco_data_packets_;
+ uint8_t version_;
+ uint16_t revision_;
+ uint8_t lmp_pal_version_;
+ uint16_t manufacturer_name_;
+ uint16_t lmp_pal_subversion_;
+ std::vector<uint8_t> supported_codecs_;
+ std::vector<uint32_t> vendor_specific_codecs_;
+ std::vector<uint8_t> local_supported_commands_;
+ std::string local_name_;
+ std::vector<uint64_t> local_extended_features_;
+ BtAddress address_;
+
+ uint16_t le_data_packet_length_;
+ uint8_t num_le_data_packets_;
+ uint8_t le_white_list_size_;
+ uint64_t le_supported_features_;
+ uint64_t le_supported_states_;
+ std::vector<uint8_t> le_vendor_cap_;
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/dual_mode_controller.h b/vendor_libs/test_vendor_lib/include/dual_mode_controller.h
index bf861b7..4f7041c 100644
--- a/vendor_libs/test_vendor_lib/include/dual_mode_controller.h
+++ b/vendor_libs/test_vendor_lib/include/dual_mode_controller.h
@@ -1,18 +1,18 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#pragma once
@@ -22,12 +22,16 @@
#include <unordered_map>
#include <vector>
+#include "acl_packet.h"
#include "async_manager.h"
-#include "base/json/json_value_converter.h"
#include "base/time/time.h"
#include "bt_address.h"
#include "command_packet.h"
+#include "connection.h"
+#include "device.h"
+#include "device_properties.h"
#include "event_packet.h"
+#include "sco_packet.h"
#include "test_channel_transport.h"
namespace test_vendor_lib {
@@ -45,129 +49,15 @@
// "Hci" to distinguish it as a controller command.
class DualModeController {
public:
- class Properties {
- public:
- explicit Properties(const std::string& file_name);
-
- // Access private configuration data
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.4.1
- const std::vector<uint8_t>& GetLocalVersionInformation() const;
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.4.2
- const std::vector<uint8_t>& GetLocalSupportedCommands() const {
- return local_supported_commands_;
- }
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.4.3
- uint64_t GetLocalSupportedFeatures() const {
- return local_extended_features_[0];
- };
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.4.4
- uint8_t GetLocalExtendedFeaturesMaximumPageNumber() const {
- return local_extended_features_.size() - 1;
- };
-
- uint64_t GetLocalExtendedFeatures(uint8_t page_number) const {
- CHECK(page_number < local_extended_features_.size());
- return local_extended_features_[page_number];
- };
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.4.5
- uint16_t GetAclDataPacketSize() const { return acl_data_packet_size_; }
-
- uint8_t GetSynchronousDataPacketSize() const {
- return sco_data_packet_size_;
- }
-
- uint16_t GetTotalNumAclDataPackets() const { return num_acl_data_packets_; }
-
- uint16_t GetTotalNumSynchronousDataPackets() const {
- return num_sco_data_packets_;
- }
-
- const BtAddress& GetAddress() const { return address_; }
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.4.8
- const std::vector<uint8_t>& GetSupportedCodecs() const {
- return supported_codecs_;
- }
-
- const std::vector<uint32_t>& GetVendorSpecificCodecs() const {
- return vendor_specific_codecs_;
- }
-
- const std::string& GetLocalName() const { return local_name_; }
-
- uint8_t GetVersion() const { return version_; }
-
- uint16_t GetRevision() const { return revision_; }
-
- uint8_t GetLmpPalVersion() const { return lmp_pal_version_; }
-
- uint16_t GetLmpPalSubversion() const { return lmp_pal_subversion_; }
-
- uint16_t GetManufacturerName() const { return manufacturer_name_; }
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.8.2
- uint16_t GetLeDataPacketLength() const { return le_data_packet_length_; }
-
- uint8_t GetTotalNumLeDataPackets() const { return num_le_data_packets_; }
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.8.3
- uint64_t GetLeLocalSupportedFeatures() const {
- return le_supported_features_;
- }
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.8.14
- uint8_t GetLeWhiteListSize() const { return le_white_list_size_; }
-
- // Specification Version 4.2, Volume 2, Part E, Section 7.8.27
- uint64_t GetLeSupportedStates() const { return le_supported_states_; }
-
- // Vendor-specific commands (see hcidefs.h)
- const std::vector<uint8_t>& GetLeVendorCap() const {
- return le_vendor_cap_;
- }
-
- static void RegisterJSONConverter(
- base::JSONValueConverter<Properties>* converter);
-
- private:
- uint16_t acl_data_packet_size_;
- uint8_t sco_data_packet_size_;
- uint16_t num_acl_data_packets_;
- uint16_t num_sco_data_packets_;
- uint8_t version_;
- uint16_t revision_;
- uint8_t lmp_pal_version_;
- uint16_t manufacturer_name_;
- uint16_t lmp_pal_subversion_;
- std::vector<uint8_t> supported_codecs_;
- std::vector<uint32_t> vendor_specific_codecs_;
- std::vector<uint8_t> local_supported_commands_;
- std::string local_name_;
- std::vector<uint64_t> local_extended_features_;
- BtAddress address_;
-
- uint16_t le_data_packet_length_;
- uint8_t num_le_data_packets_;
- uint8_t le_white_list_size_;
- uint64_t le_supported_features_;
- uint64_t le_supported_states_;
- std::vector<uint8_t> le_vendor_cap_;
- };
-
// Sets all of the methods to be used as callbacks in the HciHandler.
DualModeController();
~DualModeController() = default;
- // Preprocesses the command, primarily checking testh channel hooks. If
- // possible, dispatches the corresponding controller method corresponding to
- // carry out the command.
+ // Route commands and data from the stack.
+ void HandleAcl(std::unique_ptr<AclPacket> acl_packet);
void HandleCommand(std::unique_ptr<CommandPacket> command_packet);
+ void HandleSco(std::unique_ptr<ScoPacket> sco_packet);
// Dispatches the test channel action corresponding to the command specified
// by |name|.
@@ -186,10 +76,16 @@
void RegisterTaskCancel(std::function<void(AsyncTaskId)> cancel);
- // Sets the callback to be used for sending events back to the HCI.
+ // Set the callbacks for sending packets to the HCI.
void RegisterEventChannel(
const std::function<void(std::unique_ptr<EventPacket>)>& send_event);
+ void RegisterAclChannel(
+ const std::function<void(std::unique_ptr<AclPacket>)>& send_acl);
+
+ void RegisterScoChannel(
+ const std::function<void(std::unique_ptr<ScoPacket>)>& send_sco);
+
// Controller commands. For error codes, see the Bluetooth Core Specification,
// Version 4.2, Volume 2, Part D (page 370).
@@ -340,6 +236,14 @@
// Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.1.19
void HciRemoteNameRequest(const std::vector<uint8_t>& args);
+ // Test Commands
+
+ // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.7.1
+ void HciReadLoopbackMode(const std::vector<uint8_t>& args);
+
+ // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.7.2
+ void HciWriteLoopbackMode(const std::vector<uint8_t>& args);
+
// LE Controller Commands
// OGF: 0x0008
@@ -383,11 +287,27 @@
void HciLeSetScanEnable(const std::vector<uint8_t>& args);
// OGF: 0x0008
+ // OCF: 0x000D
+ // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.12
+ void HciLeCreateConnection(const std::vector<uint8_t>& args);
+
+ // OGF: 0x0008
+ // OCF: 0x000E
+ // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.13
+ void HciLeConnectionCancel(const std::vector<uint8_t>& args);
+
+ // OGF: 0x0008
// OCF: 0x000F
// Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.14
void HciLeReadWhiteListSize(const std::vector<uint8_t>& args);
// OGF: 0x0008
+ // OCF: 0x0016
+ // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.21
+ void HciLeReadRemoteUsedFeatures(const std::vector<uint8_t>& args);
+ void HciLeReadRemoteUsedFeaturesB(uint16_t handle);
+
+ // OGF: 0x0008
// OCF: 0x0018
// Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.23
void HciLeRand(const std::vector<uint8_t>& args);
@@ -423,26 +343,29 @@
// OCF: 0x0159
void HciBleEnergyInfo(const std::vector<uint8_t>& args);
+ // Test
+ void HciBleAdvertisingFilter(const std::vector<uint8_t>& args);
+
// OGF: 0x00FC
// OCF: 0x015A
void HciBleExtendedScanParams(const std::vector<uint8_t>& args);
// Test Channel commands:
- // Clears all test channel modifications.
- void TestChannelClear(const std::vector<std::string>& args);
+ // Add devices
+ void TestChannelAdd(const std::vector<std::string>& args);
- // Sets the response delay for events to 0.
- void TestChannelClearEventDelay(const std::vector<std::string>& args);
+ // Remove devices by index
+ void TestChannelDel(const std::vector<std::string>& args);
- // Discovers a fake device.
- void TestChannelDiscover(const std::vector<std::string>& args);
+ // List the devices that the controller knows about
+ void TestChannelList(const std::vector<std::string>& args) const;
- // Causes events to be sent after a delay.
- void TestChannelSetEventDelay(const std::vector<std::string>& args);
+ void Connections();
- // Causes all future HCI commands to timeout.
- void TestChannelTimeoutAll(const std::vector<std::string>& args);
+ void LeScan();
+
+ void PageScan();
void HandleTimerTick();
void SetTimerPeriod(std::chrono::milliseconds new_period);
@@ -456,16 +379,12 @@
kInquiry, // The controller is discovering other nearby devices.
};
- enum TestChannelState {
- kNone, // The controller is running normally.
- kTimeoutAll, // All commands should time out, i.e. send no response.
- kDelayedResponse, // Event responses are sent after a delay.
- };
-
// Set a timer for a future action
void AddControllerEvent(std::chrono::milliseconds,
const TaskCallback& callback);
+ void AddConnectionAction(const TaskCallback& callback, uint16_t handle);
+
// Creates a command complete event and sends it back to the HCI.
void SendCommandComplete(uint16_t command_opcode,
const std::vector<uint8_t>& return_parameters) const;
@@ -496,8 +415,10 @@
std::function<void(AsyncTaskId)> cancel_task_;
- // Callback provided to send events from the controller back to the HCI.
+ // Callbacks to send packets back to the HCI.
+ std::function<void(std::unique_ptr<AclPacket>)> send_acl_;
std::function<void(std::unique_ptr<EventPacket>)> send_event_;
+ std::function<void(std::unique_ptr<ScoPacket>)> send_sco_;
// Maintains the commands to be registered and used in the HciHandler object.
// Keys are command opcodes and values are the callbacks to handle each
@@ -517,6 +438,10 @@
// 0x03-0xFF: Reserved.
uint8_t inquiry_mode_;
+ bool inquiry_responses_limited_;
+ uint8_t inquiry_num_responses_;
+ uint8_t inquiry_lap_[3];
+
std::vector<uint8_t> le_event_mask_;
BtAddress le_random_address_;
@@ -530,15 +455,26 @@
uint8_t le_scan_enable_;
uint8_t filter_duplicates_;
+ bool le_connect_;
+ uint8_t initiator_filter_policy_;
+
+ BtAddress peer_address_;
+ uint8_t peer_address_type_;
+
+ uint8_t loopback_mode_;
+
State state_;
- Properties properties_;
+ DeviceProperties properties_;
- TestChannelState test_channel_state_;
+ std::vector<std::shared_ptr<Device>> devices_;
std::vector<AsyncTaskId> controller_events_;
+
+ std::vector<std::shared_ptr<Connection>> connections_;
+
AsyncTaskId timer_tick_task_;
- std::chrono::milliseconds timer_period_ = std::chrono::milliseconds(1000);
+ std::chrono::milliseconds timer_period_ = std::chrono::milliseconds(100);
DualModeController(const DualModeController& cmdPckt) = delete;
DualModeController& operator=(const DualModeController& cmdPckt) = delete;
diff --git a/vendor_libs/test_vendor_lib/include/event_packet.h b/vendor_libs/test_vendor_lib/include/event_packet.h
index d7c8268..f861c07 100644
--- a/vendor_libs/test_vendor_lib/include/event_packet.h
+++ b/vendor_libs/test_vendor_lib/include/event_packet.h
@@ -1,18 +1,18 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#pragma once
@@ -55,6 +55,16 @@
static std::unique_ptr<EventPacket> CreateCommandStatusEvent(
uint8_t status, uint16_t command_opcode);
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.19
+ static std::unique_ptr<EventPacket> CreateNumberOfCompletedPacketsEvent(
+ uint16_t handle, uint16_t num_completed_packets);
+
+ void AddCompletedPackets(uint16_t handle, uint16_t num_completed_packets);
+
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.10
+ static std::unique_ptr<EventPacket> CreateCommandCompleteDeleteStoredLinkKey(
+ uint8_t status, uint16_t num_keys_deleted);
+
// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.12
static std::unique_ptr<EventPacket> CreateCommandCompleteReadLocalName(
uint8_t status, const std::string& local_name);
@@ -96,29 +106,54 @@
uint8_t status, const std::vector<uint8_t>& supported_codecs,
const std::vector<uint32_t>& vendor_specific_codecs);
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.6.1
+ static std::unique_ptr<EventPacket> CreateCommandCompleteReadLoopbackMode(
+ uint8_t status, uint8_t mode);
+
// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.2
- enum PageScanRepetitionMode {
- kR0 = 0,
- kR1 = 1,
- kR2 = 2,
- };
+ static std::unique_ptr<EventPacket> CreateInquiryResultEvent();
- static std::unique_ptr<EventPacket> CreateInquiryResultEvent(
- const BtAddress& bt_address,
- const PageScanRepetitionMode page_scan_repetition_mode,
- uint32_t class_of_device, uint16_t clock_offset);
-
- void AddInquiryResult(const BtAddress& bt_address,
- const PageScanRepetitionMode page_scan_repetition_mode,
+ // Returns true if the result can be added to the event packet.
+ bool AddInquiryResult(const BtAddress& bt_address,
+ uint8_t page_scan_repetition_mode,
uint32_t class_of_device, uint16_t clock_offset);
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.3
+ static std::unique_ptr<EventPacket> CreateConnectionCompleteEvent(
+ uint8_t status, uint16_t handle, const BtAddress& address,
+ uint8_t link_type, bool encryption_enabled);
+
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.25
+ static std::unique_ptr<EventPacket> CreateLoopbackCommandEvent(
+ uint16_t opcode, const std::vector<uint8_t>& payload);
+
// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.38
static std::unique_ptr<EventPacket> CreateExtendedInquiryResultEvent(
- const BtAddress& bt_address,
- const PageScanRepetitionMode page_scan_repetition_mode,
+ const BtAddress& bt_address, uint8_t page_scan_repetition_mode,
uint32_t class_of_device, uint16_t clock_offset, uint8_t rssi,
const std::vector<uint8_t>& extended_inquiry_response);
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+ // 7.7.65.1
+ static std::unique_ptr<EventPacket> CreateLeConnectionCompleteEvent(
+ uint8_t status, uint16_t handle, uint8_t role, uint8_t peer_address_type,
+ const BtAddress& peer, uint16_t interval, uint16_t latency,
+ uint16_t supervision_timeout);
+
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+ // 7.7.65.2
+ static std::unique_ptr<EventPacket> CreateLeAdvertisingReportEvent();
+
+ // Returns true if the report can be added to the event packet.
+ bool AddLeAdvertisingReport(uint8_t event_type, uint8_t addr_type,
+ const BtAddress& addr,
+ const std::vector<uint8_t>& data, uint8_t rssi);
+
+ // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+ // 7.7.65.4
+ static std::unique_ptr<EventPacket> CreateLeRemoteUsedFeaturesEvent(
+ uint8_t status, uint16_t handle, uint64_t features);
+
// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.2
static std::unique_ptr<EventPacket> CreateCommandCompleteLeReadBufferSize(
uint8_t status, uint16_t hc_le_data_packet_length,
diff --git a/vendor_libs/test_vendor_lib/include/hci_packet.h b/vendor_libs/test_vendor_lib/include/hci_packet.h
new file mode 100644
index 0000000..f7be08e
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/hci_packet.h
@@ -0,0 +1,86 @@
+#pragma once
+#include <iterator>
+#include <memory>
+#include <type_traits>
+
+#include "base/logging.h"
+
+namespace test_vendor_lib {
+
+// Iterator is a custom iterator class for HciPackets.
+class Iterator
+ : public std::iterator<std::random_access_iterator_tag, uint8_t> {
+ public:
+ Iterator(std::shared_ptr<class HciPacket> packet, size_t i);
+ Iterator(const Iterator& itr);
+
+ ~Iterator() {}
+
+ operator bool() const;
+
+ // All addition and subtraction operators are bounded from 0 to the length of
+ // the packet.
+ Iterator operator+(size_t offset);
+ Iterator& operator+=(size_t offset);
+ Iterator operator++(int);
+ Iterator& operator++();
+
+ Iterator operator-(size_t offset);
+ int operator-(Iterator& itr);
+ Iterator& operator-=(size_t offset);
+ Iterator operator--(int);
+ Iterator& operator--();
+
+ Iterator& operator=(const Iterator& itr);
+
+ bool operator!=(Iterator& itr);
+ bool operator==(Iterator& itr);
+
+ bool operator<(Iterator& itr);
+ bool operator>(Iterator& itr);
+
+ bool operator<=(Iterator& itr);
+ bool operator>=(Iterator& itr);
+
+ uint8_t& operator*() const;
+ uint8_t* operator->() const;
+
+ // Get the next sizeof(FixedWidthIntegerType) bytes and return the filled type
+ template <typename FixedWidthIntegerType>
+ FixedWidthIntegerType extract() {
+ static_assert(std::is_integral<FixedWidthIntegerType>::value,
+ "Iterator::extract requires an integral type.");
+ FixedWidthIntegerType extracted_value = 0;
+
+ for (size_t i = 0; i < sizeof(FixedWidthIntegerType); i++) {
+ extracted_value |= static_cast<FixedWidthIntegerType>(**this) << i * 8;
+ (*this)++;
+ }
+
+ return extracted_value;
+ }
+
+ private:
+ std::shared_ptr<class HciPacket> hci_packet_;
+ size_t index_;
+
+}; // Iterator
+
+// HciPacket is an abstract class that will serve as the base class for all
+// packet types.
+class HciPacket : public std::enable_shared_from_this<HciPacket> {
+ public:
+ virtual ~HciPacket() = default;
+
+ Iterator get_begin();
+ Iterator get_end();
+
+ uint8_t operator[](size_t i);
+
+ virtual size_t get_length() = 0;
+
+ virtual uint8_t& get_at_index(size_t index) = 0;
+
+}; // HciPacket
+
+}; // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/keyboard.h b/vendor_libs/test_vendor_lib/include/keyboard.h
new file mode 100644
index 0000000..9d1cfbf
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/keyboard.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "bt_address.h"
+#include "device.h"
+
+namespace test_vendor_lib {
+
+class Keyboard : public Device {
+ public:
+ Keyboard();
+ virtual ~Keyboard() = default;
+
+ // Initialize the device based on the values of |args|.
+ virtual void Initialize(const std::vector<std::string>& args) override;
+
+ // Return a string representation of the type of device.
+ virtual std::string GetTypeString() const override;
+
+ virtual bool LeConnect();
+
+ virtual bool IsPageScanAvailable() const override;
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/l2cap_packet.h b/vendor_libs/test_vendor_lib/include/l2cap_packet.h
index 6c95539..1205ee1 100644
--- a/vendor_libs/test_vendor_lib/include/l2cap_packet.h
+++ b/vendor_libs/test_vendor_lib/include/l2cap_packet.h
@@ -1,20 +1,19 @@
-/******************************************************************************
+/*
+ * Copyright 2017 The Android Open Source Project
*
- * Copyright (C) 2017 Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#pragma once
#include <cmath>
@@ -24,29 +23,30 @@
#include <vector>
#include "base/macros.h"
+#include "hci_packet.h"
#include "l2cap_sdu.h"
namespace test_vendor_lib {
const int kSduHeaderLength = 4;
-class L2capPacket {
+class L2capPacket : public HciPacket {
public:
// Returns an assembled L2cap object if successful, nullptr if failure.
- static std::unique_ptr<L2capPacket> assemble(
- const std::vector<L2capSdu>& sdu_packet);
-
- // Construct a vector of just the L2CAP payload. This essentially
- // will remove the L2CAP header from the private member variable.
- // TODO: Remove this in favor of custom iterators.
- std::vector<uint8_t> get_l2cap_payload() const;
-
- uint16_t get_l2cap_cid() const;
+ static std::shared_ptr<L2capPacket> assemble(
+ const std::vector<std::shared_ptr<L2capSdu> >& sdu_packet);
// Returns a fragmented vector of L2capSdu objects if successful
// Returns an empty vector of L2capSdu objects if unsuccessful
- std::vector<L2capSdu> fragment(uint16_t maximum_sdu_size, uint8_t txseq,
- uint8_t reqseq) const;
+ std::vector<std::shared_ptr<L2capSdu> > fragment(uint16_t maximum_sdu_size,
+ uint8_t txseq,
+ uint8_t reqseq);
+
+ uint16_t get_l2cap_cid() const;
+
+ // HciPacket Functions
+ size_t get_length();
+ uint8_t& get_at_index(size_t index);
private:
L2capPacket() = default;
@@ -54,14 +54,8 @@
// Entire L2CAP packet: length, CID, and payload in that order.
std::vector<uint8_t> l2cap_packet_;
- // Returns an iterator to the beginning of the L2CAP payload on success.
- std::vector<uint8_t>::const_iterator get_l2cap_payload_begin() const;
-
DISALLOW_COPY_AND_ASSIGN(L2capPacket);
- // Returns an iterator to the end of the L2CAP payload.
- std::vector<uint8_t>::const_iterator get_l2cap_payload_end() const;
-
// Helper functions for fragmenting.
static void set_sdu_header_length(std::vector<uint8_t>& sdu, uint16_t length);
diff --git a/vendor_libs/test_vendor_lib/include/l2cap_sdu.h b/vendor_libs/test_vendor_lib/include/l2cap_sdu.h
index 8a8c591..489f001 100644
--- a/vendor_libs/test_vendor_lib/include/l2cap_sdu.h
+++ b/vendor_libs/test_vendor_lib/include/l2cap_sdu.h
@@ -1,25 +1,26 @@
-/******************************************************************************
+/*
+ * Copyright 2017 The Android Open Source Project
*
- * Copyright (C) 2017 Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#pragma once
#include <cstdint>
#include <iterator>
#include <vector>
+#include "hci_packet.h"
+
namespace test_vendor_lib {
// Abstract representation of an SDU packet that contains an L2CAP
@@ -57,36 +58,16 @@
// L2CAP packet will not include either of the control or FCS
// bytes.
//
-class L2capSdu {
+class L2capSdu : public HciPacket {
public:
- // Returns a completed L2capSdu object.
- L2capSdu(std::vector<uint8_t> create_from);
+ // Returns a unique_ptr to an L2capSdu object that is constructed with the
+ // assumption that the SDU packet is complete and correct.
+ static std::shared_ptr<L2capSdu> L2capSduConstructor(
+ std::vector<uint8_t> create_from);
- static L2capSdu L2capSduBuilder(std::vector<uint8_t> create_from);
-
- // TODO: Remove this when the move to L2capSdu* is done
- L2capSdu& operator=(L2capSdu obj1) {
- sdu_data_.clear();
-
- sdu_data_ = obj1.sdu_data_;
-
- return *this;
- }
-
- // Get a vector iterator that points to the first byte of the
- // L2CAP payload within an SDU. The offset parameter will be the
- // number of bytes that are in the SDU header. This should always
- // be 6 bytes with the exception being the first SDU of a stream
- // of SDU packets where the first SDU packet will have an extra
- // two bytes and the offset should be 8 bytes.
- std::vector<uint8_t>::const_iterator get_payload_begin(
- const unsigned int offset) const;
-
- // Get a vector iterator that points to the last bytes of the
- // L2CAP payload within an SDU packet. There is no offset
- // parameter for this function because there will always be two
- // FCS bytes and nothing else at the end of each SDU.
- std::vector<uint8_t>::const_iterator get_payload_end() const;
+ // Adds an FCS to create_from and returns a unique_ptr to an L2capSdu object.
+ static std::shared_ptr<L2capSdu> L2capSduBuilder(
+ std::vector<uint8_t> create_from);
// Get the FCS bytes from the end of the L2CAP payload of an SDU
// packet.
@@ -119,10 +100,17 @@
// Reasembly is 10b, false otherwise.
static bool is_ending_sdu(const L2capSdu& sdu);
+ // HciPacket functions
+ size_t get_length();
+ uint8_t& get_at_index(size_t index);
+
private:
// This is the SDU packet in bytes.
std::vector<uint8_t> sdu_data_;
+ // Returns a completed L2capSdu object.
+ L2capSdu(std::vector<uint8_t>&& create_from);
+
// Table for precalculated lfsr values.
static const uint16_t lfsr_table_[256];
diff --git a/vendor_libs/test_vendor_lib/include/l2cap_test_packets.h b/vendor_libs/test_vendor_lib/include/l2cap_test_packets.h
index b0d5238..652ad34 100644
--- a/vendor_libs/test_vendor_lib/include/l2cap_test_packets.h
+++ b/vendor_libs/test_vendor_lib/include/l2cap_test_packets.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 Google, Inc.
+ * Copyright 2017 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/vendor_libs/test_vendor_lib/include/packet.h b/vendor_libs/test_vendor_lib/include/packet.h
index 0feeb58..8bad493 100644
--- a/vendor_libs/test_vendor_lib/include/packet.h
+++ b/vendor_libs/test_vendor_lib/include/packet.h
@@ -1,18 +1,18 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#pragma once
@@ -49,13 +49,13 @@
// Add |octets| bytes to the payload. Return true if:
// - the size of |bytes| is equal to |octets| and
- // - the new size of the payload is still < |kMaxPacketOctets|
+ // - the new size of the payload is still < |kMaxPayloadOctets|
bool AddPayloadOctets(size_t octets, const std::vector<uint8_t>& bytes);
private:
// Add |octets| bytes to the payload. Return true if:
// - the value of |value| fits in |octets| bytes and
- // - the new size of the payload is still < |kMaxPacketOctets|
+ // - the new size of the payload is still < |kMaxPayloadOctets|
bool AddPayloadOctets(size_t octets, uint64_t value);
public:
@@ -68,9 +68,14 @@
bool AddPayloadOctets8(uint64_t value) { return AddPayloadOctets(8, value); }
// Add |address| to the payload. Return true if:
- // - the new size of the payload is still < |kMaxPacketOctets|
+ // - the new size of the payload is still < |kMaxPayloadOctets|
bool AddPayloadBtAddress(const BtAddress& address);
+ // Return true if |num_bytes| can be added to the payload.
+ bool CanAddPayloadOctets(size_t num_bytes) const {
+ return GetPayloadSize() + num_bytes <= kMaxPayloadOctets;
+ }
+
protected:
// Constructs an empty packet of type |type| and header |header|
Packet(serial_data_type_t type, std::vector<uint8_t> header);
@@ -79,7 +84,7 @@
bool IncrementPayloadCounter(size_t index, uint8_t max_val);
private:
- const size_t kMaxPacketOctets = 256; // Includes the Octet count
+ const size_t kMaxPayloadOctets = 256; // Includes the size byte.
// Underlying containers for storing the actual packet
diff --git a/vendor_libs/test_vendor_lib/include/sco_packet.h b/vendor_libs/test_vendor_lib/include/sco_packet.h
new file mode 100644
index 0000000..7b95063
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/sco_packet.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "packet.h"
+
+namespace test_vendor_lib {
+
+// SCO data packets are specified in the Bluetooth Core Specification Version
+// 4.2, Volume 2, Part E, Section 5.4.3
+class ScoPacket : public Packet {
+ public:
+ virtual ~ScoPacket() override = default;
+ typedef enum {
+ CorrectlyReceived,
+ PossiblyIncomplete,
+ NoData,
+ PartiallyLost
+ } PacketStatusFlags;
+
+ uint16_t GetChannel() const;
+
+ PacketStatusFlags GetPacketStatusFlags() const;
+
+ explicit ScoPacket(uint16_t channel, PacketStatusFlags status_flags);
+};
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/test_channel_transport.h b/vendor_libs/test_vendor_lib/include/test_channel_transport.h
index b38a8ce..069f91e 100644
--- a/vendor_libs/test_vendor_lib/include/test_channel_transport.h
+++ b/vendor_libs/test_vendor_lib/include/test_channel_transport.h
@@ -1,18 +1,18 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#pragma once
diff --git a/vendor_libs/test_vendor_lib/scripts/test_channel.py b/vendor_libs/test_vendor_lib/scripts/test_channel.py
index cf470f9..06b0410 100644
--- a/vendor_libs/test_vendor_lib/scripts/test_channel.py
+++ b/vendor_libs/test_vendor_lib/scripts/test_channel.py
@@ -168,50 +168,40 @@
cmd.Cmd.__init__(self)
self._test_channel = test_channel
- def do_clear(self, args):
+ def do_add(self, args):
"""
- Arguments: None.
- Resets the controller to its original, unmodified state.
+ Arguments: dev_type_str
+ Add a new device of type dev_type_str.
"""
- self._test_channel.send_command('CLEAR', [])
+ self._test_channel.send_command('add', args.split())
- def do_clear_event_delay(self, args):
+ def do_del(self, args):
"""
- Arguments: None.
- Clears the response delay set by set_event_delay.
+ Arguments: device index
+ Delete the device with the specified index.
"""
- self._test_channel.send_command('CLEAR_EVENT_DELAY', args.split())
+ self._test_channel.send_command('del', args.split())
- def do_discover(self, args):
+ def do_get(self, args):
"""
- Arguments: name_1 name_2 ...
- Sends an inquiry result for named device(s). If no names are provided, a
- random name is used instead.
+ Arguments: dev_num attr_str
+ Get the value of the attribute attr_str from device dev_num.
"""
- if len(args) == 0:
- args = generate_random_name()
- device_list = [self._test_channel.discover_new_device(arg) for arg in \
- args.split()]
- device_names_and_addresses = []
- for device in device_list:
- device_names_and_addresses.append(device.get_name())
- device_names_and_addresses.append(device.get_address())
- self._test_channel.send_command('DISCOVER', device_names_and_addresses)
+ self._test_channel.send_command('get', args.split())
- def do_set_event_delay(self, args):
+ def do_set(self, args):
"""
- Arguments: interval_in_ms
- Sets the response delay for all event packets sent from the controller back
- to the HCI.
+ Arguments: dev_num attr_str val
+ Set the value of the attribute attr_str from device dev_num equal to val.
"""
- self._test_channel.send_command('SET_EVENT_DELAY', args.split())
+ self._test_channel.send_command('set', args.split())
- def do_timeout_all(self, args):
+ def do_list(self, args):
"""
- Arguments: None.
- Causes all HCI commands to timeout.
+ Arguments: [dev_num [attr]]
+ List the devices from the controller, optionally filtered by device and attr.
"""
- self._test_channel.send_command('TIMEOUT_ALL', [])
+ self._test_channel.send_command('list', args.split())
def do_quit(self, args):
"""
@@ -223,6 +213,15 @@
print 'Goodbye.'
return True
+ def do_help(self, args):
+ """
+ Arguments: [dev_num [attr]]
+ List the commands available, optionally filtered by device and attr.
+ """
+ self._test_channel.send_command('help', args.split())
+ if (len(args) == 0):
+ cmd.Cmd.do_help(self, args)
+
def main(argv):
if len(argv) != 2:
print 'Usage: python test_channel.py [port]'
diff --git a/vendor_libs/test_vendor_lib/src/acl_packet.cc b/vendor_libs/test_vendor_lib/src/acl_packet.cc
new file mode 100644
index 0000000..47aa8be
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/acl_packet.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "acl_packet"
+
+#include "acl_packet.h"
+
+#include "base/logging.h"
+#include "osi/include/log.h"
+#include "stack/include/hcidefs.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+AclPacket::AclPacket(uint16_t channel,
+ AclPacket::PacketBoundaryFlags packet_boundary,
+ AclPacket::BroadcastFlags broadcast)
+ : raw_packet_({static_cast<uint8_t>(channel & 0xff),
+ static_cast<uint8_t>(((channel >> 8) & 0x0f) |
+ ((packet_boundary & 0x3) << 4) |
+ (broadcast & 0x3) << 6),
+ 0x00, 0x00}) {}
+
+void AclPacket::AddPayloadOctets(size_t octets, const vector<uint8_t>& bytes) {
+ CHECK(bytes.size() == octets);
+
+ raw_packet_.insert(raw_packet_.end(), bytes.begin(), bytes.end());
+
+ raw_packet_[2] =
+ static_cast<uint8_t>((raw_packet_.size() - kHeaderSize) & 0xff);
+ raw_packet_[3] =
+ static_cast<uint8_t>(((raw_packet_.size() - kHeaderSize) >> 8) & 0xff);
+}
+
+void AclPacket::AddPayloadOctets(size_t octets, uint64_t value) {
+ vector<uint8_t> val_vector;
+
+ uint64_t v = value;
+
+ CHECK(octets <= sizeof(uint64_t));
+
+ for (size_t i = 0; i < octets; i++) {
+ val_vector.push_back(v & 0xff);
+ v = v >> 8;
+ }
+
+ CHECK(v == 0);
+
+ AddPayloadOctets(octets, val_vector);
+}
+
+size_t AclPacket::GetPacketSize() const { return raw_packet_.size(); }
+
+const std::vector<uint8_t>& AclPacket::GetPacket() const { return raw_packet_; }
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/async_manager.cc b/vendor_libs/test_vendor_lib/src/async_manager.cc
index 355f647..0e30af7 100644
--- a/vendor_libs/test_vendor_lib/src/async_manager.cc
+++ b/vendor_libs/test_vendor_lib/src/async_manager.cc
@@ -1,18 +1,18 @@
-//
-// Copyright 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#define LOG_TAG "async_manager"
@@ -517,4 +517,4 @@
std::unique_lock<std::mutex> guard(synchronization_mutex_);
critical();
}
-}
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/beacon.cc b/vendor_libs/test_vendor_lib/src/beacon.cc
new file mode 100644
index 0000000..0ca4507
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/beacon.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "beacon"
+
+#include "beacon.h"
+#include "stack/include/hcidefs.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+Beacon::Beacon() {
+ advertising_interval_ms_ = std::chrono::milliseconds(1280);
+ advertising_type_ = BTM_BLE_NON_CONNECT_EVT;
+ adv_data_ = {0x0F, // Length
+ BTM_BLE_AD_TYPE_NAME_CMPL,
+ 'g',
+ 'D',
+ 'e',
+ 'v',
+ 'i',
+ 'c',
+ 'e',
+ '-',
+ 'b',
+ 'e',
+ 'a',
+ 'c',
+ 'o',
+ 'n',
+ 0x02, // Length
+ BTM_BLE_AD_TYPE_FLAG,
+ BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG};
+
+ scan_data_ = {0x05, // Length
+ BTM_BLE_AD_TYPE_NAME_SHORT,
+ 'b',
+ 'e',
+ 'a',
+ 'c'};
+}
+
+void Beacon::Initialize(const vector<std::string>& args) {
+ if (args.size() < 2) return;
+
+ BtAddress addr;
+ if (addr.FromString(args[1])) SetBtAddress(addr);
+
+ if (args.size() < 3) return;
+
+ SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+}
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/beacon_swarm.cc b/vendor_libs/test_vendor_lib/src/beacon_swarm.cc
new file mode 100644
index 0000000..2f4eed1
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/beacon_swarm.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "beacon_swarm"
+
+#include "beacon_swarm.h"
+#include "stack/include/hcidefs.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+BeaconSwarm::BeaconSwarm() {
+ advertising_interval_ms_ = std::chrono::milliseconds(1280);
+ advertising_type_ = BTM_BLE_NON_CONNECT_EVT;
+ adv_data_ = {0x02, // Length
+ BTM_BLE_AD_TYPE_FLAG,
+ BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG,
+ 0x15,
+ BTM_BLE_AD_TYPE_NAME_CMPL,
+ 'g',
+ 'D',
+ 'e',
+ 'v',
+ 'i',
+ 'c',
+ 'e',
+ '-',
+ 'b',
+ 'e',
+ 'a',
+ 'c',
+ 'o',
+ 'n',
+ '_',
+ 's',
+ 'w',
+ 'a',
+ 'r',
+ 'm'};
+
+ scan_response_present_ = true;
+ scan_data_ = {0x06, // Length
+ BTM_BLE_AD_TYPE_NAME_SHORT,
+ 'c',
+ 'b',
+ 'e',
+ 'a',
+ 'c'};
+}
+
+void BeaconSwarm::Initialize(const vector<std::string>& args) {
+ if (args.size() < 2) return;
+
+ BtAddress addr;
+ if (addr.FromString(args[1])) SetBtAddress(addr);
+
+ if (args.size() < 3) return;
+
+ SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+}
+
+void BeaconSwarm::TimerTick() {
+ std::vector<uint8_t> beacon_addr;
+ GetBtAddress().ToVector(beacon_addr);
+ beacon_addr[0]++;
+ BtAddress next_addr;
+ next_addr.FromVector(beacon_addr);
+
+ SetBtAddress(next_addr);
+}
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/broken_adv.cc b/vendor_libs/test_vendor_lib/src/broken_adv.cc
new file mode 100644
index 0000000..92f47fa
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/broken_adv.cc
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "broken_adv"
+
+#include "broken_adv.h"
+
+#include "osi/include/log.h"
+#include "stack/include/hcidefs.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+BrokenAdv::BrokenAdv() {
+ advertising_interval_ms_ = std::chrono::milliseconds(1280);
+ advertising_type_ = BTM_BLE_NON_CONNECT_EVT;
+ adv_data_ = {
+ 0x02, // Length
+ BTM_BLE_AD_TYPE_FLAG,
+ BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG,
+ 0x13, // Length
+ BTM_BLE_AD_TYPE_NAME_CMPL,
+ 'g',
+ 'D',
+ 'e',
+ 'v',
+ 'i',
+ 'c',
+ 'e',
+ '-',
+ 'b',
+ 'r',
+ 'o',
+ 'k',
+ 'e',
+ 'n',
+ '_',
+ 'a',
+ 'd',
+ 'v',
+ };
+
+ constant_adv_data_ = adv_data_;
+
+ scan_response_present_ = true;
+ scan_data_ = {0x0b, // Length
+ BTM_BLE_AD_TYPE_NAME_SHORT,
+ 'b',
+ 'r',
+ 'o',
+ 'k',
+ 'e',
+ 'n',
+ 'n',
+ 'e',
+ 's',
+ 's'};
+
+ extended_inquiry_data_ = {0x07, // Length
+ BT_EIR_COMPLETE_LOCAL_NAME_TYPE,
+ 'B',
+ 'R',
+ '0',
+ 'K',
+ '3',
+ 'N'};
+ page_scan_repetition_mode_ = 0;
+ page_scan_delay_ms_ = std::chrono::milliseconds(600);
+}
+
+void BrokenAdv::Initialize(const vector<std::string>& args) {
+ if (args.size() < 2) return;
+
+ BtAddress addr;
+ if (addr.FromString(args[1])) SetBtAddress(addr);
+
+ if (args.size() < 3) return;
+
+ SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+}
+
+// Mostly return the correct length
+static uint8_t random_length(size_t bytes_remaining) {
+ uint32_t randomness = rand();
+
+ switch ((randomness & 0xf000000) >> 24) {
+ case (0):
+ return bytes_remaining + (randomness & 0xff);
+ case (1):
+ return bytes_remaining - (randomness & 0xff);
+ case (2):
+ return bytes_remaining + (randomness & 0xf);
+ case (3):
+ return bytes_remaining - (randomness & 0xf);
+ case (5):
+ case (6):
+ return bytes_remaining + (randomness & 0x3);
+ case (7):
+ case (8):
+ return bytes_remaining - (randomness & 0x3);
+ default:
+ return bytes_remaining;
+ }
+}
+
+static size_t random_adv_type() {
+ uint32_t randomness = rand();
+
+ switch ((randomness & 0xf000000) >> 24) {
+ case (0):
+ return BTM_EIR_MANUFACTURER_SPECIFIC_TYPE;
+ case (1):
+ return (randomness & 0xff);
+ default:
+ return (randomness & 0x1f);
+ }
+}
+
+static size_t random_data_length(size_t length, size_t bytes_remaining) {
+ uint32_t randomness = rand();
+
+ switch ((randomness & 0xf000000) >> 24) {
+ case (0):
+ return bytes_remaining;
+ case (1):
+ return (length + (randomness & 0xff)) % bytes_remaining;
+ default:
+ return (length <= bytes_remaining ? length : bytes_remaining);
+ }
+}
+
+static void RandomizeAdvertisement(vector<uint8_t>& ad, size_t max) {
+ uint8_t length = random_length(max);
+ uint8_t data_length = random_data_length(length, max);
+
+ ad.push_back(random_adv_type());
+ ad.push_back(length);
+ for (size_t i = 0; i < data_length; i++) ad.push_back(rand() & 0xff);
+}
+
+void BrokenAdv::UpdateAdvertisement() {
+ adv_data_.clear();
+ for (size_t i = 0; i < constant_adv_data_.size(); i++)
+ adv_data_.push_back(constant_adv_data_[i]);
+
+ RandomizeAdvertisement(adv_data_, 31 - adv_data_.size());
+
+ RandomizeAdvertisement(scan_data_, 31);
+
+ std::vector<uint8_t> curr_addr;
+ BtAddress next_addr;
+ GetBtAddress().ToVector(curr_addr);
+ curr_addr[0]++;
+ next_addr.FromVector(curr_addr);
+
+ SetBtAddress(next_addr);
+}
+
+std::string BrokenAdv::ToString() const {
+ std::string str = Device::ToString() + std::string(": Interval = ") +
+ std::to_string(advertising_interval_ms_.count());
+ return str;
+}
+
+void BrokenAdv::UpdatePageScan() {
+ std::vector<uint8_t> broken_addr;
+ RandomizeAdvertisement(scan_data_, 31);
+
+ BtAddress next_addr;
+ GetBtAddress().ToVector(broken_addr);
+ broken_addr[1]++;
+ next_addr.FromVector(broken_addr);
+
+ SetBtAddress(next_addr);
+}
+
+void BrokenAdv::TimerTick() {
+ UpdatePageScan();
+ UpdateAdvertisement();
+}
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/bt_address.cc b/vendor_libs/test_vendor_lib/src/bt_address.cc
index 4deffb3..e9d6790 100644
--- a/vendor_libs/test_vendor_lib/src/bt_address.cc
+++ b/vendor_libs/test_vendor_lib/src/bt_address.cc
@@ -1,18 +1,18 @@
-//
-// Copyright 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "bt_address.h"
#include <iomanip>
@@ -40,7 +40,7 @@
std::string tok;
std::istringstream iss(str);
- if (IsValid(str) == false) return false;
+ if (!IsValid(str)) return false;
address_ = 0;
for (size_t i = 0; i < kOctets; i++) {
diff --git a/vendor_libs/test_vendor_lib/src/classic.cc b/vendor_libs/test_vendor_lib/src/classic.cc
new file mode 100644
index 0000000..b878b5f
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/classic.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "classic"
+
+#include "classic.h"
+#include "osi/include/log.h"
+#include "stack/include/hcidefs.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+Classic::Classic() {
+ advertising_interval_ms_ = std::chrono::milliseconds(0);
+ device_class_ = 0x30201;
+
+ extended_inquiry_data_ = {0x10, // Length
+ BT_EIR_COMPLETE_LOCAL_NAME_TYPE,
+ 'g',
+ 'D',
+ 'e',
+ 'v',
+ 'i',
+ 'c',
+ 'e',
+ '-',
+ 'c',
+ 'l',
+ 'a',
+ 's',
+ 's',
+ 'i',
+ 'c'};
+ page_scan_repetition_mode_ = 0;
+ page_scan_delay_ms_ = std::chrono::milliseconds(600);
+}
+
+void Classic::Initialize(const vector<std::string>& args) {
+ if (args.size() < 2) return;
+
+ BtAddress addr;
+ if (addr.FromString(args[1])) SetBtAddress(addr);
+
+ if (args.size() < 3) return;
+
+ SetClockOffset(std::stoi(args[2]));
+}
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/command_packet.cc b/vendor_libs/test_vendor_lib/src/command_packet.cc
index 79935dc..9b44c98 100644
--- a/vendor_libs/test_vendor_lib/src/command_packet.cc
+++ b/vendor_libs/test_vendor_lib/src/command_packet.cc
@@ -1,18 +1,18 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#define LOG_TAG "command_packet"
diff --git a/vendor_libs/test_vendor_lib/src/connection.cc b/vendor_libs/test_vendor_lib/src/connection.cc
new file mode 100644
index 0000000..5bdc20f
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/connection.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "connection"
+
+#include "connection.h"
+
+#include "base/logging.h"
+
+#include "osi/include/log.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+// Add an action from the controller.
+void Connection::AddAction(const TaskCallback& task) { actions_.push(task); }
+
+// Model the quality of the downstream connection
+void Connection::SendToDevice() {
+ while (actions_.size() > 0) {
+ // Execute the first action
+ actions_.front()();
+ actions_.pop();
+ }
+}
+
+// Add a message from the device to the controller.
+void Connection::AddMessage(const vector<uint8_t>& data) {
+ messages_.push(data);
+}
+
+// Model the quality of the upstream connection
+bool Connection::ReceiveFromDevice(vector<uint8_t>& data) {
+ if (messages_.size() > 0) {
+ data = messages_.front();
+ messages_.pop();
+
+ return true;
+ }
+ return false;
+}
+
+const std::string Connection::ToString() {
+ return "connection " + std::to_string(handle_) + " to " + dev_->ToString();
+}
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/device.cc b/vendor_libs/test_vendor_lib/src/device.cc
new file mode 100644
index 0000000..86d18c0
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/device.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "device"
+
+#include <vector>
+
+#include "device.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+std::string Device::ToString() const {
+ std::string dev = "(" + GetTypeString() + ")" + "@" + address_.ToString();
+
+ return dev;
+}
+
+bool Device::IsAdvertisementAvailable(
+ std::chrono::milliseconds scan_time) const {
+ if (advertising_interval_ms_ == std::chrono::milliseconds(0)) return false;
+
+ std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
+
+ std::chrono::steady_clock::time_point last_interval =
+ ((now - time_stamp_) / advertising_interval_ms_) *
+ advertising_interval_ms_ +
+ time_stamp_;
+
+ std::chrono::steady_clock::time_point next_interval =
+ last_interval + advertising_interval_ms_;
+
+ return ((now + scan_time) >= next_interval);
+}
+
+bool Device::IsPageScanAvailable() const { return true; }
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/device_factory.cc b/vendor_libs/test_vendor_lib/src/device_factory.cc
new file mode 100644
index 0000000..3e23dee
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/device_factory.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "device_factory"
+
+#include "device_factory.h"
+#include "beacon.h"
+#include "beacon_swarm.h"
+#include "broken_adv.h"
+#include "classic.h"
+#include "device.h"
+#include "keyboard.h"
+
+#include "base/logging.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+std::shared_ptr<Device> DeviceFactory::Create(const vector<std::string>& args) {
+ CHECK(!args.empty());
+
+ std::shared_ptr<Device> new_device = nullptr;
+
+ if (args[0] == "beacon") new_device = std::make_shared<Beacon>();
+ if (args[0] == "beacon_swarm") new_device = std::make_shared<BeaconSwarm>();
+ if (args[0] == "broken_adv") new_device = std::make_shared<BrokenAdv>();
+ if (args[0] == "classic") new_device = std::make_shared<Classic>();
+ if (args[0] == "keyboard") new_device = std::make_shared<Keyboard>();
+
+ if (new_device != nullptr) new_device->Initialize(args);
+
+ return new_device;
+}
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/device_properties.cc b/vendor_libs/test_vendor_lib/src/device_properties.cc
new file mode 100644
index 0000000..672dd65
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/device_properties.cc
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "device_properties"
+
+#include "device_properties.h"
+
+#include <memory>
+
+#include <base/logging.h>
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/values.h"
+
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+#include "stack/include/hcidefs.h"
+
+using std::vector;
+
+namespace {
+// Functions used by JSONValueConverter to read stringified JSON.
+bool ParseUint8t(const base::StringPiece& value, uint8_t* field) {
+ *field = std::stoi(value.as_string());
+ return true;
+}
+
+bool ParseUint16t(const base::StringPiece& value, uint16_t* field) {
+ *field = std::stoi(value.as_string());
+ return true;
+}
+
+} // namespace
+
+namespace test_vendor_lib {
+
+DeviceProperties::DeviceProperties(const std::string& file_name)
+ : acl_data_packet_size_(1024),
+ sco_data_packet_size_(255),
+ num_acl_data_packets_(10),
+ num_sco_data_packets_(10),
+ version_(HCI_PROTO_VERSION_4_1),
+ revision_(0),
+ lmp_pal_version_(7), /* 4.1 */
+ manufacturer_name_(0),
+ lmp_pal_subversion_(0),
+ le_data_packet_length_(27),
+ num_le_data_packets_(15),
+ le_white_list_size_(15) {
+ std::string properties_raw;
+
+ local_extended_features_ = {0xffffffffffffffff, 0x7};
+
+ CHECK(address_.FromString("01:02:03:04:05:06"));
+ local_name_ = "DefaultName";
+
+ supported_codecs_ = {1};
+ vendor_specific_codecs_ = {};
+
+ for (int i = 0; i < 64; i++) local_supported_commands_.push_back(0xff);
+
+ le_supported_features_ = 0x1f;
+ le_supported_states_ = 0x3ffffffffff;
+ le_vendor_cap_ = {};
+
+ LOG_INFO(LOG_TAG, "Reading controller properties from %s.",
+ file_name.c_str());
+ if (!base::ReadFileToString(base::FilePath(file_name), &properties_raw)) {
+ LOG_ERROR(LOG_TAG, "Error reading controller properties from file.");
+ return;
+ }
+
+ std::unique_ptr<base::Value> properties_value_ptr =
+ base::JSONReader::Read(properties_raw);
+ if (properties_value_ptr.get() == nullptr)
+ LOG_INFO(LOG_TAG,
+ "Error controller properties may consist of ill-formed JSON.");
+
+ // Get the underlying base::Value object, which is of type
+ // base::Value::TYPE_DICTIONARY, and read it into member variables.
+ base::Value& properties_dictionary = *(properties_value_ptr.get());
+ base::JSONValueConverter<DeviceProperties> converter;
+
+ if (!converter.Convert(properties_dictionary, this))
+ LOG_INFO(LOG_TAG,
+ "Error converting JSON properties into Properties object.");
+}
+
+// static
+void DeviceProperties::RegisterJSONConverter(
+ base::JSONValueConverter<DeviceProperties>* converter) {
+// TODO(dennischeng): Use RegisterIntField() here?
+#define REGISTER_UINT8_T(field_name, field) \
+ converter->RegisterCustomField<uint8_t>( \
+ field_name, &DeviceProperties::field, &ParseUint8t);
+#define REGISTER_UINT16_T(field_name, field) \
+ converter->RegisterCustomField<uint16_t>( \
+ field_name, &DeviceProperties::field, &ParseUint16t);
+ REGISTER_UINT16_T("AclDataPacketSize", acl_data_packet_size_);
+ REGISTER_UINT8_T("ScoDataPacketSize", sco_data_packet_size_);
+ REGISTER_UINT16_T("NumAclDataPackets", num_acl_data_packets_);
+ REGISTER_UINT16_T("NumScoDataPackets", num_sco_data_packets_);
+ REGISTER_UINT8_T("Version", version_);
+ REGISTER_UINT16_T("Revision", revision_);
+ REGISTER_UINT8_T("LmpPalVersion", lmp_pal_version_);
+ REGISTER_UINT16_T("ManufacturerName", manufacturer_name_);
+ REGISTER_UINT16_T("LmpPalSubversion", lmp_pal_subversion_);
+#undef REGISTER_UINT8_T
+#undef REGISTER_UINT16_T
+}
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc b/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc
index 86f920b..bc80866 100644
--- a/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc
+++ b/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc
@@ -1,22 +1,23 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#define LOG_TAG "dual_mode_controller"
#include "dual_mode_controller.h"
+#include "device_factory.h"
#include <memory>
@@ -24,7 +25,6 @@
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/values.h"
-#include "event_packet.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -44,30 +44,10 @@
const std::string kControllerPropertiesFile =
"/etc/bluetooth/controller_properties.json";
-// Inquiry modes for specifiying inquiry result formats.
-const uint8_t kStandardInquiry = 0x00;
-const uint8_t kRssiInquiry = 0x01;
-const uint8_t kExtendedOrRssiInquiry = 0x02;
-
-// The bd address of another (fake) device.
-const vector<uint8_t> kOtherDeviceBdAddress = {6, 5, 4, 3, 2, 1};
-
void LogCommand(const char* command) {
LOG_INFO(LOG_TAG, "Controller performing command: %s", command);
}
-// Functions used by JSONValueConverter to read stringified JSON into Properties
-// object.
-bool ParseUint8t(const base::StringPiece& value, uint8_t* field) {
- *field = std::stoi(value.as_string());
- return true;
-}
-
-bool ParseUint16t(const base::StringPiece& value, uint16_t* field) {
- *field = std::stoi(value.as_string());
- return true;
-}
-
} // namespace
namespace test_vendor_lib {
@@ -77,6 +57,12 @@
controller_events_.push_back(schedule_task_(delay, task));
}
+void DualModeController::AddConnectionAction(const TaskCallback& task,
+ uint16_t handle) {
+ for (size_t i = 0; i < connections_.size(); i++)
+ if (*connections_[i] == handle) connections_[i]->AddAction(task);
+}
+
void DualModeController::SendCommandCompleteSuccess(
uint16_t command_opcode) const {
send_event_(EventPacket::CreateCommandCompleteOnlyStatusEvent(
@@ -100,9 +86,26 @@
}
DualModeController::DualModeController()
- : state_(kStandby),
- properties_(kControllerPropertiesFile),
- test_channel_state_(kNone) {
+ : state_(kStandby), properties_(kControllerPropertiesFile) {
+ devices_ = {};
+
+ vector<std::string> beacon = {"beacon", "be:ac:10:00:00:01", "1000"};
+ TestChannelAdd(beacon);
+
+ vector<std::string> classic = {std::string("classic"),
+ std::string("c1:a5:51:c0:00:01")};
+ TestChannelAdd(classic);
+
+ vector<std::string> keyboard = {std::string("keyboard"),
+ std::string("cc:1c:eb:0a:12:d1"),
+ std::string("500")};
+ TestChannelAdd(keyboard);
+
+ le_scan_enable_ = 0;
+ le_connect_ = false;
+
+ loopback_mode_ = 0;
+
#define SET_HANDLER(opcode, method) \
active_hci_commands_[opcode] = [this](const vector<uint8_t>& param) { \
method(param); \
@@ -144,6 +147,8 @@
SET_HANDLER(HCI_BLE_WRITE_ADV_PARAMS, HciLeSetAdvertisingParameters);
SET_HANDLER(HCI_BLE_WRITE_SCAN_PARAMS, HciLeSetScanParameters);
SET_HANDLER(HCI_BLE_WRITE_SCAN_ENABLE, HciLeSetScanEnable);
+ SET_HANDLER(HCI_BLE_CREATE_LL_CONN, HciLeCreateConnection);
+ SET_HANDLER(HCI_BLE_CREATE_CONN_CANCEL, HciLeConnectionCancel);
SET_HANDLER(HCI_BLE_READ_WHITE_LIST_SIZE, HciLeReadWhiteListSize);
SET_HANDLER(HCI_BLE_RAND, HciLeRand);
SET_HANDLER(HCI_BLE_READ_SUPPORTED_STATES, HciLeReadSupportedStates);
@@ -151,19 +156,20 @@
SET_HANDLER(HCI_BLE_VENDOR_CAP_OCF, HciBleVendorCap);
SET_HANDLER(HCI_BLE_MULTI_ADV_OCF, HciBleVendorMultiAdv);
SET_HANDLER((HCI_GRP_VENDOR_SPECIFIC | 0x155), HciBleVendor155);
- SET_HANDLER((HCI_GRP_VENDOR_SPECIFIC | 0x157), HciBleVendor157);
+ SET_HANDLER(HCI_BLE_ADV_FILTER_OCF, HciBleAdvertisingFilter);
SET_HANDLER(HCI_BLE_ENERGY_INFO_OCF, HciBleEnergyInfo);
SET_HANDLER(HCI_BLE_EXTENDED_SCAN_PARAMS_OCF, HciBleExtendedScanParams);
+ // Testing Commands
+ SET_HANDLER(HCI_READ_LOOPBACK_MODE, HciReadLoopbackMode);
+ SET_HANDLER(HCI_WRITE_LOOPBACK_MODE, HciWriteLoopbackMode);
#undef SET_HANDLER
#define SET_TEST_HANDLER(command_name, method) \
active_test_channel_commands_[command_name] = \
[this](const vector<std::string>& param) { method(param); };
- SET_TEST_HANDLER("CLEAR", TestChannelClear);
- SET_TEST_HANDLER("CLEAR_EVENT_DELAY", TestChannelClearEventDelay);
- SET_TEST_HANDLER("DISCOVER", TestChannelDiscover);
- SET_TEST_HANDLER("SET_EVENT_DELAY", TestChannelSetEventDelay);
- SET_TEST_HANDLER("TIMEOUT_ALL", TestChannelTimeoutAll);
+ SET_TEST_HANDLER("add", TestChannelAdd);
+ SET_TEST_HANDLER("del", TestChannelDel);
+ SET_TEST_HANDLER("list", TestChannelList);
#undef SET_TEST_HANDLER
}
@@ -191,19 +197,43 @@
active_test_channel_commands_[name](args);
}
+void DualModeController::HandleAcl(std::unique_ptr<AclPacket> acl_packet) {
+ if (loopback_mode_ == HCI_LOOPBACK_MODE_LOCAL) {
+ uint16_t channel = acl_packet->GetChannel();
+ send_acl_(std::move(acl_packet));
+ send_event_(EventPacket::CreateNumberOfCompletedPacketsEvent(channel, 1));
+ return;
+ }
+}
+
+void DualModeController::HandleSco(std::unique_ptr<ScoPacket> sco_packet) {
+ if (loopback_mode_ == HCI_LOOPBACK_MODE_LOCAL) {
+ uint16_t channel = sco_packet->GetChannel();
+ send_sco_(std::move(sco_packet));
+ send_event_(EventPacket::CreateNumberOfCompletedPacketsEvent(channel, 1));
+ return;
+ }
+}
+
void DualModeController::HandleCommand(
std::unique_ptr<CommandPacket> command_packet) {
uint16_t opcode = command_packet->GetOpcode();
LOG_INFO(LOG_TAG, "Command opcode: 0x%04X, OGF: 0x%04X, OCF: 0x%04X", opcode,
command_packet->GetOGF(), command_packet->GetOCF());
- // The command hasn't been registered with the handler yet. There is nothing
- // to do.
- if (active_hci_commands_.count(opcode) == 0)
- return;
- else if (test_channel_state_ == kTimeoutAll)
- return;
- active_hci_commands_[opcode](command_packet->GetPayload());
+ if (loopback_mode_ == HCI_LOOPBACK_MODE_LOCAL &&
+ // Loopback exceptions.
+ opcode != HCI_RESET && opcode != HCI_SET_HC_TO_HOST_FLOW_CTRL &&
+ opcode != HCI_HOST_BUFFER_SIZE && opcode != HCI_HOST_NUM_PACKETS_DONE &&
+ opcode != HCI_READ_BUFFER_SIZE && opcode != HCI_READ_LOOPBACK_MODE &&
+ opcode != HCI_WRITE_LOOPBACK_MODE) {
+ send_event_(EventPacket::CreateLoopbackCommandEvent(
+ opcode, command_packet->GetPayload()));
+ } else if (active_hci_commands_.count(opcode) > 0) {
+ active_hci_commands_[opcode](command_packet->GetPayload());
+ } else {
+ SendCommandCompleteOnlyStatus(opcode, kUnknownHciCommand);
+ }
}
void DualModeController::RegisterEventChannel(
@@ -211,10 +241,21 @@
send_event_ = callback;
}
+void DualModeController::RegisterAclChannel(
+ const std::function<void(std::unique_ptr<AclPacket>)>& callback) {
+ send_acl_ = callback;
+}
+
+void DualModeController::RegisterScoChannel(
+ const std::function<void(std::unique_ptr<ScoPacket>)>& callback) {
+ send_sco_ = callback;
+}
+
void DualModeController::HandleTimerTick() {
- // PageScan();
- if (le_scan_enable_) LOG_ERROR(LOG_TAG, "LE scan");
- // LeScan();
+ if (state_ == kInquiry) PageScan();
+ if (le_scan_enable_ || le_connect_) LeScan();
+ Connections();
+ for (size_t dev = 0; dev < devices_.size(); dev++) devices_[dev]->TimerTick();
}
void DualModeController::SetTimerPeriod(std::chrono::milliseconds new_period) {
@@ -227,6 +268,145 @@
StartTimer();
}
+static uint8_t GetRssi(size_t dev) {
+ // TODO: Model rssi somehow
+ return -((dev * 16) % 127);
+}
+
+static uint8_t LeGetHandle() {
+ static int handle = 0;
+ return handle++;
+}
+
+static uint8_t LeGetConnInterval() { return 1; }
+
+static uint8_t LeGetConnLatency() { return 2; }
+
+static uint8_t LeGetSupervisionTimeout() { return 3; }
+
+void DualModeController::Connections() {
+ for (size_t i = 0; i < connections_.size(); i++) {
+ if (connections_[i]->Connected()) {
+ connections_[i]->SendToDevice();
+ vector<uint8_t> data;
+ connections_[i]->ReceiveFromDevice(data);
+ // HandleConnectionData(data);
+ }
+ }
+}
+
+void DualModeController::LeScan() {
+ std::unique_ptr<EventPacket> le_adverts =
+ EventPacket::CreateLeAdvertisingReportEvent();
+ vector<uint8_t> ad;
+ for (size_t dev = 0; dev < devices_.size(); dev++) {
+ uint8_t adv_type;
+ const BtAddress addr = devices_[dev]->GetBtAddress();
+ uint8_t addr_type = devices_[dev]->GetAddressType();
+ ad.clear();
+
+ // Listen for Advertisements
+ if (devices_[dev]->IsAdvertisementAvailable(
+ std::chrono::milliseconds(le_scan_window_))) {
+ ad = devices_[dev]->GetAdvertisement();
+ adv_type = devices_[dev]->GetAdvertisementType();
+ if (le_scan_enable_ && !le_adverts->AddLeAdvertisingReport(
+ adv_type, addr_type, addr, ad, GetRssi(dev))) {
+ send_event_(std::move(le_adverts));
+ le_adverts = EventPacket::CreateLeAdvertisingReportEvent();
+ CHECK(le_adverts->AddLeAdvertisingReport(adv_type, addr_type, addr, ad,
+ GetRssi(dev)));
+ }
+
+ // Connect
+ if (le_connect_ && (adv_type == BTM_BLE_CONNECT_EVT ||
+ adv_type == BTM_BLE_CONNECT_DIR_EVT)) {
+ LOG_INFO(LOG_TAG, "Connecting to device %d", static_cast<int>(dev));
+ if (peer_address_ == addr && peer_address_type_ == addr_type &&
+ devices_[dev]->LeConnect()) {
+ uint16_t handle = LeGetHandle();
+ std::unique_ptr<EventPacket> event =
+ EventPacket::CreateLeConnectionCompleteEvent(
+ kSuccessStatus, handle, HCI_ROLE_MASTER, addr_type, addr,
+ LeGetConnInterval(), LeGetConnLatency(),
+ LeGetSupervisionTimeout());
+ send_event_(std::move(event));
+ le_connect_ = false;
+
+ connections_.push_back(
+ std::make_shared<Connection>(devices_[dev], handle));
+ }
+
+ // TODO: Handle the white list (if (InWhiteList(dev)))
+ }
+
+ // Active scanning
+ if (le_scan_enable_ && le_scan_type_ == 1) {
+ ad.clear();
+ if (devices_[dev]->HasScanResponse()) {
+ ad = devices_[dev]->GetScanResponse();
+ if (!le_adverts->AddLeAdvertisingReport(
+ BTM_BLE_SCAN_RSP_EVT, addr_type, addr, ad, GetRssi(dev))) {
+ send_event_(std::move(le_adverts));
+ le_adverts = EventPacket::CreateLeAdvertisingReportEvent();
+ CHECK(le_adverts->AddLeAdvertisingReport(
+ BTM_BLE_SCAN_RSP_EVT, addr_type, addr, ad, GetRssi(dev)));
+ }
+ }
+ }
+ }
+ }
+
+ if (le_scan_enable_) send_event_(std::move(le_adverts));
+}
+
+void DualModeController::PageScan() {
+ // Inquiry modes for specifiying inquiry result formats.
+ static const uint8_t kStandardInquiry = 0x00;
+ static const uint8_t kRssiInquiry = 0x01;
+ static const uint8_t kExtendedOrRssiInquiry = 0x02;
+
+ switch (inquiry_mode_) {
+ case (kStandardInquiry): {
+ std::unique_ptr<EventPacket> inquiry_result =
+ EventPacket::CreateInquiryResultEvent();
+ for (size_t dev = 0; dev < devices_.size(); dev++)
+ // Scan for devices
+ if (devices_[dev]->IsPageScanAvailable()) {
+ bool result_added = inquiry_result->AddInquiryResult(
+ devices_[dev]->GetBtAddress(),
+ devices_[dev]->GetPageScanRepetitionMode(),
+ devices_[dev]->GetDeviceClass(), devices_[dev]->GetClockOffset());
+ if (!result_added) {
+ send_event_(std::move(inquiry_result));
+ inquiry_result = EventPacket::CreateInquiryResultEvent();
+ result_added = inquiry_result->AddInquiryResult(
+ devices_[dev]->GetBtAddress(),
+ devices_[dev]->GetPageScanRepetitionMode(),
+ devices_[dev]->GetDeviceClass(),
+ devices_[dev]->GetClockOffset());
+ CHECK(result_added);
+ }
+ }
+ } break;
+
+ case (kRssiInquiry):
+ LOG_INFO(LOG_TAG, "RSSI Inquiry Mode currently not supported.");
+ break;
+
+ case (kExtendedOrRssiInquiry):
+ for (size_t dev = 0; dev < devices_.size(); dev++)
+ if (devices_[dev]->IsPageScanAvailable()) {
+ send_event_(EventPacket::CreateExtendedInquiryResultEvent(
+ devices_[dev]->GetBtAddress(),
+ devices_[dev]->GetPageScanRepetitionMode(),
+ devices_[dev]->GetDeviceClass(), devices_[dev]->GetClockOffset(),
+ GetRssi(dev), devices_[dev]->GetExtendedInquiryData()));
+ }
+ break;
+ }
+}
+
void DualModeController::StartTimer() {
LOG_ERROR(LOG_TAG, "StartTimer");
timer_tick_task_ = schedule_periodic_task_(
@@ -240,43 +420,49 @@
timer_tick_task_ = kInvalidTaskId;
}
-void DualModeController::TestChannelClear(
- UNUSED_ATTR const vector<std::string>& args) {
- LogCommand("TestChannel Clear");
- test_channel_state_ = kNone;
+void DualModeController::SetEventDelay(int64_t delay) {
+ if (delay < 0) delay = 0;
}
-void DualModeController::TestChannelDiscover(
- UNUSED_ATTR const vector<std::string>& args) {
- LogCommand("TestChannel Discover");
- /* TODO: Replace with adding devices */
- /*
+void DualModeController::TestChannelAdd(const vector<std::string>& args) {
+ LogCommand("TestChannel 'add'");
- for (size_t i = 0; i < args.size() - 1; i += 2)
- SendExtendedInquiryResult(args[i], args[i + 1]);
- */
+ std::shared_ptr<Device> new_dev = DeviceFactory::Create(args);
+
+ if (new_dev == NULL) {
+ LOG_ERROR(LOG_TAG, "TestChannel 'add' failed!");
+ return;
+ }
+
+ devices_.push_back(new_dev);
}
-void DualModeController::TestChannelTimeoutAll(
- UNUSED_ATTR const vector<std::string>& args) {
- LogCommand("TestChannel Timeout All");
- test_channel_state_ = kTimeoutAll;
+void DualModeController::TestChannelDel(const vector<std::string>& args) {
+ LogCommand("TestChannel 'del'");
+
+ size_t dev_index = std::stoi(args[0]);
+
+ if (dev_index >= devices_.size()) {
+ LOG_INFO(LOG_TAG, "TestChannel 'del': index %d out of range!",
+ static_cast<int>(dev_index));
+ } else {
+ devices_.erase(devices_.begin() + dev_index);
+ }
}
-void DualModeController::TestChannelSetEventDelay(
- const vector<std::string>& args UNUSED_ATTR) {
- LogCommand("TestChannel Set Event Delay");
- test_channel_state_ = kDelayedResponse;
+void DualModeController::TestChannelList(
+ UNUSED_ATTR const vector<std::string>& args) const {
+ LogCommand("TestChannel 'list'");
+ LOG_INFO(LOG_TAG, "Devices:");
+ for (size_t dev = 0; dev < devices_.size(); dev++) {
+ LOG_INFO(LOG_TAG, "%d:", static_cast<int>(dev));
+ devices_[dev]->ToString();
+ }
}
-void DualModeController::TestChannelClearEventDelay(
- UNUSED_ATTR const vector<std::string>& args) {
- LogCommand("TestChannel Clear Event Delay");
- test_channel_state_ = kNone;
-}
-
-void DualModeController::HciReset(UNUSED_ATTR const vector<uint8_t>& args) {
+void DualModeController::HciReset(const vector<uint8_t>& args) {
LogCommand("Reset");
+ CHECK(args[0] == 0); // No arguments
state_ = kStandby;
if (timer_tick_task_ != kInvalidTaskId) {
LOG_INFO(LOG_TAG, "The timer was already running!");
@@ -288,9 +474,9 @@
SendCommandCompleteSuccess(HCI_RESET);
}
-void DualModeController::HciReadBufferSize(
- UNUSED_ATTR const vector<uint8_t>& args) {
+void DualModeController::HciReadBufferSize(const vector<uint8_t>& args) {
LogCommand("Read Buffer Size");
+ CHECK(args[0] == 0); // No arguments
std::unique_ptr<EventPacket> command_complete =
EventPacket::CreateCommandCompleteReadBufferSize(
kSuccessStatus, properties_.GetAclDataPacketSize(),
@@ -301,15 +487,16 @@
send_event_(std::move(command_complete));
}
-void DualModeController::HciHostBufferSize(
- UNUSED_ATTR const vector<uint8_t>& args) {
+void DualModeController::HciHostBufferSize(const vector<uint8_t>& args) {
LogCommand("Host Buffer Size");
+ CHECK(args[0] == 7); // No arguments
SendCommandCompleteSuccess(HCI_HOST_BUFFER_SIZE);
}
void DualModeController::HciReadLocalVersionInformation(
- UNUSED_ATTR const vector<uint8_t>& args) {
+ const vector<uint8_t>& args) {
LogCommand("Read Local Version Information");
+ CHECK(args[0] == 0); // No arguments
std::unique_ptr<EventPacket> command_complete =
EventPacket::CreateCommandCompleteReadLocalVersionInformation(
kSuccessStatus, properties_.GetVersion(), properties_.GetRevision(),
@@ -318,8 +505,8 @@
send_event_(std::move(command_complete));
}
-void DualModeController::HciReadBdAddr(
- UNUSED_ATTR const vector<uint8_t>& args) {
+void DualModeController::HciReadBdAddr(const vector<uint8_t>& args) {
+ CHECK(args[0] == 0); // No arguments
std::unique_ptr<EventPacket> command_complete =
EventPacket::CreateCommandCompleteReadBdAddr(kSuccessStatus,
properties_.GetAddress());
@@ -327,8 +514,9 @@
}
void DualModeController::HciReadLocalSupportedCommands(
- UNUSED_ATTR const vector<uint8_t>& args) {
+ const vector<uint8_t>& args) {
LogCommand("Read Local Supported Commands");
+ CHECK(args[0] == 0); // No arguments
std::unique_ptr<EventPacket> command_complete =
EventPacket::CreateCommandCompleteReadLocalSupportedCommands(
kSuccessStatus, properties_.GetLocalSupportedCommands());
@@ -336,8 +524,9 @@
}
void DualModeController::HciReadLocalSupportedCodecs(
- UNUSED_ATTR const vector<uint8_t>& args) {
+ const vector<uint8_t>& args) {
LogCommand("Read Local Supported Codecs");
+ CHECK(args[0] == 0); // No arguments
std::unique_ptr<EventPacket> command_complete =
EventPacket::CreateCommandCompleteReadLocalSupportedCodecs(
kSuccessStatus, properties_.GetSupportedCodecs(),
@@ -464,49 +653,21 @@
}
void DualModeController::HciInquiry(const vector<uint8_t>& args) {
- // Fake inquiry response for a fake device.
- const EventPacket::PageScanRepetitionMode kPageScanRepetitionMode =
- EventPacket::kR0;
- const uint32_t kClassOfDevice = 0x030201;
- const uint16_t kClockOffset = 513;
- BtAddress other_addr;
- other_addr.FromVector(kOtherDeviceBdAddress);
-
LogCommand("Inquiry");
+ CHECK(args.size() == 6);
state_ = kInquiry;
SendCommandStatusSuccess(HCI_INQUIRY);
- switch (inquiry_mode_) {
- case (kStandardInquiry): {
- std::unique_ptr<EventPacket> inquiry_result_evt =
- EventPacket::CreateInquiryResultEvent(other_addr,
- kPageScanRepetitionMode,
- kClassOfDevice, kClockOffset);
- send_event_(std::move(inquiry_result_evt));
- /* TODO: Return responses from modeled devices */
- } break;
+ inquiry_lap_[0] = args[1];
+ inquiry_lap_[1] = args[2];
+ inquiry_lap_[2] = args[3];
- case (kRssiInquiry):
- LOG_INFO(LOG_TAG, "RSSI Inquiry Mode currently not supported.");
- break;
-
- case (kExtendedOrRssiInquiry): {
- const std::string name = "Foobar";
- vector<uint8_t> extended_inquiry_data = {
- static_cast<uint8_t>(name.length() + 1), 0x09};
-
- for (size_t i = 0; i < name.length(); i++)
- extended_inquiry_data.push_back(name[i]);
- extended_inquiry_data.push_back('\0');
-
- uint8_t rssi = static_cast<uint8_t>(-20);
- send_event_(EventPacket::CreateExtendedInquiryResultEvent(
- other_addr, kPageScanRepetitionMode, kClassOfDevice, kClockOffset,
- rssi, extended_inquiry_data));
- /* TODO: Return responses from modeled devices */
- } break;
- }
AddControllerEvent(std::chrono::milliseconds(args[4] * 1280),
[this]() { DualModeController::InquiryTimeout(); });
+
+ if (args[5] > 0) {
+ inquiry_responses_limited_ = true;
+ inquiry_num_responses_ = args[5];
+ }
}
void DualModeController::HciInquiryCancel(
@@ -521,6 +682,7 @@
LOG_INFO(LOG_TAG, "InquiryTimer fired");
if (state_ == kInquiry) {
state_ = kStandby;
+ inquiry_responses_limited_ = false;
send_event_(EventPacket::CreateInquiryCompleteEvent(kSuccessStatus));
}
}
@@ -530,7 +692,10 @@
LogCommand("Delete Stored Link Key");
/* Check the last octect in |args|. If it is 0, delete only the link key for
* the given BD_ADDR. If is is 1, delete all stored link keys. */
- SendCommandCompleteOnlyStatus(HCI_INQUIRY_CANCEL, kUnknownHciCommand);
+ uint16_t deleted_keys = 1;
+
+ send_event_(EventPacket::CreateCommandCompleteDeleteStoredLinkKey(
+ kSuccessStatus, deleted_keys));
}
void DualModeController::HciRemoteNameRequest(
@@ -597,20 +762,76 @@
void DualModeController::HciLeSetScanEnable(const vector<uint8_t>& args) {
LogCommand("LE SetScanEnable");
CHECK(args.size() == 3);
- CHECK(args[0] == 2);
le_scan_enable_ = args[1];
filter_duplicates_ = args[2];
SendCommandCompleteSuccess(HCI_BLE_WRITE_SCAN_ENABLE);
}
-void DualModeController::HciLeReadWhiteListSize(
- UNUSED_ATTR const vector<uint8_t>& args) {
+void DualModeController::HciLeCreateConnection(const vector<uint8_t>& args) {
+ LogCommand("LE CreateConnection");
+ le_connect_ = true;
+ le_scan_interval_ = args[1] | (args[2] << 8);
+ le_scan_window_ = args[3] | (args[4] << 8);
+ initiator_filter_policy_ = args[5];
+
+ if (initiator_filter_policy_ == 0) { // White list not used
+ peer_address_type_ = args[6];
+ vector<uint8_t> peer_addr = {args[7], args[8], args[9],
+ args[10], args[11], args[12]};
+ peer_address_.FromVector(peer_addr);
+ }
+
+ SendCommandStatusSuccess(HCI_BLE_CREATE_LL_CONN);
+}
+
+void DualModeController::HciLeConnectionCancel(const vector<uint8_t>& args) {
+ LogCommand("LE ConnectionCancel");
+ CHECK(args[0] == 0); // No arguments
+ le_connect_ = false;
+ SendCommandStatusSuccess(HCI_BLE_CREATE_CONN_CANCEL);
+}
+
+void DualModeController::HciLeReadWhiteListSize(const vector<uint8_t>& args) {
+ LogCommand("LE ReadWhiteListSize");
+ CHECK(args[0] == 0); // No arguments
std::unique_ptr<EventPacket> command_complete =
EventPacket::CreateCommandCompleteLeReadWhiteListSize(
kSuccessStatus, properties_.GetLeWhiteListSize());
send_event_(std::move(command_complete));
}
+void DualModeController::HciLeReadRemoteUsedFeaturesB(uint16_t handle) {
+ uint64_t features;
+ LogCommand("LE ReadRemoteUsedFeatures Bottom half");
+
+ for (size_t i = 0; i < connections_.size(); i++)
+ if (*connections_[i] == handle)
+ // TODO:
+ // features = connections_[i]->GetDevice()->GetUsedFeatures();
+ features = 0xffffffffffffffff;
+
+ std::unique_ptr<EventPacket> event =
+ EventPacket::CreateLeRemoteUsedFeaturesEvent(kSuccessStatus, handle,
+ features);
+ send_event_(std::move(event));
+}
+
+void DualModeController::HciLeReadRemoteUsedFeatures(
+ const vector<uint8_t>& args) {
+ LogCommand("LE ReadRemoteUsedFeatures");
+ CHECK(args.size() == 3);
+
+ uint16_t handle = args[1] | (args[2] << 8);
+
+ AddConnectionAction(
+ [this, handle]() {
+ DualModeController::HciLeReadRemoteUsedFeaturesB(handle);
+ },
+ handle);
+
+ SendCommandStatusSuccess(HCI_BLE_READ_REMOTE_FEAT);
+}
+
void DualModeController::HciLeRand(UNUSED_ATTR const vector<uint8_t>& args) {
uint64_t random_val = rand();
std::unique_ptr<EventPacket> command_complete =
@@ -634,6 +855,12 @@
void DualModeController::HciBleVendorCap(
UNUSED_ATTR const vector<uint8_t>& args) {
+ vector<uint8_t> caps = properties_.GetLeVendorCap();
+ if (caps.size() == 0) {
+ SendCommandCompleteOnlyStatus(HCI_BLE_VENDOR_CAP_OCF, kUnknownHciCommand);
+ return;
+ }
+
std::unique_ptr<EventPacket> command_complete =
EventPacket::CreateCommandCompleteLeVendorCap(
kSuccessStatus, properties_.GetLeVendorCap());
@@ -651,10 +878,9 @@
kUnknownHciCommand);
}
-void DualModeController::HciBleVendor157(
+void DualModeController::HciBleAdvertisingFilter(
UNUSED_ATTR const vector<uint8_t>& args) {
- SendCommandCompleteOnlyStatus(HCI_GRP_VENDOR_SPECIFIC | 0x157,
- kUnknownHciCommand);
+ SendCommandCompleteOnlyStatus(HCI_BLE_ADV_FILTER_OCF, kUnknownHciCommand);
}
void DualModeController::HciBleEnergyInfo(
@@ -668,80 +894,28 @@
kUnknownHciCommand);
}
-DualModeController::Properties::Properties(const std::string& file_name)
- : acl_data_packet_size_(1024),
- sco_data_packet_size_(255),
- num_acl_data_packets_(10),
- num_sco_data_packets_(10),
- version_(4),
- revision_(1),
- lmp_pal_version_(0),
- manufacturer_name_(0),
- lmp_pal_subversion_(0),
- le_data_packet_length_(27),
- num_le_data_packets_(15),
- le_white_list_size_(15) {
- std::string properties_raw;
-
- local_extended_features_ = {0xffffffffffffffff, 0x7};
-
- CHECK(address_.FromString("01:02:03:04:05:06"));
- local_name_ = "DefaultName";
-
- supported_codecs_ = {1};
- vendor_specific_codecs_ = {};
-
- for (int i = 0; i < 64; i++) local_supported_commands_.push_back(0xff);
-
- le_supported_features_ = 0x1f;
- le_supported_states_ = 0x3ffffffffff;
- le_vendor_cap_ = {0x05, 0x01, 0x00, 0x04, 0x80, 0x01, 0x10,
- 0x01, 0x60, 0x00, 0x0a, 0x00, 0x01, 0x01};
-
- LOG_INFO(LOG_TAG, "Reading controller properties from %s.",
- file_name.c_str());
- if (!base::ReadFileToString(base::FilePath(file_name), &properties_raw)) {
- LOG_ERROR(LOG_TAG, "Error reading controller properties from file.");
- return;
- }
-
- std::unique_ptr<base::Value> properties_value_ptr =
- base::JSONReader::Read(properties_raw);
- if (properties_value_ptr.get() == nullptr)
- LOG_INFO(LOG_TAG,
- "Error controller properties may consist of ill-formed JSON.");
-
- // Get the underlying base::Value object, which is of type
- // base::Value::TYPE_DICTIONARY, and read it into member variables.
- base::Value& properties_dictionary = *(properties_value_ptr.get());
- base::JSONValueConverter<DualModeController::Properties> converter;
-
- if (!converter.Convert(properties_dictionary, this))
- LOG_INFO(LOG_TAG,
- "Error converting JSON properties into Properties object.");
+void DualModeController::HciReadLoopbackMode(const vector<uint8_t>& args) {
+ CHECK(args[0] == 0); // No arguments
+ std::unique_ptr<EventPacket> command_complete =
+ EventPacket::CreateCommandCompleteReadLoopbackMode(kSuccessStatus,
+ loopback_mode_);
+ send_event_(std::move(command_complete));
}
-// static
-void DualModeController::Properties::RegisterJSONConverter(
- base::JSONValueConverter<DualModeController::Properties>* converter) {
-// TODO(dennischeng): Use RegisterIntField() here?
-#define REGISTER_UINT8_T(field_name, field) \
- converter->RegisterCustomField<uint8_t>( \
- field_name, &DualModeController::Properties::field, &ParseUint8t);
-#define REGISTER_UINT16_T(field_name, field) \
- converter->RegisterCustomField<uint16_t>( \
- field_name, &DualModeController::Properties::field, &ParseUint16t);
- REGISTER_UINT16_T("AclDataPacketSize", acl_data_packet_size_);
- REGISTER_UINT8_T("ScoDataPacketSize", sco_data_packet_size_);
- REGISTER_UINT16_T("NumAclDataPackets", num_acl_data_packets_);
- REGISTER_UINT16_T("NumScoDataPackets", num_sco_data_packets_);
- REGISTER_UINT8_T("Version", version_);
- REGISTER_UINT16_T("Revision", revision_);
- REGISTER_UINT8_T("LmpPalVersion", lmp_pal_version_);
- REGISTER_UINT16_T("ManufacturerName", manufacturer_name_);
- REGISTER_UINT16_T("LmpPalSubversion", lmp_pal_subversion_);
-#undef REGISTER_UINT8_T
-#undef REGISTER_UINT16_T
+void DualModeController::HciWriteLoopbackMode(const vector<uint8_t>& args) {
+ CHECK(args[0] == 1);
+ loopback_mode_ = args[1];
+ // ACL channel
+ uint16_t acl_handle = 0x123;
+ send_event_(EventPacket::CreateConnectionCompleteEvent(
+ kSuccessStatus, acl_handle, properties_.GetAddress(), HCI_LINK_TYPE_ACL,
+ false));
+ // SCO channel
+ uint16_t sco_handle = 0x345;
+ send_event_(EventPacket::CreateConnectionCompleteEvent(
+ kSuccessStatus, sco_handle, properties_.GetAddress(), HCI_LINK_TYPE_SCO,
+ false));
+ SendCommandCompleteSuccess(HCI_WRITE_LOOPBACK_MODE);
}
} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/event_packet.cc b/vendor_libs/test_vendor_lib/src/event_packet.cc
index 78a0435..482b47f 100644
--- a/vendor_libs/test_vendor_lib/src/event_packet.cc
+++ b/vendor_libs/test_vendor_lib/src/event_packet.cc
@@ -1,18 +1,18 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#define LOG_TAG "event_packet"
@@ -79,6 +79,38 @@
return evt_ptr;
}
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.19
+std::unique_ptr<EventPacket> EventPacket::CreateNumberOfCompletedPacketsEvent(
+ uint16_t handle, uint16_t num_completed_packets) {
+ std::unique_ptr<EventPacket> evt_ptr = std::unique_ptr<EventPacket>(
+ new EventPacket(HCI_NUM_COMPL_DATA_PKTS_EVT));
+
+ CHECK(evt_ptr->AddPayloadOctets1(0)); // Number of handles.
+ evt_ptr->AddCompletedPackets(handle, num_completed_packets);
+
+ return evt_ptr;
+}
+
+void EventPacket::AddCompletedPackets(uint16_t handle,
+ uint16_t num_completed_packets) {
+ CHECK(AddPayloadOctets2(handle));
+ CHECK(AddPayloadOctets2(num_completed_packets));
+ CHECK(IncrementPayloadCounter(1)); // Increment the number of handles.
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.10
+std::unique_ptr<EventPacket>
+EventPacket::CreateCommandCompleteDeleteStoredLinkKey(
+ uint8_t status, uint16_t num_keys_deleted) {
+ std::unique_ptr<EventPacket> evt_ptr =
+ EventPacket::CreateCommandCompleteOnlyStatusEvent(
+ HCI_DELETE_STORED_LINK_KEY, status);
+
+ CHECK(evt_ptr->AddPayloadOctets2(num_keys_deleted));
+
+ return evt_ptr;
+}
+
// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.12
std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteReadLocalName(
uint8_t status, const std::string& local_name) {
@@ -189,31 +221,34 @@
return evt_ptr;
}
-std::unique_ptr<EventPacket> EventPacket::CreateInquiryResultEvent(
- const BtAddress& address,
- const PageScanRepetitionMode page_scan_repetition_mode,
- uint32_t class_of_device, uint16_t clock_offset) {
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.6.1
+std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteReadLoopbackMode(
+ uint8_t status, uint8_t mode) {
std::unique_ptr<EventPacket> evt_ptr =
- std::unique_ptr<EventPacket>(new EventPacket(HCI_INQUIRY_RESULT_EVT));
-
- CHECK(evt_ptr->AddPayloadOctets1(1)); // Start with a single response
-
- CHECK(evt_ptr->AddPayloadBtAddress(address));
- CHECK(evt_ptr->AddPayloadOctets1(page_scan_repetition_mode));
- CHECK(evt_ptr->AddPayloadOctets2(kReservedZero));
- CHECK(evt_ptr->AddPayloadOctets3(class_of_device));
- CHECK(!(clock_offset & 0x8000));
- CHECK(evt_ptr->AddPayloadOctets2(clock_offset));
+ EventPacket::CreateCommandCompleteOnlyStatusEvent(HCI_READ_LOOPBACK_MODE,
+ status);
+ CHECK(evt_ptr->AddPayloadOctets1(mode));
return evt_ptr;
}
-void EventPacket::AddInquiryResult(
- const BtAddress& address,
- const PageScanRepetitionMode page_scan_repetition_mode,
- uint32_t class_of_device, uint16_t clock_offset) {
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.2
+std::unique_ptr<EventPacket> EventPacket::CreateInquiryResultEvent() {
+ std::unique_ptr<EventPacket> evt_ptr =
+ std::unique_ptr<EventPacket>(new EventPacket(HCI_INQUIRY_RESULT_EVT));
+
+ CHECK(evt_ptr->AddPayloadOctets1(0)); // Start with no responses
+ return evt_ptr;
+}
+
+bool EventPacket::AddInquiryResult(const BtAddress& address,
+ uint8_t page_scan_repetition_mode,
+ uint32_t class_of_device,
+ uint16_t clock_offset) {
CHECK(GetEventCode() == HCI_INQUIRY_RESULT_EVT);
+ if (!CanAddPayloadOctets(14)) return false;
+
CHECK(IncrementPayloadCounter(1)); // Increment the number of responses
CHECK(AddPayloadBtAddress(address));
@@ -222,11 +257,40 @@
CHECK(AddPayloadOctets3(class_of_device));
CHECK(!(clock_offset & 0x8000));
CHECK(AddPayloadOctets2(clock_offset));
+ return true;
}
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.3
+std::unique_ptr<EventPacket> EventPacket::CreateConnectionCompleteEvent(
+ uint8_t status, uint16_t handle, const BtAddress& address,
+ uint8_t link_type, bool encryption_enabled) {
+ std::unique_ptr<EventPacket> evt_ptr =
+ std::unique_ptr<EventPacket>(new EventPacket(HCI_CONNECTION_COMP_EVT));
+
+ CHECK(evt_ptr->AddPayloadOctets1(status));
+ CHECK((handle & 0xf000) == 0); // Handles are 12-bit values.
+ CHECK(evt_ptr->AddPayloadOctets2(handle));
+ CHECK(evt_ptr->AddPayloadBtAddress(address));
+ CHECK(evt_ptr->AddPayloadOctets1(link_type));
+ CHECK(evt_ptr->AddPayloadOctets1(encryption_enabled ? 1 : 0));
+
+ return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.25
+std::unique_ptr<EventPacket> EventPacket::CreateLoopbackCommandEvent(
+ uint16_t opcode, const vector<uint8_t>& payload) {
+ std::unique_ptr<EventPacket> evt_ptr =
+ std::unique_ptr<EventPacket>(new EventPacket(HCI_LOOPBACK_COMMAND_EVT));
+ CHECK(evt_ptr->AddPayloadOctets2(opcode));
+ for (const auto& payload_byte : payload) // Fill the packet.
+ evt_ptr->AddPayloadOctets1(payload_byte);
+ return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.38
std::unique_ptr<EventPacket> EventPacket::CreateExtendedInquiryResultEvent(
- const BtAddress& address,
- const PageScanRepetitionMode page_scan_repetition_mode,
+ const BtAddress& address, uint8_t page_scan_repetition_mode,
uint32_t class_of_device, uint16_t clock_offset, uint8_t rssi,
const vector<uint8_t>& extended_inquiry_response) {
std::unique_ptr<EventPacket> evt_ptr = std::unique_ptr<EventPacket>(
@@ -248,6 +312,75 @@
return evt_ptr;
}
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.1
+std::unique_ptr<EventPacket> EventPacket::CreateLeConnectionCompleteEvent(
+ uint8_t status, uint16_t handle, uint8_t role, uint8_t peer_address_type,
+ const BtAddress& peer, uint16_t interval, uint16_t latency,
+ uint16_t supervision_timeout) {
+ std::unique_ptr<EventPacket> evt_ptr =
+ std::unique_ptr<EventPacket>(new EventPacket(HCI_BLE_EVENT));
+
+ CHECK(evt_ptr->AddPayloadOctets1(HCI_BLE_CONN_COMPLETE_EVT));
+ CHECK(evt_ptr->AddPayloadOctets1(status));
+ CHECK(evt_ptr->AddPayloadOctets2(handle));
+ CHECK(evt_ptr->AddPayloadOctets1(role));
+ CHECK(evt_ptr->AddPayloadOctets1(peer_address_type));
+ CHECK(evt_ptr->AddPayloadBtAddress(peer));
+ CHECK(evt_ptr->AddPayloadOctets2(interval));
+ CHECK(evt_ptr->AddPayloadOctets2(latency));
+ CHECK(evt_ptr->AddPayloadOctets2(supervision_timeout));
+ CHECK(evt_ptr->AddPayloadOctets1(
+ 0x00)); // Master Clock Accuracy (unused for master)
+
+ return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.2
+std::unique_ptr<EventPacket> EventPacket::CreateLeAdvertisingReportEvent() {
+ std::unique_ptr<EventPacket> evt_ptr =
+ std::unique_ptr<EventPacket>(new EventPacket(HCI_BLE_EVENT));
+
+ CHECK(evt_ptr->AddPayloadOctets1(HCI_BLE_ADV_PKT_RPT_EVT));
+
+ CHECK(evt_ptr->AddPayloadOctets1(0)); // Start with an empty report
+
+ return evt_ptr;
+}
+
+bool EventPacket::AddLeAdvertisingReport(uint8_t event_type, uint8_t addr_type,
+ const BtAddress& addr,
+ const vector<uint8_t>& data,
+ uint8_t rssi) {
+ if (!CanAddPayloadOctets(10 + data.size())) return false;
+
+ CHECK(GetEventCode() == HCI_BLE_EVENT);
+
+ CHECK(IncrementPayloadCounter(2)); // Increment the number of responses
+
+ CHECK(AddPayloadOctets1(event_type));
+ CHECK(AddPayloadOctets1(addr_type));
+ CHECK(AddPayloadBtAddress(addr));
+ CHECK(AddPayloadOctets1(data.size()));
+ CHECK(AddPayloadOctets(data.size(), data));
+ CHECK(AddPayloadOctets1(rssi));
+ return true;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.4
+std::unique_ptr<EventPacket> EventPacket::CreateLeRemoteUsedFeaturesEvent(
+ uint8_t status, uint16_t handle, uint64_t features) {
+ std::unique_ptr<EventPacket> evt_ptr =
+ std::unique_ptr<EventPacket>(new EventPacket(HCI_BLE_EVENT));
+
+ CHECK(evt_ptr->AddPayloadOctets1(HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT));
+
+ CHECK(evt_ptr->AddPayloadOctets1(status));
+ CHECK(evt_ptr->AddPayloadOctets2(handle));
+ CHECK(evt_ptr->AddPayloadOctets8(features));
+
+ return evt_ptr;
+}
+
// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.2
std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteLeReadBufferSize(
uint8_t status, uint16_t hc_le_data_packet_length,
diff --git a/vendor_libs/test_vendor_lib/src/hci_packet.cc b/vendor_libs/test_vendor_lib/src/hci_packet.cc
new file mode 100644
index 0000000..219c187
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/hci_packet.cc
@@ -0,0 +1,125 @@
+#include "hci_packet.h"
+
+namespace test_vendor_lib {
+
+// Iterator Functions
+Iterator::Iterator(std::shared_ptr<HciPacket> packet, size_t i) {
+ hci_packet_ = packet;
+ index_ = i;
+}
+
+Iterator::Iterator(const Iterator& itr) { *this = itr; }
+
+Iterator::operator bool() const { return hci_packet_ != nullptr; }
+
+Iterator Iterator::operator+(size_t offset) {
+ auto itr(*this);
+
+ return itr += offset;
+}
+
+Iterator& Iterator::operator+=(size_t offset) {
+ size_t new_offset = index_ + offset;
+ index_ = new_offset >= hci_packet_->get_length() ? hci_packet_->get_length()
+ : new_offset;
+ return *this;
+}
+
+Iterator Iterator::operator++(int) {
+ auto itr(*this);
+ index_++;
+
+ if (index_ >= hci_packet_->get_length()) index_ = hci_packet_->get_length();
+
+ return itr;
+}
+
+Iterator& Iterator::operator++() {
+ index_++;
+
+ if (index_ >= hci_packet_->get_length()) index_ = hci_packet_->get_length();
+
+ return *this;
+}
+
+Iterator Iterator::operator-(size_t offset) {
+ auto itr(*this);
+
+ return itr -= offset;
+}
+
+int Iterator::operator-(Iterator& itr) { return index_ - itr.index_; }
+
+Iterator& Iterator::operator-=(size_t offset) {
+ index_ = offset > index_ ? 0 : index_ - offset;
+
+ return *this;
+}
+
+Iterator Iterator::operator--(int) {
+ auto itr(*this);
+ if (index_ != 0) index_--;
+
+ return itr;
+}
+
+Iterator& Iterator::operator--() {
+ if (index_ != 0) index_--;
+
+ return *this;
+}
+
+Iterator& Iterator::operator=(const Iterator& itr) {
+ hci_packet_ = itr.hci_packet_;
+ index_ = itr.index_;
+
+ return *this;
+}
+
+bool Iterator::operator==(Iterator& itr) {
+ return ((hci_packet_ == itr.hci_packet_) && (index_ == itr.index_));
+}
+
+bool Iterator::operator!=(Iterator& itr) { return !(*this == itr); }
+
+bool Iterator::operator<(Iterator& itr) {
+ return ((hci_packet_ == itr.hci_packet_) && (index_ < itr.index_));
+}
+
+bool Iterator::operator>(Iterator& itr) {
+ return ((hci_packet_ == itr.hci_packet_) && (index_ > itr.index_));
+}
+
+bool Iterator::operator<=(Iterator& itr) {
+ return ((hci_packet_ == itr.hci_packet_) && (index_ <= itr.index_));
+}
+
+bool Iterator::operator>=(Iterator& itr) {
+ return ((hci_packet_ == itr.hci_packet_) && (index_ >= itr.index_));
+}
+
+uint8_t& Iterator::operator*() const {
+ CHECK(index_ != hci_packet_->get_length());
+
+ return hci_packet_->get_at_index(index_);
+}
+
+uint8_t* Iterator::operator->() const {
+ return &hci_packet_->get_at_index(index_);
+}
+
+// BtPacket Functions
+Iterator HciPacket::get_begin() {
+ Iterator itr(shared_from_this(), 0);
+
+ return itr;
+}
+
+Iterator HciPacket::get_end() {
+ Iterator itr(shared_from_this(), get_length());
+
+ return itr;
+}
+
+uint8_t HciPacket::operator[](size_t i) { return get_at_index(i); }
+}; // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/keyboard.cc b/vendor_libs/test_vendor_lib/src/keyboard.cc
new file mode 100644
index 0000000..74caf41
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/keyboard.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keyboard"
+
+#include "keyboard.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+Keyboard::Keyboard() {
+ advertising_type_ = BTM_BLE_CONNECT_EVT;
+ adv_data_ = {0x11, // Length
+ BTM_BLE_AD_TYPE_NAME_CMPL,
+ 'g',
+ 'D',
+ 'e',
+ 'v',
+ 'i',
+ 'c',
+ 'e',
+ '-',
+ 'k',
+ 'e',
+ 'y',
+ 'b',
+ 'o',
+ 'a',
+ 'r',
+ 'd',
+ 0x03, // Length
+ 0x19,
+ 0xC1,
+ 0x03,
+ 0x03, // Length
+ 0x03,
+ 0x12,
+ 0x18,
+ 0x02, // Length
+ BTM_BLE_AD_TYPE_FLAG,
+ BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG};
+
+ scan_data_ = {0x04, // Length
+ BTM_BLE_AD_TYPE_NAME_SHORT, 'k', 'e', 'y'};
+}
+
+std::string Keyboard::GetTypeString() const { return "keyboard"; }
+
+void Keyboard::Initialize(const vector<std::string>& args) {
+ if (args.size() < 2) return;
+
+ BtAddress addr;
+ if (addr.FromString(args[1])) SetBtAddress(addr);
+
+ if (args.size() < 3) return;
+
+ SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+}
+
+bool Keyboard::LeConnect() { return true; }
+
+bool Keyboard::IsPageScanAvailable() const { return false; }
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/l2cap_packet.cc b/vendor_libs/test_vendor_lib/src/l2cap_packet.cc
index 652f3c0..ad17b48 100644
--- a/vendor_libs/test_vendor_lib/src/l2cap_packet.cc
+++ b/vendor_libs/test_vendor_lib/src/l2cap_packet.cc
@@ -1,20 +1,19 @@
-/******************************************************************************
+/*
+ * Copyright 2017 The Android Open Source Project
*
- * Copyright (C) 2017 Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#define LOG_TAG "l2cap_packet"
#include "l2cap_packet.h"
@@ -25,17 +24,18 @@
namespace test_vendor_lib {
-const int kL2capHeaderLength = 4;
+const size_t kL2capHeaderLength = 4;
+const size_t kSduFirstHeaderLength = 8;
+const size_t kSduStandardHeaderLength = 6;
+const size_t kFcsBytes = 2;
const uint16_t kSduTxSeqBits = 0x007E;
-const int kSduStandardHeaderLength = 6;
-const int kSduFirstHeaderLength = 8;
const uint8_t kSduFirstReqseq = 0x40;
const uint8_t kSduContinuationReqseq = 0xC0;
const uint8_t kSduEndReqseq = 0x80;
-std::unique_ptr<L2capPacket> L2capPacket::assemble(
- const std::vector<L2capSdu>& sdu_packets) {
- std::unique_ptr<L2capPacket> built_l2cap_packet(new L2capPacket());
+std::shared_ptr<L2capPacket> L2capPacket::assemble(
+ const std::vector<std::shared_ptr<L2capSdu> >& sdu_packets) {
+ std::shared_ptr<L2capPacket> built_l2cap_packet(new L2capPacket());
uint16_t l2cap_payload_length = 0;
uint16_t first_packet_channel_id = 0;
uint16_t total_expected_l2cap_length;
@@ -45,17 +45,18 @@
LOG_DEBUG(LOG_TAG, "%s: No SDU received.", __func__);
return nullptr;
}
- if (sdu_packets.size() == 1 && !L2capSdu::is_complete_l2cap(sdu_packets[0])) {
+ if (sdu_packets.size() == 1 &&
+ !L2capSdu::is_complete_l2cap(*sdu_packets[0])) {
LOG_DEBUG(LOG_TAG, "%s: Unsegmented SDU has incorrect SAR bits.", __func__);
return nullptr;
}
- first_packet_channel_id = sdu_packets[0].get_channel_id();
+ first_packet_channel_id = sdu_packets[0]->get_channel_id();
built_l2cap_packet->l2cap_packet_.resize(kL2capHeaderLength);
for (size_t i = 0; i < sdu_packets.size(); i++) {
- uint16_t payload_length = sdu_packets[i].get_payload_length();
+ uint16_t payload_length = sdu_packets[i]->get_payload_length();
// TODO(jruthe): Remove these checks when ACL packets have been
// implemented. Once those are done, that will be the only way to create
@@ -64,21 +65,21 @@
// Check the integrity of the packet length, if it is zero, it is invalid.
// The maximum size of a single, segmented L2CAP payload is 1016 bytes.
if ((payload_length <= 0) ||
- (payload_length != sdu_packets[i].get_vector_size() - 4)) {
+ (payload_length != sdu_packets[i]->get_vector_size() - 4)) {
LOG_DEBUG(LOG_TAG, "%s: SDU payload length incorrect.", __func__);
return nullptr;
}
- uint16_t fcs_check = sdu_packets[i].get_fcs();
+ uint16_t fcs_check = sdu_packets[i]->get_fcs();
- if (sdu_packets[i].calculate_fcs() != fcs_check) {
+ if (sdu_packets[i]->calculate_fcs() != fcs_check) {
LOG_DEBUG(LOG_TAG, "%s: SDU fcs is incorrect.", __func__);
return nullptr;
}
- uint16_t controls = sdu_packets[i].get_controls();
+ uint16_t controls = sdu_packets[i]->get_controls();
- if (sdu_packets[i].get_channel_id() != first_packet_channel_id) {
+ if (sdu_packets[i]->get_channel_id() != first_packet_channel_id) {
LOG_DEBUG(LOG_TAG, "%s: SDU CID does not match expected.", __func__);
return nullptr;
}
@@ -92,15 +93,15 @@
// control bits set to 01b and the ending segment must have them set to 10b.
// Meanwhile all segments in between the start and end must have the bits
// set to 11b.
- uint16_t starting_index;
+ size_t starting_index;
uint8_t txseq = controls & kSduTxSeqBits;
if (sdu_packets.size() > 1 && i == 0 &&
- !L2capSdu::is_starting_sdu(sdu_packets[i])) {
+ !L2capSdu::is_starting_sdu(*sdu_packets[i])) {
LOG_DEBUG(LOG_TAG, "%s: First segmented SDU has incorrect SAR bits.",
__func__);
return nullptr;
}
- if (i != 0 && L2capSdu::is_starting_sdu(sdu_packets[i])) {
+ if (i != 0 && L2capSdu::is_starting_sdu(*sdu_packets[i])) {
LOG_DEBUG(LOG_TAG,
"%s: SAR bits set to first segmented SDU on "
"non-starting SDU.",
@@ -112,7 +113,7 @@
return nullptr;
}
if (sdu_packets.size() > 1 && i == sdu_packets.size() - 1 &&
- !L2capSdu::is_ending_sdu(sdu_packets[i])) {
+ !L2capSdu::is_ending_sdu(*sdu_packets[i])) {
LOG_DEBUG(LOG_TAG, "%s: Final segmented SDU has incorrect SAR bits.",
__func__);
return nullptr;
@@ -121,9 +122,9 @@
// Subtract the control and fcs from every SDU payload length.
l2cap_payload_length += (payload_length - 4);
- if (L2capSdu::is_starting_sdu(sdu_packets[i])) {
+ if (L2capSdu::is_starting_sdu(*sdu_packets[i])) {
starting_index = kSduFirstHeaderLength;
- total_expected_l2cap_length = sdu_packets[i].get_total_l2cap_length();
+ total_expected_l2cap_length = sdu_packets[i]->get_total_l2cap_length();
// Subtract the additional two bytes from the first packet of a segmented
// SDU.
@@ -132,8 +133,8 @@
starting_index = kSduStandardHeaderLength;
}
- auto payload_begin = sdu_packets[i].get_payload_begin(starting_index);
- auto payload_end = sdu_packets[i].get_payload_end();
+ Iterator payload_begin = sdu_packets[i]->get_begin() + starting_index;
+ Iterator payload_end = sdu_packets[i]->get_end() - kFcsBytes;
built_l2cap_packet->l2cap_packet_.insert(
built_l2cap_packet->l2cap_packet_.end(), payload_begin, payload_end);
@@ -155,41 +156,19 @@
return built_l2cap_packet;
} // Assemble
-std::vector<uint8_t> L2capPacket::get_l2cap_payload() const {
- std::vector<uint8_t> payload_sub_vector;
- payload_sub_vector.clear();
-
- auto begin_payload_iter = get_l2cap_payload_begin();
- payload_sub_vector.insert(payload_sub_vector.end(), begin_payload_iter,
- l2cap_packet_.end());
-
- return payload_sub_vector;
-}
-
uint16_t L2capPacket::get_l2cap_cid() const {
return ((l2cap_packet_[3] << 8) | l2cap_packet_[2]);
}
-std::vector<uint8_t>::const_iterator L2capPacket::get_l2cap_payload_begin()
- const {
- return std::next(l2cap_packet_.begin(), kSduHeaderLength);
-}
-
-std::vector<uint8_t>::const_iterator L2capPacket::get_l2cap_payload_end()
- const {
- return l2cap_packet_.end();
-}
-
-std::vector<L2capSdu> L2capPacket::fragment(uint16_t maximum_sdu_size,
- uint8_t txseq,
- uint8_t reqseq) const {
- std::vector<L2capSdu> sdu;
+std::vector<std::shared_ptr<L2capSdu> > L2capPacket::fragment(
+ uint16_t maximum_sdu_size, uint8_t txseq, uint8_t reqseq) {
+ std::vector<std::shared_ptr<L2capSdu> > sdu;
if (!check_l2cap_packet()) return sdu;
std::vector<uint8_t> current_sdu;
- auto current_iter = get_l2cap_payload_begin();
- auto end_iter = get_l2cap_payload_end();
+ Iterator current_iter = get_begin() + kL2capHeaderLength;
+ Iterator end_iter = get_end();
size_t number_of_packets = ceil((l2cap_packet_.size() - kL2capHeaderLength) /
static_cast<float>(maximum_sdu_size));
@@ -230,8 +209,8 @@
return sdu;
}
- auto next_iter =
- std::next(current_iter, maximum_sdu_size - (kSduFirstHeaderLength + 2));
+ Iterator next_iter =
+ current_iter + (maximum_sdu_size - (kSduFirstHeaderLength + 2));
sdu.reserve(number_of_packets);
sdu.clear();
@@ -269,15 +248,9 @@
if (txseq > 0x3F) txseq = 0x00;
current_sdu.insert(current_sdu.end(), current_iter, next_iter);
-
current_iter = next_iter;
- next_iter =
- std::next(current_iter, maximum_sdu_size - kSduFirstHeaderLength);
-
- if (next_iter > end_iter) {
- next_iter = end_iter;
- }
+ next_iter = current_iter + (maximum_sdu_size - kSduFirstHeaderLength);
sdu.push_back(L2capSdu::L2capSduBuilder(std::move(current_sdu)));
}
@@ -317,4 +290,11 @@
return true;
}
+// HciPacket Functions
+size_t L2capPacket::get_length() { return l2cap_packet_.size(); }
+
+uint8_t& L2capPacket::get_at_index(size_t index) {
+ return l2cap_packet_[index];
+}
+
} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/l2cap_sdu.cc b/vendor_libs/test_vendor_lib/src/l2cap_sdu.cc
index e44d241..a93c1ad 100644
--- a/vendor_libs/test_vendor_lib/src/l2cap_sdu.cc
+++ b/vendor_libs/test_vendor_lib/src/l2cap_sdu.cc
@@ -1,20 +1,19 @@
-/******************************************************************************
+/*
+ * Copyright 2017 The Android Open Source Project
*
- * Copyright (C) 2017 Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "l2cap_sdu.h"
#include <base/logging.h>
@@ -57,11 +56,19 @@
0x4100, 0x81c1, 0x8081, 0x4040,
}; // lfsr_table
-L2capSdu::L2capSdu(std::vector<uint8_t> create_from) {
- sdu_data_ = std::move(create_from);
+L2capSdu::L2capSdu(std::vector<uint8_t>&& create_from) {
+ sdu_data_ = create_from;
}
-L2capSdu L2capSdu::L2capSduBuilder(std::vector<uint8_t> create_from) {
+std::shared_ptr<L2capSdu> L2capSdu::L2capSduConstructor(
+ std::vector<uint8_t> create_from) {
+ L2capSdu packet(std::move(create_from));
+
+ return std::make_shared<L2capSdu>(packet);
+}
+
+std::shared_ptr<L2capSdu> L2capSdu::L2capSduBuilder(
+ std::vector<uint8_t> create_from) {
L2capSdu packet(std::move(create_from));
packet.sdu_data_.resize(packet.sdu_data_.size() + 2, 0x00);
@@ -71,16 +78,7 @@
packet.sdu_data_[packet.sdu_data_.size() - 2] = fcs & 0xFF;
packet.sdu_data_[packet.sdu_data_.size() - 1] = (fcs & 0xFF00) >> 8;
- return packet;
-}
-
-std::vector<uint8_t>::const_iterator L2capSdu::get_payload_begin(
- const unsigned int offset) const {
- return std::next(sdu_data_.begin(), offset);
-}
-
-std::vector<uint8_t>::const_iterator L2capSdu::get_payload_end() const {
- return std::prev(sdu_data_.end(), 2);
+ return std::make_shared<L2capSdu>(packet);
}
uint16_t L2capSdu::convert_from_little_endian(
@@ -144,4 +142,8 @@
return (sar_bits == 0x8000);
}
+// HciPacket functions.
+size_t L2capSdu::get_length() { return sdu_data_.size(); }
+uint8_t& L2capSdu::get_at_index(size_t index) { return sdu_data_[index]; }
+
} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/packet.cc b/vendor_libs/test_vendor_lib/src/packet.cc
index a622a5f..49f7272 100644
--- a/vendor_libs/test_vendor_lib/src/packet.cc
+++ b/vendor_libs/test_vendor_lib/src/packet.cc
@@ -1,18 +1,18 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#define LOG_TAG "packet"
@@ -33,7 +33,7 @@
}
bool Packet::AddPayloadOctets(size_t octets, const vector<uint8_t>& bytes) {
- if (octets + payload_.size() > kMaxPacketOctets) return false;
+ if (GetPayloadSize() + octets > kMaxPayloadOctets) return false;
if (octets != bytes.size()) return false;
@@ -61,7 +61,7 @@
}
bool Packet::AddPayloadBtAddress(const BtAddress& address) {
- if (BtAddress::kOctets + payload_.size() > kMaxPacketOctets) return false;
+ if (GetPayloadSize() + BtAddress::kOctets > kMaxPayloadOctets) return false;
address.ToVector(payload_);
diff --git a/vendor_libs/test_vendor_lib/src/sco_packet.cc b/vendor_libs/test_vendor_lib/src/sco_packet.cc
new file mode 100644
index 0000000..465d8ff
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/src/sco_packet.cc
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "sco_packet"
+
+#include "sco_packet.h"
+
+#include "stack/include/hcidefs.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+ScoPacket::ScoPacket(uint16_t channel,
+ ScoPacket::PacketStatusFlags packet_status)
+ : Packet(DATA_TYPE_SCO,
+ {static_cast<uint8_t>(channel & 0xff),
+ static_cast<uint8_t>(((channel >> 8) & 0x0f) |
+ (packet_status & 0x3 << 4))}) {}
+
+uint16_t ScoPacket::GetChannel() const {
+ return (GetHeader()[0] | (GetHeader()[1] << 8)) & 0xfff;
+}
+
+ScoPacket::PacketStatusFlags ScoPacket::GetPacketStatusFlags() const {
+ return static_cast<ScoPacket::PacketStatusFlags>((GetHeader()[1] >> 4) & 0x3);
+}
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/test_channel_transport.cc b/vendor_libs/test_vendor_lib/src/test_channel_transport.cc
index adb3f7b..0d9bc2e 100644
--- a/vendor_libs/test_vendor_lib/src/test_channel_transport.cc
+++ b/vendor_libs/test_vendor_lib/src/test_channel_transport.cc
@@ -1,18 +1,18 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#define LOG_TAG "test_channel_transport"
@@ -77,9 +77,10 @@
socklen_t sockaddr_in_size = sizeof(struct sockaddr_in);
memset(&test_channel_address, 0, sockaddr_in_size);
- OSI_NO_INTR(accept_fd = accept(listen_fd_, reinterpret_cast<sockaddr*>(
- &test_channel_address),
- &sockaddr_in_size));
+ OSI_NO_INTR(accept_fd =
+ accept(listen_fd_,
+ reinterpret_cast<sockaddr*>(&test_channel_address),
+ &sockaddr_in_size));
if (accept_fd < 0) {
LOG_INFO(LOG_TAG, "Error accepting test channel connection errno=%d (%s).",
errno, strerror(errno));
@@ -139,4 +140,4 @@
command_handler_ = callback;
}
-} // namespace test_vendor_lib {
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/async_manager_unittest.cc b/vendor_libs/test_vendor_lib/test/async_manager_unittest.cc
index 816a19b..97b7331 100644
--- a/vendor_libs/test_vendor_lib/test/async_manager_unittest.cc
+++ b/vendor_libs/test_vendor_lib/test/async_manager_unittest.cc
@@ -1,18 +1,18 @@
-//
-// Copyright 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "async_manager.h"
#include <gtest/gtest.h>
diff --git a/vendor_libs/test_vendor_lib/test/bt_address_unittest.cc b/vendor_libs/test_vendor_lib/test/bt_address_unittest.cc
index d998179..0cf3760 100644
--- a/vendor_libs/test_vendor_lib/test/bt_address_unittest.cc
+++ b/vendor_libs/test_vendor_lib/test/bt_address_unittest.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2016 Google, Inc.
+ * Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
const std::string kZeros = "00:00:00:00:00:00";
const vector<uint8_t> kZeros_octets = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const vector<uint8_t> kTestAddr1_octets = {0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12};
-}
+} // namespace
namespace test_vendor_lib {
diff --git a/vendor_libs/test_vendor_lib/test/iterator_test.cc b/vendor_libs/test_vendor_lib/test/iterator_test.cc
new file mode 100644
index 0000000..92a6d70
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/test/iterator_test.cc
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hci_packet.h"
+#include "l2cap_test_packets.h"
+
+#include <gtest/gtest.h>
+#include <memory>
+
+using std::unique_ptr;
+using std::vector;
+namespace test_vendor_lib {
+
+class TestPacket : public HciPacket {
+ public:
+ static std::shared_ptr<TestPacket> make_new_packet(vector<uint8_t> v) {
+ return std::shared_ptr<TestPacket>(new TestPacket(v));
+ }
+ size_t get_length() { return test_vector_.size(); }
+ uint8_t& get_at_index(size_t index) { return test_vector_[index]; }
+
+ private:
+ TestPacket(vector<uint8_t> v) { test_vector_ = v; }
+ vector<uint8_t> test_vector_;
+};
+
+class IteratorTest : public ::testing::Test {
+ public:
+ IteratorTest() = default;
+ ~IteratorTest() = default;
+
+ void SetUp() { packet = TestPacket::make_new_packet(complete_l2cap_packet); }
+
+ void TearDown() { packet.reset(); }
+
+ std::shared_ptr<TestPacket> packet;
+};
+
+TEST_F(IteratorTest, extractTest) {
+ Iterator general_case = packet->get_begin();
+
+ ASSERT_EQ(0x95, general_case.extract<uint8_t>());
+ ASSERT_EQ(0x471f, general_case.extract<uint16_t>());
+ ASSERT_EQ(0x951f0200u, general_case.extract<uint32_t>());
+ ASSERT_EQ(0x33000101000000cbu, general_case.extract<uint64_t>());
+}
+
+TEST_F(IteratorTest, extractBoundsDeathTest) {
+ Iterator bounds_test = packet->get_end();
+
+ ASSERT_DEATH(bounds_test.extract<uint8_t>(), "");
+ ASSERT_DEATH(bounds_test.extract<uint16_t>(), "");
+ ASSERT_DEATH(bounds_test.extract<uint32_t>(), "");
+ ASSERT_DEATH(bounds_test.extract<uint64_t>(), "");
+}
+
+TEST_F(IteratorTest, dereferenceDeathTest) {
+ Iterator dereference_test = packet->get_end();
+
+ ASSERT_EQ(0x45, *(dereference_test - static_cast<size_t>(1)));
+ ASSERT_DEATH(*dereference_test, "");
+}
+TEST_F(IteratorTest, plusEqTest) {
+ Iterator plus_eq = packet->get_begin();
+ for (size_t i = 0; i < complete_l2cap_packet.size(); i += 2) {
+ ASSERT_EQ(complete_l2cap_packet[i], *plus_eq)
+ << "+= test: Dereferenced iterator does not equal expected at index "
+ << i;
+ plus_eq += 2;
+ }
+}
+
+TEST_F(IteratorTest, preIncrementTest) {
+ Iterator plus_plus = packet->get_begin();
+ for (size_t i = 0; i < complete_l2cap_packet.size() - 1; i++) {
+ ASSERT_EQ(complete_l2cap_packet[i + 1], *(++plus_plus))
+ << "Pre-increment test: Dereferenced iterator does not equal expected "
+ << "at index " << i;
+ }
+}
+
+TEST_F(IteratorTest, postIncrementTest) {
+ Iterator plus_plus = packet->get_begin();
+ for (size_t i = 0; i < complete_l2cap_packet.size(); i++) {
+ ASSERT_EQ(complete_l2cap_packet[i], *(plus_plus++))
+ << "Post-increment test: Dereferenced iterator does not equal expected "
+ << "at index " << i;
+ }
+}
+
+TEST_F(IteratorTest, additionTest) {
+ Iterator plus = packet->get_begin();
+ for (size_t i = 0; i < complete_l2cap_packet.size(); i++) {
+ ASSERT_EQ(complete_l2cap_packet[i], *plus)
+ << "+ test: Dereferenced iterator does not equal expected at index "
+ << i;
+ plus = plus + static_cast<size_t>(1);
+ }
+}
+
+TEST_F(IteratorTest, minusEqTest) {
+ Iterator minus_eq = packet->get_end();
+ minus_eq -= 1;
+ for (size_t i = complete_l2cap_packet.size() - 1; i > 0; i -= 2) {
+ ASSERT_EQ(complete_l2cap_packet[i], *minus_eq)
+ << "-= test: Dereferenced iterator does not equal expected at index "
+ << i;
+ minus_eq -= 2;
+ }
+}
+
+TEST_F(IteratorTest, preDecrementTest) {
+ Iterator minus_minus = packet->get_end();
+ for (size_t i = complete_l2cap_packet.size(); i > 0; i--) {
+ ASSERT_EQ(complete_l2cap_packet[i - 1], *(--minus_minus))
+ << "Pre-decrement test: Dereferenced iterator does not equal expected "
+ << "at index " << i;
+ }
+}
+
+TEST_F(IteratorTest, postDecrementTest) {
+ Iterator minus_minus = packet->get_end();
+ minus_minus--;
+ for (size_t i = complete_l2cap_packet.size() - 1; i > 0; i--) {
+ ASSERT_EQ(complete_l2cap_packet[i], *(minus_minus--))
+ << "Post-decrement test: Dereferenced iterator does not equal expected "
+ << "at index " << i;
+ }
+}
+
+TEST_F(IteratorTest, subtractionTest) {
+ Iterator minus = packet->get_end();
+ minus = minus - static_cast<size_t>(1);
+ for (size_t i = complete_l2cap_packet.size() - 1; i > 0; i--) {
+ ASSERT_EQ(complete_l2cap_packet[i], *minus)
+ << "- test: Dereferenced iterator does not equal expected at index "
+ << i;
+ minus = minus - static_cast<size_t>(1);
+ }
+}
+
+TEST_F(IteratorTest, plusEqBoundsTest) {
+ Iterator plus_eq = packet->get_end();
+ plus_eq--;
+ for (size_t i = 0; i < 100; i++) {
+ plus_eq += i;
+ ASSERT_EQ(packet->get_end(), plus_eq)
+ << "+= test: Iterator exceeded the upper bound set by get_length()";
+ }
+}
+
+TEST_F(IteratorTest, preIncrementBoundsTest) {
+ Iterator plus_plus = packet->get_end();
+ plus_plus--;
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_EQ(packet->get_end(), ++plus_plus)
+ << "Pre-increment test: Iterator exceeded the upper bound set "
+ "by get_length()";
+ }
+}
+
+TEST_F(IteratorTest, postIncrementBoundsTest) {
+ Iterator plus_plus = packet->get_end();
+ plus_plus--;
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_EQ(packet->get_end(), plus_plus++)
+ << "Post-increment test: Iterator exceeded the upper bound set "
+ "by get_length()";
+ }
+}
+
+TEST_F(IteratorTest, additionBoundsTest) {
+ Iterator plus = packet->get_end();
+ plus--;
+ for (size_t i = 0; i < 100; i++) {
+ plus = plus + static_cast<size_t>(i);
+ ASSERT_EQ(packet->get_end(), plus)
+ << "+ test: Iterator exceeded the upper bound set by get_length()";
+ }
+}
+
+TEST_F(IteratorTest, minusEqBoundsTest) {
+ Iterator minus_eq = packet->get_begin();
+ for (size_t i = 0; i < 100; i++) {
+ minus_eq -= i;
+ ASSERT_EQ(complete_l2cap_packet[0], *minus_eq)
+ << "-= test: Iterator is less than the lower bound set by "
+ "packet->get_begin()";
+ }
+}
+
+TEST_F(IteratorTest, preDecrementBoundsTest) {
+ Iterator minus_minus = packet->get_begin();
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_EQ(complete_l2cap_packet[0], *(--minus_minus))
+ << "Pre-decrement test: Iterator is less than the lower bound set by "
+ "packet->get_begin()";
+ }
+}
+
+TEST_F(IteratorTest, postDecrementBoundsTest) {
+ Iterator minus_minus = packet->get_begin();
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_EQ(complete_l2cap_packet[0], *(minus_minus--))
+ << "Post-decrement test: Iterator is less than the lower bound set by "
+ "packet->get_begin()";
+ }
+}
+
+TEST_F(IteratorTest, subtractionBoundsTest) {
+ Iterator minus = packet->get_begin();
+ for (size_t i = 0; i < 100; i++) {
+ minus = minus - static_cast<size_t>(i);
+ ASSERT_EQ(complete_l2cap_packet[0], *minus)
+ << "- test: Iterator is less than the lower bound set "
+ "by packet->get_begin()";
+ }
+}
+}; // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc b/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc
index 7d63f45..2e6df2c 100644
--- a/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc
+++ b/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc
@@ -1,36 +1,48 @@
-/******************************************************************************
+/*
+ * Copyright 2017 The Android Open Source Project
*
- * Copyright (C) 2017 Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "l2cap_sdu.h"
+
#include <gtest/gtest.h>
+#include <memory>
+
#include "l2cap_test_packets.h"
+
using std::vector;
namespace test_vendor_lib {
-L2capSdu packet_1(l2cap_test_packet_1);
-L2capSdu packet_2(l2cap_test_packet_2);
-L2capSdu packet_3(l2cap_test_packet_3);
-L2capSdu packet_4(l2cap_test_packet_4);
-L2capSdu packet_5(l2cap_test_packet_5);
-L2capSdu packet_6(l2cap_test_packet_6);
-L2capSdu packet_7(l2cap_test_packet_7);
-L2capSdu packet_8(l2cap_test_packet_8);
-L2capSdu packet_9(l2cap_test_packet_9);
+std::shared_ptr<L2capSdu> packet_1 =
+ L2capSdu::L2capSduConstructor(l2cap_test_packet_1);
+std::shared_ptr<L2capSdu> packet_2 =
+ L2capSdu::L2capSduConstructor(l2cap_test_packet_2);
+std::shared_ptr<L2capSdu> packet_3 =
+ L2capSdu::L2capSduConstructor(l2cap_test_packet_3);
+std::shared_ptr<L2capSdu> packet_4 =
+ L2capSdu::L2capSduConstructor(l2cap_test_packet_4);
+std::shared_ptr<L2capSdu> packet_5 =
+ L2capSdu::L2capSduConstructor(l2cap_test_packet_5);
+std::shared_ptr<L2capSdu> packet_6 =
+ L2capSdu::L2capSduConstructor(l2cap_test_packet_6);
+std::shared_ptr<L2capSdu> packet_7 =
+ L2capSdu::L2capSduConstructor(l2cap_test_packet_7);
+std::shared_ptr<L2capSdu> packet_8 =
+ L2capSdu::L2capSduConstructor(l2cap_test_packet_8);
+std::shared_ptr<L2capSdu> packet_9 =
+ L2capSdu::L2capSduConstructor(l2cap_test_packet_9);
class L2capSduTest : public ::testing::Test {
public:
@@ -41,79 +53,79 @@
}; // L2capSduTest
TEST_F(L2capSduTest, getFcsTest) {
- EXPECT_EQ(0x72aa, packet_1.get_fcs());
- EXPECT_EQ(0x5b57, packet_2.get_fcs());
- EXPECT_EQ(0xe644, packet_3.get_fcs());
- EXPECT_EQ(0x21b0, packet_4.get_fcs());
- EXPECT_EQ(0xae96, packet_5.get_fcs());
- EXPECT_EQ(0x9254, packet_6.get_fcs());
- EXPECT_EQ(0xf6fa, packet_7.get_fcs());
- EXPECT_EQ(0x1da4, packet_8.get_fcs());
- EXPECT_EQ(0x781a, packet_9.get_fcs());
+ EXPECT_EQ(0x72aa, packet_1->get_fcs());
+ EXPECT_EQ(0x5b57, packet_2->get_fcs());
+ EXPECT_EQ(0xe644, packet_3->get_fcs());
+ EXPECT_EQ(0x21b0, packet_4->get_fcs());
+ EXPECT_EQ(0xae96, packet_5->get_fcs());
+ EXPECT_EQ(0x9254, packet_6->get_fcs());
+ EXPECT_EQ(0xf6fa, packet_7->get_fcs());
+ EXPECT_EQ(0x1da4, packet_8->get_fcs());
+ EXPECT_EQ(0x781a, packet_9->get_fcs());
}
TEST_F(L2capSduTest, getPayloadLengthTest) {
- EXPECT_EQ(l2cap_test_packet_1.size() - 4, packet_1.get_payload_length());
- EXPECT_EQ(l2cap_test_packet_2.size() - 4, packet_2.get_payload_length());
- EXPECT_EQ(l2cap_test_packet_3.size() - 4, packet_3.get_payload_length());
- EXPECT_EQ(l2cap_test_packet_4.size() - 4, packet_4.get_payload_length());
- EXPECT_EQ(l2cap_test_packet_5.size() - 4, packet_5.get_payload_length());
- EXPECT_EQ(l2cap_test_packet_6.size() - 4, packet_6.get_payload_length());
- EXPECT_EQ(l2cap_test_packet_7.size() - 4, packet_7.get_payload_length());
- EXPECT_EQ(l2cap_test_packet_8.size() - 4, packet_8.get_payload_length());
- EXPECT_EQ(l2cap_test_packet_9.size() - 4, packet_9.get_payload_length());
+ EXPECT_EQ(l2cap_test_packet_1.size() - 4, packet_1->get_payload_length());
+ EXPECT_EQ(l2cap_test_packet_2.size() - 4, packet_2->get_payload_length());
+ EXPECT_EQ(l2cap_test_packet_3.size() - 4, packet_3->get_payload_length());
+ EXPECT_EQ(l2cap_test_packet_4.size() - 4, packet_4->get_payload_length());
+ EXPECT_EQ(l2cap_test_packet_5.size() - 4, packet_5->get_payload_length());
+ EXPECT_EQ(l2cap_test_packet_6.size() - 4, packet_6->get_payload_length());
+ EXPECT_EQ(l2cap_test_packet_7.size() - 4, packet_7->get_payload_length());
+ EXPECT_EQ(l2cap_test_packet_8.size() - 4, packet_8->get_payload_length());
+ EXPECT_EQ(l2cap_test_packet_9.size() - 4, packet_9->get_payload_length());
}
TEST_F(L2capSduTest, calculateFcsTest) {
- EXPECT_EQ(0x72aa, packet_1.calculate_fcs());
- EXPECT_EQ(0x5b57, packet_2.calculate_fcs());
- EXPECT_EQ(0xe644, packet_3.calculate_fcs());
- EXPECT_EQ(0x21b0, packet_4.calculate_fcs());
- EXPECT_EQ(0xae96, packet_5.calculate_fcs());
- EXPECT_EQ(0x9254, packet_6.calculate_fcs());
- EXPECT_EQ(0xf6fa, packet_7.calculate_fcs());
- EXPECT_EQ(0x1da4, packet_8.calculate_fcs());
- EXPECT_EQ(0x781a, packet_9.calculate_fcs());
+ EXPECT_EQ(0x72aa, packet_1->calculate_fcs());
+ EXPECT_EQ(0x5b57, packet_2->calculate_fcs());
+ EXPECT_EQ(0xe644, packet_3->calculate_fcs());
+ EXPECT_EQ(0x21b0, packet_4->calculate_fcs());
+ EXPECT_EQ(0xae96, packet_5->calculate_fcs());
+ EXPECT_EQ(0x9254, packet_6->calculate_fcs());
+ EXPECT_EQ(0xf6fa, packet_7->calculate_fcs());
+ EXPECT_EQ(0x1da4, packet_8->calculate_fcs());
+ EXPECT_EQ(0x781a, packet_9->calculate_fcs());
}
TEST_F(L2capSduTest, getControlsTest) {
- EXPECT_EQ(0x4102, packet_1.get_controls());
- EXPECT_EQ(0xc104, packet_2.get_controls());
- EXPECT_EQ(0xc106, packet_3.get_controls());
- EXPECT_EQ(0xc108, packet_4.get_controls());
- EXPECT_EQ(0xc10a, packet_5.get_controls());
- EXPECT_EQ(0xc10c, packet_6.get_controls());
- EXPECT_EQ(0xc10e, packet_7.get_controls());
- EXPECT_EQ(0xc110, packet_8.get_controls());
- EXPECT_EQ(0x8112, packet_9.get_controls());
+ EXPECT_EQ(0x4102, packet_1->get_controls());
+ EXPECT_EQ(0xc104, packet_2->get_controls());
+ EXPECT_EQ(0xc106, packet_3->get_controls());
+ EXPECT_EQ(0xc108, packet_4->get_controls());
+ EXPECT_EQ(0xc10a, packet_5->get_controls());
+ EXPECT_EQ(0xc10c, packet_6->get_controls());
+ EXPECT_EQ(0xc10e, packet_7->get_controls());
+ EXPECT_EQ(0xc110, packet_8->get_controls());
+ EXPECT_EQ(0x8112, packet_9->get_controls());
}
TEST_F(L2capSduTest, getTotalLengthTest) {
- EXPECT_EQ(0x1f95, packet_1.get_total_l2cap_length());
+ EXPECT_EQ(0x1f95, packet_1->get_total_l2cap_length());
}
TEST_F(L2capSduTest, getVectorSizeTest) {
- EXPECT_EQ(l2cap_test_packet_1.size(), packet_1.get_vector_size());
- EXPECT_EQ(l2cap_test_packet_2.size(), packet_2.get_vector_size());
- EXPECT_EQ(l2cap_test_packet_3.size(), packet_3.get_vector_size());
- EXPECT_EQ(l2cap_test_packet_4.size(), packet_4.get_vector_size());
- EXPECT_EQ(l2cap_test_packet_5.size(), packet_5.get_vector_size());
- EXPECT_EQ(l2cap_test_packet_6.size(), packet_6.get_vector_size());
- EXPECT_EQ(l2cap_test_packet_7.size(), packet_7.get_vector_size());
- EXPECT_EQ(l2cap_test_packet_8.size(), packet_8.get_vector_size());
- EXPECT_EQ(l2cap_test_packet_9.size(), packet_9.get_vector_size());
+ EXPECT_EQ(l2cap_test_packet_1.size(), packet_1->get_vector_size());
+ EXPECT_EQ(l2cap_test_packet_2.size(), packet_2->get_vector_size());
+ EXPECT_EQ(l2cap_test_packet_3.size(), packet_3->get_vector_size());
+ EXPECT_EQ(l2cap_test_packet_4.size(), packet_4->get_vector_size());
+ EXPECT_EQ(l2cap_test_packet_5.size(), packet_5->get_vector_size());
+ EXPECT_EQ(l2cap_test_packet_6.size(), packet_6->get_vector_size());
+ EXPECT_EQ(l2cap_test_packet_7.size(), packet_7->get_vector_size());
+ EXPECT_EQ(l2cap_test_packet_8.size(), packet_8->get_vector_size());
+ EXPECT_EQ(l2cap_test_packet_9.size(), packet_9->get_vector_size());
}
TEST_F(L2capSduTest, getCidTest) {
- EXPECT_EQ(0x0047, packet_1.get_channel_id());
- EXPECT_EQ(0x0047, packet_2.get_channel_id());
- EXPECT_EQ(0x0047, packet_3.get_channel_id());
- EXPECT_EQ(0x0047, packet_4.get_channel_id());
- EXPECT_EQ(0x0047, packet_5.get_channel_id());
- EXPECT_EQ(0x0047, packet_6.get_channel_id());
- EXPECT_EQ(0x0047, packet_7.get_channel_id());
- EXPECT_EQ(0x0047, packet_8.get_channel_id());
- EXPECT_EQ(0x0047, packet_9.get_channel_id());
+ EXPECT_EQ(0x0047, packet_1->get_channel_id());
+ EXPECT_EQ(0x0047, packet_2->get_channel_id());
+ EXPECT_EQ(0x0047, packet_3->get_channel_id());
+ EXPECT_EQ(0x0047, packet_4->get_channel_id());
+ EXPECT_EQ(0x0047, packet_5->get_channel_id());
+ EXPECT_EQ(0x0047, packet_6->get_channel_id());
+ EXPECT_EQ(0x0047, packet_7->get_channel_id());
+ EXPECT_EQ(0x0047, packet_8->get_channel_id());
+ EXPECT_EQ(0x0047, packet_9->get_channel_id());
}
} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/l2cap_test.cc b/vendor_libs/test_vendor_lib/test/l2cap_test.cc
index d35e78f..f4eea71 100644
--- a/vendor_libs/test_vendor_lib/test/l2cap_test.cc
+++ b/vendor_libs/test_vendor_lib/test/l2cap_test.cc
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2017 Google, Inc.
+ * Copyright 2017 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,109 +16,113 @@
*
******************************************************************************/
+#include "hci_packet.h"
#include "l2cap_packet.h"
#include "l2cap_test_packets.h"
#include <gtest/gtest.h>
#include <memory>
-using std::unique_ptr;
+using std::shared_ptr;
using std::vector;
namespace test_vendor_lib {
+class TestPacket : public HciPacket {
+ public:
+ TestPacket(const std::vector<uint8_t>& packet) { complete_packet_ = packet; }
+ TestPacket() = default;
+
+ private:
+ std::vector<uint8_t> complete_packet_;
+ size_t get_length() { return complete_packet_.size(); }
+ uint8_t& get_at_index(size_t index) { return complete_packet_[index]; }
+};
+
class L2capTest : public ::testing::Test {
public:
- L2capTest() {}
-
- void compare_packets(vector<uint8_t>& complete_packet,
- vector<uint8_t>& assembled_packet) {
- ASSERT_EQ(complete_packet.size() - 4, assembled_packet.size());
-
- for (size_t i = 0; i < assembled_packet.size(); i++) {
- ASSERT_EQ(complete_packet[i + 4], assembled_packet[i]);
- }
- }
-
- L2capSdu update_fcs(vector<uint8_t> sdu) {
+ std::shared_ptr<L2capSdu> update_fcs(vector<uint8_t> sdu) {
sdu.resize(sdu.size() - 2);
return L2capSdu::L2capSduBuilder(sdu);
}
- void compare_fragmented_packets(vector<uint8_t>& expected,
- vector<uint8_t>& received) {
- ASSERT_EQ(expected.size(), received.size());
+ void compare_packets(shared_ptr<HciPacket> expected,
+ shared_ptr<HciPacket> received) {
+ Iterator expected_begin = expected->get_begin();
+ Iterator expected_end = expected->get_end();
- for (size_t i = 0; i < expected.size(); i++) {
- ASSERT_EQ(expected[i], received[i]);
+ Iterator received_begin = received->get_begin();
+ Iterator received_end = received->get_end();
+
+ ASSERT_EQ(expected_end - expected_begin, received_end - received_begin);
+
+ while (expected_begin < expected_end) {
+ ASSERT_EQ(*expected_begin, *received_begin);
+ expected_begin++;
+ received_begin++;
}
}
-
- ~L2capTest() = default;
};
TEST_F(L2capTest, assembleGoodPackets) {
- vector<L2capSdu> test_packet;
- vector<uint8_t> assembled_payload;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 1: Pass correct packets.
- test_packet.push_back(L2capSdu(good_sdu[0]));
- test_packet.push_back(L2capSdu(good_sdu[1]));
- test_packet.push_back(L2capSdu(good_sdu[2]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2]));
- unique_ptr<L2capPacket> test_1 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_1 = L2capPacket::assemble(test_packet);
ASSERT_NE(test_1, nullptr);
- assembled_payload = test_1->get_l2cap_payload();
+ shared_ptr<TestPacket> expected(new TestPacket(good_l2cap_packet));
- compare_packets(good_l2cap_packet, assembled_payload);
+ compare_packets(expected, test_1);
- assembled_payload.clear();
test_packet.clear();
- test_packet.push_back(L2capSdu(l2cap_test_packet_1));
- test_packet.push_back(L2capSdu(l2cap_test_packet_2));
- test_packet.push_back(L2capSdu(l2cap_test_packet_3));
- test_packet.push_back(L2capSdu(l2cap_test_packet_4));
- test_packet.push_back(L2capSdu(l2cap_test_packet_5));
- test_packet.push_back(L2capSdu(l2cap_test_packet_6));
- test_packet.push_back(L2capSdu(l2cap_test_packet_7));
- test_packet.push_back(L2capSdu(l2cap_test_packet_8));
- test_packet.push_back(L2capSdu(l2cap_test_packet_9));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9));
test_1 = L2capPacket::assemble(test_packet);
ASSERT_NE(test_1, nullptr);
- assembled_payload = test_1->get_l2cap_payload();
- compare_packets(complete_l2cap_packet, assembled_payload);
+ expected.reset(new TestPacket(complete_l2cap_packet));
+ compare_packets(expected, test_1);
- assembled_payload.clear();
test_packet.clear();
}
TEST_F(L2capTest, assembleOutofOrderPackets) {
- vector<L2capSdu> test_packet;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 2: Pass out of order packets.
- test_packet.push_back(L2capSdu(good_sdu[1]));
- test_packet.push_back(L2capSdu(good_sdu[0]));
- test_packet.push_back(L2capSdu(good_sdu[2]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2]));
- unique_ptr<L2capPacket> test_2 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_2 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_2, nullptr);
test_packet.clear();
- test_packet.push_back(L2capSdu(l2cap_test_packet_1));
- test_packet.push_back(L2capSdu(l2cap_test_packet_3));
- test_packet.push_back(L2capSdu(l2cap_test_packet_2));
- test_packet.push_back(L2capSdu(l2cap_test_packet_6));
- test_packet.push_back(L2capSdu(l2cap_test_packet_5));
- test_packet.push_back(L2capSdu(l2cap_test_packet_4));
- test_packet.push_back(L2capSdu(l2cap_test_packet_8));
- test_packet.push_back(L2capSdu(l2cap_test_packet_7));
- test_packet.push_back(L2capSdu(l2cap_test_packet_9));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9));
test_2 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_2, nullptr);
@@ -127,25 +131,25 @@
}
TEST_F(L2capTest, assembleBadControlBytes) {
- vector<L2capSdu> test_packet;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 3: Pass packets missing the finished control bytes.
- test_packet.push_back(L2capSdu(good_sdu[0]));
- test_packet.push_back(L2capSdu(good_sdu[1]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1]));
- unique_ptr<L2capPacket> test_3 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_3 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_3, nullptr);
test_packet.clear();
- test_packet.push_back(L2capSdu(l2cap_test_packet_1));
- test_packet.push_back(L2capSdu(l2cap_test_packet_2));
- test_packet.push_back(L2capSdu(l2cap_test_packet_3));
- test_packet.push_back(L2capSdu(l2cap_test_packet_4));
- test_packet.push_back(L2capSdu(l2cap_test_packet_5));
- test_packet.push_back(L2capSdu(l2cap_test_packet_6));
- test_packet.push_back(L2capSdu(l2cap_test_packet_7));
- test_packet.push_back(L2capSdu(l2cap_test_packet_8));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8));
test_3 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_3, nullptr);
@@ -154,31 +158,31 @@
}
TEST_F(L2capTest, assembleBadFCS) {
- vector<L2capSdu> test_packet;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 4: Pass packets with incorrect frame check sequences.
- test_packet.push_back(L2capSdu(good_sdu[0]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0]));
good_sdu[1][good_sdu[1].size() - 1]++;
- test_packet.push_back(L2capSdu(good_sdu[1]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1]));
good_sdu[1][good_sdu[1].size() - 1]--;
- test_packet.push_back(L2capSdu(good_sdu[2]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2]));
- unique_ptr<L2capPacket> test_4 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_4 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_4, nullptr);
test_packet.clear();
- test_packet.push_back(L2capSdu(l2cap_test_packet_1));
- test_packet.push_back(L2capSdu(l2cap_test_packet_2));
- test_packet.push_back(L2capSdu(l2cap_test_packet_3));
- test_packet.push_back(L2capSdu(l2cap_test_packet_4));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4));
l2cap_test_packet_5[l2cap_test_packet_5.size() - 1]++;
- test_packet.push_back(L2capSdu(l2cap_test_packet_5));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5));
l2cap_test_packet_5[l2cap_test_packet_5.size() - 1]--;
- test_packet.push_back(L2capSdu(l2cap_test_packet_6));
- test_packet.push_back(L2capSdu(l2cap_test_packet_7));
- test_packet.push_back(L2capSdu(l2cap_test_packet_8));
- test_packet.push_back(L2capSdu(l2cap_test_packet_9));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9));
test_4 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_4, nullptr);
@@ -187,68 +191,65 @@
}
TEST_F(L2capTest, assembleEmptyPayload) {
- vector<L2capSdu> test_packet;
- vector<uint8_t> assembled_payload;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 5: Pass a packet with an empty payload.
- test_packet.push_back(L2capSdu(empty_sdu_payload[0]));
- test_packet.push_back(L2capSdu(empty_sdu_payload[1]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(empty_sdu_payload[0]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(empty_sdu_payload[1]));
- unique_ptr<L2capPacket> test_5 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_5 = L2capPacket::assemble(test_packet);
ASSERT_NE(test_5, nullptr);
- EXPECT_EQ(test_5->get_l2cap_cid(), 0x0047);
- assembled_payload = test_5->get_l2cap_payload();
- compare_packets(empty_l2cap_payload, assembled_payload);
+ shared_ptr<TestPacket> expected(new TestPacket(empty_l2cap_payload));
+ compare_packets(expected, test_5);
- assembled_payload.clear();
test_packet.clear();
}
TEST_F(L2capTest, assembleAllStartingControlError) {
- vector<L2capSdu> test_packet;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 6: Pass a SDU with all the control bytes set to as the starting bytes.
- test_packet.push_back(L2capSdu(all_first_packet[0]));
- test_packet.push_back(L2capSdu(all_first_packet[1]));
- test_packet.push_back(L2capSdu(all_first_packet[2]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(all_first_packet[0]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(all_first_packet[1]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(all_first_packet[2]));
- unique_ptr<L2capPacket> test_6 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_6 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_6, nullptr);
test_packet.clear();
}
TEST_F(L2capTest, assembleBadCID) {
- vector<L2capSdu> test_packet;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 7: Pass SDUs with mixed channel ids.
- test_packet.push_back(L2capSdu(good_sdu[0]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0]));
good_sdu[1][2]++;
test_packet.push_back(update_fcs(good_sdu[1]));
good_sdu[1][2]--;
- test_packet.push_back(L2capSdu(good_sdu[2]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2]));
- unique_ptr<L2capPacket> test_7 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_7 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_7, nullptr);
test_packet.clear();
- test_packet.push_back(L2capSdu(l2cap_test_packet_1));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1));
l2cap_test_packet_2[2]++;
- test_packet.push_back(update_fcs(l2cap_test_packet_2));
+ test_packet.push_back((update_fcs(l2cap_test_packet_2)));
l2cap_test_packet_2[2]--;
- test_packet.push_back(L2capSdu(l2cap_test_packet_3));
- test_packet.push_back(L2capSdu(l2cap_test_packet_4));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4));
l2cap_test_packet_5[2]++;
- test_packet.push_back(update_fcs(l2cap_test_packet_5));
+ test_packet.push_back((update_fcs(l2cap_test_packet_5)));
l2cap_test_packet_5[2]--;
- test_packet.push_back(L2capSdu(l2cap_test_packet_6));
- test_packet.push_back(L2capSdu(l2cap_test_packet_7));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7));
l2cap_test_packet_8[2]--;
- test_packet.push_back(update_fcs(l2cap_test_packet_8));
+ test_packet.push_back((update_fcs(l2cap_test_packet_8)));
l2cap_test_packet_8[2]++;
- test_packet.push_back(L2capSdu(l2cap_test_packet_9));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9));
test_7 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_7, nullptr);
@@ -257,59 +258,59 @@
}
TEST_F(L2capTest, assembleUnsegmentedSDU) {
- vector<L2capSdu> test_packet;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 8: Pass a complete l2cap packet.
- test_packet.push_back(L2capSdu(one_sdu[0]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(one_sdu[0]));
- unique_ptr<L2capPacket> test_8 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_8 = L2capPacket::assemble(test_packet);
EXPECT_NE(test_8, nullptr);
test_packet.clear();
}
TEST_F(L2capTest, assembleBadTxSeq) {
- vector<L2capSdu> test_packet;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 9: Pass SDUs with incorrect TxSeq.
good_sdu[0][4] += 4;
- test_packet.push_back(update_fcs(good_sdu[0]));
+ test_packet.push_back((update_fcs(good_sdu[0])));
good_sdu[0][4] -= 4;
- test_packet.push_back(L2capSdu(good_sdu[1]));
- test_packet.push_back(L2capSdu(good_sdu[2]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2]));
- unique_ptr<L2capPacket> test_9 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_9 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_9, nullptr);
test_packet.clear();
}
TEST_F(L2capTest, assembleBadTotalSDULength) {
- vector<L2capSdu> test_packet;
+ vector<std::shared_ptr<L2capSdu> > test_packet;
// Test 10: Pass SDUs with an incorrect total SDU length
good_sdu[0][7]++;
- test_packet.push_back(update_fcs(good_sdu[0]));
+ test_packet.push_back((update_fcs(good_sdu[0])));
good_sdu[0][7]--;
- test_packet.push_back(L2capSdu(good_sdu[1]));
- test_packet.push_back(L2capSdu(good_sdu[2]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1]));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2]));
- unique_ptr<L2capPacket> test_10 = L2capPacket::assemble(test_packet);
+ shared_ptr<L2capPacket> test_10 = L2capPacket::assemble(test_packet);
EXPECT_EQ(test_10, nullptr);
test_packet.clear();
l2cap_test_packet_1[6]++;
- test_packet.push_back(update_fcs(l2cap_test_packet_1));
+ test_packet.push_back((update_fcs(l2cap_test_packet_1)));
l2cap_test_packet_1[6]--;
- test_packet.push_back(L2capSdu(l2cap_test_packet_2));
- test_packet.push_back(L2capSdu(l2cap_test_packet_3));
- test_packet.push_back(L2capSdu(l2cap_test_packet_4));
- test_packet.push_back(L2capSdu(l2cap_test_packet_5));
- test_packet.push_back(L2capSdu(l2cap_test_packet_6));
- test_packet.push_back(L2capSdu(l2cap_test_packet_7));
- test_packet.push_back(L2capSdu(l2cap_test_packet_8));
- test_packet.push_back(L2capSdu(l2cap_test_packet_9));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8));
+ test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9));
test_10 = L2capPacket::assemble(test_packet);
@@ -320,13 +321,13 @@
// Begin Fragment Test1
TEST_F(L2capTest, fragmentSmallSegmentTest) {
- std::vector<L2capSdu> sdu;
- std::unique_ptr<L2capPacket> l2cap_expected;
- std::unique_ptr<L2capPacket> l2cap_received;
+ std::vector<std::shared_ptr<L2capSdu> > sdu;
+ std::shared_ptr<L2capPacket> l2cap_expected;
+ std::shared_ptr<L2capPacket> l2cap_received;
- sdu.push_back(L2capSdu(good_sdu[0]));
- sdu.push_back(L2capSdu(good_sdu[1]));
- sdu.push_back(L2capSdu(good_sdu[2]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[0]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[1]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[2]));
l2cap_expected = L2capPacket::assemble(sdu);
@@ -342,31 +343,28 @@
<< "sdu used: good_sdu" << std::endl
<< "function call: fragment(16, 0x02, 0x41)" << std::endl;
- std::vector<uint8_t> small_seg_expected = l2cap_expected->get_l2cap_payload();
- std::vector<uint8_t> small_seg_received = l2cap_received->get_l2cap_payload();
-
- compare_fragmented_packets(small_seg_expected, small_seg_received);
+ compare_packets(l2cap_expected, l2cap_received);
sdu.clear();
- l2cap_expected.reset(nullptr);
- l2cap_received.reset(nullptr);
+ l2cap_expected.reset();
+ l2cap_received.reset();
} // End Fragment Test1
// Begin Fragment Test2
TEST_F(L2capTest, fragmentLargeSegmentTest) {
- std::vector<L2capSdu> sdu;
- std::unique_ptr<L2capPacket> l2cap_expected;
- std::unique_ptr<L2capPacket> l2cap_received;
+ std::vector<std::shared_ptr<L2capSdu> > sdu;
+ std::shared_ptr<L2capPacket> l2cap_expected;
+ std::shared_ptr<L2capPacket> l2cap_received;
- sdu.push_back(L2capSdu(l2cap_test_packet_1));
- sdu.push_back(L2capSdu(l2cap_test_packet_2));
- sdu.push_back(L2capSdu(l2cap_test_packet_3));
- sdu.push_back(L2capSdu(l2cap_test_packet_4));
- sdu.push_back(L2capSdu(l2cap_test_packet_5));
- sdu.push_back(L2capSdu(l2cap_test_packet_6));
- sdu.push_back(L2capSdu(l2cap_test_packet_7));
- sdu.push_back(L2capSdu(l2cap_test_packet_8));
- sdu.push_back(L2capSdu(l2cap_test_packet_9));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9));
l2cap_expected = L2capPacket::assemble(sdu);
@@ -382,25 +380,22 @@
<< "sdu used: l2cap_test_packet[1-9]" << std::endl
<< "function call: fragment(1024, 0x02, 0x41)" << std::endl;
- std::vector<uint8_t> large_seg_expected = l2cap_expected->get_l2cap_payload();
- std::vector<uint8_t> large_seg_received = l2cap_received->get_l2cap_payload();
-
- compare_fragmented_packets(large_seg_expected, large_seg_received);
+ compare_packets(l2cap_expected, l2cap_received);
sdu.clear();
- l2cap_expected.reset(nullptr);
- l2cap_received.reset(nullptr);
+ l2cap_expected.reset();
+ l2cap_received.reset();
} // End Fragment Test2
// Begin Fragment Test3
TEST_F(L2capTest, fragmentTxSeqTest) {
- std::vector<L2capSdu> sdu;
- std::unique_ptr<L2capPacket> l2cap_expected;
- std::unique_ptr<L2capPacket> l2cap_received;
+ std::vector<std::shared_ptr<L2capSdu> > sdu;
+ std::shared_ptr<L2capPacket> l2cap_expected;
+ std::shared_ptr<L2capPacket> l2cap_received;
- sdu.push_back(L2capSdu(good_sdu[0]));
- sdu.push_back(L2capSdu(good_sdu[1]));
- sdu.push_back(L2capSdu(good_sdu[2]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[0]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[1]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[2]));
l2cap_expected = L2capPacket::assemble(sdu);
@@ -416,24 +411,21 @@
<< "sdu used: good_sdu" << std::endl
<< "function call: fragment(24, 0x08, 0x41)" << std::endl;
- std::vector<uint8_t> txseq_expected = l2cap_expected->get_l2cap_payload();
- std::vector<uint8_t> txseq_received = l2cap_received->get_l2cap_payload();
-
- compare_fragmented_packets(txseq_expected, txseq_received);
+ compare_packets(l2cap_expected, l2cap_received);
sdu.clear();
- l2cap_expected.reset(nullptr);
- l2cap_received.reset(nullptr);
+ l2cap_expected.reset();
+ l2cap_received.reset();
} // End Fragment Test3
// Begin Fragment Test4
TEST_F(L2capTest, fragmentPayloadTest) {
- std::vector<L2capSdu> sdu;
- std::unique_ptr<L2capPacket> l2cap_expected;
- std::unique_ptr<L2capPacket> l2cap_received;
+ std::vector<std::shared_ptr<L2capSdu> > sdu;
+ std::shared_ptr<L2capPacket> l2cap_expected;
+ std::shared_ptr<L2capPacket> l2cap_received;
- sdu.push_back(L2capSdu(empty_sdu_payload[0]));
- sdu.push_back(L2capSdu(empty_sdu_payload[1]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(empty_sdu_payload[0]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(empty_sdu_payload[1]));
l2cap_expected = L2capPacket::assemble(sdu);
@@ -449,25 +441,22 @@
<< "sdu used: empty_sdu_payload" << std::endl
<< "function call: fragment(16, 0x02, 0x41)" << std::endl;
- std::vector<uint8_t> empty_expected = l2cap_expected->get_l2cap_payload();
- std::vector<uint8_t> empty_received = l2cap_received->get_l2cap_payload();
-
- compare_fragmented_packets(empty_expected, empty_received);
+ compare_packets(l2cap_expected, l2cap_received);
sdu.clear();
- l2cap_expected.reset(nullptr);
- l2cap_received.reset(nullptr);
+ l2cap_expected.reset();
+ l2cap_received.reset();
} // End Fragment Test4
// Begin Fragment Test5
TEST_F(L2capTest, fragmentSegmentSizeTest) {
- std::vector<L2capSdu> sdu;
- std::unique_ptr<L2capPacket> l2cap_expected;
- std::unique_ptr<L2capPacket> l2cap_received;
+ std::vector<std::shared_ptr<L2capSdu> > sdu;
+ std::shared_ptr<L2capPacket> l2cap_expected;
+ std::shared_ptr<L2capPacket> l2cap_received;
- sdu.push_back(L2capSdu(good_sdu[0]));
- sdu.push_back(L2capSdu(good_sdu[1]));
- sdu.push_back(L2capSdu(good_sdu[2]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[0]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[1]));
+ sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[2]));
l2cap_expected = L2capPacket::assemble(sdu);
@@ -483,31 +472,28 @@
<< "sdu used: good_sdu" << std::endl
<< "function call: fragment(256, 0x02, 0x41)" << std::endl;
- std::vector<uint8_t> big_segs_exp = l2cap_expected->get_l2cap_payload();
- std::vector<uint8_t> big_segs_rcvd = l2cap_received->get_l2cap_payload();
-
- compare_fragmented_packets(big_segs_exp, big_segs_rcvd);
+ compare_packets(l2cap_expected, l2cap_received);
sdu.clear();
- l2cap_expected.reset(nullptr);
- l2cap_received.reset(nullptr);
+ l2cap_expected.reset();
+ l2cap_received.reset();
} // End Fragment Test5
// Begin Fragment Test6
TEST_F(L2capTest, fragmentSegmentSizeTest2) {
- std::vector<L2capSdu> sdu;
- std::unique_ptr<L2capPacket> l2cap_expected;
- std::unique_ptr<L2capPacket> l2cap_received;
+ std::vector<std::shared_ptr<L2capSdu> > sdu;
+ std::shared_ptr<L2capPacket> l2cap_expected;
+ std::shared_ptr<L2capPacket> l2cap_received;
- sdu.push_back(L2capSdu(l2cap_test_packet_1));
- sdu.push_back(L2capSdu(l2cap_test_packet_2));
- sdu.push_back(L2capSdu(l2cap_test_packet_3));
- sdu.push_back(L2capSdu(l2cap_test_packet_4));
- sdu.push_back(L2capSdu(l2cap_test_packet_5));
- sdu.push_back(L2capSdu(l2cap_test_packet_6));
- sdu.push_back(L2capSdu(l2cap_test_packet_7));
- sdu.push_back(L2capSdu(l2cap_test_packet_8));
- sdu.push_back(L2capSdu(l2cap_test_packet_9));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8));
+ sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9));
l2cap_expected = L2capPacket::assemble(sdu);
sdu.clear();
@@ -522,14 +508,11 @@
<< "sdu used: l2cap_test_packet_[1-9]" << std::endl
<< "function call: fragment(64, 0x02, 0x41)" << std::endl;
- std::vector<uint8_t> small_segs_exp = l2cap_expected->get_l2cap_payload();
- std::vector<uint8_t> small_segs_rcvd = l2cap_received->get_l2cap_payload();
-
- compare_fragmented_packets(small_segs_exp, small_segs_rcvd);
+ compare_packets(l2cap_expected, l2cap_received);
sdu.clear();
- l2cap_expected.reset(nullptr);
- l2cap_received.reset(nullptr);
+ l2cap_expected.reset();
+ l2cap_received.reset();
} // End Fragment Test6
} // namespace test_vendor_lib
diff --git a/vnd/ble/vendor_hcidefs.h b/vnd/ble/vendor_hcidefs.h
index d0bbaf3..b6782af 100644
--- a/vnd/ble/vendor_hcidefs.h
+++ b/vnd/ble/vendor_hcidefs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2014 Broadcom Corporation
+ * Copyright 2003-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.