1/* 2 * Copyright 2015 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#define LOG_TAG "AAudio" 18//#define LOG_NDEBUG 0 19#include <utils/Log.h> 20 21#include <new> 22#include <stdint.h> 23 24#include <aaudio/AAudio.h> 25#include <aaudio/AAudioTesting.h> 26 27#include "binding/AAudioBinderClient.h" 28#include "client/AudioStreamInternalCapture.h" 29#include "client/AudioStreamInternalPlay.h" 30#include "core/AudioStream.h" 31#include "core/AudioStreamBuilder.h" 32#include "legacy/AudioStreamRecord.h" 33#include "legacy/AudioStreamTrack.h" 34 35using namespace aaudio; 36 37#define AAUDIO_MMAP_POLICY_DEFAULT AAUDIO_POLICY_NEVER 38#define AAUDIO_MMAP_EXCLUSIVE_POLICY_DEFAULT AAUDIO_POLICY_NEVER 39 40// These values are for a pre-check before we ask the lower level service to open a stream. 41// So they are just outside the maximum conceivable range of value, 42// on the edge of being ridiculous. 43// TODO These defines should be moved to a central place in audio. 44#define SAMPLES_PER_FRAME_MIN 1 45// TODO Remove 8 channel limitation. 46#define SAMPLES_PER_FRAME_MAX FCC_8 47#define SAMPLE_RATE_HZ_MIN 8000 48// HDMI supports up to 32 channels at 1536000 Hz. 49#define SAMPLE_RATE_HZ_MAX 1600000 50#define FRAMES_PER_DATA_CALLBACK_MIN 1 51#define FRAMES_PER_DATA_CALLBACK_MAX (1024 * 1024) 52 53/* 54 * AudioStreamBuilder 55 */ 56AudioStreamBuilder::AudioStreamBuilder() { 57} 58 59AudioStreamBuilder::~AudioStreamBuilder() { 60} 61 62static aaudio_result_t builder_createStream(aaudio_direction_t direction, 63 aaudio_sharing_mode_t sharingMode, 64 bool tryMMap, 65 AudioStream **audioStreamPtr) { 66 *audioStreamPtr = nullptr; 67 aaudio_result_t result = AAUDIO_OK; 68 69 switch (direction) { 70 71 case AAUDIO_DIRECTION_INPUT: 72 if (tryMMap) { 73 *audioStreamPtr = new AudioStreamInternalCapture(AAudioBinderClient::getInstance(), 74 false); 75 } else { 76 *audioStreamPtr = new AudioStreamRecord(); 77 } 78 break; 79 80 case AAUDIO_DIRECTION_OUTPUT: 81 if (tryMMap) { 82 *audioStreamPtr = new AudioStreamInternalPlay(AAudioBinderClient::getInstance(), 83 false); 84 } else { 85 *audioStreamPtr = new AudioStreamTrack(); 86 } 87 break; 88 89 default: 90 ALOGE("AudioStreamBuilder(): bad direction = %d", direction); 91 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT; 92 } 93 return result; 94} 95 96// Try to open using MMAP path if that is allowed. 97// Fall back to Legacy path if MMAP not available. 98// Exact behavior is controlled by MMapPolicy. 99aaudio_result_t AudioStreamBuilder::build(AudioStream** streamPtr) { 100 AudioStream *audioStream = nullptr; 101 if (streamPtr == nullptr) { 102 ALOGE("AudioStreamBuilder::build() streamPtr is null"); 103 return AAUDIO_ERROR_NULL; 104 } 105 *streamPtr = nullptr; 106 107 aaudio_result_t result = validate(); 108 if (result != AAUDIO_OK) { 109 return result; 110 } 111 112 // The API setting is the highest priority. 113 aaudio_policy_t mmapPolicy = AAudio_getMMapPolicy(); 114 // If not specified then get from a system property. 115 if (mmapPolicy == AAUDIO_UNSPECIFIED) { 116 mmapPolicy = AAudioProperty_getMMapPolicy(); 117 } 118 // If still not specified then use the default. 119 if (mmapPolicy == AAUDIO_UNSPECIFIED) { 120 mmapPolicy = AAUDIO_MMAP_POLICY_DEFAULT; 121 } 122 123 int32_t mapExclusivePolicy = AAudioProperty_getMMapExclusivePolicy(); 124 if (mapExclusivePolicy == AAUDIO_UNSPECIFIED) { 125 mapExclusivePolicy = AAUDIO_MMAP_EXCLUSIVE_POLICY_DEFAULT; 126 } 127 ALOGD("AudioStreamBuilder(): mmapPolicy = %d, mapExclusivePolicy = %d", 128 mmapPolicy, mapExclusivePolicy); 129 130 aaudio_sharing_mode_t sharingMode = getSharingMode(); 131 if ((sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) 132 && (mapExclusivePolicy == AAUDIO_POLICY_NEVER)) { 133 ALOGW("AudioStreamBuilder(): EXCLUSIVE sharing mode not supported. Use SHARED."); 134 sharingMode = AAUDIO_SHARING_MODE_SHARED; 135 setSharingMode(sharingMode); 136 } 137 138 bool allowMMap = mmapPolicy != AAUDIO_POLICY_NEVER; 139 bool allowLegacy = mmapPolicy != AAUDIO_POLICY_ALWAYS; 140 141 // TODO Support other performance settings in MMAP mode. 142 // Disable MMAP if low latency not requested. 143 if (getPerformanceMode() != AAUDIO_PERFORMANCE_MODE_LOW_LATENCY) { 144 allowMMap = false; 145 } 146 147 result = builder_createStream(getDirection(), sharingMode, allowMMap, &audioStream); 148 if (result == AAUDIO_OK) { 149 // Open the stream using the parameters from the builder. 150 result = audioStream->open(*this); 151 if (result == AAUDIO_OK) { 152 *streamPtr = audioStream; 153 } else { 154 bool isMMap = audioStream->isMMap(); 155 delete audioStream; 156 audioStream = nullptr; 157 158 if (isMMap && allowLegacy) { 159 ALOGD("AudioStreamBuilder.build() MMAP stream did not open so try Legacy path"); 160 // If MMAP stream failed to open then TRY using a legacy stream. 161 result = builder_createStream(getDirection(), sharingMode, 162 false, &audioStream); 163 if (result == AAUDIO_OK) { 164 result = audioStream->open(*this); 165 if (result == AAUDIO_OK) { 166 *streamPtr = audioStream; 167 } else { 168 delete audioStream; 169 } 170 } 171 } 172 } 173 } 174 175 return result; 176} 177 178aaudio_result_t AudioStreamBuilder::validate() const { 179 180 // Check for values that are ridiculously out of range to prevent math overflow exploits. 181 // The service will do a better check. 182 aaudio_result_t result = AAudioStreamParameters::validate(); 183 if (result != AAUDIO_OK) { 184 return result; 185 } 186 187 switch (mPerformanceMode) { 188 case AAUDIO_PERFORMANCE_MODE_NONE: 189 case AAUDIO_PERFORMANCE_MODE_POWER_SAVING: 190 case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY: 191 break; 192 default: 193 ALOGE("AudioStreamBuilder: illegal performanceMode = %d", mPerformanceMode); 194 return AAUDIO_ERROR_ILLEGAL_ARGUMENT; 195 // break; 196 } 197 198 // Prevent ridiculous values from causing problems. 199 if (mFramesPerDataCallback != AAUDIO_UNSPECIFIED 200 && (mFramesPerDataCallback < FRAMES_PER_DATA_CALLBACK_MIN 201 || mFramesPerDataCallback > FRAMES_PER_DATA_CALLBACK_MAX)) { 202 ALOGE("AudioStreamBuilder: framesPerDataCallback out of range = %d", 203 mFramesPerDataCallback); 204 return AAUDIO_ERROR_OUT_OF_RANGE; 205 } 206 207 return AAUDIO_OK; 208} 209