1 /*
2 * Copyright 2020 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 "BTAudioProviderStub"
18
19 #include "BluetoothAudioProvider.h"
20
21 #include <android-base/logging.h>
22
23 #include "BluetoothAudioSessionReport_2_1.h"
24 #include "BluetoothAudioSupportedCodecsDB_2_1.h"
25
26 namespace android {
27 namespace hardware {
28 namespace bluetooth {
29 namespace audio {
30 namespace V2_1 {
31 namespace implementation {
32
33 using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_1;
34 using ::android::hardware::kSynchronizedReadWrite;
35 using ::android::hardware::MessageQueue;
36 using ::android::hardware::Void;
37
38 using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
39
serviceDied(uint64_t cookie __unused,const wp<::android::hidl::base::V1_0::IBase> & who __unused)40 void BluetoothAudioDeathRecipient::serviceDied(
41 uint64_t cookie __unused,
42 const wp<::android::hidl::base::V1_0::IBase>& who __unused) {
43 LOG(ERROR) << "BluetoothAudioDeathRecipient::" << __func__
44 << " - BluetoothAudio Service died";
45 provider_->endSession();
46 }
47
BluetoothAudioProvider()48 BluetoothAudioProvider::BluetoothAudioProvider()
49 : death_recipient_(new BluetoothAudioDeathRecipient(this)),
50 session_type_(SessionType::UNKNOWN),
51 audio_config_({}) {}
52
startSession(const sp<IBluetoothAudioPort> & hostIf,const V2_0::AudioConfiguration & audioConfig,startSession_cb _hidl_cb)53 Return<void> BluetoothAudioProvider::startSession(
54 const sp<IBluetoothAudioPort>& hostIf,
55 const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
56 AudioConfiguration audioConfig_2_1;
57
58 if (audioConfig.getDiscriminator() ==
59 V2_0::AudioConfiguration::hidl_discriminator::pcmConfig) {
60 audioConfig_2_1.pcmConfig({
61 .sampleRate =
62 static_cast<SampleRate>(audioConfig.pcmConfig().sampleRate),
63 .channelMode = audioConfig.pcmConfig().channelMode,
64 .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
65 .dataIntervalUs = 0});
66 } else {
67 audioConfig_2_1.codecConfig(audioConfig.codecConfig());
68 }
69
70 return startSession_2_1(hostIf, audioConfig_2_1, _hidl_cb);
71 }
72
startSession_2_1(const sp<IBluetoothAudioPort> & hostIf,const AudioConfiguration & audioConfig,startSession_cb _hidl_cb)73 Return<void> BluetoothAudioProvider::startSession_2_1(
74 const sp<IBluetoothAudioPort>& hostIf,
75 const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
76 if (hostIf == nullptr) {
77 _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
78 return Void();
79 }
80
81 /**
82 * Initialize the audio platform if audioConfiguration is supported.
83 * Save the IBluetoothAudioPort interface, so that it can be used
84 * later to send stream control commands to the HAL client, based on
85 * interaction with Audio framework.
86 */
87 audio_config_ = audioConfig;
88 stack_iface_ = hostIf;
89 stack_iface_->linkToDeath(death_recipient_, 0);
90
91 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
92 << ", AudioConfiguration=[" << toString(audio_config_) << "]";
93
94 onSessionReady(_hidl_cb);
95 return Void();
96 }
97
streamStarted(BluetoothAudioStatus status)98 Return<void> BluetoothAudioProvider::streamStarted(
99 BluetoothAudioStatus status) {
100 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
101 << ", status=" << toString(status);
102
103 /**
104 * Streaming on control path has started,
105 * HAL server should start the streaming on data path.
106 */
107 if (stack_iface_) {
108 BluetoothAudioSessionReport_2_1::ReportControlStatus(session_type_, true,
109 status);
110 } else {
111 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
112 << ", status=" << toString(status) << " has NO session";
113 }
114
115 return Void();
116 }
117
streamSuspended(BluetoothAudioStatus status)118 Return<void> BluetoothAudioProvider::streamSuspended(
119 BluetoothAudioStatus status) {
120 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
121 << ", status=" << toString(status);
122
123 /**
124 * Streaming on control path has suspend,
125 * HAL server should suspend the streaming on data path.
126 */
127 if (stack_iface_) {
128 BluetoothAudioSessionReport_2_1::ReportControlStatus(session_type_, false,
129 status);
130 } else {
131 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
132 << ", status=" << toString(status) << " has NO session";
133 }
134
135 return Void();
136 }
137
endSession()138 Return<void> BluetoothAudioProvider::endSession() {
139 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
140
141 if (stack_iface_) {
142 BluetoothAudioSessionReport_2_1::OnSessionEnded(session_type_);
143 stack_iface_->unlinkToDeath(death_recipient_);
144 } else {
145 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
146 << " has NO session";
147 }
148
149 /**
150 * Clean up the audio platform as remote audio device is no
151 * longer active
152 */
153 stack_iface_ = nullptr;
154 audio_config_ = {};
155
156 return Void();
157 }
158
159 } // namespace implementation
160 } // namespace V2_1
161 } // namespace audio
162 } // namespace bluetooth
163 } // namespace hardware
164 } // namespace android
165