OSDN Git Service

Merge "Moved libalsautils to vendor. Marked libaudioutils and libaudioroute as vendor...
authorVijay Venkatraman <vijaykv@google.com>
Fri, 12 May 2017 22:52:17 +0000 (22:52 +0000)
committerandroid-build-merger <android-build-merger@google.com>
Fri, 12 May 2017 22:52:17 +0000 (22:52 +0000)
am: fcc32970cf

Change-Id: I658cf987c99c45bd10f72778aef18db9d66ce437

83 files changed:
alsa_utils/alsa_device_proxy.c
alsa_utils/include/alsa_device_profile.h
alsa_utils/include/alsa_device_proxy.h
audio/include/system/audio-base.h [new file with mode: 0644]
audio/include/system/audio.h
audio/include/system/audio_effect-base.h [new file with mode: 0644]
audio/include/system/audio_effect.h [new file with mode: 0644]
audio/include/system/audio_effects/audio_effects_conf.h [moved from audio_effects/include/audio_effects/audio_effects_conf.h with 100% similarity, mode: 0644]
audio/include/system/audio_effects/effect_aec.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_agc.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_bassboost.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_downmix.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_environmentalreverb.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_equalizer.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_loudnessenhancer.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_ns.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_presetreverb.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_virtualizer.h [new file with mode: 0644]
audio/include/system/audio_effects/effect_visualizer.h [new file with mode: 0644]
audio/include/system/sound_trigger.h
audio_effects/include/audio_effects/effect_aec.h
audio_effects/include/audio_effects/effect_agc.h
audio_effects/include/audio_effects/effect_bassboost.h
audio_effects/include/audio_effects/effect_downmix.h
audio_effects/include/audio_effects/effect_environmentalreverb.h
audio_effects/include/audio_effects/effect_equalizer.h
audio_effects/include/audio_effects/effect_loudnessenhancer.h
audio_effects/include/audio_effects/effect_ns.h
audio_effects/include/audio_effects/effect_presetreverb.h
audio_effects/include/audio_effects/effect_virtualizer.h
audio_effects/include/audio_effects/effect_visualizer.h
audio_route/audio_route.c
audio_utils/Android.bp
audio_utils/ErrorLog.cpp [new file with mode: 0644]
audio_utils/PowerLog.cpp [new file with mode: 0644]
audio_utils/README.md [new file with mode: 0644]
audio_utils/channels.c
audio_utils/fifo.c [deleted file]
audio_utils/fifo.cpp [new file with mode: 0644]
audio_utils/fifo_index.cpp [new file with mode: 0644]
audio_utils/include/audio_utils/ErrorLog.h [new file with mode: 0644]
audio_utils/include/audio_utils/PowerLog.h [new file with mode: 0644]
audio_utils/include/audio_utils/SimpleLog.h [new file with mode: 0644]
audio_utils/include/audio_utils/clock.h [new file with mode: 0644]
audio_utils/include/audio_utils/clock_nanosleep.h [new file with mode: 0644]
audio_utils/include/audio_utils/fifo.h
audio_utils/include/audio_utils/fifo_index.h [new file with mode: 0644]
audio_utils/include/audio_utils/futex.h [new file with mode: 0644]
audio_utils/include/audio_utils/mono_blend.h [moved from audio_utils/include/audio_utils/conversion.h with 100% similarity]
audio_utils/include/audio_utils/power.h [new file with mode: 0644]
audio_utils/include/audio_utils/sndfile.h
audio_utils/include/audio_utils/spdif/SPDIFEncoder.h
audio_utils/mono_blend.cpp [moved from audio_utils/conversion.cpp with 96% similarity]
audio_utils/power.cpp [new file with mode: 0644]
audio_utils/primitives.c
audio_utils/spdif/AC3FrameScanner.h
audio_utils/spdif/SPDIFEncoder.cpp
audio_utils/tests/Android.bp
audio_utils/tests/README.md
audio_utils/tests/errorlog_tests.cpp [new file with mode: 0644]
audio_utils/tests/fifo_multiprocess.cpp [new file with mode: 0644]
audio_utils/tests/fifo_tests.cpp
audio_utils/tests/fifo_threads.cpp [new file with mode: 0644]
audio_utils/tests/getch.c [new file with mode: 0644]
audio_utils/tests/getch.h [new file with mode: 0644]
audio_utils/tests/power_tests.cpp [new file with mode: 0644]
audio_utils/tests/powerlog_tests.cpp [new file with mode: 0644]
audio_utils/tests/simplelog_tests.cpp [new file with mode: 0644]
brillo/audio/audioservice/Android.mk
camera/Android.bp
camera/docs/docs.html
camera/docs/metadata_properties.xml
camera/docs/ndk_metadata_properties.xml
camera/include/system/camera_metadata.h
camera/include/system/camera_metadata_tags.h
camera/include/system/camera_vendor_tags.h
camera/src/camera_metadata.c
camera/src/camera_metadata_tag_info.c
camera/tests/camera_metadata_tests.cpp
private/camera/include/camera_metadata_hidden.h
radio/include/system/radio_metadata.h
radio/src/radio_metadata.c
radio/src/radio_metadata_hidden.h

index 73e4375..9b06d16 100644 (file)
@@ -39,9 +39,11 @@ static const unsigned format_byte_size_map[] = {
     3, /* PCM_FORMAT_S24_3LE */
 };
 
-void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
+int proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
                    struct pcm_config * config)
 {
+    int ret = 0;
+
     ALOGV("proxy_prepare(c:%d, d:%d)", profile->card, profile->device);
 
     proxy->profile = profile;
@@ -53,17 +55,25 @@ void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
     if (config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format)) {
         proxy->alsa_config.format = config->format;
     } else {
+        proxy->alsa_config.format = profile->default_config.format;
         ALOGW("Invalid format %d - using default %d.",
               config->format, profile->default_config.format);
-        proxy->alsa_config.format = profile->default_config.format;
+        // Indicate override when default format was not requested
+        if (config->format != PCM_FORMAT_INVALID) {
+            ret = -EINVAL;
+        }
     }
 
     if (config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate)) {
         proxy->alsa_config.rate = config->rate;
     } else {
+        proxy->alsa_config.rate = profile->default_config.rate;
         ALOGW("Invalid sample rate %u - using default %u.",
               config->rate, profile->default_config.rate);
-        proxy->alsa_config.rate = profile->default_config.rate;
+        // Indicate override when default rate was not requested
+        if (config->rate != 0) {
+            ret = -EINVAL;
+        }
     }
 
     if (config->channels != 0 && profile_is_channel_count_valid(profile, config->channels)) {
@@ -72,6 +82,10 @@ void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
         proxy->alsa_config.channels = profile_get_closest_channel_count(profile, config->channels);
         ALOGW("Invalid channel count %u - using closest %u.",
               config->channels, proxy->alsa_config.channels);
+        // Indicate override when default channel count was not requested
+        if (config->channels != 0) {
+            ret = -EINVAL;
+        }
     }
 
     proxy->alsa_config.period_count = profile->default_config.period_count;
@@ -92,6 +106,20 @@ void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
     } else {
         proxy->frame_size = 1;
     }
+
+    // let's check to make sure we can ACTUALLY use the maximum rate (with the channel count)
+    // Note that profile->sample_rates is sorted highest to lowest, so the scan will get
+    // us the highest working rate
+    int max_rate_index = proxy_scan_rates(proxy, profile->sample_rates);
+    if (max_rate_index >= 0) {
+        if (proxy->alsa_config.rate > profile->sample_rates[max_rate_index]) {
+            ALOGW("Limiting samplnig rate from %u to %u.",
+                  proxy->alsa_config.rate, profile->sample_rates[max_rate_index]);
+            proxy->alsa_config.rate = profile->sample_rates[max_rate_index];
+            ret = -EINVAL;
+        }
+    }
+    return ret;
 }
 
 int proxy_open(alsa_device_proxy * proxy)
@@ -111,7 +139,7 @@ int proxy_open(alsa_device_proxy * proxy)
     }
 
     if (!pcm_is_ready(proxy->pcm)) {
-        ALOGE("  proxy_open() pcm_open() failed: %s", pcm_get_error(proxy->pcm));
+        ALOGE("  proxy_open() pcm_is_ready() failed: %s", pcm_get_error(proxy->pcm));
 #if defined(LOG_PCM_PARAMS)
         log_pcm_config(&proxy->alsa_config, "config");
 #endif
@@ -231,3 +259,33 @@ void proxy_dump(const alsa_device_proxy* proxy, int fd)
         dprintf(fd, "  format: %d\n", proxy->alsa_config.format);
     }
 }
+
+int proxy_scan_rates(alsa_device_proxy * proxy, unsigned sample_rates[]) {
+    alsa_device_profile* profile = proxy->profile;
+    if (profile->card < 0 || profile->device < 0) {
+        return -EINVAL;
+    }
+
+    struct pcm_config alsa_config;
+    memcpy(&alsa_config, &proxy->alsa_config, sizeof(alsa_config));
+
+    struct pcm * alsa_pcm;
+    int rate_index = 0;
+    while (sample_rates[rate_index] != 0) {
+        alsa_config.rate = sample_rates[rate_index];
+        alsa_pcm = pcm_open(profile->card, profile->device,
+                profile->direction | PCM_MONOTONIC, &alsa_config);
+        if (alsa_pcm != NULL) {
+            if (pcm_is_ready(alsa_pcm)) {
+                pcm_close(alsa_pcm);
+                return rate_index;
+            }
+
+            pcm_close(alsa_pcm);
+        }
+
+        rate_index++;
+    }
+
+    return -EINVAL;
+}
index e056d70..8307d0a 100644 (file)
@@ -42,6 +42,7 @@ typedef struct  {
 
     enum pcm_format formats[MAX_PROFILE_FORMATS];
 
+    /* note that this list is sorted highest rate to lowest */
     unsigned sample_rates[MAX_PROFILE_SAMPLE_RATES];
 
     unsigned channel_counts[MAX_PROFILE_CHANNEL_COUNTS];
index 0bc0731..677bb5e 100644 (file)
@@ -34,7 +34,7 @@ typedef struct {
 
 
 /* State */
-void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile * profile,
+int proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile * profile,
                    struct pcm_config * config);
 int proxy_open(alsa_device_proxy * proxy);
 void proxy_close(alsa_device_proxy * proxy);
@@ -48,6 +48,14 @@ unsigned proxy_get_channel_count(const alsa_device_proxy * proxy);
 unsigned int proxy_get_period_size(const alsa_device_proxy * proxy);
 unsigned proxy_get_latency(const alsa_device_proxy * proxy);
 
+/*
+ * Scans the provided list of sample rates and finds the first one that works.
+ *
+ * returns the index of the first rate for which the ALSA device can be opened.
+ * return negative value if none work or an error occurs.
+ */
+int proxy_scan_rates(alsa_device_proxy * proxy, unsigned sample_rates[]);
+
 /* I/O */
 int proxy_write(alsa_device_proxy * proxy, const void *data, unsigned int count);
 int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count);
diff --git a/audio/include/system/audio-base.h b/audio/include/system/audio-base.h
new file mode 100644 (file)
index 0000000..441226d
--- /dev/null
@@ -0,0 +1,397 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+// Source: android.hardware.audio.common@2.0
+// Root: android.hardware:hardware/interfaces
+
+#ifndef HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_COMMON_V2_0_EXPORTED_CONSTANTS_H_
+#define HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_COMMON_V2_0_EXPORTED_CONSTANTS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    AUDIO_IO_HANDLE_NONE = 0,
+    AUDIO_MODULE_HANDLE_NONE = 0,
+    AUDIO_PORT_HANDLE_NONE = 0,
+    AUDIO_PATCH_HANDLE_NONE = 0,
+};
+
+typedef enum {
+    AUDIO_STREAM_DEFAULT = -1, // (-1)
+    AUDIO_STREAM_MIN = 0,
+    AUDIO_STREAM_VOICE_CALL = 0,
+    AUDIO_STREAM_SYSTEM = 1,
+    AUDIO_STREAM_RING = 2,
+    AUDIO_STREAM_MUSIC = 3,
+    AUDIO_STREAM_ALARM = 4,
+    AUDIO_STREAM_NOTIFICATION = 5,
+    AUDIO_STREAM_BLUETOOTH_SCO = 6,
+    AUDIO_STREAM_ENFORCED_AUDIBLE = 7,
+    AUDIO_STREAM_DTMF = 8,
+    AUDIO_STREAM_TTS = 9,
+    AUDIO_STREAM_ACCESSIBILITY = 10,
+    AUDIO_STREAM_REROUTING = 11,
+    AUDIO_STREAM_PATCH = 12,
+    AUDIO_STREAM_PUBLIC_CNT = 11, // (ACCESSIBILITY + 1)
+    AUDIO_STREAM_FOR_POLICY_CNT = 12, // PATCH
+    AUDIO_STREAM_CNT = 13, // (PATCH + 1)
+} audio_stream_type_t;
+
+typedef enum {
+    AUDIO_SOURCE_DEFAULT = 0,
+    AUDIO_SOURCE_MIC = 1,
+    AUDIO_SOURCE_VOICE_UPLINK = 2,
+    AUDIO_SOURCE_VOICE_DOWNLINK = 3,
+    AUDIO_SOURCE_VOICE_CALL = 4,
+    AUDIO_SOURCE_CAMCORDER = 5,
+    AUDIO_SOURCE_VOICE_RECOGNITION = 6,
+    AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
+    AUDIO_SOURCE_REMOTE_SUBMIX = 8,
+    AUDIO_SOURCE_UNPROCESSED = 9,
+    AUDIO_SOURCE_CNT = 10,
+    AUDIO_SOURCE_MAX = 9, // (CNT - 1)
+    AUDIO_SOURCE_FM_TUNER = 1998,
+    AUDIO_SOURCE_HOTWORD = 1999,
+} audio_source_t;
+
+typedef enum {
+    AUDIO_SESSION_OUTPUT_STAGE = -1, // (-1)
+    AUDIO_SESSION_OUTPUT_MIX = 0,
+    AUDIO_SESSION_ALLOCATE = 0,
+    AUDIO_SESSION_NONE = 0,
+} audio_session_t;
+
+typedef enum {
+    AUDIO_FORMAT_INVALID = 4294967295u, // 0xFFFFFFFFUL
+    AUDIO_FORMAT_DEFAULT = 0u, // 0
+    AUDIO_FORMAT_PCM = 0u, // 0x00000000UL
+    AUDIO_FORMAT_MP3 = 16777216u, // 0x01000000UL
+    AUDIO_FORMAT_AMR_NB = 33554432u, // 0x02000000UL
+    AUDIO_FORMAT_AMR_WB = 50331648u, // 0x03000000UL
+    AUDIO_FORMAT_AAC = 67108864u, // 0x04000000UL
+    AUDIO_FORMAT_HE_AAC_V1 = 83886080u, // 0x05000000UL
+    AUDIO_FORMAT_HE_AAC_V2 = 100663296u, // 0x06000000UL
+    AUDIO_FORMAT_VORBIS = 117440512u, // 0x07000000UL
+    AUDIO_FORMAT_OPUS = 134217728u, // 0x08000000UL
+    AUDIO_FORMAT_AC3 = 150994944u, // 0x09000000UL
+    AUDIO_FORMAT_E_AC3 = 167772160u, // 0x0A000000UL
+    AUDIO_FORMAT_DTS = 184549376u, // 0x0B000000UL
+    AUDIO_FORMAT_DTS_HD = 201326592u, // 0x0C000000UL
+    AUDIO_FORMAT_IEC61937 = 218103808u, // 0x0D000000UL
+    AUDIO_FORMAT_DOLBY_TRUEHD = 234881024u, // 0x0E000000UL
+    AUDIO_FORMAT_EVRC = 268435456u, // 0x10000000UL
+    AUDIO_FORMAT_EVRCB = 285212672u, // 0x11000000UL
+    AUDIO_FORMAT_EVRCWB = 301989888u, // 0x12000000UL
+    AUDIO_FORMAT_EVRCNW = 318767104u, // 0x13000000UL
+    AUDIO_FORMAT_AAC_ADIF = 335544320u, // 0x14000000UL
+    AUDIO_FORMAT_WMA = 352321536u, // 0x15000000UL
+    AUDIO_FORMAT_WMA_PRO = 369098752u, // 0x16000000UL
+    AUDIO_FORMAT_AMR_WB_PLUS = 385875968u, // 0x17000000UL
+    AUDIO_FORMAT_MP2 = 402653184u, // 0x18000000UL
+    AUDIO_FORMAT_QCELP = 419430400u, // 0x19000000UL
+    AUDIO_FORMAT_DSD = 436207616u, // 0x1A000000UL
+    AUDIO_FORMAT_FLAC = 452984832u, // 0x1B000000UL
+    AUDIO_FORMAT_ALAC = 469762048u, // 0x1C000000UL
+    AUDIO_FORMAT_APE = 486539264u, // 0x1D000000UL
+    AUDIO_FORMAT_AAC_ADTS = 503316480u, // 0x1E000000UL
+    AUDIO_FORMAT_SBC = 520093696u, // 0x1F000000UL
+    AUDIO_FORMAT_APTX = 536870912u, // 0x20000000UL
+    AUDIO_FORMAT_APTX_HD = 553648128u, // 0x21000000UL
+    AUDIO_FORMAT_AC4 = 570425344u, // 0x22000000UL
+    AUDIO_FORMAT_LDAC = 587202560u, // 0x23000000UL
+    AUDIO_FORMAT_MAIN_MASK = 4278190080u, // 0xFF000000UL
+    AUDIO_FORMAT_SUB_MASK = 16777215u, // 0x00FFFFFFUL
+    AUDIO_FORMAT_PCM_SUB_16_BIT = 1u, // 0x1
+    AUDIO_FORMAT_PCM_SUB_8_BIT = 2u, // 0x2
+    AUDIO_FORMAT_PCM_SUB_32_BIT = 3u, // 0x3
+    AUDIO_FORMAT_PCM_SUB_8_24_BIT = 4u, // 0x4
+    AUDIO_FORMAT_PCM_SUB_FLOAT = 5u, // 0x5
+    AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED = 6u, // 0x6
+    AUDIO_FORMAT_MP3_SUB_NONE = 0u, // 0x0
+    AUDIO_FORMAT_AMR_SUB_NONE = 0u, // 0x0
+    AUDIO_FORMAT_AAC_SUB_MAIN = 1u, // 0x1
+    AUDIO_FORMAT_AAC_SUB_LC = 2u, // 0x2
+    AUDIO_FORMAT_AAC_SUB_SSR = 4u, // 0x4
+    AUDIO_FORMAT_AAC_SUB_LTP = 8u, // 0x8
+    AUDIO_FORMAT_AAC_SUB_HE_V1 = 16u, // 0x10
+    AUDIO_FORMAT_AAC_SUB_SCALABLE = 32u, // 0x20
+    AUDIO_FORMAT_AAC_SUB_ERLC = 64u, // 0x40
+    AUDIO_FORMAT_AAC_SUB_LD = 128u, // 0x80
+    AUDIO_FORMAT_AAC_SUB_HE_V2 = 256u, // 0x100
+    AUDIO_FORMAT_AAC_SUB_ELD = 512u, // 0x200
+    AUDIO_FORMAT_VORBIS_SUB_NONE = 0u, // 0x0
+    AUDIO_FORMAT_PCM_16_BIT = 1u, // (PCM | PCM_SUB_16_BIT)
+    AUDIO_FORMAT_PCM_8_BIT = 2u, // (PCM | PCM_SUB_8_BIT)
+    AUDIO_FORMAT_PCM_32_BIT = 3u, // (PCM | PCM_SUB_32_BIT)
+    AUDIO_FORMAT_PCM_8_24_BIT = 4u, // (PCM | PCM_SUB_8_24_BIT)
+    AUDIO_FORMAT_PCM_FLOAT = 5u, // (PCM | PCM_SUB_FLOAT)
+    AUDIO_FORMAT_PCM_24_BIT_PACKED = 6u, // (PCM | PCM_SUB_24_BIT_PACKED)
+    AUDIO_FORMAT_AAC_MAIN = 67108865u, // (AAC | AAC_SUB_MAIN)
+    AUDIO_FORMAT_AAC_LC = 67108866u, // (AAC | AAC_SUB_LC)
+    AUDIO_FORMAT_AAC_SSR = 67108868u, // (AAC | AAC_SUB_SSR)
+    AUDIO_FORMAT_AAC_LTP = 67108872u, // (AAC | AAC_SUB_LTP)
+    AUDIO_FORMAT_AAC_HE_V1 = 67108880u, // (AAC | AAC_SUB_HE_V1)
+    AUDIO_FORMAT_AAC_SCALABLE = 67108896u, // (AAC | AAC_SUB_SCALABLE)
+    AUDIO_FORMAT_AAC_ERLC = 67108928u, // (AAC | AAC_SUB_ERLC)
+    AUDIO_FORMAT_AAC_LD = 67108992u, // (AAC | AAC_SUB_LD)
+    AUDIO_FORMAT_AAC_HE_V2 = 67109120u, // (AAC | AAC_SUB_HE_V2)
+    AUDIO_FORMAT_AAC_ELD = 67109376u, // (AAC | AAC_SUB_ELD)
+    AUDIO_FORMAT_AAC_ADTS_MAIN = 503316481u, // (AAC_ADTS | AAC_SUB_MAIN)
+    AUDIO_FORMAT_AAC_ADTS_LC = 503316482u, // (AAC_ADTS | AAC_SUB_LC)
+    AUDIO_FORMAT_AAC_ADTS_SSR = 503316484u, // (AAC_ADTS | AAC_SUB_SSR)
+    AUDIO_FORMAT_AAC_ADTS_LTP = 503316488u, // (AAC_ADTS | AAC_SUB_LTP)
+    AUDIO_FORMAT_AAC_ADTS_HE_V1 = 503316496u, // (AAC_ADTS | AAC_SUB_HE_V1)
+    AUDIO_FORMAT_AAC_ADTS_SCALABLE = 503316512u, // (AAC_ADTS | AAC_SUB_SCALABLE)
+    AUDIO_FORMAT_AAC_ADTS_ERLC = 503316544u, // (AAC_ADTS | AAC_SUB_ERLC)
+    AUDIO_FORMAT_AAC_ADTS_LD = 503316608u, // (AAC_ADTS | AAC_SUB_LD)
+    AUDIO_FORMAT_AAC_ADTS_HE_V2 = 503316736u, // (AAC_ADTS | AAC_SUB_HE_V2)
+    AUDIO_FORMAT_AAC_ADTS_ELD = 503316992u, // (AAC_ADTS | AAC_SUB_ELD)
+} audio_format_t;
+
+enum {
+    FCC_2 = 2,
+    FCC_8 = 8,
+};
+
+enum {
+    AUDIO_CHANNEL_REPRESENTATION_POSITION = 0u, // 0
+    AUDIO_CHANNEL_REPRESENTATION_INDEX = 2u, // 2
+    AUDIO_CHANNEL_NONE = 0u, // 0x0
+    AUDIO_CHANNEL_INVALID = 3221225472u, // 0xC0000000
+    AUDIO_CHANNEL_OUT_FRONT_LEFT = 1u, // 0x1
+    AUDIO_CHANNEL_OUT_FRONT_RIGHT = 2u, // 0x2
+    AUDIO_CHANNEL_OUT_FRONT_CENTER = 4u, // 0x4
+    AUDIO_CHANNEL_OUT_LOW_FREQUENCY = 8u, // 0x8
+    AUDIO_CHANNEL_OUT_BACK_LEFT = 16u, // 0x10
+    AUDIO_CHANNEL_OUT_BACK_RIGHT = 32u, // 0x20
+    AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 64u, // 0x40
+    AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 128u, // 0x80
+    AUDIO_CHANNEL_OUT_BACK_CENTER = 256u, // 0x100
+    AUDIO_CHANNEL_OUT_SIDE_LEFT = 512u, // 0x200
+    AUDIO_CHANNEL_OUT_SIDE_RIGHT = 1024u, // 0x400
+    AUDIO_CHANNEL_OUT_TOP_CENTER = 2048u, // 0x800
+    AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT = 4096u, // 0x1000
+    AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER = 8192u, // 0x2000
+    AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT = 16384u, // 0x4000
+    AUDIO_CHANNEL_OUT_TOP_BACK_LEFT = 32768u, // 0x8000
+    AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 65536u, // 0x10000
+    AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 131072u, // 0x20000
+    AUDIO_CHANNEL_OUT_MONO = 1u, // OUT_FRONT_LEFT
+    AUDIO_CHANNEL_OUT_STEREO = 3u, // (OUT_FRONT_LEFT | OUT_FRONT_RIGHT)
+    AUDIO_CHANNEL_OUT_2POINT1 = 11u, // ((OUT_FRONT_LEFT | OUT_FRONT_RIGHT) | OUT_LOW_FREQUENCY)
+    AUDIO_CHANNEL_OUT_QUAD = 51u, // (((OUT_FRONT_LEFT | OUT_FRONT_RIGHT) | OUT_BACK_LEFT) | OUT_BACK_RIGHT)
+    AUDIO_CHANNEL_OUT_QUAD_BACK = 51u, // OUT_QUAD
+    AUDIO_CHANNEL_OUT_QUAD_SIDE = 1539u, // (((OUT_FRONT_LEFT | OUT_FRONT_RIGHT) | OUT_SIDE_LEFT) | OUT_SIDE_RIGHT)
+    AUDIO_CHANNEL_OUT_SURROUND = 263u, // (((OUT_FRONT_LEFT | OUT_FRONT_RIGHT) | OUT_FRONT_CENTER) | OUT_BACK_CENTER)
+    AUDIO_CHANNEL_OUT_PENTA = 55u, // (OUT_QUAD | OUT_FRONT_CENTER)
+    AUDIO_CHANNEL_OUT_5POINT1 = 63u, // (((((OUT_FRONT_LEFT | OUT_FRONT_RIGHT) | OUT_FRONT_CENTER) | OUT_LOW_FREQUENCY) | OUT_BACK_LEFT) | OUT_BACK_RIGHT)
+    AUDIO_CHANNEL_OUT_5POINT1_BACK = 63u, // OUT_5POINT1
+    AUDIO_CHANNEL_OUT_5POINT1_SIDE = 1551u, // (((((OUT_FRONT_LEFT | OUT_FRONT_RIGHT) | OUT_FRONT_CENTER) | OUT_LOW_FREQUENCY) | OUT_SIDE_LEFT) | OUT_SIDE_RIGHT)
+    AUDIO_CHANNEL_OUT_6POINT1 = 319u, // ((((((OUT_FRONT_LEFT | OUT_FRONT_RIGHT) | OUT_FRONT_CENTER) | OUT_LOW_FREQUENCY) | OUT_BACK_LEFT) | OUT_BACK_RIGHT) | OUT_BACK_CENTER)
+    AUDIO_CHANNEL_OUT_7POINT1 = 1599u, // (((((((OUT_FRONT_LEFT | OUT_FRONT_RIGHT) | OUT_FRONT_CENTER) | OUT_LOW_FREQUENCY) | OUT_BACK_LEFT) | OUT_BACK_RIGHT) | OUT_SIDE_LEFT) | OUT_SIDE_RIGHT)
+    AUDIO_CHANNEL_OUT_ALL = 262143u, // (((((((((((((((((OUT_FRONT_LEFT | OUT_FRONT_RIGHT) | OUT_FRONT_CENTER) | OUT_LOW_FREQUENCY) | OUT_BACK_LEFT) | OUT_BACK_RIGHT) | OUT_FRONT_LEFT_OF_CENTER) | OUT_FRONT_RIGHT_OF_CENTER) | OUT_BACK_CENTER) | OUT_SIDE_LEFT) | OUT_SIDE_RIGHT) | OUT_TOP_CENTER) | OUT_TOP_FRONT_LEFT) | OUT_TOP_FRONT_CENTER) | OUT_TOP_FRONT_RIGHT) | OUT_TOP_BACK_LEFT) | OUT_TOP_BACK_CENTER) | OUT_TOP_BACK_RIGHT)
+    AUDIO_CHANNEL_IN_LEFT = 4u, // 0x4
+    AUDIO_CHANNEL_IN_RIGHT = 8u, // 0x8
+    AUDIO_CHANNEL_IN_FRONT = 16u, // 0x10
+    AUDIO_CHANNEL_IN_BACK = 32u, // 0x20
+    AUDIO_CHANNEL_IN_LEFT_PROCESSED = 64u, // 0x40
+    AUDIO_CHANNEL_IN_RIGHT_PROCESSED = 128u, // 0x80
+    AUDIO_CHANNEL_IN_FRONT_PROCESSED = 256u, // 0x100
+    AUDIO_CHANNEL_IN_BACK_PROCESSED = 512u, // 0x200
+    AUDIO_CHANNEL_IN_PRESSURE = 1024u, // 0x400
+    AUDIO_CHANNEL_IN_X_AXIS = 2048u, // 0x800
+    AUDIO_CHANNEL_IN_Y_AXIS = 4096u, // 0x1000
+    AUDIO_CHANNEL_IN_Z_AXIS = 8192u, // 0x2000
+    AUDIO_CHANNEL_IN_VOICE_UPLINK = 16384u, // 0x4000
+    AUDIO_CHANNEL_IN_VOICE_DNLINK = 32768u, // 0x8000
+    AUDIO_CHANNEL_IN_MONO = 16u, // IN_FRONT
+    AUDIO_CHANNEL_IN_STEREO = 12u, // (IN_LEFT | IN_RIGHT)
+    AUDIO_CHANNEL_IN_FRONT_BACK = 48u, // (IN_FRONT | IN_BACK)
+    AUDIO_CHANNEL_IN_6 = 252u, // (((((IN_LEFT | IN_RIGHT) | IN_FRONT) | IN_BACK) | IN_LEFT_PROCESSED) | IN_RIGHT_PROCESSED)
+    AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO = 16400u, // (IN_VOICE_UPLINK | IN_MONO)
+    AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO = 32784u, // (IN_VOICE_DNLINK | IN_MONO)
+    AUDIO_CHANNEL_IN_VOICE_CALL_MONO = 49168u, // (IN_VOICE_UPLINK_MONO | IN_VOICE_DNLINK_MONO)
+    AUDIO_CHANNEL_IN_ALL = 65532u, // (((((((((((((IN_LEFT | IN_RIGHT) | IN_FRONT) | IN_BACK) | IN_LEFT_PROCESSED) | IN_RIGHT_PROCESSED) | IN_FRONT_PROCESSED) | IN_BACK_PROCESSED) | IN_PRESSURE) | IN_X_AXIS) | IN_Y_AXIS) | IN_Z_AXIS) | IN_VOICE_UPLINK) | IN_VOICE_DNLINK)
+    AUDIO_CHANNEL_COUNT_MAX = 30u, // 30
+    AUDIO_CHANNEL_INDEX_HDR = 2147483648u, // (REPRESENTATION_INDEX << COUNT_MAX)
+    AUDIO_CHANNEL_INDEX_MASK_1 = 2147483649u, // (INDEX_HDR | ((1 << 1) - 1))
+    AUDIO_CHANNEL_INDEX_MASK_2 = 2147483651u, // (INDEX_HDR | ((1 << 2) - 1))
+    AUDIO_CHANNEL_INDEX_MASK_3 = 2147483655u, // (INDEX_HDR | ((1 << 3) - 1))
+    AUDIO_CHANNEL_INDEX_MASK_4 = 2147483663u, // (INDEX_HDR | ((1 << 4) - 1))
+    AUDIO_CHANNEL_INDEX_MASK_5 = 2147483679u, // (INDEX_HDR | ((1 << 5) - 1))
+    AUDIO_CHANNEL_INDEX_MASK_6 = 2147483711u, // (INDEX_HDR | ((1 << 6) - 1))
+    AUDIO_CHANNEL_INDEX_MASK_7 = 2147483775u, // (INDEX_HDR | ((1 << 7) - 1))
+    AUDIO_CHANNEL_INDEX_MASK_8 = 2147483903u, // (INDEX_HDR | ((1 << 8) - 1))
+};
+
+enum {
+    AUDIO_INTERLEAVE_LEFT = 0,
+    AUDIO_INTERLEAVE_RIGHT = 1,
+};
+
+typedef enum {
+    AUDIO_MODE_INVALID = -2, // (-2)
+    AUDIO_MODE_CURRENT = -1, // (-1)
+    AUDIO_MODE_NORMAL = 0,
+    AUDIO_MODE_RINGTONE = 1,
+    AUDIO_MODE_IN_CALL = 2,
+    AUDIO_MODE_IN_COMMUNICATION = 3,
+    AUDIO_MODE_CNT = 4,
+    AUDIO_MODE_MAX = 3, // (CNT - 1)
+} audio_mode_t;
+
+enum {
+    AUDIO_DEVICE_NONE = 0u, // 0x0
+    AUDIO_DEVICE_BIT_IN = 2147483648u, // 0x80000000
+    AUDIO_DEVICE_BIT_DEFAULT = 1073741824u, // 0x40000000
+    AUDIO_DEVICE_OUT_EARPIECE = 1u, // 0x1
+    AUDIO_DEVICE_OUT_SPEAKER = 2u, // 0x2
+    AUDIO_DEVICE_OUT_WIRED_HEADSET = 4u, // 0x4
+    AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 8u, // 0x8
+    AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 16u, // 0x10
+    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 32u, // 0x20
+    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 64u, // 0x40
+    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 128u, // 0x80
+    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 256u, // 0x100
+    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 512u, // 0x200
+    AUDIO_DEVICE_OUT_AUX_DIGITAL = 1024u, // 0x400
+    AUDIO_DEVICE_OUT_HDMI = 1024u, // OUT_AUX_DIGITAL
+    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 2048u, // 0x800
+    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 4096u, // 0x1000
+    AUDIO_DEVICE_OUT_USB_ACCESSORY = 8192u, // 0x2000
+    AUDIO_DEVICE_OUT_USB_DEVICE = 16384u, // 0x4000
+    AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 32768u, // 0x8000
+    AUDIO_DEVICE_OUT_TELEPHONY_TX = 65536u, // 0x10000
+    AUDIO_DEVICE_OUT_LINE = 131072u, // 0x20000
+    AUDIO_DEVICE_OUT_HDMI_ARC = 262144u, // 0x40000
+    AUDIO_DEVICE_OUT_SPDIF = 524288u, // 0x80000
+    AUDIO_DEVICE_OUT_FM = 1048576u, // 0x100000
+    AUDIO_DEVICE_OUT_AUX_LINE = 2097152u, // 0x200000
+    AUDIO_DEVICE_OUT_SPEAKER_SAFE = 4194304u, // 0x400000
+    AUDIO_DEVICE_OUT_IP = 8388608u, // 0x800000
+    AUDIO_DEVICE_OUT_BUS = 16777216u, // 0x1000000
+    AUDIO_DEVICE_OUT_PROXY = 33554432u, // 0x2000000
+    AUDIO_DEVICE_OUT_USB_HEADSET = 67108864u, // 0x4000000
+    AUDIO_DEVICE_OUT_DEFAULT = 1073741824u, // BIT_DEFAULT
+    AUDIO_DEVICE_OUT_ALL = 1207959551u, // (((((((((((((((((((((((((((OUT_EARPIECE | OUT_SPEAKER) | OUT_WIRED_HEADSET) | OUT_WIRED_HEADPHONE) | OUT_BLUETOOTH_SCO) | OUT_BLUETOOTH_SCO_HEADSET) | OUT_BLUETOOTH_SCO_CARKIT) | OUT_BLUETOOTH_A2DP) | OUT_BLUETOOTH_A2DP_HEADPHONES) | OUT_BLUETOOTH_A2DP_SPEAKER) | OUT_HDMI) | OUT_ANLG_DOCK_HEADSET) | OUT_DGTL_DOCK_HEADSET) | OUT_USB_ACCESSORY) | OUT_USB_DEVICE) | OUT_REMOTE_SUBMIX) | OUT_TELEPHONY_TX) | OUT_LINE) | OUT_HDMI_ARC) | OUT_SPDIF) | OUT_FM) | OUT_AUX_LINE) | OUT_SPEAKER_SAFE) | OUT_IP) | OUT_BUS) | OUT_PROXY) | OUT_USB_HEADSET) | OUT_DEFAULT)
+    AUDIO_DEVICE_OUT_ALL_A2DP = 896u, // ((OUT_BLUETOOTH_A2DP | OUT_BLUETOOTH_A2DP_HEADPHONES) | OUT_BLUETOOTH_A2DP_SPEAKER)
+    AUDIO_DEVICE_OUT_ALL_SCO = 112u, // ((OUT_BLUETOOTH_SCO | OUT_BLUETOOTH_SCO_HEADSET) | OUT_BLUETOOTH_SCO_CARKIT)
+    AUDIO_DEVICE_OUT_ALL_USB = 67133440u, // ((OUT_USB_ACCESSORY | OUT_USB_DEVICE) | OUT_USB_HEADSET)
+    AUDIO_DEVICE_IN_COMMUNICATION = 2147483649u, // (BIT_IN | 0x1)
+    AUDIO_DEVICE_IN_AMBIENT = 2147483650u, // (BIT_IN | 0x2)
+    AUDIO_DEVICE_IN_BUILTIN_MIC = 2147483652u, // (BIT_IN | 0x4)
+    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = 2147483656u, // (BIT_IN | 0x8)
+    AUDIO_DEVICE_IN_WIRED_HEADSET = 2147483664u, // (BIT_IN | 0x10)
+    AUDIO_DEVICE_IN_AUX_DIGITAL = 2147483680u, // (BIT_IN | 0x20)
+    AUDIO_DEVICE_IN_HDMI = 2147483680u, // IN_AUX_DIGITAL
+    AUDIO_DEVICE_IN_VOICE_CALL = 2147483712u, // (BIT_IN | 0x40)
+    AUDIO_DEVICE_IN_TELEPHONY_RX = 2147483712u, // IN_VOICE_CALL
+    AUDIO_DEVICE_IN_BACK_MIC = 2147483776u, // (BIT_IN | 0x80)
+    AUDIO_DEVICE_IN_REMOTE_SUBMIX = 2147483904u, // (BIT_IN | 0x100)
+    AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = 2147484160u, // (BIT_IN | 0x200)
+    AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = 2147484672u, // (BIT_IN | 0x400)
+    AUDIO_DEVICE_IN_USB_ACCESSORY = 2147485696u, // (BIT_IN | 0x800)
+    AUDIO_DEVICE_IN_USB_DEVICE = 2147487744u, // (BIT_IN | 0x1000)
+    AUDIO_DEVICE_IN_FM_TUNER = 2147491840u, // (BIT_IN | 0x2000)
+    AUDIO_DEVICE_IN_TV_TUNER = 2147500032u, // (BIT_IN | 0x4000)
+    AUDIO_DEVICE_IN_LINE = 2147516416u, // (BIT_IN | 0x8000)
+    AUDIO_DEVICE_IN_SPDIF = 2147549184u, // (BIT_IN | 0x10000)
+    AUDIO_DEVICE_IN_BLUETOOTH_A2DP = 2147614720u, // (BIT_IN | 0x20000)
+    AUDIO_DEVICE_IN_LOOPBACK = 2147745792u, // (BIT_IN | 0x40000)
+    AUDIO_DEVICE_IN_IP = 2148007936u, // (BIT_IN | 0x80000)
+    AUDIO_DEVICE_IN_BUS = 2148532224u, // (BIT_IN | 0x100000)
+    AUDIO_DEVICE_IN_PROXY = 2164260864u, // (BIT_IN | 0x1000000)
+    AUDIO_DEVICE_IN_USB_HEADSET = 2181038080u, // (BIT_IN | 0x2000000)
+    AUDIO_DEVICE_IN_DEFAULT = 3221225472u, // (BIT_IN | BIT_DEFAULT)
+    AUDIO_DEVICE_IN_ALL = 3273654271u, // (((((((((((((((((((((((IN_COMMUNICATION | IN_AMBIENT) | IN_BUILTIN_MIC) | IN_BLUETOOTH_SCO_HEADSET) | IN_WIRED_HEADSET) | IN_HDMI) | IN_TELEPHONY_RX) | IN_BACK_MIC) | IN_REMOTE_SUBMIX) | IN_ANLG_DOCK_HEADSET) | IN_DGTL_DOCK_HEADSET) | IN_USB_ACCESSORY) | IN_USB_DEVICE) | IN_FM_TUNER) | IN_TV_TUNER) | IN_LINE) | IN_SPDIF) | IN_BLUETOOTH_A2DP) | IN_LOOPBACK) | IN_IP) | IN_BUS) | IN_PROXY) | IN_USB_HEADSET) | IN_DEFAULT)
+    AUDIO_DEVICE_IN_ALL_SCO = 2147483656u, // IN_BLUETOOTH_SCO_HEADSET
+    AUDIO_DEVICE_IN_ALL_USB = 2181044224u, // ((IN_USB_ACCESSORY | IN_USB_DEVICE) | IN_USB_HEADSET)
+};
+
+typedef enum {
+    AUDIO_OUTPUT_FLAG_NONE = 0, // 0x0
+    AUDIO_OUTPUT_FLAG_DIRECT = 1, // 0x1
+    AUDIO_OUTPUT_FLAG_PRIMARY = 2, // 0x2
+    AUDIO_OUTPUT_FLAG_FAST = 4, // 0x4
+    AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 8, // 0x8
+    AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 16, // 0x10
+    AUDIO_OUTPUT_FLAG_NON_BLOCKING = 32, // 0x20
+    AUDIO_OUTPUT_FLAG_HW_AV_SYNC = 64, // 0x40
+    AUDIO_OUTPUT_FLAG_TTS = 128, // 0x80
+    AUDIO_OUTPUT_FLAG_RAW = 256, // 0x100
+    AUDIO_OUTPUT_FLAG_SYNC = 512, // 0x200
+    AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO = 1024, // 0x400
+    AUDIO_OUTPUT_FLAG_DIRECT_PCM = 8192, // 0x2000
+    AUDIO_OUTPUT_FLAG_MMAP_NOIRQ = 16384, // 0x4000
+    AUDIO_OUTPUT_FLAG_VOIP_RX = 32768, // 0x8000
+} audio_output_flags_t;
+
+typedef enum {
+    AUDIO_INPUT_FLAG_NONE = 0, // 0x0
+    AUDIO_INPUT_FLAG_FAST = 1, // 0x1
+    AUDIO_INPUT_FLAG_HW_HOTWORD = 2, // 0x2
+    AUDIO_INPUT_FLAG_RAW = 4, // 0x4
+    AUDIO_INPUT_FLAG_SYNC = 8, // 0x8
+    AUDIO_INPUT_FLAG_MMAP_NOIRQ = 16, // 0x10
+    AUDIO_INPUT_FLAG_VOIP_TX = 32, // 0x20
+} audio_input_flags_t;
+
+typedef enum {
+    AUDIO_USAGE_UNKNOWN = 0,
+    AUDIO_USAGE_MEDIA = 1,
+    AUDIO_USAGE_VOICE_COMMUNICATION = 2,
+    AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING = 3,
+    AUDIO_USAGE_ALARM = 4,
+    AUDIO_USAGE_NOTIFICATION = 5,
+    AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE = 6,
+    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7,
+    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8,
+    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9,
+    AUDIO_USAGE_NOTIFICATION_EVENT = 10,
+    AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY = 11,
+    AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12,
+    AUDIO_USAGE_ASSISTANCE_SONIFICATION = 13,
+    AUDIO_USAGE_GAME = 14,
+    AUDIO_USAGE_VIRTUAL_SOURCE = 15,
+    AUDIO_USAGE_ASSISTANT = 16,
+    AUDIO_USAGE_CNT = 17,
+    AUDIO_USAGE_MAX = 16, // (CNT - 1)
+} audio_usage_t;
+
+enum {
+    AUDIO_GAIN_MODE_JOINT = 1u, // 0x1
+    AUDIO_GAIN_MODE_CHANNELS = 2u, // 0x2
+    AUDIO_GAIN_MODE_RAMP = 4u, // 0x4
+};
+
+typedef enum {
+    AUDIO_PORT_ROLE_NONE = 0,
+    AUDIO_PORT_ROLE_SOURCE = 1,
+    AUDIO_PORT_ROLE_SINK = 2,
+} audio_port_role_t;
+
+typedef enum {
+    AUDIO_PORT_TYPE_NONE = 0,
+    AUDIO_PORT_TYPE_DEVICE = 1,
+    AUDIO_PORT_TYPE_MIX = 2,
+    AUDIO_PORT_TYPE_SESSION = 3,
+} audio_port_type_t;
+
+enum {
+    AUDIO_PORT_CONFIG_SAMPLE_RATE = 1u, // 0x1
+    AUDIO_PORT_CONFIG_CHANNEL_MASK = 2u, // 0x2
+    AUDIO_PORT_CONFIG_FORMAT = 4u, // 0x4
+    AUDIO_PORT_CONFIG_GAIN = 8u, // 0x8
+    AUDIO_PORT_CONFIG_ALL = 15u, // (((SAMPLE_RATE | CHANNEL_MASK) | FORMAT) | GAIN)
+};
+
+typedef enum {
+    AUDIO_LATENCY_LOW = 0,
+    AUDIO_LATENCY_NORMAL = 1,
+} audio_mix_latency_class_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_COMMON_V2_0_EXPORTED_CONSTANTS_H_
index d7a90ea..e683d60 100644 (file)
 
 #include <cutils/bitops.h>
 
-__BEGIN_DECLS
-
-/* The macro FCC_2 highlights places where there are 2-channel assumptions.
- * This is typically due to legacy implementation of stereo input or output.
- * Search also for "2", "left", "right", "[0]", "[1]", ">> 16", "<< 16", etc.
- * Do not change this value.
- */
-#define FCC_2 2     // FCC_2 = Fixed Channel Count 2
+#include "audio-base.h"
 
-/* The macro FCC_8 highlights places where there are 8-channel assumptions.
- * This is typically due to audio mixer and resampler limitations.
- * Do not change this value without verifying all locations that use it.
- */
-#define FCC_8 8     // FCC_8 = Fixed Channel Count 8
+__BEGIN_DECLS
 
 /* The enums were moved here mostly from
  * frameworks/base/include/media/AudioSystem.h
  */
 
+/* represents an invalid uid for tracks; the calling or client uid is often substituted. */
+#define AUDIO_UID_INVALID ((uid_t)-1)
+
 /* device address used to refer to the standard remote submix */
 #define AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS "0"
 
 /* AudioFlinger and AudioPolicy services use I/O handles to identify audio sources and sinks */
 typedef int audio_io_handle_t;
-#define AUDIO_IO_HANDLE_NONE    0
-
-/* Audio stream types */
-typedef enum {
-    /* These values must kept in sync with
-     * frameworks/base/media/java/android/media/AudioSystem.java
-     */
-    AUDIO_STREAM_DEFAULT          = -1,
-    AUDIO_STREAM_MIN              = 0,
-    AUDIO_STREAM_VOICE_CALL       = 0,
-    AUDIO_STREAM_SYSTEM           = 1,
-    AUDIO_STREAM_RING             = 2,
-    AUDIO_STREAM_MUSIC            = 3,
-    AUDIO_STREAM_ALARM            = 4,
-    AUDIO_STREAM_NOTIFICATION     = 5,
-    AUDIO_STREAM_BLUETOOTH_SCO    = 6,
-    AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user
-                                        * and must be routed to speaker
-                                        */
-    AUDIO_STREAM_DTMF             = 8,
-    AUDIO_STREAM_TTS              = 9,  /* Transmitted Through Speaker.
-                                         * Plays over speaker only, silent on other devices.
-                                         */
-    AUDIO_STREAM_ACCESSIBILITY    = 10, /* For accessibility talk back prompts */
-    AUDIO_STREAM_REROUTING        = 11, /* For dynamic policy output mixes */
-    AUDIO_STREAM_PATCH            = 12, /* For internal audio flinger tracks. Fixed volume */
-    AUDIO_STREAM_PUBLIC_CNT       = AUDIO_STREAM_TTS + 1,
-    AUDIO_STREAM_FOR_POLICY_CNT   = AUDIO_STREAM_PATCH, /* number of streams considered by
-                                           audio policy for volume and routing */
-    AUDIO_STREAM_CNT              = AUDIO_STREAM_PATCH + 1,
-} audio_stream_type_t;
 
 /* Do not change these values without updating their counterparts
  * in frameworks/base/media/java/android/media/AudioAttributes.java
@@ -96,37 +57,13 @@ typedef enum {
     AUDIO_CONTENT_TYPE_MAX          = AUDIO_CONTENT_TYPE_CNT - 1,
 } audio_content_type_t;
 
-/* Do not change these values without updating their counterparts
- * in frameworks/base/media/java/android/media/AudioAttributes.java
- */
-typedef enum {
-    AUDIO_USAGE_UNKNOWN                            = 0,
-    AUDIO_USAGE_MEDIA                              = 1,
-    AUDIO_USAGE_VOICE_COMMUNICATION                = 2,
-    AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING     = 3,
-    AUDIO_USAGE_ALARM                              = 4,
-    AUDIO_USAGE_NOTIFICATION                       = 5,
-    AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE    = 6,
-    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7,
-    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8,
-    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9,
-    AUDIO_USAGE_NOTIFICATION_EVENT                 = 10,
-    AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY           = 11,
-    AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE     = 12,
-    AUDIO_USAGE_ASSISTANCE_SONIFICATION            = 13,
-    AUDIO_USAGE_GAME                               = 14,
-    AUDIO_USAGE_VIRTUAL_SOURCE                     = 15,
-
-    AUDIO_USAGE_CNT,
-    AUDIO_USAGE_MAX                                = AUDIO_USAGE_CNT - 1,
-} audio_usage_t;
-
 typedef uint32_t audio_flags_mask_t;
 
 /* Do not change these values without updating their counterparts
  * in frameworks/base/media/java/android/media/AudioAttributes.java
  */
 enum {
+    AUDIO_FLAG_NONE                       = 0x0,
     AUDIO_FLAG_AUDIBILITY_ENFORCED        = 0x1,
     AUDIO_FLAG_SECURE                     = 0x2,
     AUDIO_FLAG_SCO                        = 0x4,
@@ -136,39 +73,9 @@ enum {
     AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY = 0x40,
     AUDIO_FLAG_BYPASS_MUTE                = 0x80,
     AUDIO_FLAG_LOW_LATENCY                = 0x100,
+    AUDIO_FLAG_DEEP_BUFFER                = 0x200,
 };
 
-/* Do not change these values without updating their counterparts
- * in frameworks/base/media/java/android/media/MediaRecorder.java,
- * frameworks/av/services/audiopolicy/AudioPolicyService.cpp,
- * and system/media/audio_effects/include/audio_effects/audio_effects_conf.h!
- */
-typedef enum {
-    AUDIO_SOURCE_DEFAULT             = 0,
-    AUDIO_SOURCE_MIC                 = 1,
-    AUDIO_SOURCE_VOICE_UPLINK        = 2,
-    AUDIO_SOURCE_VOICE_DOWNLINK      = 3,
-    AUDIO_SOURCE_VOICE_CALL          = 4,
-    AUDIO_SOURCE_CAMCORDER           = 5,
-    AUDIO_SOURCE_VOICE_RECOGNITION   = 6,
-    AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
-    AUDIO_SOURCE_REMOTE_SUBMIX       = 8, /* Source for the mix to be presented remotely.      */
-                                          /* An example of remote presentation is Wifi Display */
-                                          /*  where a dongle attached to a TV can be used to   */
-                                          /*  play the mix captured by this audio source.      */
-    AUDIO_SOURCE_UNPROCESSED         = 9, /* Source for unprocessed sound.
-                                             Usage examples include level measurement and raw
-                                             signal analysis. */
-    AUDIO_SOURCE_CNT,
-    AUDIO_SOURCE_MAX                 = AUDIO_SOURCE_CNT - 1,
-    AUDIO_SOURCE_FM_TUNER            = 1998,
-    AUDIO_SOURCE_HOTWORD             = 1999, /* A low-priority, preemptible audio source for
-                                                for background software hotword detection.
-                                                Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION.
-                                                Used only internally to the framework. Not exposed
-                                                at the audio HAL. */
-} audio_source_t;
-
 /* Audio attributes */
 #define AUDIO_ATTRIBUTES_TAGS_MAX_SIZE 256
 typedef struct {
@@ -179,36 +86,6 @@ typedef struct {
     char                 tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE]; /* UTF8 */
 } audio_attributes_t;
 
-/* special audio session values
- * do not need to have audio_unique_id_get_use(session) == AUDIO_UNIQUE_ID_USE_SESSION
- * (XXX: should this be living in the audio effects land?)
- */
-typedef enum {
-    /* session for effects attached to a particular output stream
-     * (value must be less than 0)
-     */
-    AUDIO_SESSION_OUTPUT_STAGE = -1,
-
-    /* session for effects applied to output mix. These effects can
-     * be moved by audio policy manager to another output stream
-     * (value must be 0)
-     */
-    AUDIO_SESSION_OUTPUT_MIX = 0,
-
-    /* application does not specify an explicit session ID to be used,
-     * and requests a new session ID to be allocated
-     * TODO use unique values for AUDIO_SESSION_OUTPUT_MIX and AUDIO_SESSION_ALLOCATE,
-     * after all uses have been updated from 0 to the appropriate symbol, and have been tested.
-     * Corresponds to AudioManager.AUDIO_SESSION_ID_GENERATE and AudioSystem.AUDIO_SESSION_ALLOCATE.
-     */
-    AUDIO_SESSION_ALLOCATE = 0,
-
-    /* For use with AudioRecord::start(), this indicates no trigger session.
-     * It is also used with output tracks and patch tracks, which never have a session.
-     */
-    AUDIO_SESSION_NONE = 0,
-} audio_session_t;
-
 /* a unique ID allocated by AudioFlinger for use as an audio_io_handle_t, audio_session_t,
  * effect ID (int), audio_module_handle_t, and audio_patch_handle_t.
  * Audio port IDs (audio_port_handle_t) are allocated by AudioPolicy
@@ -225,7 +102,7 @@ typedef enum {
     AUDIO_UNIQUE_ID_USE_PATCH = 4,
     AUDIO_UNIQUE_ID_USE_OUTPUT = 5,
     AUDIO_UNIQUE_ID_USE_INPUT = 6,
-    // 7 is available
+    AUDIO_UNIQUE_ID_USE_PLAYER = 7,
     AUDIO_UNIQUE_ID_USE_MAX = 8,  // must be a power-of-two
     AUDIO_UNIQUE_ID_USE_MASK = AUDIO_UNIQUE_ID_USE_MAX - 1
 } audio_unique_id_use_t;
@@ -239,253 +116,6 @@ static inline audio_unique_id_use_t audio_unique_id_get_use(audio_unique_id_t id
 /* Reserved audio_unique_id_t values.  FIXME: not a complete list. */
 #define AUDIO_UNIQUE_ID_ALLOCATE AUDIO_SESSION_ALLOCATE
 
-/* Audio sub formats (see enum audio_format). */
-
-/* PCM sub formats */
-typedef enum {
-    /* All of these are in native byte order */
-    AUDIO_FORMAT_PCM_SUB_16_BIT          = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */
-    AUDIO_FORMAT_PCM_SUB_8_BIT           = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */
-    AUDIO_FORMAT_PCM_SUB_32_BIT          = 0x3, /* PCM signed .31 fixed point */
-    AUDIO_FORMAT_PCM_SUB_8_24_BIT        = 0x4, /* PCM signed 8.23 fixed point */
-    AUDIO_FORMAT_PCM_SUB_FLOAT           = 0x5, /* PCM single-precision floating point */
-    AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED   = 0x6, /* PCM signed .23 fixed point packed in 3 bytes */
-} audio_format_pcm_sub_fmt_t;
-
-/* The audio_format_*_sub_fmt_t declarations are not currently used */
-
-/* MP3 sub format field definition : can use 11 LSBs in the same way as MP3
- * frame header to specify bit rate, stereo mode, version...
- */
-typedef enum {
-    AUDIO_FORMAT_MP3_SUB_NONE            = 0x0,
-} audio_format_mp3_sub_fmt_t;
-
-/* AMR NB/WB sub format field definition: specify frame block interleaving,
- * bandwidth efficient or octet aligned, encoding mode for recording...
- */
-typedef enum {
-    AUDIO_FORMAT_AMR_SUB_NONE            = 0x0,
-} audio_format_amr_sub_fmt_t;
-
-/* AAC sub format field definition: specify profile or bitrate for recording... */
-typedef enum {
-    AUDIO_FORMAT_AAC_SUB_MAIN            = 0x1,
-    AUDIO_FORMAT_AAC_SUB_LC              = 0x2,
-    AUDIO_FORMAT_AAC_SUB_SSR             = 0x4,
-    AUDIO_FORMAT_AAC_SUB_LTP             = 0x8,
-    AUDIO_FORMAT_AAC_SUB_HE_V1           = 0x10,
-    AUDIO_FORMAT_AAC_SUB_SCALABLE        = 0x20,
-    AUDIO_FORMAT_AAC_SUB_ERLC            = 0x40,
-    AUDIO_FORMAT_AAC_SUB_LD              = 0x80,
-    AUDIO_FORMAT_AAC_SUB_HE_V2           = 0x100,
-    AUDIO_FORMAT_AAC_SUB_ELD             = 0x200,
-} audio_format_aac_sub_fmt_t;
-
-/* VORBIS sub format field definition: specify quality for recording... */
-typedef enum {
-    AUDIO_FORMAT_VORBIS_SUB_NONE         = 0x0,
-} audio_format_vorbis_sub_fmt_t;
-
-
-/* Audio format  is a 32-bit word that consists of:
- *   main format field (upper 8 bits)
- *   sub format field (lower 24 bits).
- *
- * The main format indicates the main codec type. The sub format field
- * indicates options and parameters for each format. The sub format is mainly
- * used for record to indicate for instance the requested bitrate or profile.
- * It can also be used for certain formats to give informations not present in
- * the encoded audio stream (e.g. octet alignement for AMR).
- */
-typedef enum {
-    AUDIO_FORMAT_INVALID             = 0xFFFFFFFFUL,
-    AUDIO_FORMAT_DEFAULT             = 0,
-    AUDIO_FORMAT_PCM                 = 0x00000000UL, /* DO NOT CHANGE */
-    AUDIO_FORMAT_MP3                 = 0x01000000UL,
-    AUDIO_FORMAT_AMR_NB              = 0x02000000UL,
-    AUDIO_FORMAT_AMR_WB              = 0x03000000UL,
-    AUDIO_FORMAT_AAC                 = 0x04000000UL,
-    AUDIO_FORMAT_HE_AAC_V1           = 0x05000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V1*/
-    AUDIO_FORMAT_HE_AAC_V2           = 0x06000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V2*/
-    AUDIO_FORMAT_VORBIS              = 0x07000000UL,
-    AUDIO_FORMAT_OPUS                = 0x08000000UL,
-    AUDIO_FORMAT_AC3                 = 0x09000000UL,
-    AUDIO_FORMAT_E_AC3               = 0x0A000000UL,
-    AUDIO_FORMAT_DTS                 = 0x0B000000UL,
-    AUDIO_FORMAT_DTS_HD              = 0x0C000000UL,
-    // IEC61937 is encoded audio wrapped in 16-bit PCM.
-    AUDIO_FORMAT_IEC61937            = 0x0D000000UL,
-    AUDIO_FORMAT_DOLBY_TRUEHD        = 0x0E000000UL,
-    AUDIO_FORMAT_MAIN_MASK           = 0xFF000000UL, /* Deprecated. Use audio_get_main_format() */
-    AUDIO_FORMAT_SUB_MASK            = 0x00FFFFFFUL,
-
-    /* Aliases */
-    /* note != AudioFormat.ENCODING_PCM_16BIT */
-    AUDIO_FORMAT_PCM_16_BIT          = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_16_BIT),
-    /* note != AudioFormat.ENCODING_PCM_8BIT */
-    AUDIO_FORMAT_PCM_8_BIT           = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_8_BIT),
-    AUDIO_FORMAT_PCM_32_BIT          = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_32_BIT),
-    AUDIO_FORMAT_PCM_8_24_BIT        = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_8_24_BIT),
-    AUDIO_FORMAT_PCM_FLOAT           = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_FLOAT),
-    AUDIO_FORMAT_PCM_24_BIT_PACKED   = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED),
-    AUDIO_FORMAT_AAC_MAIN            = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_MAIN),
-    AUDIO_FORMAT_AAC_LC              = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_LC),
-    AUDIO_FORMAT_AAC_SSR             = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_SSR),
-    AUDIO_FORMAT_AAC_LTP             = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_LTP),
-    AUDIO_FORMAT_AAC_HE_V1           = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_HE_V1),
-    AUDIO_FORMAT_AAC_SCALABLE        = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_SCALABLE),
-    AUDIO_FORMAT_AAC_ERLC            = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_ERLC),
-    AUDIO_FORMAT_AAC_LD              = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_LD),
-    AUDIO_FORMAT_AAC_HE_V2           = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_HE_V2),
-    AUDIO_FORMAT_AAC_ELD             = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_ELD),
-} audio_format_t;
-
-/* For the channel mask for position assignment representation */
-enum {
-
-/* These can be a complete audio_channel_mask_t. */
-
-    AUDIO_CHANNEL_NONE                      = 0x0,
-    AUDIO_CHANNEL_INVALID                   = 0xC0000000,
-
-/* These can be the bits portion of an audio_channel_mask_t
- * with representation AUDIO_CHANNEL_REPRESENTATION_POSITION.
- * Using these bits as a complete audio_channel_mask_t is deprecated.
- */
-
-    /* output channels */
-    AUDIO_CHANNEL_OUT_FRONT_LEFT            = 0x1,
-    AUDIO_CHANNEL_OUT_FRONT_RIGHT           = 0x2,
-    AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4,
-    AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8,
-    AUDIO_CHANNEL_OUT_BACK_LEFT             = 0x10,
-    AUDIO_CHANNEL_OUT_BACK_RIGHT            = 0x20,
-    AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER  = 0x40,
-    AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80,
-    AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100,
-    AUDIO_CHANNEL_OUT_SIDE_LEFT             = 0x200,
-    AUDIO_CHANNEL_OUT_SIDE_RIGHT            = 0x400,
-    AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800,
-    AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT        = 0x1000,
-    AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000,
-    AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT       = 0x4000,
-    AUDIO_CHANNEL_OUT_TOP_BACK_LEFT         = 0x8000,
-    AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000,
-    AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT        = 0x20000,
-
-/* TODO: should these be considered complete channel masks, or only bits? */
-
-    AUDIO_CHANNEL_OUT_MONO     = AUDIO_CHANNEL_OUT_FRONT_LEFT,
-    AUDIO_CHANNEL_OUT_STEREO   = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT),
-    AUDIO_CHANNEL_OUT_QUAD     = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
-                                  AUDIO_CHANNEL_OUT_BACK_RIGHT),
-    AUDIO_CHANNEL_OUT_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD,
-    /* like AUDIO_CHANNEL_OUT_QUAD_BACK with *_SIDE_* instead of *_BACK_* */
-    AUDIO_CHANNEL_OUT_QUAD_SIDE = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_SIDE_LEFT |
-                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT),
-    AUDIO_CHANNEL_OUT_5POINT1  = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
-                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
-                                  AUDIO_CHANNEL_OUT_BACK_RIGHT),
-    AUDIO_CHANNEL_OUT_5POINT1_BACK = AUDIO_CHANNEL_OUT_5POINT1,
-    /* like AUDIO_CHANNEL_OUT_5POINT1_BACK with *_SIDE_* instead of *_BACK_* */
-    AUDIO_CHANNEL_OUT_5POINT1_SIDE = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
-                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                                  AUDIO_CHANNEL_OUT_SIDE_LEFT |
-                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT),
-    // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1
-    AUDIO_CHANNEL_OUT_7POINT1  = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
-                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
-                                  AUDIO_CHANNEL_OUT_BACK_RIGHT |
-                                  AUDIO_CHANNEL_OUT_SIDE_LEFT |
-                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT),
-    AUDIO_CHANNEL_OUT_ALL      = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
-                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
-                                  AUDIO_CHANNEL_OUT_BACK_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER |
-                                  AUDIO_CHANNEL_OUT_BACK_CENTER|
-                                  AUDIO_CHANNEL_OUT_SIDE_LEFT|
-                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT|
-                                  AUDIO_CHANNEL_OUT_TOP_CENTER|
-                                  AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT|
-                                  AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER|
-                                  AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT|
-                                  AUDIO_CHANNEL_OUT_TOP_BACK_LEFT|
-                                  AUDIO_CHANNEL_OUT_TOP_BACK_CENTER|
-                                  AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
-
-/* These are bits only, not complete values */
-
-    /* input channels */
-    AUDIO_CHANNEL_IN_LEFT            = 0x4,
-    AUDIO_CHANNEL_IN_RIGHT           = 0x8,
-    AUDIO_CHANNEL_IN_FRONT           = 0x10,
-    AUDIO_CHANNEL_IN_BACK            = 0x20,
-    AUDIO_CHANNEL_IN_LEFT_PROCESSED  = 0x40,
-    AUDIO_CHANNEL_IN_RIGHT_PROCESSED = 0x80,
-    AUDIO_CHANNEL_IN_FRONT_PROCESSED = 0x100,
-    AUDIO_CHANNEL_IN_BACK_PROCESSED  = 0x200,
-    AUDIO_CHANNEL_IN_PRESSURE        = 0x400,
-    AUDIO_CHANNEL_IN_X_AXIS          = 0x800,
-    AUDIO_CHANNEL_IN_Y_AXIS          = 0x1000,
-    AUDIO_CHANNEL_IN_Z_AXIS          = 0x2000,
-    AUDIO_CHANNEL_IN_VOICE_UPLINK    = 0x4000,
-    AUDIO_CHANNEL_IN_VOICE_DNLINK    = 0x8000,
-
-/* TODO: should these be considered complete channel masks, or only bits, or deprecated? */
-
-    AUDIO_CHANNEL_IN_MONO   = AUDIO_CHANNEL_IN_FRONT,
-    AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT),
-    AUDIO_CHANNEL_IN_FRONT_BACK = (AUDIO_CHANNEL_IN_FRONT | AUDIO_CHANNEL_IN_BACK),
-    AUDIO_CHANNEL_IN_ALL    = (AUDIO_CHANNEL_IN_LEFT |
-                               AUDIO_CHANNEL_IN_RIGHT |
-                               AUDIO_CHANNEL_IN_FRONT |
-                               AUDIO_CHANNEL_IN_BACK|
-                               AUDIO_CHANNEL_IN_LEFT_PROCESSED |
-                               AUDIO_CHANNEL_IN_RIGHT_PROCESSED |
-                               AUDIO_CHANNEL_IN_FRONT_PROCESSED |
-                               AUDIO_CHANNEL_IN_BACK_PROCESSED|
-                               AUDIO_CHANNEL_IN_PRESSURE |
-                               AUDIO_CHANNEL_IN_X_AXIS |
-                               AUDIO_CHANNEL_IN_Y_AXIS |
-                               AUDIO_CHANNEL_IN_Z_AXIS |
-                               AUDIO_CHANNEL_IN_VOICE_UPLINK |
-                               AUDIO_CHANNEL_IN_VOICE_DNLINK),
-};
-
 /* A channel mask per se only defines the presence or absence of a channel, not the order.
  * But see AUDIO_INTERLEAVE_* below for the platform convention of order.
  *
@@ -519,42 +149,17 @@ enum {
  */
 typedef uint32_t audio_channel_mask_t;
 
-/* Maximum number of channels for all representations */
-#define AUDIO_CHANNEL_COUNT_MAX             30
-
 /* log(2) of maximum number of representations, not part of public API */
 #define AUDIO_CHANNEL_REPRESENTATION_LOG2   2
 
-/* Representations */
-typedef enum {
-    AUDIO_CHANNEL_REPRESENTATION_POSITION    = 0,    // must be zero for compatibility
-    // 1 is reserved for future use
-    AUDIO_CHANNEL_REPRESENTATION_INDEX       = 2,
-    // 3 is reserved for future use
-} audio_channel_representation_t;
-
-/* The channel index masks defined here are the canonical masks for 1 to 8 channel
- * endpoints and apply to both source and sink.
- */
-enum {
-    AUDIO_CHANNEL_INDEX_HDR  = AUDIO_CHANNEL_REPRESENTATION_INDEX << AUDIO_CHANNEL_COUNT_MAX,
-    AUDIO_CHANNEL_INDEX_MASK_1 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 1) - 1),
-    AUDIO_CHANNEL_INDEX_MASK_2 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 2) - 1),
-    AUDIO_CHANNEL_INDEX_MASK_3 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 3) - 1),
-    AUDIO_CHANNEL_INDEX_MASK_4 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 4) - 1),
-    AUDIO_CHANNEL_INDEX_MASK_5 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 5) - 1),
-    AUDIO_CHANNEL_INDEX_MASK_6 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 6) - 1),
-    AUDIO_CHANNEL_INDEX_MASK_7 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 7) - 1),
-    AUDIO_CHANNEL_INDEX_MASK_8 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 8) - 1),
-    // FIXME FCC_8
-};
-
 /* The return value is undefined if the channel mask is invalid. */
 static inline uint32_t audio_channel_mask_get_bits(audio_channel_mask_t channel)
 {
     return channel & ((1 << AUDIO_CHANNEL_COUNT_MAX) - 1);
 }
 
+typedef uint32_t audio_channel_representation_t;
+
 /* The return value is undefined if the channel mask is invalid. */
 static inline audio_channel_representation_t audio_channel_mask_get_representation(
         audio_channel_mask_t channel)
@@ -593,32 +198,6 @@ static inline audio_channel_mask_t audio_channel_mask_from_representation_and_bi
     return (audio_channel_mask_t) ((representation << AUDIO_CHANNEL_COUNT_MAX) | bits);
 }
 
-/* Expresses the convention when stereo audio samples are stored interleaved
- * in an array.  This should improve readability by allowing code to use
- * symbolic indices instead of hard-coded [0] and [1].
- *
- * For multi-channel beyond stereo, the platform convention is that channels
- * are interleaved in order from least significant channel mask bit
- * to most significant channel mask bit, with unused bits skipped.
- * Any exceptions to this convention will be noted at the appropriate API.
- */
-enum {
-    AUDIO_INTERLEAVE_LEFT   = 0,
-    AUDIO_INTERLEAVE_RIGHT  = 1,
-};
-
-typedef enum {
-    AUDIO_MODE_INVALID          = -2,
-    AUDIO_MODE_CURRENT          = -1,
-    AUDIO_MODE_NORMAL           = 0,
-    AUDIO_MODE_RINGTONE         = 1,
-    AUDIO_MODE_IN_CALL          = 2,
-    AUDIO_MODE_IN_COMMUNICATION = 3,
-
-    AUDIO_MODE_CNT,
-    AUDIO_MODE_MAX              = AUDIO_MODE_CNT - 1,
-} audio_mode_t;
-
 /* This enum is deprecated */
 typedef enum {
     AUDIO_IN_ACOUSTICS_NONE          = 0,
@@ -630,193 +209,17 @@ typedef enum {
     AUDIO_IN_ACOUSTICS_TX_DISABLE    = 0,
 } audio_in_acoustics_t;
 
-enum {
-    AUDIO_DEVICE_NONE                          = 0x0,
-    /* reserved bits */
-    AUDIO_DEVICE_BIT_IN                        = 0x80000000,
-    AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000,
-    /* output devices */
-    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,
-    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,
-    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,
-    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,
-    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10,
-    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20,
-    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT      = 0x40,
-    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP            = 0x80,
-    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
-    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER    = 0x200,
-    AUDIO_DEVICE_OUT_AUX_DIGITAL               = 0x400,
-    AUDIO_DEVICE_OUT_HDMI                      = AUDIO_DEVICE_OUT_AUX_DIGITAL,
-    /* uses an analog connection (multiplexed over the USB connector pins for instance) */
-    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET         = 0x800,
-    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET         = 0x1000,
-    /* USB accessory mode: your Android device is a USB device and the dock is a USB host */
-    AUDIO_DEVICE_OUT_USB_ACCESSORY             = 0x2000,
-    /* USB host mode: your Android device is a USB host and the dock is a USB device */
-    AUDIO_DEVICE_OUT_USB_DEVICE                = 0x4000,
-    AUDIO_DEVICE_OUT_REMOTE_SUBMIX             = 0x8000,
-    /* Telephony voice TX path */
-    AUDIO_DEVICE_OUT_TELEPHONY_TX              = 0x10000,
-    /* Analog jack with line impedance detected */
-    AUDIO_DEVICE_OUT_LINE                      = 0x20000,
-    /* HDMI Audio Return Channel */
-    AUDIO_DEVICE_OUT_HDMI_ARC                  = 0x40000,
-    /* S/PDIF out */
-    AUDIO_DEVICE_OUT_SPDIF                     = 0x80000,
-    /* FM transmitter out */
-    AUDIO_DEVICE_OUT_FM                        = 0x100000,
-    /* Line out for av devices */
-    AUDIO_DEVICE_OUT_AUX_LINE                  = 0x200000,
-    /* limited-output speaker device for acoustic safety */
-    AUDIO_DEVICE_OUT_SPEAKER_SAFE              = 0x400000,
-    AUDIO_DEVICE_OUT_IP                        = 0x800000,
-    /* audio bus implemented by the audio system (e.g an MOST stereo channel) */
-    AUDIO_DEVICE_OUT_BUS                       = 0x1000000,
-    AUDIO_DEVICE_OUT_DEFAULT                   = AUDIO_DEVICE_BIT_DEFAULT,
-    AUDIO_DEVICE_OUT_ALL      = (AUDIO_DEVICE_OUT_EARPIECE |
-                                 AUDIO_DEVICE_OUT_SPEAKER |
-                                 AUDIO_DEVICE_OUT_WIRED_HEADSET |
-                                 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
-                                 AUDIO_DEVICE_OUT_HDMI |
-                                 AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
-                                 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
-                                 AUDIO_DEVICE_OUT_USB_ACCESSORY |
-                                 AUDIO_DEVICE_OUT_USB_DEVICE |
-                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
-                                 AUDIO_DEVICE_OUT_TELEPHONY_TX |
-                                 AUDIO_DEVICE_OUT_LINE |
-                                 AUDIO_DEVICE_OUT_HDMI_ARC |
-                                 AUDIO_DEVICE_OUT_SPDIF |
-                                 AUDIO_DEVICE_OUT_FM |
-                                 AUDIO_DEVICE_OUT_AUX_LINE |
-                                 AUDIO_DEVICE_OUT_SPEAKER_SAFE |
-                                 AUDIO_DEVICE_OUT_IP |
-                                 AUDIO_DEVICE_OUT_BUS |
-                                 AUDIO_DEVICE_OUT_DEFAULT),
-    AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-    AUDIO_DEVICE_OUT_ALL_SCO  = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
-    AUDIO_DEVICE_OUT_ALL_USB  = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
-                                 AUDIO_DEVICE_OUT_USB_DEVICE),
-    /* input devices */
-    AUDIO_DEVICE_IN_COMMUNICATION         = AUDIO_DEVICE_BIT_IN | 0x1,
-    AUDIO_DEVICE_IN_AMBIENT               = AUDIO_DEVICE_BIT_IN | 0x2,
-    AUDIO_DEVICE_IN_BUILTIN_MIC           = AUDIO_DEVICE_BIT_IN | 0x4,
-    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,
-    AUDIO_DEVICE_IN_WIRED_HEADSET         = AUDIO_DEVICE_BIT_IN | 0x10,
-    AUDIO_DEVICE_IN_AUX_DIGITAL           = AUDIO_DEVICE_BIT_IN | 0x20,
-    AUDIO_DEVICE_IN_HDMI                  = AUDIO_DEVICE_IN_AUX_DIGITAL,
-    /* Telephony voice RX path */
-    AUDIO_DEVICE_IN_VOICE_CALL            = AUDIO_DEVICE_BIT_IN | 0x40,
-    AUDIO_DEVICE_IN_TELEPHONY_RX          = AUDIO_DEVICE_IN_VOICE_CALL,
-    AUDIO_DEVICE_IN_BACK_MIC              = AUDIO_DEVICE_BIT_IN | 0x80,
-    AUDIO_DEVICE_IN_REMOTE_SUBMIX         = AUDIO_DEVICE_BIT_IN | 0x100,
-    AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x200,
-    AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x400,
-    AUDIO_DEVICE_IN_USB_ACCESSORY         = AUDIO_DEVICE_BIT_IN | 0x800,
-    AUDIO_DEVICE_IN_USB_DEVICE            = AUDIO_DEVICE_BIT_IN | 0x1000,
-    /* FM tuner input */
-    AUDIO_DEVICE_IN_FM_TUNER              = AUDIO_DEVICE_BIT_IN | 0x2000,
-    /* TV tuner input */
-    AUDIO_DEVICE_IN_TV_TUNER              = AUDIO_DEVICE_BIT_IN | 0x4000,
-    /* Analog jack with line impedance detected */
-    AUDIO_DEVICE_IN_LINE                  = AUDIO_DEVICE_BIT_IN | 0x8000,
-    /* S/PDIF in */
-    AUDIO_DEVICE_IN_SPDIF                 = AUDIO_DEVICE_BIT_IN | 0x10000,
-    AUDIO_DEVICE_IN_BLUETOOTH_A2DP        = AUDIO_DEVICE_BIT_IN | 0x20000,
-    AUDIO_DEVICE_IN_LOOPBACK              = AUDIO_DEVICE_BIT_IN | 0x40000,
-    AUDIO_DEVICE_IN_IP                    = AUDIO_DEVICE_BIT_IN | 0x80000,
-    /* audio bus implemented by the audio system (e.g an MOST stereo channel) */
-    AUDIO_DEVICE_IN_BUS                   = AUDIO_DEVICE_BIT_IN | 0x100000,
-    AUDIO_DEVICE_IN_DEFAULT               = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
-
-    AUDIO_DEVICE_IN_ALL     = (AUDIO_DEVICE_IN_COMMUNICATION |
-                               AUDIO_DEVICE_IN_AMBIENT |
-                               AUDIO_DEVICE_IN_BUILTIN_MIC |
-                               AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
-                               AUDIO_DEVICE_IN_WIRED_HEADSET |
-                               AUDIO_DEVICE_IN_HDMI |
-                               AUDIO_DEVICE_IN_TELEPHONY_RX |
-                               AUDIO_DEVICE_IN_BACK_MIC |
-                               AUDIO_DEVICE_IN_REMOTE_SUBMIX |
-                               AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
-                               AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
-                               AUDIO_DEVICE_IN_USB_ACCESSORY |
-                               AUDIO_DEVICE_IN_USB_DEVICE |
-                               AUDIO_DEVICE_IN_FM_TUNER |
-                               AUDIO_DEVICE_IN_TV_TUNER |
-                               AUDIO_DEVICE_IN_LINE |
-                               AUDIO_DEVICE_IN_SPDIF |
-                               AUDIO_DEVICE_IN_BLUETOOTH_A2DP |
-                               AUDIO_DEVICE_IN_LOOPBACK |
-                               AUDIO_DEVICE_IN_IP |
-                               AUDIO_DEVICE_IN_BUS |
-                               AUDIO_DEVICE_IN_DEFAULT),
-    AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
-    AUDIO_DEVICE_IN_ALL_USB  = (AUDIO_DEVICE_IN_USB_ACCESSORY |
-                                AUDIO_DEVICE_IN_USB_DEVICE),
-};
-
 typedef uint32_t audio_devices_t;
-
-/* the audio output flags serve two purposes:
- * - when an AudioTrack is created they indicate a "wish" to be connected to an
- * output stream with attributes corresponding to the specified flags
- * - when present in an output profile descriptor listed for a particular audio
- * hardware module, they indicate that an output stream can be opened that
- * supports the attributes indicated by the flags.
- * the audio policy manager will try to match the flags in the request
- * (when getOuput() is called) to an available output stream.
+/**
+ * Stub audio output device. Used in policy configuration file on platforms without audio outputs.
+ * This alias value to AUDIO_DEVICE_OUT_DEFAULT is only used in the audio policy context.
  */
-typedef enum {
-    AUDIO_OUTPUT_FLAG_NONE = 0x0,       // no attributes
-    AUDIO_OUTPUT_FLAG_DIRECT = 0x1,     // this output directly connects a track
-                                        // to one output stream: no software mixer
-    AUDIO_OUTPUT_FLAG_PRIMARY = 0x2,    // this output is the primary output of
-                                        // the device. It is unique and must be
-                                        // present. It is opened by default and
-                                        // receives routing, audio mode and volume
-                                        // controls related to voice calls.
-    AUDIO_OUTPUT_FLAG_FAST = 0x4,       // output supports "fast tracks",
-                                        // defined elsewhere
-    AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8, // use deep audio buffers
-    AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10,  // offload playback of compressed
-                                                // streams to hardware codec
-    AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20, // use non-blocking write
-    AUDIO_OUTPUT_FLAG_HW_AV_SYNC = 0x40,   // output uses a hardware A/V synchronization source
-    AUDIO_OUTPUT_FLAG_TTS = 0x80,          // output for streams transmitted through speaker
-                                           // at a sample rate high enough to accommodate
-                                           // lower-range ultrasonic playback
-    AUDIO_OUTPUT_FLAG_RAW = 0x100,         // minimize signal processing
-    AUDIO_OUTPUT_FLAG_SYNC = 0x200,        // synchronize I/O streams
-
-    AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO = 0x400, // Audio stream contains compressed audio in
-                                               // SPDIF data bursts, not PCM.
-} audio_output_flags_t;
-
-/* The audio input flags are analogous to audio output flags.
- * Currently they are used only when an AudioRecord is created,
- * to indicate a preference to be connected to an input stream with
- * attributes corresponding to the specified flags.
+#define AUDIO_DEVICE_OUT_STUB AUDIO_DEVICE_OUT_DEFAULT
+/**
+ * Stub audio input device. Used in policy configuration file on platforms without audio inputs.
+ * This alias value to AUDIO_DEVICE_IN_DEFAULT is only used in the audio policy context.
  */
-typedef enum {
-    AUDIO_INPUT_FLAG_NONE       = 0x0,  // no attributes
-    AUDIO_INPUT_FLAG_FAST       = 0x1,  // prefer an input that supports "fast tracks"
-    AUDIO_INPUT_FLAG_HW_HOTWORD = 0x2,  // prefer an input that captures from hw hotword source
-    AUDIO_INPUT_FLAG_RAW        = 0x4,  // minimize signal processing
-    AUDIO_INPUT_FLAG_SYNC       = 0x8,  // synchronize I/O streams
-
-} audio_input_flags_t;
+#define AUDIO_DEVICE_IN_STUB AUDIO_DEVICE_IN_DEFAULT
 
 /* Additional information about compressed streams offloaded to
  * hardware playback
@@ -834,6 +237,9 @@ typedef struct {
     int64_t duration_us;                // duration in microseconds, -1 if unknown
     bool has_video;                     // true if stream is tied to a video stream
     bool is_streaming;                  // true if streaming, false if local playback
+    uint32_t bit_width;
+    uint32_t offload_buffer_size;       // offload fragment size
+    audio_usage_t usage;
 } audio_offload_info_t;
 
 #define AUDIO_MAKE_OFFLOAD_INFO_VERSION(maj,min) \
@@ -852,7 +258,10 @@ static const audio_offload_info_t AUDIO_INFO_INITIALIZER = {
     /* .bit_rate = */ 0,
     /* .duration_us = */ 0,
     /* .has_video = */ false,
-    /* .is_streaming = */ false
+    /* .is_streaming = */ false,
+    /* .bit_width = */ 16,
+    /* .offload_buffer_size = */ 0,
+    /* .usage = */ AUDIO_USAGE_UNKNOWN
 };
 
 /* common audio stream configuration parameters
@@ -882,7 +291,10 @@ static const audio_config_t AUDIO_CONFIG_INITIALIZER = {
         /* .bit_rate = */ 0,
         /* .duration_us = */ 0,
         /* .has_video = */ false,
-        /* .is_streaming = */ false
+        /* .is_streaming = */ false,
+        /* .bit_width = */ 16,
+        /* .offload_buffer_size = */ 0,
+        /* .usage = */ AUDIO_USAGE_UNKNOWN
     },
     /* .frame_count = */ 0,
 };
@@ -902,9 +314,7 @@ static const audio_config_base_t AUDIO_CONFIG_BASE_INITIALIZER = {
 };
 
 /* audio hw module handle functions or structures referencing a module */
-typedef enum {
-    AUDIO_MODULE_HANDLE_NONE = 0,
-} audio_module_handle_t;
+typedef int audio_module_handle_t;
 
 /******************************
  *  Volume control
@@ -915,11 +325,6 @@ typedef enum {
  * will then implement gain control functions that will use the following data
  * structures. */
 
-/* Type of gain control exposed by an audio port */
-#define AUDIO_GAIN_MODE_JOINT     0x1 /* supports joint channel gain control */
-#define AUDIO_GAIN_MODE_CHANNELS  0x2 /* supports separate channel gain control */
-#define AUDIO_GAIN_MODE_RAMP      0x4 /* supports gain ramps */
-
 typedef uint32_t audio_gain_mode_t;
 
 
@@ -964,26 +369,8 @@ struct audio_gain_config  {
  * audio end point at the edge of the system managed by the module exposing
  * the interface. */
 
-/* Audio port role: either source or sink */
-typedef enum {
-    AUDIO_PORT_ROLE_NONE,
-    AUDIO_PORT_ROLE_SOURCE,
-    AUDIO_PORT_ROLE_SINK,
-} audio_port_role_t;
-
-/* Audio port type indicates if it is a session (e.g AudioTrack),
- * a mix (e.g PlaybackThread output) or a physical device
- * (e.g AUDIO_DEVICE_OUT_SPEAKER) */
-typedef enum {
-    AUDIO_PORT_TYPE_NONE,
-    AUDIO_PORT_TYPE_DEVICE,
-    AUDIO_PORT_TYPE_MIX,
-    AUDIO_PORT_TYPE_SESSION,
-} audio_port_type_t;
-
 /* Each port has a unique ID or handle allocated by policy manager */
 typedef int audio_port_handle_t;
-#define AUDIO_PORT_HANDLE_NONE 0
 
 /* the maximum length for the human-readable device name */
 #define AUDIO_PORT_MAX_NAME_LEN 128
@@ -1017,16 +404,6 @@ struct audio_port_config_session_ext {
     audio_session_t   session; /* audio session */
 };
 
-/* Flags indicating which fields are to be considered in struct audio_port_config */
-#define AUDIO_PORT_CONFIG_SAMPLE_RATE  0x1
-#define AUDIO_PORT_CONFIG_CHANNEL_MASK 0x2
-#define AUDIO_PORT_CONFIG_FORMAT       0x4
-#define AUDIO_PORT_CONFIG_GAIN         0x8
-#define AUDIO_PORT_CONFIG_ALL (AUDIO_PORT_CONFIG_SAMPLE_RATE | \
-                               AUDIO_PORT_CONFIG_CHANNEL_MASK | \
-                               AUDIO_PORT_CONFIG_FORMAT | \
-                               AUDIO_PORT_CONFIG_GAIN)
-
 /* audio port configuration structure used to specify a particular configuration of
  * an audio port */
 struct audio_port_config {
@@ -1047,11 +424,11 @@ struct audio_port_config {
 
 
 /* max number of sampling rates in audio port */
-#define AUDIO_PORT_MAX_SAMPLING_RATES 16
+#define AUDIO_PORT_MAX_SAMPLING_RATES 32
 /* max number of channel masks in audio port */
-#define AUDIO_PORT_MAX_CHANNEL_MASKS 16
+#define AUDIO_PORT_MAX_CHANNEL_MASKS 32
 /* max number of audio formats in audio port */
-#define AUDIO_PORT_MAX_FORMATS 16
+#define AUDIO_PORT_MAX_FORMATS 32
 /* max number of gain controls in audio port */
 #define AUDIO_PORT_MAX_GAINS 16
 
@@ -1062,12 +439,6 @@ struct audio_port_device_ext {
     char                  address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
 };
 
-/* Latency class of the audio mix */
-typedef enum {
-    AUDIO_LATENCY_LOW,
-    AUDIO_LATENCY_NORMAL,
-} audio_mix_latency_class_t;
-
 /* extension for audio port structure when the audio port is a sub mix */
 struct audio_port_mix_ext {
     audio_module_handle_t     hw_module;     /* module the stream is attached to */
@@ -1111,9 +482,7 @@ struct audio_port {
  * But the same patch receives another system wide unique handle allocated by the framework.
  * This unique handle is used for all transactions inside the framework.
  */
-typedef enum {
-    AUDIO_PATCH_HANDLE_NONE = 0,
-} audio_patch_handle_t;
+typedef int audio_patch_handle_t;
 
 #define AUDIO_PATCH_PORTS_MAX   16
 
@@ -1133,6 +502,28 @@ typedef uint32_t audio_hw_sync_t;
 /* an invalid HW synchronization source indicating an error */
 #define AUDIO_HW_SYNC_INVALID 0
 
+/**
+ * Mmap buffer descriptor returned by audio_stream->create_mmap_buffer().
+ * note\ Used by streams opened in mmap mode.
+ */
+struct audio_mmap_buffer_info {
+    void*   shared_memory_address;  /**< base address of mmap memory buffer.
+                                         For use by local process only */
+    int32_t shared_memory_fd;       /**< FD for mmap memory buffer */
+    int32_t buffer_size_frames;     /**< total buffer size in frames */
+    int32_t burst_size_frames;      /**< transfer size granularity in frames */
+};
+
+/**
+ * Mmap buffer read/write position returned by audio_stream->get_mmap_position().
+ * note\ Used by streams opened in mmap mode.
+ */
+struct audio_mmap_position {
+    int64_t  time_nanoseconds; /**< timestamp in ns, CLOCK_MONOTONIC */
+    int32_t  position_frames;  /**< increasing 32 bit frame count reset when stream->stop()
+                                    is called */
+};
+
 static inline bool audio_is_output_device(audio_devices_t device)
 {
     if (((device & AUDIO_DEVICE_BIT_IN) == 0) &&
@@ -1434,6 +825,7 @@ static inline bool audio_is_valid_format(audio_format_t format)
     case AUDIO_FORMAT_AMR_NB:
     case AUDIO_FORMAT_AMR_WB:
     case AUDIO_FORMAT_AAC:
+    case AUDIO_FORMAT_AAC_ADTS:
     case AUDIO_FORMAT_HE_AAC_V1:
     case AUDIO_FORMAT_HE_AAC_V2:
     case AUDIO_FORMAT_VORBIS:
@@ -1444,6 +836,22 @@ static inline bool audio_is_valid_format(audio_format_t format)
     case AUDIO_FORMAT_DTS_HD:
     case AUDIO_FORMAT_IEC61937:
     case AUDIO_FORMAT_DOLBY_TRUEHD:
+    case AUDIO_FORMAT_QCELP:
+    case AUDIO_FORMAT_EVRC:
+    case AUDIO_FORMAT_EVRCB:
+    case AUDIO_FORMAT_EVRCWB:
+    case AUDIO_FORMAT_AAC_ADIF:
+    case AUDIO_FORMAT_AMR_WB_PLUS:
+    case AUDIO_FORMAT_MP2:
+    case AUDIO_FORMAT_EVRCNW:
+    case AUDIO_FORMAT_FLAC:
+    case AUDIO_FORMAT_ALAC:
+    case AUDIO_FORMAT_APE:
+    case AUDIO_FORMAT_WMA:
+    case AUDIO_FORMAT_WMA_PRO:
+    case AUDIO_FORMAT_DSD:
+    case AUDIO_FORMAT_AC4:
+    case AUDIO_FORMAT_LDAC:
         return true;
     default:
         return false;
@@ -1546,6 +954,108 @@ static inline bool audio_device_is_digital(audio_devices_t device) {
     }
 }
 
+// Unique effect ID (can be generated from the following site:
+//  http://www.itu.int/ITU-T/asn1/uuid.html)
+// This struct is used for effects identification and in soundtrigger.
+typedef struct audio_uuid_s {
+    uint32_t timeLow;
+    uint16_t timeMid;
+    uint16_t timeHiAndVersion;
+    uint16_t clockSeq;
+    uint8_t node[6];
+} audio_uuid_t;
+
 __END_DECLS
 
+/**
+ * List of known audio HAL modules. This is the base name of the audio HAL
+ * library composed of the "audio." prefix, one of the base names below and
+ * a suffix specific to the device.
+ * e.g: audio.primary.goldfish.so or audio.a2dp.default.so
+ *
+ * The same module names are used in audio policy configuration files.
+ */
+
+#define AUDIO_HARDWARE_MODULE_ID_PRIMARY "primary"
+#define AUDIO_HARDWARE_MODULE_ID_A2DP "a2dp"
+#define AUDIO_HARDWARE_MODULE_ID_USB "usb"
+#define AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX "r_submix"
+#define AUDIO_HARDWARE_MODULE_ID_CODEC_OFFLOAD "codec_offload"
+#define AUDIO_HARDWARE_MODULE_ID_STUB "stub"
+
+/**
+ * Parameter definitions.
+ * Note that in the framework code it's recommended to use AudioParameter.h
+ * instead of these preprocessor defines, and for sure avoid just copying
+ * the constant values.
+ */
+
+#define AUDIO_PARAMETER_VALUE_ON "on"
+#define AUDIO_PARAMETER_VALUE_OFF "off"
+
+/**
+ *  audio device parameters
+ */
+
+/* BT SCO Noise Reduction + Echo Cancellation parameters */
+#define AUDIO_PARAMETER_KEY_BT_NREC "bt_headset_nrec"
+
+/* Get a new HW synchronization source identifier.
+ * Return a valid source (positive integer) or AUDIO_HW_SYNC_INVALID if an error occurs
+ * or no HW sync is available. */
+#define AUDIO_PARAMETER_HW_AV_SYNC "hw_av_sync"
+
+/* Screen state */
+#define AUDIO_PARAMETER_KEY_SCREEN_STATE "screen_state"
+
+/**
+ *  audio stream parameters
+ */
+
+#define AUDIO_PARAMETER_STREAM_ROUTING "routing"             /* audio_devices_t */
+#define AUDIO_PARAMETER_STREAM_FORMAT "format"               /* audio_format_t */
+#define AUDIO_PARAMETER_STREAM_CHANNELS "channels"           /* audio_channel_mask_t */
+#define AUDIO_PARAMETER_STREAM_FRAME_COUNT "frame_count"     /* size_t */
+#define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source"   /* audio_source_t */
+#define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" /* uint32_t */
+
+#define AUDIO_PARAMETER_DEVICE_CONNECT "connect"            /* audio_devices_t */
+#define AUDIO_PARAMETER_DEVICE_DISCONNECT "disconnect"      /* audio_devices_t */
+
+/* Enable mono audio playback if 1, else should be 0. */
+#define AUDIO_PARAMETER_MONO_OUTPUT "mono_output"
+
+/* Set the HW synchronization source for an output stream. */
+#define AUDIO_PARAMETER_STREAM_HW_AV_SYNC "hw_av_sync"
+
+/* Query supported formats. The response is a '|' separated list of strings from
+ * audio_format_t enum e.g: "sup_formats=AUDIO_FORMAT_PCM_16_BIT" */
+#define AUDIO_PARAMETER_STREAM_SUP_FORMATS "sup_formats"
+/* Query supported channel masks. The response is a '|' separated list of strings from
+ * audio_channel_mask_t enum e.g: "sup_channels=AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_MONO" */
+#define AUDIO_PARAMETER_STREAM_SUP_CHANNELS "sup_channels"
+/* Query supported sampling rates. The response is a '|' separated list of integer values e.g:
+ * "sup_sampling_rates=44100|48000" */
+#define AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES "sup_sampling_rates"
+
+#define AUDIO_PARAMETER_VALUE_LIST_SEPARATOR "|"
+
+/**
+ * audio codec parameters
+ */
+
+#define AUDIO_OFFLOAD_CODEC_PARAMS "music_offload_codec_param"
+#define AUDIO_OFFLOAD_CODEC_BIT_PER_SAMPLE "music_offload_bit_per_sample"
+#define AUDIO_OFFLOAD_CODEC_BIT_RATE "music_offload_bit_rate"
+#define AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE "music_offload_avg_bit_rate"
+#define AUDIO_OFFLOAD_CODEC_ID "music_offload_codec_id"
+#define AUDIO_OFFLOAD_CODEC_BLOCK_ALIGN "music_offload_block_align"
+#define AUDIO_OFFLOAD_CODEC_SAMPLE_RATE "music_offload_sample_rate"
+#define AUDIO_OFFLOAD_CODEC_ENCODE_OPTION "music_offload_encode_option"
+#define AUDIO_OFFLOAD_CODEC_NUM_CHANNEL  "music_offload_num_channels"
+#define AUDIO_OFFLOAD_CODEC_DOWN_SAMPLING  "music_offload_down_sampling"
+#define AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES  "delay_samples"
+#define AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES  "padding_samples"
+
+
 #endif  // ANDROID_AUDIO_CORE_H
diff --git a/audio/include/system/audio_effect-base.h b/audio/include/system/audio_effect-base.h
new file mode 100644 (file)
index 0000000..572b788
--- /dev/null
@@ -0,0 +1,100 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+// Source: android.hardware.audio.effect@2.0
+// Root: android.hardware:hardware/interfaces
+
+#ifndef HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EXPORTED_CONSTANTS_H_
+#define HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EXPORTED_CONSTANTS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    EFFECT_FLAG_TYPE_SHIFT = 0,
+    EFFECT_FLAG_TYPE_SIZE = 3,
+    EFFECT_FLAG_TYPE_MASK = 7, // (((1 << TYPE_SIZE) - 1) << TYPE_SHIFT)
+    EFFECT_FLAG_TYPE_INSERT = 0, // (0 << TYPE_SHIFT)
+    EFFECT_FLAG_TYPE_AUXILIARY = 1, // (1 << TYPE_SHIFT)
+    EFFECT_FLAG_TYPE_REPLACE = 2, // (2 << TYPE_SHIFT)
+    EFFECT_FLAG_TYPE_PRE_PROC = 3, // (3 << TYPE_SHIFT)
+    EFFECT_FLAG_TYPE_POST_PROC = 4, // (4 << TYPE_SHIFT)
+    EFFECT_FLAG_INSERT_SHIFT = 3, // (TYPE_SHIFT + TYPE_SIZE)
+    EFFECT_FLAG_INSERT_SIZE = 3,
+    EFFECT_FLAG_INSERT_MASK = 56, // (((1 << INSERT_SIZE) - 1) << INSERT_SHIFT)
+    EFFECT_FLAG_INSERT_ANY = 0, // (0 << INSERT_SHIFT)
+    EFFECT_FLAG_INSERT_FIRST = 8, // (1 << INSERT_SHIFT)
+    EFFECT_FLAG_INSERT_LAST = 16, // (2 << INSERT_SHIFT)
+    EFFECT_FLAG_INSERT_EXCLUSIVE = 24, // (3 << INSERT_SHIFT)
+    EFFECT_FLAG_VOLUME_SHIFT = 6, // (INSERT_SHIFT + INSERT_SIZE)
+    EFFECT_FLAG_VOLUME_SIZE = 3,
+    EFFECT_FLAG_VOLUME_MASK = 448, // (((1 << VOLUME_SIZE) - 1) << VOLUME_SHIFT)
+    EFFECT_FLAG_VOLUME_CTRL = 64, // (1 << VOLUME_SHIFT)
+    EFFECT_FLAG_VOLUME_IND = 128, // (2 << VOLUME_SHIFT)
+    EFFECT_FLAG_VOLUME_NONE = 0, // (0 << VOLUME_SHIFT)
+    EFFECT_FLAG_DEVICE_SHIFT = 9, // (VOLUME_SHIFT + VOLUME_SIZE)
+    EFFECT_FLAG_DEVICE_SIZE = 3,
+    EFFECT_FLAG_DEVICE_MASK = 3584, // (((1 << DEVICE_SIZE) - 1) << DEVICE_SHIFT)
+    EFFECT_FLAG_DEVICE_IND = 512, // (1 << DEVICE_SHIFT)
+    EFFECT_FLAG_DEVICE_NONE = 0, // (0 << DEVICE_SHIFT)
+    EFFECT_FLAG_INPUT_SHIFT = 12, // (DEVICE_SHIFT + DEVICE_SIZE)
+    EFFECT_FLAG_INPUT_SIZE = 2,
+    EFFECT_FLAG_INPUT_MASK = 12288, // (((1 << INPUT_SIZE) - 1) << INPUT_SHIFT)
+    EFFECT_FLAG_INPUT_DIRECT = 4096, // (1 << INPUT_SHIFT)
+    EFFECT_FLAG_INPUT_PROVIDER = 8192, // (2 << INPUT_SHIFT)
+    EFFECT_FLAG_INPUT_BOTH = 12288, // (3 << INPUT_SHIFT)
+    EFFECT_FLAG_OUTPUT_SHIFT = 14, // (INPUT_SHIFT + INPUT_SIZE)
+    EFFECT_FLAG_OUTPUT_SIZE = 2,
+    EFFECT_FLAG_OUTPUT_MASK = 49152, // (((1 << OUTPUT_SIZE) - 1) << OUTPUT_SHIFT)
+    EFFECT_FLAG_OUTPUT_DIRECT = 16384, // (1 << OUTPUT_SHIFT)
+    EFFECT_FLAG_OUTPUT_PROVIDER = 32768, // (2 << OUTPUT_SHIFT)
+    EFFECT_FLAG_OUTPUT_BOTH = 49152, // (3 << OUTPUT_SHIFT)
+    EFFECT_FLAG_HW_ACC_SHIFT = 16, // (OUTPUT_SHIFT + OUTPUT_SIZE)
+    EFFECT_FLAG_HW_ACC_SIZE = 2,
+    EFFECT_FLAG_HW_ACC_MASK = 196608, // (((1 << HW_ACC_SIZE) - 1) << HW_ACC_SHIFT)
+    EFFECT_FLAG_HW_ACC_SIMPLE = 65536, // (1 << HW_ACC_SHIFT)
+    EFFECT_FLAG_HW_ACC_TUNNEL = 131072, // (2 << HW_ACC_SHIFT)
+    EFFECT_FLAG_AUDIO_MODE_SHIFT = 18, // (HW_ACC_SHIFT + HW_ACC_SIZE)
+    EFFECT_FLAG_AUDIO_MODE_SIZE = 2,
+    EFFECT_FLAG_AUDIO_MODE_MASK = 786432, // (((1 << AUDIO_MODE_SIZE) - 1) << AUDIO_MODE_SHIFT)
+    EFFECT_FLAG_AUDIO_MODE_IND = 262144, // (1 << AUDIO_MODE_SHIFT)
+    EFFECT_FLAG_AUDIO_MODE_NONE = 0, // (0 << AUDIO_MODE_SHIFT)
+    EFFECT_FLAG_AUDIO_SOURCE_SHIFT = 20, // (AUDIO_MODE_SHIFT + AUDIO_MODE_SIZE)
+    EFFECT_FLAG_AUDIO_SOURCE_SIZE = 2,
+    EFFECT_FLAG_AUDIO_SOURCE_MASK = 3145728, // (((1 << AUDIO_SOURCE_SIZE) - 1) << AUDIO_SOURCE_SHIFT)
+    EFFECT_FLAG_AUDIO_SOURCE_IND = 1048576, // (1 << AUDIO_SOURCE_SHIFT)
+    EFFECT_FLAG_AUDIO_SOURCE_NONE = 0, // (0 << AUDIO_SOURCE_SHIFT)
+    EFFECT_FLAG_OFFLOAD_SHIFT = 22, // (AUDIO_SOURCE_SHIFT + AUDIO_SOURCE_SIZE)
+    EFFECT_FLAG_OFFLOAD_SIZE = 1,
+    EFFECT_FLAG_OFFLOAD_MASK = 4194304, // (((1 << OFFLOAD_SIZE) - 1) << OFFLOAD_SHIFT)
+    EFFECT_FLAG_OFFLOAD_SUPPORTED = 4194304, // (1 << OFFLOAD_SHIFT)
+    EFFECT_FLAG_NO_PROCESS_SHIFT = 23, // (OFFLOAD_SHIFT + OFFLOAD_SIZE)
+    EFFECT_FLAG_NO_PROCESS_SIZE = 1,
+    EFFECT_FLAG_NO_PROCESS_MASK = 8388608, // (((1 << NO_PROCESS_SIZE) - 1) << NO_PROCESS_SHIFT)
+    EFFECT_FLAG_NO_PROCESS = 8388608, // (1 << NO_PROCESS_SHIFT)
+};
+
+typedef enum {
+    EFFECT_BUFFER_ACCESS_WRITE = 0,
+    EFFECT_BUFFER_ACCESS_READ = 1,
+    EFFECT_BUFFER_ACCESS_ACCUMULATE = 2,
+} effect_buffer_access_e;
+
+enum {
+    EFFECT_CONFIG_BUFFER = 1, // 0x0001
+    EFFECT_CONFIG_SMP_RATE = 2, // 0x0002
+    EFFECT_CONFIG_CHANNELS = 4, // 0x0004
+    EFFECT_CONFIG_FORMAT = 8, // 0x0008
+    EFFECT_CONFIG_ACC_MODE = 16, // 0x0010
+    EFFECT_CONFIG_ALL = 31, // ((((BUFFER | SMP_RATE) | CHANNELS) | FORMAT) | ACC_MODE)
+};
+
+typedef enum {
+    EFFECT_FEATURE_AUX_CHANNELS = 0,
+    EFFECT_FEATURE_CNT = 1,
+} effect_feature_e;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EXPORTED_CONSTANTS_H_
diff --git a/audio/include/system/audio_effect.h b/audio/include/system/audio_effect.h
new file mode 100644 (file)
index 0000000..d7bb1a9
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_AUDIO_EFFECT_CORE_H
+#define ANDROID_AUDIO_EFFECT_CORE_H
+
+#include "audio.h"
+#include "audio_effect-base.h"
+
+__BEGIN_DECLS
+
+/////////////////////////////////////////////////
+//      Common Definitions
+/////////////////////////////////////////////////
+
+//
+//--- Effect descriptor structure effect_descriptor_t
+//
+
+// This format is used for both "type" and "uuid" fields of the effect descriptor structure.
+// - When used for effect type and the engine is implementing and effect corresponding to a standard
+// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface.
+// - When used as uuid, it should be a unique UUID for this particular implementation.
+typedef audio_uuid_t effect_uuid_t;
+
+// Maximum length of character strings in structures defines by this API.
+#define EFFECT_STRING_LEN_MAX 64
+
+// NULL UUID definition (matches SL_IID_NULL_)
+#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \
+                                  { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } }
+static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER;
+static const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_;
+static const char * const EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210";
+
+// The effect descriptor contains necessary information to facilitate the enumeration of the effect
+// engines present in a library.
+typedef struct effect_descriptor_s {
+    effect_uuid_t type;     // UUID of to the OpenSL ES interface implemented by this effect
+    effect_uuid_t uuid;     // UUID for this particular implementation
+    uint32_t apiVersion;    // Version of the effect control API implemented
+    uint32_t flags;         // effect engine capabilities/requirements flags (see below)
+    uint16_t cpuLoad;       // CPU load indication (see below)
+    uint16_t memoryUsage;   // Data Memory usage (see below)
+    char    name[EFFECT_STRING_LEN_MAX];   // human readable effect name
+    char    implementor[EFFECT_STRING_LEN_MAX];    // human readable effect implementor name
+} effect_descriptor_t;
+
+/////////////////////////////////////////////////
+//      Effect control interface
+/////////////////////////////////////////////////
+
+//
+//--- Standardized command codes for command() function
+//
+enum effect_command_e {
+   EFFECT_CMD_INIT,                 // initialize effect engine
+   EFFECT_CMD_SET_CONFIG,           // configure effect engine (see effect_config_t)
+   EFFECT_CMD_RESET,                // reset effect engine
+   EFFECT_CMD_ENABLE,               // enable effect process
+   EFFECT_CMD_DISABLE,              // disable effect process
+   EFFECT_CMD_SET_PARAM,            // set parameter immediately (see effect_param_t)
+   EFFECT_CMD_SET_PARAM_DEFERRED,   // set parameter deferred
+   EFFECT_CMD_SET_PARAM_COMMIT,     // commit previous set parameter deferred
+   EFFECT_CMD_GET_PARAM,            // get parameter
+   EFFECT_CMD_SET_DEVICE,           // set audio device (see audio.h, audio_devices_t)
+   EFFECT_CMD_SET_VOLUME,           // set volume
+   EFFECT_CMD_SET_AUDIO_MODE,       // set the audio mode (normal, ring, ...)
+   EFFECT_CMD_SET_CONFIG_REVERSE,   // configure effect engine reverse stream(see effect_config_t)
+   EFFECT_CMD_SET_INPUT_DEVICE,     // set capture device (see audio.h, audio_devices_t)
+   EFFECT_CMD_GET_CONFIG,           // read effect engine configuration
+   EFFECT_CMD_GET_CONFIG_REVERSE,   // read configure effect engine reverse stream configuration
+   EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,// get all supported configurations for a feature.
+   EFFECT_CMD_GET_FEATURE_CONFIG,   // get current feature configuration
+   EFFECT_CMD_SET_FEATURE_CONFIG,   // set current feature configuration
+   EFFECT_CMD_SET_AUDIO_SOURCE,     // set the audio source (see audio.h, audio_source_t)
+   EFFECT_CMD_OFFLOAD,              // set if effect thread is an offload one,
+                                    // send the ioHandle of the effect thread
+   EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
+};
+
+//==================================================================================================
+// command: EFFECT_CMD_INIT
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Initialize effect engine: All configurations return to default
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_SET_CONFIG
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Apply new audio parameters configurations for input and output buffers
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_config_t)
+//  data: effect_config_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_RESET
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Reset the effect engine. Keep configuration but resets state and buffer content
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_ENABLE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Enable the process. Called by the framework before the first call to process()
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_DISABLE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Disable the process. Called by the framework after the last call to process()
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_SET_PARAM
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set a parameter and apply it immediately
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_param_t) + size of param and value
+//  data: effect_param_t + param + value. See effect_param_t definition below for value offset
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_SET_PARAM_DEFERRED
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set a parameter but apply it only when receiving EFFECT_CMD_SET_PARAM_COMMIT command
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_param_t) + size of param and value
+//  data: effect_param_t + param + value. See effect_param_t definition below for value offset
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_SET_PARAM_COMMIT
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Apply all previously received EFFECT_CMD_SET_PARAM_DEFERRED commands
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_GET_PARAM
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Get a parameter value
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_param_t) + size of param
+//  data: effect_param_t + param
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(effect_param_t) + size of param and value
+//  data: effect_param_t + param + value. See effect_param_t definition below for value offset
+//==================================================================================================
+// command: EFFECT_CMD_SET_DEVICE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set the rendering device the audio output path is connected to. See audio.h, audio_devices_t
+//  for device values.
+//  The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this
+//  command when the device changes
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(uint32_t)
+//  data: uint32_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_SET_VOLUME
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set and get volume. Used by audio framework to delegate volume control to effect engine.
+//  The effect implementation must set EFFECT_FLAG_VOLUME_IND or EFFECT_FLAG_VOLUME_CTRL flag in
+//  its descriptor to receive this command before every call to process() function
+//  If EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must return
+//  the volume that should be applied before the effect is processed. The overall volume (the volume
+//  actually applied by the effect engine multiplied by the returned value) should match the value
+//  indicated in the command.
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: n * sizeof(uint32_t)
+//  data: volume for each channel defined in effect_config_t for output buffer expressed in
+//      8.24 fixed point format
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: n * sizeof(uint32_t) / 0
+//  data: - if EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor:
+//              volume for each channel defined in effect_config_t for output buffer expressed in
+//              8.24 fixed point format
+//        - if EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor:
+//              N/A
+//  It is legal to receive a null pointer as pReplyData in which case the effect framework has
+//  delegated volume control to another effect
+//==================================================================================================
+// command: EFFECT_CMD_SET_AUDIO_MODE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set the audio mode. The effect implementation must set EFFECT_FLAG_AUDIO_MODE_IND flag in its
+//  descriptor to receive this command when the audio mode changes.
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(uint32_t)
+//  data: audio_mode_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_SET_CONFIG_REVERSE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Apply new audio parameters configurations for input and output buffers of reverse stream.
+//  An example of reverse stream is the echo reference supplied to an Acoustic Echo Canceler.
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_config_t)
+//  data: effect_config_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_SET_INPUT_DEVICE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set the capture device the audio input path is connected to. See audio.h, audio_devices_t
+//  for device values.
+//  The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this
+//  command when the device changes
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(uint32_t)
+//  data: uint32_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_GET_CONFIG
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Read audio parameters configurations for input and output buffers
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(effect_config_t)
+//  data: effect_config_t
+//==================================================================================================
+// command: EFFECT_CMD_GET_CONFIG_REVERSE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Read audio parameters configurations for input and output buffers of reverse stream
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(effect_config_t)
+//  data: effect_config_t
+//==================================================================================================
+// command: EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Queries for supported configurations for a particular feature (e.g. get the supported
+// combinations of main and auxiliary channels for a noise suppressor).
+// The command parameter is the feature identifier (See effect_feature_e for a list of defined
+// features) followed by the maximum number of configuration descriptor to return.
+// The reply is composed of:
+//  - status (uint32_t):
+//          - 0 if feature is supported
+//          - -ENOSYS if the feature is not supported,
+//          - -ENOMEM if the feature is supported but the total number of supported configurations
+//          exceeds the maximum number indicated by the caller.
+//  - total number of supported configurations (uint32_t)
+//  - an array of configuration descriptors.
+// The actual number of descriptors returned must not exceed the maximum number indicated by
+// the caller.
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 2 x sizeof(uint32_t)
+//  data: effect_feature_e + maximum number of configurations to return
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 2 x sizeof(uint32_t) + n x sizeof (<config descriptor>)
+//  data: status + total number of configurations supported + array of n config descriptors
+//==================================================================================================
+// command: EFFECT_CMD_GET_FEATURE_CONFIG
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Retrieves current configuration for a given feature.
+// The reply status is:
+//      - 0 if feature is supported
+//      - -ENOSYS if the feature is not supported,
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(uint32_t)
+//  data: effect_feature_e
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(uint32_t) + sizeof (<config descriptor>)
+//  data: status + config descriptor
+//==================================================================================================
+// command: EFFECT_CMD_SET_FEATURE_CONFIG
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Sets current configuration for a given feature.
+// The reply status is:
+//      - 0 if feature is supported
+//      - -ENOSYS if the feature is not supported,
+//      - -EINVAL if the configuration is invalid
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(uint32_t) + sizeof (<config descriptor>)
+//  data: effect_feature_e + config descriptor
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(uint32_t)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_SET_AUDIO_SOURCE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set the audio source the capture path is configured for (Camcorder, voice recognition...).
+//  See audio.h, audio_source_t for values.
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(uint32_t)
+//  data: uint32_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_OFFLOAD
+//--------------------------------------------------------------------------------------------------
+// description:
+//  1.indicate if the playback thread the effect is attached to is offloaded or not
+//  2.update the io handle of the playback thread the effect is attached to
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_offload_param_t)
+//  data: effect_offload_param_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(uint32_t)
+//  data: uint32_t
+//--------------------------------------------------------------------------------------------------
+// command: EFFECT_CMD_FIRST_PROPRIETARY
+//--------------------------------------------------------------------------------------------------
+// description:
+//  All proprietary effect commands must use command codes above this value. The size and format of
+//  command and response fields is free in this case
+//==================================================================================================
+
+// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t
+// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with
+// regard to the channel mask definition in audio.h, audio_channel_mask_t e.g :
+// Stereo: left, right
+// 5 point 1: front left, front right, front center, low frequency, back left, back right
+// The buffer size is expressed in frame count, a frame being composed of samples for all
+// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by
+// definition
+typedef struct audio_buffer_s {
+    size_t   frameCount;        // number of frames in buffer
+    union {
+        void*       raw;        // raw pointer to start of buffer
+        int32_t*    s32;        // pointer to signed 32 bit data at start of buffer
+        int16_t*    s16;        // pointer to signed 16 bit data at start of buffer
+        uint8_t*    u8;         // pointer to unsigned 8 bit data at start of buffer
+    };
+} audio_buffer_t;
+
+// The buffer_provider_s structure contains functions that can be used
+// by the effect engine process() function to query and release input
+// or output audio buffer.
+// The getBuffer() function is called to retrieve a buffer where data
+// should read from or written to by process() function.
+// The releaseBuffer() function MUST be called when the buffer retrieved
+// with getBuffer() is not needed anymore.
+// The process function should use the buffer provider mechanism to retrieve
+// input or output buffer if the inBuffer or outBuffer passed as argument is NULL
+// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_SET_CONFIG
+// command did not specify an audio buffer.
+
+typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer);
+
+typedef struct buffer_provider_s {
+    buffer_function_t getBuffer;       // retrieve next buffer
+    buffer_function_t releaseBuffer;   // release used buffer
+    void       *cookie;                // for use by client of buffer provider functions
+} buffer_provider_t;
+
+// The buffer_config_s structure specifies the input or output audio format
+// to be used by the effect engine.
+typedef struct buffer_config_s {
+    audio_buffer_t  buffer;     // buffer for use by process() function if not passed explicitly
+    uint32_t   samplingRate;    // sampling rate
+    uint32_t   channels;        // channel mask (see audio_channel_mask_t in audio.h)
+    buffer_provider_t bufferProvider;   // buffer provider
+    uint8_t    format;          // Audio format (see audio_format_t in audio.h)
+    uint8_t    accessMode;      // read/write or accumulate in buffer (effect_buffer_access_e)
+    uint16_t   mask;            // indicates which of the above fields is valid
+} buffer_config_t;
+
+// EFFECT_FEATURE_AUX_CHANNELS feature configuration descriptor. Describe a combination
+// of main and auxiliary channels supported
+typedef struct channel_config_s {
+    audio_channel_mask_t main_channels; // channel mask for main channels
+    audio_channel_mask_t aux_channels;  // channel mask for auxiliary channels
+} channel_config_t;
+
+
+// effect_config_s structure is used to configure audio parameters and buffers for effect engine
+// input and output.
+typedef struct effect_config_s {
+    buffer_config_t   inputCfg;
+    buffer_config_t   outputCfg;
+} effect_config_t;
+
+
+// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM
+// command and pCmdData and pReplyData of EFFECT_CMD_GET_PARAM command.
+// psize and vsize represent the actual size of parameter and value.
+//
+// NOTE: the start of value field inside the data field is always on a 32 bit boundary:
+//
+//  +-----------+
+//  | status    | sizeof(int)
+//  +-----------+
+//  | psize     | sizeof(int)
+//  +-----------+
+//  | vsize     | sizeof(int)
+//  +-----------+
+//  |           |   |           |
+//  ~ parameter ~   > psize     |
+//  |           |   |           >  ((psize - 1)/sizeof(int) + 1) * sizeof(int)
+//  +-----------+               |
+//  | padding   |               |
+//  +-----------+
+//  |           |   |
+//  ~ value     ~   > vsize
+//  |           |   |
+//  +-----------+
+
+typedef struct effect_param_s {
+    int32_t     status;     // Transaction status (unused for command, used for reply)
+    uint32_t    psize;      // Parameter size
+    uint32_t    vsize;      // Value size
+    char        data[];     // Start of Parameter + Value data
+} effect_param_t;
+
+// Maximum effect_param_t size
+#define EFFECT_PARAM_SIZE_MAX       65536
+
+// structure used by EFFECT_CMD_OFFLOAD command
+typedef struct effect_offload_param_s {
+    bool isOffload;         // true if the playback thread the effect is attached to is offloaded
+    int ioHandle;           // io handle of the playback thread the effect is attached to
+} effect_offload_param_t;
+
+
+__END_DECLS
+
+#endif  // ANDROID_AUDIO_EFFECT_CORE_H
diff --git a/audio/include/system/audio_effects/effect_aec.h b/audio/include/system/audio_effects/effect_aec.h
new file mode 100644 (file)
index 0000000..e87471e
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_AEC_CORE_H_
+#define ANDROID_EFFECT_AEC_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+// The AEC type UUID is not defined by OpenSL ES and has been generated from
+// http://www.itu.int/ITU-T/asn1/uuid.html
+static const effect_uuid_t FX_IID_AEC_ =
+    { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const FX_IID_AEC = &FX_IID_AEC_;
+
+typedef enum
+{
+    AEC_PARAM_ECHO_DELAY,           // echo delay in microseconds
+    AEC_PARAM_PROPERTIES
+} t_aec_params;
+
+//t_equalizer_settings groups all current aec settings for backup and restore.
+typedef struct s_aec_settings {
+    uint32_t echoDelay;
+} t_aec_settings;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_AEC_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_agc.h b/audio/include/system/audio_effects/effect_agc.h
new file mode 100644 (file)
index 0000000..b1b9b1d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_AGC_CORE_H_
+#define ANDROID_EFFECT_AGC_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+// The AGC type UUID is not defined by OpenSL ES and has been generated from
+// http://www.itu.int/ITU-T/asn1/uuid.html
+static const effect_uuid_t FX_IID_AGC_ =
+    { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const FX_IID_AGC = &FX_IID_AGC_;
+
+
+typedef enum
+{
+    AGC_PARAM_TARGET_LEVEL,      // target output level in millibel
+    AGC_PARAM_COMP_GAIN,         // gain in the compression range in millibel
+    AGC_PARAM_LIMITER_ENA,       // enable or disable limiter (boolean)
+    AGC_PARAM_PROPERTIES
+} t_agc_params;
+
+
+//t_agc_settings groups all current agc settings for backup and restore.
+typedef struct s_agc_settings {
+    int16_t  targetLevel;
+    int16_t  compGain;
+    bool     limiterEnabled;
+} t_agc_settings;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_AGC_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_bassboost.h b/audio/include/system/audio_effects/effect_bassboost.h
new file mode 100644 (file)
index 0000000..8776cd7
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_BASSBOOST_CORE_H_
+#define ANDROID_EFFECT_BASSBOOST_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_BASSBOOST_ = { 0x0634f220, 0xddd4, 0x11db, 0xa0fc,
+        { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_BASSBOOST = &SL_IID_BASSBOOST_;
+#endif //OPENSL_ES_H_
+
+/* enumerated parameter settings for BassBoost effect */
+typedef enum
+{
+    BASSBOOST_PARAM_STRENGTH_SUPPORTED,
+    BASSBOOST_PARAM_STRENGTH
+} t_bassboost_params;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_BASSBOOST_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_downmix.h b/audio/include/system/audio_effects/effect_downmix.h
new file mode 100644 (file)
index 0000000..731229e
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_DOWNMIX_CORE_H_
+#define ANDROID_EFFECT_DOWNMIX_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#define EFFECT_UIID_DOWNMIX__ { 0x381e49cc, 0xa858, 0x4aa2, 0x87f6, \
+                              { 0xe8, 0x38, 0x8e, 0x76, 0x01, 0xb2 } }
+static const effect_uuid_t EFFECT_UIID_DOWNMIX_ = EFFECT_UIID_DOWNMIX__;
+const effect_uuid_t * const EFFECT_UIID_DOWNMIX = &EFFECT_UIID_DOWNMIX_;
+
+
+/* enumerated parameter settings for downmix effect */
+typedef enum {
+    DOWNMIX_PARAM_TYPE
+} downmix_params_t;
+
+
+typedef enum {
+    DOWNMIX_TYPE_INVALID                 = -1,
+    // throw away the extra channels
+    DOWNMIX_TYPE_STRIP                   = 0,
+    // mix the extra channels with FL/FR
+    DOWNMIX_TYPE_FOLD                    = 1,
+    DOWNMIX_TYPE_CNT,
+    DOWNMIX_TYPE_LAST = DOWNMIX_TYPE_CNT - 1
+} downmix_type_t;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_DOWNMIX_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_environmentalreverb.h b/audio/include/system/audio_effects/effect_environmentalreverb.h
new file mode 100644 (file)
index 0000000..2910a1d
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_ENVIRONMENTALREVERB_CORE_H_
+#define ANDROID_EFFECT_ENVIRONMENTALREVERB_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac,
+        { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } };
+const effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_;
+#endif //OPENSL_ES_H_
+
+/* enumerated parameter settings for environmental reverb effect */
+typedef enum
+{
+    // Parameters below are as defined in OpenSL ES specification for environmental reverb interface
+    REVERB_PARAM_ROOM_LEVEL,            // in millibels,    range -6000 to 0
+    REVERB_PARAM_ROOM_HF_LEVEL,         // in millibels,    range -4000 to 0
+    REVERB_PARAM_DECAY_TIME,            // in milliseconds, range 100 to 20000
+    REVERB_PARAM_DECAY_HF_RATIO,        // in permilles,    range 100 to 1000
+    REVERB_PARAM_REFLECTIONS_LEVEL,     // in millibels,    range -6000 to 0
+    REVERB_PARAM_REFLECTIONS_DELAY,     // in milliseconds, range 0 to 65
+    REVERB_PARAM_REVERB_LEVEL,          // in millibels,    range -6000 to 0
+    REVERB_PARAM_REVERB_DELAY,          // in milliseconds, range 0 to 65
+    REVERB_PARAM_DIFFUSION,             // in permilles,    range 0 to 1000
+    REVERB_PARAM_DENSITY,               // in permilles,    range 0 to 1000
+    REVERB_PARAM_PROPERTIES,
+    REVERB_PARAM_BYPASS
+} t_env_reverb_params;
+
+//t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification.
+typedef struct s_reverb_settings {
+    int16_t     roomLevel;
+    int16_t     roomHFLevel;
+    uint32_t    decayTime;
+    int16_t     decayHFRatio;
+    int16_t     reflectionsLevel;
+    uint32_t    reflectionsDelay;
+    int16_t     reverbLevel;
+    uint32_t    reverbDelay;
+    int16_t     diffusion;
+    int16_t     density;
+} __attribute__((packed)) t_reverb_settings;
+
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_ENVIRONMENTALREVERB_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_equalizer.h b/audio/include/system/audio_effects/effect_equalizer.h
new file mode 100644 (file)
index 0000000..e0f6848
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_EQUALIZER_CORE_H_
+#define ANDROID_EFFECT_EQUALIZER_CORE_H_
+
+#include <system/audio_effect.h>
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_EQUALIZER_ = { 0x0bed4300, 0xddd6, 0x11db, 0x8f34,
+        { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_EQUALIZER = &SL_IID_EQUALIZER_;
+#endif //OPENSL_ES_H_
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/* enumerated parameters for Equalizer effect */
+typedef enum
+{
+    EQ_PARAM_NUM_BANDS,             // Gets the number of frequency bands that the equalizer
+                                    // supports.
+    EQ_PARAM_LEVEL_RANGE,           // Returns the minimum and maximum band levels supported.
+    EQ_PARAM_BAND_LEVEL,            // Gets/Sets the gain set for the given equalizer band.
+    EQ_PARAM_CENTER_FREQ,           // Gets the center frequency of the given band.
+    EQ_PARAM_BAND_FREQ_RANGE,       // Gets the frequency range of the given frequency band.
+    EQ_PARAM_GET_BAND,              // Gets the band that has the most effect on the given
+                                    // frequency.
+    EQ_PARAM_CUR_PRESET,            // Gets/Sets the current preset.
+    EQ_PARAM_GET_NUM_OF_PRESETS,    // Gets the total number of presets the equalizer supports.
+    EQ_PARAM_GET_PRESET_NAME,       // Gets the preset name based on the index.
+    EQ_PARAM_PROPERTIES             // Gets/Sets all parameters at a time.
+} t_equalizer_params;
+
+//t_equalizer_settings groups all current equalizer setting for backup and restore.
+typedef struct s_equalizer_settings {
+    uint16_t curPreset;
+    uint16_t numBands;
+    uint16_t bandLevels[];
+} t_equalizer_settings;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_EQUALIZER_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_loudnessenhancer.h b/audio/include/system/audio_effects/effect_loudnessenhancer.h
new file mode 100644 (file)
index 0000000..a8a8c9b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_LOUDNESS_ENHANCER_CORE_H_
+#define ANDROID_EFFECT_LOUDNESS_ENHANCER_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+// this effect is not defined in OpenSL ES as one of the standard effects
+static const effect_uuid_t FX_IID_LOUDNESS_ENHANCER_ =
+        {0xfe3199be, 0xaed0, 0x413f, 0x87bb, {0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}};
+const effect_uuid_t * const FX_IID_LOUDNESS_ENHANCER = &FX_IID_LOUDNESS_ENHANCER_;
+
+#define LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB 0 // mB
+
+// enumerated parameters for DRC effect
+// to keep in sync with frameworks/base/media/java/android/media/audiofx/LoudnessEnhancer.java
+typedef enum
+{
+    LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB = 0,// target gain expressed in mB
+} t_level_monitor_params;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_LOUDNESS_ENHANCER_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_ns.h b/audio/include/system/audio_effects/effect_ns.h
new file mode 100644 (file)
index 0000000..e0d4330
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_NS_CORE_H_
+#define ANDROID_EFFECT_NS_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+// The NS type UUID is not defined by OpenSL ES and has been generated from
+// http://www.itu.int/ITU-T/asn1/uuid.html
+static const effect_uuid_t FX_IID_NS_ =
+    { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const FX_IID_NS = &FX_IID_NS_;
+
+typedef enum
+{
+    NS_PARAM_LEVEL,             // noise suppression level (t_ns_level)
+    NS_PARAM_PROPERTIES,
+    NS_PARAM_TYPE               // noise suppression type (t_ns_type)
+} t_ns_params;
+
+// noise suppression level
+typedef enum {
+    NS_LEVEL_LOW,
+    NS_LEVEL_MEDIUM,
+    NS_LEVEL_HIGH
+} t_ns_level;
+
+// noise suppression type
+typedef enum {
+    NS_TYPE_SINGLE_CHANNEL,
+    NS_TYPE_MULTI_CHANNEL
+} t_ns_type;
+
+// s_ns_settings groups all current ns settings for backup and restore.
+typedef struct s_ns_settings {
+    uint32_t  level;
+    uint32_t  type;
+} t_ns_settings;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_NS_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_presetreverb.h b/audio/include/system/audio_effects/effect_presetreverb.h
new file mode 100644 (file)
index 0000000..831e117
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_PRESETREVERB_CORE_H_
+#define ANDROID_EFFECT_PRESETREVERB_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a,
+        { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_;
+#endif //OPENSL_ES_H_
+
+/* enumerated parameter settings for preset reverb effect */
+typedef enum
+{
+    REVERB_PARAM_PRESET
+} t_preset_reverb_params;
+
+
+typedef enum
+{
+    REVERB_PRESET_NONE,
+    REVERB_PRESET_SMALLROOM,
+    REVERB_PRESET_MEDIUMROOM,
+    REVERB_PRESET_LARGEROOM,
+    REVERB_PRESET_MEDIUMHALL,
+    REVERB_PRESET_LARGEHALL,
+    REVERB_PRESET_PLATE,
+    REVERB_PRESET_LAST = REVERB_PRESET_PLATE
+} t_reverb_presets;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_PRESETREVERB_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_virtualizer.h b/audio/include/system/audio_effects/effect_virtualizer.h
new file mode 100644 (file)
index 0000000..05b1544
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_VIRTUALIZER_CORE_H_
+#define ANDROID_EFFECT_VIRTUALIZER_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_VIRTUALIZER_ = { 0x37cc2c00, 0xdddd, 0x11db, 0x8577,
+        { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_VIRTUALIZER = &SL_IID_VIRTUALIZER_;
+#endif //OPENSL_ES_H_
+
+/* enumerated parameter settings for virtualizer effect */
+/* to keep in sync with frameworks/base/media/java/android/media/audiofx/Virtualizer.java */
+typedef enum
+{
+    VIRTUALIZER_PARAM_STRENGTH_SUPPORTED,
+    VIRTUALIZER_PARAM_STRENGTH,
+    // used with EFFECT_CMD_GET_PARAM
+    // format:
+    //   parameters int32_t              VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES
+    //              audio_channel_mask_t input channel mask
+    //              audio_devices_t      audio output device
+    //   output     int32_t*             an array of length 3 * the number of channels in the mask
+    //                                       where entries are the succession of the channel mask
+    //                                       of each speaker (i.e. a single bit is selected in the
+    //                                       channel mask) followed by the azimuth and the
+    //                                       elevation angles.
+    //   status     int -EINVAL  if configuration is not supported or invalid or not forcing
+    //                   0       if configuration is supported and the mode is forced
+    // notes:
+    // - all angles are expressed in degrees and are relative to the listener,
+    // - for azimuth: 0 is the direction the listener faces, 180 is behind the listener, and
+    //    -90 is to her/his left,
+    // - for elevation: 0 is the horizontal plane, +90 is above the listener, -90 is below.
+    VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES,
+    // used with EFFECT_CMD_SET_PARAM
+    // format:
+    //   parameters  int32_t           VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE
+    //               audio_devices_t   audio output device
+    //   status      int -EINVAL   if the device is not supported or invalid
+    //                   0         if the device is supported and the mode is forced, or forcing
+    //                               was disabled for the AUDIO_DEVICE_NONE audio device.
+    VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE,
+    // used with EFFECT_CMD_GET_PARAM
+    // format:
+    //   parameters int32_t              VIRTUALIZER_PARAM_VIRTUALIZATION_MODE
+    //   output     audio_device_t       audio device reflecting the current virtualization mode,
+    //                                   AUDIO_DEVICE_NONE when not virtualizing
+    //   status     int -EINVAL if an error occurred
+    //                  0       if the output value is successfully retrieved
+    VIRTUALIZER_PARAM_VIRTUALIZATION_MODE
+} t_virtualizer_params;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_VIRTUALIZER_CORE_H_*/
diff --git a/audio/include/system/audio_effects/effect_visualizer.h b/audio/include/system/audio_effects/effect_visualizer.h
new file mode 100644 (file)
index 0000000..b314822
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECT_VISUALIZER_CORE_H_
+#define ANDROID_EFFECT_VISUALIZER_CORE_H_
+
+#include <system/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_VISUALIZATION_ =
+    { 0xe46b26a0, 0xdddd, 0x11db, 0x8afd, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_VISUALIZATION = &SL_IID_VISUALIZATION_;
+#endif //OPENSL_ES_H_
+
+#define VISUALIZER_CAPTURE_SIZE_MAX 1024  // maximum capture size in samples
+#define VISUALIZER_CAPTURE_SIZE_MIN 128   // minimum capture size in samples
+
+// to keep in sync with frameworks/base/media/java/android/media/audiofx/Visualizer.java
+#define VISUALIZER_SCALING_MODE_NORMALIZED 0
+#define VISUALIZER_SCALING_MODE_AS_PLAYED  1
+
+#define MEASUREMENT_MODE_NONE      0x0
+#define MEASUREMENT_MODE_PEAK_RMS  0x1
+
+#define MEASUREMENT_IDX_PEAK 0
+#define MEASUREMENT_IDX_RMS  1
+#define MEASUREMENT_COUNT 2
+
+/* enumerated parameters for Visualizer effect */
+typedef enum
+{
+    VISUALIZER_PARAM_CAPTURE_SIZE, // Sets the number PCM samples in the capture.
+    VISUALIZER_PARAM_SCALING_MODE, // Sets the way the captured data is scaled
+    VISUALIZER_PARAM_LATENCY,      // Informs the visualizer about the downstream latency
+    VISUALIZER_PARAM_MEASUREMENT_MODE, // Sets which measurements are to be made
+} t_visualizer_params;
+
+/* commands */
+typedef enum
+{
+    VISUALIZER_CMD_CAPTURE = EFFECT_CMD_FIRST_PROPRIETARY, // Gets the latest PCM capture.
+    VISUALIZER_CMD_MEASURE, // Gets the current measurements
+}t_visualizer_cmds;
+
+// VISUALIZER_CMD_CAPTURE retrieves the latest PCM snapshot captured by the visualizer engine.
+// It returns the number of samples specified by VISUALIZER_PARAM_CAPTURE_SIZE
+// in 8 bit unsigned format (0 = 0x80)
+
+// VISUALIZER_CMD_MEASURE retrieves the lastest measurements as int32_t saved in the
+// MEASUREMENT_IDX_* array index order.
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECT_VISUALIZER_CORE_H_*/
index 8f80080..c5156d9 100644 (file)
@@ -50,13 +50,7 @@ typedef enum {
     SOUND_MODEL_TYPE_GENERIC = 1      /* use for all models other than keyphrase */
 } sound_trigger_sound_model_type_t;
 
-typedef struct sound_trigger_uuid_s {
-    unsigned int   timeLow;
-    unsigned short timeMid;
-    unsigned short timeHiAndVersion;
-    unsigned short clockSeq;
-    unsigned char  node[6];
-} sound_trigger_uuid_t;
+typedef audio_uuid_t sound_trigger_uuid_t;
 
 /*
  * sound trigger implementation descriptor read by the framework via get_properties().
index a0e1ca0..f48749a 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_AEC_H_
 #define ANDROID_EFFECT_AEC_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// The AEC type UUID is not defined by OpenSL ES and has been generated from
-// http://www.itu.int/ITU-T/asn1/uuid.html
-static const effect_uuid_t FX_IID_AEC_ =
-    { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const FX_IID_AEC = &FX_IID_AEC_;
-
-typedef enum
-{
-    AEC_PARAM_ECHO_DELAY,           // echo delay in microseconds
-    AEC_PARAM_PROPERTIES
-} t_aec_params;
-
-//t_equalizer_settings groups all current aec settings for backup and restore.
-typedef struct s_aec_settings {
-    uint32_t echoDelay;
-} t_aec_settings;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_aec.h>
 
 #endif /*ANDROID_EFFECT_AEC_H_*/
index eddac67..466ea96 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_AGC_H_
 #define ANDROID_EFFECT_AGC_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// The AGC type UUID is not defined by OpenSL ES and has been generated from
-// http://www.itu.int/ITU-T/asn1/uuid.html
-static const effect_uuid_t FX_IID_AGC_ =
-    { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const FX_IID_AGC = &FX_IID_AGC_;
-
-
-typedef enum
-{
-    AGC_PARAM_TARGET_LEVEL,      // target output level in millibel
-    AGC_PARAM_COMP_GAIN,         // gain in the compression range in millibel
-    AGC_PARAM_LIMITER_ENA,       // enable or disable limiter (boolean)
-    AGC_PARAM_PROPERTIES
-} t_agc_params;
-
-
-//t_agc_settings groups all current agc settings for backup and restore.
-typedef struct s_agc_settings {
-    int16_t  targetLevel;
-    int16_t  compGain;
-    bool     limiterEnabled;
-} t_agc_settings;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_agc.h>
 
 #endif /*ANDROID_EFFECT_AGC_H_*/
index 3735904..157452e 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_BASSBOOST_H_
 #define ANDROID_EFFECT_BASSBOOST_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_BASSBOOST_ = { 0x0634f220, 0xddd4, 0x11db, 0xa0fc,
-        { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_BASSBOOST = &SL_IID_BASSBOOST_;
-#endif //OPENSL_ES_H_
-
-/* enumerated parameter settings for BassBoost effect */
-typedef enum
-{
-    BASSBOOST_PARAM_STRENGTH_SUPPORTED,
-    BASSBOOST_PARAM_STRENGTH
-} t_bassboost_params;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_bassboost.h>
 
 #endif /*ANDROID_EFFECT_BASSBOOST_H_*/
index 0f6b073..26b849b 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_DOWNMIX_H_
 #define ANDROID_EFFECT_DOWNMIX_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#define EFFECT_UIID_DOWNMIX__ { 0x381e49cc, 0xa858, 0x4aa2, 0x87f6, \
-                              { 0xe8, 0x38, 0x8e, 0x76, 0x01, 0xb2 } }
-static const effect_uuid_t EFFECT_UIID_DOWNMIX_ = EFFECT_UIID_DOWNMIX__;
-const effect_uuid_t * const EFFECT_UIID_DOWNMIX = &EFFECT_UIID_DOWNMIX_;
-
-
-/* enumerated parameter settings for downmix effect */
-typedef enum {
-    DOWNMIX_PARAM_TYPE
-} downmix_params_t;
-
-
-typedef enum {
-    DOWNMIX_TYPE_INVALID                 = -1,
-    // throw away the extra channels
-    DOWNMIX_TYPE_STRIP                   = 0,
-    // mix the extra channels with FL/FR
-    DOWNMIX_TYPE_FOLD                    = 1,
-    DOWNMIX_TYPE_CNT,
-    DOWNMIX_TYPE_LAST = DOWNMIX_TYPE_CNT - 1
-} downmix_type_t;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_downmix.h>
 
 #endif /*ANDROID_EFFECT_DOWNMIX_H_*/
index 3acbd5c..dd474c2 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_ENVIRONMENTALREVERB_H_
 #define ANDROID_EFFECT_ENVIRONMENTALREVERB_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac,
-        { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } };
-const effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_;
-#endif //OPENSL_ES_H_
-
-/* enumerated parameter settings for environmental reverb effect */
-typedef enum
-{
-    // Parameters below are as defined in OpenSL ES specification for environmental reverb interface
-    REVERB_PARAM_ROOM_LEVEL,            // in millibels,    range -6000 to 0
-    REVERB_PARAM_ROOM_HF_LEVEL,         // in millibels,    range -4000 to 0
-    REVERB_PARAM_DECAY_TIME,            // in milliseconds, range 100 to 20000
-    REVERB_PARAM_DECAY_HF_RATIO,        // in permilles,    range 100 to 1000
-    REVERB_PARAM_REFLECTIONS_LEVEL,     // in millibels,    range -6000 to 0
-    REVERB_PARAM_REFLECTIONS_DELAY,     // in milliseconds, range 0 to 65
-    REVERB_PARAM_REVERB_LEVEL,          // in millibels,    range -6000 to 0
-    REVERB_PARAM_REVERB_DELAY,          // in milliseconds, range 0 to 65
-    REVERB_PARAM_DIFFUSION,             // in permilles,    range 0 to 1000
-    REVERB_PARAM_DENSITY,               // in permilles,    range 0 to 1000
-    REVERB_PARAM_PROPERTIES,
-    REVERB_PARAM_BYPASS
-} t_env_reverb_params;
-
-//t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification.
-typedef struct s_reverb_settings {
-    int16_t     roomLevel;
-    int16_t     roomHFLevel;
-    uint32_t    decayTime;
-    int16_t     decayHFRatio;
-    int16_t     reflectionsLevel;
-    uint32_t    reflectionsDelay;
-    int16_t     reverbLevel;
-    uint32_t    reverbDelay;
-    int16_t     diffusion;
-    int16_t     density;
-} __attribute__((packed)) t_reverb_settings;
-
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_environmentalreverb.h>
 
 #endif /*ANDROID_EFFECT_ENVIRONMENTALREVERB_H_*/
index 17ee74f..3059ec2 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_EQUALIZER_H_
 #define ANDROID_EFFECT_EQUALIZER_H_
 
 #include <hardware/audio_effect.h>
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_EQUALIZER_ = { 0x0bed4300, 0xddd6, 0x11db, 0x8f34,
-        { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_EQUALIZER = &SL_IID_EQUALIZER_;
-#endif //OPENSL_ES_H_
-
-#if __cplusplus
-extern "C" {
-#endif
-
-/* enumerated parameters for Equalizer effect */
-typedef enum
-{
-    EQ_PARAM_NUM_BANDS,             // Gets the number of frequency bands that the equalizer
-                                    // supports.
-    EQ_PARAM_LEVEL_RANGE,           // Returns the minimum and maximum band levels supported.
-    EQ_PARAM_BAND_LEVEL,            // Gets/Sets the gain set for the given equalizer band.
-    EQ_PARAM_CENTER_FREQ,           // Gets the center frequency of the given band.
-    EQ_PARAM_BAND_FREQ_RANGE,       // Gets the frequency range of the given frequency band.
-    EQ_PARAM_GET_BAND,              // Gets the band that has the most effect on the given
-                                    // frequency.
-    EQ_PARAM_CUR_PRESET,            // Gets/Sets the current preset.
-    EQ_PARAM_GET_NUM_OF_PRESETS,    // Gets the total number of presets the equalizer supports.
-    EQ_PARAM_GET_PRESET_NAME,       // Gets the preset name based on the index.
-    EQ_PARAM_PROPERTIES             // Gets/Sets all parameters at a time.
-} t_equalizer_params;
-
-//t_equalizer_settings groups all current equalizer setting for backup and restore.
-typedef struct s_equalizer_settings {
-    uint16_t curPreset;
-    uint16_t numBands;
-    uint16_t bandLevels[];
-} t_equalizer_settings;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_equalizer.h>
 
 #endif /*ANDROID_EFFECT_EQUALIZER_H_*/
index c5bcaee..f37ba45 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_LOUDNESS_ENHANCER_H_
 #define ANDROID_EFFECT_LOUDNESS_ENHANCER_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// this effect is not defined in OpenSL ES as one of the standard effects
-static const effect_uuid_t FX_IID_LOUDNESS_ENHANCER_ =
-        {0xfe3199be, 0xaed0, 0x413f, 0x87bb, {0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}};
-const effect_uuid_t * const FX_IID_LOUDNESS_ENHANCER = &FX_IID_LOUDNESS_ENHANCER_;
-
-#define LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB 0 // mB
-
-// enumerated parameters for DRC effect
-// to keep in sync with frameworks/base/media/java/android/media/audiofx/LoudnessEnhancer.java
-typedef enum
-{
-    LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB = 0,// target gain expressed in mB
-} t_level_monitor_params;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_loudnessenhancer.h>
 
 #endif /*ANDROID_EFFECT_LOUDNESS_ENHANCER_H_*/
index 8cda094..3bd8a41 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_NS_H_
 #define ANDROID_EFFECT_NS_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// The NS type UUID is not defined by OpenSL ES and has been generated from
-// http://www.itu.int/ITU-T/asn1/uuid.html
-static const effect_uuid_t FX_IID_NS_ =
-    { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const FX_IID_NS = &FX_IID_NS_;
-
-typedef enum
-{
-    NS_PARAM_LEVEL,             // noise suppression level (t_ns_level)
-    NS_PARAM_PROPERTIES,
-    NS_PARAM_TYPE               // noise suppression type (t_ns_type)
-} t_ns_params;
-
-// noise suppression level
-typedef enum {
-    NS_LEVEL_LOW,
-    NS_LEVEL_MEDIUM,
-    NS_LEVEL_HIGH
-} t_ns_level;
-
-// noise suppression type
-typedef enum {
-    NS_TYPE_SINGLE_CHANNEL,
-    NS_TYPE_MULTI_CHANNEL
-} t_ns_type;
-
-// s_ns_settings groups all current ns settings for backup and restore.
-typedef struct s_ns_settings {
-    uint32_t  level;
-    uint32_t  type;
-} t_ns_settings;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_ns.h>
 
 #endif /*ANDROID_EFFECT_NS_H_*/
index ba1beae..eac1f5f 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_PRESETREVERB_H_
 #define ANDROID_EFFECT_PRESETREVERB_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a,
-        { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_;
-#endif //OPENSL_ES_H_
-
-/* enumerated parameter settings for preset reverb effect */
-typedef enum
-{
-    REVERB_PARAM_PRESET
-} t_preset_reverb_params;
-
-
-typedef enum
-{
-    REVERB_PRESET_NONE,
-    REVERB_PRESET_SMALLROOM,
-    REVERB_PRESET_MEDIUMROOM,
-    REVERB_PRESET_LARGEROOM,
-    REVERB_PRESET_MEDIUMHALL,
-    REVERB_PRESET_LARGEHALL,
-    REVERB_PRESET_PLATE,
-    REVERB_PRESET_LAST = REVERB_PRESET_PLATE
-} t_reverb_presets;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_presetreverb.h>
 
 #endif /*ANDROID_EFFECT_PRESETREVERB_H_*/
index 3374a35..aeecfa5 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_VIRTUALIZER_H_
 #define ANDROID_EFFECT_VIRTUALIZER_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_VIRTUALIZER_ = { 0x37cc2c00, 0xdddd, 0x11db, 0x8577,
-        { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_VIRTUALIZER = &SL_IID_VIRTUALIZER_;
-#endif //OPENSL_ES_H_
-
-/* enumerated parameter settings for virtualizer effect */
-/* to keep in sync with frameworks/base/media/java/android/media/audiofx/Virtualizer.java */
-typedef enum
-{
-    VIRTUALIZER_PARAM_STRENGTH_SUPPORTED,
-    VIRTUALIZER_PARAM_STRENGTH,
-    // used with EFFECT_CMD_GET_PARAM
-    // format:
-    //   parameters int32_t              VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES
-    //              audio_channel_mask_t input channel mask
-    //              audio_devices_t      audio output device
-    //   output     int32_t*             an array of length 3 * the number of channels in the mask
-    //                                       where entries are the succession of the channel mask
-    //                                       of each speaker (i.e. a single bit is selected in the
-    //                                       channel mask) followed by the azimuth and the
-    //                                       elevation angles.
-    //   status     int -EINVAL  if configuration is not supported or invalid or not forcing
-    //                   0       if configuration is supported and the mode is forced
-    // notes:
-    // - all angles are expressed in degrees and are relative to the listener,
-    // - for azimuth: 0 is the direction the listener faces, 180 is behind the listener, and
-    //    -90 is to her/his left,
-    // - for elevation: 0 is the horizontal plane, +90 is above the listener, -90 is below.
-    VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES,
-    // used with EFFECT_CMD_SET_PARAM
-    // format:
-    //   parameters  int32_t           VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE
-    //               audio_devices_t   audio output device
-    //   status      int -EINVAL   if the device is not supported or invalid
-    //                   0         if the device is supported and the mode is forced, or forcing
-    //                               was disabled for the AUDIO_DEVICE_NONE audio device.
-    VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE,
-    // used with EFFECT_CMD_GET_PARAM
-    // format:
-    //   parameters int32_t              VIRTUALIZER_PARAM_VIRTUALIZATION_MODE
-    //   output     audio_device_t       audio device reflecting the current virtualization mode,
-    //                                   AUDIO_DEVICE_NONE when not virtualizing
-    //   status     int -EINVAL if an error occurred
-    //                  0       if the output value is successfully retrieved
-    VIRTUALIZER_PARAM_VIRTUALIZATION_MODE
-} t_virtualizer_params;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_virtualizer.h>
 
 #endif /*ANDROID_EFFECT_VIRTUALIZER_H_*/
index fe46d7f..47217e7 100644 (file)
  * limitations under the License.
  */
 
+/*
+ * USAGE NOTE: Only include this header when _implementing_ a particular
+ * effect. When access to UUID and properties is enough, include the
+ * corresponding header from system/audio_effects/, which doesn't include
+ * hardware/audio_effect.h.
+ *
+ * Only code that immediately calls into HAL or implements an effect
+ * can import hardware/audio_effect.h.
+ */
+
 #ifndef ANDROID_EFFECT_VISUALIZER_H_
 #define ANDROID_EFFECT_VISUALIZER_H_
 
 #include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_VISUALIZATION_ =
-    { 0xe46b26a0, 0xdddd, 0x11db, 0x8afd, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_VISUALIZATION = &SL_IID_VISUALIZATION_;
-#endif //OPENSL_ES_H_
-
-#define VISUALIZER_CAPTURE_SIZE_MAX 1024  // maximum capture size in samples
-#define VISUALIZER_CAPTURE_SIZE_MIN 128   // minimum capture size in samples
-
-// to keep in sync with frameworks/base/media/java/android/media/audiofx/Visualizer.java
-#define VISUALIZER_SCALING_MODE_NORMALIZED 0
-#define VISUALIZER_SCALING_MODE_AS_PLAYED  1
-
-#define MEASUREMENT_MODE_NONE      0x0
-#define MEASUREMENT_MODE_PEAK_RMS  0x1
-
-#define MEASUREMENT_IDX_PEAK 0
-#define MEASUREMENT_IDX_RMS  1
-#define MEASUREMENT_COUNT 2
-
-/* enumerated parameters for Visualizer effect */
-typedef enum
-{
-    VISUALIZER_PARAM_CAPTURE_SIZE, // Sets the number PCM samples in the capture.
-    VISUALIZER_PARAM_SCALING_MODE, // Sets the way the captured data is scaled
-    VISUALIZER_PARAM_LATENCY,      // Informs the visualizer about the downstream latency
-    VISUALIZER_PARAM_MEASUREMENT_MODE, // Sets which measurements are to be made
-} t_visualizer_params;
-
-/* commands */
-typedef enum
-{
-    VISUALIZER_CMD_CAPTURE = EFFECT_CMD_FIRST_PROPRIETARY, // Gets the latest PCM capture.
-    VISUALIZER_CMD_MEASURE, // Gets the current measurements
-}t_visualizer_cmds;
-
-// VISUALIZER_CMD_CAPTURE retrieves the latest PCM snapshot captured by the visualizer engine.
-// It returns the number of samples specified by VISUALIZER_PARAM_CAPTURE_SIZE
-// in 8 bit unsigned format (0 = 0x80)
-
-// VISUALIZER_CMD_MEASURE retrieves the lastest measurements as int32_t saved in the
-// MEASUREMENT_IDX_* array index order.
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
+#include <system/audio_effects/effect_visualizer.h>
 
 #endif /*ANDROID_EFFECT_VISUALIZER_H_*/
index 3796958..89b076b 100644 (file)
@@ -153,17 +153,16 @@ static void path_free(struct audio_route *ar)
     unsigned int i;
 
     for (i = 0; i < ar->num_mixer_paths; i++) {
-        if (ar->mixer_path[i].name)
-            free(ar->mixer_path[i].name);
+        free(ar->mixer_path[i].name);
         if (ar->mixer_path[i].setting) {
-            if (ar->mixer_path[i].setting->value.ptr)
-                free(ar->mixer_path[i].setting->value.ptr);
+            free(ar->mixer_path[i].setting->value.ptr);
             free(ar->mixer_path[i].setting);
         }
     }
     free(ar->mixer_path);
     ar->mixer_path = NULL;
     ar->mixer_path_size = 0;
+    ar->num_mixer_paths = 0;
 }
 
 static struct mixer_path *path_get_by_name(struct audio_route *ar,
@@ -478,7 +477,11 @@ static void start_tag(void *data, const XML_Char *tag_name,
             } else {
                 /* nested path */
                 struct mixer_path *sub_path = path_get_by_name(ar, attr_name);
-                path_add_path(ar, state->path, sub_path);
+                if (!sub_path) {
+                    ALOGE("unable to find sub path '%s'", attr_name);
+                } else {
+                    path_add_path(ar, state->path, sub_path);
+                }
             }
         }
     }
@@ -878,7 +881,7 @@ struct audio_route *audio_route_init(unsigned int card, const char *xml_path)
     file = fopen(xml_path, "r");
 
     if (!file) {
-        ALOGE("Failed to open %s", xml_path);
+        ALOGE("Failed to open %s: %s", xml_path, strerror(errno));
         goto err_fopen;
     }
 
index 629e864..ecd95cd 100644 (file)
@@ -20,10 +20,14 @@ cc_library {
 
     srcs: [
         "channels.c",
-        "fifo.c",
+        "ErrorLog.cpp",
+        "fifo.cpp",
+        "fifo_index.cpp",
         "format.c",
         "limiter.c",
         "minifloat.c",
+        "power.cpp",
+        "PowerLog.cpp",
         "primitives.c",
         "roundup.c",
     ],
@@ -36,7 +40,7 @@ cc_library {
     target: {
         android: {
             srcs: [
-                "conversion.cpp",
+                "mono_blend.cpp",
                 "resampler.c",
                 "echo_reference.c",
             ],
@@ -78,7 +82,8 @@ cc_library_static {
     name: "libfifo",
     defaults: ["audio_utils_defaults"],
     srcs: [
-        "fifo.c",
+        "fifo.cpp",
+        "fifo_index.cpp",
         "primitives.c",
         "roundup.c",
     ],
diff --git a/audio_utils/ErrorLog.cpp b/audio_utils/ErrorLog.cpp
new file mode 100644 (file)
index 0000000..54742e9
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_ErrorLog"
+#include <log/log.h>
+
+#include <audio_utils/ErrorLog.h>
+
+using namespace android;
+
+error_log_t *error_log_create(size_t entries, int64_t aggregate_ns)
+{
+    return reinterpret_cast<error_log_t *>
+            (new(std::nothrow) ErrorLog<int32_t>(entries, aggregate_ns));
+}
+
+void error_log_log(error_log_t *error_log, int32_t code, int64_t now_ns)
+{
+    if (error_log == nullptr) {
+        return;
+    }
+    reinterpret_cast<ErrorLog<int32_t> *>(error_log)->log(code, now_ns);
+}
+
+int error_log_dump(
+        error_log_t *error_log, int fd, const char *prefix, size_t lines, int64_t limit_ns)
+{
+    if (error_log == nullptr) {
+        return BAD_VALUE;
+    }
+    return reinterpret_cast<ErrorLog<int32_t> *>(error_log)->dump(fd, prefix, lines, limit_ns);
+}
+
+void error_log_destroy(error_log_t *error_log)
+{
+    delete reinterpret_cast<ErrorLog<int32_t> *>(error_log);
+}
diff --git a/audio_utils/PowerLog.cpp b/audio_utils/PowerLog.cpp
new file mode 100644 (file)
index 0000000..ab0dcaa
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_PowerLog"
+#include <log/log.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <math.h>
+#include <sstream>
+#include <stdint.h>
+
+#include <audio_utils/clock.h>
+#include <audio_utils/power.h>
+#include <audio_utils/PowerLog.h>
+
+namespace android {
+
+// TODO move to separate file
+template <typename T, size_t N>
+constexpr size_t array_size(const T(&)[N])
+{
+    return N;
+}
+
+PowerLog::PowerLog(uint32_t sampleRate,
+        uint32_t channelCount,
+        audio_format_t format,
+        size_t entries,
+        size_t framesPerEntry)
+    : mCurrentTime(0)
+    , mCurrentEnergy(0)
+    , mCurrentFrames(0)
+    , mIdx(0)
+    , mConsecutiveZeroes(0)
+    , mSampleRate(sampleRate)
+    , mChannelCount(channelCount)
+    , mFormat(format)
+    , mFramesPerEntry(framesPerEntry)
+    , mEntries(entries)
+{
+    (void)mSampleRate; // currently unused, for future use
+    LOG_ALWAYS_FATAL_IF(!audio_utils_is_compute_power_format_supported(format),
+            "unsupported format: %#x", format);
+}
+
+void PowerLog::log(const void *buffer, size_t frames, int64_t nowNs)
+{
+    std::lock_guard<std::mutex> guard(mLock);
+
+    const size_t bytes_per_sample = audio_bytes_per_sample(mFormat);
+    while (frames > 0) {
+        // check partial computation
+        size_t required = mFramesPerEntry - mCurrentFrames;
+        size_t process = std::min(required, frames);
+
+        if (mCurrentTime == 0) {
+            mCurrentTime = nowNs;
+        }
+        mCurrentEnergy +=
+                audio_utils_compute_energy_mono(buffer, mFormat, process * mChannelCount);
+        mCurrentFrames += process;
+
+        ALOGV("nowNs:%lld, required:%zu, process:%zu, mCurrentEnergy:%f, mCurrentFrames:%zu",
+                (long long)nowNs, required, process, mCurrentEnergy, mCurrentFrames);
+        if (process < required) {
+            return;
+        }
+
+        // We store the data as normalized energy per sample. The energy sequence is
+        // zero terminated. Consecutive zeroes are ignored.
+        if (mCurrentEnergy == 0.f) {
+            if (mConsecutiveZeroes++ == 0) {
+                mEntries[mIdx++] = std::make_pair(nowNs, 0.f);
+                // zero terminate the signal sequence.
+            }
+        } else {
+            mConsecutiveZeroes = 0;
+            mEntries[mIdx++] = std::make_pair(mCurrentTime, mCurrentEnergy);
+            ALOGV("writing %lld %f", (long long)mCurrentTime, mCurrentEnergy);
+        }
+        if (mIdx >= mEntries.size()) {
+            mIdx -= mEntries.size();
+        }
+        mCurrentTime = 0;
+        mCurrentEnergy = 0;
+        mCurrentFrames = 0;
+        frames -= process;
+        buffer = (const uint8_t *)buffer + mCurrentFrames * mChannelCount * bytes_per_sample;
+    }
+}
+
+std::string PowerLog::dumpToString(const char *prefix, size_t lines, int64_t limitNs) const
+{
+    std::lock_guard<std::mutex> guard(mLock);
+
+    const size_t maxColumns = 10;
+    const size_t numberOfEntries = mEntries.size();
+    if (lines == 0) lines = SIZE_MAX;
+
+    // compute where to start logging
+    enum {
+        AT_END,
+        IN_SIGNAL,
+    } state = IN_SIGNAL;
+    size_t count = 1;
+    size_t column = 0;
+    size_t nonzeros = 0;
+    ssize_t offset; // TODO doesn't dump if # entries exceeds SSIZE_MAX
+    for (offset = 0; offset < (ssize_t)numberOfEntries && count < lines; ++offset) {
+        const size_t idx = (mIdx + numberOfEntries - offset - 1) % numberOfEntries; // reverse direction
+        const int64_t time = mEntries[idx].first;
+        const float energy = mEntries[idx].second;
+
+        if (state == AT_END) {
+            if (energy == 0.f) {
+                ALOGV("two zeroes detected");
+                break; // normally single zero terminated - two zeroes means no more data.
+            }
+            state = IN_SIGNAL;
+        } else { // IN_SIGNAL
+            if (energy == 0.f) {
+                if (column != 0) {
+                    column = 0;
+                    ++count;
+                }
+                state = AT_END;
+                continue;
+            }
+        }
+        if (column == 0 && time < limitNs) {
+            break;
+        }
+        ++nonzeros;
+        if (++column == maxColumns) {
+            column = 0;
+            // TODO ideally we would peek the previous entry to see if it is 0
+            // to ensure we properly put in a starting signal bracket.
+            // We don't do that because it would complicate the logic here.
+            ++count;
+        }
+    }
+    if (offset > 0) {
+        --offset;
+    }
+    // We accumulate the log info into a string, and write to the fd once.
+    std::stringstream ss;
+    ss << std::fixed << std::setprecision(1);
+    // ss << std::scientific;
+    if (nonzeros == 0) {
+        ss << prefix << "Signal power history: (none)\n";
+    } else {
+        ss << prefix << "Signal power history:\n";
+
+        size_t column = 0;
+        bool first = true;
+        bool start = false;
+        float cumulative = 0.f;
+        for (; offset >= 0; --offset) {
+            const size_t idx = (mIdx + numberOfEntries - offset - 1) % numberOfEntries;
+            const int64_t time = mEntries[idx].first;
+            const float energy = mEntries[idx].second;
+
+            if (energy == 0.f) {
+                if (!first) {
+                    ss << " ] sum(" << audio_utils_power_from_energy(cumulative) << ")";
+                }
+                cumulative = 0.f;
+                column = 0;
+                start = true;
+                continue;
+            }
+            if (column == 0) {
+                // print time if at start of column
+                if (!first) {
+                    ss << "\n";
+                }
+                ss << prefix << " " << audio_utils_time_string_from_ns(time).time
+                        << (start ? ": [ ": ":   ");
+                first = false;
+                start = false;
+            }  else {
+                ss << " ";
+            }
+            if (++column >= maxColumns) {
+                column = 0;
+            }
+
+            cumulative += energy;
+            // convert energy to power and print
+            const float power =
+                    audio_utils_power_from_energy(energy / (mChannelCount * mFramesPerEntry));
+            ss << std::setw(6) << power;
+            ALOGV("state: %d %lld %f", state, (long long)time, power);
+        }
+        ss << "\n";
+    }
+    return ss.str();
+}
+
+status_t PowerLog::dump(int fd, const char *prefix, size_t lines, int64_t limitNs) const
+{
+    // Since dumpToString and write are thread safe, this function
+    // is conceptually thread-safe but simultaneous calls to dump
+    // by different threads to the same file descriptor may not write
+    // the two logs in time order.
+    const std::string s = dumpToString(prefix, lines, limitNs);
+    if (s.size() > 0 && write(fd, s.c_str(), s.size()) < 0) {
+        return -errno;
+    }
+    return NO_ERROR;
+}
+
+} // namespace android
+
+using namespace android;
+
+power_log_t *power_log_create(uint32_t sample_rate,
+        uint32_t channel_count, audio_format_t format, size_t entries, size_t frames_per_entry)
+{
+    if (!audio_utils_is_compute_power_format_supported(format)) {
+        return nullptr;
+    }
+    return reinterpret_cast<power_log_t *>
+            (new(std::nothrow)
+                    PowerLog(sample_rate, channel_count, format, entries, frames_per_entry));
+}
+
+void power_log_log(power_log_t *power_log,
+        const void *buffer, size_t frames, int64_t now_ns)
+{
+    if (power_log == nullptr) {
+        return;
+    }
+    reinterpret_cast<PowerLog *>(power_log)->log(buffer, frames, now_ns);
+}
+
+int power_log_dump(
+        power_log_t *power_log, int fd, const char *prefix, size_t lines, int64_t limit_ns)
+{
+    if (power_log == nullptr) {
+        return BAD_VALUE;
+    }
+    return reinterpret_cast<PowerLog *>(power_log)->dump(fd, prefix, lines, limit_ns);
+}
+
+void power_log_destroy(power_log_t *power_log)
+{
+    delete reinterpret_cast<PowerLog *>(power_log);
+}
diff --git a/audio_utils/README.md b/audio_utils/README.md
new file mode 100644 (file)
index 0000000..df78972
--- /dev/null
@@ -0,0 +1,8 @@
+# How to build and view documentation
+
+* doxygen Doxyfile
+* cd html
+* python -m SimpleHTTPServer
+* open in web browser
+  http://localhost:8000/classaudio__utils__fifo.html
+* when done: rm -rf html
index fa005d3..538deba 100644 (file)
@@ -33,7 +33,7 @@ static inline int32_t clamp24(int32_t sample)
  * Converts a uint8x3_t into an int32_t
  */
 inline int32_t uint8x3_to_int32(uint8x3_t val) {
-#ifdef HAVE_BIG_ENDIAN
+#if HAVE_BIG_ENDIAN
     int32_t temp = (val.c[0] << 24 | val.c[1] << 16 | val.c[2] << 8) >> 8;
 #else
     int32_t temp = (val.c[2] << 24 | val.c[1] << 16 | val.c[0] << 8) >> 8;
@@ -46,7 +46,7 @@ inline int32_t uint8x3_to_int32(uint8x3_t val) {
  */
 inline uint8x3_t int32_to_uint8x3(int32_t in) {
     uint8x3_t out;
-#ifdef HAVE_BIG_ENDIAN
+#if HAVE_BIG_ENDIAN
     out.c[2] = in;
     out.c[1] = in >> 8;
     out.c[0] = in >> 16;
diff --git a/audio_utils/fifo.c b/audio_utils/fifo.c
deleted file mode 100644 (file)
index c818a50..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "audio_utils_fifo"
-
-#include <stdlib.h>
-#include <string.h>
-#include <audio_utils/fifo.h>
-#include <audio_utils/roundup.h>
-#include <cutils/atomic.h>
-#include <cutils/log.h>
-
-void audio_utils_fifo_init(struct audio_utils_fifo *fifo, size_t frameCount, size_t frameSize,
-        void *buffer)
-{
-    // We would need a 64-bit roundup to support larger frameCount.
-    ALOG_ASSERT(fifo != NULL && frameCount > 0 && frameSize > 0 && buffer != NULL);
-    fifo->mFrameCount = frameCount;
-    fifo->mFrameCountP2 = roundup(frameCount);
-    fifo->mFudgeFactor = fifo->mFrameCountP2 - fifo->mFrameCount;
-    fifo->mFrameSize = frameSize;
-    fifo->mBuffer = buffer;
-    fifo->mFront = 0;
-    fifo->mRear = 0;
-}
-
-void audio_utils_fifo_deinit(struct audio_utils_fifo *fifo __unused)
-{
-}
-
-// Return a new index as the sum of an old index (either mFront or mRear) and a specified increment.
-static inline int32_t audio_utils_fifo_sum(struct audio_utils_fifo *fifo, int32_t index,
-        uint32_t increment)
-{
-    if (fifo->mFudgeFactor) {
-        uint32_t mask = fifo->mFrameCountP2 - 1;
-        ALOG_ASSERT((index & mask) < fifo->mFrameCount);
-        ALOG_ASSERT(/*0 <= increment &&*/ increment <= fifo->mFrameCountP2);
-        if ((index & mask) + increment >= fifo->mFrameCount) {
-            increment += fifo->mFudgeFactor;
-        }
-        index += increment;
-        ALOG_ASSERT((index & mask) < fifo->mFrameCount);
-        return index;
-    } else {
-        return index + increment;
-    }
-}
-
-// Return the difference between two indices: rear - front, where 0 <= difference <= mFrameCount.
-static inline size_t audio_utils_fifo_diff(struct audio_utils_fifo *fifo, int32_t rear,
-        int32_t front)
-{
-    int32_t diff = rear - front;
-    if (fifo->mFudgeFactor) {
-        uint32_t mask = ~(fifo->mFrameCountP2 - 1);
-        int32_t genDiff = (rear & mask) - (front & mask);
-        if (genDiff != 0) {
-            ALOG_ASSERT(genDiff == (int32_t) fifo->mFrameCountP2);
-            diff -= fifo->mFudgeFactor;
-        }
-    }
-    // FIFO should not be overfull
-    ALOG_ASSERT(0 <= diff && diff <= (int32_t) fifo->mFrameCount);
-    return (size_t) diff;
-}
-
-ssize_t audio_utils_fifo_write(struct audio_utils_fifo *fifo, const void *buffer, size_t count)
-{
-    int32_t front = android_atomic_acquire_load(&fifo->mFront);
-    int32_t rear = fifo->mRear;
-    size_t availToWrite = fifo->mFrameCount - audio_utils_fifo_diff(fifo, rear, front);
-    if (availToWrite > count) {
-        availToWrite = count;
-    }
-    rear &= fifo->mFrameCountP2 - 1;
-    size_t part1 = fifo->mFrameCount - rear;
-    if (part1 > availToWrite) {
-        part1 = availToWrite;
-    }
-    if (part1 > 0) {
-        memcpy((char *) fifo->mBuffer + (rear * fifo->mFrameSize), buffer,
-                part1 * fifo->mFrameSize);
-        size_t part2 = availToWrite - part1;
-        if (part2 > 0) {
-            memcpy(fifo->mBuffer, (char *) buffer + (part1 * fifo->mFrameSize),
-                    part2 * fifo->mFrameSize);
-        }
-        android_atomic_release_store(audio_utils_fifo_sum(fifo, fifo->mRear, availToWrite),
-                &fifo->mRear);
-    }
-    return availToWrite;
-}
-
-ssize_t audio_utils_fifo_read(struct audio_utils_fifo *fifo, void *buffer, size_t count)
-{
-    int32_t rear = android_atomic_acquire_load(&fifo->mRear);
-    int32_t front = fifo->mFront;
-    size_t availToRead = audio_utils_fifo_diff(fifo, rear, front);
-    if (availToRead > count) {
-        availToRead = count;
-    }
-    front &= fifo->mFrameCountP2 - 1;
-    size_t part1 = fifo->mFrameCount - front;
-    if (part1 > availToRead) {
-        part1 = availToRead;
-    }
-    if (part1 > 0) {
-        memcpy(buffer, (char *) fifo->mBuffer + (front * fifo->mFrameSize),
-                part1 * fifo->mFrameSize);
-        size_t part2 = availToRead - part1;
-        if (part2 > 0) {
-            memcpy((char *) buffer + (part1 * fifo->mFrameSize), fifo->mBuffer,
-                    part2 * fifo->mFrameSize);
-        }
-        android_atomic_release_store(audio_utils_fifo_sum(fifo, fifo->mFront, availToRead),
-                &fifo->mFront);
-    }
-    return availToRead;
-}
diff --git a/audio_utils/fifo.cpp b/audio_utils/fifo.cpp
new file mode 100644 (file)
index 0000000..883a9c0
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_fifo"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <audio_utils/clock_nanosleep.h>
+#include <audio_utils/fifo.h>
+#include <audio_utils/futex.h>
+#include <audio_utils/roundup.h>
+#include <cutils/log.h>
+#include <utils/Errors.h>
+
+audio_utils_fifo_base::audio_utils_fifo_base(uint32_t frameCount,
+        audio_utils_fifo_index& writerRear, audio_utils_fifo_index *throttleFront)
+        __attribute__((no_sanitize("integer"))) :
+    mFrameCount(frameCount), mFrameCountP2(roundup(frameCount)),
+    mFudgeFactor(mFrameCountP2 - mFrameCount),
+    // FIXME need an API to configure the sync types
+    mWriterRear(writerRear), mWriterRearSync(AUDIO_UTILS_FIFO_SYNC_SHARED),
+    mThrottleFront(throttleFront), mThrottleFrontSync(AUDIO_UTILS_FIFO_SYNC_SHARED),
+    mIsShutdown(false)
+{
+    // actual upper bound on frameCount will depend on the frame size
+    LOG_ALWAYS_FATAL_IF(frameCount == 0 || frameCount > ((uint32_t) INT32_MAX));
+}
+
+audio_utils_fifo_base::~audio_utils_fifo_base()
+{
+}
+
+uint32_t audio_utils_fifo_base::sum(uint32_t index, uint32_t increment) const
+        __attribute__((no_sanitize("integer")))
+{
+    if (mFudgeFactor > 0) {
+        uint32_t mask = mFrameCountP2 - 1;
+        ALOG_ASSERT((index & mask) < mFrameCount);
+        ALOG_ASSERT(increment <= mFrameCountP2);
+        if ((index & mask) + increment >= mFrameCount) {
+            increment += mFudgeFactor;
+        }
+        index += increment;
+        ALOG_ASSERT((index & mask) < mFrameCount);
+        return index;
+    } else {
+        return index + increment;
+    }
+}
+
+int32_t audio_utils_fifo_base::diff(uint32_t rear, uint32_t front, size_t *lost, bool flush) const
+        __attribute__((no_sanitize("integer")))
+{
+    // TODO replace multiple returns by a single return point so this isn't needed
+    if (lost != NULL) {
+        *lost = 0;
+    }
+    if (mIsShutdown) {
+        return -EIO;
+    }
+    uint32_t diff = rear - front;
+    if (mFudgeFactor > 0) {
+        uint32_t mask = mFrameCountP2 - 1;
+        uint32_t rearOffset = rear & mask;
+        uint32_t frontOffset = front & mask;
+        if (rearOffset >= mFrameCount || frontOffset >= mFrameCount) {
+            ALOGE("%s frontOffset=%u rearOffset=%u mFrameCount=%u",
+                    __func__, frontOffset, rearOffset, mFrameCount);
+            shutdown();
+            return -EIO;
+        }
+        // genDiff is the difference between the generation count fields of rear and front,
+        // and is always a multiple of mFrameCountP2.
+        uint32_t genDiff = (rear & ~mask) - (front & ~mask);
+        // It's OK for writer to be one generation beyond reader,
+        // but reader has lost frames if writer is further than one generation beyond.
+        if (genDiff > mFrameCountP2) {
+            if (lost != NULL) {
+                // Calculate the number of lost frames as the raw difference,
+                // less the mFrameCount frames that are still valid and can be read on retry,
+                // less the wasted indices that don't count as true lost frames.
+                *lost = diff - (flush ? 0 : mFrameCount) - mFudgeFactor * (genDiff/mFrameCountP2);
+            }
+            return -EOVERFLOW;
+        }
+        // If writer is one generation beyond reader, skip over the wasted indices.
+        if (genDiff > 0) {
+            diff -= mFudgeFactor;
+            // Note is still possible for diff > mFrameCount. BCD 16 - BCD 1 shows the problem.
+            // genDiff is 16, fudge is 6, decimal diff is 15 = (22 - 1 - 6).
+            // So we need to check diff for overflow one more time. See "if" a few lines below.
+        }
+    }
+    // FIFO should not be overfull
+    if (diff > mFrameCount) {
+        if (lost != NULL) {
+            *lost = diff - (flush ? 0 : mFrameCount);
+        }
+        return -EOVERFLOW;
+    }
+    return (int32_t) diff;
+}
+
+void audio_utils_fifo_base::shutdown() const
+{
+    ALOGE("%s", __func__);
+    mIsShutdown = true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+audio_utils_fifo::audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
+        audio_utils_fifo_index& writerRear, audio_utils_fifo_index *throttleFront)
+        __attribute__((no_sanitize("integer"))) :
+    audio_utils_fifo_base(frameCount, writerRear, throttleFront),
+    mFrameSize(frameSize), mBuffer(buffer)
+{
+    // maximum value of frameCount * frameSize is INT32_MAX (2^31 - 1), not 2^31, because we need to
+    // be able to distinguish successful and error return values from read and write.
+    LOG_ALWAYS_FATAL_IF(frameCount == 0 || frameSize == 0 || buffer == NULL ||
+            frameCount > ((uint32_t) INT32_MAX) / frameSize);
+}
+
+audio_utils_fifo::audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
+        bool throttlesWriter) :
+    audio_utils_fifo(frameCount, frameSize, buffer, mSingleProcessSharedRear,
+        throttlesWriter ?  &mSingleProcessSharedFront : NULL)
+{
+}
+
+audio_utils_fifo::~audio_utils_fifo()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+audio_utils_fifo_provider::audio_utils_fifo_provider(audio_utils_fifo& fifo) :
+    mFifo(fifo), mObtained(0), mTotalReleased(0)
+{
+}
+
+audio_utils_fifo_provider::~audio_utils_fifo_provider()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+audio_utils_fifo_writer::audio_utils_fifo_writer(audio_utils_fifo& fifo) :
+    audio_utils_fifo_provider(fifo), mLocalRear(0),
+    mArmLevel(fifo.mFrameCount), mTriggerLevel(0),
+    mIsArmed(true), // because initial fill level of zero is < mArmLevel
+    mEffectiveFrames(fifo.mFrameCount)
+{
+}
+
+audio_utils_fifo_writer::~audio_utils_fifo_writer()
+{
+}
+
+ssize_t audio_utils_fifo_writer::write(const void *buffer, size_t count,
+        const struct timespec *timeout)
+        __attribute__((no_sanitize("integer")))
+{
+    audio_utils_iovec iovec[2];
+    ssize_t availToWrite = obtain(iovec, count, timeout);
+    if (availToWrite > 0) {
+        memcpy((char *) mFifo.mBuffer + iovec[0].mOffset * mFifo.mFrameSize, buffer,
+                iovec[0].mLength * mFifo.mFrameSize);
+        if (iovec[1].mLength > 0) {
+            memcpy((char *) mFifo.mBuffer + iovec[1].mOffset * mFifo.mFrameSize,
+                    (char *) buffer + (iovec[0].mLength * mFifo.mFrameSize),
+                    iovec[1].mLength * mFifo.mFrameSize);
+        }
+        release(availToWrite);
+    }
+    return availToWrite;
+}
+
+// iovec == NULL is not part of the public API, but internally it means don't set mObtained
+ssize_t audio_utils_fifo_writer::obtain(audio_utils_iovec iovec[2], size_t count,
+        const struct timespec *timeout)
+        __attribute__((no_sanitize("integer")))
+{
+    int err = 0;
+    size_t availToWrite;
+    if (mFifo.mThrottleFront != NULL) {
+        int retries = kRetries;
+        uint32_t front;
+        for (;;) {
+            front = mFifo.mThrottleFront->loadAcquire();
+            // returns -EIO if mIsShutdown
+            int32_t filled = mFifo.diff(mLocalRear, front);
+            if (filled < 0) {
+                // on error, return an empty slice
+                err = filled;
+                availToWrite = 0;
+                break;
+            }
+            availToWrite = mEffectiveFrames > (uint32_t) filled ?
+                    mEffectiveFrames - (uint32_t) filled : 0;
+            // TODO pull out "count == 0"
+            if (count == 0 || availToWrite > 0 || timeout == NULL ||
+                    (timeout->tv_sec == 0 && timeout->tv_nsec == 0)) {
+                break;
+            }
+            // TODO add comments
+            // TODO abstract out switch and replace by general sync object
+            //      the high level code (synchronization, sleep, futex, iovec) should be completely
+            //      separate from the low level code (indexes, available, masking).
+            int op = FUTEX_WAIT;
+            switch (mFifo.mThrottleFrontSync) {
+            case AUDIO_UTILS_FIFO_SYNC_SLEEP:
+                err = audio_utils_clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, timeout,
+                        NULL /*remain*/);
+                if (err < 0) {
+                    LOG_ALWAYS_FATAL_IF(errno != EINTR, "unexpected err=%d errno=%d", err, errno);
+                    err = -errno;
+                } else {
+                    err = -ETIMEDOUT;
+                }
+                break;
+            case AUDIO_UTILS_FIFO_SYNC_PRIVATE:
+                op = FUTEX_WAIT_PRIVATE;
+                // fall through
+            case AUDIO_UTILS_FIFO_SYNC_SHARED:
+                if (timeout->tv_sec == LONG_MAX) {
+                    timeout = NULL;
+                }
+                err = mFifo.mThrottleFront->wait(op, front, timeout);
+                if (err < 0) {
+                    switch (errno) {
+                    case EWOULDBLOCK:
+                        // Benign race condition with partner: mFifo.mThrottleFront->mIndex
+                        // changed value between the earlier atomic_load_explicit() and sys_futex().
+                        // Try to load index again, but give up if we are unable to converge.
+                        if (retries-- > 0) {
+                            // bypass the "timeout = NULL;" below
+                            continue;
+                        }
+                        // fall through
+                    case EINTR:
+                    case ETIMEDOUT:
+                        err = -errno;
+                        break;
+                    default:
+                        LOG_ALWAYS_FATAL("unexpected err=%d errno=%d", err, errno);
+                        break;
+                    }
+                }
+                break;
+            default:
+                LOG_ALWAYS_FATAL("mFifo.mThrottleFrontSync=%d", mFifo.mThrottleFrontSync);
+                break;
+            }
+            timeout = NULL;
+        }
+    } else {
+        if (mFifo.mIsShutdown) {
+            err = -EIO;
+            availToWrite = 0;
+        } else {
+            availToWrite = mEffectiveFrames;
+        }
+    }
+    if (availToWrite > count) {
+        availToWrite = count;
+    }
+    uint32_t rearOffset = mLocalRear & (mFifo.mFrameCountP2 - 1);
+    size_t part1 = mFifo.mFrameCount - rearOffset;
+    if (part1 > availToWrite) {
+        part1 = availToWrite;
+    }
+    size_t part2 = part1 > 0 ? availToWrite - part1 : 0;
+    // return slice
+    if (iovec != NULL) {
+        iovec[0].mOffset = rearOffset;
+        iovec[0].mLength = part1;
+        iovec[1].mOffset = 0;
+        iovec[1].mLength = part2;
+        mObtained = availToWrite;
+    }
+    return availToWrite > 0 ? availToWrite : err;
+}
+
+void audio_utils_fifo_writer::release(size_t count)
+        __attribute__((no_sanitize("integer")))
+{
+    // no need to do an early check for mIsShutdown, because the extra code executed is harmless
+    if (count > 0) {
+        if (count > mObtained) {
+            ALOGE("%s(count=%zu) > mObtained=%u", __func__, count, mObtained);
+            mFifo.shutdown();
+            return;
+        }
+        if (mFifo.mThrottleFront != NULL) {
+            uint32_t front = mFifo.mThrottleFront->loadAcquire();
+            // returns -EIO if mIsShutdown
+            int32_t filled = mFifo.diff(mLocalRear, front);
+            mLocalRear = mFifo.sum(mLocalRear, count);
+            mFifo.mWriterRear.storeRelease(mLocalRear);
+            // TODO add comments
+            int op = FUTEX_WAKE;
+            switch (mFifo.mWriterRearSync) {
+            case AUDIO_UTILS_FIFO_SYNC_SLEEP:
+                break;
+            case AUDIO_UTILS_FIFO_SYNC_PRIVATE:
+                op = FUTEX_WAKE_PRIVATE;
+                // fall through
+            case AUDIO_UTILS_FIFO_SYNC_SHARED:
+                if (filled >= 0) {
+                    if ((uint32_t) filled < mArmLevel) {
+                        mIsArmed = true;
+                    }
+                    if (mIsArmed && filled + count > mTriggerLevel) {
+                        int err = mFifo.mWriterRear.wake(op, INT32_MAX /*waiters*/);
+                        // err is number of processes woken up
+                        if (err < 0) {
+                            LOG_ALWAYS_FATAL("%s: unexpected err=%d errno=%d",
+                                    __func__, err, errno);
+                        }
+                        mIsArmed = false;
+                    }
+                }
+                break;
+            default:
+                LOG_ALWAYS_FATAL("mFifo.mWriterRearSync=%d", mFifo.mWriterRearSync);
+                break;
+            }
+        } else {
+            mLocalRear = mFifo.sum(mLocalRear, count);
+            mFifo.mWriterRear.storeRelease(mLocalRear);
+        }
+        mObtained -= count;
+        mTotalReleased += count;
+    }
+}
+
+ssize_t audio_utils_fifo_writer::available()
+{
+    // iovec == NULL is not part of the public API, but internally it means don't set mObtained
+    return obtain(NULL /*iovec*/, SIZE_MAX /*count*/, NULL /*timeout*/);
+}
+
+void audio_utils_fifo_writer::resize(uint32_t frameCount)
+{
+    // cap to range [0, mFifo.mFrameCount]
+    if (frameCount > mFifo.mFrameCount) {
+        frameCount = mFifo.mFrameCount;
+    }
+    // if we reduce the effective frame count, update hysteresis points to be within the new range
+    if (frameCount < mEffectiveFrames) {
+        if (mArmLevel > frameCount) {
+            mArmLevel = frameCount;
+        }
+        if (mTriggerLevel > frameCount) {
+            mTriggerLevel = frameCount;
+        }
+    }
+    mEffectiveFrames = frameCount;
+}
+
+uint32_t audio_utils_fifo_writer::size() const
+{
+    return mEffectiveFrames;
+}
+
+void audio_utils_fifo_writer::setHysteresis(uint32_t lowLevelArm, uint32_t highLevelTrigger)
+{
+    // cap to range [0, mEffectiveFrames]
+    if (lowLevelArm > mEffectiveFrames) {
+        lowLevelArm = mEffectiveFrames;
+    }
+    if (highLevelTrigger > mEffectiveFrames) {
+        highLevelTrigger = mEffectiveFrames;
+    }
+    // TODO this is overly conservative; it would be better to arm based on actual fill level
+    if (lowLevelArm > mArmLevel) {
+        mIsArmed = true;
+    }
+    mArmLevel = lowLevelArm;
+    mTriggerLevel = highLevelTrigger;
+}
+
+void audio_utils_fifo_writer::getHysteresis(uint32_t *armLevel, uint32_t *triggerLevel) const
+{
+    *armLevel = mArmLevel;
+    *triggerLevel = mTriggerLevel;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+audio_utils_fifo_reader::audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter,
+        bool flush) :
+    audio_utils_fifo_provider(fifo),
+
+    // If we throttle the writer, then initialize our front index to zero so that we see all data
+    // currently in the buffer.
+    // Otherwise, ignore everything currently in the buffer by initializing our front index to the
+    // current value of writer's rear.  This avoids an immediate -EOVERFLOW (overrun) in the case
+    // where reader starts out more than one buffer behind writer.  The initial catch-up does not
+    // contribute towards the totalLost, totalFlushed, or totalReleased counters.
+    mLocalFront(throttlesWriter ? 0 : mFifo.mWriterRear.loadConsume()),
+
+    mThrottleFront(throttlesWriter ? mFifo.mThrottleFront : NULL),
+    mFlush(flush),
+    mArmLevel(-1), mTriggerLevel(mFifo.mFrameCount),
+    mIsArmed(true), // because initial fill level of zero is > mArmLevel
+    mTotalLost(0), mTotalFlushed(0)
+{
+}
+
+audio_utils_fifo_reader::~audio_utils_fifo_reader()
+{
+    // TODO Need a way to pass throttle capability to the another reader, should one reader exit.
+}
+
+ssize_t audio_utils_fifo_reader::read(void *buffer, size_t count, const struct timespec *timeout,
+        size_t *lost)
+        __attribute__((no_sanitize("integer")))
+{
+    audio_utils_iovec iovec[2];
+    ssize_t availToRead = obtain(iovec, count, timeout, lost);
+    if (availToRead > 0) {
+        memcpy(buffer, (char *) mFifo.mBuffer + iovec[0].mOffset * mFifo.mFrameSize,
+                iovec[0].mLength * mFifo.mFrameSize);
+        if (iovec[1].mLength > 0) {
+            memcpy((char *) buffer + (iovec[0].mLength * mFifo.mFrameSize),
+                    (char *) mFifo.mBuffer + iovec[1].mOffset * mFifo.mFrameSize,
+                    iovec[1].mLength * mFifo.mFrameSize);
+        }
+        release(availToRead);
+    }
+    return availToRead;
+}
+
+ssize_t audio_utils_fifo_reader::obtain(audio_utils_iovec iovec[2], size_t count,
+        const struct timespec *timeout)
+        __attribute__((no_sanitize("integer")))
+{
+    return obtain(iovec, count, timeout, NULL /*lost*/);
+}
+
+void audio_utils_fifo_reader::release(size_t count)
+        __attribute__((no_sanitize("integer")))
+{
+    // no need to do an early check for mIsShutdown, because the extra code executed is harmless
+    if (count > 0) {
+        if (count > mObtained) {
+            ALOGE("%s(count=%zu) > mObtained=%u", __func__, count, mObtained);
+            mFifo.shutdown();
+            return;
+        }
+        if (mThrottleFront != NULL) {
+            uint32_t rear = mFifo.mWriterRear.loadAcquire();
+            // returns -EIO if mIsShutdown
+            int32_t filled = mFifo.diff(rear, mLocalFront);
+            mLocalFront = mFifo.sum(mLocalFront, count);
+            mThrottleFront->storeRelease(mLocalFront);
+            // TODO add comments
+            int op = FUTEX_WAKE;
+            switch (mFifo.mThrottleFrontSync) {
+            case AUDIO_UTILS_FIFO_SYNC_SLEEP:
+                break;
+            case AUDIO_UTILS_FIFO_SYNC_PRIVATE:
+                op = FUTEX_WAKE_PRIVATE;
+                // fall through
+            case AUDIO_UTILS_FIFO_SYNC_SHARED:
+                if (filled >= 0) {
+                    if (filled > mArmLevel) {
+                        mIsArmed = true;
+                    }
+                    if (mIsArmed && filled - count < mTriggerLevel) {
+                        int err = mThrottleFront->wake(op, 1 /*waiters*/);
+                        // err is number of processes woken up
+                        if (err < 0 || err > 1) {
+                            LOG_ALWAYS_FATAL("%s: unexpected err=%d errno=%d",
+                                    __func__, err, errno);
+                        }
+                        mIsArmed = false;
+                    }
+                }
+                break;
+            default:
+                LOG_ALWAYS_FATAL("mFifo.mThrottleFrontSync=%d", mFifo.mThrottleFrontSync);
+                break;
+            }
+        } else {
+            mLocalFront = mFifo.sum(mLocalFront, count);
+        }
+        mObtained -= count;
+        mTotalReleased += count;
+    }
+}
+
+// iovec == NULL is not part of the public API, but internally it means don't set mObtained
+ssize_t audio_utils_fifo_reader::obtain(audio_utils_iovec iovec[2], size_t count,
+        const struct timespec *timeout, size_t *lost)
+        __attribute__((no_sanitize("integer")))
+{
+    int err = 0;
+    int retries = kRetries;
+    uint32_t rear;
+    for (;;) {
+        rear = mFifo.mWriterRear.loadAcquire();
+        // TODO pull out "count == 0"
+        if (count == 0 || rear != mLocalFront || timeout == NULL ||
+                (timeout->tv_sec == 0 && timeout->tv_nsec == 0)) {
+            break;
+        }
+        // TODO add comments
+        int op = FUTEX_WAIT;
+        switch (mFifo.mWriterRearSync) {
+        case AUDIO_UTILS_FIFO_SYNC_SLEEP:
+            err = audio_utils_clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, timeout,
+                    NULL /*remain*/);
+            if (err < 0) {
+                LOG_ALWAYS_FATAL_IF(errno != EINTR, "unexpected err=%d errno=%d", err, errno);
+                err = -errno;
+            } else {
+                err = -ETIMEDOUT;
+            }
+            break;
+        case AUDIO_UTILS_FIFO_SYNC_PRIVATE:
+            op = FUTEX_WAIT_PRIVATE;
+            // fall through
+        case AUDIO_UTILS_FIFO_SYNC_SHARED:
+            if (timeout->tv_sec == LONG_MAX) {
+                timeout = NULL;
+            }
+            err = mFifo.mWriterRear.wait(op, rear, timeout);
+            if (err < 0) {
+                switch (errno) {
+                case EWOULDBLOCK:
+                    // Benign race condition with partner: mFifo.mWriterRear->mIndex
+                    // changed value between the earlier atomic_load_explicit() and sys_futex().
+                    // Try to load index again, but give up if we are unable to converge.
+                    if (retries-- > 0) {
+                        // bypass the "timeout = NULL;" below
+                        continue;
+                    }
+                    // fall through
+                case EINTR:
+                case ETIMEDOUT:
+                    err = -errno;
+                    break;
+                default:
+                    LOG_ALWAYS_FATAL("unexpected err=%d errno=%d", err, errno);
+                    break;
+                }
+            }
+            break;
+        default:
+            LOG_ALWAYS_FATAL("mFifo.mWriterRearSync=%d", mFifo.mWriterRearSync);
+            break;
+        }
+        timeout = NULL;
+    }
+    size_t ourLost;
+    if (lost == NULL) {
+        lost = &ourLost;
+    }
+    // returns -EIO if mIsShutdown
+    int32_t filled = mFifo.diff(rear, mLocalFront, lost, mFlush);
+    mTotalLost += *lost;
+    mTotalReleased += *lost;
+    if (filled < 0) {
+        if (filled == -EOVERFLOW) {
+            // catch up with writer, but preserve the still valid frames in buffer
+            mLocalFront = rear - (mFlush ? 0 : mFifo.mFrameCountP2 /*sic*/);
+        }
+        // on error, return an empty slice
+        err = filled;
+        filled = 0;
+    }
+    size_t availToRead = (size_t) filled;
+    if (availToRead > count) {
+        availToRead = count;
+    }
+    uint32_t frontOffset = mLocalFront & (mFifo.mFrameCountP2 - 1);
+    size_t part1 = mFifo.mFrameCount - frontOffset;
+    if (part1 > availToRead) {
+        part1 = availToRead;
+    }
+    size_t part2 = part1 > 0 ? availToRead - part1 : 0;
+    // return slice
+    if (iovec != NULL) {
+        iovec[0].mOffset = frontOffset;
+        iovec[0].mLength = part1;
+        iovec[1].mOffset = 0;
+        iovec[1].mLength = part2;
+        mObtained = availToRead;
+    }
+    return availToRead > 0 ? availToRead : err;
+}
+
+ssize_t audio_utils_fifo_reader::available()
+{
+    return available(NULL /*lost*/);
+}
+
+ssize_t audio_utils_fifo_reader::available(size_t *lost)
+{
+    // iovec == NULL is not part of the public API, but internally it means don't set mObtained
+    return obtain(NULL /*iovec*/, SIZE_MAX /*count*/, NULL /*timeout*/, lost);
+}
+
+ssize_t audio_utils_fifo_reader::flush(size_t *lost)
+{
+    audio_utils_iovec iovec[2];
+    ssize_t ret = obtain(iovec, SIZE_MAX /*count*/, NULL /*timeout*/, lost);
+    if (ret > 0) {
+        size_t flushed = (size_t) ret;
+        release(flushed);
+        mTotalFlushed += flushed;
+        ret = flushed;
+    }
+    return ret;
+}
+
+void audio_utils_fifo_reader::setHysteresis(int32_t armLevel, uint32_t triggerLevel)
+{
+    // cap to range [0, mFifo.mFrameCount]
+    if (armLevel < 0) {
+        armLevel = -1;
+    } else if ((uint32_t) armLevel > mFifo.mFrameCount) {
+        armLevel = mFifo.mFrameCount;
+    }
+    if (triggerLevel > mFifo.mFrameCount) {
+        triggerLevel = mFifo.mFrameCount;
+    }
+    // TODO this is overly conservative; it would be better to arm based on actual fill level
+    if (armLevel < mArmLevel) {
+        mIsArmed = true;
+    }
+    mArmLevel = armLevel;
+    mTriggerLevel = triggerLevel;
+}
+
+void audio_utils_fifo_reader::getHysteresis(int32_t *armLevel, uint32_t *triggerLevel) const
+{
+    *armLevel = mArmLevel;
+    *triggerLevel = mTriggerLevel;
+}
diff --git a/audio_utils/fifo_index.cpp b/audio_utils/fifo_index.cpp
new file mode 100644 (file)
index 0000000..d9a200a
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <audio_utils/fifo_index.h>
+#include <audio_utils/futex.h>
+
+// These are not implemented within <audio_utils/fifo_index.h>
+// so that we don't expose futex.
+
+uint32_t audio_utils_fifo_index::loadAcquire()
+{
+    return atomic_load_explicit(&mIndex, std::memory_order_acquire);
+}
+
+void audio_utils_fifo_index::storeRelease(uint32_t value)
+{
+    atomic_store_explicit(&mIndex, value, std::memory_order_release);
+}
+
+int audio_utils_fifo_index::wait(int op, uint32_t expected, const struct timespec *timeout)
+{
+    return sys_futex(&mIndex, op, expected, timeout, NULL, 0);
+}
+
+int audio_utils_fifo_index::wake(int op, int waiters)
+{
+    return sys_futex(&mIndex, op, waiters, NULL, NULL, 0);
+}
+
+uint32_t audio_utils_fifo_index::loadConsume()
+{
+    return atomic_load_explicit(&mIndex, std::memory_order_consume);
+}
+
+////
+
+RefIndexDeferredStoreReleaseDeferredWake::RefIndexDeferredStoreReleaseDeferredWake(
+        audio_utils_fifo_index& index)
+    : mIndex(index), mValue(0), mWriteback(false), mWaiters(0), mWakeOp(FUTEX_WAIT_PRIVATE)
+{
+}
+
+RefIndexDeferredStoreReleaseDeferredWake::~RefIndexDeferredStoreReleaseDeferredWake()
+{
+    writeback();
+    wakeNowIfNeeded();
+}
+
+void RefIndexDeferredStoreReleaseDeferredWake::set(uint32_t value) {
+    mValue = value;
+    mWriteback = true;
+}
+
+void RefIndexDeferredStoreReleaseDeferredWake::writeback()
+{
+    if (mWriteback) {
+        // TODO When part of a collection, should use relaxed for all but the last writeback
+        mIndex.storeRelease(mValue);
+        mWriteback = false;
+    }
+}
+
+void RefIndexDeferredStoreReleaseDeferredWake::writethrough(uint32_t value) {
+    set(value);
+    writeback();
+}
+
+void RefIndexDeferredStoreReleaseDeferredWake::wakeDeferred(int op, int waiters)
+{
+    if (waiters <= 0) {
+        return;
+    }
+    // default is FUTEX_WAKE_PRIVATE
+    if (op == FUTEX_WAKE) {
+        mWakeOp = FUTEX_WAKE;
+    }
+    if (waiters < INT_MAX - mWaiters) {
+        mWaiters += waiters;
+    } else {
+        mWaiters = INT_MAX;
+    }
+}
+
+void RefIndexDeferredStoreReleaseDeferredWake::wakeNowIfNeeded()
+{
+    if (mWaiters > 0) {
+        mIndex.wake(mWakeOp, mWaiters);
+        mWaiters = 0;
+        mWakeOp = FUTEX_WAKE_PRIVATE;
+    }
+}
+
+void RefIndexDeferredStoreReleaseDeferredWake::wakeNow(int op, int waiters)
+{
+    wakeDeferred(op, waiters);
+    wakeNowIfNeeded();
+}
+
+////
+
+RefIndexCachedLoadAcquireDeferredWait::RefIndexCachedLoadAcquireDeferredWait(
+        audio_utils_fifo_index& index)
+    : mIndex(index), mValue(0), mLoaded(false)
+{
+}
+
+RefIndexCachedLoadAcquireDeferredWait::~RefIndexCachedLoadAcquireDeferredWait()
+{
+}
+
+uint32_t RefIndexCachedLoadAcquireDeferredWait::get()
+{
+    prefetch();
+    return mValue;
+}
+
+void RefIndexCachedLoadAcquireDeferredWait::prefetch()
+{
+    if (!mLoaded) {
+        // TODO When part of a collection, should use relaxed for all but the last load
+        mValue = mIndex.loadAcquire();
+        mLoaded = true;
+    }
+}
+
+void RefIndexCachedLoadAcquireDeferredWait::invalidate()
+{
+    mLoaded = false;
+}
+
+#if 0
+uint32_t RefIndexCachedLoadAcquireDeferredWait::readthrough()
+{
+    invalidate();
+    return get();
+}
+#endif
+
+int RefIndexCachedLoadAcquireDeferredWait::wait(int op, const struct timespec *timeout)
+{
+    if (!mLoaded) {
+        return -EINVAL;
+    }
+    int err = mIndex.wait(op, mValue /*expected*/, timeout);
+    invalidate();
+    return err;
+}
diff --git a/audio_utils/include/audio_utils/ErrorLog.h b/audio_utils/include/audio_utils/ErrorLog.h
new file mode 100644 (file)
index 0000000..88448b1
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_ERROR_LOG_H
+#define ANDROID_AUDIO_ERROR_LOG_H
+
+#ifdef __cplusplus
+
+#include <iomanip>
+#include <mutex>
+#include <sstream>
+#include <unistd.h>
+#include <vector>
+
+#include <audio_utils/clock.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+/**
+ * ErrorLog captures audio errors codes, combining consecutive identical error codes
+ * (within a specified time) into a single entry (to reduce log spamming).
+ *
+ * The entry thus contains the number of consecutive error codes,
+ * together with the first time the error code occurs and the last time the error code occurs.
+ *
+ * The type T represents the error code type and is an int32_t for the C API.
+ */
+template <typename T>
+class ErrorLog {
+public:
+    /**
+     * \brief Creates an ErrorLog object
+     *
+     * \param entries           the length of error history.
+     * \param aggregateNs       the maximum time in nanoseconds between identical error codes
+     *                          to be aggregated into a single entry.
+     */
+    explicit ErrorLog(size_t entries, int64_t aggregateNs = 1000000000 /* one second */)
+        : mErrors(0)
+        , mIdx(0)
+        , mAggregateNs(aggregateNs)
+        , mEntries(entries)
+    {
+    }
+
+    /**
+     * \brief Adds new error code to the error log.
+     *
+     * Consecutive errors with the same code will be aggregated
+     * if they occur within aggregateNs.
+     *
+     * \param code              error code of type T.
+     * \param nowNs             current time in nanoseconds.
+     */
+    void log(const T &code, int64_t nowNs)
+    {
+        std::lock_guard<std::mutex> guard(mLock);
+
+        ++mErrors;
+
+        // Within mAggregateNs (1 second by default), aggregate error codes together.
+        if (code == mEntries[mIdx].mCode
+                && nowNs - mEntries[mIdx].mLastTime < mAggregateNs) {
+            mEntries[mIdx].mCount++;
+            mEntries[mIdx].mLastTime = nowNs;
+            return;
+        }
+
+        // Add new error entry.
+        if (++mIdx >= mEntries.size()) {
+            mIdx = 0;
+        }
+        mEntries[mIdx].setFirstError(code, nowNs);
+    }
+
+    /**
+     * \brief Dumps the log to a std::string.
+     * \param prefix            the prefix to use for each line
+     *                          (generally a null terminated string of spaces).
+     * \param lines             maximum number of lines to output (0 disables).
+     * \param limitNs           limit dump to data more recent than limitNs (0 disables).
+     * \return std::string of the dump.
+     */
+    std::string dumpToString(const char *prefix = "", size_t lines = 0, int64_t limitNs = 0) const
+    {
+        std::lock_guard<std::mutex> guard(mLock);
+
+        std::stringstream ss;
+        const size_t numberOfEntries = mEntries.size();
+        const size_t headerLines = 2;
+
+        if (lines == 0) {
+            lines = SIZE_MAX;
+        }
+        ss << prefix << "Errors: " << mErrors << "\n";
+
+        if (mErrors == 0 || lines <= headerLines) {
+            return ss.str();
+        }
+
+        lines = std::min(lines - headerLines, numberOfEntries);
+        // compute where to start dump log
+        ssize_t offset;
+        for (offset = 0; offset < (ssize_t)lines; ++offset) {
+            const auto &entry =
+                    mEntries[(mIdx + numberOfEntries - offset) % numberOfEntries];
+            if (entry.mCount == 0 || entry.mLastTime < limitNs) {
+                break;
+            }
+        }
+        if (offset > 0) {
+            offset--;
+            ss << prefix << " Code  Freq          First time           Last time\n";
+            for (; offset >= 0; --offset) {
+                const auto &entry =
+                        mEntries[(mIdx + numberOfEntries - offset) % numberOfEntries];
+
+                ss << prefix << std::setw(5) <<  entry.mCode
+                        << " " << std::setw(5) << entry.mCount
+                        << "  " << audio_utils_time_string_from_ns(entry.mFirstTime).time
+                        << "  " << audio_utils_time_string_from_ns(entry.mLastTime).time << "\n";
+            }
+        }
+        return ss.str();
+    }
+
+    /**
+     * \brief Dumps the log to a raw file descriptor.
+     * \param fd                file descriptor to use.
+     * \param prefix            the prefix to use for each line
+     *                          (generally a null terminated string of spaces).
+     * \param lines             maximum number of lines to output (0 disables).
+     * \param limitNs           limit dump to data more recent than limitNs (0 disables).
+     * \return
+     *   NO_ERROR on success or a negative number (-errno) on failure of write().
+     */
+    status_t dump(int fd, const char *prefix = "", size_t lines = 0, int64_t limitNs = 0) const
+    {
+        // thread safe but not necessarily serial with respect to concurrent dumps to the same fd.
+        const std::string s = dumpToString(prefix, lines, limitNs);
+        if (s.size() > 0 && write(fd, s.c_str(), s.size()) < 0) {
+            return -errno;
+        }
+        return NO_ERROR;
+    }
+
+    struct Entry {
+        Entry()
+            : mCode(0)
+            , mCount(0)
+            , mFirstTime(0)
+            , mLastTime(0)
+        {
+        }
+
+        // Initialize entry with code as the first error at the given time.
+        void setFirstError(T code, int64_t time) {
+            mCode = code;
+            mCount = 1;
+            mFirstTime = time;
+            mLastTime = time;
+        }
+
+        T mCode;            // error code
+        uint32_t mCount;    // number of consecutive errors of the same code.
+        int64_t mFirstTime; // first time of the error code.
+        int64_t mLastTime;  // last time of the error code.
+    };
+
+private:
+    mutable std::mutex mLock;     // monitor mutex
+    int64_t mErrors;              // total number of errors registered
+    size_t mIdx;                  // current index into mEntries (active)
+    const int64_t mAggregateNs;   // number of nanoseconds to aggregate consecutive error codes.
+    std::vector<Entry> mEntries;  // circular buffer of error entries.
+};
+
+} // namespace android
+
+#endif // __cplusplus
+
+// C API (see C++ API above for details)
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+typedef struct error_log_t error_log_t;
+
+/**
+ * \brief Creates an error log object
+ *
+ * \param entries           the length of error history.
+ * \param aggregate_ns      the maximum time in nanoseconds between identical error codes
+ *                          to be aggregated into a single entry.
+ * \return the error log object or NULL on failure.
+ */
+error_log_t *error_log_create(size_t entries, int64_t aggregate_ns);
+
+/**
+ * \brief Adds new error code to the error log.
+ *
+ * Consecutive errors with the same code will be aggregated if
+ * they occur within aggregate_ns.
+ *
+ * \param error_log         object returned by create, if NULL nothing happens.
+ * \param code              error code of type T.
+ * \param now_ns            current time in nanoseconds.
+ */
+void error_log_log(error_log_t *error_log, int32_t code, int64_t now_ns);
+
+/**
+ * \brief Dumps the log to a raw file descriptor.
+ * \param error_log         object returned by create, if NULL nothing happens.
+ * \param prefix            the prefix to use for each line
+ *                          (generally a null terminated string of spaces).
+ * \param fd                file descriptor to use.
+ * \param lines             maximum number of lines to output (0 disables).
+ * \param limit_ns          limit dump to data more recent than limit_ns (0 disables).
+ * \return
+ *   NO_ERROR on success or a negative number (-errno) on failure of write().
+ *   if power_log is NULL, BAD_VALUE is returned.
+ */
+int error_log_dump(
+        error_log_t *error_log, int fd, const char *prefix, size_t lines, int64_t limit_ns);
+
+/**
+ * \brief Destroys the error log object.
+ *
+ * \param error_log         object returned by create, if NULL nothing happens.
+ */
+void error_log_destroy(error_log_t *error_log);
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif // !ANDROID_AUDIO_ERROR_LOG_H
diff --git a/audio_utils/include/audio_utils/PowerLog.h b/audio_utils/include/audio_utils/PowerLog.h
new file mode 100644 (file)
index 0000000..1f5a8b7
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_POWER_LOG_H
+#define ANDROID_AUDIO_POWER_LOG_H
+
+#ifdef __cplusplus
+
+#include <mutex>
+#include <vector>
+#include <system/audio.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+/**
+ * PowerLog captures the audio data power (measured in dBFS) over time.
+ *
+ * For the purposes of power evaluation, the audio data is divided into "bins",
+ * and grouped by signals consisting of consecutive non-zero energy bins.
+ * The sum energy in dB of each signal is computed for comparison purposes.
+ *
+ * No distinction is made between channels in an audio frame; they are all
+ * summed together for energy purposes.
+ *
+ * The public methods are internally protected by a mutex to be thread-safe.
+ */
+class PowerLog {
+public:
+    /**
+     * \brief Creates a PowerLog object.
+     *
+     * \param sampleRate        sample rate of the audio data.
+     * \param channelCount      channel count of the audio data.
+     * \param format            format of the audio data. It must be allowed by
+     *                          audio_utils_is_compute_power_format_supported()
+     *                          else the constructor will abort.
+     * \param entries           total number of energy entries "bins" to use.
+     * \param framesPerEntry    total number of audio frames used in each entry.
+     */
+    PowerLog(uint32_t sampleRate,
+            uint32_t channelCount,
+            audio_format_t format,
+            size_t entries,
+            size_t framesPerEntry);
+
+    /**
+     * \brief Adds new audio data to the power log.
+     *
+     * \param buffer            pointer to the audio data buffer.
+     * \param frames            buffer size in audio frames.
+     * \param nowNs             current time in nanoseconds.
+     */
+    void log(const void *buffer, size_t frames, int64_t nowNs);
+
+    /**
+     * \brief Dumps the log to a std::string.
+     *
+     * \param lines             maximum number of lines to output (0 disables).
+     * \param limitNs           limit dump to data more recent than limitNs (0 disables).
+     * \return the std::string for the log.
+     */
+    std::string dumpToString(
+            const char *prefix = "", size_t lines = 0, int64_t limitNs = 0) const;
+
+    /**
+     * \brief Dumps the log to a raw file descriptor.
+     *
+     * \param fd                file descriptor to use.
+     * \param lines             maximum number of lines to output (0 disables).
+     * \param limitNs           limit dump to data more recent than limitNs (0 disables).
+     * \return
+     *   NO_ERROR on success or a negative number (-errno) on failure of write().
+     */
+    status_t dump(int fd, const char *prefix = "", size_t lines = 0, int64_t limitNs = 0) const;
+
+private:
+    mutable std::mutex mLock;     // monitor mutex
+    int64_t mCurrentTime;         // time of first frame in buffer
+    float mCurrentEnergy;         // local energy accumulation
+    size_t mCurrentFrames;        // number of frames in the energy
+    size_t mIdx;                  // next usable index in mEntries
+    size_t mConsecutiveZeroes;    // current run of consecutive zero entries
+    const uint32_t mSampleRate;   // audio data sample rate
+    const uint32_t mChannelCount; // audio data channel count
+    const audio_format_t mFormat; // audio data format
+    const size_t mFramesPerEntry; // number of audio frames per entry
+    std::vector<std::pair<int64_t /* real time ns */, float /* energy */>> mEntries;
+};
+
+} // namespace android
+
+#endif // __cplusplus
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+// C API (see C++ api above for details)
+
+typedef struct power_log_t power_log_t;
+
+/**
+ * \brief Creates a power log object.
+ *
+ * \param sample_rate       sample rate of the audio data.
+ * \param channel_count     channel count of the audio data.
+ * \param format            format of the audio data. It must be allowed by
+ *                          audio_utils_is_compute_power_format_supported().
+ * \param entries           total number of energy entries "bins" to use.
+ * \param frames_per_entry  total number of audio frames used in each entry.
+ *
+ * \return power log object or NULL on failure.
+ */
+power_log_t *power_log_create(uint32_t sample_rate,
+        uint32_t channel_count, audio_format_t format, size_t entries, size_t frames_per_entry);
+
+/**
+ * \brief Adds new audio data to the power log.
+ *
+ * \param power_log         object returned by create, if NULL nothing happens.
+ * \param buffer            pointer to the audio data buffer.
+ * \param frames            buffer size in audio frames.
+ * \param now_ns            current time in nanoseconds.
+ */
+void power_log_log(power_log_t *power_log, const void *buffer, size_t frames, int64_t now_ns);
+
+/**
+ * \brief Dumps the log to a raw file descriptor.
+ *
+ * \param power_log         object returned by create, if NULL nothing happens.
+ * \param fd                file descriptor to use.
+ * \param lines             maximum number of lines to output (0 disables).
+ * \param limit_ns          limit dump to data more recent than limit_ns (0 disables).
+ * \return
+ *   NO_ERROR on success or a negative number (-errno) on failure of write().
+ *   if power_log is NULL, BAD_VALUE is returned.
+ */
+int power_log_dump(
+        power_log_t *power_log, int fd, const char *prefix,  size_t lines, int64_t limit_ns);
+
+/**
+ * \brief Destroys the power log object.
+ *
+ * \param power_log         object returned by create, if NULL nothing happens.
+ */
+void power_log_destroy(power_log_t *power_log);
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif // !ANDROID_AUDIO_POWER_LOG_H
diff --git a/audio_utils/include/audio_utils/SimpleLog.h b/audio_utils/include/audio_utils/SimpleLog.h
new file mode 100644 (file)
index 0000000..d5fd021
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_SIMPLE_LOG_H
+#define ANDROID_AUDIO_SIMPLE_LOG_H
+
+#include <deque>
+#include <mutex>
+#include <sstream>
+#include <stdint.h>
+#include <string>
+#include <unistd.h>
+#include <utils/Errors.h>
+
+#include <audio_utils/clock.h>
+
+namespace android {
+
+/**
+ * SimpleLog provides a private logcat-style logging to avoid cluttering
+ * the device logcat.
+ *
+ * The public methods are internally protected by a mutex to be thread-safe.
+ * Do not call from a sched_fifo thread as it can use a system time call
+ * and obtains a local mutex.
+ *
+ * Formatted logs by log() and logv() will be truncated at kMaxStringLength - 1
+ * due to null termination. logs() does not have a string length limitation.
+ */
+
+class SimpleLog {
+public:
+    /**
+     * \brief Creates a SimpleLog object.
+     *
+     * \param maxLogLines the maximum number of log lines.
+     */
+    explicit SimpleLog(size_t maxLogLines = kDefaultMaxLogLines)
+        : mMaxLogLines(maxLogLines)
+    {
+    }
+
+    /**
+     * \brief Adds a formatted string into the log.
+     *
+     * Time is automatically associated with the string by audio_utils_get_real_time_ns().
+     *
+     * \param format            the format string, similar to printf().
+     *
+     * and optional arguments.
+     */
+    // using C++11 unified attribute syntax; index is offset by 1 for implicit "this".
+    [[gnu::format(printf, 2 /* string-index */, 3 /* first-to-check */)]]
+    void log(const char *format, ...)
+    {
+        va_list args;
+        va_start(args, format);
+        // use -1 to trigger the clock fetch within the mutex lock.
+        logv(-1 /* nowNs */, format, args);
+        va_end(args);
+    }
+
+    /**
+     * \brief Adds a formatted string into the log with time.
+     *
+     * \param nowNs             the time to use for logging. Assumed to be monotonically
+     *                          increasing for sequential calls.  If -1, then
+     *                          audio_utils_get_real_time_ns() is called.
+     * \param format            the format string, similar to printf().
+     *
+     * and optional arguments.
+     */
+    // using C++11 unified attribute syntax; index is offset by 1 for implicit "this".
+    [[gnu::format(printf, 3 /* string-index */, 4 /* first-to-check */)]]
+    void log(int64_t nowNs, const char *format, ...)
+    {
+        va_list args;
+        va_start(args, format);
+        logv(nowNs, format, args);
+        va_end(args);
+    }
+
+    /**
+     * \brief Adds a formatted string by va_list with time.  Not intended for typical use.
+     *
+     * \param nowNs             the time to use for logging. Assumed to be monotonically
+     *                          increasing for sequential calls.  If -1, then
+     *                          audio_utils_get_real_time_ns() is called.
+     * \param format            the format string, similar to printf().
+     * \param args              va_list args.
+     */
+    void logv(int64_t nowNs, const char *format, va_list args)
+    {
+        // format to buffer
+        char buffer[kMaxStringLength];
+        int length = vsnprintf(buffer, sizeof(buffer), format, args);
+        if (length < 0) { // encoding error
+            logs(nowNs, "invalid format");
+            return;
+        } else if (length >= (signed)sizeof(buffer)) {
+            length = sizeof(buffer) - 1;
+        }
+
+        // strip out trailing newlines
+        while (length > 0 && buffer[length - 1] == '\n') {
+            buffer[--length] = '\0';
+        }
+        logs(nowNs, buffer);
+    }
+
+    /**
+     * \brief Logs a string to the buffer with time.
+     * \param nowNs             the time to use for logging. Assumed to be monotonically
+     *                          increasing for sequential calls.  If -1, then
+     *                          audio_utils_get_real_time_ns() is called.
+     * \param buffer            contains a null terminated string, which may have
+     *                          special characters such as % and \ that are
+     *                          not interpreted.
+     */
+    void logs(int64_t nowNs, const char *buffer)
+    {
+        // store in circular array
+        std::lock_guard<std::mutex> guard(mLock);
+        if (nowNs == -1) {
+            nowNs = audio_utils_get_real_time_ns();
+        }
+        mLog.emplace_back(nowNs, std::string(buffer));
+        if (mLog.size() > mMaxLogLines) {
+            mLog.pop_front();
+        }
+    }
+
+    /**
+     * \brief Dumps the log to a string.
+     *
+     * \param prefix            the prefix to use for each line
+     *                          (generally a null terminated string of spaces).
+     * \param lines             maximum number of lines to output (0 disables).
+     * \param limitNs           limit dump to data more recent than limitNs (0 disables).
+     * \return a string object for the log.
+     */
+    std::string dumpToString(const char *prefix = "", size_t lines = 0, int64_t limitNs = 0) const
+    {
+        if (lines == 0) {
+            lines = mLog.size();
+        }
+
+        std::stringstream ss;
+        std::lock_guard<std::mutex> guard(mLock);
+        auto it = mLog.begin();
+
+        // Note: this restricts the lines before checking the time constraint.
+        if (mLog.size() > lines) {
+            it += (mLog.size() - lines);
+        }
+        for (; it != mLog.end(); ++it) {
+            const int64_t time = it->first;
+            if (time < limitNs) continue;  // too old
+            ss << prefix << audio_utils_time_string_from_ns(time).time
+                    << " " << it->second.c_str() << "\n";
+        }
+        return ss.str();
+    }
+
+    /**
+     * \brief Dumps the log to a raw file descriptor.
+     *
+     * \param fd                file descriptor to use.
+     * \param prefix            the prefix to use for each line
+     *                          (generally a null terminated string of spaces).
+     * \param lines             maximum number of lines to output (0 disables).
+     * \param limitNs           limit dump to data more recent than limitNs (0 disables).
+     * \return
+     *   NO_ERROR on success or a negative number (-errno) on failure of write().
+     */
+    status_t dump(int fd, const char *prefix = "", size_t lines = 0, int64_t limitNs = 0) const
+    {
+        // dumpToString() and write() are individually thread-safe, but concurrent threads
+        // using dump() to the same file descriptor may write out of order.
+        const std::string s = dumpToString(prefix, lines, limitNs);
+        if (s.size() > 0 && write(fd, s.c_str(), s.size()) < 0) {
+            return -errno;
+        }
+        return NO_ERROR;
+    }
+
+private:
+    mutable std::mutex mLock;
+    static const size_t kMaxStringLength = 1024;  // maximum formatted string length
+    static const size_t kDefaultMaxLogLines = 80; // default maximum log history
+
+    const size_t mMaxLogLines;                    // maximum log history
+    std::deque<std::pair<int64_t, std::string>> mLog; // circular buffer is backed by deque.
+};
+
+} // namespace android
+
+#endif // !ANDROID_AUDIO_SIMPLE_LOG_H
diff --git a/audio_utils/include/audio_utils/clock.h b/audio_utils/include/audio_utils/clock.h
new file mode 100644 (file)
index 0000000..31bf1f6
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_CLOCK_H
+#define ANDROID_AUDIO_CLOCK_H
+
+// This file can be included for either C or C++ source.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+
+/**
+ * \brief Converts time in ns to a time string, with format similar to logcat.
+ * \param ns          input time in nanoseconds to convert.
+ * \param buffer      caller allocated string buffer, buffer_length must be >= 19 chars
+ *                    in order to fully fit in time.  The string is always returned
+ *                    null terminated if buffer_size is greater than zero.
+ * \param buffer_size size of buffer.
+ */
+static inline void audio_utils_ns_to_string(int64_t ns, char *buffer, size_t buffer_size)
+{
+    if (buffer_size == 0) return;
+
+    const int one_second = 1000000000;
+    const time_t sec = ns / one_second;
+    struct tm tm;
+
+    // Supported on bionic, glibc, and macOS, but not mingw.
+    if (localtime_r(&sec, &tm) == NULL) {
+        buffer[0] = '\0';
+        return;
+    }
+
+    if (snprintf(buffer, buffer_size, "%02d-%02d %02d:%02d:%02d.%03d",
+        tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
+        tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
+        (int)(ns % one_second / 1000000)) < 0) {
+        buffer[0] = '\0'; // null terminate on format error, which should not happen
+    }
+}
+
+/**
+ * An object that contains the formatted time string.
+ *
+ * The time string is 19 characters (including null termination).
+ * Example: "03-27 16:47:06.187"
+ *           MM DD HH MM SS MS
+ */
+typedef struct audio_utils_time_string {
+    char time[19]; /* minimum size buffer */
+} audio_utils_time_string_t;
+
+/**
+ * \brief Converts time in ns to a time string object, with format similar to logcat.
+ * \param ns          input time in nanoseconds to convert.
+ */
+static inline audio_utils_time_string_t audio_utils_time_string_from_ns(int64_t ns)
+{
+    audio_utils_time_string_t ts;
+
+    audio_utils_ns_to_string(ns, ts.time, sizeof(ts.time));
+    return ts;
+}
+
+/**
+ * \brief Converts a timespec to nanoseconds.
+ * \param ts   input timespec to convert.
+ * \return     timespec converted to nanoseconds.
+ */
+static inline int64_t audio_utils_ns_from_timespec(const struct timespec *ts)
+{
+    return ts->tv_sec * 1000000000LL + ts->tv_nsec;
+}
+
+/**
+ * \brief Gets the real time clock in nanoseconds.
+ * \return the real time clock in nanoseconds, or 0 on error.
+ */
+static inline int64_t audio_utils_get_real_time_ns() {
+
+#if defined(__linux__)
+
+    struct timespec now_ts;
+    if (clock_gettime(CLOCK_REALTIME, &now_ts) == 0) {
+        return audio_utils_ns_from_timespec(&now_ts);
+    }
+    return 0; // should not happen.
+
+#else
+
+    // Mac OS X compatible
+    struct timeval now_tv;
+    if (gettimeofday(&now_tv, NULL /* struct timezone * */) == 0) {
+        return now_tv.tv_sec * 1000000000LL + now_tv.tv_usec * 1000LL;
+    }
+    return 0; // should not happen.
+
+#endif
+
+}
+
+#endif  // !ANDROID_AUDIO_CLOCK_H
diff --git a/audio_utils/include/audio_utils/clock_nanosleep.h b/audio_utils/include/audio_utils/clock_nanosleep.h
new file mode 100644 (file)
index 0000000..e39c0ab
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_CLOCK_NANOSLEEP_H
+#define ANDROID_AUDIO_CLOCK_NANOSLEEP_H
+
+#include <time.h>
+#include <unistd.h>
+
+#ifdef __linux__
+
+#include <sys/syscall.h>
+#ifdef __ANDROID__
+// bionic for Android provides clock_nanosleep
+#define audio_utils_clock_nanosleep clock_nanosleep
+#else
+// bionic for desktop Linux omits clock_nanosleep
+static inline
+int audio_utils_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request,
+        struct timespec *remain)
+{
+    return syscall(SYS_clock_nanosleep, clock_id, flags, request, remain);
+}
+#endif  // __ANDROID__
+
+#else   // __linux__
+
+// macOS <10.12 doesn't have clockid_t / CLOCK_MONOTONIC
+#ifndef CLOCK_MONOTONIC
+typedef int clockid_t;
+#define CLOCK_MONOTONIC 0
+#endif
+// macOS doesn't have clock_nanosleep
+static inline
+int audio_utils_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request,
+        struct timespec *remain)
+{
+    (void) clock_id;
+    (void) flags;
+    (void) request;
+    (void) remain;
+    errno = ENOSYS;
+    return -1;
+}
+
+#endif  // __linux__
+
+#endif  // !ANDROID_AUDIO_CLOCK_NANOSLEEP_H
index f882368..14b50da 100644 (file)
 #ifndef ANDROID_AUDIO_FIFO_H
 #define ANDROID_AUDIO_FIFO_H
 
+#include <atomic>
 #include <stdlib.h>
+#include <audio_utils/fifo_index.h>
 
-// FIXME use atomic_int_least32_t and new atomic operations instead of legacy Android ones
-// #include <stdatomic.h>
-
-#ifdef __cplusplus
-extern "C" {
+#ifndef __cplusplus
+#error C API is no longer supported
 #endif
 
-// Single writer, single reader non-blocking FIFO.
-// Writer and reader must be in same process.
+/** Indicates whether an index is also used for synchronization. */
+enum audio_utils_fifo_sync {
+    /** Index is not also used for synchronization; timeouts are done via clock_nanosleep(). */
+    AUDIO_UTILS_FIFO_SYNC_SLEEP,
+    /** Index is also used for synchronization as futex, and is mapped by one process. */
+    AUDIO_UTILS_FIFO_SYNC_PRIVATE,
+    /** Index is also used for synchronization as futex, and is mapped by one or more processes. */
+    AUDIO_UTILS_FIFO_SYNC_SHARED,
+};
+
+/**
+ * Base class for single-writer, single-reader or multi-reader, optionally blocking FIFO.
+ * The base class manipulates frame indices only, and has no knowledge of frame sizes or the buffer.
+ * At most one reader, called the "throttling reader", can block the writer.
+ * The "fill level", or unread frame count, is defined with respect to the throttling reader.
+ */
+class audio_utils_fifo_base {
+
+public:
+
+    /**
+     * Return the capacity, or statically configured maximum frame count.
+     *
+     * \return The capacity in frames.
+     */
+    uint32_t capacity() const
+            { return mFrameCount; }
+
+protected:
+
+    /**
+     * Construct FIFO base class
+     *
+     *  \param frameCount    Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX,
+     *                       aka "capacity".
+     *                       If release()s always use the same count, and the count is a divisor of
+     *                       (effective) \p frameCount, then the obtain()s won't ever be fragmented.
+     *  \param writerRear    Writer's rear index.  Passed by reference because it must be non-NULL.
+     *  \param throttleFront Pointer to the front index of at most one reader that throttles the
+     *                       writer, or NULL for no throttling.
+     */
+    audio_utils_fifo_base(uint32_t frameCount, audio_utils_fifo_index& writerRear,
+            audio_utils_fifo_index *throttleFront = NULL);
+    /*virtual*/ ~audio_utils_fifo_base();
+
+    /** Return a new index as the sum of a validated index and a specified increment.
+     *
+     * \param index     Caller should supply a validated mFront or mRear.
+     * \param increment Value to be added to the index <= mFrameCount.
+     *
+     * \return The sum of index plus increment.
+     */
+    uint32_t sum(uint32_t index, uint32_t increment) const;
+
+    /** Return the difference between two indices: rear - front.
+     *
+     * \param rear  Caller should supply an unvalidated mRear.
+     * \param front Caller should supply an unvalidated mFront.
+     * \param lost  If non-NULL, set to the approximate number of frames lost before
+     *              re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
+     * \param flush Whether to flush the entire buffer on -EOVERFLOW.
+     *
+     * \return The zero or positive difference <= mFrameCount, or a negative error code.
+     * \retval -EIO        corrupted indices, no recovery is possible
+     * \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
+     *                     isn't keeping up with writer; see \p lost
+     */
+    int32_t diff(uint32_t rear, uint32_t front, size_t *lost = NULL, bool flush = false) const;
+
+    /**
+     * Mark the FIFO as shutdown (permanently unusable), usually due to an -EIO status from an API.
+     * Thereafter, all APIs that return a status will return -EIO, and other APIs will be no-ops.
+     */
+    void shutdown() const;
 
-// No user-serviceable parts within.
-struct audio_utils_fifo {
     // These fields are const after initialization
-    size_t     mFrameCount;   // max number of significant frames to be stored in the FIFO > 0
-    size_t     mFrameCountP2; // roundup(mFrameCount)
-    size_t     mFudgeFactor;  // mFrameCountP2 - mFrameCount, the number of "wasted" frames after
-                              // the end of mBuffer.  Only the indices are wasted, not any memory.
-    size_t     mFrameSize;    // size of each frame in bytes
-    void      *mBuffer;       // pointer to caller-allocated buffer of size mFrameCount frames
-
-    volatile int32_t mFront; // frame index of first frame slot available to read, or read index
-    volatile int32_t mRear;  // frame index of next frame slot available to write, or write index
+
+    /** Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX, aka "capacity". */
+    const uint32_t mFrameCount;
+    /** Equal to roundup(mFrameCount). */
+    const uint32_t mFrameCountP2;
+
+    /**
+     * Equal to mFrameCountP2 - mFrameCount, the number of "wasted" frames after the end of mBuffer.
+     * Only the indices are wasted, not any memory.
+     */
+    const uint32_t mFudgeFactor;
+
+    /** Reference to writer's rear index. */
+    audio_utils_fifo_index&         mWriterRear;
+    /** Indicates how synchronization is done for mWriterRear. */
+    const audio_utils_fifo_sync     mWriterRearSync;
+
+    /**
+     * Pointer to the front index of at most one reader that throttles the writer,
+     * or NULL for no throttling.
+     */
+    audio_utils_fifo_index* const   mThrottleFront;
+    /** Indicates how synchronization is done for mThrottleFront. */
+    const audio_utils_fifo_sync     mThrottleFrontSync;
+
+    /** Whether FIFO is marked as shutdown due to detection of an "impossible" error condition. */
+    mutable bool                    mIsShutdown;
 };
 
+////////////////////////////////////////////////////////////////////////////////
+
 /**
- * Initialize a FIFO object.
- *
- *  \param fifo        Pointer to the FIFO object.
- *  \param frameCount  Max number of significant frames to be stored in the FIFO > 0.
- *                     If writes and reads always use the same count, and that count is a divisor of
- *                     frameCount, then the writes and reads will never do a partial transfer.
- *  \param frameSize   Size of each frame in bytes.
- *  \param buffer      Pointer to a caller-allocated buffer of frameCount frames.
+ * Same as audio_utils_fifo_base, but understands frame sizes and knows about the buffer but does
+ * not own it.
  */
-void audio_utils_fifo_init(struct audio_utils_fifo *fifo, size_t frameCount, size_t frameSize,
-        void *buffer);
+class audio_utils_fifo : public audio_utils_fifo_base {
+
+    friend class audio_utils_fifo_reader;
+    friend class audio_utils_fifo_writer;
+
+public:
+
+    /**
+     * Construct a FIFO object: multi-process.
+     *
+     *  \param frameCount  Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX,
+     *                     aka "capacity".
+     *                     If writes and reads always use the same count, and the count is a divisor
+     *                     of \p frameCount, then the writes and reads won't do a partial transfer.
+     *  \param frameSize   Size of each frame in bytes > 0,
+     *                     \p frameSize * \p frameCount <= INT32_MAX.
+     *  \param buffer      Pointer to a non-NULL caller-allocated buffer of \p frameCount frames.
+     *  \param writerRear  Writer's rear index.  Passed by reference because it must be non-NULL.
+     *  \param throttleFront Pointer to the front index of at most one reader that throttles the
+     *                       writer, or NULL for no throttling.
+     */
+    audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
+            audio_utils_fifo_index& writerRear, audio_utils_fifo_index *throttleFront = NULL);
+
+    /**
+     * Construct a FIFO object: single-process.
+     *  \param frameCount  Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX,
+     *                     aka "capacity".
+     *                     If writes and reads always use the same count, and the count is a divisor
+     *                     of \p frameCount, then the writes and reads won't do a partial transfer.
+     *  \param frameSize   Size of each frame in bytes > 0,
+     *                     \p frameSize * \p frameCount <= INT32_MAX.
+     *  \param buffer      Pointer to a non-NULL caller-allocated buffer of \p frameCount frames.
+     *  \param throttlesWriter Whether there is one reader that throttles the writer.
+     */
+    audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
+            bool throttlesWriter = true);
+
+    /*virtual*/ ~audio_utils_fifo();
+
+    /**
+     * Return the frame size in bytes.
+     *
+     * \return frame size in bytes, always > 0.
+     */
+    uint32_t frameSize() const
+            { return mFrameSize; }
+
+    /**
+     * Return a pointer to the caller-allocated buffer.
+     *
+     * \return non-NULL pointer to buffer.
+     */
+    void *buffer() const
+            { return mBuffer; }
+
+private:
+    // These fields are const after initialization
+    const uint32_t mFrameSize;  // size of each frame in bytes
+    void * const   mBuffer;     // non-NULL pointer to caller-allocated buffer
+                                // of size mFrameCount frames
+
+    // only used for single-process constructor
+    audio_utils_fifo_index      mSingleProcessSharedRear;
+
+    // only used for single-process constructor when throttlesWriter == true
+    audio_utils_fifo_index      mSingleProcessSharedFront;
+};
 
 /**
- * De-initialize a FIFO object.
- *
- *  \param fifo        Pointer to the FIFO object.
+ * Describes one virtually contiguous fragment of a logically contiguous slice.
+ * Compare to struct iovec for readv(2) and writev(2).
  */
-void audio_utils_fifo_deinit(struct audio_utils_fifo *fifo);
+struct audio_utils_iovec {
+    /** Offset of fragment in frames, relative to mBuffer, undefined if mLength == 0 */
+    uint32_t    mOffset;
+    /** Length of fragment in frames, 0 means fragment is empty */
+    uint32_t    mLength;
+};
+
+////////////////////////////////////////////////////////////////////////////////
 
 /**
- * Write to FIFO.
- *
- *  \param fifo        Pointer to the FIFO object.
- *  \param buffer      Pointer to source buffer containing 'count' frames of data.
- *  \param count       Desired number of frames to write.
- *
- * \return actual number of frames written <= count.
- *
- * The actual transfer count may be zero if the FIFO is full,
- * or partial if the FIFO was almost full.
- * A negative return value indicates an error.  Currently there are no errors defined.
+ * Based on frameworks/av/include/media/AudioBufferProvider.h
  */
-ssize_t audio_utils_fifo_write(struct audio_utils_fifo *fifo, const void *buffer, size_t count);
+class audio_utils_fifo_provider {
+public:
+    audio_utils_fifo_provider(audio_utils_fifo& fifo);
+    virtual ~audio_utils_fifo_provider();
 
-/** Read from FIFO.
- *
- *  \param fifo        Pointer to the FIFO object.
- *  \param buffer      Pointer to destination buffer to be filled with up to 'count' frames of data.
- *  \param count       Desired number of frames to read.
- *
- * \return actual number of frames read <= count.
- *
- * The actual transfer count may be zero if the FIFO is empty,
- * or partial if the FIFO was almost empty.
- * A negative return value indicates an error.  Currently there are no errors defined.
+    /**
+     * Obtain access to a logically contiguous slice of a stream, represented by \p iovec.
+     * For the reader(s), the slice is initialized and has read-only access.
+     * For the writer, the slice is uninitialized and has read/write access.
+     * It is permitted to call obtain() multiple times without an intervening release().
+     * Each call resets the notion of most recently obtained slice.
+     *
+     * \param iovec Non-NULL pointer to a pair of fragment descriptors.
+     *              On entry, the descriptors may be uninitialized.
+     *              On exit, the descriptors are initialized and refer to each of the two fragments.
+     *              iovec[0] describes the initial fragment of the slice, and
+     *              iovec[1] describes the remaining non-virtually-contiguous fragment.
+     *              Empty iovec[0] implies that iovec[1] is also empty.
+     *              iovec[0].mOffset and iovec[1].mOffset are always < capacity.
+     *              Typically iovec[1].mOffset is zero, but don't assume that.
+     * \param count The maximum number of frames to obtain.
+     *              See setHysteresis() for something which is close to, but not the same as,
+     *              a minimum.
+     * \param timeout Indicates the maximum time to block for at least one frame.
+     *                NULL and {0, 0} both mean non-blocking.
+     *                Time is expressed as relative CLOCK_MONOTONIC.
+     *                As an optimization, if \p timeout->tv_sec is the maximum positive value for
+     *                time_t (LONG_MAX), then the implementation treats it as infinite timeout.
+     *                See fifo_index.h for explanation of why representation is struct timespec.
+     *
+     * \return Actual number of frames available, if greater than or equal to zero.
+     *         Guaranteed to be <= \p count and == iovec[0].mLength + iovec[1].mLength.
+     *
+     *  \retval -EIO        corrupted indices, no recovery is possible
+     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
+     *                      isn't keeping up with writer; see \p lost
+     *  \retval -ETIMEDOUT  count is greater than zero, timeout is non-NULL and not {0, 0},
+     *                      timeout expired, and no frames were available after the timeout.
+     *  \retval -EINTR      count is greater than zero, timeout is non-NULL and not {0, 0}, timeout
+     *                      was interrupted by a signal, and no frames were available after signal.
+     *  \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0},
+     *                      futex wait failed due to benign race, and unable to converge after
+     *                      retrying.  Should usually handle like -EINTR.
+     *
+     * Applications should treat all of these as equivalent to zero available frames,
+     * except they convey extra information as to the cause.
+     * After any error, both iovec[0] and iovec[1] will be empty.
+     */
+    virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count,
+            const struct timespec *timeout = NULL) = 0;
+
+    /**
+     * Release access to a portion of the most recently obtained slice.
+     * It is permitted to call release() multiple times without an intervening obtain().
+     *
+     * \param count Number of frames to release.  The cumulative number of frames released must not
+     *              exceed the number of frames most recently obtained.
+     *              If it ever happens, then the FIFO will be marked unusable with shutdown().
+     */
+    virtual void release(size_t count) = 0;
+
+    /**
+     * Determine the number of frames that could be obtained or read/written without blocking.
+     * There's an inherent race condition: the value may soon be obsolete so shouldn't be trusted.
+     * available() may be called after obtain(), but doesn't affect the number of releasable frames.
+     *
+     * \return Number of available frames, if greater than or equal to zero.
+     *  \retval -EIO        corrupted indices, no recovery is possible
+     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
+     *                      isn't keeping up with writer
+     */
+    virtual ssize_t available() = 0;
+
+    /**
+     * Return the capacity, or statically configured maximum frame count.
+     *
+     * \return The capacity in frames.
+     */
+    uint32_t capacity() const
+            { return mFifo.capacity(); }
+
+    /**
+     * Return the total number of frames released since construction.
+     * For a reader, this includes lost and flushed frames.
+     *
+     * \return Total frames released.
+     */
+    uint64_t totalReleased() const
+            { return mTotalReleased; }
+
+protected:
+    audio_utils_fifo&   mFifo;
+
+    /** Number of frames obtained at most recent obtain(), less total number of frames released. */
+    uint32_t    mObtained;
+
+    /** Number of times to retry a futex wait that fails with EWOULDBLOCK. */
+    static const int kRetries = 2;
+
+    /**
+     * Total number of frames released since construction.
+     * For a reader, this includes lost and flushed frames.
+     */
+    uint64_t    mTotalReleased;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Used to write to a FIFO.  There should be exactly one writer per FIFO.
+ * The writer is multi-thread safe with respect to reader(s),
+ * but not with respect to multiple threads calling the writer API.
  */
-ssize_t audio_utils_fifo_read(struct audio_utils_fifo *fifo, void *buffer, size_t count);
+class audio_utils_fifo_writer : public audio_utils_fifo_provider {
 
-#ifdef __cplusplus
-}
-#endif
+public:
+    /**
+     * Single-process and multi-process use same constructor here,
+     * but different FIFO constructors.
+     *
+     * \param fifo Associated FIFO.  Passed by reference because it must be non-NULL.
+     */
+    explicit audio_utils_fifo_writer(audio_utils_fifo& fifo);
+    virtual ~audio_utils_fifo_writer();
+
+    /**
+     * Write to FIFO.  Resets the number of releasable frames to zero.
+     *
+     * \param buffer  Pointer to source buffer containing \p count frames of data.
+     *                Pointer must be non-NULL if \p count is greater than zero.
+     * \param count   Desired number of frames to write.
+     * \param timeout Indicates the maximum time to block for at least one frame.
+     *                NULL and {0, 0} both mean non-blocking.
+     *                Time is expressed as relative CLOCK_MONOTONIC.
+     *                As an optimization, if \p timeout->tv_sec is the maximum positive value for
+     *                time_t (LONG_MAX), then the implementation treats it as infinite timeout.
+     *                See fifo_index.h for explanation of why representation is struct timespec.
+     *
+     * \return Actual number of frames written, if greater than or equal to zero.
+     *         Guaranteed to be <= \p count.
+     *         The actual transfer count may be zero if the FIFO is full,
+     *         or partial if the FIFO was almost full.
+     *  \retval -EIO       corrupted indices, no recovery is possible
+     *  \retval -ETIMEDOUT count is greater than zero, timeout is non-NULL and not {0, 0},
+     *                     timeout expired, and no frames were available after the timeout.
+     *  \retval -EINTR     count is greater than zero, timeout is non-NULL and not {0, 0}, timeout
+     *                     was interrupted by a signal, and no frames were available after signal.
+     *  \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0},
+     *                      futex wait failed due to benign race, and unable to converge after
+     *                      retrying.  Should usually handle like -EINTR.
+     */
+    ssize_t write(const void *buffer, size_t count, const struct timespec *timeout = NULL);
+
+    // Implement audio_utils_fifo_provider
+    virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count,
+            const struct timespec *timeout = NULL);
+    virtual void release(size_t count);
+    virtual ssize_t available();
+
+    /**
+     * Set the current effective buffer size.
+     * Any filled frames already written or released to the buffer are unaltered, and pending
+     * releasable frames from obtain() may be release()ed.  However subsequent write() and obtain()
+     * will be limited such that the total filled frame count is <= the effective buffer size.
+     * The default effective buffer size is mFifo.mFrameCount.
+     * Reducing the effective buffer size may update the hysteresis levels; see getHysteresis().
+     *
+     * \param frameCount    effective buffer size in frames. Capped to range [0, mFifo.mFrameCount].
+     */
+    void resize(uint32_t frameCount);
+
+    /**
+     * Get the current effective buffer size.
+     * This value is not exposed to reader(s), and so must be conveyed via an out-of-band channel.
+     *
+     * \return effective buffer size in frames
+     */
+    uint32_t size() const;
+
+    /**
+     * Set the hysteresis levels for the writer to wake blocked readers.
+     * Hysteresis can decrease the number of context switches between writer and a blocking reader.
+     * A non-empty write() or release() will wake readers
+     * only if the fill level was < \p armLevel before the write() or release(),
+     * and then the fill level became > \p triggerLevel afterwards.
+     * The default value for \p armLevel is mFifo.mFrameCount, which means always armed.
+     * The default value for \p triggerLevel is zero,
+     * which means every write() or release() will wake the readers.
+     * For hysteresis, \p armLevel must be <= \p triggerLevel + 1.
+     * Increasing \p armLevel will arm for wakeup, regardless of the current fill level.
+     *
+     * \param armLevel      Arm for wakeup when fill level < this value.
+     *                      Capped to range [0, effective buffer size].
+     * \param triggerLevel  Trigger wakeup when armed and fill level > this value.
+     *                      Capped to range [0, effective buffer size].
+     */
+    void setHysteresis(uint32_t armLevel, uint32_t triggerLevel);
+
+    /**
+     * Get the hysteresis levels for waking readers.
+     *
+     * \param armLevel      Set to the current arm level in frames.
+     * \param triggerLevel  Set to the current trigger level in frames.
+     */
+    void getHysteresis(uint32_t *armLevel, uint32_t *triggerLevel) const;
+
+private:
+    // Accessed by writer only using ordinary operations
+    uint32_t    mLocalRear; // frame index of next frame slot available to write, or write index
+
+    // TODO make a separate class and associate with the synchronization object
+    uint32_t    mArmLevel;          // arm if filled < arm level before release()
+    uint32_t    mTriggerLevel;      // trigger if armed and filled > trigger level after release()
+    bool        mIsArmed;           // whether currently armed
+
+    uint32_t    mEffectiveFrames;   // current effective buffer size, <= mFifo.mFrameCount
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Used to read from a FIFO.  There can be one or more readers per FIFO,
+ * and at most one of those readers can throttle the writer.
+ * All other readers must keep up with the writer or they will lose frames.
+ * Each reader is multi-thread safe with respect to the writer and any other readers,
+ * but not with respect to multiple threads calling the reader API.
+ */
+class audio_utils_fifo_reader : public audio_utils_fifo_provider {
+
+public:
+    /**
+     * Single-process and multi-process use same constructor here,
+     * but different FIFO constructors.
+     *
+     * \param fifo            Associated FIFO.  Passed by reference because it must be non-NULL.
+     * \param throttlesWriter Whether this reader throttles the writer.
+     *                        At most one reader can specify throttlesWriter == true.
+     *                        A non-throttling reader does not see any data written
+     *                        prior to construction of the reader.
+     * \param flush           Whether to flush (discard) the entire buffer on -EOVERFLOW.
+     *                        The advantage of flushing is that it increases the chance that next
+     *                        read will be successful.  The disadvantage is that it loses more data.
+     */
+    explicit audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter = true,
+                                     bool flush = false);
+    virtual ~audio_utils_fifo_reader();
+
+    /**
+     * Read from FIFO.  Resets the number of releasable frames to zero.
+     *
+     * \param buffer  Pointer to destination buffer to be filled with up to \p count frames of data.
+     *                Pointer must be non-NULL if \p count is greater than zero.
+     * \param count   Desired number of frames to read.
+     * \param timeout Indicates the maximum time to block for at least one frame.
+     *                NULL and {0, 0} both mean non-blocking.
+     *                Time is expressed as relative CLOCK_MONOTONIC.
+     *                As an optimization, if \p timeout->tv_sec is the maximum positive value for
+     *                time_t (LONG_MAX), then the implementation treats it as infinite timeout.
+     *                See fifo_index.h for explanation of why representation is struct timespec.
+     * \param lost    If non-NULL, set to the approximate number of frames lost before
+     *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
+     *
+     * \return Actual number of frames read, if greater than or equal to zero.
+     *         Guaranteed to be <= \p count.
+     *         The actual transfer count may be zero if the FIFO is empty,
+     *         or partial if the FIFO was almost empty.
+     *  \retval -EIO        corrupted indices, no recovery is possible
+     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
+     *                      isn't keeping up with writer; see \p lost
+     *  \retval -ETIMEDOUT  count is greater than zero, timeout is non-NULL and not {0, 0},
+     *                      timeout expired, and no frames were available after the timeout.
+     *  \retval -EINTR      count is greater than zero, timeout is non-NULL and not {0, 0}, timeout
+     *                      was interrupted by a signal, and no frames were available after signal.
+     *  \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0},
+     *                      futex wait failed due to benign race, and unable to converge after
+     *                      retrying.  Should usually handle like -EINTR.
+     */
+    ssize_t read(void *buffer, size_t count, const struct timespec *timeout = NULL,
+            size_t *lost = NULL);
+
+    // Implement audio_utils_fifo_provider
+    virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count,
+            const struct timespec *timeout = NULL);
+    virtual void release(size_t count);
+    virtual ssize_t available();
+
+    /**
+     * Same as audio_utils_fifo_provider::obtain, except has an additional parameter \p lost.
+     *
+     * \param iovec   See audio_utils_fifo_provider::obtain.
+     * \param count   See audio_utils_fifo_provider::obtain.
+     * \param timeout See audio_utils_fifo_provider::obtain.
+     * \param lost    If non-NULL, set to the approximate number of frames lost before
+     *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
+     * \return See audio_utils_fifo_provider::obtain for 'Returns' and 'Return values'.
+     */
+    ssize_t obtain(audio_utils_iovec iovec[2], size_t count, const struct timespec *timeout,
+            size_t *lost);
+
+    /**
+     * Determine the number of frames that could be obtained or read without blocking.
+     * There's an inherent race condition: the value may soon be obsolete so shouldn't be trusted.
+     * available() may be called after obtain(), but doesn't affect the number of releasable frames.
+     *
+     * \param lost    If non-NULL, set to the approximate number of frames lost before
+     *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
+     *
+     * \return Number of available frames, if greater than or equal to zero.
+     *  \retval -EIO        corrupted indices, no recovery is possible
+     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
+     *                      isn't keeping up with writer; see \p lost
+     */
+    ssize_t available(size_t *lost);
+
+    /**
+     * Flush (discard) all frames that could be obtained or read without blocking.
+     * Note that flush is a method on a reader, so if the writer wants to flush
+     * then it must communicate the request to the reader(s) via an out-of-band channel.
+     *
+     * \param lost    If non-NULL, set to the approximate number of frames lost before
+     *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
+     *
+     * \return Number of flushed frames, if greater than or equal to zero.
+     *         This number does not include any lost frames.
+     *  \retval -EIO        corrupted indices, no recovery is possible
+     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
+     *                      isn't keeping up with writer; see \p lost
+     */
+    ssize_t flush(size_t *lost = NULL);
+
+    /**
+     * Set the hysteresis levels for a throttling reader to wake a blocked writer.
+     * Hysteresis can decrease the number of context switches between reader and a blocking writer.
+     * A non-empty read() or release() by a throttling reader will wake the writer
+     * only if the fill level was > \p armLevel before the read() or release(),
+     * and then the fill level became < \p triggerLevel afterwards.
+     * The default value for \p armLevel is -1, which means always armed.
+     * The default value for \p triggerLevel is mFifo.mFrameCount,
+     * which means every read() or release() will wake the writer.
+     * For hysteresis, \p armLevel must be >= \p triggerLevel - 1.
+     * Decreasing \p armLevel will arm for wakeup, regardless of the current fill level.
+     * Note that the throttling reader is not directly aware of the writer's effective buffer size,
+     * so any change in effective buffer size must be communicated indirectly.
+     *
+     * \param armLevel      Arm for wakeup when fill level > this value.
+     *                      Capped to range [-1, mFifo.mFrameCount].
+     * \param triggerLevel  Trigger wakeup when armed and fill level < this value.
+     *                      Capped to range [0, mFifo.mFrameCount].
+     */
+    void setHysteresis(int32_t armLevel, uint32_t triggerLevel);
+
+    /**
+     * Get the hysteresis levels for waking readers.
+     *
+     * \param armLevel      Set to the current arm level in frames.
+     * \param triggerLevel  Set to the current trigger level in frames.
+     */
+    void getHysteresis(int32_t *armLevel, uint32_t *triggerLevel) const;
+
+    /**
+     * Return the total number of lost frames since construction, due to reader not keeping up with
+     * writer.  Does not include flushed frames.
+     * It is necessary to call read(), obtain(), or flush() prior to calling this method,
+     * in order to observe an increase in the total,
+     * but it is not necessary for the 'lost' parameter of those prior calls to be non-NULL.
+     *
+     * \return Total lost frames.
+     */
+    uint64_t totalLost() const
+            { return mTotalLost; }
+
+    /**
+     * Return the total number of flushed frames since construction.
+     * Does not include lost frames.
+     *
+     * \return Total flushed frames.
+     */
+    uint64_t totalFlushed() const
+            { return mTotalFlushed; }
+
+private:
+    // Accessed by reader only using ordinary operations
+    uint32_t     mLocalFront;   // frame index of first frame slot available to read, or read index
+
+    // Points to shared front index if this reader throttles writer, or NULL if we don't throttle
+    // FIXME consider making it a boolean
+    audio_utils_fifo_index*     mThrottleFront;
+
+    bool        mFlush;             // whether to flush the entire buffer on -EOVERFLOW
+
+    int32_t     mArmLevel;          // arm if filled > arm level before release()
+    uint32_t    mTriggerLevel;      // trigger if armed and filled < trigger level after release()
+    bool        mIsArmed;           // whether currently armed
+
+    uint64_t    mTotalLost;         // total lost frames, does not include flushed frames
+    uint64_t    mTotalFlushed;      // total flushed frames, does not include lost frames
+};
 
 #endif  // !ANDROID_AUDIO_FIFO_H
diff --git a/audio_utils/include/audio_utils/fifo_index.h b/audio_utils/include/audio_utils/fifo_index.h
new file mode 100644 (file)
index 0000000..1b8401f
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_FIFO_INDEX_H
+#define ANDROID_AUDIO_FIFO_INDEX_H
+
+#include <atomic>
+#include <stdint.h>
+#include <time.h>
+
+/**
+ * An index that may optionally be placed in shared memory.
+ * Must be Plain Old Data (POD), so no virtual methods are allowed.
+ * If in shared memory, exactly one process must explicitly call the constructor via placement new.
+ * \see #audio_utils_fifo_sync
+ */
+class audio_utils_fifo_index {
+
+public:
+    audio_utils_fifo_index() : mIndex(0) { }
+    ~audio_utils_fifo_index() { }
+
+    /**
+     * Load value of index now with memory order 'acquire'.
+     *
+     * \return Index value
+     */
+    uint32_t loadAcquire();
+
+    /**
+     * Store new value into index now with memory order 'release'.
+     *
+     * \param value New value to store into index
+     */
+    void storeRelease(uint32_t value);
+
+    // TODO op should be set in the constructor.
+    /**
+     * Wait for value of index to change from the specified expected value.
+     *
+     * \param op      Either FUTEX_WAIT or FUTEX_WAIT_PRIVATE.
+     * \param timeout Indicates the maximum time to block while waiting for value to change.
+     *                NULL means to block forever.
+     *                Time is expressed as relative CLOCK_MONOTONIC.
+     *                We use the Linux kernel representation of time for the very lowest levels,
+     *                and save other representations for the APIs that are built on top of this.
+     *                This permits APIs to choose the int64_t representation if desired, or the
+     *                Linux representation without a double conversion.
+     *
+     * \return Zero for success, or a negative error code as specified at "man 2 futex".
+     */
+    int wait(int op, uint32_t expected, const struct timespec *timeout);
+
+    // TODO op should be set in the constructor.
+    /**
+     * Wake up any threads waiting for the value of index to change.
+     *
+     * \param op      Either FUTEX_WAIT or FUTEX_WAIT_PRIVATE.
+     * \param waiters Maximum number of waiting threads to wake up.
+     *
+     * \return Actual number of threads woken up.
+     */
+    int wake(int op, int waiters = 1);
+
+    // specialized use only, prefer loadAcquire in most cases
+    uint32_t loadConsume();
+
+private:
+    // Linux futex is 32 bits regardless of platform.
+    // It would make more sense to declare this as atomic_uint32_t, but there is no such type name.
+    // TODO Support 64-bit index with 32-bit futex in low-order bits.
+    std::atomic_uint_least32_t  mIndex; // accessed by both sides using atomic operations
+    static_assert(sizeof(mIndex) == sizeof(uint32_t), "mIndex must be 32 bits");
+};
+
+static_assert(sizeof(audio_utils_fifo_index) == sizeof(uint32_t),
+        "audio_utils_fifo_index must be 32 bits");
+
+// TODO
+// From a design POV, these next two classes should be related.
+// Extract a base class (that shares their property of being a reference to a fifo index)
+// This should be good in the case if there is a need for generic manipulations on these references.
+// Or can we perhaps define a template and make two specializations of it.
+// This is in the case when compile-time polymorphism is sufficient.
+
+/**
+ * A reference to an audio_utils_fifo_index with deferred store-release and deferred wake.
+ *
+ * TODO Currently the index and futex share the same 32-bit cell.
+ * In the future, the index may optionally be increased to 64-bits,
+ * and the futex will either be the low-order 32 bits of the index,
+ * or an unrelated 32-bit cell used as a set of event flags.
+ * Both of these will require a change to the API.
+ */
+class RefIndexDeferredStoreReleaseDeferredWake
+{
+public:
+    RefIndexDeferredStoreReleaseDeferredWake(audio_utils_fifo_index& index);
+    ~RefIndexDeferredStoreReleaseDeferredWake();
+
+    // Place 'value' into the cache but do not store it to memory yet.
+    void set(uint32_t value);
+
+    // If there is a new value in the cache, store it now with memory order 'release'.
+    void writeback();
+
+    // Place 'value' into the cache and then store it with memory order 'release'.
+    void writethrough(uint32_t value);
+
+    // op is FUTEX_WAKE or FUTEX_WAKE_PRIVATE
+    // TODO op should be set in the constructor, and should be abstracted.
+    // waiters is number of waiting threads to wake up
+    void wakeDeferred(int op, int waiters = 1);
+    void wakeNowIfNeeded();
+    // TODO op should be set in the constructor.
+    void wakeNow(int op, int waiters = 1);
+
+private:
+    audio_utils_fifo_index& mIndex;     // reference to associated index
+    uint32_t                mValue;     // cached value to be stored
+    bool                    mWriteback; // whether the cached value needs to be stored
+    int                     mWaiters;   // number of waiters to wake
+    int                     mWakeOp;    // which kind of wake operation to use
+};
+
+/**
+ * A reference to an audio_utils_fifo_index with cached load-acquire, and deferred wait.
+ *
+ * TODO Same as RefIndexDeferredStoreReleaseDeferredWake.
+ */
+class RefIndexCachedLoadAcquireDeferredWait
+{
+public:
+    RefIndexCachedLoadAcquireDeferredWait(audio_utils_fifo_index& index);
+    ~RefIndexCachedLoadAcquireDeferredWait();
+
+    // If value is already cached, return the cached value.
+    // Otherwise load now with memory order 'acquire', cache for later, and return the value.
+    uint32_t    get();
+
+    // If value is already cached, this is a no-op.
+    // Otherwise load now with memory order 'acquire' and cache the value for later use.
+    void        prefetch();
+
+    // Discard any value in the cache.
+    void        invalidate();
+
+#if 0
+    /**
+     * Load a fresh value for index, ignoring any previously cached information.
+     */
+    uint32_t    readthrough();
+#endif
+
+    // TODO This is an immediate wait, but we needed deferred wait
+    /**
+     * Wait for value of index to change from when it was most recently read with get().
+     * To avoid a race condition, the caller must have already read the index with get(),
+     * and then made the decision to call wait() based on that value.
+     *
+     * \param op      Either FUTEX_WAIT or FUTEX_WAIT_PRIVATE.
+     * \param timeout Indicates the maximum time to block while waiting for value to change.
+     *                NULL means to block forever.
+     *                Time is expressed as relative CLOCK_MONOTONIC.
+     *                See above for explanation of why representation is struct timespec.
+     *
+     * \return Zero for success, or a negative error code as specified at "man 2 futex".
+     * \retval -EINVAL caller did not call get() prior to wait()
+     */
+    int         wait(int op, const struct timespec *timeout);
+
+private:
+    audio_utils_fifo_index& mIndex;     // reference to associated index
+    uint32_t                mValue;     // most recently cached value
+    bool                    mLoaded;    // whether mValue is valid
+};
+
+#endif  // !ANDROID_AUDIO_FIFO_INDEX_H
diff --git a/audio_utils/include/audio_utils/futex.h b/audio_utils/include/audio_utils/futex.h
new file mode 100644 (file)
index 0000000..77e6fa8
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_FUTEX_H
+#define ANDROID_AUDIO_FUTEX_H
+
+// FIXME futex portion is not supported on macOS, should use the macOS alternative
+
+#ifdef __linux__
+#include <unistd.h>
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#else
+#include <errno.h>
+#define FUTEX_WAIT 0
+#define FUTEX_WAIT_PRIVATE 0
+#define FUTEX_WAKE 0
+#define FUTEX_WAKE_PRIVATE 0
+#endif
+
+static inline
+int sys_futex(void *addr1, int op, int val1, const struct timespec *timeout, void *addr2,
+        int val3)
+{
+#ifdef __linux__
+    return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
+#else   // __linux__
+    // macOS doesn't have futex
+    (void) addr1;
+    (void) op;
+    (void) val1;
+    (void) timeout;
+    (void) addr2;
+    (void) val3;
+    errno = ENOSYS;
+    return -1;
+#endif  // __linux__
+}
+
+#endif  // !ANDROID_AUDIO_FUTEX_H
diff --git a/audio_utils/include/audio_utils/power.h b/audio_utils/include/audio_utils/power.h
new file mode 100644 (file)
index 0000000..385b6a7
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_POWER_H
+#define ANDROID_AUDIO_POWER_H
+
+#include <math.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <system/audio.h>
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+/**
+ * \brief Compute signal power on a scale of 0 dBFS.
+ *
+ *   \param buffer       buffer of samples.
+ *   \param format       one of AUDIO_FORMAT_PCM_8_BIT, AUDIO_FORMAT_PCM_16_BIT,
+ *                       AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_8_24_BIT,
+ *                       AUDIO_FORMAT_PCM_32_BIT, AUDIO_FORMAT_PCM_FLOAT.
+ *   \param samples      number of samples in buffer.  This is not audio frames;
+ *                       usually the number of samples is the number of audio frames
+ *                       multiplied by channel count.
+ *
+ * \return
+ *   signal power of the samples in the buffer. It is possible to return negative infinity
+ *   if the power is zero.
+ */
+
+float audio_utils_compute_power_mono(const void *buffer, audio_format_t format, size_t samples);
+
+/**
+ * \brief Compute signal energy (sum of squared amplitudes).
+ *
+ *   \param buffer       buffer of samples.
+ *   \param format       one of AUDIO_FORMAT_PCM_8_BIT, AUDIO_FORMAT_PCM_16_BIT,
+ *                       AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_8_24_BIT,
+ *                       AUDIO_FORMAT_PCM_32_BIT, AUDIO_FORMAT_PCM_FLOAT.
+ *   \param samples      number of samples in buffer.  This is not audio frames;
+ *                       usually the number of samples is the number of audio frames
+ *                       multiplied by channel count.
+ *
+ * \return
+ *   signal energy of the samples in the buffer (sum of squares) where each sample is
+ *   normalized to peak to peak range of 1.f.
+ */
+
+float audio_utils_compute_energy_mono(const void *buffer, audio_format_t format, size_t samples);
+
+/**
+ * \brief  Returns true if the format is supported for compute_energy_for_mono()
+ *         and compute_power_for_mono().
+ * \param  format        format under consideration.
+ * \return true if supported.
+ */
+bool audio_utils_is_compute_power_format_supported(audio_format_t format);
+
+/**
+ * \brief  Returns the signal power from amplitude.
+ * \param  amplitude the signal amplitude. A negative amplitude is treated
+ *                   the same as a positive amplitude.
+ * \return signal power in dB. It is possible to return negative infinity
+ *         if the input is zero.
+ */
+static inline float audio_utils_power_from_amplitude(float amplitude)
+{
+    return 20.f * log10f(fabsf(amplitude));
+}
+
+/**
+ * \brief  Returns the signal power from energy.
+ * \param  energy the signal energy. This should be non-negative.
+ * \return signal power in dB. It is possible to return NaN if the input is
+ *         negative, or negative infinity if the input is zero.
+ */
+static inline float audio_utils_power_from_energy(float energy)
+{
+    return 10.f * log10f(energy);
+}
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif // !ANDROID_AUDIO_POWER_H
index 958b414..6346295 100644 (file)
@@ -67,7 +67,7 @@ void sf_close(SNDFILE *handle);
  * Read interleaved frames
  * \return actual number of frames read
  */
-sf_count_t sf_readf_short(SNDFILE *handle, short *ptr, sf_count_t desired);
+sf_count_t sf_readf_short(SNDFILE *handle, int16_t *ptr, sf_count_t desired);
 sf_count_t sf_readf_float(SNDFILE *handle, float *ptr, sf_count_t desired);
 sf_count_t sf_readf_int(SNDFILE *handle, int *ptr, sf_count_t desired);
 
@@ -75,7 +75,7 @@ sf_count_t sf_readf_int(SNDFILE *handle, int *ptr, sf_count_t desired);
  * Write interleaved frames
  * \return actual number of frames written
  */
-sf_count_t sf_writef_short(SNDFILE *handle, const short *ptr, sf_count_t desired);
+sf_count_t sf_writef_short(SNDFILE *handle, const int16_t *ptr, sf_count_t desired);
 sf_count_t sf_writef_float(SNDFILE *handle, const float *ptr, sf_count_t desired);
 sf_count_t sf_writef_int(SNDFILE *handle, const int *ptr, sf_count_t desired);
 
index b356149..3c84d73 100644 (file)
@@ -18,7 +18,7 @@
 #define ANDROID_AUDIO_SPDIF_ENCODER_H
 
 #include <stdint.h>
-#include <hardware/audio.h>
+#include <system/audio.h>
 #include <audio_utils/spdif/FrameScanner.h>
 
 namespace android {
@@ -105,8 +105,8 @@ protected:
     // state variable, true if scanning for start of frame
     bool      mScanning;
 
-    static const unsigned short kSPDIFSync1; // Pa
-    static const unsigned short kSPDIFSync2; // Pb
+    static const uint16_t kSPDIFSync1; // Pa
+    static const uint16_t kSPDIFSync2; // Pb
 };
 
 }  // namespace android
similarity index 96%
rename from audio_utils/conversion.cpp
rename to audio_utils/mono_blend.cpp
index a2d931f..933ccf8 100644 (file)
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "audio_utils_conversion"
+#define LOG_TAG "audio_utils_mono_blend"
 
 #include <math.h>
-#include <audio_utils/conversion.h>
+#include <audio_utils/mono_blend.h>
 #include <utils/Log.h>
 #include <audio_utils/limiter.h>
 
diff --git a/audio_utils/power.cpp b/audio_utils/power.cpp
new file mode 100644 (file)
index 0000000..e801da0
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_power"
+#include <log/log.h>
+
+#include <math.h>
+
+#include <audio_utils/power.h>
+#include <audio_utils/primitives.h>
+
+#if defined(__aarch64__) || defined(__ARM_NEON__)
+#include <arm_neon.h>
+#define USE_NEON
+#endif
+
+namespace {
+
+constexpr inline bool isFormatSupported(audio_format_t format) {
+    switch (format) {
+    case AUDIO_FORMAT_PCM_8_BIT:
+    case AUDIO_FORMAT_PCM_16_BIT:
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+    case AUDIO_FORMAT_PCM_8_24_BIT:
+    case AUDIO_FORMAT_PCM_32_BIT:
+    case AUDIO_FORMAT_PCM_FLOAT:
+        return true;
+    default:
+        return false;
+    }
+}
+
+template <typename T>
+inline T getPtrPtrValueAndIncrement(const void **data)
+{
+    return *(*reinterpret_cast<const T **>(data))++;
+}
+
+template <audio_format_t FORMAT>
+inline float convertToFloatAndIncrement(const void **data)
+{
+    switch (FORMAT) {
+    case AUDIO_FORMAT_PCM_8_BIT:
+        return float_from_u8(getPtrPtrValueAndIncrement<uint8_t>(data));
+
+    case AUDIO_FORMAT_PCM_16_BIT:
+        return float_from_i16(getPtrPtrValueAndIncrement<int16_t>(data));
+
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED: {
+        const uint8_t *uptr = reinterpret_cast<const uint8_t *>(*data);
+        *data = uptr + 3;
+        return float_from_p24(uptr);
+    }
+
+    case AUDIO_FORMAT_PCM_8_24_BIT:
+        return float_from_q8_23(getPtrPtrValueAndIncrement<int32_t>(data));
+
+    case AUDIO_FORMAT_PCM_32_BIT:
+        return float_from_i32(getPtrPtrValueAndIncrement<int32_t>(data));
+
+    case AUDIO_FORMAT_PCM_FLOAT:
+        return getPtrPtrValueAndIncrement<float>(data);
+
+    default:
+        // static_assert cannot use false because the compiler may interpret it
+        // even though this code path may never be taken.
+        static_assert(isFormatSupported(FORMAT), "unsupported format");
+    }
+}
+
+// used to normalize integer fixed point value to the floating point equivalent.
+template <audio_format_t FORMAT>
+constexpr inline float normalizeAmplitude()
+{
+    switch (FORMAT) {
+    case AUDIO_FORMAT_PCM_8_BIT:
+        return 1.f / (1 << 7);
+
+    case AUDIO_FORMAT_PCM_16_BIT:
+        return 1.f / (1 << 15);
+
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED: // fall through
+    case AUDIO_FORMAT_PCM_8_24_BIT:
+        return 1.f / (1 << 23);
+
+    case AUDIO_FORMAT_PCM_32_BIT:
+        return 1.f / (1U << 31);
+
+    case AUDIO_FORMAT_PCM_FLOAT:
+         return 1.f;
+
+    default:
+        // static_assert cannot use false because the compiler may interpret it
+        // even though this code path may never be taken.
+        static_assert(isFormatSupported(FORMAT), "unsupported format");
+    }
+}
+
+template <audio_format_t FORMAT>
+constexpr inline float normalizeEnergy()
+{
+    const float val = normalizeAmplitude<FORMAT>();
+    return val * val;
+}
+
+template <audio_format_t FORMAT>
+inline float energyMonoRef(const void *amplitudes, size_t size)
+{
+    float accum(0.f);
+    for (size_t i = 0; i < size; ++i) {
+        const float amplitude = convertToFloatAndIncrement<FORMAT>(&amplitudes);
+        accum += amplitude * amplitude;
+    }
+    return accum;
+}
+
+template <audio_format_t FORMAT>
+inline float energyMono(const void *amplitudes, size_t size)
+{
+    return energyMonoRef<FORMAT>(amplitudes, size);
+}
+
+// fast float power computation for ARM processors that support NEON.
+#ifdef USE_NEON
+
+template <>
+inline float energyMono<AUDIO_FORMAT_PCM_FLOAT>(const void *amplitudes, size_t size)
+{
+    float32x4_t *famplitudes = (float32x4_t *)amplitudes;
+
+    // clear accumulator
+    float32x4_t accum = vdupq_n_f32(0);
+
+    // iterate over array getting sum of squares in 4 lanes.
+    size_t i;
+    for (i = 0; i < (size & ~3); i += 4) {
+        accum = vmlaq_f32(accum, *famplitudes, *famplitudes);
+        ++famplitudes;
+    }
+
+    // narrow 4 lanes of floats
+    float32x2_t accum2 = vadd_f32(vget_low_f32(accum), vget_high_f32(accum)); // get stereo volume
+    accum2 = vpadd_f32(accum2, accum2); // combine to mono
+
+    // accumulate remainder
+    float value = vget_lane_f32(accum2, 0);
+    for (; i < size; ++i) {
+        const float amplitude = ((float *)amplitudes)[i];
+        value +=  amplitude * amplitude;
+    }
+
+    return value;
+}
+
+template <>
+inline float energyMono<AUDIO_FORMAT_PCM_16_BIT>(const void *amplitudes, size_t size)
+{
+    int16x4_t *samplitudes = (int16x4_t *)amplitudes;
+
+    // clear accumulator
+    float32x4_t accum = vdupq_n_f32(0);
+
+    // iterate over array getting sum of squares in 4 lanes.
+    size_t i;
+    for (i = 0; i < (size & ~3); i += 4) {
+        // expand s16 to s32
+        int32x4_t amplitude = vmovl_s16(*samplitudes);
+        ++samplitudes;
+        // convert s32 to f32
+        float32x4_t famplitude = vcvtq_f32_s32(amplitude);
+        accum = vmlaq_f32(accum, famplitude, famplitude);
+    }
+
+    // narrow 4 lanes of floats
+    float32x2_t accum2 = vadd_f32(vget_low_f32(accum), vget_high_f32(accum)); // get stereo volume
+    accum2 = vpadd_f32(accum2, accum2); // combine to mono
+
+    // accumulate remainder
+    float value = vget_lane_f32(accum2, 0);
+    for (; i < size; ++i) {
+        const float amplitude = (float)((int16_t *)amplitudes)[i];
+        value +=  amplitude * amplitude;
+    }
+
+    return value * normalizeEnergy<AUDIO_FORMAT_PCM_16_BIT>();
+}
+
+// fast int32_t power computation for PCM_32
+template <>
+inline float energyMono<AUDIO_FORMAT_PCM_32_BIT>(const void *amplitudes, size_t size)
+{
+    int32x4_t *samplitudes = (int32x4_t *)amplitudes;
+
+    // clear accumulator
+    float32x4_t accum = vdupq_n_f32(0);
+
+    // iterate over array getting sum of squares in 4 lanes.
+    size_t i;
+    for (i = 0; i < (size & ~3); i += 4) {
+        // convert s32 to f32
+        float32x4_t famplitude = vcvtq_f32_s32(*samplitudes);
+        ++samplitudes;
+        accum = vmlaq_f32(accum, famplitude, famplitude);
+    }
+
+    // narrow 4 lanes of floats
+    float32x2_t accum2 = vadd_f32(vget_low_f32(accum), vget_high_f32(accum)); // get stereo volume
+    accum2 = vpadd_f32(accum2, accum2); // combine to mono
+
+    // accumulate remainder
+    float value = vget_lane_f32(accum2, 0);
+    for (; i < size; ++i) {
+        const float amplitude = (float)((int32_t *)amplitudes)[i];
+        value +=  amplitude * amplitude;
+    }
+
+    return value * normalizeEnergy<AUDIO_FORMAT_PCM_32_BIT>();
+}
+
+// fast int32_t power computation for PCM_8_24 (essentially identical to PCM_32 above)
+template <>
+inline float energyMono<AUDIO_FORMAT_PCM_8_24_BIT>(const void *amplitudes, size_t size)
+{
+    int32x4_t *samplitudes = (int32x4_t *)amplitudes;
+
+    // clear accumulator
+    float32x4_t accum = vdupq_n_f32(0);
+
+    // iterate over array getting sum of squares in 4 lanes.
+    size_t i;
+    for (i = 0; i < (size & ~3); i += 4) {
+        // convert s32 to f32
+        float32x4_t famplitude = vcvtq_f32_s32(*samplitudes);
+        ++samplitudes;
+        accum = vmlaq_f32(accum, famplitude, famplitude);
+    }
+
+    // narrow 4 lanes of floats
+    float32x2_t accum2 = vadd_f32(vget_low_f32(accum), vget_high_f32(accum)); // get stereo volume
+    accum2 = vpadd_f32(accum2, accum2); // combine to mono
+
+    // accumulate remainder
+    float value = vget_lane_f32(accum2, 0);
+    for (; i < size; ++i) {
+        const float amplitude = (float)((int32_t *)amplitudes)[i];
+        value +=  amplitude * amplitude;
+    }
+
+    return value * normalizeEnergy<AUDIO_FORMAT_PCM_8_24_BIT>();
+}
+
+#endif // USE_NEON
+
+} // namespace
+
+float audio_utils_compute_energy_mono(const void *buffer, audio_format_t format, size_t samples)
+{
+    switch (format) {
+    case AUDIO_FORMAT_PCM_8_BIT:
+        return energyMono<AUDIO_FORMAT_PCM_8_BIT>(buffer, samples);
+
+    case AUDIO_FORMAT_PCM_16_BIT:
+        return energyMono<AUDIO_FORMAT_PCM_16_BIT>(buffer, samples);
+
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+        return energyMono<AUDIO_FORMAT_PCM_24_BIT_PACKED>(buffer, samples);
+
+    case AUDIO_FORMAT_PCM_8_24_BIT:
+        return energyMono<AUDIO_FORMAT_PCM_8_24_BIT>(buffer, samples);
+
+    case AUDIO_FORMAT_PCM_32_BIT:
+        return energyMono<AUDIO_FORMAT_PCM_32_BIT>(buffer, samples);
+
+    case AUDIO_FORMAT_PCM_FLOAT:
+        return energyMono<AUDIO_FORMAT_PCM_FLOAT>(buffer, samples);
+
+    default:
+        LOG_ALWAYS_FATAL("invalid format: %#x", format);
+    }
+}
+
+float audio_utils_compute_power_mono(const void *buffer, audio_format_t format, size_t samples)
+{
+    return audio_utils_power_from_energy(
+            audio_utils_compute_energy_mono(buffer, format, samples) / samples);
+}
+
+bool audio_utils_is_compute_power_format_supported(audio_format_t format)
+{
+    return isFormatSupported(format);
+}
+
index d44c29e..f4bd645 100644 (file)
@@ -101,7 +101,7 @@ void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count)
 void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count)
 {
     while (count--) {
-#ifdef HAVE_BIG_ENDIAN
+#if HAVE_BIG_ENDIAN
         *dst++ = src[1] | (src[0] << 8);
 #else
         *dst++ = src[1] | (src[2] << 8);
@@ -113,7 +113,7 @@ void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count)
 void memcpy_to_i32_from_p24(int32_t *dst, const uint8_t *src, size_t count)
 {
     while (count--) {
-#ifdef HAVE_BIG_ENDIAN
+#if HAVE_BIG_ENDIAN
         *dst++ = (src[2] << 8) | (src[1] << 16) | (src[0] << 24);
 #else
         *dst++ = (src[0] << 8) | (src[1] << 16) | (src[2] << 24);
@@ -125,7 +125,7 @@ void memcpy_to_i32_from_p24(int32_t *dst, const uint8_t *src, size_t count)
 void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count)
 {
     while (count--) {
-#ifdef HAVE_BIG_ENDIAN
+#if HAVE_BIG_ENDIAN
         *dst++ = *src >> 8;
         *dst++ = *src++;
         *dst++ = 0;
@@ -142,7 +142,7 @@ void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count)
     while (count--) {
         int32_t ival = clamp24_from_float(*src++);
 
-#ifdef HAVE_BIG_ENDIAN
+#if HAVE_BIG_ENDIAN
         *dst++ = ival >> 16;
         *dst++ = ival >> 8;
         *dst++ = ival;
@@ -159,7 +159,7 @@ void memcpy_to_p24_from_q8_23(uint8_t *dst, const int32_t *src, size_t count)
     while (count--) {
         int32_t ival = clamp24_from_q8_23(*src++);
 
-#ifdef HAVE_BIG_ENDIAN
+#if HAVE_BIG_ENDIAN
         *dst++ = ival >> 16;
         *dst++ = ival >> 8;
         *dst++ = ival;
@@ -176,7 +176,7 @@ void memcpy_to_p24_from_i32(uint8_t *dst, const int32_t *src, size_t count)
     while (count--) {
         int32_t ival = *src++ >> 8;
 
-#ifdef HAVE_BIG_ENDIAN
+#if HAVE_BIG_ENDIAN
         *dst++ = ival >> 16;
         *dst++ = ival >> 8;
         *dst++ = ival;
@@ -205,7 +205,7 @@ void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_
 void memcpy_to_q8_23_from_p24(int32_t *dst, const uint8_t *src, size_t count)
 {
     while (count--) {
-#ifdef HAVE_BIG_ENDIAN
+#if HAVE_BIG_ENDIAN
         *dst++ = (int8_t)src[0] << 16 | src[1] << 8 | src[2];
 #else
         *dst++ = (int8_t)src[2] << 16 | src[1] << 8 | src[0];
index 9f3ea57..a73a860 100644 (file)
@@ -18,7 +18,7 @@
 #define ANDROID_AUDIO_AC3_FRAME_SCANNER_H
 
 #include <stdint.h>
-#include <hardware/audio.h>
+#include <system/audio.h>
 #include <audio_utils/spdif/FrameScanner.h>
 
 namespace android {
index efcd556..5c62299 100644 (file)
@@ -27,8 +27,8 @@
 namespace android {
 
 // Burst Preamble defined in IEC61937-1
-const unsigned short SPDIFEncoder::kSPDIFSync1 = 0xF872; // Pa
-const unsigned short SPDIFEncoder::kSPDIFSync2 = 0x4E1F; // Pb
+const uint16_t SPDIFEncoder::kSPDIFSync1 = 0xF872; // Pa
+const uint16_t SPDIFEncoder::kSPDIFSync2 = 0x4E1F; // Pb
 
 static int32_t sEndianDetector = 1;
 #define isLittleEndian()  (*((uint8_t *)&sEndianDetector))
index 2d5f1a4..0f13a1e 100644 (file)
@@ -35,6 +35,35 @@ cc_binary {
     ],
 }
 
+cc_binary {
+    name: "fifo_multiprocess",
+    host_supported: false,
+    srcs: ["fifo_multiprocess.cpp"],
+    shared_libs: ["libaudioutils", "libcutils"],
+    static_libs: ["libsndfile"],
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+}
+
+cc_binary_host {
+    name: "fifo_threads",
+    // TODO move getch.c and .h to a utility library
+    srcs: [
+        "fifo_threads.cpp",
+        "getch.c",
+    ],
+    static_libs: [
+        "libaudioutils",
+        "liblog",
+    ],
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+}
+
 cc_binary_host {
     name: "limiter_tests",
     srcs: ["limiter_tests.c"],
@@ -42,5 +71,102 @@ cc_binary_host {
     cflags: [
         "-Werror",
         "-Wall",
+        "-UNDEBUG",
+    ],
+}
+
+cc_test {
+    name: "power_tests",
+    host_supported: true,
+
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+    srcs: ["power_tests.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
     ],
+    target: {
+        android: {
+            shared_libs: ["libaudioutils"],
+        },
+        host: {
+            static_libs: ["libaudioutils"],
+        },
+    }
+}
+
+cc_test {
+    name: "errorlog_tests",
+    host_supported: false,
+
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+    srcs: ["errorlog_tests.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    target: {
+        android: {
+            shared_libs: ["libaudioutils"],
+        },
+        host: {
+            static_libs: ["libaudioutils"],
+        },
+    }
+}
+
+cc_test {
+    name: "powerlog_tests",
+    host_supported: false,
+
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+    srcs: ["powerlog_tests.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    target: {
+        android: {
+            shared_libs: ["libaudioutils"],
+        },
+        host: {
+            static_libs: ["libaudioutils"],
+        },
+    }
+}
+
+cc_test {
+    name: "simplelog_tests",
+    host_supported: false,
+
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+    srcs: ["simplelog_tests.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    target: {
+        android: {
+            shared_libs: ["libaudioutils"],
+        },
+        host: {
+            static_libs: ["libaudioutils"],
+        },
+    }
 }
index 021818a..456350c 100644 (file)
@@ -1,3 +1,5 @@
 primitive\_tests uses gtest framework
 
 fifo\_tests does not run under gtest
+
+FIXME: getch.[ch] are copied from ../../../../frameworks/wilhelm/tests/sandbox/
diff --git a/audio_utils/tests/errorlog_tests.cpp b/audio_utils/tests/errorlog_tests.cpp
new file mode 100644 (file)
index 0000000..491d43b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_errorlog_tests"
+
+#include <audio_utils/ErrorLog.h>
+#include <gtest/gtest.h>
+#include <iostream>
+#include <log/log.h>
+
+using namespace android;
+
+static size_t countNewLines(const std::string &s) {
+    return std::count(s.begin(), s.end(), '\n');
+}
+
+TEST(audio_utils_errorlog, basic) {
+    auto elog = std::make_unique<ErrorLog<int32_t>>(100 /* lines */);
+    const int64_t oneSecond = 1000000000;
+
+    EXPECT_EQ((size_t)1, countNewLines(elog->dumpToString()));
+
+    elog->log(1 /* code */, 0 /* nowNs */);
+    elog->log(2 /* code */, 1 /* nowNs */);
+
+    // two separate errors (4 lines including 2 header lines)
+    EXPECT_EQ((size_t)4, countNewLines(elog->dumpToString()));
+
+    // aggregation at (oneSecond - 1)
+    elog->log(2 /* code */, oneSecond /* nowNs */);
+    EXPECT_EQ((size_t)4, countNewLines(elog->dumpToString()));
+
+    // no aggregation if spaced exactly one second apart
+    elog->log(2 /* code */, oneSecond * 2 /* nowNs */);
+    EXPECT_EQ((size_t)5, countNewLines(elog->dumpToString()));
+
+    // Check log:
+    // truncate on lines
+    EXPECT_EQ((size_t)3, countNewLines(elog->dumpToString("" /* prefix */, 3 /* lines */)));
+
+    // truncate on time
+    EXPECT_EQ((size_t)4, countNewLines(
+            elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond - 1 /* limitNs */)));
+
+    // truncate on time
+    EXPECT_EQ((size_t)4, countNewLines(
+            elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond /* limitNs */)));
+
+    // truncate on time (more)
+    EXPECT_EQ((size_t)3, countNewLines(
+            elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond + 1 /* limitNs */)));
+
+    // truncate on time
+    EXPECT_EQ((size_t)3, countNewLines(
+            elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond * 2 /* limitNs */)));
+
+    // truncate on time (to first header line)
+    EXPECT_EQ((size_t)1, countNewLines(
+            elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond * 2 + 1/* limitNs */)));
+
+    elog->dump(0 /* fd (stdout) */);
+
+    // The output below depends on the local time zone.
+    // The indentation below is exact, check alignment.
+    /*
+Errors: 4
+ Code  Freq          First time           Last time
+    1     1  12-31 16:00:00.000  12-31 16:00:00.000
+    2     2  12-31 16:00:00.000  12-31 16:00:01.000
+    2     1  12-31 16:00:02.000  12-31 16:00:02.000
+     */
+}
+
+TEST(audio_utils_errorlog, c) {
+    error_log_t *error_log =
+            error_log_create(100 /* lines */, 1000000000 /* one second aggregation */);
+
+    // just a sanity test
+    error_log_log(error_log, 2 /* code */, 1 /* now_ns */);
+    error_log_dump(error_log, 0 /* fd */, "  " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
+    error_log_destroy(error_log);
+
+    // This has a 2 character prefix offset from the previous test when dumping.
+    // The indentation below is exact, check alignment.
+    /*
+  Errors: 1
+   Code  Freq          First time           Last time
+      2     1  12-31 16:00:00.000  12-31 16:00:00.000
+     */
+}
diff --git a/audio_utils/tests/fifo_multiprocess.cpp b/audio_utils/tests/fifo_multiprocess.cpp
new file mode 100644 (file)
index 0000000..f9c72e2
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <new>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <audio_utils/fifo.h>
+#include <cutils/ashmem.h>
+
+#define FRAME_COUNT 2048
+#define FRAME_SIZE sizeof(int16_t)
+#define BUFFER_SIZE (FRAME_COUNT * FRAME_SIZE)
+
+int main(int argc __unused, char **argv __unused)
+{
+    // TODO Add error checking for ashmem_create_region and mmap
+
+    const int frontFd = ashmem_create_region("front", sizeof(audio_utils_fifo_index));
+    printf("frontFd=%d\n", frontFd);
+
+    const int rearFd = ashmem_create_region("rear", sizeof(audio_utils_fifo_index));
+    printf("rearFd=%d\n", rearFd);
+
+    const int dataFd = ashmem_create_region("buffer", BUFFER_SIZE);
+    printf("dataFd=%d\n", dataFd);
+
+    // next two index constructors must execute exactly once, so we do it in the parent
+
+    audio_utils_fifo_index *frontIndex = (audio_utils_fifo_index *) mmap(NULL,
+            sizeof(audio_utils_fifo_index), PROT_READ | PROT_WRITE, MAP_SHARED, frontFd, (off_t) 0);
+    printf("parent frontIndex=%p\n", frontIndex);
+    (void) new(frontIndex) audio_utils_fifo_index();
+
+    audio_utils_fifo_index *rearIndex = (audio_utils_fifo_index *) mmap(NULL,
+            sizeof(audio_utils_fifo_index), PROT_READ | PROT_WRITE, MAP_SHARED, rearFd, (off_t) 0);
+    printf("parent rearIndex=%p\n", rearIndex);
+    (void) new(rearIndex) audio_utils_fifo_index();
+
+    int16_t *data = (int16_t *) mmap(NULL, sizeof(audio_utils_fifo_index), PROT_READ | PROT_WRITE,
+            MAP_SHARED, dataFd, (off_t) 0);
+    printf("parent data=%p\n", data);
+    memset(data, 0, BUFFER_SIZE);
+
+    const int pageSize = getpagesize();
+    printf("page size=%d\n", pageSize);
+
+    // create writer
+
+    printf("fork writer:\n");
+    const pid_t pidWriter = fork();
+    // TODO check if pidWriter < 0
+    if (!pidWriter) {
+
+        // Child inherits the parent's read/write mapping of front index.
+        // To confirm that there are no attempts to write to the front index,
+        // unmap it and then re-map it as read-only.
+        int ok = munmap(frontIndex, sizeof(audio_utils_fifo_index));
+        printf("writer unmap front ok=%d\n", ok);
+        ok = ashmem_set_prot_region(frontFd, PROT_READ);
+        printf("writer prot read front ok=%d\n", ok);
+        // The pagesize * 4 offset confirms that we don't assume identical mapping in both processes
+        frontIndex = (audio_utils_fifo_index *) mmap((char *) frontIndex + pageSize * 4,
+                sizeof(audio_utils_fifo_index), PROT_READ, MAP_SHARED | MAP_FIXED, frontFd,
+                (off_t) 0);
+        printf("writer frontIndex=%p\n", frontIndex);
+
+        // Retain our read/write mapping of rear index and data
+        audio_utils_fifo fifo(FRAME_COUNT, FRAME_SIZE, data, *rearIndex, frontIndex);
+        audio_utils_fifo_writer writer(fifo);
+
+        sleep(2);
+
+        for (int16_t value = 1; value <= 20; value++) {
+            printf("writing %d\n", value);
+            const ssize_t actual = writer.write(&value, 1);
+            if (actual != 1) {
+                printf("wrote unexpected actual = %zd\n", actual);
+                break;
+            }
+            // TODO needs a lot of work
+            switch (value) {
+            case 10:
+                sleep(2);
+                break;
+            case 14:
+                sleep(4);
+                break;
+            default:
+                usleep(500000);
+                break;
+            }
+        }
+
+        (void) close(frontFd);
+        (void) close(rearFd);
+        (void) close(dataFd);
+
+        return EXIT_SUCCESS;
+    }
+
+    // The sleep(2) above and sleep(1) here ensure that the order is:
+    //  a. writer initializes
+    //  b. reader initializes
+    //  c. reader starts the read loop
+    //  d. writer starts the write loop
+    // Actually, as long as (a) precedes (d) and (b) precedes (c), the order does not matter.
+    // TODO test all valid sequences.
+    sleep(1);
+
+    // create reader
+
+    printf("fork reader:\n");
+    const pid_t pidReader = fork();
+    // TODO check if pidReader < 0
+    if (!pidReader) {
+
+        // Child inherits the parent's read/write mapping of rear index.
+        // To confirm that there are no attempts to write to the rear index,
+        // unmap it and then re-map it as read-only.
+        int ok = munmap(rearIndex, sizeof(audio_utils_fifo_index));
+        printf("reader unmap rear ok=%d\n", ok);
+        ok = ashmem_set_prot_region(rearFd, PROT_READ);
+        printf("reader prot read rear ok=%d\n", ok);
+        // The pagesize * 4 offset confirms that we don't assume identical mapping in both processes
+        rearIndex = (audio_utils_fifo_index *) mmap((char *) rearIndex + pageSize * 4,
+                sizeof(audio_utils_fifo_index), PROT_READ, MAP_SHARED | MAP_FIXED, rearFd,
+                (off_t) 0);
+        printf("reader rearIndex=%p\n", rearIndex);
+
+        // Similarly for the data
+        ok = munmap(data, BUFFER_SIZE);
+        printf("reader unmap data ok=%d\n", ok);
+        ok = ashmem_set_prot_region(dataFd, PROT_READ);
+        printf("reader prot read data ok=%d\n", ok);
+        // The pagesize * 8 offset confirms that we don't assume identical mapping in both processes
+        data = (int16_t *) mmap((char *) data + pageSize * 8, BUFFER_SIZE, PROT_READ,
+                MAP_SHARED | MAP_FIXED, dataFd, (off_t) 0);
+        printf("reader data=%p\n", data);
+
+        // Retain our read/write mapping of front index
+        audio_utils_fifo fifo(FRAME_COUNT, FRAME_SIZE, data, *rearIndex, frontIndex);
+        audio_utils_fifo_reader reader(fifo);
+
+        for (;;) {
+            int16_t value;
+            struct timespec timeout = {
+                .tv_sec = 1,
+                .tv_nsec = 0
+            };
+            const ssize_t actual = reader.read(&value, 1, &timeout);
+            switch (actual) {
+            case 0:
+                break;
+            case 1:
+                printf("read %d\n", value);
+                if (value == 20) {
+                    goto out;
+                }
+                break;
+            case -ETIMEDOUT:
+                printf("read timed out\n");
+                break;
+            default:
+                printf("read unexpected actual = %zd\n", actual);
+                goto out;
+            }
+        }
+out:
+
+        (void) close(frontFd);
+        (void) close(rearFd);
+        (void) close(dataFd);
+
+        return EXIT_SUCCESS;
+    }
+
+    int status;
+    pid_t pid = waitpid(pidWriter, &status, 0);
+    if (pid == pidWriter) {
+        printf("writer exited with status %d\n", status);
+    } else {
+        printf("waitpid on writer = %d\n", pid);
+    }
+    pid = waitpid(pidReader, &status, 0);
+    if (pid == pidReader) {
+        printf("reader exited with status %d\n", status);
+    } else {
+        printf("waitpid on reader = %d\n", pid);
+    }
+
+    // next two index destructors must execute exactly once, so we do it in the parent
+    frontIndex->~audio_utils_fifo_index();
+    rearIndex->~audio_utils_fifo_index();
+
+    int ok = munmap(frontIndex, sizeof(audio_utils_fifo_index));
+    printf("parent unmap front ok=%d\n", ok);
+    ok = munmap(rearIndex, sizeof(audio_utils_fifo_index));
+    printf("parent unmap rear ok=%d\n", ok);
+    ok = munmap(data, BUFFER_SIZE);
+    printf("parent unmap data ok=%d\n", ok);
+
+    (void) close(frontFd);
+    (void) close(rearFd);
+    (void) close(dataFd);
+
+    return EXIT_SUCCESS;
+}
index 99e73c9..b015810 100644 (file)
 // Test program for audio_utils FIFO library.
 // This only tests the single-threaded aspects, not the barriers.
 
+#include <errno.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 #include <audio_utils/fifo.h>
 #include <audio_utils/sndfile.h>
 
+#ifndef min
+#define min(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
 int main(int argc, char **argv)
 {
-    size_t frameCount = 256;
-    size_t maxFramesPerRead = 1;
-    size_t maxFramesPerWrite = 1;
+    size_t frameCount = 0;
+    size_t maxFramesPerRead = 0;
+    size_t maxFramesPerWrite = 0;
+    bool readerThrottlesWriter = true;
+    bool verbose = false;
     int i;
     for (i = 1; i < argc; i++) {
         char *arg = argv[i];
         if (arg[0] != '-')
             break;
         switch (arg[1]) {
-        case 'c':   // FIFO frame count
+        case 'f':   // FIFO frame count
             frameCount = atoi(&arg[2]);
             break;
         case 'r':   // maximum frame count per read from FIFO
             maxFramesPerRead = atoi(&arg[2]);
             break;
+        case 't':   // disable throttling of writer by reader
+            readerThrottlesWriter = false;
+            break;
+        case 'v':   // enable verbose logging
+            verbose = true;
+            break;
         case 'w':   // maximum frame count per write to FIFO
             maxFramesPerWrite = atoi(&arg[2]);
             break;
@@ -48,10 +61,19 @@ int main(int argc, char **argv)
             goto usage;
         }
     }
+    if (frameCount == 0) {
+        frameCount = 256;
+    }
+    if (maxFramesPerRead == 0) {
+        maxFramesPerRead = frameCount;
+    }
+    if (maxFramesPerWrite == 0) {
+        maxFramesPerWrite = frameCount;
+    }
 
     if (argc - i != 2) {
 usage:
-        fprintf(stderr, "usage: %s [-c#] in.wav out.wav\n", argv[0]);
+        fprintf(stderr, "usage: %s [-f#] [-r#] [-t] [-v] [-w#] in.wav out.wav\n", argv[0]);
         return EXIT_FAILURE;
     }
     char *inputFile = argv[i];
@@ -64,18 +86,17 @@ usage:
         perror(inputFile);
         return EXIT_FAILURE;
     }
-    // sf_readf_short() does conversion, so not strictly necessary to check the file format.
-    // But I want to do "cmp" on input and output files afterwards,
-    // and it is easier if they are all the same format.
-    // Enforcing that everything is 16-bit is convenient for this.
-    if ((sfinfoin.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) !=
-            (SF_FORMAT_WAV | SF_FORMAT_PCM_16)) {
+    switch (sfinfoin.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) {
+    case SF_FORMAT_WAV | SF_FORMAT_PCM_16:
+    case SF_FORMAT_WAV | SF_FORMAT_PCM_U8:
+        break;
+    default:
         fprintf(stderr, "%s: unsupported format\n", inputFile);
         sf_close(sfin);
         return EXIT_FAILURE;
     }
-    size_t frameSize = sizeof(short) * sfinfoin.channels;
-    short *inputBuffer = new short[sfinfoin.frames * sfinfoin.channels];
+    size_t frameSize = sizeof(int16_t) * sfinfoin.channels;
+    int16_t *inputBuffer = new int16_t[sfinfoin.frames * sfinfoin.channels];
     sf_count_t actualRead = sf_readf_short(sfin, inputBuffer, sfinfoin.frames);
     if (actualRead != sfinfoin.frames) {
         fprintf(stderr, "%s: unexpected EOF or error\n", inputFile);
@@ -84,18 +105,19 @@ usage:
     }
     sf_close(sfin);
 
-    short *outputBuffer = new short[sfinfoin.frames * sfinfoin.channels];
+    int16_t *outputBuffer = new int16_t[sfinfoin.frames * sfinfoin.channels];
     size_t framesWritten = 0;
     size_t framesRead = 0;
-    struct audio_utils_fifo fifo;
-    short *fifoBuffer = new short[frameCount * sfinfoin.channels];
-    audio_utils_fifo_init(&fifo, frameCount, frameSize, fifoBuffer);
+    int16_t *fifoBuffer = new int16_t[frameCount * sfinfoin.channels];
+    audio_utils_fifo fifo(frameCount, frameSize, fifoBuffer, readerThrottlesWriter);
+    audio_utils_fifo_writer fifoWriter(fifo);
+    audio_utils_fifo_reader fifoReader(fifo, readerThrottlesWriter);
     int fifoWriteCount = 0, fifoReadCount = 0;
     int fifoFillLevel = 0, minFillLevel = INT_MAX, maxFillLevel = INT_MIN;
     for (;;) {
         size_t framesToWrite = sfinfoin.frames - framesWritten;
         size_t framesToRead = sfinfoin.frames - framesRead;
-        if (framesToWrite == 0 && framesToRead == 0) {
+        if (framesToWrite == 0 && (framesToRead == 0 || !readerThrottlesWriter)) {
             break;
         }
 
@@ -103,49 +125,100 @@ usage:
             framesToWrite = maxFramesPerWrite;
         }
         framesToWrite = rand() % (framesToWrite + 1);
-        ssize_t actualWritten = audio_utils_fifo_write(&fifo,
+        ssize_t actualWritten = fifoWriter.write(
                 &inputBuffer[framesWritten * sfinfoin.channels], framesToWrite);
+        if (verbose) {
+            printf("wrote %d out of %d\n", (int) actualWritten, (int) framesToWrite);
+        }
         if (actualWritten < 0 || (size_t) actualWritten > framesToWrite) {
             fprintf(stderr, "write to FIFO failed\n");
             break;
         }
+        if (actualWritten < min((int) frameCount - fifoFillLevel, (int) framesToWrite)) {
+            fprintf(stderr, "only wrote %d when should have written min(%d, %d)\n",
+                    (int) actualWritten, (int) frameCount - fifoFillLevel, (int) framesToWrite);
+        }
         framesWritten += actualWritten;
         if (actualWritten > 0) {
             fifoWriteCount++;
         }
         fifoFillLevel += actualWritten;
+        if (verbose) {
+            printf("fill level after write %d\n", fifoFillLevel);
+        }
         if (fifoFillLevel > maxFillLevel) {
             maxFillLevel = fifoFillLevel;
-            if (maxFillLevel > (int) frameCount)
-                abort();
+            if (maxFillLevel > (int) frameCount) {
+                if (readerThrottlesWriter) {
+                    printf("maxFillLevel=%d > frameCount=%d\n", maxFillLevel, (int) frameCount);
+                    abort();
+                }
+            }
         }
 
         if (framesToRead > maxFramesPerRead) {
             framesToRead = maxFramesPerRead;
         }
         framesToRead = rand() % (framesToRead + 1);
-        ssize_t actualRead = audio_utils_fifo_read(&fifo,
+        ssize_t actualRead = fifoReader.read(
                 &outputBuffer[framesRead * sfinfoin.channels], framesToRead);
+        if (verbose) {
+            printf("read %d out of %d\n", (int) actualRead, (int) framesToRead);
+        }
         if (actualRead < 0 || (size_t) actualRead > framesToRead) {
-            fprintf(stderr, "read from FIFO failed\n");
-            break;
+            switch (actualRead) {
+            case -EIO:
+                fprintf(stderr, "read from FIFO failed: corrupted indices\n");
+                abort();
+                break;
+            case -EOVERFLOW:
+                if (readerThrottlesWriter) {
+                    fprintf(stderr, "read from FIFO failed: unexpected overflow\n");
+                    abort();
+                }
+                printf("warning: reader lost frames\n");
+                actualRead = 0;
+                break;
+            default:
+                if (actualRead < 0) {
+                    fprintf(stderr, "read from FIFO failed: unexpected error code %d\n",
+                            (int) actualRead);
+                } else {
+                    fprintf(stderr, "read from FIFO failed: actualRead=%d > framesToRead=%d\n",
+                            (int) actualRead, (int) framesToRead);
+                }
+                abort();
+            }
+        }
+        if (actualRead < min(fifoFillLevel, (int) framesToRead)) {
+            //fprintf(stderr, "only read %d when should have read min(%d, %d)\n",
+            //        (int) actualRead, fifoFillLevel, (int) framesToRead);
         }
         framesRead += actualRead;
         if (actualRead > 0) {
             fifoReadCount++;
         }
         fifoFillLevel -= actualRead;
+        if (verbose) {
+            printf("fill level after read %d\n", fifoFillLevel);
+        }
         if (fifoFillLevel < minFillLevel) {
             minFillLevel = fifoFillLevel;
-            if (minFillLevel < 0)
+            if (minFillLevel < 0) {
+                printf("minFillLevel=%d < 0\n", minFillLevel);
                 abort();
+            }
         }
     }
+    delete[] inputBuffer;
+    inputBuffer = NULL;
+    delete[] fifoBuffer;
+    fifoBuffer = NULL;
+
     printf("FIFO non-empty writes: %d, non-empty reads: %d\n", fifoWriteCount, fifoReadCount);
     printf("fill=%d, min=%d, max=%d\n", fifoFillLevel, minFillLevel, maxFillLevel);
-    audio_utils_fifo_deinit(&fifo);
-    delete[] fifoBuffer;
 
+    printf("writing output\n");
     SF_INFO sfinfoout;
     memset(&sfinfoout, 0, sizeof(sfinfoout));
     sfinfoout.samplerate = sfinfoin.samplerate;
@@ -157,14 +230,16 @@ usage:
         return EXIT_FAILURE;
     }
     sf_count_t actualWritten = sf_writef_short(sfout, outputBuffer, framesRead);
-    delete[] inputBuffer;
     delete[] outputBuffer;
-    delete[] fifoBuffer;
+    outputBuffer = NULL;
+
     if (actualWritten != (sf_count_t) framesRead) {
         fprintf(stderr, "%s: unexpected error\n", outputFile);
         sf_close(sfout);
         return EXIT_FAILURE;
     }
     sf_close(sfout);
+    printf("done\n");
+
     return EXIT_SUCCESS;
 }
diff --git a/audio_utils/tests/fifo_threads.cpp b/audio_utils/tests/fifo_threads.cpp
new file mode 100644 (file)
index 0000000..83a0cdf
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <audio_utils/fifo.h>
+extern "C" {
+#include "getch.h"
+}
+
+struct Context {
+    audio_utils_fifo_writer *mInputWriter;
+    audio_utils_fifo_reader *mInputReader;
+    audio_utils_fifo_writer *mTransferWriter;
+    audio_utils_fifo_reader *mTransferReader;
+    audio_utils_fifo_writer *mOutputWriter;
+    audio_utils_fifo_reader *mOutputReader;
+};
+
+void *input_routine(void *arg)
+{
+    Context *context = (Context *) arg;
+    for (;;) {
+        struct timespec timeout;
+        timeout.tv_sec = 30;
+        timeout.tv_nsec = 0;
+        char buffer[4];
+        ssize_t actual = context->mInputReader->read(buffer, sizeof(buffer), &timeout);
+        // TODO this test is unreadable
+        if (actual > 0) {
+            if ((size_t) actual > sizeof(buffer)) {
+                printf("input.read actual = %d\n", (int) actual);
+                abort();
+            }
+            ssize_t actual2 = context->mTransferWriter->write(buffer, actual, &timeout);
+            if (actual2 != actual) {
+                printf("transfer.write(%d) = %d\n", (int) actual, (int) actual2);
+            }
+            //sleep(10);
+        } else if (actual == -ETIMEDOUT) {
+            (void) write(1, "t", 1);
+        } else {
+            printf("input.read actual = %d\n", (int) actual);
+        }
+    }
+    return NULL;
+}
+
+volatile bool outputPaused = false;
+
+void *output_routine(void *arg)
+{
+    Context *context = (Context *) arg;
+    for (;;) {
+        if (outputPaused) {
+            sleep(1);
+            continue;
+        }
+        struct timespec timeout;
+        timeout.tv_sec = 60;
+        timeout.tv_nsec = 0;
+        char buffer[4];
+        ssize_t actual = context->mTransferReader->read(buffer, sizeof(buffer), &timeout);
+        if (actual > 0) {
+            if ((size_t) actual > sizeof(buffer)) {
+                printf("transfer.read actual = %d\n", (int) actual);
+                abort();
+            }
+            ssize_t actual2 = context->mOutputWriter->write(buffer, actual, NULL /*timeout*/);
+            if (actual2 != actual) {
+                printf("output.write(%d) = %d\n", (int) actual, (int) actual2);
+            }
+        } else if (actual == -ETIMEDOUT) {
+            (void) write(1, "T", 1);
+        } else {
+            printf("transfer.read actual = %d\n", (int) actual);
+        }
+    }
+    return NULL;
+}
+
+int main(int argc, char **argv)
+{
+    set_conio_terminal_mode();
+    argc = argc + 0;
+    argv = &argv[0];
+
+    char inputBuffer[16];
+    audio_utils_fifo inputFifo(sizeof(inputBuffer) /*frameCount*/, 1 /*frameSize*/, inputBuffer,
+            true /*throttlesWriter*/);
+    audio_utils_fifo_writer inputWriter(inputFifo);
+    audio_utils_fifo_reader inputReader(inputFifo, true /*throttlesWriter*/);
+    //inputWriter.setHysteresis(sizeof(inputBuffer) * 1/4, sizeof(inputBuffer) * 3/4);
+
+    char transferBuffer[64];
+    audio_utils_fifo transferFifo(sizeof(transferBuffer) /*frameCount*/, 1 /*frameSize*/,
+            transferBuffer, true /*throttlesWriter*/);
+    audio_utils_fifo_writer transferWriter(transferFifo);
+    audio_utils_fifo_reader transferReader(transferFifo, true /*throttlesWriter*/);
+    transferReader.setHysteresis(sizeof(transferBuffer) * 3/4, sizeof(transferBuffer) * 1/4);
+    //transferWriter.setEffective(8);
+
+    char outputBuffer[64];
+    audio_utils_fifo outputFifo(sizeof(outputBuffer) /*frameCount*/, 1 /*frameSize*/, outputBuffer,
+            true /*throttlesWriter*/);
+    audio_utils_fifo_writer outputWriter(outputFifo);
+    audio_utils_fifo_reader outputReader(outputFifo, true /*readerThrottlesWriter*/);
+
+    Context context;
+    context.mInputWriter = &inputWriter;
+    context.mInputReader = &inputReader;
+    context.mTransferWriter = &transferWriter;
+    context.mTransferReader = &transferReader;
+    context.mOutputWriter = &outputWriter;
+    context.mOutputReader = &outputReader;
+
+    pthread_t input_thread;
+    int ok = pthread_create(&input_thread, (const pthread_attr_t *) NULL, input_routine,
+            (void *) &context);
+    pthread_t output_thread;
+    ok = pthread_create(&output_thread, (const pthread_attr_t *) NULL, output_routine,
+            (void *) &context);
+    ok = ok + 0;
+
+    for (;;) {
+        char buffer[4];
+        ssize_t actual = outputReader.read(buffer, sizeof(buffer), NULL /*timeout*/);
+        if (actual > 0) {
+            printf("%.*s", (int) actual, buffer);
+            fflush(stdout);
+        } else if (actual != 0) {
+            printf("outputReader.read actual = %d\n", (int) actual);
+        }
+        if (kbhit()) {
+            int ch = getch();
+            if (ch <= 0 || ch == '\003' /*control-C*/) {
+                break;
+            }
+            if (ch == 'p')
+                outputPaused = true;
+            else if (ch == 'p')
+                outputPaused = false;
+            buffer[0] = ch;
+            actual = inputWriter.write(buffer, 1, NULL /*timeout*/);
+            if (actual != 1) {
+                printf("inputWriter.write actual = %d\n", (int) actual);
+            }
+        }
+    }
+    reset_terminal_mode();
+}
diff --git a/audio_utils/tests/getch.c b/audio_utils/tests/getch.c
new file mode 100644 (file)
index 0000000..446770a
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+C non-blocking keyboard input
+http://stackoverflow.com/questions/448944/c-non-blocking-keyboard-input
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+#include <termios.h>
+#include <unistd.h>
+#include "getch.h"
+
+struct termios orig_termios;
+
+void reset_terminal_mode()
+{
+    tcsetattr(0, TCSANOW, &orig_termios);
+}
+
+void set_conio_terminal_mode()
+{
+    struct termios new_termios;
+
+    /* take two copies - one for now, one for later */
+    tcgetattr(0, &orig_termios);
+    memcpy(&new_termios, &orig_termios, sizeof(new_termios));
+
+    /* register cleanup handler, and set the new terminal mode */
+    atexit(reset_terminal_mode);
+    cfmakeraw(&new_termios);
+    new_termios.c_oflag |= OPOST;
+    tcsetattr(0, TCSANOW, &new_termios);
+}
+
+int kbhit()
+{
+    struct timeval tv = { 0L, 0L };
+    fd_set fds;
+    FD_ZERO(&fds); // not in original posting to stackoverflow
+    FD_SET(0, &fds);
+    return select(1, &fds, NULL, NULL, &tv);
+}
+
+int getch()
+{
+    int r;
+    unsigned char c;
+    if ((r = read(0, &c, sizeof(c))) < 0) {
+        return r;
+    } else {
+        return c;
+    }
+}
+
+#if 0
+int main(int argc, char *argv[])
+{
+    set_conio_terminal_mode();
+
+    while (!kbhit()) {
+        /* do some work */
+    }
+    (void)getch(); /* consume the character */
+}
+#endif
diff --git a/audio_utils/tests/getch.h b/audio_utils/tests/getch.h
new file mode 100644 (file)
index 0000000..41b050d
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+extern int kbhit();
+extern int getch(void);
+extern void set_conio_terminal_mode(void);
+extern void reset_terminal_mode(void);
diff --git a/audio_utils/tests/power_tests.cpp b/audio_utils/tests/power_tests.cpp
new file mode 100644 (file)
index 0000000..b86dac3
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_power_tests"
+
+#include <cmath>
+#include <math.h>
+
+#include <audio_utils/power.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+
+typedef struct { uint8_t c[3]; } __attribute__((__packed__)) uint8x3_t;
+
+void testFloatValue(float f_value, size_t length) {
+    const float power = audio_utils_power_from_amplitude(f_value);
+    float f_ary[length];
+    uint8_t u8_ary[length];
+    int16_t i16_ary[length];
+    int32_t i32_ary[length];
+    int32_t q8_23_ary[length];
+    uint8x3_t p24_ary[length];
+
+    // magic formulas to convert floating point to fixed point representations.
+    // we negate the floating point value to ensure full integer range for 1.f.
+    const uint8_t u8_value((1.f - f_value) * 128);
+    const int16_t i16_value(f_value * INT16_MIN);
+    const int32_t i32_value (f_value * INT32_MIN);
+    const int32_t q8_23_value(f_value * -(1 << 23));
+
+    // PCM_24_BIT_PACKED is native endian.
+#if HAVE_BIG_ENDIAN
+    const uint8x3_t p24_value{{
+        uint8_t(q8_23_value >> 16),
+                uint8_t(q8_23_value >> 8),
+                uint8_t(q8_23_value),
+    }};
+#else
+    const uint8x3_t p24_value{{
+        uint8_t(q8_23_value),
+                uint8_t(q8_23_value >> 8),
+                uint8_t(q8_23_value >> 16),
+    }};
+#endif
+
+    for (size_t i = 0; i < length; ++i) {
+        f_ary[i] = f_value;
+        u8_ary[i] = u8_value;
+        i16_ary[i] = i16_value;
+        i32_ary[i] = i32_value;
+        q8_23_ary[i] = q8_23_value;
+        p24_ary[i] = p24_value;
+    }
+
+    EXPECT_EQ(power,
+            audio_utils_compute_power_mono(f_ary, AUDIO_FORMAT_PCM_FLOAT, length));
+    EXPECT_EQ(power,
+            audio_utils_compute_power_mono(u8_ary, AUDIO_FORMAT_PCM_8_BIT, length));
+    EXPECT_EQ(power,
+            audio_utils_compute_power_mono(i16_ary, AUDIO_FORMAT_PCM_16_BIT, length));
+    EXPECT_EQ(power,
+            audio_utils_compute_power_mono(i32_ary, AUDIO_FORMAT_PCM_32_BIT, length));
+    EXPECT_EQ(power,
+            audio_utils_compute_power_mono(q8_23_ary, AUDIO_FORMAT_PCM_8_24_BIT, length));
+    EXPECT_EQ(power,
+            audio_utils_compute_power_mono(p24_ary, AUDIO_FORMAT_PCM_24_BIT_PACKED, length));
+}
+
+void testFloatRamp(size_t length) {
+    float f_ary[length];
+    uint8_t u8_ary[length];
+    int16_t i16_ary[length];
+    int32_t i32_ary[length];
+    int32_t q8_23_ary[length];
+    uint8x3_t p24_ary[length];
+
+    for (size_t i = 0; i < length; ++i) {
+        // must be expressed cleanly in uint8_t
+        const float f_value = (int(length & 0xff) - 128) / 128.f;
+
+        // magic formulas to convert floating point to fixed point representations.
+        // we negate the floating point value to ensure full integer range for 1.f.
+        const uint8_t u8_value((1.f - f_value) * 128);
+        const int16_t i16_value(f_value * INT16_MIN);
+        const int32_t i32_value (f_value * INT32_MIN);
+        const int32_t q8_23_value(f_value * -(1 << 23));
+
+        // PCM_24_BIT_PACKED is native endian.
+    #if HAVE_BIG_ENDIAN
+        const uint8x3_t p24_value{{
+            uint8_t(q8_23_value >> 16),
+                    uint8_t(q8_23_value >> 8),
+                    uint8_t(q8_23_value),
+        }};
+    #else
+        const uint8x3_t p24_value{{
+            uint8_t(q8_23_value),
+                    uint8_t(q8_23_value >> 8),
+                    uint8_t(q8_23_value >> 16),
+        }};
+    #endif
+
+        f_ary[i] = f_value;
+        u8_ary[i] = u8_value;
+        i16_ary[i] = i16_value;
+        i32_ary[i] = i32_value;
+        q8_23_ary[i] = q8_23_value;
+        p24_ary[i] = p24_value;
+    }
+
+    const float power8 =  audio_utils_compute_power_mono(u8_ary, AUDIO_FORMAT_PCM_8_BIT, length);
+
+    EXPECT_EQ(power8,
+            audio_utils_compute_power_mono(f_ary, AUDIO_FORMAT_PCM_FLOAT, length));
+    EXPECT_EQ(power8,
+            audio_utils_compute_power_mono(i16_ary, AUDIO_FORMAT_PCM_16_BIT, length));
+    EXPECT_EQ(power8,
+            audio_utils_compute_power_mono(i32_ary, AUDIO_FORMAT_PCM_32_BIT, length));
+    EXPECT_EQ(power8,
+            audio_utils_compute_power_mono(q8_23_ary, AUDIO_FORMAT_PCM_8_24_BIT, length));
+    EXPECT_EQ(power8,
+            audio_utils_compute_power_mono(p24_ary, AUDIO_FORMAT_PCM_24_BIT_PACKED, length));
+}
+
+// power_mono implicitly tests energy_mono
+TEST(audio_utils_power, power_mono) {
+    // f_values should have limited mantissa
+    for (float f_value : { 0.f, 0.25f, 0.5f, 0.75f, 1.f }) {
+        const float power = audio_utils_power_from_amplitude(f_value);
+        printf("power_mono: amplitude: %f  power: %f\n", f_value, power);
+
+        for (size_t length : { 1, 3, 5, 7, 16, 21, 32, 37 }) {
+            testFloatValue(f_value, length);
+        }
+    }
+}
+
+// power_mono implicitly tests energy_mono
+TEST(audio_utils_power, power_mono_ramp) {
+    for (size_t length : { 1, 3, 5, 7, 16, 21, 32, 37, 297 }) {
+        testFloatRamp(length);
+    }
+}
+
+TEST(audio_utils_power, power_from) {
+    EXPECT_EQ(0.f, audio_utils_power_from_amplitude(1.f));
+    EXPECT_EQ(-INFINITY, audio_utils_power_from_amplitude(0.f));
+    EXPECT_EQ(0.f, audio_utils_power_from_amplitude(-1.f));
+
+    EXPECT_EQ(0.f, audio_utils_power_from_energy(1.f));
+    EXPECT_EQ(-INFINITY, audio_utils_power_from_energy(0.f));
+    EXPECT_TRUE(std::isnan(audio_utils_power_from_energy(-1.f)));
+}
diff --git a/audio_utils/tests/powerlog_tests.cpp b/audio_utils/tests/powerlog_tests.cpp
new file mode 100644 (file)
index 0000000..2a7988d
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_powerlog_tests"
+
+#include <audio_utils/PowerLog.h>
+#include <gtest/gtest.h>
+#include <iostream>
+#include <log/log.h>
+
+using namespace android;
+
+static size_t countNewLines(const std::string &s) {
+    return std::count(s.begin(), s.end(), '\n');
+}
+
+TEST(audio_utils_powerlog, basic) {
+    auto plog = std::make_unique<PowerLog>(
+            48000 /* sampleRate */,
+            1 /* channelCount */,
+            AUDIO_FORMAT_PCM_16_BIT,
+            100 /* entries */,
+            1 /* framesPerEntry */);
+
+    // header
+    EXPECT_EQ((size_t)1, countNewLines(plog->dumpToString()));
+
+    const int16_t zero = 0;
+    const int16_t half = 0x4000;
+
+    plog->log(&half, 1 /* frame */, 0 /* nowNs */);
+    plog->log(&half, 1 /* frame */, 1 /* nowNs */);
+    plog->log(&half, 1 /* frame */, 2 /* nowNs */);
+
+    // one line / signal
+    EXPECT_EQ((size_t)2, countNewLines(plog->dumpToString()));
+
+    plog->log(&zero, 1 /* frame */, 3 /* nowNs */);
+    // zero termination doesn't change this.
+    EXPECT_EQ((size_t)2, countNewLines(plog->dumpToString()));
+
+    // but adding next line does.
+    plog->log(&half, 1 /* frame */, 4 /* nowNs */);
+    EXPECT_EQ((size_t)3, countNewLines(plog->dumpToString()));
+
+    // truncating on lines
+    EXPECT_EQ((size_t)2, countNewLines(plog->dumpToString(
+            "" /* prefix */, 2 /* lines */)));
+
+    // truncating on time
+    EXPECT_EQ((size_t)3, countNewLines(plog->dumpToString(
+            "" /* prefix */, 0 /* lines */, 2 /* limitNs */)));
+    EXPECT_EQ((size_t)2, countNewLines(plog->dumpToString(
+            "" /* prefix */, 0 /* lines */, 3 /* limitNs */)));
+    plog->dump(0 /* fd (stdout) */);
+
+    // The output below depends on the local time zone.
+    // The indentation below is exact, check alignment.
+    /*
+Signal power history:
+ 12-31 16:00:00.000: [   -6.0   -6.0   -6.0 ] sum(-1.2)
+ 12-31 16:00:00.000: [   -6.0
+     */
+}
+
+TEST(audio_utils_powerlog, c) {
+    power_log_t *power_log = power_log_create(
+            48000 /* sample_rate */,
+            1 /* channel_count */,
+            AUDIO_FORMAT_PCM_16_BIT,
+            100 /* entries */,
+            1 /* frames_per_entry */);
+
+    // sanity test
+    const int16_t zero = 0;
+    const int16_t quarter = 0x2000;
+
+    power_log_log(power_log, &quarter, 1 /* frame */, 0 /* now_ns */);
+    power_log_log(power_log, &zero, 1 /* frame */, 1 /* now_ns */);
+    power_log_dump(power_log, 0 /* fd */, "  " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
+    power_log_destroy(power_log);
+
+    // This has a 2 character prefix offset from the previous test when dumping.
+    // The indentation below is exact, check alignment.
+    /*
+  Signal power history:
+   12-31 16:00:00.000: [  -12.0 ] sum(-12.0)
+     */
+}
diff --git a/audio_utils/tests/simplelog_tests.cpp b/audio_utils/tests/simplelog_tests.cpp
new file mode 100644 (file)
index 0000000..1ef8a83
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_errorlog_tests"
+
+#include <audio_utils/SimpleLog.h>
+#include <gtest/gtest.h>
+#include <iostream>
+#include <log/log.h>
+
+using namespace android;
+
+static size_t countNewLines(const std::string &s) {
+    return std::count(s.begin(), s.end(), '\n');
+}
+
+TEST(audio_utils_simplelog, basic) {
+    auto slog = std::make_unique<SimpleLog>();
+    const int64_t oneSecond = 1000000000;
+
+    EXPECT_EQ((size_t)0, countNewLines(slog->dumpToString()));
+
+    const int nine = 9;
+    slog->log("Hello %d", nine);
+    slog->log("World");
+
+    // two lines (no header)
+    EXPECT_EQ((size_t)2, countNewLines(slog->dumpToString()));
+
+    // another two lines (this is out of time order, but the log doesn't care)
+    slog->log(oneSecond /* nowNs */, "Hello World %d", 10);
+    slog->log(oneSecond * 2 /* nowNs */, "%s", "Goodbye");
+
+    EXPECT_EQ((size_t)4, countNewLines(slog->dumpToString()));
+
+    // truncate on lines
+    EXPECT_EQ((size_t)1, countNewLines(slog->dumpToString("" /* prefix */, 1 /* lines */)));
+
+    // truncate on time
+    EXPECT_EQ((size_t)4, countNewLines(
+            slog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond /* limitNs */)));
+
+    // truncate on time (more)
+    EXPECT_EQ((size_t)3, countNewLines(
+            slog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond * 2 /* limitNs */)));
+
+    // truncate on time (more)
+    EXPECT_EQ((size_t)2, countNewLines(
+            slog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond * 2 + 1 /* limitNs */)));
+
+    std::cout << slog->dumpToString() << std::flush;
+
+    slog->dump(0 /* fd (stdout) */, "  "); // add a prefix
+
+    // The output below depends on the local time zone and current time.
+    // The indentation below is exact, check alignment.
+    /*
+03-27 14:47:43.567 Hello 9
+03-27 14:47:43.567 World
+12-31 16:00:01.000 Hello World 10
+12-31 16:00:02.000 Goodbye
+  03-27 14:47:43.567 Hello 9
+  03-27 14:47:43.567 World
+  12-31 16:00:01.000 Hello World 10
+  12-31 16:00:02.000 Goodbye
+     */
+}
index 16fdb88..ada9fe2 100644 (file)
@@ -63,7 +63,7 @@ LOCAL_SRC_FILES := \
   $(audio_client_sources)
 LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl
 LOCAL_SHARED_LIBRARIES := $(audio_service_shared_libraries)
-LOCAL_CFLAGS := -Wall -std=c++14
+LOCAL_CFLAGS := -Wall -Werror -std=c++14
 include $(BUILD_SHARED_LIBRARY)
 
 # Unit tests for the Brillo audio service.
@@ -105,5 +105,5 @@ LOCAL_STATIC_LIBRARIES := \
   libbinderwrapper_test_support \
   libchrome_test_helpers \
   libgmock
-LOCAL_CFLAGS := -Wno-sign-compare -Wall
+LOCAL_CFLAGS := -Wno-sign-compare -Wall -Werror
 include $(BUILD_NATIVE_TEST)
index 4a2c96f..ba31c56 100644 (file)
@@ -19,7 +19,7 @@ cc_library_shared {
         "-Wextra",
         "-Werror",
         "-fvisibility=hidden",
-        "-std=c99",
+        "-std=c11",
     ],
 
     product_variables: {
index 004ecae..e861312 100644 (file)
             ><a href="#controls_android.control.videoStabilizationMode">android.control.videoStabilizationMode</a></li>
             <li
             ><a href="#controls_android.control.postRawSensitivityBoost">android.control.postRawSensitivityBoost</a></li>
+            <li
+            ><a href="#controls_android.control.enableZsl">android.control.enableZsl</a></li>
           </ul>
         </li>
         <li>
             ><a href="#dynamic_android.control.videoStabilizationMode">android.control.videoStabilizationMode</a></li>
             <li
             ><a href="#dynamic_android.control.postRawSensitivityBoost">android.control.postRawSensitivityBoost</a></li>
+            <li
+            ><a href="#dynamic_android.control.enableZsl">android.control.enableZsl</a></li>
           </ul>
         </li>
       </ul> <!-- toc_section -->
@@ -4226,6 +4230,93 @@ OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
           <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
            <!-- end of entry -->
         
+                
+          <tr class="entry" id="controls_android.control.enableZsl">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>enable<wbr/>Zsl
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FALSE</span>
+                    <span class="entry_type_enum_notes"><p>Requests with <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> == STILL_<wbr/>CAPTURE must be captured
+after previous requests.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TRUE</span>
+                    <span class="entry_type_enum_notes"><p>Requests with <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> == STILL_<wbr/>CAPTURE may or may not be
+captured before previous requests.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Allow camera device to enable zero-shutter-lag mode for requests with
+<a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> == STILL_<wbr/>CAPTURE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If enableZsl is <code>true</code>,<wbr/> the camera device may enable zero-shutter-lag mode for requests with
+STILL_<wbr/>CAPTURE capture intent.<wbr/> The camera device may use images captured in the past to
+produce output images for a zero-shutter-lag request.<wbr/> The result metadata including the
+<a href="#dynamic_android.sensor.timestamp">android.<wbr/>sensor.<wbr/>timestamp</a> reflects the source frames used to produce output images.<wbr/>
+Therefore,<wbr/> the contents of the output images and the result metadata may be out of order
+compared to previous regular requests.<wbr/> enableZsl does not affect requests with other
+capture intents.<wbr/></p>
+<p>For example,<wbr/> when requests are submitted in the following order:
+  Request A: enableZsl is ON,<wbr/> <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> is PREVIEW
+  Request B: enableZsl is ON,<wbr/> <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> is STILL_<wbr/>CAPTURE</p>
+<p>The output images for request B may have contents captured before the output images for
+request A,<wbr/> and the result metadata for request B may be older than the result metadata for
+request A.<wbr/></p>
+<p>Note that when enableZsl is <code>true</code>,<wbr/> it is not guaranteed to get output images captured in
+the past for requests with STILL_<wbr/>CAPTURE capture intent.<wbr/></p>
+<p>For applications targeting SDK versions O and newer,<wbr/> the value of enableZsl in
+TEMPLATE_<wbr/>STILL_<wbr/>CAPTURE template may be <code>true</code>.<wbr/> The value in other templates is always
+<code>false</code> if present.<wbr/></p>
+<p>For applications targeting SDK versions older than O,<wbr/> the value of enableZsl in all
+capture templates is always <code>false</code> if present.<wbr/></p>
+<p>For application-operated ZSL,<wbr/> use CAMERA3_<wbr/>TEMPLATE_<wbr/>ZERO_<wbr/>SHUTTER_<wbr/>LAG template.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>It is valid for HAL to produce regular output images for requests with STILL_<wbr/>CAPTURE
+capture intent.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
         
 
       <!-- end of kind -->
@@ -8872,6 +8963,93 @@ OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
           <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
            <!-- end of entry -->
         
+                
+          <tr class="entry" id="dynamic_android.control.enableZsl">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>enable<wbr/>Zsl
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FALSE</span>
+                    <span class="entry_type_enum_notes"><p>Requests with <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> == STILL_<wbr/>CAPTURE must be captured
+after previous requests.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TRUE</span>
+                    <span class="entry_type_enum_notes"><p>Requests with <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> == STILL_<wbr/>CAPTURE may or may not be
+captured before previous requests.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Allow camera device to enable zero-shutter-lag mode for requests with
+<a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> == STILL_<wbr/>CAPTURE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If enableZsl is <code>true</code>,<wbr/> the camera device may enable zero-shutter-lag mode for requests with
+STILL_<wbr/>CAPTURE capture intent.<wbr/> The camera device may use images captured in the past to
+produce output images for a zero-shutter-lag request.<wbr/> The result metadata including the
+<a href="#dynamic_android.sensor.timestamp">android.<wbr/>sensor.<wbr/>timestamp</a> reflects the source frames used to produce output images.<wbr/>
+Therefore,<wbr/> the contents of the output images and the result metadata may be out of order
+compared to previous regular requests.<wbr/> enableZsl does not affect requests with other
+capture intents.<wbr/></p>
+<p>For example,<wbr/> when requests are submitted in the following order:
+  Request A: enableZsl is ON,<wbr/> <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> is PREVIEW
+  Request B: enableZsl is ON,<wbr/> <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> is STILL_<wbr/>CAPTURE</p>
+<p>The output images for request B may have contents captured before the output images for
+request A,<wbr/> and the result metadata for request B may be older than the result metadata for
+request A.<wbr/></p>
+<p>Note that when enableZsl is <code>true</code>,<wbr/> it is not guaranteed to get output images captured in
+the past for requests with STILL_<wbr/>CAPTURE capture intent.<wbr/></p>
+<p>For applications targeting SDK versions O and newer,<wbr/> the value of enableZsl in
+TEMPLATE_<wbr/>STILL_<wbr/>CAPTURE template may be <code>true</code>.<wbr/> The value in other templates is always
+<code>false</code> if present.<wbr/></p>
+<p>For applications targeting SDK versions older than O,<wbr/> the value of enableZsl in all
+capture templates is always <code>false</code> if present.<wbr/></p>
+<p>For application-operated ZSL,<wbr/> use CAMERA3_<wbr/>TEMPLATE_<wbr/>ZERO_<wbr/>SHUTTER_<wbr/>LAG template.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>It is valid for HAL to produce regular output images for requests with STILL_<wbr/>CAPTURE
+capture intent.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
         
 
       <!-- end of kind -->
index a1a5fac..f800efe 100644 (file)
@@ -2792,6 +2792,58 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
         <clone entry="android.control.postRawSensitivityBoost" kind="controls">
         </clone>
       </dynamic>
+      <controls>
+        <entry name="enableZsl" type="byte" visibility="public" enum="true" typedef="boolean">
+          <enum>
+            <value>FALSE
+            <notes>Requests with android.control.captureIntent == STILL_CAPTURE must be captured
+              after previous requests.</notes></value>
+            <value>TRUE
+            <notes>Requests with android.control.captureIntent == STILL_CAPTURE may or may not be
+              captured before previous requests.</notes></value>
+          </enum>
+          <description>Allow camera device to enable zero-shutter-lag mode for requests with
+            android.control.captureIntent == STILL_CAPTURE.
+          </description>
+          <details>
+          If enableZsl is `true`, the camera device may enable zero-shutter-lag mode for requests with
+          STILL_CAPTURE capture intent. The camera device may use images captured in the past to
+          produce output images for a zero-shutter-lag request. The result metadata including the
+          android.sensor.timestamp reflects the source frames used to produce output images.
+          Therefore, the contents of the output images and the result metadata may be out of order
+          compared to previous regular requests. enableZsl does not affect requests with other
+          capture intents.
+
+          For example, when requests are submitted in the following order:
+            Request A: enableZsl is ON, android.control.captureIntent is PREVIEW
+            Request B: enableZsl is ON, android.control.captureIntent is STILL_CAPTURE
+
+          The output images for request B may have contents captured before the output images for
+          request A, and the result metadata for request B may be older than the result metadata for
+          request A.
+
+          Note that when enableZsl is `true`, it is not guaranteed to get output images captured in
+          the past for requests with STILL_CAPTURE capture intent.
+
+          For applications targeting SDK versions O and newer, the value of enableZsl in
+          TEMPLATE_STILL_CAPTURE template may be `true`. The value in other templates is always
+          `false` if present.
+
+          For applications targeting SDK versions older than O, the value of enableZsl in all
+          capture templates is always `false` if present.
+
+          For application-operated ZSL, use CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG template.
+          </details>
+          <hal_details>
+          It is valid for HAL to produce regular output images for requests with STILL_CAPTURE
+          capture intent.
+          </hal_details>
+        </entry>
+      </controls>
+      <dynamic>
+        <clone entry="android.control.enableZsl" kind="controls">
+        </clone>
+      </dynamic>
     </section>
     <section name="demosaic">
       <controls>
index a424c3d..cb346f3 100644 (file)
@@ -2810,6 +2810,58 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
         <clone entry="android.control.postRawSensitivityBoost" kind="controls">
         </clone>
       </dynamic>
+      <controls>
+        <entry name="enableZsl" type="byte" visibility="public" enum="true" typedef="boolean">
+          <enum>
+            <value>FALSE
+            <notes>Requests with android.control.captureIntent == STILL_CAPTURE must be captured
+              after previous requests.</notes></value>
+            <value>TRUE
+            <notes>Requests with android.control.captureIntent == STILL_CAPTURE may or may not be
+              captured before previous requests.</notes></value>
+          </enum>
+          <description>Allow camera device to enable zero-shutter-lag mode for requests with
+            android.control.captureIntent == STILL_CAPTURE.
+          </description>
+          <details>
+          If enableZsl is `true`, the camera device may enable zero-shutter-lag mode for requests with
+          STILL_CAPTURE capture intent. The camera device may use images captured in the past to
+          produce output images for a zero-shutter-lag request. The result metadata including the
+          android.sensor.timestamp reflects the source frames used to produce output images.
+          Therefore, the contents of the output images and the result metadata may be out of order
+          compared to previous regular requests. enableZsl does not affect requests with other
+          capture intents.
+
+          For example, when requests are submitted in the following order:
+            Request A: enableZsl is `true`, android.control.captureIntent is PREVIEW
+            Request B: enableZsl is `true`, android.control.captureIntent is STILL_CAPTURE
+
+          The output images for request B may have contents captured before the output images for
+          request A, and the result metadata for request B may be older than the result metadata for
+          request A.
+
+          Note that when enableZsl is `true`, it is not guaranteed to get output images captured in the
+          past for requests with STILL_CAPTURE capture intent.
+
+          For applications targeting SDK versions O and newer, the value of enableZsl in
+          TEMPLATE_STILL_CAPTURE template may be `true`. The value in other templates is always
+          `false` if present.
+
+          For applications targeting SDK versions older than O, the value of enableZsl in all
+          capture templates is always `false` if present.
+
+          For application-operated ZSL, use CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG template.
+          </details>
+          <hal_details>
+          It is valid for HAL to produce regular output images for requests with STILL_CAPTURE
+          capture intent.
+          </hal_details>
+        </entry>
+      </controls>
+      <dynamic>
+        <clone entry="android.control.enableZsl" kind="controls">
+        </clone>
+      </dynamic>
     </section>
     <section name="demosaic">
       <controls>
index 9de902b..46e7ac0 100644 (file)
@@ -20,7 +20,6 @@
 #include <string.h>
 #include <stdint.h>
 #include <cutils/compiler.h>
-#include <system/camera_vendor_tags.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -279,6 +278,13 @@ ANDROID_API
 camera_metadata_t *copy_camera_metadata(void *dst, size_t dst_size,
         const camera_metadata_t *src);
 
+
+// Non-zero return values for validate_camera_metadata_structure
+enum {
+    CAMERA_METADATA_VALIDATION_ERROR = 1,
+    CAMERA_METADATA_VALIDATION_SHIFTED = 2,
+};
+
 /**
  * Validate that a metadata is structurally sane. That is, its internal
  * state is such that we won't get buffer overflows or run into other
@@ -290,7 +296,11 @@ camera_metadata_t *copy_camera_metadata(void *dst, size_t dst_size,
  *
  * The expected_size argument is optional.
  *
- * Returns 0 on success. A non-0 value is returned on error.
+ * Returns 0: on success
+ *         CAMERA_METADATA_VALIDATION_ERROR: on error
+ *         CAMERA_METADATA_VALIDATION_SHIFTED: when the data is not properly aligned, but can be
+ *                 used as input of clone_camera_metadata and the returned metadata will be valid.
+ *
  */
 ANDROID_API
 int validate_camera_metadata_structure(const camera_metadata_t *metadata,
@@ -448,6 +458,29 @@ ANDROID_API
 int get_camera_metadata_tag_type(uint32_t tag);
 
 /**
+ * Retrieve human-readable name of section the tag is in. Returns NULL if
+ * no such tag is defined.
+ */
+ANDROID_API
+const char *get_local_camera_metadata_section_name(uint32_t tag,
+        const camera_metadata_t *meta);
+
+/**
+ * Retrieve human-readable name of tag (not including section). Returns NULL if
+ * no such tag is defined.
+ */
+ANDROID_API
+const char *get_local_camera_metadata_tag_name(uint32_t tag,
+        const camera_metadata_t *meta);
+
+/**
+ * Retrieve the type of a tag. Returns -1 if no such tag is defined.
+ */
+ANDROID_API
+int get_local_camera_metadata_tag_type(uint32_t tag,
+        const camera_metadata_t *meta);
+
+/**
  * Set up vendor-specific tag query methods. These are needed to properly add
  * entries with vendor-specified tags and to use the
  * get_camera_metadata_section_name, _tag_name, and _tag_type methods with
index 81dac87..9c2956f 100644 (file)
@@ -160,6 +160,7 @@ typedef enum camera_metadata_tag {
     ANDROID_CONTROL_AVAILABLE_MODES,                  // byte[]       | public
     ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE, // int32[]      | public
     ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,       // int32        | public
+    ANDROID_CONTROL_ENABLE_ZSL,                       // enum         | public
     ANDROID_CONTROL_END,
 
     ANDROID_DEMOSAIC_MODE =                           // enum         | system
@@ -605,6 +606,12 @@ typedef enum camera_metadata_enum_android_control_awb_lock_available {
     ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE,
 } camera_metadata_enum_android_control_awb_lock_available_t;
 
+// ANDROID_CONTROL_ENABLE_ZSL
+typedef enum camera_metadata_enum_android_control_enable_zsl {
+    ANDROID_CONTROL_ENABLE_ZSL_FALSE,
+    ANDROID_CONTROL_ENABLE_ZSL_TRUE,
+} camera_metadata_enum_android_control_enable_zsl_t;
+
 
 // ANDROID_DEMOSAIC_MODE
 typedef enum camera_metadata_enum_android_demosaic_mode {
index 57cba49..0bb5426 100644 (file)
@@ -22,6 +22,9 @@ extern "C" {
 #endif
 
 #define CAMERA_METADATA_VENDOR_TAG_BOUNDARY 0x80000000u
+#define CAMERA_METADATA_INVALID_VENDOR_ID UINT64_MAX
+
+typedef uint64_t metadata_vendor_id_t;
 
 /**
  * Vendor tags:
@@ -90,6 +93,63 @@ struct vendor_tag_ops {
     void* reserved[8];
 };
 
+struct vendor_tag_cache_ops {
+    /**
+     * Get the number of vendor tags supported on this platform. Used to
+     * calculate the size of buffer needed for holding the array of all tags
+     * returned by get_all_tags().  This must return -1 on error.
+     */
+    int (*get_tag_count)(metadata_vendor_id_t id);
+
+    /**
+     * Fill an array with all of the supported vendor tags on this platform.
+     * get_tag_count() must return the number of tags supported, and
+     * tag_array will be allocated with enough space to hold the number of tags
+     * returned by get_tag_count().
+     */
+    void (*get_all_tags)(uint32_t *tag_array, metadata_vendor_id_t id);
+
+    /**
+     * Get the vendor section name for a vendor-specified entry tag. This will
+     * only be called for vendor-defined tags.
+     *
+     * The naming convention for the vendor-specific section names should
+     * follow a style similar to the Java package style.  For example,
+     * CameraZoom Inc. must prefix their sections with "com.camerazoom."
+     * This must return NULL if the tag is outside the bounds of
+     * vendor-defined sections.
+     *
+     * There may be different vendor-defined tag sections, for example the
+     * phone maker, the chipset maker, and the camera module maker may each
+     * have their own "com.vendor."-prefixed section.
+     *
+     * The memory pointed to by the return value must remain valid for the
+     * lifetime of the module, and is owned by the module.
+     */
+    const char *(*get_section_name)(uint32_t tag, metadata_vendor_id_t id);
+
+    /**
+     * Get the tag name for a vendor-specified entry tag. This is only called
+     * for vendor-defined tags, and must return NULL if it is not a
+     * vendor-defined tag.
+     *
+     * The memory pointed to by the return value must remain valid for the
+     * lifetime of the module, and is owned by the module.
+     */
+    const char *(*get_tag_name)(uint32_t tag, metadata_vendor_id_t id);
+
+    /**
+     * Get tag type for a vendor-specified entry tag. The type returned must be
+     * a valid type defined in camera_metadata.h.  This method is only called
+     * for tags >= CAMERA_METADATA_VENDOR_TAG_BOUNDARY, and must return
+     * -1 if the tag is outside the bounds of the vendor-defined sections.
+     */
+    int (*get_tag_type)(uint32_t tag, metadata_vendor_id_t id);
+
+    /* Reserved for future use.  These must be initialized to NULL. */
+    void* reserved[8];
+};
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index 156f5ab..dc80086 100644 (file)
@@ -101,7 +101,8 @@ struct camera_metadata {
     metadata_size_t          data_count;
     metadata_size_t          data_capacity;
     metadata_uptrdiff_t      data_start; // Offset from camera_metadata
-    uint8_t                  reserved[];
+    uint32_t                 padding;    // padding to 8 bytes boundary
+    metadata_vendor_id_t     vendor_id;
 };
 
 /**
@@ -120,6 +121,49 @@ typedef union camera_metadata_data {
     camera_metadata_rational_t r;
 } camera_metadata_data_t;
 
+_Static_assert(sizeof(metadata_size_t) == 4,
+         "Size of metadata_size_t must be 4");
+_Static_assert(sizeof(metadata_uptrdiff_t) == 4,
+         "Size of metadata_uptrdiff_t must be 4");
+_Static_assert(sizeof(metadata_vendor_id_t) == 8,
+         "Size of metadata_vendor_id_t must be 8");
+_Static_assert(sizeof(camera_metadata_data_t) == 8,
+         "Size of camera_metadata_data_t must be 8");
+
+_Static_assert(offsetof(camera_metadata_buffer_entry_t, tag) == 0,
+         "Offset of tag must be 0");
+_Static_assert(offsetof(camera_metadata_buffer_entry_t, count) == 4,
+         "Offset of count must be 4");
+_Static_assert(offsetof(camera_metadata_buffer_entry_t, data) == 8,
+         "Offset of data must be 8");
+_Static_assert(offsetof(camera_metadata_buffer_entry_t, type) == 12,
+         "Offset of type must be 12");
+_Static_assert(sizeof(camera_metadata_buffer_entry_t) == 16,
+         "Size of camera_metadata_buffer_entry_t must be 16");
+
+_Static_assert(offsetof(camera_metadata_t, size) == 0,
+         "Offset of size must be 0");
+_Static_assert(offsetof(camera_metadata_t, version) == 4,
+         "Offset of version must be 4");
+_Static_assert(offsetof(camera_metadata_t, flags) == 8,
+         "Offset of flags must be 8");
+_Static_assert(offsetof(camera_metadata_t, entry_count) == 12,
+         "Offset of entry_count must be 12");
+_Static_assert(offsetof(camera_metadata_t, entry_capacity) == 16,
+         "Offset of entry_capacity must be 16");
+_Static_assert(offsetof(camera_metadata_t, entries_start) == 20,
+         "Offset of entries_start must be 20");
+_Static_assert(offsetof(camera_metadata_t, data_count) == 24,
+         "Offset of data_count must be 24");
+_Static_assert(offsetof(camera_metadata_t, data_capacity) == 28,
+         "Offset of data_capacity must be 28");
+_Static_assert(offsetof(camera_metadata_t, data_start) == 32,
+         "Offset of data_start must be 32");
+_Static_assert(offsetof(camera_metadata_t, vendor_id) == 40,
+         "Offset of vendor_id must be 40");
+_Static_assert(sizeof(camera_metadata_t) == 48,
+         "Size of camera_metadata_t must be 48");
+
 /**
  * The preferred alignment of a packet of camera metadata. In general,
  * this is the lowest common multiple of the constituents of a metadata
@@ -127,7 +171,7 @@ typedef union camera_metadata_data {
  */
 #define MAX_ALIGNMENT(A, B) (((A) > (B)) ? (A) : (B))
 #define METADATA_PACKET_ALIGNMENT \
-    MAX_ALIGNMENT(MAX_ALIGNMENT(DATA_ALIGNMENT, METADATA_ALIGNMENT), ENTRY_ALIGNMENT);
+    MAX_ALIGNMENT(MAX_ALIGNMENT(DATA_ALIGNMENT, METADATA_ALIGNMENT), ENTRY_ALIGNMENT)
 
 /** Versioning information */
 #define CURRENT_METADATA_VERSION 1
@@ -236,6 +280,7 @@ camera_metadata_t *place_camera_metadata(void *dst,
     size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
             metadata->entry_capacity) - (uint8_t*)metadata;
     metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
+    metadata->vendor_id = CAMERA_METADATA_INVALID_VENDOR_ID;
 
     assert(validate_camera_metadata_structure(metadata, NULL) == OK);
     return metadata;
@@ -253,6 +298,8 @@ size_t calculate_camera_metadata_size(size_t entry_count,
     // Start buffer list at aligned boundary
     memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
     memory_needed += sizeof(uint8_t[data_count]);
+    // Make sure camera metadata can be stacked in continuous memory
+    memory_needed = ALIGN_TO(memory_needed, METADATA_PACKET_ALIGNMENT);
     return memory_needed;
 }
 
@@ -298,6 +345,7 @@ camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
     metadata->flags = src->flags;
     metadata->entry_count = src->entry_count;
     metadata->data_count = src->data_count;
+    metadata->vendor_id = src->vendor_id;
 
     memcpy(get_entries(metadata), get_entries(src),
             sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
@@ -345,9 +393,12 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
 
     if (metadata == NULL) {
         ALOGE("%s: metadata is null!", __FUNCTION__);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
+    uintptr_t aligned_ptr = ALIGN_TO(metadata, METADATA_PACKET_ALIGNMENT);
+    const uintptr_t alignmentOffset = aligned_ptr - (uintptr_t) metadata;
+
     // Check that the metadata pointer is well-aligned first.
     {
         static const struct {
@@ -369,14 +420,15 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
         };
 
         for (size_t i = 0; i < sizeof(alignments)/sizeof(alignments[0]); ++i) {
-            uintptr_t aligned_ptr = ALIGN_TO(metadata, alignments[i].alignment);
+            uintptr_t aligned_ptr = ALIGN_TO((uintptr_t) metadata + alignmentOffset,
+                    alignments[i].alignment);
 
-            if ((uintptr_t)metadata != aligned_ptr) {
+            if ((uintptr_t)metadata + alignmentOffset != aligned_ptr) {
                 ALOGE("%s: Metadata pointer is not aligned (actual %p, "
-                      "expected %p) to type %s",
+                      "expected %p, offset %" PRIuPTR ") to type %s",
                       __FUNCTION__, metadata,
-                      (void*)aligned_ptr, alignments[i].name);
-                return ERROR;
+                      (void*)aligned_ptr, alignmentOffset, alignments[i].name);
+                return CAMERA_METADATA_VALIDATION_ERROR;
             }
         }
     }
@@ -388,14 +440,14 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
     if (expected_size != NULL && metadata->size > *expected_size) {
         ALOGE("%s: Metadata size (%" PRIu32 ") should be <= expected size (%zu)",
               __FUNCTION__, metadata->size, *expected_size);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     if (metadata->entry_count > metadata->entry_capacity) {
         ALOGE("%s: Entry count (%" PRIu32 ") should be <= entry capacity "
               "(%" PRIu32 ")",
               __FUNCTION__, metadata->entry_count, metadata->entry_capacity);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     if (metadata->data_count > metadata->data_capacity) {
@@ -403,7 +455,7 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
               "(%" PRIu32 ")",
               __FUNCTION__, metadata->data_count, metadata->data_capacity);
         android_errorWriteLog(SN_EVENT_LOG_ID, "30591838");
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     const metadata_uptrdiff_t entries_end =
@@ -416,7 +468,7 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                __FUNCTION__,
               (metadata->entries_start + metadata->entry_capacity),
               metadata->data_start);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     const metadata_uptrdiff_t data_end =
@@ -429,7 +481,7 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                __FUNCTION__,
               (metadata->data_start + metadata->data_capacity),
               metadata->size);
-        return ERROR;
+        return CAMERA_METADATA_VALIDATION_ERROR;
     }
 
     // Validate each entry
@@ -438,11 +490,12 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
 
     for (size_t i = 0; i < entry_count; ++i) {
 
-        if ((uintptr_t)&entries[i] != ALIGN_TO(&entries[i], ENTRY_ALIGNMENT)) {
+        if ((uintptr_t)&entries[i] + alignmentOffset !=
+                ALIGN_TO((uintptr_t)&entries[i] + alignmentOffset, ENTRY_ALIGNMENT)) {
             ALOGE("%s: Entry index %zu had bad alignment (address %p),"
                   " expected alignment %zu",
                   __FUNCTION__, i, &entries[i], ENTRY_ALIGNMENT);
-            return ERROR;
+            return CAMERA_METADATA_VALIDATION_ERROR;
         }
 
         camera_metadata_buffer_entry_t entry = entries[i];
@@ -450,17 +503,17 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
         if (entry.type >= NUM_TYPES) {
             ALOGE("%s: Entry index %zu had a bad type %d",
                   __FUNCTION__, i, entry.type);
-            return ERROR;
+            return CAMERA_METADATA_VALIDATION_ERROR;
         }
 
         // TODO: fix vendor_tag_ops across processes so we don't need to special
         //       case vendor-specific tags
         uint32_t tag_section = entry.tag >> 16;
-        int tag_type = get_camera_metadata_tag_type(entry.tag);
+        int tag_type = get_local_camera_metadata_tag_type(entry.tag, metadata);
         if (tag_type != (int)entry.type && tag_section < VENDOR_SECTION) {
             ALOGE("%s: Entry index %zu had tag type %d, but the type was %d",
                   __FUNCTION__, i, tag_type, entry.type);
-            return ERROR;
+            return CAMERA_METADATA_VALIDATION_ERROR;
         }
 
         size_t data_size;
@@ -468,7 +521,7 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                 entry.count) != OK) {
             ALOGE("%s: Entry data size is invalid. type: %u count: %u", __FUNCTION__, entry.type,
                     entry.count);
-            return ERROR;
+            return CAMERA_METADATA_VALIDATION_ERROR;
         }
 
         if (data_size != 0) {
@@ -476,13 +529,14 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                     (camera_metadata_data_t*) (get_data(metadata) +
                                                entry.data.offset);
 
-            if ((uintptr_t)data != ALIGN_TO(data, DATA_ALIGNMENT)) {
+            if ((uintptr_t)data + alignmentOffset !=
+                        ALIGN_TO((uintptr_t)data + alignmentOffset, DATA_ALIGNMENT)) {
                 ALOGE("%s: Entry index %zu had bad data alignment (address %p),"
                       " expected align %zu, (tag name %s, data size %zu)",
                       __FUNCTION__, i, data, DATA_ALIGNMENT,
-                      get_camera_metadata_tag_name(entry.tag) ?: "unknown",
-                      data_size);
-                return ERROR;
+                      get_local_camera_metadata_tag_name(entry.tag, metadata) ?
+                              : "unknown", data_size);
+                return CAMERA_METADATA_VALIDATION_ERROR;
             }
 
             size_t data_entry_end = entry.data.offset + data_size;
@@ -492,20 +546,23 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
                 ALOGE("%s: Entry index %zu data ends (%zu) beyond the capacity "
                       "%" PRIu32, __FUNCTION__, i, data_entry_end,
                       metadata->data_capacity);
-                return ERROR;
+                return CAMERA_METADATA_VALIDATION_ERROR;
             }
 
         } else if (entry.count == 0) {
             if (entry.data.offset != 0) {
                 ALOGE("%s: Entry index %zu had 0 items, but offset was non-0 "
                      "(%" PRIu32 "), tag name: %s", __FUNCTION__, i, entry.data.offset,
-                        get_camera_metadata_tag_name(entry.tag) ?: "unknown");
-                return ERROR;
+                        get_local_camera_metadata_tag_name(entry.tag, metadata) ? : "unknown");
+                return CAMERA_METADATA_VALIDATION_ERROR;
             }
         } // else data stored inline, so we look at value which can be anything.
     }
 
-    return OK;
+    if (alignmentOffset == 0) {
+        return OK;
+    }
+    return CAMERA_METADATA_VALIDATION_SHIFTED;
 }
 
 int append_camera_metadata(camera_metadata_t *dst,
@@ -519,6 +576,15 @@ int append_camera_metadata(camera_metadata_t *dst,
     if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
     if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
 
+    if ((dst->vendor_id != CAMERA_METADATA_INVALID_VENDOR_ID) &&
+            (src->vendor_id != CAMERA_METADATA_INVALID_VENDOR_ID)) {
+        if (dst->vendor_id != src->vendor_id) {
+            ALOGE("%s: Append for metadata from different vendors is"
+                    "not supported!", __func__);
+            return ERROR;
+        }
+    }
+
     memcpy(get_entries(dst) + dst->entry_count, get_entries(src),
             sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
     memcpy(get_data(dst) + dst->data_count, get_data(src),
@@ -544,6 +610,10 @@ int append_camera_metadata(camera_metadata_t *dst,
     dst->entry_count += src->entry_count;
     dst->data_count += src->data_count;
 
+    if (dst->vendor_id == CAMERA_METADATA_INVALID_VENDOR_ID) {
+        dst->vendor_id = src->vendor_id;
+    }
+
     assert(validate_camera_metadata_structure(dst, NULL) == OK);
     return OK;
 }
@@ -607,7 +677,7 @@ int add_camera_metadata_entry(camera_metadata_t *dst,
         const void *data,
         size_t data_count) {
 
-    int type = get_camera_metadata_tag_type(tag);
+    int type = get_local_camera_metadata_tag_type(tag, dst);
     if (type == -1) {
         ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
         return ERROR;
@@ -826,10 +896,16 @@ int update_camera_metadata_entry(camera_metadata_t *dst,
 }
 
 static const vendor_tag_ops_t *vendor_tag_ops = NULL;
+static const struct vendor_tag_cache_ops *vendor_cache_ops = NULL;
 
-const char *get_camera_metadata_section_name(uint32_t tag) {
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+const char *get_local_camera_metadata_section_name_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id) {
     uint32_t tag_section = tag >> 16;
-    if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
+    if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL &&
+               id != CAMERA_METADATA_INVALID_VENDOR_ID) {
+           return vendor_cache_ops->get_section_name(tag, id);
+    } else if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
         return vendor_tag_ops->get_section_name(
             vendor_tag_ops,
             tag);
@@ -840,9 +916,14 @@ const char *get_camera_metadata_section_name(uint32_t tag) {
     return camera_metadata_section_names[tag_section];
 }
 
-const char *get_camera_metadata_tag_name(uint32_t tag) {
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+const char *get_local_camera_metadata_tag_name_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id) {
     uint32_t tag_section = tag >> 16;
-    if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
+    if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL &&
+                id != CAMERA_METADATA_INVALID_VENDOR_ID) {
+            return vendor_cache_ops->get_tag_name(tag, id);
+    } else  if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
         return vendor_tag_ops->get_tag_name(
             vendor_tag_ops,
             tag);
@@ -855,9 +936,14 @@ const char *get_camera_metadata_tag_name(uint32_t tag) {
     return tag_info[tag_section][tag_index].tag_name;
 }
 
-int get_camera_metadata_tag_type(uint32_t tag) {
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+int get_local_camera_metadata_tag_type_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id) {
     uint32_t tag_section = tag >> 16;
-    if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
+    if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL &&
+                id != CAMERA_METADATA_INVALID_VENDOR_ID) {
+            return vendor_cache_ops->get_tag_type(tag, id);
+    } else if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
         return vendor_tag_ops->get_tag_type(
             vendor_tag_ops,
             tag);
@@ -870,6 +956,42 @@ int get_camera_metadata_tag_type(uint32_t tag) {
     return tag_info[tag_section][tag_index].tag_type;
 }
 
+const char *get_camera_metadata_section_name(uint32_t tag) {
+    return get_local_camera_metadata_section_name(tag, NULL);
+}
+
+const char *get_camera_metadata_tag_name(uint32_t tag) {
+    return get_local_camera_metadata_tag_name(tag, NULL);
+}
+
+int get_camera_metadata_tag_type(uint32_t tag) {
+    return get_local_camera_metadata_tag_type(tag, NULL);
+}
+
+const char *get_local_camera_metadata_section_name(uint32_t tag,
+        const camera_metadata_t *meta) {
+    metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
+            meta->vendor_id;
+
+    return get_local_camera_metadata_section_name_vendor_id(tag, id);
+}
+
+const char *get_local_camera_metadata_tag_name(uint32_t tag,
+        const camera_metadata_t *meta) {
+    metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
+            meta->vendor_id;
+
+    return get_local_camera_metadata_tag_name_vendor_id(tag, id);
+}
+
+int get_local_camera_metadata_tag_type(uint32_t tag,
+        const camera_metadata_t *meta) {
+    metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
+            meta->vendor_id;
+
+    return get_local_camera_metadata_tag_type_vendor_id(tag, id);
+}
+
 int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t* ops) {
     // **DEPRECATED**
     (void) ops;
@@ -883,6 +1005,33 @@ int set_camera_metadata_vendor_ops(const vendor_tag_ops_t* ops) {
     return OK;
 }
 
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+int set_camera_metadata_vendor_cache_ops(
+        const struct vendor_tag_cache_ops *query_cache_ops) {
+    vendor_cache_ops = query_cache_ops;
+    return OK;
+}
+
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+void set_camera_metadata_vendor_id(camera_metadata_t *meta,
+        metadata_vendor_id_t id) {
+    if (NULL != meta) {
+        meta->vendor_id = id;
+    }
+}
+
+// Declared in system/media/private/camera/include/camera_metadata_hidden.h
+metadata_vendor_id_t get_camera_metadata_vendor_id(
+        const camera_metadata_t *meta) {
+    metadata_vendor_id_t ret = CAMERA_METADATA_INVALID_VENDOR_ID;
+
+    if (NULL != meta) {
+        ret = meta->vendor_id;
+    }
+
+    return ret;
+}
+
 static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type,
         int count,
         int indentation);
@@ -915,11 +1064,11 @@ void dump_indented_camera_metadata(const camera_metadata_t *metadata,
     for (i=0; i < metadata->entry_count; i++, entry++) {
 
         const char *tag_name, *tag_section;
-        tag_section = get_camera_metadata_section_name(entry->tag);
+        tag_section = get_local_camera_metadata_section_name(entry->tag, metadata);
         if (tag_section == NULL) {
             tag_section = "unknownSection";
         }
-        tag_name = get_camera_metadata_tag_name(entry->tag);
+        tag_name = get_local_camera_metadata_tag_name(entry->tag, metadata);
         if (tag_name == NULL) {
             tag_name = "unknownTag";
         }
index 1716a84..23af44b 100644 (file)
@@ -216,6 +216,8 @@ static tag_info_t android_control[ANDROID_CONTROL_END -
     { "postRawSensitivityBoostRange",  TYPE_INT32  },
     [ ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST - ANDROID_CONTROL_START ] =
     { "postRawSensitivityBoost",       TYPE_INT32  },
+    [ ANDROID_CONTROL_ENABLE_ZSL - ANDROID_CONTROL_START ] =
+    { "enableZsl",                     TYPE_BYTE   },
 };
 
 static tag_info_t android_demosaic[ANDROID_DEMOSAIC_END -
@@ -1350,6 +1352,21 @@ int camera_metadata_enum_snprint(uint32_t tag,
         case ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST: {
             break;
         }
+        case ANDROID_CONTROL_ENABLE_ZSL: {
+            switch (value) {
+                case ANDROID_CONTROL_ENABLE_ZSL_FALSE:
+                    msg = "FALSE";
+                    ret = 0;
+                    break;
+                case ANDROID_CONTROL_ENABLE_ZSL_TRUE:
+                    msg = "TRUE";
+                    ret = 0;
+                    break;
+                default:
+                    msg = "error: enum value out of range";
+            }
+            break;
+        }
 
         case ANDROID_DEMOSAIC_MODE: {
             switch (value) {
index 121ce19..bcebf2e 100644 (file)
@@ -1870,3 +1870,37 @@ TEST(camera_metadata, data_alignment) {
         }
     }
 }
+
+TEST(camera_metadata, buffer_alignment) {
+    // Verify that misaligned metadata buffers only fail VALIDATION_SHIFTED, nothing else
+    const size_t entry_capacity = 50;
+    const size_t data_capacity = 450;
+    const size_t offsetRange = 16;
+    const uint32_t validAlignment = 8;
+
+    camera_metadata_t *m = NULL;
+    m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+    add_test_metadata(m, 15);
+
+    size_t m_size = get_camera_metadata_size(m);
+    size_t dst_size = m_size + offsetRange;
+    uint8_t *dst = new uint8_t[dst_size];
+
+    for (size_t i = 0; i < offsetRange; i++) {
+        memset(dst, 0, dst_size);
+        memcpy(dst + i, m, m_size);
+        camera_metadata_t *m_shifted = (camera_metadata_t*)(dst + i);
+
+        int err = validate_camera_metadata_structure(m_shifted, &m_size);
+        if (i % validAlignment == 0) {
+            ASSERT_EQ(OK, err) << "For alignment shift " << i << ", expected OK" ;
+        } else {
+            ASSERT_EQ(CAMERA_METADATA_VALIDATION_SHIFTED, err) <<
+                    "For alignment shift " << i << ", expected VALIDATION_SHIFTED" ;
+        }
+    }
+
+    delete[] dst;
+    FINISH_USING_CAMERA_METADATA(m);
+}
index c5e0a39..31f1ad1 100644 (file)
@@ -42,6 +42,57 @@ extern "C" {
 ANDROID_API
 int set_camera_metadata_vendor_ops(const vendor_tag_ops_t *query_ops);
 
+/**
+ * Set the global vendor tag cache operations object used to define vendor tag
+ * structure when parsing camera metadata with functions defined in
+ * system/media/camera/include/camera_metadata.h.
+ */
+ANDROID_API
+int set_camera_metadata_vendor_cache_ops(
+        const struct vendor_tag_cache_ops *query_cache_ops);
+
+/**
+ * Set the vendor id for a particular metadata buffer.
+ */
+ANDROID_API
+void set_camera_metadata_vendor_id(camera_metadata_t *meta,
+        metadata_vendor_id_t id);
+
+/**
+ * Retrieve the vendor id for a particular metadata buffer.
+ */
+ANDROID_API
+metadata_vendor_id_t get_camera_metadata_vendor_id(
+        const camera_metadata_t *meta);
+
+/**
+ * Retrieve the type of a tag. Returns -1 if no such tag is defined.
+ */
+ANDROID_API
+int get_local_camera_metadata_tag_type_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id);
+
+/**
+ * Retrieve the name of a tag. Returns NULL if no such tag is defined.
+ */
+ANDROID_API
+const char *get_local_camera_metadata_tag_name_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id);
+
+/**
+ * Retrieve the name of a tag section. Returns NULL if no such tag is defined.
+ */
+ANDROID_API
+const char *get_local_camera_metadata_section_name_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id);
+
+/**
+ * Retrieve the type of a tag. Returns -1 if no such tag is defined.
+ */
+ANDROID_API
+int get_local_camera_metadata_tag_type_vendor_id(uint32_t tag,
+        metadata_vendor_id_t id);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index 7dc35cc..45db916 100644 (file)
@@ -46,7 +46,7 @@ enum {
     RADIO_METADATA_KEY_MIN          = RADIO_METADATA_KEY_RDS_PI,
     RADIO_METADATA_KEY_MAX          = RADIO_METADATA_KEY_CLOCK,
 };
-typedef int radio_metadata_key_t;
+typedef int32_t radio_metadata_key_t;
 
 enum {
     RADIO_METADATA_TYPE_INVALID    = -1,
@@ -56,7 +56,7 @@ enum {
     RADIO_METADATA_TYPE_RAW        = 2,      /* raw binary data (icon or art) */
     RADIO_METADATA_TYPE_CLOCK      = 3,      /* clock data, see radio_metadata_clock_t */
 };
-typedef int radio_metadata_type_t;
+typedef int32_t radio_metadata_type_t;
 
 typedef struct radio_metadata_clock {
     uint64_t utc_seconds_since_epoch;            /* Seconds since epoch at GMT + 0. */
@@ -90,8 +90,8 @@ radio_metadata_type_t radio_metadata_type_of_key(const radio_metadata_key_t key)
  */
 ANDROID_API
 int radio_metadata_allocate(radio_metadata_t **metadata,
-                            const unsigned int channel,
-                            const unsigned int sub_channel);
+                            const uint32_t channel,
+                            const uint32_t sub_channel);
 
 /*
  * De-allocate a meta data buffer.
@@ -119,7 +119,7 @@ void radio_metadata_deallocate(radio_metadata_t *metadata);
 ANDROID_API
 int radio_metadata_add_int(radio_metadata_t **metadata,
                            const radio_metadata_key_t key,
-                           const int value);
+                           const int32_t value);
 
 /*
  * Add an text meta data to the buffer.
@@ -159,7 +159,7 @@ ANDROID_API
 int radio_metadata_add_raw(radio_metadata_t **metadata,
                            const radio_metadata_key_t key,
                            const unsigned char *value,
-                           const unsigned int size);
+                           const size_t size);
 
 /*
  * Add a clock meta data to the buffer.
@@ -255,11 +255,11 @@ int radio_metadata_get_count(const radio_metadata_t *metadata);
  */
 ANDROID_API
 int radio_metadata_get_at_index(const radio_metadata_t *metadata,
-                                const unsigned int index,
+                                const uint32_t index,
                                 radio_metadata_key_t *key,
                                 radio_metadata_type_t *type,
                                 void **value,
-                                unsigned int *size);
+                                size_t *size);
 
 /*
  * Get a meta data with the specified key.
@@ -284,7 +284,24 @@ int radio_metadata_get_from_key(const radio_metadata_t *metadata,
                                 const radio_metadata_key_t key,
                                 radio_metadata_type_t *type,
                                 void **value,
-                                unsigned int *size);
+                                size_t *size);
+
+/*
+ * Get channel and sub channel associated with metadata.
+ *
+ * arguments:
+ * - metadata: the meta data buffer
+ * - channel: address where to return the channel.
+ * - sub_channel: address where to return the sub channel.
+ *
+ * returns:
+ *  0 if successfully added
+ *  -EINVAL if the buffer passed is invalid
+ */
+ANDROID_API
+int radio_metadata_get_channel(radio_metadata_t *metadata,
+                               uint32_t *channel,
+                               uint32_t *sub_channel);
 
 #ifdef __cplusplus
 }
index 21a73fc..9e593fb 100644 (file)
@@ -56,14 +56,16 @@ bool is_valid_metadata_key(const radio_metadata_key_t key)
     return true;
 }
 
-int check_size(radio_metadata_buffer_t **metadata_ptr, const unsigned int size_int)
+int check_size(radio_metadata_buffer_t **metadata_ptr, const uint32_t size_int)
 {
     radio_metadata_buffer_t *metadata = *metadata_ptr;
-    unsigned int index_offset = metadata->size_int - metadata->count - 1;
-    unsigned int data_offset = *((unsigned int *)metadata + index_offset);
-    unsigned int req_size_int;
-    unsigned int new_size_int;
+    uint32_t index_offset = metadata->size_int - metadata->count - 1;
+    uint32_t data_offset = *((uint32_t *)metadata + index_offset);
+    uint32_t req_size_int;
+    uint32_t new_size_int;
 
+    LOG_ALWAYS_FATAL_IF(metadata->size_int < (metadata->count + 1),
+                        "%s: invalid size %u", __func__, metadata->size_int);
     if (size_int == 0) {
         return 0;
     }
@@ -84,11 +86,11 @@ int check_size(radio_metadata_buffer_t **metadata_ptr, const unsigned int size_i
         new_size_int *= 2;
 
     ALOGV("%s growing from %u to %u", __func__, metadata->size_int, new_size_int);
-    metadata = realloc(metadata, new_size_int * sizeof(unsigned int));
+    metadata = realloc(metadata, new_size_int * sizeof(uint32_t));
     /* move index table */
-    memmove((unsigned int *)metadata + new_size_int - (metadata->count + 1),
-            (unsigned int *)metadata + metadata->size_int - (metadata->count + 1),
-            (metadata->count + 1) * sizeof(unsigned int));
+    memmove((uint32_t *)metadata + new_size_int - (metadata->count + 1),
+            (uint32_t *)metadata + metadata->size_int - (metadata->count + 1),
+            (metadata->count + 1) * sizeof(uint32_t));
     metadata->size_int = new_size_int;
 
     *metadata_ptr = metadata;
@@ -100,17 +102,17 @@ int add_metadata(radio_metadata_buffer_t **metadata_ptr,
                  const radio_metadata_key_t key,
                  const radio_metadata_type_t type,
                  const void *value,
-                 const unsigned int size)
+                 const size_t size)
 {
-    unsigned int entry_size_int;
+    uint32_t entry_size_int;
     int ret;
     radio_metadata_entry_t *entry;
-    unsigned int index_offset;
-    unsigned int data_offset;
+    uint32_t index_offset;
+    uint32_t data_offset;
     radio_metadata_buffer_t *metadata = *metadata_ptr;
 
-    entry_size_int = size + sizeof(radio_metadata_entry_t);
-    entry_size_int = (entry_size_int + sizeof(unsigned int) - 1) / sizeof(unsigned int);
+    entry_size_int = (uint32_t)(size + sizeof(radio_metadata_entry_t));
+    entry_size_int = (entry_size_int + sizeof(uint32_t) - 1) / sizeof(uint32_t);
 
     ret = check_size(metadata_ptr, entry_size_int);
     if (ret < 0) {
@@ -118,17 +120,18 @@ int add_metadata(radio_metadata_buffer_t **metadata_ptr,
     }
     metadata = *metadata_ptr;
     index_offset = metadata->size_int - metadata->count - 1;
-    data_offset = *((unsigned int *)metadata + index_offset);
+    data_offset = *((uint32_t *)metadata + index_offset);
 
-    entry = (radio_metadata_entry_t *)((unsigned int *)metadata + data_offset);
+    entry = (radio_metadata_entry_t *)((uint32_t *)metadata + data_offset);
     entry->key = key;
     entry->type = type;
-    entry->size = size;
+    entry->size = (uint32_t)size;
     memcpy(entry->data, value, size);
 
     data_offset += entry_size_int;
-    *((unsigned int *)metadata + index_offset -1) = data_offset;
+    *((uint32_t *)metadata + index_offset -1) = data_offset;
     metadata->count++;
+
     return 0;
 }
 
@@ -137,29 +140,36 @@ radio_metadata_entry_t *get_entry_at_index(
                                     const unsigned index,
                                     bool check)
 {
-    unsigned int index_offset = metadata->size_int - index - 1;
-    unsigned int data_offset = *((unsigned int *)metadata + index_offset);
+    uint32_t index_offset = metadata->size_int - index - 1;
+    uint32_t data_offset = *((uint32_t *)metadata + index_offset);
 
+    LOG_ALWAYS_FATAL_IF(metadata->size_int < (index + 1),
+                        "%s: invalid size %u", __func__, metadata->size_int);
     if (check) {
         if (index >= metadata->count) {
             return NULL;
         }
-        unsigned int min_offset;
-        unsigned int max_offset;
-        unsigned int min_entry_size_int;
-        min_offset = (sizeof(radio_metadata_buffer_t) + sizeof(unsigned int) - 1) /
-                        sizeof(unsigned int);
+        uint32_t min_offset;
+        uint32_t max_offset;
+        uint32_t min_entry_size_int;
+        min_offset = (sizeof(radio_metadata_buffer_t) + sizeof(uint32_t) - 1) /
+                        sizeof(uint32_t);
         if (data_offset < min_offset) {
             return NULL;
         }
         min_entry_size_int = 1 + sizeof(radio_metadata_entry_t);
-        min_entry_size_int = (min_entry_size_int + sizeof(unsigned int) - 1) / sizeof(unsigned int);
+        min_entry_size_int = (min_entry_size_int + sizeof(uint32_t) - 1) / sizeof(uint32_t);
+
+        LOG_ALWAYS_FATAL_IF(metadata->size_int < (metadata->count + 1),
+                            "%s: invalid size %u vs count %u", __func__,
+                            metadata->size_int, metadata->count);
+
         max_offset = metadata->size_int - metadata->count - 1 - min_entry_size_int;
         if (data_offset > max_offset) {
             return NULL;
         }
     }
-    return (radio_metadata_entry_t *)((unsigned int *)metadata + data_offset);
+    return (radio_metadata_entry_t *)((uint32_t *)metadata + data_offset);
 }
 
 /**
@@ -175,11 +185,11 @@ radio_metadata_type_t radio_metadata_type_of_key(const radio_metadata_key_t key)
 }
 
 int radio_metadata_allocate(radio_metadata_t **metadata,
-                            const unsigned int channel,
-                            const unsigned int sub_channel)
+                            const uint32_t channel,
+                            const uint32_t sub_channel)
 {
     radio_metadata_buffer_t *metadata_buf =
-            (radio_metadata_buffer_t *)calloc(RADIO_METADATA_DEFAULT_SIZE, sizeof(unsigned int));
+            (radio_metadata_buffer_t *)calloc(RADIO_METADATA_DEFAULT_SIZE, sizeof(uint32_t));
     if (metadata_buf == NULL) {
         return -ENOMEM;
     }
@@ -187,9 +197,9 @@ int radio_metadata_allocate(radio_metadata_t **metadata,
     metadata_buf->channel = channel;
     metadata_buf->sub_channel = sub_channel;
     metadata_buf->size_int = RADIO_METADATA_DEFAULT_SIZE;
-    *((unsigned int *)metadata_buf + RADIO_METADATA_DEFAULT_SIZE - 1) =
-            (sizeof(radio_metadata_buffer_t) + sizeof(unsigned int) - 1) /
-                sizeof(unsigned int);
+    *((uint32_t *)metadata_buf + RADIO_METADATA_DEFAULT_SIZE - 1) =
+            (sizeof(radio_metadata_buffer_t) + sizeof(uint32_t) - 1) /
+                sizeof(uint32_t);
     *metadata = (radio_metadata_t *)metadata_buf;
     return 0;
 }
@@ -201,14 +211,14 @@ void radio_metadata_deallocate(radio_metadata_t *metadata)
 
 int radio_metadata_add_int(radio_metadata_t **metadata,
                            const radio_metadata_key_t key,
-                           const int value)
+                           const int32_t value)
 {
     radio_metadata_type_t type = radio_metadata_type_of_key(key);
     if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_INT) {
         return -EINVAL;
     }
     return add_metadata((radio_metadata_buffer_t **)metadata,
-                        key, type, &value, sizeof(int));
+                        key, type, &value, sizeof(int32_t));
 }
 
 int radio_metadata_add_text(radio_metadata_t **metadata,
@@ -226,7 +236,7 @@ int radio_metadata_add_text(radio_metadata_t **metadata,
 int radio_metadata_add_raw(radio_metadata_t **metadata,
                            const radio_metadata_key_t key,
                            const unsigned char *value,
-                           const unsigned int size)
+                           const size_t size)
 {
     radio_metadata_type_t type = radio_metadata_type_of_key(key);
     if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_RAW || value == NULL) {
@@ -254,7 +264,7 @@ int radio_metadata_add_metadata(radio_metadata_t **dst_metadata,
     radio_metadata_buffer_t *src_metadata_buf = (radio_metadata_buffer_t *)src_metadata;
     radio_metadata_buffer_t *dst_metadata_buf;
     int status;
-    unsigned int index;
+    uint32_t index;
 
     if (dst_metadata == NULL || src_metadata == NULL) {
         return -EINVAL;
@@ -275,7 +285,7 @@ int radio_metadata_add_metadata(radio_metadata_t **dst_metadata,
         radio_metadata_key_t key;
         radio_metadata_type_t type;
         void *value;
-        unsigned int size;
+        size_t size;
         status = radio_metadata_get_at_index(src_metadata, index, &key, &type, &value, &size);
         if (status != 0)
             continue;
@@ -290,8 +300,8 @@ int radio_metadata_check(const radio_metadata_t *metadata)
 {
     radio_metadata_buffer_t *metadata_buf =
             (radio_metadata_buffer_t *)metadata;
-    unsigned int count;
-    unsigned int min_entry_size_int;
+    uint32_t count;
+    uint32_t min_entry_size_int;
 
     if (metadata_buf == NULL) {
         return -EINVAL;
@@ -303,10 +313,10 @@ int radio_metadata_check(const radio_metadata_t *metadata)
 
     /* sanity check on entry count versus buffer size */
     min_entry_size_int = 1 + sizeof(radio_metadata_entry_t);
-    min_entry_size_int = (min_entry_size_int + sizeof(unsigned int) - 1) /
-                                sizeof(unsigned int);
+    min_entry_size_int = (min_entry_size_int + sizeof(uint32_t) - 1) /
+                                sizeof(uint32_t);
     if ((metadata_buf->count * min_entry_size_int + metadata_buf->count + 1 +
-            (sizeof(radio_metadata_buffer_t) + sizeof(unsigned int) - 1) / sizeof(unsigned int)) >
+            (sizeof(radio_metadata_buffer_t) + sizeof(uint32_t) - 1) / sizeof(uint32_t)) >
                     metadata_buf->size_int) {
         return -EINVAL;
     }
@@ -343,7 +353,7 @@ size_t radio_metadata_get_size(const radio_metadata_t *metadata)
     if (metadata_buf == NULL) {
         return 0;
     }
-    return (size_t)(metadata_buf->size_int * sizeof(unsigned int));
+    return metadata_buf->size_int * sizeof(uint32_t);
 }
 
 int radio_metadata_get_count(const radio_metadata_t *metadata)
@@ -358,11 +368,11 @@ int radio_metadata_get_count(const radio_metadata_t *metadata)
 }
 
 int radio_metadata_get_at_index(const radio_metadata_t *metadata,
-                                const unsigned int index,
+                                const uint32_t index,
                                 radio_metadata_key_t *key,
                                 radio_metadata_type_t *type,
                                 void **value,
-                                unsigned int *size)
+                                size_t *size)
 {
     radio_metadata_entry_t *entry;
     radio_metadata_buffer_t *metadata_buf =
@@ -380,7 +390,7 @@ int radio_metadata_get_at_index(const radio_metadata_t *metadata,
     *key = entry->key;
     *type = entry->type;
     *value = (void *)entry->data;
-    *size = entry->size;
+    *size = (size_t)entry->size;
 
     return 0;
 }
@@ -389,9 +399,9 @@ int radio_metadata_get_from_key(const radio_metadata_t *metadata,
                                 const radio_metadata_key_t key,
                                 radio_metadata_type_t *type,
                                 void **value,
-                                unsigned int *size)
+                                size_t *size)
 {
-    unsigned int count;
+    uint32_t count;
     radio_metadata_entry_t *entry = NULL;
     radio_metadata_buffer_t *metadata_buf =
             (radio_metadata_buffer_t *)metadata;
@@ -414,6 +424,21 @@ int radio_metadata_get_from_key(const radio_metadata_t *metadata,
     }
     *type = entry->type;
     *value = (void *)entry->data;
-    *size = entry->size;
+    *size = (size_t)entry->size;
+    return 0;
+}
+
+int radio_metadata_get_channel(radio_metadata_t *metadata,
+                               uint32_t *channel,
+                               uint32_t *sub_channel)
+{
+    radio_metadata_buffer_t *metadata_buf =
+            (radio_metadata_buffer_t *)metadata;
+
+    if (metadata_buf == NULL || channel == NULL || sub_channel == NULL) {
+        return -EINVAL;
+    }
+    *channel = metadata_buf->channel;
+    *sub_channel = metadata_buf->sub_channel;
     return 0;
 }
index 1b76aa0..8bdbad4 100644 (file)
@@ -30,8 +30,8 @@
 typedef struct radio_metadata_entry {
     radio_metadata_key_t    key;
     radio_metadata_type_t   type;
-    unsigned int            size;
-    unsigned char           data[];
+    uint32_t                size;
+    uint8_t                 data[];
 } radio_metadata_entry_t;
 
 
@@ -75,10 +75,10 @@ typedef struct radio_metadata_entry {
 
 /* Radio meta data buffer header */
 typedef struct radio_metadata_buffer {
-    unsigned int channel;       /* channel (frequency) this meta data is associated with */
-    unsigned int sub_channel;   /* sub channel this meta data is associated with */
-    unsigned int size_int;      /* Total size in 32 bit word units */
-    unsigned int count;         /* number of meta data entries */
+    uint32_t channel;       /* channel (frequency) this meta data is associated with */
+    uint32_t sub_channel;   /* sub channel this meta data is associated with */
+    uint32_t size_int;      /* Total size in 32 bit word units */
+    uint32_t count;         /* number of meta data entries */
 } radio_metadata_buffer_t;