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