blob: ba7a89d8befa79de9bae7aca6bf2f7f247a88809 [file] [log] [blame]
Josh Wu6ab53e72021-12-29 23:53:33 -08001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "BTAudioProviderA2dpHW"
18
19#include "A2dpOffloadAudioProvider.h"
20
21#include <BluetoothAudioCodecs.h>
22#include <BluetoothAudioSessionReport.h>
23#include <android-base/logging.h>
24
Antoine SOULIER4e34d052023-09-29 19:10:07 +000025#include "A2dpOffloadCodecAac.h"
26#include "A2dpOffloadCodecFactory.h"
27#include "A2dpOffloadCodecSbc.h"
28
Josh Wu6ab53e72021-12-29 23:53:33 -080029namespace aidl {
30namespace android {
31namespace hardware {
32namespace bluetooth {
33namespace audio {
34
Alice Kuoadcceec2022-03-28 13:28:43 +080035A2dpOffloadEncodingAudioProvider::A2dpOffloadEncodingAudioProvider()
36 : A2dpOffloadAudioProvider() {
Josh Wu6ab53e72021-12-29 23:53:33 -080037 session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
38}
39
Alice Kuoadcceec2022-03-28 13:28:43 +080040A2dpOffloadDecodingAudioProvider::A2dpOffloadDecodingAudioProvider()
41 : A2dpOffloadAudioProvider() {
42 session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH;
43}
44
45A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() {}
46
Josh Wu6ab53e72021-12-29 23:53:33 -080047bool A2dpOffloadAudioProvider::isValid(const SessionType& session_type) {
48 return (session_type == session_type_);
49}
50
51ndk::ScopedAStatus A2dpOffloadAudioProvider::startSession(
52 const std::shared_ptr<IBluetoothAudioPort>& host_if,
Chen Chenc92270e2022-02-14 18:29:52 -080053 const AudioConfiguration& audio_config,
Cheney Ni6ecbc762022-03-03 00:12:48 +080054 const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
Antoine SOULIER4e34d052023-09-29 19:10:07 +000055 if (audio_config.getTag() == AudioConfiguration::Tag::a2dp) {
56 auto a2dp_config = audio_config.get<AudioConfiguration::Tag::a2dp>();
57 A2dpStatus a2dp_status = A2dpStatus::NOT_SUPPORTED_CODEC_TYPE;
58
59 if (a2dp_config.codecId ==
60 A2dpOffloadCodecSbc::GetInstance()->GetCodecId()) {
61 SbcParameters sbc_parameters;
62 a2dp_status = A2dpOffloadCodecSbc::GetInstance()->ParseConfiguration(
63 a2dp_config.configuration, &sbc_parameters);
64
65 } else if (a2dp_config.codecId ==
66 A2dpOffloadCodecAac::GetInstance()->GetCodecId()) {
67 AacParameters aac_parameters;
68 a2dp_status = A2dpOffloadCodecAac::GetInstance()->ParseConfiguration(
69 a2dp_config.configuration, &aac_parameters);
70 }
71 if (a2dp_status != A2dpStatus::OK) {
72 LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
73 << audio_config.toString();
74 *_aidl_return = DataMQDesc();
75 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
76 }
77 } else if (audio_config.getTag() == AudioConfiguration::Tag::a2dpConfig) {
78 if (!BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
79 session_type_,
80 audio_config.get<AudioConfiguration::a2dpConfig>())) {
81 LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
82 << audio_config.toString();
83 *_aidl_return = DataMQDesc();
84 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
85 }
86 } else {
Josh Wu6ab53e72021-12-29 23:53:33 -080087 LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
88 << audio_config.toString();
89 *_aidl_return = DataMQDesc();
90 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
91 }
Antoine SOULIER4e34d052023-09-29 19:10:07 +000092
Chen Chenc92270e2022-02-14 18:29:52 -080093 return BluetoothAudioProvider::startSession(
94 host_if, audio_config, latency_modes, _aidl_return);
Josh Wu6ab53e72021-12-29 23:53:33 -080095}
96
97ndk::ScopedAStatus A2dpOffloadAudioProvider::onSessionReady(
98 DataMQDesc* _aidl_return) {
99 *_aidl_return = DataMQDesc();
Cheney Ni6ecbc762022-03-03 00:12:48 +0800100 BluetoothAudioSessionReport::OnSessionStarted(
101 session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
Josh Wu6ab53e72021-12-29 23:53:33 -0800102 return ndk::ScopedAStatus::ok();
103}
104
Antoine SOULIER4e34d052023-09-29 19:10:07 +0000105ndk::ScopedAStatus A2dpOffloadAudioProvider::parseA2dpConfiguration(
106 const CodecId& codec_id, const std::vector<uint8_t>& configuration,
107 CodecParameters* codec_parameters, A2dpStatus* _aidl_return) {
108 auto codec = A2dpOffloadCodecFactory::GetInstance()->GetCodec(codec_id);
109 if (!codec) {
110 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
111 << " - CodecId=" << codec_id.toString() << " is not found";
112 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
113 }
114
115 *_aidl_return = codec->ParseConfiguration(configuration, codec_parameters);
116
117 return ndk::ScopedAStatus::ok();
118}
119
120ndk::ScopedAStatus A2dpOffloadAudioProvider::getA2dpConfiguration(
121 const std::vector<A2dpRemoteCapabilities>& remote_a2dp_capabilities,
122 const A2dpConfigurationHint& hint,
123 std::optional<audio::A2dpConfiguration>* _aidl_return) {
124 *_aidl_return = std::nullopt;
125 A2dpConfiguration avdtp_configuration;
126
127 if (A2dpOffloadCodecFactory::GetInstance()->GetConfiguration(
128 remote_a2dp_capabilities, hint, &avdtp_configuration))
129 *_aidl_return =
130 std::make_optional<A2dpConfiguration>(std::move(avdtp_configuration));
131
132 return ndk::ScopedAStatus::ok();
133}
134
Josh Wu6ab53e72021-12-29 23:53:33 -0800135} // namespace audio
136} // namespace bluetooth
137} // namespace hardware
138} // namespace android
Cheney Ni6ecbc762022-03-03 00:12:48 +0800139} // namespace aidl