Home | History | Annotate | Download | only in utility
      1 /*
      2  * Copyright 2016 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 <cutils/properties.h>
     22 #include <stdint.h>
     23 #include <sys/types.h>
     24 #include <utils/Errors.h>
     25 
     26 #include "aaudio/AAudio.h"
     27 #include <aaudio/AAudioTesting.h>
     28 #include <math.h>
     29 #include <system/audio-base.h>
     30 #include <assert.h>
     31 
     32 #include "utility/AAudioUtilities.h"
     33 
     34 using namespace android;
     35 
     36 status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) {
     37     // This covers the case for AAUDIO_OK and for positive results.
     38     if (result >= 0) {
     39         return result;
     40     }
     41     status_t status;
     42     switch (result) {
     43     case AAUDIO_ERROR_DISCONNECTED:
     44     case AAUDIO_ERROR_NO_SERVICE:
     45         status = DEAD_OBJECT;
     46         break;
     47     case AAUDIO_ERROR_INVALID_HANDLE:
     48         status = BAD_TYPE;
     49         break;
     50     case AAUDIO_ERROR_INVALID_STATE:
     51         status = INVALID_OPERATION;
     52         break;
     53     case AAUDIO_ERROR_INVALID_RATE:
     54     case AAUDIO_ERROR_INVALID_FORMAT:
     55     case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
     56     case AAUDIO_ERROR_OUT_OF_RANGE:
     57         status = BAD_VALUE;
     58         break;
     59     case AAUDIO_ERROR_WOULD_BLOCK:
     60         status = WOULD_BLOCK;
     61         break;
     62     case AAUDIO_ERROR_NULL:
     63         status = UNEXPECTED_NULL;
     64         break;
     65     case AAUDIO_ERROR_UNAVAILABLE:
     66         status = NOT_ENOUGH_DATA;
     67         break;
     68 
     69     // TODO translate these result codes
     70     case AAUDIO_ERROR_INTERNAL:
     71     case AAUDIO_ERROR_UNIMPLEMENTED:
     72     case AAUDIO_ERROR_NO_FREE_HANDLES:
     73     case AAUDIO_ERROR_NO_MEMORY:
     74     case AAUDIO_ERROR_TIMEOUT:
     75     default:
     76         status = UNKNOWN_ERROR;
     77         break;
     78     }
     79     return status;
     80 }
     81 
     82 aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
     83     // This covers the case for OK and for positive result.
     84     if (status >= 0) {
     85         return status;
     86     }
     87     aaudio_result_t result;
     88     switch (status) {
     89     case BAD_TYPE:
     90         result = AAUDIO_ERROR_INVALID_HANDLE;
     91         break;
     92     case DEAD_OBJECT:
     93         result = AAUDIO_ERROR_NO_SERVICE;
     94         break;
     95     case INVALID_OPERATION:
     96         result = AAUDIO_ERROR_INVALID_STATE;
     97         break;
     98     case UNEXPECTED_NULL:
     99         result = AAUDIO_ERROR_NULL;
    100         break;
    101     case BAD_VALUE:
    102         result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    103         break;
    104     case WOULD_BLOCK:
    105         result = AAUDIO_ERROR_WOULD_BLOCK;
    106         break;
    107     case NOT_ENOUGH_DATA:
    108         result = AAUDIO_ERROR_UNAVAILABLE;
    109         break;
    110     default:
    111         result = AAUDIO_ERROR_INTERNAL;
    112         break;
    113     }
    114     return result;
    115 }
    116 
    117 audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId) {
    118     // If not a regular sessionId then convert to a safe value of AUDIO_SESSION_ALLOCATE.
    119     return (sessionId == AAUDIO_SESSION_ID_ALLOCATE || sessionId == AAUDIO_SESSION_ID_NONE)
    120            ? AUDIO_SESSION_ALLOCATE
    121            : (audio_session_t) sessionId;
    122 }
    123 
    124 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
    125     audio_format_t androidFormat;
    126     switch (aaudioFormat) {
    127     case AAUDIO_FORMAT_UNSPECIFIED:
    128         androidFormat = AUDIO_FORMAT_DEFAULT;
    129         break;
    130     case AAUDIO_FORMAT_PCM_I16:
    131         androidFormat = AUDIO_FORMAT_PCM_16_BIT;
    132         break;
    133     case AAUDIO_FORMAT_PCM_FLOAT:
    134         androidFormat = AUDIO_FORMAT_PCM_FLOAT;
    135         break;
    136     default:
    137         androidFormat = AUDIO_FORMAT_INVALID;
    138         ALOGE("%s() 0x%08X unrecognized", __func__, aaudioFormat);
    139         break;
    140     }
    141     return androidFormat;
    142 }
    143 
    144 aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
    145     aaudio_format_t aaudioFormat;
    146     switch (androidFormat) {
    147     case AUDIO_FORMAT_DEFAULT:
    148         aaudioFormat = AAUDIO_FORMAT_UNSPECIFIED;
    149         break;
    150     case AUDIO_FORMAT_PCM_16_BIT:
    151         aaudioFormat = AAUDIO_FORMAT_PCM_I16;
    152         break;
    153     case AUDIO_FORMAT_PCM_FLOAT:
    154         aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
    155         break;
    156     default:
    157         aaudioFormat = AAUDIO_FORMAT_INVALID;
    158         ALOGE("%s() 0x%08X unrecognized", __func__, androidFormat);
    159         break;
    160     }
    161     return aaudioFormat;
    162 }
    163 
    164 // Make a message string from the condition.
    165 #define STATIC_ASSERT(condition) static_assert(condition, #condition)
    166 
    167 audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage) {
    168     // The public aaudio_content_type_t constants are supposed to have the same
    169     // values as the internal audio_content_type_t values.
    170     STATIC_ASSERT(AAUDIO_USAGE_MEDIA == AUDIO_USAGE_MEDIA);
    171     STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION == AUDIO_USAGE_VOICE_COMMUNICATION);
    172     STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING
    173                   == AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING);
    174     STATIC_ASSERT(AAUDIO_USAGE_ALARM == AUDIO_USAGE_ALARM);
    175     STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION == AUDIO_USAGE_NOTIFICATION);
    176     STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_RINGTONE
    177                   == AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE);
    178     STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_EVENT == AUDIO_USAGE_NOTIFICATION_EVENT);
    179     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY);
    180     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
    181                   == AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
    182     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_SONIFICATION == AUDIO_USAGE_ASSISTANCE_SONIFICATION);
    183     STATIC_ASSERT(AAUDIO_USAGE_GAME == AUDIO_USAGE_GAME);
    184     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANT == AUDIO_USAGE_ASSISTANT);
    185     if (usage == AAUDIO_UNSPECIFIED) {
    186         usage = AAUDIO_USAGE_MEDIA;
    187     }
    188     return (audio_usage_t) usage; // same value
    189 }
    190 
    191 audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType) {
    192     // The public aaudio_content_type_t constants are supposed to have the same
    193     // values as the internal audio_content_type_t values.
    194     STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MUSIC == AUDIO_CONTENT_TYPE_MUSIC);
    195     STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SPEECH == AUDIO_CONTENT_TYPE_SPEECH);
    196     STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SONIFICATION == AUDIO_CONTENT_TYPE_SONIFICATION);
    197     STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MOVIE == AUDIO_CONTENT_TYPE_MOVIE);
    198     if (contentType == AAUDIO_UNSPECIFIED) {
    199         contentType = AAUDIO_CONTENT_TYPE_MUSIC;
    200     }
    201     return (audio_content_type_t) contentType; // same value
    202 }
    203 
    204 audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset) {
    205     // The public aaudio_input_preset_t constants are supposed to have the same
    206     // values as the internal audio_source_t values.
    207     STATIC_ASSERT(AAUDIO_UNSPECIFIED == AUDIO_SOURCE_DEFAULT);
    208     STATIC_ASSERT(AAUDIO_INPUT_PRESET_GENERIC == AUDIO_SOURCE_MIC);
    209     STATIC_ASSERT(AAUDIO_INPUT_PRESET_CAMCORDER == AUDIO_SOURCE_CAMCORDER);
    210     STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION);
    211     STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
    212     STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
    213     STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE == AUDIO_SOURCE_VOICE_PERFORMANCE);
    214     if (preset == AAUDIO_UNSPECIFIED) {
    215         preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
    216     }
    217     return (audio_source_t) preset; // same value
    218 }
    219 
    220 audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
    221         aaudio_allowed_capture_policy_t policy) {
    222     switch (policy) {
    223         case AAUDIO_UNSPECIFIED:
    224         case AAUDIO_ALLOW_CAPTURE_BY_ALL:
    225             return AUDIO_FLAG_NONE;
    226         case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
    227             return AUDIO_FLAG_NO_MEDIA_PROJECTION;
    228         case AAUDIO_ALLOW_CAPTURE_BY_NONE:
    229             return AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE;
    230         default:
    231             ALOGE("%s() 0x%08X unrecognized", __func__, policy);
    232             return AUDIO_FLAG_NONE; //
    233     }
    234 }
    235 
    236 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
    237                                     int32_t bytesPerFrame,
    238                                     int32_t *sizeInBytes) {
    239     *sizeInBytes = 0;
    240 
    241     if (numFrames < 0 || bytesPerFrame < 0) {
    242         ALOGE("negative size, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
    243         return AAUDIO_ERROR_OUT_OF_RANGE;
    244     }
    245 
    246     // Prevent numeric overflow.
    247     if (numFrames > (INT32_MAX / bytesPerFrame)) {
    248         ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
    249         return AAUDIO_ERROR_OUT_OF_RANGE;
    250     }
    251 
    252     *sizeInBytes = numFrames * bytesPerFrame;
    253     return AAUDIO_OK;
    254 }
    255 
    256 static int32_t AAudioProperty_getMMapProperty(const char *propName,
    257                                               int32_t defaultValue,
    258                                               const char * caller) {
    259     int32_t prop = property_get_int32(propName, defaultValue);
    260     switch (prop) {
    261         case AAUDIO_UNSPECIFIED:
    262         case AAUDIO_POLICY_NEVER:
    263         case AAUDIO_POLICY_ALWAYS:
    264         case AAUDIO_POLICY_AUTO:
    265             break;
    266         default:
    267             ALOGE("%s: invalid = %d", caller, prop);
    268             prop = defaultValue;
    269             break;
    270     }
    271     return prop;
    272 }
    273 
    274 int32_t AAudioProperty_getMMapPolicy() {
    275     return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY,
    276                                           AAUDIO_UNSPECIFIED, __func__);
    277 }
    278 
    279 int32_t AAudioProperty_getMMapExclusivePolicy() {
    280     return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY,
    281                                           AAUDIO_UNSPECIFIED, __func__);
    282 }
    283 
    284 int32_t AAudioProperty_getMixerBursts() {
    285     const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered
    286     const int32_t maxBursts = 1024; // arbitrary
    287     int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts);
    288     if (prop < 1 || prop > maxBursts) {
    289         ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop);
    290         prop = defaultBursts;
    291     }
    292     return prop;
    293 }
    294 
    295 int32_t AAudioProperty_getWakeupDelayMicros() {
    296     const int32_t minMicros = 0; // arbitrary
    297     const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter
    298     const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500
    299     int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros);
    300     if (prop < minMicros) {
    301         ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros);
    302         prop = minMicros;
    303     } else if (prop > maxMicros) {
    304         ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros);
    305         prop = maxMicros;
    306     }
    307     return prop;
    308 }
    309 
    310 int32_t AAudioProperty_getMinimumSleepMicros() {
    311     const int32_t minMicros = 20; // arbitrary
    312     const int32_t defaultMicros = 200; // arbitrary
    313     const int32_t maxMicros = 2000; // arbitrary
    314     int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
    315     if (prop < minMicros) {
    316         ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros);
    317         prop = minMicros;
    318     } else if (prop > maxMicros) {
    319         ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros);
    320         prop = maxMicros;
    321     }
    322     return prop;
    323 }
    324 
    325 int32_t AAudioProperty_getHardwareBurstMinMicros() {
    326     const int32_t defaultMicros = 1000; // arbitrary
    327     const int32_t maxMicros = 1000 * 1000; // arbitrary
    328     int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros);
    329     if (prop < 1 || prop > maxMicros) {
    330         ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d, use %d",
    331               prop, defaultMicros);
    332         prop = defaultMicros;
    333     }
    334     return prop;
    335 }
    336 
    337 aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state) {
    338     aaudio_result_t result = AAUDIO_OK;
    339     switch (state) {
    340 // Proceed with flushing.
    341         case AAUDIO_STREAM_STATE_OPEN:
    342         case AAUDIO_STREAM_STATE_PAUSED:
    343         case AAUDIO_STREAM_STATE_STOPPED:
    344         case AAUDIO_STREAM_STATE_FLUSHED:
    345             break;
    346 
    347 // Transition from one inactive state to another.
    348         case AAUDIO_STREAM_STATE_STARTING:
    349         case AAUDIO_STREAM_STATE_STARTED:
    350         case AAUDIO_STREAM_STATE_STOPPING:
    351         case AAUDIO_STREAM_STATE_PAUSING:
    352         case AAUDIO_STREAM_STATE_FLUSHING:
    353         case AAUDIO_STREAM_STATE_CLOSING:
    354         case AAUDIO_STREAM_STATE_CLOSED:
    355         case AAUDIO_STREAM_STATE_DISCONNECTED:
    356         default:
    357             ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s",
    358                   AAudio_convertStreamStateToText(state));
    359             result =  AAUDIO_ERROR_INVALID_STATE;
    360             break;
    361     }
    362     return result;
    363 }
    364