1 /* 2 * Copyright 2023 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 #pragma once 18 19 #include <condition_variable> 20 #include <mutex> 21 22 #include <android-base/thread_annotations.h> 23 24 #include <aidl/android/hardware/audio/common/SinkMetadata.h> 25 #include <aidl/android/hardware/audio/common/SourceMetadata.h> 26 #include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h> 27 #include <aidl/android/hardware/bluetooth/audio/PcmConfiguration.h> 28 #include <aidl/android/hardware/bluetooth/audio/SessionType.h> 29 #include <aidl/android/media/audio/common/AudioDeviceDescription.h> 30 31 #include "BluetoothAudioSessionControl.h" 32 33 namespace android::bluetooth::audio::aidl { 34 35 enum class BluetoothStreamState : uint8_t { 36 DISABLED = 0, // This stream is closing or Bluetooth profiles (A2DP/LE) is disabled 37 STANDBY, 38 STARTING, 39 STARTED, 40 SUSPENDING, 41 UNKNOWN, 42 }; 43 44 std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state); 45 46 /** 47 * Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio 48 * Session Control. All methods are not thread safe, so users must acquire a 49 * lock. Note: currently, getState() of DevicePortProxy is only used for 50 * verbose logging, it is not locked, so the state may not be synchronized. 51 */ 52 class BluetoothAudioPort { 53 public: 54 BluetoothAudioPort() = default; 55 virtual ~BluetoothAudioPort() = default; 56 57 /** 58 * Fetch output control / data path of BluetoothAudioPort and setup 59 * callbacks into BluetoothAudioProvider. If registerPort() returns false, the audio 60 * HAL must delete this BluetoothAudioPort and return EINVAL to caller 61 */ 62 virtual bool registerPort( 63 const ::aidl::android::media::audio::common::AudioDeviceDescription&) = 0; 64 65 /** 66 * Unregister this BluetoothAudioPort from BluetoothAudioSessionControl. 67 * Audio HAL must delete this BluetoothAudioPort after calling this. 68 */ 69 virtual void unregisterPort() = 0; 70 71 /** 72 * When the Audio framework / HAL tries to query audio config about format, 73 * channel mask and sample rate, it uses this function to fetch from the 74 * Bluetooth stack 75 */ 76 virtual bool loadAudioConfig( 77 ::aidl::android::hardware::bluetooth::audio::PcmConfiguration*) const = 0; 78 79 /** 80 * WAR to support Mono mode / 16 bits per sample 81 */ 82 virtual void forcePcmStereoToMono(bool) = 0; 83 84 /** 85 * When the Audio framework / HAL wants to change the stream state, it invokes 86 * these 4 functions to control the Bluetooth stack (Audio Control Path). 87 * Note: standby(), start() and suspend() will return true when there are no errors. 88 89 * Called by Audio framework / HAL to change the state to stand by. When A2DP/LE profile is 90 * disabled, the port is first set to STANDBY by calling suspend and then mState is set to 91 * DISABLED. To reset the state back to STANDBY this method is called. 92 */ 93 virtual bool standby() = 0; 94 95 /** 96 * Called by Audio framework / HAL to start the stream 97 */ 98 virtual bool start() = 0; 99 100 /** 101 * Called by Audio framework / HAL to suspend the stream 102 */ 103 virtual bool suspend() = 0; 104 105 /** 106 * Called by Audio framework / HAL to stop the stream 107 */ 108 virtual void stop() = 0; 109 110 /** 111 * Called by the Audio framework / HAL to fetch information about audio frames 112 * presented to an external sink, or frames presented fror an internal sink 113 */ 114 virtual bool getPresentationPosition( 115 ::aidl::android::hardware::bluetooth::audio::PresentationPosition&) const = 0; 116 117 /** 118 * Called by the Audio framework / HAL when the metadata of the stream's 119 * source has been changed. 120 */ updateSourceMetadata(const::aidl::android::hardware::audio::common::SourceMetadata &)121 virtual bool updateSourceMetadata( 122 const ::aidl::android::hardware::audio::common::SourceMetadata&) const { 123 return false; 124 } 125 126 /** 127 * Called by the Audio framework / HAL when the metadata of the stream's 128 * sink has been changed. 129 */ updateSinkMetadata(const::aidl::android::hardware::audio::common::SinkMetadata &)130 virtual bool updateSinkMetadata( 131 const ::aidl::android::hardware::audio::common::SinkMetadata&) const { 132 return false; 133 } 134 135 /** 136 * Return the current BluetoothStreamState 137 */ 138 virtual BluetoothStreamState getState() const = 0; 139 140 /** 141 * Set the current BluetoothStreamState 142 */ 143 virtual bool setState(BluetoothStreamState) = 0; 144 145 virtual bool isA2dp() const = 0; 146 147 virtual bool isLeAudio() const = 0; 148 149 virtual bool getPreferredDataIntervalUs(size_t*) const = 0; 150 writeData(const void *,size_t)151 virtual size_t writeData(const void*, size_t) const { return 0; } 152 readData(void *,size_t)153 virtual size_t readData(void*, size_t) const { return 0; } 154 }; 155 156 class BluetoothAudioPortAidl : public BluetoothAudioPort { 157 public: 158 BluetoothAudioPortAidl(); 159 virtual ~BluetoothAudioPortAidl(); 160 161 bool registerPort(const ::aidl::android::media::audio::common::AudioDeviceDescription& 162 description) override; 163 164 void unregisterPort() override; 165 166 bool loadAudioConfig(::aidl::android::hardware::bluetooth::audio::PcmConfiguration* audio_cfg) 167 const override; 168 forcePcmStereoToMono(bool force)169 void forcePcmStereoToMono(bool force) override { mIsStereoToMono = force; } 170 171 bool standby() override; 172 bool start() override; 173 bool suspend() override; 174 void stop() override; 175 176 bool getPresentationPosition(::aidl::android::hardware::bluetooth::audio::PresentationPosition& 177 presentation_position) const override; 178 179 bool updateSourceMetadata(const ::aidl::android::hardware::audio::common::SourceMetadata& 180 sourceMetadata) const override; 181 182 bool updateSinkMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata& 183 sinkMetadata) const override; 184 185 /** 186 * Return the current BluetoothStreamState 187 * Note: This method is used for logging, does not lock, so value returned may not be latest 188 */ 189 BluetoothStreamState getState() const override NO_THREAD_SAFETY_ANALYSIS; 190 191 bool setState(BluetoothStreamState state) override; 192 193 bool isA2dp() const override; 194 195 bool isLeAudio() const override; 196 197 bool getPreferredDataIntervalUs(size_t* interval_us) const override; 198 199 protected: 200 uint16_t mCookie; 201 BluetoothStreamState mState GUARDED_BY(mCvMutex); 202 ::aidl::android::hardware::bluetooth::audio::SessionType mSessionType; 203 // WR to support Mono: True if fetching Stereo and mixing into Mono 204 bool mIsStereoToMono = false; 205 206 bool inUse() const; 207 208 std::string debugMessage() const; 209 210 private: 211 // start()/suspend() report state change status via callback. Wait until kMaxWaitingTimeMs or a 212 // state change after a call to start()/suspend() and analyse the returned status. Below mutex, 213 // conditional variable serves this purpose. 214 mutable std::mutex mCvMutex; 215 std::condition_variable mInternalCv GUARDED_BY(mCvMutex); 216 217 // Check and initialize session type for |devices| If failed, this 218 // BluetoothAudioPortAidl is not initialized and must be deleted. 219 bool initSessionType( 220 const ::aidl::android::media::audio::common::AudioDeviceDescription& description); 221 222 bool condWaitState(BluetoothStreamState state); 223 224 void controlResultHandler( 225 uint16_t cookie, 226 const ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus& status); 227 void sessionChangedHandler(uint16_t cookie); 228 }; 229 230 class BluetoothAudioPortAidlOut : public BluetoothAudioPortAidl { 231 public: 232 // The audio data path to the Bluetooth stack (Software encoding) 233 size_t writeData(const void* buffer, size_t bytes) const override; 234 }; 235 236 class BluetoothAudioPortAidlIn : public BluetoothAudioPortAidl { 237 public: 238 // The audio data path from the Bluetooth stack (Software decoded) 239 size_t readData(void* buffer, size_t bytes) const override; 240 }; 241 242 } // namespace android::bluetooth::audio::aidl