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_AAUDIO_EXTENSIONS_H 18*05767d91SRobert Wu #define OBOE_AAUDIO_EXTENSIONS_H 19*05767d91SRobert Wu 20*05767d91SRobert Wu #include <dlfcn.h> 21*05767d91SRobert Wu #include <stdint.h> 22*05767d91SRobert Wu 23*05767d91SRobert Wu #include <sys/system_properties.h> 24*05767d91SRobert Wu 25*05767d91SRobert Wu #include "common/OboeDebug.h" 26*05767d91SRobert Wu #include "oboe/Oboe.h" 27*05767d91SRobert Wu #include "AAudioLoader.h" 28*05767d91SRobert Wu 29*05767d91SRobert Wu namespace oboe { 30*05767d91SRobert Wu 31*05767d91SRobert Wu #define LIB_AAUDIO_NAME "libaaudio.so" 32*05767d91SRobert Wu #define FUNCTION_IS_MMAP "AAudioStream_isMMapUsed" 33*05767d91SRobert Wu #define FUNCTION_SET_MMAP_POLICY "AAudio_setMMapPolicy" 34*05767d91SRobert Wu #define FUNCTION_GET_MMAP_POLICY "AAudio_getMMapPolicy" 35*05767d91SRobert Wu 36*05767d91SRobert Wu #define AAUDIO_ERROR_UNAVAILABLE static_cast<aaudio_result_t>(Result::ErrorUnavailable) 37*05767d91SRobert Wu 38*05767d91SRobert Wu typedef struct AAudioStreamStruct AAudioStream; 39*05767d91SRobert Wu 40*05767d91SRobert Wu /** 41*05767d91SRobert Wu * Call some AAudio test routines that are not part of the normal API. 42*05767d91SRobert Wu */ 43*05767d91SRobert Wu class AAudioExtensions { 44*05767d91SRobert Wu private: // Because it is a singleton. Call getInstance() instead. AAudioExtensions()45*05767d91SRobert Wu AAudioExtensions() { 46*05767d91SRobert Wu int32_t policy = getIntegerProperty("aaudio.mmap_policy", 0); 47*05767d91SRobert Wu mMMapSupported = isPolicyEnabled(policy); 48*05767d91SRobert Wu 49*05767d91SRobert Wu policy = getIntegerProperty("aaudio.mmap_exclusive_policy", 0); 50*05767d91SRobert Wu mMMapExclusiveSupported = isPolicyEnabled(policy); 51*05767d91SRobert Wu } 52*05767d91SRobert Wu 53*05767d91SRobert Wu public: isPolicyEnabled(int32_t policy)54*05767d91SRobert Wu static bool isPolicyEnabled(int32_t policy) { 55*05767d91SRobert Wu return (policy == AAUDIO_POLICY_AUTO || policy == AAUDIO_POLICY_ALWAYS); 56*05767d91SRobert Wu } 57*05767d91SRobert Wu getInstance()58*05767d91SRobert Wu static AAudioExtensions &getInstance() { 59*05767d91SRobert Wu static AAudioExtensions instance; 60*05767d91SRobert Wu return instance; 61*05767d91SRobert Wu } 62*05767d91SRobert Wu isMMapUsed(oboe::AudioStream * oboeStream)63*05767d91SRobert Wu bool isMMapUsed(oboe::AudioStream *oboeStream) { 64*05767d91SRobert Wu AAudioStream *aaudioStream = (AAudioStream *) oboeStream->getUnderlyingStream(); 65*05767d91SRobert Wu return isMMapUsed(aaudioStream); 66*05767d91SRobert Wu } 67*05767d91SRobert Wu isMMapUsed(AAudioStream * aaudioStream)68*05767d91SRobert Wu bool isMMapUsed(AAudioStream *aaudioStream) { 69*05767d91SRobert Wu if (loadSymbols()) return false; 70*05767d91SRobert Wu if (mAAudioStream_isMMap == nullptr) return false; 71*05767d91SRobert Wu return mAAudioStream_isMMap(aaudioStream); 72*05767d91SRobert Wu } 73*05767d91SRobert Wu 74*05767d91SRobert Wu /** 75*05767d91SRobert Wu * Controls whether the MMAP data path can be selected when opening a stream. 76*05767d91SRobert Wu * It has no effect after the stream has been opened. 77*05767d91SRobert Wu * It only affects the application that calls it. Other apps are not affected. 78*05767d91SRobert Wu * 79*05767d91SRobert Wu * @param enabled 80*05767d91SRobert Wu * @return 0 or a negative error code 81*05767d91SRobert Wu */ setMMapEnabled(bool enabled)82*05767d91SRobert Wu int32_t setMMapEnabled(bool enabled) { 83*05767d91SRobert Wu if (loadSymbols()) return AAUDIO_ERROR_UNAVAILABLE; 84*05767d91SRobert Wu if (mAAudio_setMMapPolicy == nullptr) return false; 85*05767d91SRobert Wu return mAAudio_setMMapPolicy(enabled ? AAUDIO_POLICY_AUTO : AAUDIO_POLICY_NEVER); 86*05767d91SRobert Wu } 87*05767d91SRobert Wu isMMapEnabled()88*05767d91SRobert Wu bool isMMapEnabled() { 89*05767d91SRobert Wu if (loadSymbols()) return false; 90*05767d91SRobert Wu if (mAAudio_getMMapPolicy == nullptr) return false; 91*05767d91SRobert Wu int32_t policy = mAAudio_getMMapPolicy(); 92*05767d91SRobert Wu return (policy == Unspecified) ? mMMapSupported : isPolicyEnabled(policy); 93*05767d91SRobert Wu } 94*05767d91SRobert Wu isMMapSupported()95*05767d91SRobert Wu bool isMMapSupported() { 96*05767d91SRobert Wu return mMMapSupported; 97*05767d91SRobert Wu } 98*05767d91SRobert Wu isMMapExclusiveSupported()99*05767d91SRobert Wu bool isMMapExclusiveSupported() { 100*05767d91SRobert Wu return mMMapExclusiveSupported; 101*05767d91SRobert Wu } 102*05767d91SRobert Wu 103*05767d91SRobert Wu private: 104*05767d91SRobert Wu 105*05767d91SRobert Wu enum { 106*05767d91SRobert Wu AAUDIO_POLICY_NEVER = 1, 107*05767d91SRobert Wu AAUDIO_POLICY_AUTO, 108*05767d91SRobert Wu AAUDIO_POLICY_ALWAYS 109*05767d91SRobert Wu }; 110*05767d91SRobert Wu typedef int32_t aaudio_policy_t; 111*05767d91SRobert Wu getIntegerProperty(const char * name,int defaultValue)112*05767d91SRobert Wu int getIntegerProperty(const char *name, int defaultValue) { 113*05767d91SRobert Wu int result = defaultValue; 114*05767d91SRobert Wu char valueText[PROP_VALUE_MAX] = {0}; 115*05767d91SRobert Wu if (__system_property_get(name, valueText) != 0) { 116*05767d91SRobert Wu result = atoi(valueText); 117*05767d91SRobert Wu } 118*05767d91SRobert Wu return result; 119*05767d91SRobert Wu } 120*05767d91SRobert Wu 121*05767d91SRobert Wu /** 122*05767d91SRobert Wu * Load the function pointers. 123*05767d91SRobert Wu * This can be called multiple times. 124*05767d91SRobert Wu * It should only be called from one thread. 125*05767d91SRobert Wu * 126*05767d91SRobert Wu * @return 0 if successful or negative error. 127*05767d91SRobert Wu */ loadSymbols()128*05767d91SRobert Wu aaudio_result_t loadSymbols() { 129*05767d91SRobert Wu if (mAAudio_getMMapPolicy != nullptr) { 130*05767d91SRobert Wu return 0; 131*05767d91SRobert Wu } 132*05767d91SRobert Wu 133*05767d91SRobert Wu AAudioLoader *libLoader = AAudioLoader::getInstance(); 134*05767d91SRobert Wu int openResult = libLoader->open(); 135*05767d91SRobert Wu if (openResult != 0) { 136*05767d91SRobert Wu LOGD("%s() could not open " LIB_AAUDIO_NAME, __func__); 137*05767d91SRobert Wu return AAUDIO_ERROR_UNAVAILABLE; 138*05767d91SRobert Wu } 139*05767d91SRobert Wu 140*05767d91SRobert Wu void *libHandle = AAudioLoader::getInstance()->getLibHandle(); 141*05767d91SRobert Wu if (libHandle == nullptr) { 142*05767d91SRobert Wu LOGE("%s() could not find " LIB_AAUDIO_NAME, __func__); 143*05767d91SRobert Wu return AAUDIO_ERROR_UNAVAILABLE; 144*05767d91SRobert Wu } 145*05767d91SRobert Wu 146*05767d91SRobert Wu mAAudioStream_isMMap = (bool (*)(AAudioStream *stream)) 147*05767d91SRobert Wu dlsym(libHandle, FUNCTION_IS_MMAP); 148*05767d91SRobert Wu if (mAAudioStream_isMMap == nullptr) { 149*05767d91SRobert Wu LOGI("%s() could not find " FUNCTION_IS_MMAP, __func__); 150*05767d91SRobert Wu return AAUDIO_ERROR_UNAVAILABLE; 151*05767d91SRobert Wu } 152*05767d91SRobert Wu 153*05767d91SRobert Wu mAAudio_setMMapPolicy = (int32_t (*)(aaudio_policy_t policy)) 154*05767d91SRobert Wu dlsym(libHandle, FUNCTION_SET_MMAP_POLICY); 155*05767d91SRobert Wu if (mAAudio_setMMapPolicy == nullptr) { 156*05767d91SRobert Wu LOGI("%s() could not find " FUNCTION_SET_MMAP_POLICY, __func__); 157*05767d91SRobert Wu return AAUDIO_ERROR_UNAVAILABLE; 158*05767d91SRobert Wu } 159*05767d91SRobert Wu 160*05767d91SRobert Wu mAAudio_getMMapPolicy = (aaudio_policy_t (*)()) 161*05767d91SRobert Wu dlsym(libHandle, FUNCTION_GET_MMAP_POLICY); 162*05767d91SRobert Wu if (mAAudio_getMMapPolicy == nullptr) { 163*05767d91SRobert Wu LOGI("%s() could not find " FUNCTION_GET_MMAP_POLICY, __func__); 164*05767d91SRobert Wu return AAUDIO_ERROR_UNAVAILABLE; 165*05767d91SRobert Wu } 166*05767d91SRobert Wu 167*05767d91SRobert Wu return 0; 168*05767d91SRobert Wu } 169*05767d91SRobert Wu 170*05767d91SRobert Wu bool mMMapSupported = false; 171*05767d91SRobert Wu bool mMMapExclusiveSupported = false; 172*05767d91SRobert Wu 173*05767d91SRobert Wu bool (*mAAudioStream_isMMap)(AAudioStream *stream) = nullptr; 174*05767d91SRobert Wu int32_t (*mAAudio_setMMapPolicy)(aaudio_policy_t policy) = nullptr; 175*05767d91SRobert Wu aaudio_policy_t (*mAAudio_getMMapPolicy)() = nullptr; 176*05767d91SRobert Wu }; 177*05767d91SRobert Wu 178*05767d91SRobert Wu } // namespace oboe 179*05767d91SRobert Wu 180*05767d91SRobert Wu #endif //OBOE_AAUDIO_EXTENSIONS_H 181