1 /*
2  * Copyright 2019 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 <android/hardware/bluetooth/audio/2.1/types.h>
20 #include <hardware/audio.h>
21 #include <condition_variable>
22 #include <mutex>
23 #include <unordered_map>
24 
25 enum class BluetoothStreamState : uint8_t;
26 
27 namespace android {
28 namespace bluetooth {
29 namespace audio {
30 
31 using SessionType_2_1 =
32     ::android::hardware::bluetooth::audio::V2_1::SessionType;
33 
34 // Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio
35 // Session Control. All methods are not thread safe, so users must acquire a
36 // lock. Note: currently, in stream_apis.cc, if GetState() is only used for
37 // verbose logging, it is not locked, so the state may not be synchronized.
38 class BluetoothAudioPort {
39  public:
40   BluetoothAudioPort();
41   virtual ~BluetoothAudioPort() = default;
42 
43   // Fetch output control / data path of BluetoothAudioPort and setup
44   // callbacks into BluetoothAudioProvider. If SetUp() returns false, the audio
45   // HAL must delete this BluetoothAudioPort and return EINVAL to caller
46   bool SetUp(audio_devices_t devices);
47 
48   // Unregister this BluetoothAudioPort from BluetoothAudioSessionControl.
49   // Audio HAL must delete this BluetoothAudioPort after calling this.
50   void TearDown();
51 
52   // When the Audio framework / HAL tries to query audio config about format,
53   // channel mask and sample rate, it uses this function to fetch from the
54   // Bluetooth stack
55   virtual bool LoadAudioConfig(audio_config_t* audio_cfg) const = 0;
56 
57   // WAR to support Mono mode / 16 bits per sample
ForcePcmStereoToMono(bool force)58   void ForcePcmStereoToMono(bool force) {
59     is_stereo_to_mono_ = force;
60   }
61 
62   // When the Audio framework / HAL wants to change the stream state, it invokes
63   // these 3 functions to control the Bluetooth stack (Audio Control Path).
64   // Note: Both Start() and Suspend() will return ture when there are no errors.
65   // Called by Audio framework / HAL to start the stream
66   bool Start();
67   // Called by Audio framework / HAL to suspend the stream
68   bool Suspend();
69   // Called by Audio framework / HAL to stop the stream
70   void Stop();
71 
72   // Called by the Audio framework / HAL to fetch informaiton about audio frames
73   // presented to an external sink, or frames presented fror an internal sink
74   bool GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes,
75                                timespec* timestamp) const;
76 
77   // Called by the Audio framework / HAL when the metadata of the stream's
78   // source has been changed.
79   void UpdateMetadata(const source_metadata* source_metadata) const;
80 
81   // Return the current BluetoothStreamState
82   BluetoothStreamState GetState() const;
83 
84   // Set the current BluetoothStreamState
85   void SetState(BluetoothStreamState state);
86 
IsA2dp()87   bool IsA2dp() const {
88     return session_type_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
89            session_type_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH;
90   }
91 
92  protected:
93   uint16_t cookie_;
94   BluetoothStreamState state_;
95   SessionType_2_1 session_type_;
96   // WR to support Mono: True if fetching Stereo and mixing into Mono
97   bool is_stereo_to_mono_ = false;
98   bool in_use() const;
99 
100  private:
101   mutable std::mutex cv_mutex_;
102   std::condition_variable internal_cv_;
103 
104   // Check and initialize session type for |devices| If failed, this
105   // BluetoothAudioPort is not initialized and must be deleted.
106   bool init_session_type(audio_devices_t device);
107 
108   bool CondwaitState(BluetoothStreamState state);
109 
110   void ControlResultHandler(
111       const ::android::hardware::bluetooth::audio::V2_0::Status& status);
112   void SessionChangedHandler();
113 };
114 
115 class BluetoothAudioPortOut : public BluetoothAudioPort {
116  public:
117   ~BluetoothAudioPortOut() = default;
118 
119   // The audio data path to the Bluetooth stack (Software encoding)
120   size_t WriteData(const void* buffer, size_t bytes) const;
121   bool LoadAudioConfig(audio_config_t* audio_cfg) const;
122 };
123 
124 class BluetoothAudioPortIn : public BluetoothAudioPort {
125  public:
126   ~BluetoothAudioPortIn() = default;
127 
128   // The audio data path from the Bluetooth stack (Software decoded)
129   size_t ReadData(void* buffer, size_t bytes) const;
130   bool LoadAudioConfig(audio_config_t* audio_cfg) const;
131 };
132 
133 }  // namespace audio
134 }  // namespace bluetooth
135 }  // namespace android
136