1 /* 2 * Copyright (C) 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 <mutex> 20 #include <string> 21 22 #include <android-base/thread_annotations.h> 23 #include <audio_utils/clock.h> 24 25 #include <media/nbaio/MonoPipe.h> 26 #include <media/nbaio/MonoPipeReader.h> 27 28 #include <aidl/android/media/audio/common/AudioChannelLayout.h> 29 #include <aidl/android/media/audio/common/AudioDeviceAddress.h> 30 #include <aidl/android/media/audio/common/AudioFormatDescription.h> 31 32 using aidl::android::media::audio::common::AudioChannelLayout; 33 using aidl::android::media::audio::common::AudioFormatDescription; 34 using aidl::android::media::audio::common::AudioFormatType; 35 using aidl::android::media::audio::common::PcmType; 36 using ::android::MonoPipe; 37 using ::android::MonoPipeReader; 38 using ::android::sp; 39 40 namespace aidl::android::hardware::audio::core::r_submix { 41 42 static constexpr int kDefaultSampleRateHz = 48000; 43 // Value used to divide the MonoPipe buffer into segments that are written to the source and 44 // read from the sink. The maximum latency of the device is the size of the MonoPipe's buffer 45 // the minimum latency is the MonoPipe buffer size divided by this value. 46 static constexpr int kDefaultPipePeriodCount = 4; 47 // Size at the default sample rate 48 // NOTE: This value will be rounded up to the nearest power of 2 by MonoPipe. 49 static constexpr int kDefaultPipeSizeInFrames = 1024 * kDefaultPipePeriodCount; 50 51 // Configuration of the audio stream. 52 struct AudioConfig { 53 int sampleRate = kDefaultSampleRateHz; 54 AudioFormatDescription format = 55 AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT}; 56 AudioChannelLayout channelLayout = 57 AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( 58 AudioChannelLayout::LAYOUT_STEREO); 59 size_t frameSize; 60 size_t frameCount; 61 }; 62 63 class SubmixRoute { 64 public: 65 static std::shared_ptr<SubmixRoute> findOrCreateRoute( 66 const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress, 67 const AudioConfig& pipeConfig); 68 static std::shared_ptr<SubmixRoute> findRoute( 69 const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress); 70 static void removeRoute( 71 const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress); 72 static std::string dumpRoutes(); 73 isStreamInOpen()74 bool isStreamInOpen() { 75 std::lock_guard guard(mLock); 76 return mStreamInOpen; 77 } getStreamInStandby()78 bool getStreamInStandby() { 79 std::lock_guard guard(mLock); 80 return mStreamInStandby; 81 } isStreamOutOpen()82 bool isStreamOutOpen() { 83 std::lock_guard guard(mLock); 84 return mStreamOutOpen; 85 } getStreamOutStandby()86 bool getStreamOutStandby() { 87 std::lock_guard guard(mLock); 88 return mStreamOutStandby; 89 } getReadCounterFrames()90 long getReadCounterFrames() { 91 std::lock_guard guard(mLock); 92 return mReadCounterFrames; 93 } getSink()94 sp<MonoPipe> getSink() { 95 std::lock_guard guard(mLock); 96 return mSink; 97 } getSource()98 sp<MonoPipeReader> getSource() { 99 std::lock_guard guard(mLock); 100 return mSource; 101 } getPipeConfig()102 AudioConfig getPipeConfig() { 103 std::lock_guard guard(mLock); 104 return mPipeConfig; 105 } 106 107 bool isStreamConfigValid(bool isInput, const AudioConfig& streamConfig); 108 void closeStream(bool isInput); 109 ::android::status_t createPipe(const AudioConfig& streamConfig); 110 void exitStandby(bool isInput); 111 bool hasAtleastOneStreamOpen(); 112 int notifyReadError(); 113 void openStream(bool isInput); 114 AudioConfig releasePipe(); 115 ::android::status_t resetPipe(); 116 bool shouldBlockWrite(); 117 void standby(bool isInput); 118 long updateReadCounterFrames(size_t frameCount); 119 120 std::string dump(); 121 122 private: 123 using RoutesMap = std::map<::aidl::android::media::audio::common::AudioDeviceAddress, 124 std::shared_ptr<r_submix::SubmixRoute>>; 125 class RoutesMonitor { 126 public: RoutesMonitor(std::mutex & mutex,RoutesMap & routes)127 RoutesMonitor(std::mutex& mutex, RoutesMap& routes) : mLock(mutex), mRoutes(routes) {} RoutesMonitor(std::mutex & mutex,RoutesMap & routes,bool)128 RoutesMonitor(std::mutex& mutex, RoutesMap& routes, bool /*tryLock*/) 129 : mLock(mutex, std::try_to_lock), mRoutes(routes) {} 130 RoutesMap* operator->() { return &mRoutes; } 131 132 private: 133 std::unique_lock<std::mutex> mLock; 134 RoutesMap& mRoutes; 135 }; 136 137 static RoutesMonitor getRoutes(bool tryLock = false); 138 139 bool isStreamConfigCompatible(const AudioConfig& streamConfig); 140 141 std::mutex mLock; 142 AudioConfig mPipeConfig GUARDED_BY(mLock); 143 bool mStreamInOpen GUARDED_BY(mLock) = false; 144 int mInputRefCount GUARDED_BY(mLock) = 0; 145 bool mStreamInStandby GUARDED_BY(mLock) = true; 146 bool mStreamOutStandbyTransition GUARDED_BY(mLock) = false; 147 bool mStreamOutOpen GUARDED_BY(mLock) = false; 148 bool mStreamOutStandby GUARDED_BY(mLock) = true; 149 // how many frames have been requested to be read since standby 150 long mReadCounterFrames GUARDED_BY(mLock) = 0; 151 152 // Pipe variables: they handle the ring buffer that "pipes" audio: 153 // - from the submix virtual audio output == what needs to be played 154 // remotely, seen as an output for the client 155 // - to the virtual audio source == what is captured by the component 156 // which "records" the submix / virtual audio source, and handles it as needed. 157 // A usecase example is one where the component capturing the audio is then sending it over 158 // Wifi for presentation on a remote Wifi Display device (e.g. a dongle attached to a TV, or a 159 // TV with Wifi Display capabilities), or to a wireless audio player. 160 sp<MonoPipe> mSink GUARDED_BY(mLock); 161 sp<MonoPipeReader> mSource GUARDED_BY(mLock); 162 }; 163 164 } // namespace aidl::android::hardware::audio::core::r_submix 165