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