| /* |
| * Copyright 2023 The Android Open 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 <condition_variable> |
| #include <mutex> |
| |
| #include <android-base/thread_annotations.h> |
| |
| #include <aidl/android/hardware/audio/common/SinkMetadata.h> |
| #include <aidl/android/hardware/audio/common/SourceMetadata.h> |
| #include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h> |
| #include <aidl/android/hardware/bluetooth/audio/PcmConfiguration.h> |
| #include <aidl/android/hardware/bluetooth/audio/PresentationPosition.h> |
| #include <aidl/android/hardware/bluetooth/audio/SessionType.h> |
| #include <aidl/android/media/audio/common/AudioDeviceDescription.h> |
| |
| namespace android::bluetooth::audio::aidl { |
| |
| enum class BluetoothStreamState : uint8_t { |
| DISABLED = 0, // This stream is closing or Bluetooth profiles (A2DP/LE) is disabled |
| STANDBY, |
| STARTING, |
| STARTED, |
| SUSPENDING, |
| UNKNOWN, |
| }; |
| |
| std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state); |
| |
| /** |
| * Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio |
| * Session Control. All methods are not thread safe, so users must acquire a |
| * lock. Note: currently, getState() of DevicePortProxy is only used for |
| * verbose logging, it is not locked, so the state may not be synchronized. |
| */ |
| class BluetoothAudioPort { |
| public: |
| BluetoothAudioPort() = default; |
| virtual ~BluetoothAudioPort() = default; |
| |
| /** |
| * Fetch output control / data path of BluetoothAudioPort and setup |
| * callbacks into BluetoothAudioProvider. If registerPort() returns false, the audio |
| * HAL must delete this BluetoothAudioPort and return EINVAL to caller |
| */ |
| virtual bool registerPort( |
| const ::aidl::android::media::audio::common::AudioDeviceDescription&) = 0; |
| |
| /** |
| * Unregister this BluetoothAudioPort from BluetoothAudioSessionControl. |
| * Audio HAL must delete this BluetoothAudioPort after calling this. |
| */ |
| virtual void unregisterPort() = 0; |
| |
| /** |
| * When the Audio framework / HAL tries to query audio config about format, |
| * channel mask and sample rate, it uses this function to fetch from the |
| * Bluetooth stack |
| */ |
| virtual bool loadAudioConfig( |
| ::aidl::android::hardware::bluetooth::audio::PcmConfiguration&) = 0; |
| |
| /** |
| * When the Audio framework / HAL wants to change the stream state, it invokes |
| * these 4 functions to control the Bluetooth stack (Audio Control Path). |
| * Note: standby(), start() and suspend() will return true when there are no errors. |
| |
| * Called by Audio framework / HAL to change the state to stand by. When A2DP/LE profile is |
| * disabled, the port is first set to STANDBY by calling suspend and then mState is set to |
| * DISABLED. To reset the state back to STANDBY this method is called. |
| */ |
| virtual bool standby() = 0; |
| |
| /** |
| * Called by Audio framework / HAL to start the stream |
| */ |
| virtual bool start() = 0; |
| |
| /** |
| * Called by Audio framework / HAL to suspend the stream |
| */ |
| virtual bool suspend() = 0; |
| |
| /** |
| * Called by Audio framework / HAL to stop the stream |
| */ |
| virtual void stop() = 0; |
| |
| /** |
| * Called by the Audio framework / HAL to fetch information about audio frames |
| * presented to an external sink, or frames presented fror an internal sink |
| */ |
| virtual bool getPresentationPosition( |
| ::aidl::android::hardware::bluetooth::audio::PresentationPosition&) const = 0; |
| |
| /** |
| * Called by the Audio framework / HAL when the metadata of the stream's |
| * source has been changed. |
| */ |
| virtual bool updateSourceMetadata( |
| const ::aidl::android::hardware::audio::common::SourceMetadata&) const { |
| return false; |
| } |
| |
| /** |
| * Called by the Audio framework / HAL when the metadata of the stream's |
| * sink has been changed. |
| */ |
| virtual bool updateSinkMetadata( |
| const ::aidl::android::hardware::audio::common::SinkMetadata&) const { |
| return false; |
| } |
| |
| /** |
| * Return the current BluetoothStreamState |
| */ |
| virtual BluetoothStreamState getState() const = 0; |
| |
| /** |
| * Set the current BluetoothStreamState |
| */ |
| virtual bool setState(BluetoothStreamState) = 0; |
| |
| virtual bool isA2dp() const = 0; |
| |
| virtual bool isLeAudio() const = 0; |
| |
| virtual bool getPreferredDataIntervalUs(size_t&) const = 0; |
| |
| virtual size_t writeData(const void*, size_t) const { return 0; } |
| |
| virtual size_t readData(void*, size_t) const { return 0; } |
| }; |
| |
| class BluetoothAudioPortAidl : public BluetoothAudioPort { |
| public: |
| BluetoothAudioPortAidl(); |
| virtual ~BluetoothAudioPortAidl(); |
| |
| bool registerPort(const ::aidl::android::media::audio::common::AudioDeviceDescription& |
| description) override; |
| |
| void unregisterPort() override; |
| |
| bool loadAudioConfig( |
| ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& audio_cfg) override; |
| |
| bool standby() override; |
| bool start() override; |
| bool suspend() override; |
| void stop() override; |
| |
| bool getPresentationPosition(::aidl::android::hardware::bluetooth::audio::PresentationPosition& |
| presentation_position) const override; |
| |
| bool updateSourceMetadata(const ::aidl::android::hardware::audio::common::SourceMetadata& |
| sourceMetadata) const override; |
| |
| bool updateSinkMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata& |
| sinkMetadata) const override; |
| |
| /** |
| * Return the current BluetoothStreamState |
| * Note: This method is used for logging, does not lock, so value returned may not be latest |
| */ |
| BluetoothStreamState getState() const override NO_THREAD_SAFETY_ANALYSIS; |
| |
| bool setState(BluetoothStreamState state) override; |
| |
| bool isA2dp() const override; |
| |
| bool isLeAudio() const override; |
| |
| bool getPreferredDataIntervalUs(size_t& interval_us) const override; |
| |
| protected: |
| uint16_t mCookie; |
| BluetoothStreamState mState GUARDED_BY(mCvMutex); |
| ::aidl::android::hardware::bluetooth::audio::SessionType mSessionType; |
| // WR to support Mono: True if fetching Stereo and mixing into Mono |
| bool mIsStereoToMono = false; |
| |
| bool inUse() const; |
| |
| std::string debugMessage() const; |
| |
| private: |
| // start()/suspend() report state change status via callback. Wait until kMaxWaitingTimeMs or a |
| // state change after a call to start()/suspend() and analyse the returned status. Below mutex, |
| // conditional variable serves this purpose. |
| mutable std::mutex mCvMutex; |
| std::condition_variable mInternalCv GUARDED_BY(mCvMutex); |
| |
| // Check and initialize session type for |devices| If failed, this |
| // BluetoothAudioPortAidl is not initialized and must be deleted. |
| bool initSessionType( |
| const ::aidl::android::media::audio::common::AudioDeviceDescription& description); |
| |
| bool condWaitState(BluetoothStreamState state); |
| |
| void controlResultHandler( |
| uint16_t cookie, |
| const ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus& status); |
| void sessionChangedHandler(uint16_t cookie); |
| }; |
| |
| class BluetoothAudioPortAidlOut : public BluetoothAudioPortAidl { |
| public: |
| bool loadAudioConfig( |
| ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& audio_cfg) override; |
| |
| // The audio data path to the Bluetooth stack (Software encoding) |
| size_t writeData(const void* buffer, size_t bytes) const override; |
| }; |
| |
| class BluetoothAudioPortAidlIn : public BluetoothAudioPortAidl { |
| public: |
| // The audio data path from the Bluetooth stack (Software decoded) |
| size_t readData(void* buffer, size_t bytes) const override; |
| }; |
| |
| } // namespace android::bluetooth::audio::aidl |