• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef OBOE_QUIRKS_MANAGER_H
18 #define OBOE_QUIRKS_MANAGER_H
19 
20 #include <memory>
21 #include <oboe/AudioStreamBuilder.h>
22 #include <aaudio/AudioStreamAAudio.h>
23 
24 namespace oboe {
25 
26 /**
27  * INTERNAL USE ONLY.
28  *
29  * Based on manufacturer, model and Android version number
30  * decide whether data conversion needs to occur.
31  *
32  * This also manages device and version specific workarounds.
33  */
34 
35 class QuirksManager {
36 public:
37 
getInstance()38     static QuirksManager &getInstance() {
39         static QuirksManager instance; // singleton
40         return instance;
41     }
42 
43     QuirksManager();
44     virtual ~QuirksManager() = default;
45 
46     /**
47      * Do we need to do channel, format or rate conversion to provide a low latency
48      * stream for this builder? If so then provide a builder for the native child stream
49      * that will be used to get low latency.
50      *
51      * @param builder builder provided by application
52      * @param childBuilder modified builder appropriate for the underlying device
53      * @return true if conversion is needed
54      */
55     bool isConversionNeeded(const AudioStreamBuilder &builder, AudioStreamBuilder &childBuilder);
56 
isMMapUsed(AudioStream & stream)57     static bool isMMapUsed(AudioStream &stream) {
58         bool answer = false;
59         if (stream.getAudioApi() == AudioApi::AAudio) {
60             AudioStreamAAudio *streamAAudio =
61                     reinterpret_cast<AudioStreamAAudio *>(&stream);
62             answer = streamAAudio->isMMapUsed();
63         }
64         return answer;
65     }
66 
clipBufferSize(AudioStream & stream,int32_t bufferSize)67     virtual int32_t clipBufferSize(AudioStream &stream, int32_t bufferSize) {
68         return mDeviceQuirks->clipBufferSize(stream, bufferSize);
69     }
70 
71     class DeviceQuirks {
72     public:
73         virtual ~DeviceQuirks() = default;
74 
75         /**
76          * Restrict buffer size. This is mainly to avoid glitches caused by MMAP
77          * timestamp inaccuracies.
78          * @param stream
79          * @param requestedSize
80          * @return
81          */
82         int32_t clipBufferSize(AudioStream &stream, int32_t requestedSize);
83 
84         // Exclusive MMAP streams can have glitches because they are using a timing
85         // model of the DSP to control IO instead of direct synchronization.
getExclusiveBottomMarginInBursts()86         virtual int32_t getExclusiveBottomMarginInBursts() const {
87             return kDefaultBottomMarginInBursts;
88         }
89 
getExclusiveTopMarginInBursts()90         virtual int32_t getExclusiveTopMarginInBursts() const {
91             return kDefaultTopMarginInBursts;
92         }
93 
94         // On some devices, you can open a mono stream but it is actually running in stereo!
isMonoMMapActuallyStereo()95         virtual bool isMonoMMapActuallyStereo() const {
96             return false;
97         }
98 
99         virtual bool isAAudioMMapPossible(const AudioStreamBuilder &builder) const;
100 
101         static constexpr int32_t kDefaultBottomMarginInBursts = 0;
102         static constexpr int32_t kDefaultTopMarginInBursts = 0;
103 
104         // For Legacy streams, do not let the buffer go below one burst.
105         // b/129545119 | AAudio Legacy allows setBufferSizeInFrames too low
106         // Fixed in Q
107         static constexpr int32_t kLegacyBottomMarginInBursts = 1;
108         static constexpr int32_t kCommonNativeRate = 48000; // very typical native sample rate
109     };
110 
111 private:
112 
113     static constexpr int32_t kChannelCountMono = 1;
114     static constexpr int32_t kChannelCountStereo = 2;
115 
116     std::unique_ptr<DeviceQuirks> mDeviceQuirks{};
117 
118 };
119 
120 }
121 #endif //OBOE_QUIRKS_MANAGER_H
122