xref: /aosp_15_r20/external/oboe/src/common/QuirksManager.h (revision 05767d913155b055644481607e6fa1e35e2fe72c)
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