• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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