Skip to content

Commit

Permalink
CRAS: allow fallback to default SBC params in A2DP
Browse files Browse the repository at this point in the history
While SBC is supposed to be mandatory to be supported and listed in the
available codecs advertised by the peer, we found some cases that this
could not hold, likely due to how AAC is usually the preferred/default
codec to the peers.

If the peer advertises some non-mandatory codec but not SBC, the current
logic will end up in losing A2DP capability. Assuming that SBC should
always be supported but maybe the codec advertisement could not be as
reliable, we add a fallback to a set of default (and must-be-supported)
parameters in such cases.

BUG=b:311233879
TEST=verify A2DP works when SBC is not in codec list

Change-Id: I3f9f8aff4956b53b7c46f25728523af4679c73a9
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/adhd/+/5076843
Tested-by: chromeos-cop-builder@chromeos-cop.iam.gserviceaccount.com <chromeos-cop-builder@chromeos-cop.iam.gserviceaccount.com>
Reviewed-by: Ching Yun Chang <whalechang@google.com>
Commit-Queue: Ching Yun Chang <whalechang@google.com>
  • Loading branch information
Jeremy Wu authored and Chromeos LUCI committed Dec 4, 2023
1 parent bbfaa6c commit 079d5db
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 18 deletions.
29 changes: 18 additions & 11 deletions cras/src/server/cras_a2dp_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,17 @@ static bool cras_floss_a2dp_nonstandard_codecs_allowed() {
return cras_feature_enabled(CrOSLateBootAudioA2DPAdvancedCodecs);
}

static struct cras_fl_a2dp_codec_config* cras_floss_a2dp_get_best_codec(
static struct cras_fl_a2dp_codec_config cras_floss_a2dp_get_best_codec(
struct cras_fl_a2dp_codec_config* codecs) {
struct cras_fl_a2dp_codec_config* codec;
struct cras_fl_a2dp_codec_config* best_codec = NULL;
struct cras_fl_a2dp_codec_config best_codec = {
.bits_per_sample = FL_SAMPLE_16,
.channel_mode = FL_MODE_STEREO,
.codec_priority = -1,
.codec_type = FL_A2DP_CODEC_SRC_SBC,
.sample_rate = FL_RATE_44100,
.next = NULL,
};

DL_FOREACH (codecs, codec) {
// TODO(b/279991957): Add UMA to record availability of codecs
Expand All @@ -262,11 +269,15 @@ static struct cras_fl_a2dp_codec_config* cras_floss_a2dp_get_best_codec(
continue;
}

if (!best_codec || codec->codec_priority > best_codec->codec_priority) {
best_codec = codec;
if (codec->codec_priority >= best_codec.codec_priority) {
best_codec = *codec;
}
}

if (best_codec.codec_priority == -1) {
syslog(LOG_WARNING, "No valid A2DP codec available, fallback to SBC.");
}

return best_codec;
}

Expand All @@ -275,12 +286,8 @@ struct cras_a2dp* cras_floss_a2dp_create(
const char* addr,
const char* name,
struct cras_fl_a2dp_codec_config* codecs) {
struct cras_fl_a2dp_codec_config* codec =
struct cras_fl_a2dp_codec_config codec =
cras_floss_a2dp_get_best_codec(codecs);
if (!codec) {
syslog(LOG_WARNING, "No supported A2dp codec");
return NULL;
}

struct cras_a2dp* a2dp = (struct cras_a2dp*)calloc(1, sizeof(*a2dp));
if (!a2dp) {
Expand All @@ -290,9 +297,9 @@ struct cras_a2dp* cras_floss_a2dp_create(
a2dp->fm = fm;
a2dp->addr = strdup(addr);
a2dp->name = strdup(name);
a2dp->active_codec_type = codec->codec_type;
a2dp->active_codec_type = codec.codec_type;
a2dp->iodev = a2dp_pcm_iodev_create(
a2dp, codec->sample_rate, codec->bits_per_sample, codec->channel_mode);
a2dp, codec.sample_rate, codec.bits_per_sample, codec.channel_mode);

if (!a2dp->iodev) {
syslog(LOG_WARNING, "Failed to create a2dp pcm_iodev for %s", name);
Expand Down
16 changes: 9 additions & 7 deletions cras/src/tests/a2dp_manager_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,17 @@ TEST_F(A2dpManagerTestSuite, CreateFailed) {
a2dp_pcm_iodev_create_ret =
(struct cras_iodev*)calloc(1, sizeof(struct cras_iodev));

// NULL a2dp_codec_configs should fail the a2dp_create without a crash
ASSERT_EQ(cras_floss_a2dp_create(NULL, "addr", "name",
(struct cras_fl_a2dp_codec_config*)NULL),
(struct cras_a2dp*)NULL);
// NULL a2dp_codec_configs should succeed with fallback to default params
struct cras_a2dp* a2dp = cras_floss_a2dp_create(
NULL, "addr", "name", (struct cras_fl_a2dp_codec_config*)NULL);
ASSERT_NE(a2dp, (struct cras_a2dp*)NULL);
cras_floss_a2dp_destroy(a2dp);

// Unsupported codecs should fail the a2dp_create without a crash
// Unsupported codecs should succeed with fallback to default params
a2dp_codecs.codec_type = FL_A2DP_CODEC_SINK_AAC;
ASSERT_EQ(cras_floss_a2dp_create(NULL, "addr", "name", &a2dp_codecs),
(struct cras_a2dp*)NULL);
a2dp = cras_floss_a2dp_create(NULL, "addr", "name", &a2dp_codecs);
ASSERT_NE(a2dp, (struct cras_a2dp*)NULL);
cras_floss_a2dp_destroy(a2dp);
}

TEST_F(A2dpManagerTestSuite, CreateDestroy) {
Expand Down

0 comments on commit 079d5db

Please sign in to comment.