1717#ifndef OBOE_AAUDIO_EXTENSIONS_H
1818#define OBOE_AAUDIO_EXTENSIONS_H
1919
20+ #include < algorithm>
2021#include < dlfcn.h>
22+ #include < set>
2123#include < stdint.h>
2224
2325#include < sys/system_properties.h>
@@ -37,22 +39,82 @@ namespace oboe {
3739
3840typedef struct AAudioStreamStruct AAudioStream;
3941
42+ // The output device type collection must be updated if there is any new added output device type
43+ const static std::set<DeviceType> ALL_OUTPUT_DEVICE_TYPES = {
44+ DeviceType::BuiltinEarpiece,
45+ DeviceType::BuiltinSpeaker,
46+ DeviceType::WiredHeadset,
47+ DeviceType::WiredHeadphones,
48+ DeviceType::LineAnalog,
49+ DeviceType::LineDigital,
50+ DeviceType::BluetoothSco,
51+ DeviceType::BluetoothA2dp,
52+ DeviceType::Hdmi,
53+ DeviceType::HdmiArc,
54+ DeviceType::HdmiEarc,
55+ DeviceType::UsbDevice,
56+ DeviceType::UsbHeadset,
57+ DeviceType::UsbAccessory,
58+ DeviceType::Dock,
59+ DeviceType::DockAnalog,
60+ DeviceType::FM,
61+ DeviceType::Telephony,
62+ DeviceType::AuxLine,
63+ DeviceType::IP,
64+ DeviceType::Bus,
65+ DeviceType::HearingAid,
66+ DeviceType::BuiltinSpeakerSafe,
67+ DeviceType::RemoteSubmix,
68+ DeviceType::BleHeadset,
69+ DeviceType::BleSpeaker,
70+ DeviceType::BleBroadcast,
71+ };
72+
73+ // The input device type collection must be updated if there is any new added input device type
74+ const static std::set<DeviceType> ALL_INPUT_DEVICE_TYPES = {
75+ DeviceType::BuiltinMic,
76+ DeviceType::BluetoothSco,
77+ DeviceType::WiredHeadset,
78+ DeviceType::Hdmi,
79+ DeviceType::Telephony,
80+ DeviceType::Dock,
81+ DeviceType::DockAnalog,
82+ DeviceType::UsbAccessory,
83+ DeviceType::UsbDevice,
84+ DeviceType::UsbHeadset,
85+ DeviceType::FMTuner,
86+ DeviceType::TVTuner,
87+ DeviceType::LineAnalog,
88+ DeviceType::LineDigital,
89+ DeviceType::BluetoothA2dp,
90+ DeviceType::IP,
91+ DeviceType::Bus,
92+ DeviceType::RemoteSubmix,
93+ DeviceType::BleHeadset,
94+ DeviceType::HdmiArc,
95+ DeviceType::HdmiEarc,
96+ };
97+
4098/* *
4199 * Call some AAudio test routines that are not part of the normal API.
42100 */
43101class AAudioExtensions {
44102private: // Because it is a singleton. Call getInstance() instead.
45103 AAudioExtensions () {
46- int32_t policy = getIntegerProperty (" aaudio.mmap_policy" , 0 );
47- mMMapSupported = isPolicyEnabled (policy);
104+ mLibLoader = AAudioLoader::getInstance ();
105+ if (!initMMapPolicy ()) {
106+ int32_t policy = getIntegerProperty (" aaudio.mmap_policy" , 0 );
107+ mMMapSupported = isPolicyEnabled (policy);
48108
49- policy = getIntegerProperty (" aaudio.mmap_exclusive_policy" , 0 );
50- mMMapExclusiveSupported = isPolicyEnabled (policy);
109+ policy = getIntegerProperty (" aaudio.mmap_exclusive_policy" , 0 );
110+ mMMapExclusiveSupported = isPolicyEnabled (policy);
111+ }
51112 }
52113
53114public:
54115 static bool isPolicyEnabled (int32_t policy) {
55- return (policy == AAUDIO_POLICY_AUTO || policy == AAUDIO_POLICY_ALWAYS);
116+ const MMapPolicy mmapPolicy = static_cast <MMapPolicy>(policy);
117+ return (mmapPolicy == MMapPolicy::Auto || mmapPolicy == MMapPolicy::Always);
56118 }
57119
58120 static AAudioExtensions &getInstance () {
@@ -66,6 +128,9 @@ class AAudioExtensions {
66128 }
67129
68130 bool isMMapUsed (AAudioStream *aaudioStream) {
131+ if (mLibLoader != nullptr && mLibLoader ->stream_isMMapUsed != nullptr ) {
132+ return mLibLoader ->stream_isMMapUsed (aaudioStream);
133+ }
69134 if (loadSymbols ()) return false ;
70135 if (mAAudioStream_isMMap == nullptr ) return false ;
71136 return mAAudioStream_isMMap (aaudioStream);
@@ -80,12 +145,27 @@ class AAudioExtensions {
80145 * @return 0 or a negative error code
81146 */
82147 int32_t setMMapEnabled (bool enabled) {
148+ // The API for setting mmap policy is public after API level 36.
149+ if (mLibLoader != nullptr && mLibLoader ->aaudio_setMMapPolicy != nullptr ) {
150+ return mLibLoader ->aaudio_setMMapPolicy (
151+ static_cast <aaudio_policy_t >(enabled ? MMapPolicy::Auto : MMapPolicy::Never));
152+ }
153+ // When there is no public API, fallback to loading the symbol from hidden API.
83154 if (loadSymbols ()) return AAUDIO_ERROR_UNAVAILABLE;
84155 if (mAAudio_setMMapPolicy == nullptr ) return false ;
85- return mAAudio_setMMapPolicy (enabled ? AAUDIO_POLICY_AUTO : AAUDIO_POLICY_NEVER);
156+ return mAAudio_setMMapPolicy (
157+ static_cast <int32_t >(enabled ? MMapPolicy::Auto : MMapPolicy::Never));
86158 }
87159
88160 bool isMMapEnabled () {
161+ // The API for getting mmap policy is public after API level 36.
162+ // Use it when it is available.
163+ if (mLibLoader != nullptr && mLibLoader ->aaudio_getMMapPolicy != nullptr ) {
164+ MMapPolicy policy = static_cast <MMapPolicy>(mLibLoader ->aaudio_getMMapPolicy ());
165+ return policy == MMapPolicy::Unspecified
166+ ? mMMapSupported : isPolicyEnabled (static_cast <int32_t >(policy));
167+ }
168+ // When there is no public API, fallback to loading the symbol from hidden API.
89169 if (loadSymbols ()) return false ;
90170 if (mAAudio_getMMapPolicy == nullptr ) return false ;
91171 int32_t policy = mAAudio_getMMapPolicy ();
@@ -100,14 +180,63 @@ class AAudioExtensions {
100180 return mMMapExclusiveSupported ;
101181 }
102182
103- private:
183+ MMapPolicy getMMapPolicy (DeviceType deviceType, Direction direction) {
184+ if (mLibLoader == nullptr ||
185+ mLibLoader ->aaudio_getPlatformMMapPolicy == nullptr ) {
186+ return MMapPolicy::Unspecified;
187+ }
188+ return static_cast <MMapPolicy>(mLibLoader ->aaudio_getPlatformMMapPolicy (
189+ static_cast <AAudio_DeviceType>(deviceType),
190+ static_cast <aaudio_direction_t >(direction)));
191+ }
104192
105- enum {
106- AAUDIO_POLICY_NEVER = 1 ,
107- AAUDIO_POLICY_AUTO,
108- AAUDIO_POLICY_ALWAYS
109- };
110- typedef int32_t aaudio_policy_t ;
193+ MMapPolicy getMMapExclusivePolicy (DeviceType deviceType, Direction direction) {
194+ if (mLibLoader == nullptr ||
195+ mLibLoader ->aaudio_getPlatformMMapExclusivePolicy == nullptr ) {
196+ return MMapPolicy::Unspecified;
197+ }
198+ return static_cast <MMapPolicy>(mLibLoader ->aaudio_getPlatformMMapExclusivePolicy (
199+ static_cast <AAudio_DeviceType>(deviceType),
200+ static_cast <aaudio_direction_t >(direction)));
201+ }
202+
203+ bool isPartialDataCallbackSupported () {
204+ return mLibLoader != nullptr && mLibLoader ->builder_setPartialDataCallback != nullptr ;
205+ }
206+
207+ private:
208+ bool initMMapPolicy () {
209+ if (mLibLoader == nullptr || mLibLoader ->open () != 0 ) {
210+ return false ;
211+ }
212+ if (mLibLoader ->aaudio_getPlatformMMapPolicy == nullptr ||
213+ mLibLoader ->aaudio_getPlatformMMapExclusivePolicy == nullptr ) {
214+ return false ;
215+ }
216+ mMMapSupported =
217+ std::any_of (ALL_INPUT_DEVICE_TYPES.begin (), ALL_INPUT_DEVICE_TYPES.end (),
218+ [this ](DeviceType deviceType) {
219+ return isPolicyEnabled (static_cast <int32_t >(
220+ getMMapPolicy (deviceType, Direction::Input)));
221+ }) ||
222+ std::any_of (ALL_OUTPUT_DEVICE_TYPES.begin (), ALL_OUTPUT_DEVICE_TYPES.end (),
223+ [this ](DeviceType deviceType) {
224+ return isPolicyEnabled (static_cast <int32_t >(
225+ getMMapPolicy (deviceType, Direction::Output)));
226+ });
227+ mMMapExclusiveSupported =
228+ std::any_of (ALL_INPUT_DEVICE_TYPES.begin (), ALL_INPUT_DEVICE_TYPES.end (),
229+ [this ](DeviceType deviceType) {
230+ return isPolicyEnabled (static_cast <int32_t >(
231+ getMMapExclusivePolicy (deviceType, Direction::Input)));
232+ }) ||
233+ std::any_of (ALL_OUTPUT_DEVICE_TYPES.begin (), ALL_OUTPUT_DEVICE_TYPES.end (),
234+ [this ](DeviceType deviceType) {
235+ return isPolicyEnabled (static_cast <int32_t >(
236+ getMMapExclusivePolicy (deviceType, Direction::Output)));
237+ });
238+ return true ;
239+ }
111240
112241 int getIntegerProperty (const char *name, int defaultValue) {
113242 int result = defaultValue;
@@ -130,14 +259,12 @@ class AAudioExtensions {
130259 return 0 ;
131260 }
132261
133- AAudioLoader *libLoader = AAudioLoader::getInstance ();
134- int openResult = libLoader->open ();
135- if (openResult != 0 ) {
262+ if (mLibLoader == nullptr || mLibLoader ->open () != 0 ) {
136263 LOGD (" %s() could not open " LIB_AAUDIO_NAME, __func__);
137264 return AAUDIO_ERROR_UNAVAILABLE;
138265 }
139266
140- void *libHandle = AAudioLoader::getInstance () ->getLibHandle ();
267+ void *libHandle = mLibLoader ->getLibHandle ();
141268 if (libHandle == nullptr ) {
142269 LOGE (" %s() could not find " LIB_AAUDIO_NAME, __func__);
143270 return AAUDIO_ERROR_UNAVAILABLE;
@@ -173,6 +300,8 @@ class AAudioExtensions {
173300 bool (*mAAudioStream_isMMap )(AAudioStream *stream) = nullptr ;
174301 int32_t (*mAAudio_setMMapPolicy )(aaudio_policy_t policy) = nullptr ;
175302 aaudio_policy_t (*mAAudio_getMMapPolicy )() = nullptr ;
303+
304+ AAudioLoader *mLibLoader ;
176305};
177306
178307} // namespace oboe
0 commit comments