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