1 /*
2 * Copyright 2017 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
18 #define LOG_TAG "AAudioStreamParameters"
19
20 #include <android-base/strings.h>
21 #include <utils/Log.h>
22 #include <system/audio.h>
23 #include <system/aaudio/AAudio.h>
24
25 #include "AAudioStreamParameters.h"
26
27 using namespace aaudio;
28
copyFrom(const AAudioStreamParameters & other)29 void AAudioStreamParameters::copyFrom(const AAudioStreamParameters &other) {
30 mSamplesPerFrame = other.mSamplesPerFrame;
31 mSampleRate = other.mSampleRate;
32 mDeviceIds = other.mDeviceIds;
33 mSessionId = other.mSessionId;
34 mSharingMode = other.mSharingMode;
35 mAudioFormat = other.mAudioFormat;
36 mDirection = other.mDirection;
37 mBufferCapacity = other.mBufferCapacity;
38 mUsage = other.mUsage;
39 mContentType = other.mContentType;
40 mTags = other.mTags;
41 mSpatializationBehavior = other.mSpatializationBehavior;
42 mIsContentSpatialized = other.mIsContentSpatialized;
43 mInputPreset = other.mInputPreset;
44 mAllowedCapturePolicy = other.mAllowedCapturePolicy;
45 mIsPrivacySensitive = other.mIsPrivacySensitive;
46 mOpPackageName = other.mOpPackageName;
47 mAttributionTag = other.mAttributionTag;
48 mChannelMask = other.mChannelMask;
49 mHardwareSamplesPerFrame = other.mHardwareSamplesPerFrame;
50 mHardwareSampleRate = other.mHardwareSampleRate;
51 mHardwareAudioFormat = other.mHardwareAudioFormat;
52 }
53
isFormatValid(audio_format_t format)54 static aaudio_result_t isFormatValid(audio_format_t format) {
55 switch (format) {
56 case AUDIO_FORMAT_DEFAULT:
57 case AUDIO_FORMAT_PCM_16_BIT:
58 case AUDIO_FORMAT_PCM_32_BIT:
59 case AUDIO_FORMAT_PCM_FLOAT:
60 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
61 case AUDIO_FORMAT_PCM_8_24_BIT:
62 case AUDIO_FORMAT_IEC61937:
63 case AUDIO_FORMAT_MP3:
64 case AUDIO_FORMAT_AAC_LC:
65 case AUDIO_FORMAT_AAC_HE_V1:
66 case AUDIO_FORMAT_AAC_HE_V2:
67 case AUDIO_FORMAT_AAC_ELD:
68 case AUDIO_FORMAT_AAC_XHE:
69 case AUDIO_FORMAT_OPUS:
70 break; // valid
71 default:
72 ALOGD("audioFormat not valid, audio_format_t = 0x%08x", format);
73 return AAUDIO_ERROR_INVALID_FORMAT;
74 // break;
75 }
76 return AAUDIO_OK;
77 }
78
validate() const79 aaudio_result_t AAudioStreamParameters::validate() const {
80 if (mSamplesPerFrame != AAUDIO_UNSPECIFIED && (mSamplesPerFrame < CHANNEL_COUNT_MIN_AAUDIO ||
81 mSamplesPerFrame > CHANNEL_COUNT_MAX_AAUDIO)) {
82 ALOGD("channelCount out of range = %d", mSamplesPerFrame);
83 return AAUDIO_ERROR_OUT_OF_RANGE;
84 }
85
86 // TODO(b/379139078): Query AudioSystem::listAudioPorts
87 for (auto deviceId : mDeviceIds) {
88 if (deviceId < 0) {
89 ALOGE("deviceId out of range = %d, deviceIds = %s", deviceId,
90 android::toString(mDeviceIds).c_str());
91 return AAUDIO_ERROR_OUT_OF_RANGE;
92 }
93 }
94
95 // All Session ID values are legal.
96 switch (mSessionId) {
97 case AAUDIO_SESSION_ID_NONE:
98 case AAUDIO_SESSION_ID_ALLOCATE:
99 default:
100 break;
101 }
102
103 switch (mSharingMode) {
104 case AAUDIO_SHARING_MODE_EXCLUSIVE:
105 case AAUDIO_SHARING_MODE_SHARED:
106 break;
107 default:
108 ALOGD("illegal sharingMode = %d", mSharingMode);
109 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
110 // break;
111 }
112
113 aaudio_result_t result = isFormatValid (mAudioFormat);
114 if (result != AAUDIO_OK) return result;
115
116 if (mSampleRate != AAUDIO_UNSPECIFIED &&
117 (mSampleRate < SAMPLE_RATE_HZ_MIN_AAUDIO || mSampleRate > SAMPLE_RATE_HZ_MAX_IEC610937)) {
118 ALOGD("sampleRate out of range = %d", mSampleRate);
119 return AAUDIO_ERROR_INVALID_RATE;
120 }
121
122 if (mBufferCapacity < 0) {
123 ALOGD("bufferCapacity out of range = %d", mBufferCapacity);
124 return AAUDIO_ERROR_OUT_OF_RANGE;
125 }
126
127 switch (mDirection) {
128 case AAUDIO_DIRECTION_INPUT:
129 case AAUDIO_DIRECTION_OUTPUT:
130 break; // valid
131 default:
132 ALOGD("direction not valid = %d", mDirection);
133 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
134 // break;
135 }
136
137 switch (mUsage) {
138 case AAUDIO_UNSPECIFIED:
139 case AAUDIO_USAGE_MEDIA:
140 case AAUDIO_USAGE_VOICE_COMMUNICATION:
141 case AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
142 case AAUDIO_USAGE_ALARM:
143 case AAUDIO_USAGE_NOTIFICATION:
144 case AAUDIO_USAGE_NOTIFICATION_RINGTONE:
145 case AAUDIO_USAGE_NOTIFICATION_EVENT:
146 case AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
147 case AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
148 case AAUDIO_USAGE_ASSISTANCE_SONIFICATION:
149 case AAUDIO_USAGE_GAME:
150 case AAUDIO_USAGE_ASSISTANT:
151 case AAUDIO_SYSTEM_USAGE_EMERGENCY:
152 case AAUDIO_SYSTEM_USAGE_SAFETY:
153 case AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS:
154 case AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT:
155 break; // valid
156 default:
157 ALOGD("usage not valid = %d", mUsage);
158 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
159 // break;
160 }
161
162 switch (mContentType) {
163 case AAUDIO_UNSPECIFIED:
164 case AAUDIO_CONTENT_TYPE_MUSIC:
165 case AAUDIO_CONTENT_TYPE_MOVIE:
166 case AAUDIO_CONTENT_TYPE_SONIFICATION:
167 case AAUDIO_CONTENT_TYPE_SPEECH:
168 break; // valid
169 default:
170 ALOGD("content type not valid = %d", mContentType);
171 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
172 // break;
173 }
174
175 switch (mSpatializationBehavior) {
176 case AAUDIO_UNSPECIFIED:
177 case AAUDIO_SPATIALIZATION_BEHAVIOR_AUTO:
178 case AAUDIO_SPATIALIZATION_BEHAVIOR_NEVER:
179 break; // valid
180 default:
181 ALOGD("spatialization behavior not valid = %d", mSpatializationBehavior);
182 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
183 // break;
184 }
185
186 // no validation required for mIsContentSpatialized
187
188 switch (mInputPreset) {
189 case AAUDIO_UNSPECIFIED:
190 case AAUDIO_INPUT_PRESET_GENERIC:
191 case AAUDIO_INPUT_PRESET_CAMCORDER:
192 case AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION:
193 case AAUDIO_INPUT_PRESET_VOICE_RECOGNITION:
194 case AAUDIO_INPUT_PRESET_UNPROCESSED:
195 case AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE:
196 case AAUDIO_INPUT_PRESET_SYSTEM_ECHO_REFERENCE:
197 case AAUDIO_INPUT_PRESET_SYSTEM_HOTWORD:
198 break; // valid
199 default:
200 ALOGD("input preset not valid = %d", mInputPreset);
201 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
202 // break;
203 }
204
205 switch (mAllowedCapturePolicy) {
206 case AAUDIO_UNSPECIFIED:
207 case AAUDIO_ALLOW_CAPTURE_BY_ALL:
208 case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
209 case AAUDIO_ALLOW_CAPTURE_BY_NONE:
210 break; // valid
211 default:
212 ALOGD("allowed capture policy not valid = %d", mAllowedCapturePolicy);
213 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
214 // break;
215 }
216
217 if (getTagsAsString().size() >= AUDIO_ATTRIBUTES_TAGS_MAX_SIZE) {
218 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
219 }
220
221 return validateChannelMask();
222 }
223
validateChannelMask() const224 aaudio_result_t AAudioStreamParameters::validateChannelMask() const {
225 if (mChannelMask == AAUDIO_UNSPECIFIED) {
226 return AAUDIO_OK;
227 }
228
229 if (mChannelMask & AAUDIO_CHANNEL_BIT_INDEX) {
230 switch (mChannelMask) {
231 case AAUDIO_CHANNEL_INDEX_MASK_1:
232 case AAUDIO_CHANNEL_INDEX_MASK_2:
233 case AAUDIO_CHANNEL_INDEX_MASK_3:
234 case AAUDIO_CHANNEL_INDEX_MASK_4:
235 case AAUDIO_CHANNEL_INDEX_MASK_5:
236 case AAUDIO_CHANNEL_INDEX_MASK_6:
237 case AAUDIO_CHANNEL_INDEX_MASK_7:
238 case AAUDIO_CHANNEL_INDEX_MASK_8:
239 case AAUDIO_CHANNEL_INDEX_MASK_9:
240 case AAUDIO_CHANNEL_INDEX_MASK_10:
241 case AAUDIO_CHANNEL_INDEX_MASK_11:
242 case AAUDIO_CHANNEL_INDEX_MASK_12:
243 case AAUDIO_CHANNEL_INDEX_MASK_13:
244 case AAUDIO_CHANNEL_INDEX_MASK_14:
245 case AAUDIO_CHANNEL_INDEX_MASK_15:
246 case AAUDIO_CHANNEL_INDEX_MASK_16:
247 case AAUDIO_CHANNEL_INDEX_MASK_17:
248 case AAUDIO_CHANNEL_INDEX_MASK_18:
249 case AAUDIO_CHANNEL_INDEX_MASK_19:
250 case AAUDIO_CHANNEL_INDEX_MASK_20:
251 case AAUDIO_CHANNEL_INDEX_MASK_21:
252 case AAUDIO_CHANNEL_INDEX_MASK_22:
253 case AAUDIO_CHANNEL_INDEX_MASK_23:
254 case AAUDIO_CHANNEL_INDEX_MASK_24:
255 return AAUDIO_OK;
256 default:
257 ALOGD("Invalid channel index mask %#x", mChannelMask);
258 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
259 }
260 }
261
262 if (getDirection() == AAUDIO_DIRECTION_INPUT) {
263 switch (mChannelMask) {
264 case AAUDIO_CHANNEL_MONO:
265 case AAUDIO_CHANNEL_STEREO:
266 case AAUDIO_CHANNEL_FRONT_BACK:
267 case AAUDIO_CHANNEL_2POINT0POINT2:
268 case AAUDIO_CHANNEL_2POINT1POINT2:
269 case AAUDIO_CHANNEL_3POINT0POINT2:
270 case AAUDIO_CHANNEL_3POINT1POINT2:
271 case AAUDIO_CHANNEL_5POINT1:
272 return AAUDIO_OK;
273 default:
274 ALOGD("Invalid channel mask %#x, IN", mChannelMask);
275 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
276 }
277 } else {
278 switch (mChannelMask) {
279 case AAUDIO_CHANNEL_MONO:
280 case AAUDIO_CHANNEL_STEREO:
281 case AAUDIO_CHANNEL_2POINT1:
282 case AAUDIO_CHANNEL_TRI:
283 case AAUDIO_CHANNEL_TRI_BACK:
284 case AAUDIO_CHANNEL_3POINT1:
285 case AAUDIO_CHANNEL_2POINT0POINT2:
286 case AAUDIO_CHANNEL_2POINT1POINT2:
287 case AAUDIO_CHANNEL_3POINT0POINT2:
288 case AAUDIO_CHANNEL_3POINT1POINT2:
289 case AAUDIO_CHANNEL_QUAD:
290 case AAUDIO_CHANNEL_QUAD_SIDE:
291 case AAUDIO_CHANNEL_SURROUND:
292 case AAUDIO_CHANNEL_PENTA:
293 case AAUDIO_CHANNEL_5POINT1:
294 case AAUDIO_CHANNEL_5POINT1_SIDE:
295 case AAUDIO_CHANNEL_5POINT1POINT2:
296 case AAUDIO_CHANNEL_5POINT1POINT4:
297 case AAUDIO_CHANNEL_6POINT1:
298 case AAUDIO_CHANNEL_7POINT1:
299 case AAUDIO_CHANNEL_7POINT1POINT2:
300 case AAUDIO_CHANNEL_7POINT1POINT4:
301 case AAUDIO_CHANNEL_9POINT1POINT4:
302 case AAUDIO_CHANNEL_9POINT1POINT6:
303 return AAUDIO_OK;
304 default:
305 ALOGD("Invalid channel mask %#x. OUT", mChannelMask);
306 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
307 }
308 }
309 }
310
getTagsAsString() const311 std::string AAudioStreamParameters::getTagsAsString() const {
312 return android::base::Join(mTags, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
313 }
314
dump() const315 void AAudioStreamParameters::dump() const {
316 ALOGD("mDeviceIds = %s", android::toString(mDeviceIds).c_str());
317 ALOGD("mSessionId = %6d", mSessionId);
318 ALOGD("mSampleRate = %6d", mSampleRate);
319 ALOGD("mSamplesPerFrame = %6d", mSamplesPerFrame);
320 ALOGD("mChannelMask = %#x", mChannelMask);
321 ALOGD("mSharingMode = %6d", (int)mSharingMode);
322 ALOGD("mAudioFormat = %6d", (int)mAudioFormat);
323 ALOGD("mDirection = %6d", mDirection);
324 ALOGD("mBufferCapacity = %6d", mBufferCapacity);
325 ALOGD("mUsage = %6d", mUsage);
326 ALOGD("mContentType = %6d", mContentType);
327 ALOGD("mTags = %s", getTagsAsString().c_str());
328 ALOGD("mSpatializationBehavior = %6d", mSpatializationBehavior);
329 ALOGD("mIsContentSpatialized = %s", mIsContentSpatialized ? "true" : "false");
330 ALOGD("mInputPreset = %6d", mInputPreset);
331 ALOGD("mAllowedCapturePolicy = %6d", mAllowedCapturePolicy);
332 ALOGD("mIsPrivacySensitive = %s", mIsPrivacySensitive ? "true" : "false");
333 ALOGD("mOpPackageName = %s", !mOpPackageName.has_value() ?
334 "(null)" : mOpPackageName.value().c_str());
335 ALOGD("mAttributionTag = %s", !mAttributionTag.has_value() ?
336 "(null)" : mAttributionTag.value().c_str());
337 ALOGD("mHardwareSamplesPerFrame = %6d", mHardwareSamplesPerFrame);
338 ALOGD("mHardwareSampleRate = %6d", mHardwareSampleRate);
339 ALOGD("mHardwareAudioFormat = %6d", (int)mHardwareAudioFormat);
340 }
341