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/* 41 * AudioStreamBuilder 42 */ 43AudioStreamBuilder::AudioStreamBuilder() { 44} 45 46AudioStreamBuilder::~AudioStreamBuilder() { 47} 48 49static aaudio_result_t builder_createStream(aaudio_direction_t direction, 50 aaudio_sharing_mode_t sharingMode, 51 bool tryMMap, 52 AudioStream **audioStreamPtr) { 53 *audioStreamPtr = nullptr; 54 aaudio_result_t result = AAUDIO_OK; 55 56 switch (direction) { 57 58 case AAUDIO_DIRECTION_INPUT: 59 if (tryMMap) { 60 *audioStreamPtr = new AudioStreamInternalCapture(AAudioBinderClient::getInstance(), 61 false); 62 } else { 63 *audioStreamPtr = new AudioStreamRecord(); 64 } 65 break; 66 67 case AAUDIO_DIRECTION_OUTPUT: 68 if (tryMMap) { 69 *audioStreamPtr = new AudioStreamInternalPlay(AAudioBinderClient::getInstance(), 70 false); 71 } else { 72 *audioStreamPtr = new AudioStreamTrack(); 73 } 74 break; 75 76 default: 77 ALOGE("AudioStreamBuilder(): bad direction = %d", direction); 78 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT; 79 } 80 return result; 81} 82 83// Try to open using MMAP path if that is allowed. 84// Fall back to Legacy path if MMAP not available. 85// Exact behavior is controlled by MMapPolicy. 86aaudio_result_t AudioStreamBuilder::build(AudioStream** streamPtr) { 87 AudioStream *audioStream = nullptr; 88 *streamPtr = nullptr; 89 90 // The API setting is the highest priority. 91 aaudio_policy_t mmapPolicy = AAudio_getMMapPolicy(); 92 // If not specified then get from a system property. 93 if (mmapPolicy == AAUDIO_UNSPECIFIED) { 94 mmapPolicy = AAudioProperty_getMMapPolicy(); 95 } 96 // If still not specified then use the default. 97 if (mmapPolicy == AAUDIO_UNSPECIFIED) { 98 mmapPolicy = AAUDIO_MMAP_POLICY_DEFAULT; 99 } 100 101 int32_t mapExclusivePolicy = AAudioProperty_getMMapExclusivePolicy(); 102 if (mapExclusivePolicy == AAUDIO_UNSPECIFIED) { 103 mapExclusivePolicy = AAUDIO_MMAP_EXCLUSIVE_POLICY_DEFAULT; 104 } 105 ALOGD("AudioStreamBuilder(): mmapPolicy = %d, mapExclusivePolicy = %d", 106 mmapPolicy, mapExclusivePolicy); 107 108 aaudio_sharing_mode_t sharingMode = getSharingMode(); 109 if ((sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) 110 && (mapExclusivePolicy == AAUDIO_POLICY_NEVER)) { 111 ALOGW("AudioStreamBuilder(): EXCLUSIVE sharing mode not supported. Use SHARED."); 112 sharingMode = AAUDIO_SHARING_MODE_SHARED; 113 setSharingMode(sharingMode); 114 } 115 116 bool allowMMap = mmapPolicy != AAUDIO_POLICY_NEVER; 117 bool allowLegacy = mmapPolicy != AAUDIO_POLICY_ALWAYS; 118 119 aaudio_result_t result = builder_createStream(getDirection(), sharingMode, 120 allowMMap, &audioStream); 121 if (result == AAUDIO_OK) { 122 // Open the stream using the parameters from the builder. 123 result = audioStream->open(*this); 124 if (result == AAUDIO_OK) { 125 *streamPtr = audioStream; 126 } else { 127 bool isMMap = audioStream->isMMap(); 128 delete audioStream; 129 audioStream = nullptr; 130 131 if (isMMap && allowLegacy) { 132 ALOGD("AudioStreamBuilder.build() MMAP stream did not open so try Legacy path"); 133 // If MMAP stream failed to open then TRY using a legacy stream. 134 result = builder_createStream(getDirection(), sharingMode, 135 false, &audioStream); 136 if (result == AAUDIO_OK) { 137 result = audioStream->open(*this); 138 if (result == AAUDIO_OK) { 139 *streamPtr = audioStream; 140 } else { 141 delete audioStream; 142 } 143 } 144 } 145 } 146 } 147 148 return result; 149} 150