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 "AudioStreamBuilder"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20
21 #include <new>
22 #include <stdint.h>
23 #include <vector>
24
25 #include <aaudio/AAudio.h>
26 #include <aaudio/AAudioTesting.h>
27 #include <android/media/audio/common/AudioMMapPolicy.h>
28 #include <android/media/audio/common/AudioMMapPolicyInfo.h>
29 #include <android/media/audio/common/AudioMMapPolicyType.h>
30 #include <media/AudioSystem.h>
31
32 #include "binding/AAudioBinderClient.h"
33 #include "client/AudioStreamInternalCapture.h"
34 #include "client/AudioStreamInternalPlay.h"
35 #include "core/AudioGlobal.h"
36 #include "core/AudioStream.h"
37 #include "core/AudioStreamBuilder.h"
38 #include "legacy/AudioStreamRecord.h"
39 #include "legacy/AudioStreamTrack.h"
40
41 using namespace aaudio;
42
43 using android::media::audio::common::AudioMMapPolicy;
44 using android::media::audio::common::AudioMMapPolicyInfo;
45 using android::media::audio::common::AudioMMapPolicyType;
46
47 #define AAUDIO_MMAP_POLICY_DEFAULT AAUDIO_POLICY_NEVER
48 #define AAUDIO_MMAP_EXCLUSIVE_POLICY_DEFAULT AAUDIO_POLICY_NEVER
49
50 // These values are for a pre-check before we ask the lower level service to open a stream.
51 // So they are just outside the maximum conceivable range of value,
52 // on the edge of being ridiculous.
53 // TODO These defines should be moved to a central place in audio.
54 #define SAMPLES_PER_FRAME_MIN 1
55 #define SAMPLES_PER_FRAME_MAX FCC_LIMIT
56 #define SAMPLE_RATE_HZ_MIN 8000
57 // HDMI supports up to 32 channels at 1536000 Hz.
58 #define SAMPLE_RATE_HZ_MAX 1600000
59 #define FRAMES_PER_DATA_CALLBACK_MIN 1
60 #define FRAMES_PER_DATA_CALLBACK_MAX (1024 * 1024)
61
62 /*
63 * AudioStreamBuilder
64 */
builder_createStream(aaudio_direction_t direction,aaudio_sharing_mode_t,bool tryMMap,android::sp<AudioStream> & stream)65 static aaudio_result_t builder_createStream(aaudio_direction_t direction,
66 aaudio_sharing_mode_t /*sharingMode*/,
67 bool tryMMap,
68 android::sp<AudioStream> &stream) {
69 aaudio_result_t result = AAUDIO_OK;
70
71 switch (direction) {
72
73 case AAUDIO_DIRECTION_INPUT:
74 if (tryMMap) {
75 stream = new AudioStreamInternalCapture(AAudioBinderClient::getInstance(),
76 false);
77 } else {
78 stream = new AudioStreamRecord();
79 }
80 break;
81
82 case AAUDIO_DIRECTION_OUTPUT:
83 if (tryMMap) {
84 stream = new AudioStreamInternalPlay(AAudioBinderClient::getInstance(),
85 false);
86 } else {
87 stream = new AudioStreamTrack();
88 }
89 break;
90
91 default:
92 ALOGE("%s() bad direction = %d", __func__, direction);
93 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
94 }
95 return result;
96 }
97
98 namespace {
99
aidl2legacy_aaudio_policy(AudioMMapPolicy aidl)100 aaudio_policy_t aidl2legacy_aaudio_policy(AudioMMapPolicy aidl) {
101 switch (aidl) {
102 case AudioMMapPolicy::NEVER:
103 return AAUDIO_POLICY_NEVER;
104 case AudioMMapPolicy::AUTO:
105 return AAUDIO_POLICY_AUTO;
106 case AudioMMapPolicy::ALWAYS:
107 return AAUDIO_POLICY_ALWAYS;
108 case AudioMMapPolicy::UNSPECIFIED:
109 default:
110 return AAUDIO_UNSPECIFIED;
111 }
112 }
113
114 // The aaudio policy will be ALWAYS, NEVER, UNSPECIFIED only when all policy info are
115 // ALWAYS, NEVER or UNSPECIFIED. Otherwise, the aaudio policy will be AUTO.
getAAudioPolicy(const std::vector<AudioMMapPolicyInfo> & policyInfos)116 aaudio_policy_t getAAudioPolicy(
117 const std::vector<AudioMMapPolicyInfo>& policyInfos) {
118 if (policyInfos.empty()) return AAUDIO_POLICY_AUTO;
119 for (size_t i = 1; i < policyInfos.size(); ++i) {
120 if (policyInfos.at(i).mmapPolicy != policyInfos.at(0).mmapPolicy) {
121 return AAUDIO_POLICY_AUTO;
122 }
123 }
124 return aidl2legacy_aaudio_policy(policyInfos.at(0).mmapPolicy);
125 }
126
127 } // namespace
128
129 // Try to open using MMAP path if that is allowed.
130 // Fall back to Legacy path if MMAP not available.
131 // Exact behavior is controlled by MMapPolicy.
build(AudioStream ** streamPtr)132 aaudio_result_t AudioStreamBuilder::build(AudioStream** streamPtr) {
133
134 if (streamPtr == nullptr) {
135 ALOGE("%s() streamPtr is null", __func__);
136 return AAUDIO_ERROR_NULL;
137 }
138 *streamPtr = nullptr;
139
140 logParameters();
141
142 aaudio_result_t result = validate();
143 if (result != AAUDIO_OK) {
144 return result;
145 }
146
147 std::vector<AudioMMapPolicyInfo> policyInfos;
148 // The API setting is the highest priority.
149 aaudio_policy_t mmapPolicy = AudioGlobal_getMMapPolicy();
150 // If not specified then get from a system property.
151 if (mmapPolicy == AAUDIO_UNSPECIFIED && android::AudioSystem::getMmapPolicyInfo(
152 AudioMMapPolicyType::DEFAULT, &policyInfos) == NO_ERROR) {
153 mmapPolicy = getAAudioPolicy(policyInfos);
154 }
155 // If still not specified then use the default.
156 if (mmapPolicy == AAUDIO_UNSPECIFIED) {
157 mmapPolicy = AAUDIO_MMAP_POLICY_DEFAULT;
158 }
159
160 policyInfos.clear();
161 aaudio_policy_t mmapExclusivePolicy = AAUDIO_UNSPECIFIED;
162 if (android::AudioSystem::getMmapPolicyInfo(
163 AudioMMapPolicyType::EXCLUSIVE, &policyInfos) == NO_ERROR) {
164 mmapExclusivePolicy = getAAudioPolicy(policyInfos);
165 }
166 if (mmapExclusivePolicy == AAUDIO_UNSPECIFIED) {
167 mmapExclusivePolicy = AAUDIO_MMAP_EXCLUSIVE_POLICY_DEFAULT;
168 }
169
170 aaudio_sharing_mode_t sharingMode = getSharingMode();
171 if ((sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE)
172 && (mmapExclusivePolicy == AAUDIO_POLICY_NEVER)) {
173 ALOGD("%s() EXCLUSIVE sharing mode not supported. Use SHARED.", __func__);
174 sharingMode = AAUDIO_SHARING_MODE_SHARED;
175 setSharingMode(sharingMode);
176 }
177
178 bool allowMMap = mmapPolicy != AAUDIO_POLICY_NEVER;
179 bool allowLegacy = mmapPolicy != AAUDIO_POLICY_ALWAYS;
180
181 // TODO Support other performance settings in MMAP mode.
182 // Disable MMAP if low latency not requested.
183 if (getPerformanceMode() != AAUDIO_PERFORMANCE_MODE_LOW_LATENCY) {
184 ALOGD("%s() MMAP not used because AAUDIO_PERFORMANCE_MODE_LOW_LATENCY not requested.",
185 __func__);
186 allowMMap = false;
187 }
188
189 // SessionID and Effects are only supported in Legacy mode.
190 if (getSessionId() != AAUDIO_SESSION_ID_NONE) {
191 ALOGD("%s() MMAP not used because sessionId specified.", __func__);
192 allowMMap = false;
193 }
194
195 if (!allowMMap && !allowLegacy) {
196 ALOGE("%s() no backend available: neither MMAP nor legacy path are allowed", __func__);
197 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
198 }
199
200 setPrivacySensitive(false);
201 if (mPrivacySensitiveReq == PRIVACY_SENSITIVE_DEFAULT) {
202 // When not explicitly requested, set privacy sensitive mode according to input preset:
203 // communication and camcorder captures are considered privacy sensitive by default.
204 aaudio_input_preset_t preset = getInputPreset();
205 if (preset == AAUDIO_INPUT_PRESET_CAMCORDER
206 || preset == AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION) {
207 setPrivacySensitive(true);
208 }
209 } else if (mPrivacySensitiveReq == PRIVACY_SENSITIVE_ENABLED) {
210 setPrivacySensitive(true);
211 }
212
213 android::sp<AudioStream> audioStream;
214 result = builder_createStream(getDirection(), sharingMode, allowMMap, audioStream);
215 if (result == AAUDIO_OK) {
216 // Open the stream using the parameters from the builder.
217 result = audioStream->open(*this);
218 if (result != AAUDIO_OK) {
219 bool isMMap = audioStream->isMMap();
220 if (isMMap && allowLegacy) {
221 ALOGV("%s() MMAP stream did not open so try Legacy path", __func__);
222 // If MMAP stream failed to open then TRY using a legacy stream.
223 result = builder_createStream(getDirection(), sharingMode,
224 false, audioStream);
225 if (result == AAUDIO_OK) {
226 result = audioStream->open(*this);
227 }
228 }
229 }
230 if (result == AAUDIO_OK) {
231 audioStream->registerPlayerBase();
232 audioStream->logOpenActual();
233 *streamPtr = startUsingStream(audioStream);
234 } // else audioStream will go out of scope and be deleted
235 }
236
237 return result;
238 }
239
startUsingStream(android::sp<AudioStream> & audioStream)240 AudioStream *AudioStreamBuilder::startUsingStream(android::sp<AudioStream> &audioStream) {
241 // Increment the smart pointer so it will not get deleted when
242 // we pass it to the C caller and it goes out of scope.
243 // The C code cannot hold a smart pointer so we increment the reference
244 // count to indicate that the C app owns a reference.
245 audioStream->incStrong(nullptr);
246 return audioStream.get();
247 }
248
stopUsingStream(AudioStream * stream)249 void AudioStreamBuilder::stopUsingStream(AudioStream *stream) {
250 // Undo the effect of startUsingStream()
251 android::sp<AudioStream> spAudioStream(stream);
252 ALOGV("%s() strongCount = %d", __func__, spAudioStream->getStrongCount());
253 spAudioStream->decStrong(nullptr);
254 }
255
validate() const256 aaudio_result_t AudioStreamBuilder::validate() const {
257
258 // Check for values that are ridiculously out of range to prevent math overflow exploits.
259 // The service will do a better check.
260 aaudio_result_t result = AAudioStreamParameters::validate();
261 if (result != AAUDIO_OK) {
262 return result;
263 }
264
265 switch (mPerformanceMode) {
266 case AAUDIO_PERFORMANCE_MODE_NONE:
267 case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
268 case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
269 break;
270 default:
271 ALOGE("illegal performanceMode = %d", mPerformanceMode);
272 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
273 // break;
274 }
275
276 // Prevent ridiculous values from causing problems.
277 if (mFramesPerDataCallback != AAUDIO_UNSPECIFIED
278 && (mFramesPerDataCallback < FRAMES_PER_DATA_CALLBACK_MIN
279 || mFramesPerDataCallback > FRAMES_PER_DATA_CALLBACK_MAX)) {
280 ALOGE("framesPerDataCallback out of range = %d",
281 mFramesPerDataCallback);
282 return AAUDIO_ERROR_OUT_OF_RANGE;
283 }
284
285 return AAUDIO_OK;
286 }
287
AAudio_convertSharingModeToShortText(aaudio_sharing_mode_t sharingMode)288 static const char *AAudio_convertSharingModeToShortText(aaudio_sharing_mode_t sharingMode) {
289 switch (sharingMode) {
290 case AAUDIO_SHARING_MODE_EXCLUSIVE:
291 return "EX";
292 case AAUDIO_SHARING_MODE_SHARED:
293 return "SH";
294 default:
295 return "?!";
296 }
297 }
298
AAudio_convertDirectionToText(aaudio_direction_t direction)299 static const char *AAudio_convertDirectionToText(aaudio_direction_t direction) {
300 switch (direction) {
301 case AAUDIO_DIRECTION_OUTPUT:
302 return "OUTPUT";
303 case AAUDIO_DIRECTION_INPUT:
304 return "INPUT";
305 default:
306 return "?!";
307 }
308 }
309
logParameters() const310 void AudioStreamBuilder::logParameters() const {
311 // This is very helpful for debugging in the future. Please leave it in.
312 ALOGI("rate = %6d, channels = %d, channelMask = %#x, format = %d, sharing = %s, dir = %s",
313 getSampleRate(), getSamplesPerFrame(), getChannelMask(), getFormat(),
314 AAudio_convertSharingModeToShortText(getSharingMode()),
315 AAudio_convertDirectionToText(getDirection()));
316 ALOGI("device = %6d, sessionId = %d, perfMode = %d, callback: %s with frames = %d",
317 getDeviceId(),
318 getSessionId(),
319 getPerformanceMode(),
320 ((getDataCallbackProc() != nullptr) ? "ON" : "OFF"),
321 mFramesPerDataCallback);
322 ALOGI("usage = %6d, contentType = %d, inputPreset = %d, allowedCapturePolicy = %d",
323 getUsage(), getContentType(), getInputPreset(), getAllowedCapturePolicy());
324 ALOGI("privacy sensitive = %s, opPackageName = %s, attributionTag = %s",
325 isPrivacySensitive() ? "true" : "false",
326 !getOpPackageName().has_value() ? "(null)" : getOpPackageName().value().c_str(),
327 !getAttributionTag().has_value() ? "(null)" : getAttributionTag().value().c_str());
328 }
329