1*05767d91SRobert Wu /* 2*05767d91SRobert Wu * Copyright 2019 The Android Open Source Project 3*05767d91SRobert Wu * 4*05767d91SRobert Wu * Licensed under the Apache License, Version 2.0 (the "License"); 5*05767d91SRobert Wu * you may not use this file except in compliance with the License. 6*05767d91SRobert Wu * You may obtain a copy of the License at 7*05767d91SRobert Wu * 8*05767d91SRobert Wu * http://www.apache.org/licenses/LICENSE-2.0 9*05767d91SRobert Wu * 10*05767d91SRobert Wu * Unless required by applicable law or agreed to in writing, software 11*05767d91SRobert Wu * distributed under the License is distributed on an "AS IS" BASIS, 12*05767d91SRobert Wu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*05767d91SRobert Wu * See the License for the specific language governing permissions and 14*05767d91SRobert Wu * limitations under the License. 15*05767d91SRobert Wu */ 16*05767d91SRobert Wu 17*05767d91SRobert Wu #ifndef OBOE_QUIRKS_MANAGER_H 18*05767d91SRobert Wu #define OBOE_QUIRKS_MANAGER_H 19*05767d91SRobert Wu 20*05767d91SRobert Wu #include <memory> 21*05767d91SRobert Wu #include <oboe/AudioStreamBuilder.h> 22*05767d91SRobert Wu #include <aaudio/AudioStreamAAudio.h> 23*05767d91SRobert Wu 24*05767d91SRobert Wu #ifndef __ANDROID_API_R__ 25*05767d91SRobert Wu #define __ANDROID_API_R__ 30 26*05767d91SRobert Wu #endif 27*05767d91SRobert Wu 28*05767d91SRobert Wu namespace oboe { 29*05767d91SRobert Wu 30*05767d91SRobert Wu /** 31*05767d91SRobert Wu * INTERNAL USE ONLY. 32*05767d91SRobert Wu * 33*05767d91SRobert Wu * Based on manufacturer, model and Android version number 34*05767d91SRobert Wu * decide whether data conversion needs to occur. 35*05767d91SRobert Wu * 36*05767d91SRobert Wu * This also manages device and version specific workarounds. 37*05767d91SRobert Wu */ 38*05767d91SRobert Wu 39*05767d91SRobert Wu class QuirksManager { 40*05767d91SRobert Wu public: 41*05767d91SRobert Wu getInstance()42*05767d91SRobert Wu static QuirksManager &getInstance() { 43*05767d91SRobert Wu static QuirksManager instance; // singleton 44*05767d91SRobert Wu return instance; 45*05767d91SRobert Wu } 46*05767d91SRobert Wu 47*05767d91SRobert Wu QuirksManager(); 48*05767d91SRobert Wu virtual ~QuirksManager() = default; 49*05767d91SRobert Wu 50*05767d91SRobert Wu /** 51*05767d91SRobert Wu * Do we need to do channel, format or rate conversion to provide a low latency 52*05767d91SRobert Wu * stream for this builder? If so then provide a builder for the native child stream 53*05767d91SRobert Wu * that will be used to get low latency. 54*05767d91SRobert Wu * 55*05767d91SRobert Wu * @param builder builder provided by application 56*05767d91SRobert Wu * @param childBuilder modified builder appropriate for the underlying device 57*05767d91SRobert Wu * @return true if conversion is needed 58*05767d91SRobert Wu */ 59*05767d91SRobert Wu bool isConversionNeeded(const AudioStreamBuilder &builder, AudioStreamBuilder &childBuilder); 60*05767d91SRobert Wu isMMapUsed(AudioStream & stream)61*05767d91SRobert Wu static bool isMMapUsed(AudioStream &stream) { 62*05767d91SRobert Wu bool answer = false; 63*05767d91SRobert Wu if (stream.getAudioApi() == AudioApi::AAudio) { 64*05767d91SRobert Wu AudioStreamAAudio *streamAAudio = 65*05767d91SRobert Wu reinterpret_cast<AudioStreamAAudio *>(&stream); 66*05767d91SRobert Wu answer = streamAAudio->isMMapUsed(); 67*05767d91SRobert Wu } 68*05767d91SRobert Wu return answer; 69*05767d91SRobert Wu } 70*05767d91SRobert Wu clipBufferSize(AudioStream & stream,int32_t bufferSize)71*05767d91SRobert Wu virtual int32_t clipBufferSize(AudioStream &stream, int32_t bufferSize) { 72*05767d91SRobert Wu return mDeviceQuirks->clipBufferSize(stream, bufferSize); 73*05767d91SRobert Wu } 74*05767d91SRobert Wu 75*05767d91SRobert Wu class DeviceQuirks { 76*05767d91SRobert Wu public: 77*05767d91SRobert Wu virtual ~DeviceQuirks() = default; 78*05767d91SRobert Wu 79*05767d91SRobert Wu /** 80*05767d91SRobert Wu * Restrict buffer size. This is mainly to avoid glitches caused by MMAP 81*05767d91SRobert Wu * timestamp inaccuracies. 82*05767d91SRobert Wu * @param stream 83*05767d91SRobert Wu * @param requestedSize 84*05767d91SRobert Wu * @return 85*05767d91SRobert Wu */ 86*05767d91SRobert Wu int32_t clipBufferSize(AudioStream &stream, int32_t requestedSize); 87*05767d91SRobert Wu 88*05767d91SRobert Wu // Exclusive MMAP streams can have glitches because they are using a timing 89*05767d91SRobert Wu // model of the DSP to control IO instead of direct synchronization. getExclusiveBottomMarginInBursts()90*05767d91SRobert Wu virtual int32_t getExclusiveBottomMarginInBursts() const { 91*05767d91SRobert Wu return kDefaultBottomMarginInBursts; 92*05767d91SRobert Wu } 93*05767d91SRobert Wu getExclusiveTopMarginInBursts()94*05767d91SRobert Wu virtual int32_t getExclusiveTopMarginInBursts() const { 95*05767d91SRobert Wu return kDefaultTopMarginInBursts; 96*05767d91SRobert Wu } 97*05767d91SRobert Wu 98*05767d91SRobert Wu // On some devices, you can open a mono stream but it is actually running in stereo! isMonoMMapActuallyStereo()99*05767d91SRobert Wu virtual bool isMonoMMapActuallyStereo() const { 100*05767d91SRobert Wu return false; 101*05767d91SRobert Wu } 102*05767d91SRobert Wu 103*05767d91SRobert Wu virtual bool isAAudioMMapPossible(const AudioStreamBuilder &builder) const; 104*05767d91SRobert Wu isMMapSafe(const AudioStreamBuilder &)105*05767d91SRobert Wu virtual bool isMMapSafe(const AudioStreamBuilder & /* builder */ ) { 106*05767d91SRobert Wu return true; 107*05767d91SRobert Wu } 108*05767d91SRobert Wu 109*05767d91SRobert Wu // On some devices, Float does not work so it should be converted to I16. 110*05767d91SRobert Wu static bool shouldConvertFloatToI16ForOutputStreams(); 111*05767d91SRobert Wu 112*05767d91SRobert Wu static constexpr int32_t kDefaultBottomMarginInBursts = 0; 113*05767d91SRobert Wu static constexpr int32_t kDefaultTopMarginInBursts = 0; 114*05767d91SRobert Wu 115*05767d91SRobert Wu // For Legacy streams, do not let the buffer go below one burst. 116*05767d91SRobert Wu // b/129545119 | AAudio Legacy allows setBufferSizeInFrames too low 117*05767d91SRobert Wu // Fixed in Q 118*05767d91SRobert Wu static constexpr int32_t kLegacyBottomMarginInBursts = 1; 119*05767d91SRobert Wu static constexpr int32_t kCommonNativeRate = 48000; // very typical native sample rate 120*05767d91SRobert Wu }; 121*05767d91SRobert Wu 122*05767d91SRobert Wu bool isMMapSafe(AudioStreamBuilder &builder); 123*05767d91SRobert Wu 124*05767d91SRobert Wu private: 125*05767d91SRobert Wu 126*05767d91SRobert Wu static constexpr int32_t kChannelCountMono = 1; 127*05767d91SRobert Wu static constexpr int32_t kChannelCountStereo = 2; 128*05767d91SRobert Wu 129*05767d91SRobert Wu std::unique_ptr<DeviceQuirks> mDeviceQuirks{}; 130*05767d91SRobert Wu 131*05767d91SRobert Wu }; 132*05767d91SRobert Wu 133*05767d91SRobert Wu } 134*05767d91SRobert Wu #endif //OBOE_QUIRKS_MANAGER_H 135