aml_amaudioutils: audio hal utilities library [1/1]

PD#SWPL-17555

Problem:
This is the initial import of the utility library
to support audio hal implementation on Linux.

Solution:
This library is added on Linux for:
1. The resampler routines from speex
2. The Android SPDIF encoder
3. Partial Android libcutils support needed
as dependencies for audio hal.

Verify:
Local

Change-Id: I28cbc154c82bf6c395aba2f066a2fe0e6f6349db
Signed-off-by: Tim Yao <tim.yao@amlogic.com>
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..10e9b30
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,62 @@
+OBJS=src/primitives.o \
+	src/resampler.o \
+	src/speexresample/resample.o \
+	src/spdif/AC3FrameScanner.o \
+	src/spdif/BitFieldParser.o \
+	src/spdif/DTSFrameScanner.o \
+	src/spdif/FrameScanner.o \
+	src/spdif/SPDIFEncoder.o
+
+CUTILS_OBJS=src/cutils/hashmap.o \
+	src/cutils/properties.o \
+	src/cutils/str_parms.o \
+	src/cutils/threads.o \
+	src/cutils/strlcpy.o
+
+CFLAGS+=-fPIC -O2 -I./include -I./include/speex -I. -I./src -I./src/ -mfpu=neon -DFIXED_POINT -DRESAMPLE_FORCE_FULL_SINC_TABLE -D_USE_NEON -DEXPORT=
+LDFLAGS+=-llog -ldl -lrt -lpthread -lstdc++
+
+%.o: %.cpp
+	$(CC) -c $(CFLAGS) $(CXXFLAGS) -o $@ $<
+
+%.o: %.cc
+	$(CC) -c $(CFLAGS) $(CXXFLAGS) -o $@ $<
+
+%.o: %.c
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+all: libamaudioutils.so libcutils.so
+
+libamaudioutils.so: $(OBJS)
+	$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^
+
+libcutils.so: $(CUTILS_OBJS)
+	$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^
+
+.PHONY: install
+install:
+	install -m 644 -D libamaudioutils.so -t $(STAGING_DIR)/usr/lib
+	install -m 644 -D libamaudioutils.so -t $(TARGET_DIR)/usr/lib
+	install -m 644 -D libcutils.so -t $(STAGING_DIR)/usr/lib
+	install -m 644 -D libcutils.so -t $(TARGET_DIR)/usr/lib
+	for f in $(@D)/include/audio_utils/*.h; do \
+		install -m 644 -D $${f} -t $(STAGING_DIR)/usr/include/audio_utils; \
+	done
+	for f in $(@D)/include/audio_utils/spdif/*.h; do \
+		install -m 644 -D $${f} -t $(STAGING_DIR)/usr/include/audio_utils/spdif; \
+	done
+	for f in $(@D)/include/cutils/*.h; do \
+		install -m 644 -D $${f} -t $(STAGING_DIR)/usr/include/cutils; \
+	done
+	for f in $(@D)/include/android/*.h; do \
+		install -m 644 -D $${f} -t $(STAGING_DIR)/usr/include/android; \
+	done
+
+.PHONY: clean
+clean:
+	rm -rf $(STAGING_DIR)/usr/include/audio_utils
+	rm -rf $(STAGING_DIR)/usr/include/cutils
+	rm -f libamaudioutils.so
+	rm -f $(TARGET_DIR)/usr/lib/libamaudioutils.so
+	rm -f $(STAGING_DIR)/usr/lib/libamaudioutils.so
+
diff --git a/include/android/log.h b/include/android/log.h
new file mode 100644
index 0000000..1f96220
--- /dev/null
+++ b/include/android/log.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2009 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_LOG_H
+#define _ANDROID_LOG_H
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ *   This file is part of Android's set of stable system headers
+ *   exposed by the Android NDK (Native Development Kit) since
+ *   platform release 1.5
+ *
+ *   Third-party source AND binary code relies on the definitions
+ *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+/*
+ * Support routines to send messages to the Android in-kernel log buffer,
+ * which can later be accessed through the 'logcat' utility.
+ *
+ * Each log message must have
+ *   - a priority
+ *   - a log tag
+ *   - some text
+ *
+ * The tag normally corresponds to the component that emits the log message,
+ * and should be reasonably small.
+ *
+ * Log message text may be truncated to less than an implementation-specific
+ * limit (e.g. 1023 characters max).
+ *
+ * Note that a newline character ("\n") will be appended automatically to your
+ * log message, if not already there. It is not possible to send several messages
+ * and have them appear on a single line in logcat.
+ *
+ * PLEASE USE LOGS WITH MODERATION:
+ *
+ *  - Sending log messages eats CPU and slow down your application and the
+ *    system.
+ *
+ *  - The circular log buffer is pretty small (<64KB), sending many messages
+ *    might push off other important log messages from the rest of the system.
+ *
+ *  - In release builds, only send log messages to account for exceptional
+ *    conditions.
+ *
+ * NOTE: These functions MUST be implemented by /system/lib/liblog.so
+ */
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Android log priority values, in ascending priority order.
+ */
+typedef enum android_LogPriority {
+    ANDROID_LOG_UNKNOWN = 0,
+    ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
+    ANDROID_LOG_VERBOSE,
+    ANDROID_LOG_DEBUG,
+    ANDROID_LOG_INFO,
+    ANDROID_LOG_WARN,
+    ANDROID_LOG_ERROR,
+    ANDROID_LOG_FATAL,
+    ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
+} android_LogPriority;
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_write(int prio, const char *tag, const char *text);
+
+/*
+ * Send a formatted string to the log, used like printf(fmt,...)
+ */
+int __android_log_print(int prio, const char *tag,  const char *fmt, ...)
+#if defined(__GNUC__)
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+    ;
+
+/*
+ * A variant of __android_log_print() that takes a va_list to list
+ * additional parameters.
+ */
+int __android_log_vprint(int prio, const char *tag,
+                         const char *fmt, va_list ap);
+
+/*
+ * Log an assertion failure and SIGTRAP the process to have a chance
+ * to inspect it, if a debugger is attached. This uses the FATAL priority.
+ */
+void __android_log_assert(const char *cond, const char *tag,
+			  const char *fmt, ...)
+#if defined(__GNUC__)
+    __attribute__ ((noreturn))
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+    ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ANDROID_LOG_H */
diff --git a/include/audio_utils/channels.h b/include/audio_utils/channels.h
new file mode 100644
index 0000000..10026f4
--- /dev/null
+++ b/include/audio_utils/channels.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 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_CHANNELS_H
+#define ANDROID_AUDIO_CHANNELS_H
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+/**
+ * Expands or contracts sample data from one interleaved channel format to another.
+ * Expanded channels are filled with zeros and put at the end of each audio frame.
+ * Contracted channels are omitted from the end of each audio frame.
+ *
+ *   \param in_buff              points to the buffer of samples
+ *   \param in_buff_chans        Specifies the number of channels in the input buffer.
+ *   \param out_buff             points to the buffer to receive converted samples.
+ *   \param out_buff_chans       Specifies the number of channels in the output buffer.
+ *   \param sample_size_in_bytes Specifies the number of bytes per sample. 1, 2, 3, 4 are
+ *     currently valid.
+ *   \param num_in_bytes         size of input buffer in BYTES
+ *
+ * \return
+ *   the number of BYTES of output data or 0 if an error occurs.
+ *
+ * \note
+ *   The out and sums buffers must either be completely separate (non-overlapping), or
+ *   they must both start at the same address. Partially overlapping buffers are not supported.
+ */
+size_t adjust_channels(const void* in_buff, size_t in_buff_chans,
+                       void* out_buff, size_t out_buff_chans,
+                       unsigned sample_size_in_bytes, size_t num_in_bytes);
+
+/**
+ * Expands or contracts sample data from one interleaved channel format to another.
+ * Extra expanded channels are left alone in the output buffer.
+ * Contracted channels are omitted from the end of each audio frame.
+ *
+ *   \param in_buff              points to the buffer of samples
+ *   \param in_buff_chans        Specifies the number of channels in the input buffer.
+ *   \param out_buff             points to the buffer to receive converted samples.
+ *   \param out_buff_chans       Specifies the number of channels in the output buffer.
+ *   \param sample_size_in_bytes Specifies the number of bytes per sample. 1, 2, 3, 4 are
+ *     currently valid.
+ *   \param num_in_bytes         size of input buffer in BYTES
+ *
+ * \return
+ *   the number of BYTES of output data or 0 if an error occurs.
+ *
+ * \note
+ *   The out and in buffers must either be completely separate (non-overlapping), or
+ *   they must both start at the same address. Partially overlapping buffers are not supported.
+ */
+size_t adjust_selected_channels(const void* in_buff, size_t in_buff_chans,
+                       void* out_buff, size_t out_buff_chans,
+                       unsigned sample_size_in_bytes, size_t num_in_bytes);
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif
diff --git a/include/audio_utils/primitives.h b/include/audio_utils/primitives.h
new file mode 100644
index 0000000..a3727d7
--- /dev/null
+++ b/include/audio_utils/primitives.h
@@ -0,0 +1,1199 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_AUDIO_PRIMITIVES_H
+#define ANDROID_AUDIO_PRIMITIVES_H
+
+#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/cdefs.h>
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+/**
+ * \file primitives.h
+ * The memcpy_* conversion routines are designed to work in-place on same dst as src
+ * buffers only if the types shrink on copy, with the exception of memcpy_to_i16_from_u8().
+ * This allows the loops to go upwards for faster cache access (and may be more flexible
+ * for future optimization later).
+ */
+
+/**
+ * Deprecated. Use memcpy_to_i16_from_q4_27() instead (double the pairs for the count).
+ * Neither this function nor memcpy_to_i16_from_q4_27() actually dither.
+ *
+ * Dither and clamp pairs of 32-bit input samples (sums) to 16-bit output samples (out).
+ * Each 32-bit input sample can be viewed as a signed fixed-point Q19.12 of which the
+ * .12 fraction bits are dithered and the 19 integer bits are clamped to signed 16 bits.
+ * Alternatively the input can be viewed as Q4.27, of which the lowest .12 of the fraction
+ * is dithered and the remaining fraction is converted to the output Q.15, with clamping
+ * on the 4 integer guard bits.
+ *
+ * For interleaved stereo, pairs is the number of sample pairs,
+ * and out is an array of interleaved pairs of 16-bit samples per channel.
+ * For mono, pairs is the number of samples / 2, and out is an array of 16-bit samples.
+ * The name "dither" is a misnomer; the current implementation does not actually dither
+ * but uses truncation.  This may change.
+ * The out and sums buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void ditherAndClamp(int32_t *out, const int32_t *sums, size_t pairs);
+
+/**
+ * Copy samples from signed fixed-point 32-bit Q4.27 to 16-bit Q0.15
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_i16_from_q4_27(int16_t *dst, const int32_t *src, size_t count);
+
+/**
+ * Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count);
+
+/**
+ * Shrink and copy samples from signed 16-bit to unsigned 8-bit offset by 0x80.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ * The conversion is done by truncation, without dithering, so it loses resolution.
+ */
+void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count);
+
+/**
+ * Copy samples from float to unsigned 8-bit offset by 0x80.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ * The conversion is done by truncation, without dithering, so it loses resolution.
+ */
+void memcpy_to_u8_from_float(uint8_t *dst, const float *src, size_t count);
+
+/**
+ * Shrink and copy samples from signed 32-bit fixed-point Q0.31 to signed 16-bit Q0.15.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ * The conversion is done by truncation, without dithering, so it loses resolution.
+ */
+void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count);
+
+/**
+ * Shrink and copy samples from single-precision floating-point to signed 16-bit.
+ * Each float should be in the range -1.0 to 1.0.  Values outside that range are clamped,
+ * refer to clamp16_from_float().
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ * The conversion is done by truncation, without dithering, so it loses resolution.
+ */
+void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count);
+
+/**
+ * Copy samples from signed fixed-point 32-bit Q4.27 to single-precision floating-point.
+ * The nominal output float range is [-1.0, 1.0] if the fixed-point range is
+ * [0xf8000000, 0x07ffffff].  The full float range is [-16.0, 16.0].  Note the closed range
+ * at 1.0 and 16.0 is due to rounding on conversion to float. See float_from_q4_27() for details.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_float_from_q4_27(float *dst, const int32_t *src, size_t count);
+
+/**
+ * Copy samples from signed fixed-point 16 bit Q0.15 to single-precision floating-point.
+ * The output float range is [-1.0, 1.0) for the fixed-point range [0x8000, 0x7fff].
+ * No rounding is needed as the representation is exact.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_float_from_i16(float *dst, const int16_t *src, size_t count);
+
+/**
+ * Copy samples from unsigned fixed-point 8 bit to single-precision floating-point.
+ * The output float range is [-1.0, 1.0) for the fixed-point range [0x00, 0xFF].
+ * No rounding is needed as the representation is exact.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_float_from_u8(float *dst, const uint8_t *src, size_t count);
+
+/**
+ * Copy samples from signed fixed-point packed 24 bit Q0.23 to single-precision floating-point.
+ * The packed 24 bit input is stored in native endian format in a uint8_t byte array.
+ * The output float range is [-1.0, 1.0) for the fixed-point range [0x800000, 0x7fffff].
+ * No rounding is needed as the representation is exact.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count);
+
+/**
+ * Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed point 16 bit Q0.15.
+ * The packed 24 bit output is stored in native endian format in a uint8_t byte array.
+ * The data is truncated without rounding.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count);
+
+/**
+ * Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed-point 32-bit Q0.31.
+ * The packed 24 bit input is stored in native endian format in a uint8_t byte array.
+ * The output data range is [0x80000000, 0x7fffff00] at intervals of 0x100.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_i32_from_p24(int32_t *dst, const uint8_t *src, size_t count);
+
+/**
+ * Copy samples from signed fixed point 16 bit Q0.15 to signed fixed-point packed 24 bit Q0.23.
+ * The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
+ * The output data range is [0x800000, 0x7fff00] (not full).
+ * Nevertheless there is no DC offset on the output, if the input has no DC offset.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count);
+
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point packed 24 bit Q0.23.
+ * The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
+ * The data is clamped and rounded to nearest, ties away from zero. See clamp24_from_float()
+ * for details.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count);
+
+/**
+ * Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed-point packed 24 bit Q0.23.
+ * The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
+ * The data is clamped to the range is [0x800000, 0x7fffff].
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.
+ */
+void memcpy_to_p24_from_q8_23(uint8_t *dst, const int32_t *src, size_t count);
+
+/**
+ * Shrink and copy samples from signed 32-bit fixed-point Q0.31
+ * to signed fixed-point packed 24 bit Q0.23.
+ * The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ * The conversion is done by truncation, without dithering, so it loses resolution.
+ */
+void memcpy_to_p24_from_i32(uint8_t *dst, const int32_t *src, size_t count);
+
+/**
+ * Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q8.23.
+ * The output data range is [0xff800000, 0x007fff00] at intervals of 0x100.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_q8_23_from_i16(int32_t *dst, const int16_t *src, size_t count);
+
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point 32-bit Q8.23.
+ * This copy will clamp the Q8.23 representation to [0xff800000, 0x007fffff] even though there
+ * are guard bits available. Fractional lsb is rounded to nearest, ties away from zero.
+ * See clamp24_from_float() for details.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_t count);
+
+/**
+ * Copy samples from signed fixed point packed 24-bit Q0.23 to signed fixed-point 32-bit Q8.23.
+ * The output data range is [0xff800000, 0x007fffff].
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_q8_23_from_p24(int32_t *dst, const uint8_t *src, size_t count);
+
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point 32-bit Q4.27.
+ * The conversion will use the full available Q4.27 range, including guard bits.
+ * Fractional lsb is rounded to nearest, ties away from zero.
+ * See clampq4_27_from_float() for details.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_q4_27_from_float(int32_t *dst, const float *src, size_t count);
+
+/**
+ * Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed point 16-bit Q0.15.
+ * The data is clamped, and truncated without rounding.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_i16_from_q8_23(int16_t *dst, const int32_t *src, size_t count);
+
+/**
+ * Copy samples from signed fixed-point 32-bit Q8.23 to single-precision floating-point.
+ * The nominal output float range is [-1.0, 1.0) for the fixed-point
+ * range [0xff800000, 0x007fffff]. The maximum output float range is [-256.0, 256.0).
+ * No rounding is needed as the representation is exact for nominal values.
+ * Rounding for overflow values is to nearest, ties to even.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_float_from_q8_23(float *dst, const int32_t *src, size_t count);
+
+/**
+ * Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q0.31.
+ * The output data range is [0x80000000, 0x7fff0000] at intervals of 0x10000.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_i32_from_i16(int32_t *dst, const int16_t *src, size_t count);
+
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point 32-bit Q0.31.
+ * If rounding is needed on truncation, the fractional lsb is rounded to nearest,
+ * ties away from zero. See clamp32_from_float() for details.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_i32_from_float(int32_t *dst, const float *src, size_t count);
+
+/**
+ * Copy samples from signed fixed-point 32-bit Q0.31 to single-precision floating-point.
+ * The float range is [-1.0, 1.0] for the fixed-point range [0x80000000, 0x7fffffff].
+ * Rounding is done according to float_from_i32().
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void memcpy_to_float_from_i32(float *dst, const int32_t *src, size_t count);
+
+/**
+ * Copy samples from unrestricted float to range restricted float [-absMax, absMax].
+ * Any float sample not in the range [-absMax, absMax] will be clamped in this range.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *  \param absMax  Maximum of the absolute value of the copied samples.
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ * Note: NAN is clamped to absMax and not 0 for performance reason (~2xfaster).
+ */
+void memcpy_to_float_from_float_with_clamping(float *dst, const float *src, size_t count,
+                                              float absMax);
+
+/**
+ * Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of stereo frames to downmix
+ *
+ * The destination and source buffers must be completely separate (non-overlapping).
+ * The current implementation truncates the mean rather than dither, but this may change.
+ */
+void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count);
+
+/**
+ * Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by
+ * duplicating.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of mono samples to upmix
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count);
+
+/**
+ * Downmix pairs of interleaved stereo input float samples to mono output float samples
+ * by averaging the stereo pair together.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of stereo frames to downmix
+ *
+ * The destination and source buffers must be completely separate (non-overlapping),
+ * or they must both start at the same address.
+ */
+void downmix_to_mono_float_from_stereo_float(float *dst, const float *src, size_t count);
+
+/**
+ * Upmix mono input float samples to pairs of interleaved stereo output float samples by
+ * duplicating.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of mono samples to upmix
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void upmix_to_stereo_float_from_mono_float(float *dst, const float *src, size_t count);
+
+/**
+ * \return the total number of non-zero 32-bit samples.
+ */
+size_t nonZeroMono32(const int32_t *samples, size_t count);
+
+/**
+ * \return the total number of non-zero 16-bit samples.
+ */
+size_t nonZeroMono16(const int16_t *samples, size_t count);
+
+/**
+ * \return the total number of non-zero stereo frames, where a frame is considered non-zero
+ * if either of its constituent 32-bit samples is non-zero.
+ */
+size_t nonZeroStereo32(const int32_t *frames, size_t count);
+
+/**
+ * \return the total number of non-zero stereo frames, where a frame is considered non-zero
+ * if either of its constituent 16-bit samples is non-zero.
+ */
+size_t nonZeroStereo16(const int16_t *frames, size_t count);
+
+/**
+ * Copy frames, selecting source samples based on a source channel mask to fit
+ * the destination channel mask. Unmatched channels in the destination channel mask
+ * are zero filled. Unmatched channels in the source channel mask are dropped.
+ * Channels present in the channel mask are represented by set bits in the
+ * uint32_t value and are matched without further interpretation.
+ *
+ *  \param dst         Destination buffer
+ *  \param dst_mask    Bit mask corresponding to destination channels present
+ *  \param src         Source buffer
+ *  \param src_mask    Bit mask corresponding to source channels present
+ *  \param sample_size Size of each sample in bytes.  Must be 1, 2, 3, or 4.
+ *  \param count       Number of frames to copy
+ *
+ * The destination and source buffers must be completely separate (non-overlapping).
+ * If the sample size is not in range, the function will abort.
+ */
+void memcpy_by_channel_mask(void *dst, uint32_t dst_mask,
+        const void *src, uint32_t src_mask, size_t sample_size, size_t count);
+
+/**
+ * Copy frames, selecting source samples based on an index array (idxary).
+ * The idxary[] consists of dst_channels number of elements.
+ * The ith element if idxary[] corresponds the ith destination channel.
+ * A non-negative value is the channel index in the source frame.
+ * A negative index (-1) represents filling with 0.
+ *
+ * Example: Swapping L and R channels for stereo streams
+ * <PRE>
+ * idxary[0] = 1;
+ * idxary[1] = 0;
+ * </PRE>
+ *
+ * Example: Copying a mono source to the front center 5.1 channel
+ * <PRE>
+ * idxary[0] = -1;
+ * idxary[1] = -1;
+ * idxary[2] = 0;
+ * idxary[3] = -1;
+ * idxary[4] = -1;
+ * idxary[5] = -1;
+ * </PRE>
+ *
+ * This copy allows swizzling of channels or replication of channels.
+ *
+ *  \param dst           Destination buffer
+ *  \param dst_channels  Number of destination channels per frame
+ *  \param src           Source buffer
+ *  \param src_channels  Number of source channels per frame
+ *  \param idxary        Array of indices representing channels in the source frame
+ *  \param sample_size   Size of each sample in bytes.  Must be 1, 2, 3, or 4.
+ *  \param count         Number of frames to copy
+ *
+ * The destination and source buffers must be completely separate (non-overlapping).
+ * If the sample size is not in range, the function will abort.
+ */
+void memcpy_by_index_array(void *dst, uint32_t dst_channels,
+        const void *src, uint32_t src_channels,
+        const int8_t *idxary, size_t sample_size, size_t count);
+
+/**
+ * Prepares an index array (idxary) from channel masks, which can be later
+ * used by memcpy_by_index_array().
+ *
+ * \return the number of array elements required.
+ * This may be greater than idxcount, so the return value should be checked
+ * if idxary size is less than 32.
+ *
+ * Note that idxary is a caller allocated array
+ * of at least as many channels as present in the dst_mask.
+ * Channels present in the channel mask are represented by set bits in the
+ * uint32_t value and are matched without further interpretation.
+ *
+ * This function is typically used for converting audio data with different
+ * channel position masks.
+ *
+ *  \param idxary      Updated array of indices of channels in the src frame for the dst frame
+ *  \param idxcount    Number of caller allocated elements in idxary
+ *  \param dst_mask    Bit mask corresponding to destination channels present
+ *  \param src_mask    Bit mask corresponding to source channels present
+ */
+size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
+        uint32_t dst_mask, uint32_t src_mask);
+
+/**
+ * Prepares an index array (idxary) from channel masks, which can be later
+ * used by memcpy_by_index_array().
+ *
+ * \return the number of array elements required.
+ *
+ * For a source channel index mask, the source channels will map to the destination
+ * channels as if counting the set bits in dst_mask in order from lsb to msb
+ * (zero bits are ignored). The ith bit of the src_mask corresponds to the
+ * ith SET bit of dst_mask and the ith destination channel.  Hence, a zero ith
+ * bit of the src_mask indicates that the ith destination channel plays silence.
+ *
+ *  \param idxary      Updated array of indices of channels in the src frame for the dst frame
+ *  \param idxcount    Number of caller allocated elements in idxary
+ *  \param dst_mask    Bit mask corresponding to destination channels present
+ *  \param src_mask    Bit mask corresponding to source channels present
+ */
+size_t memcpy_by_index_array_initialization_src_index(int8_t *idxary, size_t idxcount,
+        uint32_t dst_mask, uint32_t src_mask);
+
+/**
+ * Prepares an index array (idxary) from channel mask bits, which can be later
+ * used by memcpy_by_index_array().
+ *
+ * \return the number of array elements required.
+ *
+ * This initialization is for a destination channel index mask from a positional
+ * source mask.
+ *
+ * For an destination channel index mask, the input channels will map
+ * to the destination channels, with the ith SET bit in the source bits corresponding
+ * to the ith bit in the destination bits. If there is a zero bit in the middle
+ * of set destination bits (unlikely), the corresponding source channel will
+ * be dropped.
+ *
+ *  \param idxary      Updated array of indices of channels in the src frame for the dst frame
+ *  \param idxcount    Number of caller allocated elements in idxary
+ *  \param dst_mask    Bit mask corresponding to destination channels present
+ *  \param src_mask    Bit mask corresponding to source channels present
+ */
+size_t memcpy_by_index_array_initialization_dst_index(int8_t *idxary, size_t idxcount,
+        uint32_t dst_mask, uint32_t src_mask);
+
+/**
+ * Add and clamp signed 16-bit samples.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to add
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void accumulate_i16(int16_t *dst, const int16_t *src, size_t count);
+
+/**
+ * Add and clamp unsigned 8-bit samples.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to add
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void accumulate_u8(uint8_t *dst, const uint8_t *src, size_t count);
+
+/**
+ * Add and clamp packed 24-bit Q0.23 samples.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to add
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void accumulate_p24(uint8_t *dst, const uint8_t *src, size_t count);
+
+/**
+ * Add and clamp 32-bit Q8.23 samples.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to add
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void accumulate_q8_23(int32_t *dst, const int32_t *src, size_t count);
+
+/**
+ * Add and clamp signed 32-bit Q0.31 samples.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to add
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void accumulate_i32(int32_t *dst, const int32_t *src, size_t count);
+
+/**
+ * Add float samples. Result is not clamped.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to add
+ *
+ * The destination and source buffers must either be completely separate (non-overlapping), or
+ * they must both start at the same address.  Partially overlapping buffers are not supported.
+ */
+void accumulate_float(float *dst, const float *src, size_t count);
+
+/**
+ * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range.
+ */
+static inline int16_t clamp16(int32_t sample)
+{
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
+/**
+ * Clamp (aka hard limit or clip) a signed 64-bit sample to 32-bit range.
+ */
+static inline int32_t clamp32(int64_t sample)
+{
+    if ((sample>>31) ^ (sample>>63))
+        sample = 0x7fffffff ^ (sample>>63);
+    return sample;
+}
+
+/**
+ * Convert a IEEE 754 single precision float [-1.0, 1.0) to int16_t [-32768, 32767]
+ * with clamping.  Note the open bound at 1.0, values within 1/65536 of 1.0 map
+ * to 32767 instead of 32768 (early clamping due to the smaller positive integer subrange).
+ *
+ * Values outside the range [-1.0, 1.0) are properly clamped to -32768 and 32767,
+ * including -Inf and +Inf. NaN will generally be treated either as -32768 or 32767,
+ * depending on the sign bit inside NaN (whose representation is not unique).
+ * Nevertheless, strictly speaking, NaN behavior should be considered undefined.
+ *
+ * OLD code disabled: Rounding of 0.5 lsb is to even (default for IEEE 754).
+ * NEW code enabled: Rounding of 0.5 lsb is away from 0.
+ */
+static inline int16_t clamp16_from_float(float f)
+{
+#if 0
+    /* Offset is used to expand the valid range of [-1.0, 1.0) into the 16 lsbs of the
+     * floating point significand. The normal shift is 3<<22, but the -15 offset
+     * is used to multiply by 32768.
+     */
+    static const float offset = (float)(3 << (22 - 15));
+    /* zero = (0x10f << 22) =  0x43c00000 (not directly used) */
+    static const int32_t limneg = (0x10f << 22) /*zero*/ - 32768; /* 0x43bf8000 */
+    static const int32_t limpos = (0x10f << 22) /*zero*/ + 32767; /* 0x43c07fff */
+
+    union {
+        float f;
+        int32_t i;
+    } u;
+
+    u.f = f + offset; /* recenter valid range */
+    /* Now the valid range is represented as integers between [limneg, limpos].
+     * Clamp using the fact that float representation (as an integer) is an ordered set.
+     */
+    if (u.i < limneg)
+        u.i = -32768;
+    else if (u.i > limpos)
+        u.i = 32767;
+    return u.i; /* Return lower 16 bits, the part of interest in the significand. */
+#else
+    static const float scale = 1 << 15;
+    return roundf(fmaxf(fminf(f * scale, scale - 1.f), -scale));
+#endif
+}
+
+/**
+ * Convert a IEEE 754 single precision float [-1.0, 1.0) to uint8_t [0, 0xff]
+ * with clamping.  Note the open bound at 1.0, values within 1/128 of 1.0 map
+ * to 255 instead of 256 (early clamping due to the smaller positive integer subrange).
+ *
+ * Values outside the range [-1.0, 1.0) are properly clamped to 0 and 255,
+ * including -Inf and +Inf. NaN will generally be treated either as 0 or 255,
+ * depending on the sign bit inside NaN (whose representation is not unique).
+ * Nevertheless, strictly speaking, NaN behavior should be considered undefined.
+ *
+ * OLD code disabled: Rounding of 0.5 lsb is to even (default for IEEE 754).
+ * NEW code enabled: Rounding of 0.5 lsb is away from 0.
+ */
+static inline uint8_t clamp8_from_float(float f)
+{
+#if 0
+    /* Offset is used to expand the valid range of [-1.0, 1.0) into the 16 lsbs of the
+     * floating point significand. The normal shift is 3<<22, but the -7 offset
+     * is used to multiply by 128.
+     */
+    static const float offset = (float)((3 << (22 - 7)) + 1 /* to cancel -1.0 */);
+    /* zero = (0x11f << 22) =  0x47c00000 */
+    static const int32_t limneg = (0x11f << 22) /*zero*/;
+    static const int32_t limpos = (0x11f << 22) /*zero*/ + 255; /* 0x47c000ff */
+
+    union {
+        float f;
+        int32_t i;
+    } u;
+
+    u.f = f + offset; /* recenter valid range */
+    /* Now the valid range is represented as integers between [limneg, limpos].
+     * Clamp using the fact that float representation (as an integer) is an ordered set.
+     */
+    if (u.i < limneg)
+        return 0;
+    if (u.i > limpos)
+        return 255;
+    return u.i; /* Return lower 8 bits, the part of interest in the significand. */
+#else
+    return roundf(fmaxf(fminf(f * 128.f + 128.f, 255.f), 0.f));
+#endif
+}
+
+/**
+ * Convert a single-precision floating point value to a Q0.23 integer value, stored in a
+ * 32 bit signed integer (technically stored as Q8.23, but clamped to Q0.23).
+ *
+ * OLD code disabled: Rounds to nearest, ties away from 0.
+ * NEW code enabled: Rounding of 0.5 lsb is away from 0.
+ *
+ * Values outside the range [-1.0, 1.0) are properly clamped to -8388608 and 8388607,
+ * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
+ * depending on hardware and future implementation of this function.
+ */
+static inline int32_t clamp24_from_float(float f)
+{
+#if 0
+    static const float scale = (float)(1 << 23);
+    static const float limpos = 0x7fffff / scale;
+    static const float limneg = -0x800000 / scale;
+
+    if (f <= limneg) {
+        return -0x800000;
+    } else if (f >= limpos) {
+        return 0x7fffff;
+    }
+    f *= scale;
+    /* integer conversion is through truncation (though int to float is not).
+     * ensure that we round to nearest, ties away from 0.
+     */
+    return f > 0 ? f + 0.5 : f - 0.5;
+#else
+    static const float scale = 1 << 23;
+    return roundf(fmaxf(fminf(f * scale, scale - 1.f), -scale));
+#endif
+}
+
+/**
+ * Convert a signed fixed-point 32-bit Q8.23 value to a Q0.23 integer value,
+ * stored in a 32-bit signed integer (technically stored as Q8.23, but clamped to Q0.23).
+ *
+ * Values outside the range [-0x800000, 0x7fffff] are clamped to that range.
+ */
+static inline int32_t clamp24_from_q8_23(int32_t ival)
+{
+    static const int32_t limpos = 0x7fffff;
+    static const int32_t limneg = -0x800000;
+    if (ival < limneg) {
+        return limneg;
+    } else if (ival > limpos) {
+        return limpos;
+    } else {
+        return ival;
+    }
+}
+
+/**
+ * Convert a single-precision floating point value to a Q4.27 integer value.
+ * Rounds to nearest, ties away from 0.
+ *
+ * Values outside the range [-16.0, 16.0) are properly clamped to -2147483648 and 2147483647,
+ * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
+ * depending on hardware and future implementation of this function.
+ */
+static inline int32_t clampq4_27_from_float(float f)
+{
+    static const float scale = (float)(1UL << 27);
+    static const float limpos = 16.;
+    static const float limneg = -16.;
+
+    if (f <= limneg) {
+        return -0x80000000; /* or 0x80000000 */
+    } else if (f >= limpos) {
+        return 0x7fffffff;
+    }
+    f *= scale;
+    /* integer conversion is through truncation (though int to float is not).
+     * ensure that we round to nearest, ties away from 0.
+     */
+    return f > 0 ? f + 0.5 : f - 0.5;
+}
+
+/**
+ * Convert a single-precision floating point value to a Q0.31 integer value.
+ * Rounds to nearest, ties away from 0.
+ *
+ * Values outside the range [-1.0, 1.0) are properly clamped to -2147483648 and 2147483647,
+ * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
+ * depending on hardware and future implementation of this function.
+ */
+static inline int32_t clamp32_from_float(float f)
+{
+    static const float scale = (float)(1UL << 31);
+    static const float limpos = 1.;
+    static const float limneg = -1.;
+
+    if (f <= limneg) {
+        return -0x80000000; /* or 0x80000000 */
+    } else if (f >= limpos) {
+        return 0x7fffffff;
+    }
+    f *= scale;
+    /* integer conversion is through truncation (though int to float is not).
+     * ensure that we round to nearest, ties away from 0.
+     */
+    return f > 0 ? f + 0.5 : f - 0.5;
+}
+
+/**
+ * Convert a signed fixed-point 32-bit Q4.27 value to single-precision floating-point.
+ * The nominal output float range is [-1.0, 1.0] if the fixed-point range is
+ * [0xf8000000, 0x07ffffff].  The full float range is [-16.0, 16.0].
+ *
+ * Note the closed range at 1.0 and 16.0 is due to rounding on conversion to float.
+ * In more detail: if the fixed-point integer exceeds 24 bit significand of single
+ * precision floating point, the 0.5 lsb in the significand conversion will round
+ * towards even, as per IEEE 754 default.
+ */
+static inline float float_from_q4_27(int32_t ival)
+{
+    /* The scale factor is the reciprocal of the fractional bits.
+     *
+     * Since the scale factor is a power of 2, the scaling is exact, and there
+     * is no rounding due to the multiplication - the bit pattern is preserved.
+     * However, there may be rounding due to the fixed-point to float conversion,
+     * as described above.
+     */
+    static const float scale = 1. / (float)(1UL << 27);
+
+    return ival * scale;
+}
+
+/**
+ * Convert an unsigned fixed-point 32-bit U4.28 value to single-precision floating-point.
+ * The nominal output float range is [0.0, 1.0] if the fixed-point range is
+ * [0x00000000, 0x10000000].  The full float range is [0.0, 16.0].
+ *
+ * Note the closed range at 1.0 and 16.0 is due to rounding on conversion to float.
+ * In more detail: if the fixed-point integer exceeds 24 bit significand of single
+ * precision floating point, the 0.5 lsb in the significand conversion will round
+ * towards even, as per IEEE 754 default.
+ */
+static inline float float_from_u4_28(uint32_t uval)
+{
+    static const float scale = 1. / (float)(1UL << 28);
+
+    return uval * scale;
+}
+
+/**
+ * Convert an unsigned fixed-point 16-bit U4.12 value to single-precision floating-point.
+ * The nominal output float range is [0.0, 1.0] if the fixed-point range is
+ * [0x0000, 0x1000].  The full float range is [0.0, 16.0).
+ */
+static inline float float_from_u4_12(uint16_t uval)
+{
+    static const float scale = 1. / (float)(1UL << 12);
+
+    return uval * scale;
+}
+
+/**
+ * Convert a single-precision floating point value to a U4.28 integer value.
+ * Rounds to nearest, ties away from 0.
+ *
+ * Values outside the range [0, 16.0] are properly clamped to [0, 4294967295]
+ * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
+ * depending on hardware and future implementation of this function.
+ */
+static inline uint32_t u4_28_from_float(float f)
+{
+    static const float scale = (float)(1 << 28);
+    static const float limpos = 0xffffffffUL / scale;
+
+    if (f <= 0.) {
+        return 0;
+    } else if (f >= limpos) {
+        return 0xffffffff;
+    }
+    /* integer conversion is through truncation (though int to float is not).
+     * ensure that we round to nearest, ties away from 0.
+     */
+    return f * scale + 0.5;
+}
+
+/**
+ * Convert a single-precision floating point value to a U4.12 integer value.
+ * Rounds to nearest, ties away from 0.
+ *
+ * Values outside the range [0, 16.0) are properly clamped to [0, 65535]
+ * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
+ * depending on hardware and future implementation of this function.
+ */
+static inline uint16_t u4_12_from_float(float f)
+{
+    static const float scale = (float)(1 << 12);
+    static const float limpos = 0xffff / scale;
+
+    if (f <= 0.) {
+        return 0;
+    } else if (f >= limpos) {
+        return 0xffff;
+    }
+    /* integer conversion is through truncation (though int to float is not).
+     * ensure that we round to nearest, ties away from 0.
+     */
+    return f * scale + 0.5;
+}
+
+/**
+ * Convert a signed fixed-point 16-bit Q0.15 value to single-precision floating-point.
+ * The output float range is [-1.0, 1.0) for the fixed-point range
+ * [0x8000, 0x7fff].
+ *
+ * There is no rounding, the conversion and representation is exact.
+ */
+static inline float float_from_i16(int16_t ival)
+{
+    /* The scale factor is the reciprocal of the nominal 16 bit integer
+     * half-sided range (32768).
+     *
+     * Since the scale factor is a power of 2, the scaling is exact, and there
+     * is no rounding due to the multiplication - the bit pattern is preserved.
+     */
+    static const float scale = 1. / (float)(1UL << 15);
+
+    return ival * scale;
+}
+
+/**
+ * Convert an unsigned fixed-point 8-bit U0.8 value to single-precision floating-point.
+ * The nominal output float range is [-1.0, 1.0) if the fixed-point range is
+ * [0x00, 0xff].
+ */
+static inline float float_from_u8(uint8_t uval)
+{
+    static const float scale = 1. / (float)(1UL << 7);
+
+    return ((int)uval - 128) * scale;
+}
+
+/**
+ * Convert a packed 24bit Q0.23 value stored native-endian in a uint8_t ptr
+ * to a signed fixed-point 32 bit integer Q0.31 value. The output Q0.31 range
+ * is [0x80000000, 0x7fffff00] for the fixed-point range [0x800000, 0x7fffff].
+ * Even though the output range is limited on the positive side, there is no
+ * DC offset on the output, if the input has no DC offset.
+ *
+ * Avoid relying on the limited output range, as future implementations may go
+ * to full range.
+ */
+static inline int32_t i32_from_p24(const uint8_t *packed24)
+{
+    /* convert to 32b */
+    return (packed24[0] << 8) | (packed24[1] << 16) | (packed24[2] << 24);
+}
+
+/**
+ * Convert a 32-bit Q0.31 value to single-precision floating-point.
+ * The output float range is [-1.0, 1.0] for the fixed-point range
+ * [0x80000000, 0x7fffffff].
+ *
+ * Rounding may occur in the least significant 8 bits for large fixed point
+ * values due to storage into the 24-bit floating-point significand.
+ * Rounding will be to nearest, ties to even.
+ */
+static inline float float_from_i32(int32_t ival)
+{
+    static const float scale = 1. / (float)(1UL << 31);
+
+    return ival * scale;
+}
+
+/**
+ * Convert a packed 24bit Q0.23 value stored native endian in a uint8_t ptr
+ * to single-precision floating-point. The output float range is [-1.0, 1.0)
+ * for the fixed-point range [0x800000, 0x7fffff].
+ *
+ * There is no rounding, the conversion and representation is exact.
+ */
+static inline float float_from_p24(const uint8_t *packed24)
+{
+    return float_from_i32(i32_from_p24(packed24));
+}
+
+/**
+ * Convert a 24-bit Q8.23 value to single-precision floating-point.
+ * The nominal output float range is [-1.0, 1.0) for the fixed-point
+ * range [0xff800000, 0x007fffff].  The maximum float range is [-256.0, 256.0).
+ *
+ * There is no rounding in the nominal range, the conversion and representation
+ * is exact. For values outside the nominal range, rounding is to nearest, ties to even.
+ */
+static inline float float_from_q8_23(int32_t ival)
+{
+    static const float scale = 1. / (float)(1UL << 23);
+
+    return ival * scale;
+}
+
+/**
+ * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v.
+ */
+static inline
+int32_t mulAdd(int16_t in, int16_t v, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    asm( "smlabb %[out], %[in], %[v], %[a] \n"
+         : [out]"=r"(out)
+         : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
+         : );
+    return out;
+#else
+    return a + in * (int32_t)v;
+#endif
+}
+
+/**
+ * Multiply 16-bit terms with 32-bit result: return in*v.
+ */
+static inline
+int32_t mul(int16_t in, int16_t v)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    asm( "smulbb %[out], %[in], %[v] \n"
+         : [out]"=r"(out)
+         : [in]"%r"(in), [v]"r"(v)
+         : );
+    return out;
+#else
+    return in * (int32_t)v;
+#endif
+}
+
+/**
+ * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair.
+ */
+static inline
+int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    if (left) {
+        asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
+             : );
+    } else {
+        asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
+             : );
+    }
+    return out;
+#else
+    if (left) {
+        return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF);
+    } else {
+        return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16);
+    }
+#endif
+}
+
+/**
+ * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair.
+ */
+static inline
+int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    if (left) {
+        asm( "smulbb %[out], %[inRL], %[vRL] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
+             : );
+    } else {
+        asm( "smultt %[out], %[inRL], %[vRL] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
+             : );
+    }
+    return out;
+#else
+    if (left) {
+        return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF);
+    } else {
+        return (int16_t)(inRL>>16) * (int16_t)(vRL>>16);
+    }
+#endif
+}
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif  // ANDROID_AUDIO_PRIMITIVES_H
diff --git a/include/audio_utils/resampler.h b/include/audio_utils/resampler.h
new file mode 100644
index 0000000..559e020
--- /dev/null
+++ b/include/audio_utils/resampler.h
@@ -0,0 +1,109 @@
+/*
+** Copyright 2008, 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_RESAMPLER_H
+#define ANDROID_RESAMPLER_H
+
+#include <stdint.h>
+#include <sys/time.h>
+
+__BEGIN_DECLS
+
+
+#define RESAMPLER_QUALITY_MAX 10
+#define RESAMPLER_QUALITY_MIN 0
+#define RESAMPLER_QUALITY_DEFAULT 4
+#define RESAMPLER_QUALITY_VOIP 3
+#define RESAMPLER_QUALITY_DESKTOP 5
+
+struct resampler_buffer {
+    union {
+        void*       raw;
+        short*      i16;
+        int8_t*     i8;
+    };
+    size_t frame_count;
+};
+
+/** call back interface used by the resampler to get new data */
+struct resampler_buffer_provider
+{
+    /**
+     *  get a new buffer of data:
+     *   as input: buffer->frame_count is the number of frames requested
+     *   as output: buffer->frame_count is the number of frames returned
+     *              buffer->raw points to data returned
+     */
+    int (*get_next_buffer)(struct resampler_buffer_provider *provider,
+            struct resampler_buffer *buffer);
+    /**
+     *  release a consumed buffer of data:
+     *   as input: buffer->frame_count is the number of frames released
+     *             buffer->raw points to data released
+     */
+    void (*release_buffer)(struct resampler_buffer_provider *provider,
+            struct resampler_buffer *buffer);
+};
+
+/** resampler interface */
+struct resampler_itfe {
+    /**
+     * reset resampler state
+     */
+    void (*reset)(struct resampler_itfe *resampler);
+    /**
+     * resample input from buffer provider and output at most *outFrameCount to out buffer.
+     * *outFrameCount is updated with the actual number of frames produced.
+     */
+    int (*resample_from_provider)(struct resampler_itfe *resampler,
+                    int16_t *out,
+                    size_t *outFrameCount);
+    /**
+     * resample at most *inFrameCount frames from in buffer and output at most
+     * *outFrameCount to out buffer. *inFrameCount and *outFrameCount are updated respectively
+     * with the number of frames remaining in input and written to output.
+     */
+    int (*resample_from_input)(struct resampler_itfe *resampler,
+                    int16_t *in,
+                    size_t *inFrameCount,
+                    int16_t *out,
+                    size_t *outFrameCount);
+    /**
+     * \return the latency introduced by the resampler in ns.
+     */
+    int32_t (*delay_ns)(struct resampler_itfe *resampler);
+};
+
+/**
+ * create a resampler according to input parameters passed.
+ * If resampler_buffer_provider is not NULL only resample_from_provider() can be called.
+ * If resampler_buffer_provider is NULL only resample_from_input() can be called.
+ */
+int create_resampler(uint32_t inSampleRate,
+          uint32_t outSampleRate,
+          uint32_t channelCount,
+          uint32_t quality,
+          struct resampler_buffer_provider *provider,
+          struct resampler_itfe **);
+
+/**
+ * release resampler resources.
+ */
+void release_resampler(struct resampler_itfe *);
+
+__END_DECLS
+
+#endif // ANDROID_RESAMPLER_H
diff --git a/include/audio_utils/sndfile.h b/include/audio_utils/sndfile.h
new file mode 100644
index 0000000..6346295
--- /dev/null
+++ b/include/audio_utils/sndfile.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 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 __AUDIO_UTIL_SNDFILE_H
+#define __AUDIO_UTIL_SNDFILE_H
+
+// This is a C library for reading and writing PCM .wav files.  It is
+// influenced by other libraries such as libsndfile and audiofile, except is
+// much smaller and has an Apache 2.0 license.
+// The API should be familiar to clients of similar libraries, but there is
+// no guarantee that it will stay exactly source-code compatible with other libraries.
+
+#include <stdio.h>
+#include <sys/cdefs.h>
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+// visible to clients
+typedef int sf_count_t;
+
+typedef struct {
+    sf_count_t frames;
+    int samplerate;
+    int channels;
+    int format;
+} SF_INFO;
+
+// opaque to clients
+typedef struct SNDFILE_ SNDFILE;
+
+// Access modes
+#define SFM_READ    1
+#define SFM_WRITE   2
+
+// Format
+#define SF_FORMAT_TYPEMASK  1
+#define SF_FORMAT_WAV       1
+#define SF_FORMAT_SUBMASK   14
+#define SF_FORMAT_PCM_16    2
+#define SF_FORMAT_PCM_U8    4
+#define SF_FORMAT_FLOAT     6
+#define SF_FORMAT_PCM_32    8
+#define SF_FORMAT_PCM_24    10
+
+/** Open stream */
+SNDFILE *sf_open(const char *path, int mode, SF_INFO *info);
+
+/** Close stream */
+void sf_close(SNDFILE *handle);
+
+/**
+ * Read interleaved frames
+ * \return actual number of frames read
+ */
+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);
+
+/**
+ * Write interleaved frames
+ * \return actual number of frames written
+ */
+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);
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif /* __AUDIO_UTIL_SNDFILE_H */
diff --git a/include/audio_utils/spdif/FrameScanner.h b/include/audio_utils/spdif/FrameScanner.h
new file mode 100644
index 0000000..6d391ee
--- /dev/null
+++ b/include/audio_utils/spdif/FrameScanner.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2014, 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_FRAME_SCANNER_H
+#define ANDROID_AUDIO_FRAME_SCANNER_H
+
+#include <stdint.h>
+
+namespace android {
+
+
+/**
+ * Scan a byte stream looking for the start of an encoded frame.
+ * Parse the sample rate and the size of the encoded frame.
+ * Buffer the sync header so it can be prepended to the remaining data.
+ *
+ * This is used directly by the SPDIFEncoder. External clients will
+ * generally not call this class.
+ */
+class FrameScanner {
+public:
+    FrameScanner(int dataType,
+            const uint8_t *syncBytes,
+            uint32_t syncLength,
+            uint32_t headerLength
+            );
+    virtual ~FrameScanner();
+
+    /**
+     * Pass each byte of the encoded stream to this scanner.
+     * @return true if a complete and valid header was detected
+     */
+    virtual bool scan(uint8_t byte);
+
+    /**
+     * @return address of where the sync header was stored by scan()
+     */
+    const uint8_t *getHeaderAddress() const { return mHeaderBuffer; }
+
+    /**
+     * @return number of bytes in sync header stored by scan()
+     */
+    size_t getHeaderSizeBytes() const { return mHeaderLength; }
+
+    /**
+     * @return sample rate of the encoded audio
+     */
+    uint32_t getSampleRate()   const { return mSampleRate; }
+
+    /**
+     * Some formats, for example EAC3, are wrapped in data bursts that have
+     * a sample rate that is a multiple of the encoded sample rate.
+     * The default multiplier is 1.
+     * @return sample rate multiplier for the SP/DIF PCM data bursts
+     */
+    uint32_t getRateMultiplier()   const { return mRateMultiplier; }
+
+    size_t getFrameSizeBytes()     const { return mFrameSizeBytes; }
+
+    /**
+     * dataType is defined by the SPDIF standard for each format
+     */
+    int getDataType()      const { return mDataType; }
+    int getDataTypeInfo()  const { return mDataTypeInfo; }
+
+    virtual int getMaxChannels() const = 0;
+
+    virtual void resetBurst() = 0;
+
+    /**
+     * @return the number of pcm frames that correspond to one encoded frame
+     */
+    virtual int getMaxSampleFramesPerSyncFrame() const = 0;
+    virtual int getSampleFramesPerSyncFrame()    const = 0;
+
+    /**
+     * @return true if this parsed frame must be the first frame in a data burst.
+     */
+    virtual bool isFirstInBurst() = 0;
+
+    /**
+     * If this returns false then the previous frame may or may not be the last frame.
+     * @return true if this parsed frame is definitely the last frame in a data burst.
+     */
+    virtual bool isLastInBurst()  = 0;
+
+    /**
+     * Most compression types use a lengthCode expressed in bits.
+     */
+    virtual uint16_t convertBytesToLengthCode(uint16_t numBytes) const { return numBytes * 8; }
+
+protected:
+    uint32_t  mBytesSkipped;     // how many bytes were skipped looking for the start of a frame
+    const uint8_t *mSyncBytes;   // pointer to the sync word specific to a format
+    uint32_t  mSyncLength;       // number of bytes in sync word
+    uint8_t   mHeaderBuffer[32]; // a place to gather the relevant header bytes for parsing
+    uint32_t  mHeaderLength;     // the number of bytes we need to parse
+    uint32_t  mCursor;           // position in the mHeaderBuffer
+    uint32_t  mFormatDumpCount;  // used to thin out the debug dumps
+    uint32_t  mSampleRate;       // encoded sample rate
+    uint32_t  mRateMultiplier;   // SPDIF output data burst rate = msampleRate * mRateMultiplier
+    size_t    mFrameSizeBytes;   // encoded frame size
+    int       mDataType;         // as defined in IEC61937-2 paragraph 4.2
+    int       mDataTypeInfo;     // as defined in IEC61937-2 paragraph 4.1
+
+    /**
+     * Parse data in mHeaderBuffer.
+     * Sets mDataType, mFrameSizeBytes, mSampleRate, mRateMultiplier.
+     * @return true if the header is valid.
+     */
+    virtual bool parseHeader() = 0;
+
+};
+
+
+}  // namespace android
+#endif  // ANDROID_AUDIO_FRAME_SCANNER_H
diff --git a/include/audio_utils/spdif/SPDIFEncoder.h b/include/audio_utils/spdif/SPDIFEncoder.h
new file mode 100644
index 0000000..3c84d73
--- /dev/null
+++ b/include/audio_utils/spdif/SPDIFEncoder.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2014, 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_SPDIF_ENCODER_H
+#define ANDROID_AUDIO_SPDIF_ENCODER_H
+
+#include <stdint.h>
+#include <system/audio.h>
+#include <audio_utils/spdif/FrameScanner.h>
+
+namespace android {
+
+/**
+ * Scan the incoming byte stream for a frame sync.
+ * Then wrap the encoded frame in a data burst and send it as if it were PCM.
+ * The receiver will see the data burst header and decode the wrapped frame.
+ */
+#define SPDIF_MAX_CHANNELS          8
+#define SPDIF_ENCODED_CHANNEL_COUNT 2
+
+class SPDIFEncoder {
+public:
+
+    explicit SPDIFEncoder(audio_format_t format);
+    // Defaults to AC3 format. Was in original API.
+    SPDIFEncoder();
+
+    virtual ~SPDIFEncoder();
+
+    /**
+     * Write encoded data to be wrapped for SPDIF.
+     * The compressed frames do not have to be aligned.
+     * @return number of bytes written or negative error
+     */
+    ssize_t write( const void* buffer, size_t numBytes );
+
+    /**
+     * Called by SPDIFEncoder when it is ready to output a data burst.
+     * Must be implemented in the subclass.
+     * @return number of bytes written or negative error
+     */
+    virtual ssize_t writeOutput( const void* buffer, size_t numBytes ) = 0;
+
+    /**
+     * Get ratio of the encoded data burst sample rate to the encoded rate.
+     * For example, EAC3 data bursts are 4X the encoded rate.
+     */
+    uint32_t getRateMultiplier() const { return mRateMultiplier; }
+
+    /**
+     * @return number of PCM frames in a data burst
+     */
+    uint32_t getBurstFrames() const { return mBurstFrames; }
+
+    /**
+     * @return number of bytes per PCM frame for the data burst
+     */
+    int      getBytesPerOutputFrame();
+
+    /**
+     * @return  true if we can wrap this format in an SPDIF stream
+     */
+    static bool isFormatSupported(audio_format_t format);
+
+    /**
+     * Discard any data in the buffer. Reset frame scanners.
+     * This should be called when seeking to a new position in the stream.
+     */
+    void reset();
+
+protected:
+    void   clearBurstBuffer();
+    void   writeBurstBufferShorts(const uint16_t* buffer, size_t numBytes);
+    void   writeBurstBufferBytes(const uint8_t* buffer, size_t numBytes);
+    void   sendZeroPad();
+    void   flushBurstBuffer();
+    void   startDataBurst();
+    size_t startSyncFrame();
+
+    // Works with various formats including AC3.
+    FrameScanner *mFramer;
+
+    uint32_t  mSampleRate;
+    size_t    mFrameSize;   // size of sync frame in bytes
+    uint16_t *mBurstBuffer; // ALSA wants to get SPDIF data as shorts.
+    size_t    mBurstBufferSizeBytes;
+    uint32_t  mRateMultiplier;
+    uint32_t  mBurstFrames;
+    size_t    mByteCursor;  // cursor into data burst
+    int       mBitstreamNumber;
+    size_t    mPayloadBytesPending; // number of bytes needed to finish burst
+    // state variable, true if scanning for start of frame
+    bool      mScanning;
+
+    static const uint16_t kSPDIFSync1; // Pa
+    static const uint16_t kSPDIFSync2; // Pb
+};
+
+}  // namespace android
+
+#endif  // ANDROID_AUDIO_SPDIF_ENCODER_H
diff --git a/include/cutils/abort_socket.h b/include/cutils/abort_socket.h
new file mode 100644
index 0000000..fbb1112
--- /dev/null
+++ b/include/cutils/abort_socket.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2009, 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.
+ */
+
+/* Helper to perform abortable blocking operations on a socket:
+ *   asocket_connect()
+ *   asocket_accept()
+ *   asocket_read()
+ *   asocket_write()
+ * These calls are similar to the regular syscalls, but can be aborted with:
+ *   asocket_abort()
+ *
+ * Calling close() on a regular POSIX socket does not abort blocked syscalls on
+ * that socket in other threads.
+ *
+ * After calling asocket_abort() the socket cannot be reused.
+ *
+ * Call asocket_destory() *after* all threads have finished with the socket to
+ * finish closing the socket and free the asocket structure.
+ *
+ * The helper is implemented by setting the socket non-blocking to initiate
+ * syscalls connect(), accept(), read(), write(), then using a blocking poll()
+ * on both the primary socket and a local pipe. This makes the poll() abortable
+ * by writing a byte to the local pipe in asocket_abort().
+ *
+ * asocket_create() sets the fd to non-blocking mode. It must not be changed to
+ * blocking mode.
+ *
+ * Using asocket will triple the number of file descriptors required per
+ * socket, due to the local pipe. It may be possible to use a global pipe per
+ * process rather than per socket, but we have not been able to come up with a
+ * race-free implementation yet.
+ *
+ * All functions except asocket_init() and asocket_destroy() are thread safe.
+ */
+
+#include <stdlib.h>
+#include <sys/socket.h>
+
+#ifndef __CUTILS_ABORT_SOCKET_H__
+#define __CUTILS_ABORT_SOCKET_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asocket {
+    int fd;           /* primary socket fd */
+    int abort_fd[2];  /* pipe used to abort */
+};
+
+/* Create an asocket from fd.
+ * Sets the socket to non-blocking mode.
+ * Returns NULL on error with errno set.
+ */
+struct asocket *asocket_init(int fd);
+
+/* Blocking socket I/O with timeout.
+ * Calling asocket_abort() from another thread will cause each of these
+ * functions to immediately return with value -1 and errno ECANCELED.
+ * timeout is in ms, use -1 to indicate no timeout. On timeout -1 is returned
+ * with errno ETIMEDOUT.
+ * EINTR is handled in-call.
+ * Other semantics are identical to the regular syscalls.
+ */
+int asocket_connect(struct asocket *s, const struct sockaddr *addr,
+        socklen_t addrlen, int timeout);
+
+int asocket_accept(struct asocket *s, struct sockaddr *addr,
+        socklen_t *addrlen, int timeout);
+
+int asocket_read(struct asocket *s, void *buf, size_t count, int timeout);
+
+int asocket_write(struct asocket *s, const void *buf, size_t count,
+        int timeout);
+
+/* Abort above calls and shutdown socket.
+ * Further I/O operations on this socket will immediately fail after this call.
+ * asocket_destroy() should be used to release resources once all threads
+ * have returned from blocking calls on the socket.
+ */
+void asocket_abort(struct asocket *s);
+
+/* Close socket and free asocket structure.
+ * Must not be called until all calls on this structure have completed.
+ */
+void asocket_destroy(struct asocket *s);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__CUTILS_ABORT_SOCKET__H__
diff --git a/include/cutils/android_reboot.h b/include/cutils/android_reboot.h
new file mode 100644
index 0000000..0c79be7
--- /dev/null
+++ b/include/cutils/android_reboot.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef __CUTILS_ANDROID_REBOOT_H__
+#define __CUTILS_ANDROID_REBOOT_H__
+
+__BEGIN_DECLS
+
+/* Commands */
+#define ANDROID_RB_RESTART  0xDEAD0001
+#define ANDROID_RB_POWEROFF 0xDEAD0002
+#define ANDROID_RB_RESTART2 0xDEAD0003
+
+/* Flags */
+#define ANDROID_RB_FLAG_NO_SYNC       0x1
+#define ANDROID_RB_FLAG_NO_REMOUNT_RO 0x2
+
+int android_reboot(int cmd, int flags, char *arg);
+
+__END_DECLS
+
+#endif /* __CUTILS_ANDROID_REBOOT_H__ */
diff --git a/include/cutils/array.h b/include/cutils/array.h
new file mode 100644
index 0000000..d8d6fe6
--- /dev/null
+++ b/include/cutils/array.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/**
+ * A pointer array which intelligently expands its capacity ad needed.
+ */
+
+#ifndef __ARRAY_H
+#define __ARRAY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+/** An array. */
+typedef struct Array Array;
+
+/** Constructs a new array. Returns NULL if we ran out of memory. */
+Array* arrayCreate();
+
+/** Frees an array. Does not free elements themselves. */
+void arrayFree(Array* array);
+
+/** Adds a pointer. Returns 0 is successful, < 0 otherwise. */
+int arrayAdd(Array* array, void* pointer);
+
+/** Gets the pointer at the specified index. */
+void* arrayGet(Array* array, int index);
+
+/** Removes the pointer at the given index and returns it. */
+void* arrayRemove(Array* array, int index);
+
+/** Sets pointer at the given index. Returns old pointer. */
+void* arraySet(Array* array, int index, void* pointer);
+
+/** Sets the array size. Sets new pointers to NULL. Returns 0 if successful, < 0 otherwise . */
+int arraySetSize(Array* array, int size);
+
+/** Returns the size of the given array. */
+int arraySize(Array* array);
+
+/**
+ * Returns a pointer to a C-style array which will be valid until this array
+ * changes.
+ */
+const void** arrayUnwrap(Array* array);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ARRAY_H */
\ No newline at end of file
diff --git a/include/cutils/ashmem.h b/include/cutils/ashmem.h
new file mode 100644
index 0000000..25b233e
--- /dev/null
+++ b/include/cutils/ashmem.h
@@ -0,0 +1,45 @@
+/* cutils/ashmem.h
+ **
+ ** Copyright 2008 The Android Open Source Project
+ **
+ ** This file is dual licensed.  It may be redistributed and/or modified
+ ** under the terms of the Apache 2.0 License OR version 2 of the GNU
+ ** General Public License.
+ */
+
+#ifndef _CUTILS_ASHMEM_H
+#define _CUTILS_ASHMEM_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ashmem_create_region(const char *name, size_t size);
+int ashmem_set_prot_region(int fd, int prot);
+int ashmem_pin_region(int fd, size_t offset, size_t len);
+int ashmem_unpin_region(int fd, size_t offset, size_t len);
+int ashmem_get_size_region(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef __ASHMEMIOC	/* in case someone included <linux/ashmem.h> too */
+
+#define ASHMEM_NAME_LEN		256
+
+#define ASHMEM_NAME_DEF		"dev/ashmem"
+
+/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
+#define ASHMEM_NOT_PURGED	0
+#define ASHMEM_WAS_PURGED	1
+
+/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
+#define ASHMEM_IS_UNPINNED	0
+#define ASHMEM_IS_PINNED	1
+
+#endif	/* ! __ASHMEMIOC */
+
+#endif	/* _CUTILS_ASHMEM_H */
diff --git a/include/cutils/atomic-arm.h b/include/cutils/atomic-arm.h
new file mode 100644
index 0000000..b9d639d
--- /dev/null
+++ b/include/cutils/atomic-arm.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2010 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_CUTILS_ATOMIC_ARM_H
+#define ANDROID_CUTILS_ATOMIC_ARM_H
+
+#include <stdint.h>
+
+#ifndef ANDROID_ATOMIC_INLINE
+#define ANDROID_ATOMIC_INLINE inline /* __attribute__((always_inline)) */
+#endif
+
+extern ANDROID_ATOMIC_INLINE void android_compiler_barrier()
+{
+    __asm__ __volatile__ ("" : : : "memory");
+}
+
+extern ANDROID_ATOMIC_INLINE void android_memory_barrier()
+{
+#if ANDROID_SMP == 0
+    android_compiler_barrier();
+#else
+    __asm__ __volatile__ ("dmb" : : : "memory");
+#endif
+}
+
+extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier()
+{
+#if ANDROID_SMP == 0
+    android_compiler_barrier();
+#else
+    __asm__ __volatile__ ("dmb st" : : : "memory");
+#endif
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+    int32_t value = *ptr;
+    android_memory_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_cas(int32_t old_value, int32_t new_value,
+                       volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        __asm__ __volatile__ ("ldrex %0, [%3]\n"
+                              "mov %1, #0\n"
+                              "teq %0, %4\n"
+#ifdef __thumb2__
+                              "it eq\n"
+#endif
+                              "strexeq %1, %5, [%3]"
+                              : "=&r" (prev), "=&r" (status), "+m"(*ptr)
+                              : "r" (ptr), "Ir" (old_value), "r" (new_value)
+                              : "cc");
+    } while (__builtin_expect(status != 0, 0));
+    return prev != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    int status = android_atomic_cas(old_value, new_value, ptr);
+    android_memory_barrier();
+    return status;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_release_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
+{
+    int32_t prev, tmp, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ ("ldrex %0, [%4]\n"
+                              "add %1, %0, %5\n"
+                              "strex %2, %1, [%4]"
+                              : "=&r" (prev), "=&r" (tmp),
+                                "=&r" (status), "+m" (*ptr)
+                              : "r" (ptr), "Ir" (increment)
+                              : "cc");
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr)
+{
+    return android_atomic_add(1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr)
+{
+    return android_atomic_add(-1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, tmp, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ ("ldrex %0, [%4]\n"
+                              "and %1, %0, %5\n"
+                              "strex %2, %1, [%4]"
+                              : "=&r" (prev), "=&r" (tmp),
+                                "=&r" (status), "+m" (*ptr)
+                              : "r" (ptr), "Ir" (value)
+                              : "cc");
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, tmp, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ ("ldrex %0, [%4]\n"
+                              "orr %1, %0, %5\n"
+                              "strex %2, %1, [%4]"
+                              : "=&r" (prev), "=&r" (tmp),
+                                "=&r" (status), "+m" (*ptr)
+                              : "r" (ptr), "Ir" (value)
+                              : "cc");
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_ARM_H */
diff --git a/include/cutils/atomic-arm64.h b/include/cutils/atomic-arm64.h
new file mode 100644
index 0000000..4562ad0
--- /dev/null
+++ b/include/cutils/atomic-arm64.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_CUTILS_ATOMIC_AARCH64_H
+#define ANDROID_CUTILS_ATOMIC_AARCH64_H
+
+#include <stdint.h>
+
+#ifndef ANDROID_ATOMIC_INLINE
+#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
+#endif
+
+/*
+   TODOAArch64: Revisit the below functions and check for potential
+   optimizations using assembly code or otherwise.
+*/
+
+extern ANDROID_ATOMIC_INLINE
+void android_compiler_barrier(void)
+{
+    __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern ANDROID_ATOMIC_INLINE
+void android_memory_barrier(void)
+{
+    android_compiler_barrier();
+}
+extern ANDROID_ATOMIC_INLINE
+void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#else
+extern ANDROID_ATOMIC_INLINE
+void android_memory_barrier(void)
+{
+    __asm__ __volatile__ ("dmb ish" : : : "memory");
+}
+extern ANDROID_ATOMIC_INLINE
+void android_memory_store_barrier(void)
+{
+    __asm__ __volatile__ ("dmb ishst" : : : "memory");
+}
+#endif
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+    int32_t value = *ptr;
+    android_memory_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_load64(volatile const int64_t *ptr)
+{
+    int64_t value = *ptr;
+    android_memory_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_load64(volatile const int64_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store64(int64_t value, volatile int64_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store64(int64_t value, volatile int64_t *ptr)
+{
+    android_memory_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_cas(int32_t old_value, int32_t new_value,
+                       volatile int32_t *ptr)
+{
+    return __sync_val_compare_and_swap(ptr, old_value, new_value) != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_cas64(int64_t old_value, int64_t new_value,
+                             volatile int64_t *ptr)
+{
+    return __sync_val_compare_and_swap(ptr, old_value, new_value) != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    int status = android_atomic_cas(old_value, new_value, ptr);
+    android_memory_barrier();
+    return status;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_cas64(int64_t old_value, int64_t new_value,
+                                     volatile int64_t *ptr)
+{
+    int status = android_atomic_cas64(old_value, new_value, ptr);
+    android_memory_barrier();
+    return status;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_release_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_cas64(int64_t old_value, int64_t new_value,
+                                     volatile int64_t *ptr)
+{
+    android_memory_barrier();
+    return android_atomic_cas64(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev + increment, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_inc(volatile int32_t *addr)
+{
+    return android_atomic_add(1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_dec(volatile int32_t *addr)
+{
+    return android_atomic_add(-1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev & value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev | value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_AARCH64_H */
diff --git a/include/cutils/atomic-inline.h b/include/cutils/atomic-inline.h
new file mode 100644
index 0000000..5c03bd6
--- /dev/null
+++ b/include/cutils/atomic-inline.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 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_CUTILS_ATOMIC_INLINE_H
+#define ANDROID_CUTILS_ATOMIC_INLINE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Inline declarations and macros for some special-purpose atomic
+ * operations.  These are intended for rare circumstances where a
+ * memory barrier needs to be issued inline rather than as a function
+ * call.
+ *
+ * Most code should not use these.
+ *
+ * Anything that does include this file must set ANDROID_SMP to either
+ * 0 or 1, indicating compilation for UP or SMP, respectively.
+ *
+ * Macros defined in this header:
+ *
+ * void ANDROID_MEMBAR_FULL(void)
+ *   Full memory barrier.  Provides a compiler reordering barrier, and
+ *   on SMP systems emits an appropriate instruction.
+ */
+
+#if !defined(ANDROID_SMP)
+# error "Must define ANDROID_SMP before including atomic-inline.h"
+#endif
+#if defined(__aarch64__)
+#include <cutils/atomic-arm64.h>
+#elif defined(__arm__)
+#include <cutils/atomic-arm.h>
+#elif defined(__i386__) || defined(__x86_64__)
+#include <cutils/atomic-x86.h>
+#elif defined(__sh__)
+/* implementation is in atomic-android-sh.c */
+#else
+#error atomic operations are unsupported
+#endif
+
+#if ANDROID_SMP == 0
+#define ANDROID_MEMBAR_FULL android_compiler_barrier
+#else
+#define ANDROID_MEMBAR_FULL android_memory_barrier
+#endif
+
+#if ANDROID_SMP == 0
+#define ANDROID_MEMBAR_STORE android_compiler_barrier
+#else
+#define ANDROID_MEMBAR_STORE android_memory_store_barrier
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ANDROID_CUTILS_ATOMIC_INLINE_H */
diff --git a/include/cutils/atomic-x86.h b/include/cutils/atomic-x86.h
new file mode 100644
index 0000000..438012e
--- /dev/null
+++ b/include/cutils/atomic-x86.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2010 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_CUTILS_ATOMIC_X86_H
+#define ANDROID_CUTILS_ATOMIC_X86_H
+
+#include <stdint.h>
+
+extern inline void android_compiler_barrier(void)
+{
+    __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern inline void android_memory_barrier(void)
+{
+    android_compiler_barrier();
+}
+extern inline void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#else
+extern inline void android_memory_barrier(void)
+{
+    __asm__ __volatile__ ("mfence" : : : "memory");
+}
+extern inline void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#endif
+
+extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+    int32_t value = *ptr;
+    android_compiler_barrier();
+    return value;
+}
+
+extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern inline void android_atomic_acquire_store(int32_t value,
+                                                volatile int32_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern inline void android_atomic_release_store(int32_t value,
+                                                volatile int32_t *ptr)
+{
+    android_compiler_barrier();
+    *ptr = value;
+}
+
+extern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
+                                     volatile int32_t *ptr)
+{
+    int32_t prev;
+    __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
+                          : "=a" (prev)
+                          : "q" (new_value), "m" (*ptr), "0" (old_value)
+                          : "memory");
+    return prev != old_value;
+}
+
+extern inline int android_atomic_acquire_cas(int32_t old_value,
+                                             int32_t new_value,
+                                             volatile int32_t *ptr)
+{
+    /* Loads are not reordered with other loads. */
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern inline int android_atomic_release_cas(int32_t old_value,
+                                             int32_t new_value,
+                                             volatile int32_t *ptr)
+{
+    /* Stores are not reordered with other stores. */
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern inline int32_t android_atomic_add(int32_t increment,
+                                         volatile int32_t *ptr)
+{
+    __asm__ __volatile__ ("lock; xaddl %0, %1"
+                          : "+r" (increment), "+m" (*ptr)
+                          : : "memory");
+    /* increment now holds the old value of *ptr */
+    return increment;
+}
+
+extern inline int32_t android_atomic_inc(volatile int32_t *addr)
+{
+    return android_atomic_add(1, addr);
+}
+
+extern inline int32_t android_atomic_dec(volatile int32_t *addr)
+{
+    return android_atomic_add(-1, addr);
+}
+
+extern inline int32_t android_atomic_and(int32_t value,
+                                         volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev & value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev | value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_X86_H */
diff --git a/include/cutils/atomic.h b/include/cutils/atomic.h
new file mode 100644
index 0000000..ae42eb8
--- /dev/null
+++ b/include/cutils/atomic.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2007 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_CUTILS_ATOMIC_H
+#define ANDROID_CUTILS_ATOMIC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * A handful of basic atomic operations.  The appropriate pthread
+ * functions should be used instead of these whenever possible.
+ *
+ * The "acquire" and "release" terms can be defined intuitively in terms
+ * of the placement of memory barriers in a simple lock implementation:
+ *   - wait until compare-and-swap(lock-is-free --> lock-is-held) succeeds
+ *   - barrier
+ *   - [do work]
+ *   - barrier
+ *   - store(lock-is-free)
+ * In very crude terms, the initial (acquire) barrier prevents any of the
+ * "work" from happening before the lock is held, and the later (release)
+ * barrier ensures that all of the work happens before the lock is released.
+ * (Think of cached writes, cache read-ahead, and instruction reordering
+ * around the CAS and store instructions.)
+ *
+ * The barriers must apply to both the compiler and the CPU.  Note it is
+ * legal for instructions that occur before an "acquire" barrier to be
+ * moved down below it, and for instructions that occur after a "release"
+ * barrier to be moved up above it.
+ *
+ * The ARM-driven implementation we use here is short on subtlety,
+ * and actually requests a full barrier from the compiler and the CPU.
+ * The only difference between acquire and release is in whether they
+ * are issued before or after the atomic operation with which they
+ * are associated.  To ease the transition to C/C++ atomic intrinsics,
+ * you should not rely on this, and instead assume that only the minimal
+ * acquire/release protection is provided.
+ *
+ * NOTE: all int32_t* values are expected to be aligned on 32-bit boundaries.
+ * If they are not, atomicity is not guaranteed.
+ */
+
+/*
+ * Basic arithmetic and bitwise operations.  These all provide a
+ * barrier with "release" ordering, and return the previous value.
+ *
+ * These have the same characteristics (e.g. what happens on overflow)
+ * as the equivalent non-atomic C operations.
+ */
+int32_t android_atomic_inc(volatile int32_t* addr);
+int32_t android_atomic_dec(volatile int32_t* addr);
+int32_t android_atomic_add(int32_t value, volatile int32_t* addr);
+int32_t android_atomic_and(int32_t value, volatile int32_t* addr);
+int32_t android_atomic_or(int32_t value, volatile int32_t* addr);
+
+/*
+ * Perform an atomic load with "acquire" or "release" ordering.
+ *
+ * This is only necessary if you need the memory barrier.  A 32-bit read
+ * from a 32-bit aligned address is atomic on all supported platforms.
+ */
+int32_t android_atomic_acquire_load(volatile const int32_t* addr);
+int32_t android_atomic_release_load(volatile const int32_t* addr);
+
+/*
+ * Perform an atomic store with "acquire" or "release" ordering.
+ *
+ * This is only necessary if you need the memory barrier.  A 32-bit write
+ * to a 32-bit aligned address is atomic on all supported platforms.
+ */
+void android_atomic_acquire_store(int32_t value, volatile int32_t* addr);
+void android_atomic_release_store(int32_t value, volatile int32_t* addr);
+
+/*
+ * Compare-and-set operation with "acquire" or "release" ordering.
+ *
+ * This returns zero if the new value was successfully stored, which will
+ * only happen when *addr == oldvalue.
+ *
+ * (The return value is inverted from implementations on other platforms,
+ * but matches the ARM ldrex/strex result.)
+ *
+ * Implementations that use the release CAS in a loop may be less efficient
+ * than possible, because we re-issue the memory barrier on each iteration.
+ */
+int android_atomic_acquire_cas(int32_t oldvalue, int32_t newvalue,
+        volatile int32_t* addr);
+int android_atomic_release_cas(int32_t oldvalue, int32_t newvalue,
+        volatile int32_t* addr);
+
+/*
+ * Aliases for code using an older version of this header.  These are now
+ * deprecated and should not be used.  The definitions will be removed
+ * in a future release.
+ */
+#define android_atomic_write android_atomic_release_store
+#define android_atomic_cmpxchg android_atomic_release_cas
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ANDROID_CUTILS_ATOMIC_H
diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h
new file mode 100644
index 0000000..38d2840
--- /dev/null
+++ b/include/cutils/bitops.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef __CUTILS_BITOPS_H
+#define __CUTILS_BITOPS_H
+
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+static inline int popcount(unsigned int x) {
+    return __builtin_popcount(x);
+}
+
+static inline int popcountl(unsigned long x) {
+    return __builtin_popcountl(x);
+}
+
+static inline int popcountll(unsigned long long x) {
+    return __builtin_popcountll(x);
+}
+
+__END_DECLS
+
+#endif /* __CUTILS_BITOPS_H */
diff --git a/include/cutils/compiler.h b/include/cutils/compiler.h
new file mode 100644
index 0000000..70f884a
--- /dev/null
+++ b/include/cutils/compiler.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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_CUTILS_COMPILER_H
+#define ANDROID_CUTILS_COMPILER_H
+
+/*
+ * helps the compiler's optimizer predicting branches
+ */
+
+#ifdef __cplusplus
+#   define CC_LIKELY( exp )    (__builtin_expect( !!(exp), true ))
+#   define CC_UNLIKELY( exp )  (__builtin_expect( !!(exp), false ))
+#else
+#   define CC_LIKELY( exp )    (__builtin_expect( !!(exp), 1 ))
+#   define CC_UNLIKELY( exp )  (__builtin_expect( !!(exp), 0 ))
+#endif
+
+/**
+ * exports marked symbols
+ *
+ * if used on a C++ class declaration, this macro must be inserted
+ * after the "class" keyword. For instance:
+ *
+ * template <typename TYPE>
+ * class ANDROID_API Singleton { }
+ */
+
+#define ANDROID_API __attribute__((visibility("default")))
+
+#endif // ANDROID_CUTILS_COMPILER_H
diff --git a/include/cutils/config_utils.h b/include/cutils/config_utils.h
new file mode 100644
index 0000000..30e762f
--- /dev/null
+++ b/include/cutils/config_utils.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006 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 __CUTILS_CONFIG_UTILS_H
+#define __CUTILS_CONFIG_UTILS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct cnode cnode;
+
+
+struct cnode
+{
+    cnode *next;
+    cnode *first_child;
+    cnode *last_child;
+    const char *name;
+    const char *value;
+};
+
+/* parse a text string into a config node tree */
+void config_load(cnode *root, char *data);
+
+/* parse a file into a config node tree */
+void config_load_file(cnode *root, const char *fn);
+
+/* create a single config node */
+cnode* config_node(const char *name, const char *value);
+
+/* locate a named child of a config node */
+cnode* config_find(cnode *root, const char *name);
+
+/* look up a child by name and return the boolean value */
+int config_bool(cnode *root, const char *name, int _default);
+
+/* look up a child by name and return the string value */
+const char* config_str(cnode *root, const char *name, const char *_default);
+
+/* add a named child to a config node (or modify it if it already exists) */
+void config_set(cnode *root, const char *name, const char *value);
+
+/* free a config node tree */
+void config_free(cnode *root);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cutils/cpu_info.h b/include/cutils/cpu_info.h
new file mode 100644
index 0000000..e1170e4
--- /dev/null
+++ b/include/cutils/cpu_info.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2007 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 __CUTILS_CPU_INFO_H
+#define __CUTILS_CPU_INFO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* returns a string contiaining an ASCII representation of the CPU serial number,
+** or NULL if cpu info not available.
+** The string is a static variable, so don't call free() on it.
+*/
+extern const char* get_cpu_serial_number(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_CPU_INFO_H */
diff --git a/include/cutils/dir_hash.h b/include/cutils/dir_hash.h
new file mode 100644
index 0000000..fbb4d02
--- /dev/null
+++ b/include/cutils/dir_hash.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+typedef enum {
+    SHA_1,
+} HashAlgorithm;
+
+int get_file_hash(HashAlgorithm algorithm, const char *path,
+                  char *output_string, size_t max_output_string);
+
+int get_recursive_hash_manifest(HashAlgorithm algorithm,
+                                const char *directory_path,
+                                char **output_string);
diff --git a/include/cutils/dlmalloc.h b/include/cutils/dlmalloc.h
new file mode 100644
index 0000000..1b642d2
--- /dev/null
+++ b/include/cutils/dlmalloc.h
@@ -0,0 +1,655 @@
+/*
+  Default header file for malloc-2.8.x, written by Doug Lea
+  and released to the public domain, as explained at
+  http://creativecommons.org/licenses/publicdomain.
+
+  last update: Mon Aug 15 08:55:52 2005  Doug Lea  (dl at gee)
+
+  This header is for ANSI C/C++ only.  You can set any of
+  the following #defines before including:
+
+  * If USE_DL_PREFIX is defined, it is assumed that malloc.c
+    was also compiled with this option, so all routines
+    have names starting with "dl".
+
+  * If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this
+    file will be #included AFTER <malloc.h>. This is needed only if
+    your system defines a struct mallinfo that is incompatible with the
+    standard one declared here.  Otherwise, you can include this file
+    INSTEAD of your system system <malloc.h>.  At least on ANSI, all
+    declarations should be compatible with system versions
+
+  * If MSPACES is defined, declarations for mspace versions are included.
+*/
+
+#ifndef MALLOC_280_H
+#define MALLOC_280_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>   /* for size_t */
+
+#if !ONLY_MSPACES
+
+/* Check an additional macro for the five primary functions */
+#if !defined(USE_DL_PREFIX)
+#define dlcalloc               calloc
+#define dlfree                 free
+#define dlmalloc               malloc
+#define dlmemalign             memalign
+#define dlrealloc              realloc
+#endif
+
+#ifndef USE_DL_PREFIX
+#define dlvalloc               valloc
+#define dlpvalloc              pvalloc
+#define dlmallinfo             mallinfo
+#define dlmallopt              mallopt
+#define dlmalloc_trim          malloc_trim
+#define dlmalloc_walk_free_pages \
+                               malloc_walk_free_pages
+#define dlmalloc_walk_heap \
+                               malloc_walk_heap
+#define dlmalloc_stats         malloc_stats
+#define dlmalloc_usable_size   malloc_usable_size
+#define dlmalloc_footprint     malloc_footprint
+#define dlmalloc_max_allowed_footprint \
+                               malloc_max_allowed_footprint
+#define dlmalloc_set_max_allowed_footprint \
+                               malloc_set_max_allowed_footprint
+#define dlmalloc_max_footprint malloc_max_footprint
+#define dlindependent_calloc   independent_calloc
+#define dlindependent_comalloc independent_comalloc
+#endif /* USE_DL_PREFIX */
+
+
+/*
+  malloc(size_t n)
+  Returns a pointer to a newly allocated chunk of at least n bytes, or
+  null if no space is available, in which case errno is set to ENOMEM
+  on ANSI C systems.
+
+  If n is zero, malloc returns a minimum-sized chunk. (The minimum
+  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
+  systems.)  Note that size_t is an unsigned type, so calls with
+  arguments that would be negative if signed are interpreted as
+  requests for huge amounts of space, which will often fail. The
+  maximum supported value of n differs across systems, but is in all
+  cases less than the maximum representable value of a size_t.
+*/
+void* dlmalloc(size_t);
+
+/*
+  free(void* p)
+  Releases the chunk of memory pointed to by p, that had been previously
+  allocated using malloc or a related routine such as realloc.
+  It has no effect if p is null. If p was not malloced or already
+  freed, free(p) will by default cuase the current program to abort.
+*/
+void  dlfree(void*);
+
+/*
+  calloc(size_t n_elements, size_t element_size);
+  Returns a pointer to n_elements * element_size bytes, with all locations
+  set to zero.
+*/
+void* dlcalloc(size_t, size_t);
+
+/*
+  realloc(void* p, size_t n)
+  Returns a pointer to a chunk of size n that contains the same data
+  as does chunk p up to the minimum of (n, p's size) bytes, or null
+  if no space is available.
+
+  The returned pointer may or may not be the same as p. The algorithm
+  prefers extending p in most cases when possible, otherwise it
+  employs the equivalent of a malloc-copy-free sequence.
+
+  If p is null, realloc is equivalent to malloc.
+
+  If space is not available, realloc returns null, errno is set (if on
+  ANSI) and p is NOT freed.
+
+  if n is for fewer bytes than already held by p, the newly unused
+  space is lopped off and freed if possible.  realloc with a size
+  argument of zero (re)allocates a minimum-sized chunk.
+
+  The old unix realloc convention of allowing the last-free'd chunk
+  to be used as an argument to realloc is not supported.
+*/
+
+void* dlrealloc(void*, size_t);
+
+/*
+  memalign(size_t alignment, size_t n);
+  Returns a pointer to a newly allocated chunk of n bytes, aligned
+  in accord with the alignment argument.
+
+  The alignment argument should be a power of two. If the argument is
+  not a power of two, the nearest greater power is used.
+  8-byte alignment is guaranteed by normal malloc calls, so don't
+  bother calling memalign with an argument of 8 or less.
+
+  Overreliance on memalign is a sure way to fragment space.
+*/
+void* dlmemalign(size_t, size_t);
+
+/*
+  valloc(size_t n);
+  Equivalent to memalign(pagesize, n), where pagesize is the page
+  size of the system. If the pagesize is unknown, 4096 is used.
+*/
+void* dlvalloc(size_t);
+
+/*
+  mallopt(int parameter_number, int parameter_value)
+  Sets tunable parameters The format is to provide a
+  (parameter-number, parameter-value) pair.  mallopt then sets the
+  corresponding parameter to the argument value if it can (i.e., so
+  long as the value is meaningful), and returns 1 if successful else
+  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,
+  normally defined in malloc.h.  None of these are use in this malloc,
+  so setting them has no effect. But this malloc also supports other
+  options in mallopt:
+
+  Symbol            param #  default    allowed param values
+  M_TRIM_THRESHOLD     -1   2*1024*1024   any   (-1U disables trimming)
+  M_GRANULARITY        -2     page size   any power of 2 >= page size
+  M_MMAP_THRESHOLD     -3      256*1024   any   (or 0 if no MMAP support)
+*/
+int dlmallopt(int, int);
+
+#define M_TRIM_THRESHOLD     (-1)
+#define M_GRANULARITY        (-2)
+#define M_MMAP_THRESHOLD     (-3)
+
+
+/*
+  malloc_footprint();
+  Returns the number of bytes obtained from the system.  The total
+  number of bytes allocated by malloc, realloc etc., is less than this
+  value. Unlike mallinfo, this function returns only a precomputed
+  result, so can be called frequently to monitor memory consumption.
+  Even if locks are otherwise defined, this function does not use them,
+  so results might not be up to date.
+*/
+size_t dlmalloc_footprint();
+
+/*
+  malloc_max_allowed_footprint();
+  Returns the number of bytes that the heap is allowed to obtain
+  from the system.  malloc_footprint() should always return a
+  size less than or equal to max_allowed_footprint, unless the
+  max_allowed_footprint was set to a value smaller than the
+  footprint at the time.
+
+  This function is only available if dlmalloc.c was compiled
+  with USE_MAX_ALLOWED_FOOTPRINT set.
+*/
+size_t dlmalloc_max_allowed_footprint();
+
+/*
+  malloc_set_max_allowed_footprint();
+  Set the maximum number of bytes that the heap is allowed to
+  obtain from the system.  The size will be rounded up to a whole
+  page, and the rounded number will be returned from future calls
+  to malloc_max_allowed_footprint().  If the new max_allowed_footprint
+  is larger than the current footprint, the heap will never grow
+  larger than max_allowed_footprint.  If the new max_allowed_footprint
+  is smaller than the current footprint, the heap will not grow
+  further.
+
+  This function is only available if dlmalloc.c was compiled
+  with USE_MAX_ALLOWED_FOOTPRINT set.
+
+  TODO: try to force the heap to give up memory in the shrink case,
+        and update this comment once that happens.
+*/
+void dlmalloc_set_max_allowed_footprint(size_t bytes);
+
+/*
+  malloc_max_footprint();
+  Returns the maximum number of bytes obtained from the system. This
+  value will be greater than current footprint if deallocated space
+  has been reclaimed by the system. The peak number of bytes allocated
+  by malloc, realloc etc., is less than this value. Unlike mallinfo,
+  this function returns only a precomputed result, so can be called
+  frequently to monitor memory consumption.  Even if locks are
+  otherwise defined, this function does not use them, so results might
+  not be up to date.
+*/
+size_t dlmalloc_max_footprint(void);
+
+#if !NO_MALLINFO
+/*
+  mallinfo()
+  Returns (by copy) a struct containing various summary statistics:
+
+  arena:     current total non-mmapped bytes allocated from system
+  ordblks:   the number of free chunks
+  smblks:    always zero.
+  hblks:     current number of mmapped regions
+  hblkhd:    total bytes held in mmapped regions
+  usmblks:   the maximum total allocated space. This will be greater
+                than current total if trimming has occurred.
+  fsmblks:   always zero
+  uordblks:  current total allocated space (normal or mmapped)
+  fordblks:  total free space
+  keepcost:  the maximum number of bytes that could ideally be released
+               back to system via malloc_trim. ("ideally" means that
+               it ignores page restrictions etc.)
+
+  Because these fields are ints, but internal bookkeeping may
+  be kept as longs, the reported values may wrap around zero and
+  thus be inaccurate.
+*/
+#ifndef HAVE_USR_INCLUDE_MALLOC_H
+#ifndef _MALLOC_H_
+#ifndef MALLINFO_FIELD_TYPE
+#define MALLINFO_FIELD_TYPE size_t
+#endif /* MALLINFO_FIELD_TYPE */
+struct mallinfo {
+  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system */
+  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */
+  MALLINFO_FIELD_TYPE smblks;   /* always 0 */
+  MALLINFO_FIELD_TYPE hblks;    /* always 0 */
+  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */
+  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */
+  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */
+  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
+  MALLINFO_FIELD_TYPE fordblks; /* total free space */
+  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
+};
+#endif  /* _MALLOC_H_ */
+#endif  /* HAVE_USR_INCLUDE_MALLOC_H */
+
+struct mallinfo dlmallinfo(void);
+#endif  /* NO_MALLINFO */
+
+/*
+  independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
+
+  independent_calloc is similar to calloc, but instead of returning a
+  single cleared space, it returns an array of pointers to n_elements
+  independent elements that can hold contents of size elem_size, each
+  of which starts out cleared, and can be independently freed,
+  realloc'ed etc. The elements are guaranteed to be adjacently
+  allocated (this is not guaranteed to occur with multiple callocs or
+  mallocs), which may also improve cache locality in some
+  applications.
+
+  The "chunks" argument is optional (i.e., may be null, which is
+  probably the most typical usage). If it is null, the returned array
+  is itself dynamically allocated and should also be freed when it is
+  no longer needed. Otherwise, the chunks array must be of at least
+  n_elements in length. It is filled in with the pointers to the
+  chunks.
+
+  In either case, independent_calloc returns this pointer array, or
+  null if the allocation failed.  If n_elements is zero and "chunks"
+  is null, it returns a chunk representing an array with zero elements
+  (which should be freed if not wanted).
+
+  Each element must be individually freed when it is no longer
+  needed. If you'd like to instead be able to free all at once, you
+  should instead use regular calloc and assign pointers into this
+  space to represent elements.  (In this case though, you cannot
+  independently free elements.)
+
+  independent_calloc simplifies and speeds up implementations of many
+  kinds of pools.  It may also be useful when constructing large data
+  structures that initially have a fixed number of fixed-sized nodes,
+  but the number is not known at compile time, and some of the nodes
+  may later need to be freed. For example:
+
+  struct Node { int item; struct Node* next; };
+
+  struct Node* build_list() {
+    struct Node** pool;
+    int n = read_number_of_nodes_needed();
+    if (n <= 0) return 0;
+    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
+    if (pool == 0) die();
+    // organize into a linked list...
+    struct Node* first = pool[0];
+    for (i = 0; i < n-1; ++i)
+      pool[i]->next = pool[i+1];
+    free(pool);     // Can now free the array (or not, if it is needed later)
+    return first;
+  }
+*/
+void** dlindependent_calloc(size_t, size_t, void**);
+
+/*
+  independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
+
+  independent_comalloc allocates, all at once, a set of n_elements
+  chunks with sizes indicated in the "sizes" array.    It returns
+  an array of pointers to these elements, each of which can be
+  independently freed, realloc'ed etc. The elements are guaranteed to
+  be adjacently allocated (this is not guaranteed to occur with
+  multiple callocs or mallocs), which may also improve cache locality
+  in some applications.
+
+  The "chunks" argument is optional (i.e., may be null). If it is null
+  the returned array is itself dynamically allocated and should also
+  be freed when it is no longer needed. Otherwise, the chunks array
+  must be of at least n_elements in length. It is filled in with the
+  pointers to the chunks.
+
+  In either case, independent_comalloc returns this pointer array, or
+  null if the allocation failed.  If n_elements is zero and chunks is
+  null, it returns a chunk representing an array with zero elements
+  (which should be freed if not wanted).
+
+  Each element must be individually freed when it is no longer
+  needed. If you'd like to instead be able to free all at once, you
+  should instead use a single regular malloc, and assign pointers at
+  particular offsets in the aggregate space. (In this case though, you
+  cannot independently free elements.)
+
+  independent_comallac differs from independent_calloc in that each
+  element may have a different size, and also that it does not
+  automatically clear elements.
+
+  independent_comalloc can be used to speed up allocation in cases
+  where several structs or objects must always be allocated at the
+  same time.  For example:
+
+  struct Head { ... }
+  struct Foot { ... }
+
+  void send_message(char* msg) {
+    int msglen = strlen(msg);
+    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
+    void* chunks[3];
+    if (independent_comalloc(3, sizes, chunks) == 0)
+      die();
+    struct Head* head = (struct Head*)(chunks[0]);
+    char*        body = (char*)(chunks[1]);
+    struct Foot* foot = (struct Foot*)(chunks[2]);
+    // ...
+  }
+
+  In general though, independent_comalloc is worth using only for
+  larger values of n_elements. For small values, you probably won't
+  detect enough difference from series of malloc calls to bother.
+
+  Overuse of independent_comalloc can increase overall memory usage,
+  since it cannot reuse existing noncontiguous small chunks that
+  might be available for some of the elements.
+*/
+void** dlindependent_comalloc(size_t, size_t*, void**);
+
+
+/*
+  pvalloc(size_t n);
+  Equivalent to valloc(minimum-page-that-holds(n)), that is,
+  round up n to nearest pagesize.
+ */
+void*  dlpvalloc(size_t);
+
+/*
+  malloc_trim(size_t pad);
+
+  If possible, gives memory back to the system (via negative arguments
+  to sbrk) if there is unused memory at the `high' end of the malloc
+  pool or in unused MMAP segments. You can call this after freeing
+  large blocks of memory to potentially reduce the system-level memory
+  requirements of a program. However, it cannot guarantee to reduce
+  memory. Under some allocation patterns, some large free blocks of
+  memory will be locked between two used chunks, so they cannot be
+  given back to the system.
+
+  The `pad' argument to malloc_trim represents the amount of free
+  trailing space to leave untrimmed. If this argument is zero, only
+  the minimum amount of memory to maintain internal data structures
+  will be left. Non-zero arguments can be supplied to maintain enough
+  trailing space to service future expected allocations without having
+  to re-obtain memory from the system.
+
+  Malloc_trim returns 1 if it actually released any memory, else 0.
+*/
+int  dlmalloc_trim(size_t);
+
+/*
+  malloc_walk_free_pages(handler, harg)
+
+  Calls the provided handler on each free region in the heap.  The
+  memory between start and end are guaranteed not to contain any
+  important data, so the handler is free to alter the contents
+  in any way.  This can be used to advise the OS that large free
+  regions may be swapped out.
+
+  The value in harg will be passed to each call of the handler.
+ */
+void dlmalloc_walk_free_pages(void(*handler)(void *start, void *end, void *arg),
+    void *harg);
+
+/*
+  malloc_walk_heap(handler, harg)
+
+  Calls the provided handler on each object or free region in the
+  heap.  The handler will receive the chunk pointer and length, the
+  object pointer and length, and the value in harg on each call.
+ */
+void dlmalloc_walk_heap(void(*handler)(const void *chunkptr, size_t chunklen,
+                                       const void *userptr, size_t userlen,
+                                       void *arg),
+                        void *harg);
+
+/*
+  malloc_usable_size(void* p);
+
+  Returns the number of bytes you can actually use in
+  an allocated chunk, which may be more than you requested (although
+  often not) due to alignment and minimum size constraints.
+  You can use this many bytes without worrying about
+  overwriting other allocated objects. This is not a particularly great
+  programming practice. malloc_usable_size can be more useful in
+  debugging and assertions, for example:
+
+  p = malloc(n);
+  assert(malloc_usable_size(p) >= 256);
+*/
+size_t dlmalloc_usable_size(void*);
+
+/*
+  malloc_stats();
+  Prints on stderr the amount of space obtained from the system (both
+  via sbrk and mmap), the maximum amount (which may be more than
+  current if malloc_trim and/or munmap got called), and the current
+  number of bytes allocated via malloc (or realloc, etc) but not yet
+  freed. Note that this is the number of bytes allocated, not the
+  number requested. It will be larger than the number requested
+  because of alignment and bookkeeping overhead. Because it includes
+  alignment wastage as being in use, this figure may be greater than
+  zero even when no user-level chunks are allocated.
+
+  The reported current and maximum system memory can be inaccurate if
+  a program makes other calls to system memory allocation functions
+  (normally sbrk) outside of malloc.
+
+  malloc_stats prints only the most commonly interesting statistics.
+  More information can be obtained by calling mallinfo.
+*/
+void  dlmalloc_stats();
+
+#endif /* !ONLY_MSPACES */
+
+#if MSPACES
+
+/*
+  mspace is an opaque type representing an independent
+  region of space that supports mspace_malloc, etc.
+*/
+typedef void* mspace;
+
+/*
+  create_mspace creates and returns a new independent space with the
+  given initial capacity, or, if 0, the default granularity size.  It
+  returns null if there is no system memory available to create the
+  space.  If argument locked is non-zero, the space uses a separate
+  lock to control access. The capacity of the space will grow
+  dynamically as needed to service mspace_malloc requests.  You can
+  control the sizes of incremental increases of this space by
+  compiling with a different DEFAULT_GRANULARITY or dynamically
+  setting with mallopt(M_GRANULARITY, value).
+*/
+mspace create_mspace(size_t capacity, int locked);
+
+/*
+  destroy_mspace destroys the given space, and attempts to return all
+  of its memory back to the system, returning the total number of
+  bytes freed. After destruction, the results of access to all memory
+  used by the space become undefined.
+*/
+size_t destroy_mspace(mspace msp);
+
+/*
+  create_mspace_with_base uses the memory supplied as the initial base
+  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
+  space is used for bookkeeping, so the capacity must be at least this
+  large. (Otherwise 0 is returned.) When this initial space is
+  exhausted, additional memory will be obtained from the system.
+  Destroying this space will deallocate all additionally allocated
+  space (if possible) but not the initial base.
+*/
+mspace create_mspace_with_base(void* base, size_t capacity, int locked);
+
+/*
+  mspace_malloc behaves as malloc, but operates within
+  the given space.
+*/
+void* mspace_malloc(mspace msp, size_t bytes);
+
+/*
+  mspace_free behaves as free, but operates within
+  the given space.
+
+  If compiled with FOOTERS==1, mspace_free is not actually needed.
+  free may be called instead of mspace_free because freed chunks from
+  any space are handled by their originating spaces.
+*/
+void mspace_free(mspace msp, void* mem);
+
+/*
+  mspace_realloc behaves as realloc, but operates within
+  the given space.
+
+  If compiled with FOOTERS==1, mspace_realloc is not actually
+  needed.  realloc may be called instead of mspace_realloc because
+  realloced chunks from any space are handled by their originating
+  spaces.
+*/
+void* mspace_realloc(mspace msp, void* mem, size_t newsize);
+
+/*
+  mspace_merge_objects will merge allocated memory mema and memb
+  together, provided memb immediately follows mema.  It is roughly as
+  if memb has been freed and mema has been realloced to a larger size.
+  On successfully merging, mema will be returned. If either argument
+  is null or memb does not immediately follow mema, null will be
+  returned.
+
+  Both mema and memb should have been previously allocated using
+  malloc or a related routine such as realloc. If either mema or memb
+  was not malloced or was previously freed, the result is undefined,
+  but like mspace_free, the default is to abort the program.
+*/
+void* mspace_merge_objects(mspace msp, void* mema, void* memb);
+
+/*
+  mspace_calloc behaves as calloc, but operates within
+  the given space.
+*/
+void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
+
+/*
+  mspace_memalign behaves as memalign, but operates within
+  the given space.
+*/
+void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
+
+/*
+  mspace_independent_calloc behaves as independent_calloc, but
+  operates within the given space.
+*/
+void** mspace_independent_calloc(mspace msp, size_t n_elements,
+                                 size_t elem_size, void* chunks[]);
+
+/*
+  mspace_independent_comalloc behaves as independent_comalloc, but
+  operates within the given space.
+*/
+void** mspace_independent_comalloc(mspace msp, size_t n_elements,
+                                   size_t sizes[], void* chunks[]);
+
+/*
+  mspace_footprint() returns the number of bytes obtained from the
+  system for this space.
+*/
+size_t mspace_footprint(mspace msp);
+
+/*
+  mspace_max_allowed_footprint() returns the number of bytes that
+  this space is allowed to obtain from the system. See
+  malloc_max_allowed_footprint() for a more in-depth description.
+
+  This function is only available if dlmalloc.c was compiled
+  with USE_MAX_ALLOWED_FOOTPRINT set.
+*/
+size_t mspace_max_allowed_footprint(mspace msp);
+
+/*
+  mspace_set_max_allowed_footprint() sets the maximum number of
+  bytes (rounded up to a page) that this space is allowed to
+  obtain from the system.  See malloc_set_max_allowed_footprint()
+  for a more in-depth description.
+
+  This function is only available if dlmalloc.c was compiled
+  with USE_MAX_ALLOWED_FOOTPRINT set.
+*/
+void mspace_set_max_allowed_footprint(mspace msp, size_t bytes);
+
+/*
+  mspace_max_footprint() returns the maximum number of bytes obtained
+  from the system over the lifetime of this space.
+*/
+size_t mspace_max_footprint(mspace msp);
+
+
+#if !NO_MALLINFO
+/*
+  mspace_mallinfo behaves as mallinfo, but reports properties of
+  the given space.
+*/
+struct mallinfo mspace_mallinfo(mspace msp);
+#endif /* NO_MALLINFO */
+
+/*
+  mspace_malloc_stats behaves as malloc_stats, but reports
+  properties of the given space.
+*/
+void mspace_malloc_stats(mspace msp);
+
+/*
+  mspace_trim behaves as malloc_trim, but
+  operates within the given space.
+*/
+int mspace_trim(mspace msp, size_t pad);
+
+/*
+  An alias for mallopt.
+*/
+int mspace_mallopt(int, int);
+
+#endif  /* MSPACES */
+
+#ifdef __cplusplus
+};  /* end of extern "C" */
+#endif
+
+#endif /* MALLOC_280_H */
diff --git a/include/cutils/event_tag_map.h b/include/cutils/event_tag_map.h
new file mode 100644
index 0000000..1653c61
--- /dev/null
+++ b/include/cutils/event_tag_map.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 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 _LIBS_CUTILS_EVENTTAGMAP_H
+#define _LIBS_CUTILS_EVENTTAGMAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EVENT_TAG_MAP_FILE  "/system/etc/event-log-tags"
+
+struct EventTagMap;
+typedef struct EventTagMap EventTagMap;
+
+/*
+ * Open the specified file as an event log tag map.
+ *
+ * Returns NULL on failure.
+ */
+EventTagMap* android_openEventTagMap(const char* fileName);
+
+/*
+ * Close the map.
+ */
+void android_closeEventTagMap(EventTagMap* map);
+
+/*
+ * Look up a tag by index.  Returns the tag string, or NULL if not found.
+ */
+const char* android_lookupEventTag(const EventTagMap* map, int tag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_LIBS_CUTILS_EVENTTAGMAP_H*/
diff --git a/include/cutils/hashmap.h b/include/cutils/hashmap.h
new file mode 100644
index 0000000..5cb344c
--- /dev/null
+++ b/include/cutils/hashmap.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/**
+ * Hash map.
+ */
+
+#ifndef __HASHMAP_H
+#define __HASHMAP_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** A hash map. */
+typedef struct Hashmap Hashmap;
+
+/**
+ * Creates a new hash map. Returns NULL if memory allocation fails.
+ *
+ * @param initialCapacity number of expected entries
+ * @param hash function which hashes keys
+ * @param equals function which compares keys for equality
+ */
+Hashmap* hashmapCreate(size_t initialCapacity,
+        int (*hash)(void* key), bool (*equals)(void* keyA, void* keyB));
+
+/**
+ * Frees the hash map. Does not free the keys or values themselves.
+ */
+void hashmapFree(Hashmap* map);
+
+/**
+ * Hashes the memory pointed to by key with the given size. Useful for
+ * implementing hash functions.
+ */
+int hashmapHash(void* key, size_t keySize);
+
+/**
+ * Puts value for the given key in the map. Returns pre-existing value if
+ * any.
+ *
+ * If memory allocation fails, this function returns NULL, the map's size
+ * does not increase, and errno is set to ENOMEM.
+ */
+void* hashmapPut(Hashmap* map, void* key, void* value);
+
+/**
+ * Gets a value from the map. Returns NULL if no entry for the given key is
+ * found or if the value itself is NULL.
+ */
+void* hashmapGet(Hashmap* map, void* key);
+
+/**
+ * Returns true if the map contains an entry for the given key.
+ */
+bool hashmapContainsKey(Hashmap* map, void* key);
+
+/**
+ * Gets the value for a key. If a value is not found, this function gets a 
+ * value and creates an entry using the given callback.
+ *
+ * If memory allocation fails, the callback is not called, this function
+ * returns NULL, and errno is set to ENOMEM.
+ */
+void* hashmapMemoize(Hashmap* map, void* key, 
+        void* (*initialValue)(void* key, void* context), void* context);
+
+/**
+ * Removes an entry from the map. Returns the removed value or NULL if no
+ * entry was present.
+ */
+void* hashmapRemove(Hashmap* map, void* key);
+
+/**
+ * Gets the number of entries in this map.
+ */
+size_t hashmapSize(Hashmap* map);
+
+/**
+ * Invokes the given callback on each entry in the map. Stops iterating if
+ * the callback returns false.
+ */
+void hashmapForEach(Hashmap* map, 
+        bool (*callback)(void* key, void* value, void* context),
+        void* context);
+
+/**
+ * Concurrency support.
+ */
+
+/**
+ * Locks the hash map so only the current thread can access it.
+ */
+void hashmapLock(Hashmap* map);
+
+/**
+ * Unlocks the hash map so other threads can access it.
+ */
+void hashmapUnlock(Hashmap* map);
+
+/**
+ * Key utilities.
+ */
+
+/**
+ * Hashes int keys. 'key' is a pointer to int.
+ */
+int hashmapIntHash(void* key);
+
+/**
+ * Compares two int keys for equality.
+ */
+bool hashmapIntEquals(void* keyA, void* keyB);
+
+/**
+ * For debugging.
+ */
+
+/**
+ * Gets current capacity.
+ */
+size_t hashmapCurrentCapacity(Hashmap* map);
+
+/**
+ * Counts the number of entry collisions.
+ */
+size_t hashmapCountCollisions(Hashmap* map);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HASHMAP_H */ 
diff --git a/include/cutils/iosched_policy.h b/include/cutils/iosched_policy.h
new file mode 100644
index 0000000..175494a
--- /dev/null
+++ b/include/cutils/iosched_policy.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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 __CUTILS_IOSCHED_POLICY_H
+#define __CUTILS_IOSCHED_POLICY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    IoSchedClass_NONE,
+    IoSchedClass_RT,
+    IoSchedClass_BE,
+    IoSchedClass_IDLE,
+} IoSchedClass;
+
+extern int android_set_ioprio(int pid, IoSchedClass clazz, int ioprio);
+extern int android_get_ioprio(int pid, IoSchedClass *clazz, int *ioprio);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_IOSCHED_POLICY_H */
diff --git a/include/cutils/jstring.h b/include/cutils/jstring.h
new file mode 100644
index 0000000..ee0018f
--- /dev/null
+++ b/include/cutils/jstring.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2006 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 __CUTILS_STRING16_H
+#define __CUTILS_STRING16_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint16_t char16_t;
+
+extern char * strndup16to8 (const char16_t* s, size_t n);
+extern size_t strnlen16to8 (const char16_t* s, size_t n);
+extern char * strncpy16to8 (char *dest, const char16_t*s, size_t n);
+
+extern char16_t * strdup8to16 (const char* s, size_t *out_len);
+extern size_t strlen8to16 (const char* utf8Str);
+extern char16_t * strcpy8to16 (char16_t *dest, const char*s, size_t *out_len);
+extern char16_t * strcpylen8to16 (char16_t *dest, const char*s, int length,
+    size_t *out_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_STRING16_H */
diff --git a/include/cutils/klog.h b/include/cutils/klog.h
new file mode 100644
index 0000000..1335543
--- /dev/null
+++ b/include/cutils/klog.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 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 _CUTILS_KLOG_H_
+#define _CUTILS_KLOG_H_
+
+void klog_init(void);
+void klog_set_level(int level);
+void klog_close(void);
+void klog_write(int level, const char *fmt, ...)
+    __attribute__ ((format(printf, 2, 3)));
+
+#define KLOG_ERROR(tag,x...)   klog_write(3, "<3>" tag ": " x)
+#define KLOG_WARNING(tag,x...) klog_write(4, "<4>" tag ": " x)
+#define KLOG_NOTICE(tag,x...)  klog_write(5, "<5>" tag ": " x)
+#define KLOG_INFO(tag,x...)    klog_write(6, "<6>" tag ": " x)
+#define KLOG_DEBUG(tag,x...)   klog_write(7, "<7>" tag ": " x)
+
+#define KLOG_DEFAULT_LEVEL  3  /* messages <= this level are logged */
+
+#endif
diff --git a/include/cutils/list.h b/include/cutils/list.h
new file mode 100644
index 0000000..dfdc53b
--- /dev/null
+++ b/include/cutils/list.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008-2013 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 _CUTILS_LIST_H_
+#define _CUTILS_LIST_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct listnode
+{
+    struct listnode *next;
+    struct listnode *prev;
+};
+
+#define node_to_item(node, container, member) \
+    (container *) (((char*) (node)) - offsetof(container, member))
+
+#define list_declare(name) \
+    struct listnode name = { \
+        .next = &(name), \
+        .prev = &(name), \
+    }
+
+#define list_for_each(node, list) \
+    for ((node) = (list)->next; (node) != (list); (node) = (node)->next)
+
+#define list_for_each_reverse(node, list) \
+    for ((node) = (list)->prev; (node) != (list); (node) = (node)->prev)
+
+#define list_for_each_safe(node, n, list) \
+    for ((node) = (list)->next, (n) = (node)->next; \
+         (node) != (list); \
+         (node) = (n), (n) = (node)->next)
+
+static inline void list_init(struct listnode *node)
+{
+    node->next = node;
+    node->prev = node;
+}
+
+static inline void list_add_tail(struct listnode *head, struct listnode *item)
+{
+    item->next = head;
+    item->prev = head->prev;
+    head->prev->next = item;
+    head->prev = item;
+}
+
+static inline void list_add_head(struct listnode *head, struct listnode *item)
+{
+    item->next = head->next;
+    item->prev = head;
+    head->next->prev = item;
+    head->next = item;
+}
+
+static inline void list_remove(struct listnode *item)
+{
+    item->next->prev = item->prev;
+    item->prev->next = item->next;
+}
+
+#define list_empty(list) ((list) == (list)->next)
+#define list_head(list) ((list)->next)
+#define list_tail(list) ((list)->prev)
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif
diff --git a/include/cutils/log.h b/include/cutils/log.h
new file mode 100644
index 0000000..0339bce
--- /dev/null
+++ b/include/cutils/log.h
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// C/C++ logging functions.  See the logging documentation for API details.
+//
+// We'd like these to be available from C code (in case we import some from
+// somewhere), so this has a C interface.
+//
+// The output will be correct when the log file is shared between multiple
+// threads and/or multiple processes so long as the operating system
+// supports O_APPEND.  These calls have mutex-protected data structures
+// and so are NOT reentrant.  Do not use LOG in a signal handler.
+//
+#ifndef _LIBS_CUTILS_LOG_H
+#define _LIBS_CUTILS_LOG_H
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+#include <stdarg.h>
+
+#include <cutils/uio.h>
+#include <cutils/logd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Normally we strip ALOGV (VERBOSE messages) from release builds.
+ * You can modify this (for example with "#define LOG_NDEBUG 0"
+ * at the top of your source file) to change that behavior.
+ */
+#ifndef LOG_NDEBUG
+#ifdef NDEBUG
+#define LOG_NDEBUG 1
+#else
+#define LOG_NDEBUG 0
+#endif
+#endif
+
+/*
+ * This is the local tag used for the following simplified
+ * logging macros.  You can change this preprocessor definition
+ * before using the other macros to change the tag.
+ */
+#ifndef LOG_TAG
+#define LOG_TAG NULL
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose log message using the current LOG_TAG.
+ */
+#ifndef ALOGV
+#if LOG_NDEBUG
+#define ALOGV(...)   ((void)0)
+#else
+#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#endif
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGV
+#define LOGV ALOGV
+#endif
+#endif
+
+#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
+
+#ifndef ALOGV_IF
+#if LOG_NDEBUG
+#define ALOGV_IF(cond, ...)   ((void)0)
+#else
+#define ALOGV_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGV_IF
+#define LOGV_IF ALOGV_IF
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug log message using the current LOG_TAG.
+ */
+#ifndef ALOGD
+#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGD
+#define LOGD ALOGD
+#endif
+#endif
+
+#ifndef ALOGD_IF
+#define ALOGD_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGD_IF
+#define LOGD_IF ALOGD_IF
+#endif
+#endif
+
+/*
+ * Simplified macro to send an info log message using the current LOG_TAG.
+ */
+#ifndef ALOGI
+#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGI
+#define LOGI ALOGI
+#endif
+#endif
+
+#ifndef ALOGI_IF
+#define ALOGI_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGI_IF
+#define LOGI_IF ALOGI_IF
+#endif
+#endif
+
+/*
+ * Simplified macro to send a warning log message using the current LOG_TAG.
+ */
+#ifndef ALOGW
+#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGW
+#define LOGW ALOGW
+#endif
+#endif
+
+#ifndef ALOGW_IF
+#define ALOGW_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGW_IF
+#define LOGW_IF ALOGW_IF
+#endif
+#endif
+
+/*
+ * Simplified macro to send an error log message using the current LOG_TAG.
+ */
+#ifndef ALOGE
+#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGE
+#define LOGE ALOGE
+#endif
+#endif
+
+#ifndef ALOGE_IF
+#define ALOGE_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+// Temporary measure for code still using old LOG macros.
+#ifndef LOGE_IF
+#define LOGE_IF ALOGE_IF
+#endif
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * verbose priority.
+ */
+#ifndef IF_ALOGV
+#if LOG_NDEBUG
+#define IF_ALOGV() if (false)
+#else
+#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG)
+#endif
+// Temporary measure for code still using old LOG macros.
+#ifndef IF_LOGV
+#define IF_LOGV IF_ALOGV
+#endif
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * debug priority.
+ */
+#ifndef IF_ALOGD
+#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG)
+// Temporary measure for code still using old LOG macros.
+#ifndef IF_LOGD
+#define IF_LOGD IF_ALOGD
+#endif
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * info priority.
+ */
+#ifndef IF_ALOGI
+#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG)
+// Temporary measure for code still using old LOG macros.
+#ifndef IF_LOGI
+#define IF_LOGI IF_ALOGI
+#endif
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * warn priority.
+ */
+#ifndef IF_ALOGW
+#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG)
+// Temporary measure for code still using old LOG macros.
+#ifndef IF_LOGW
+#define IF_LOGW IF_ALOGW
+#endif
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * error priority.
+ */
+#ifndef IF_ALOGE
+#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG)
+// Temporary measure for code still using old LOG macros.
+#ifndef IF_LOGE
+#define IF_LOGE IF_ALOGE
+#endif
+#endif
+
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose system log message using the current LOG_TAG.
+ */
+#ifndef SLOGV
+#if LOG_NDEBUG
+#define SLOGV(...)   ((void)0)
+#else
+#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#endif
+#endif
+
+#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
+
+#ifndef SLOGV_IF
+#if LOG_NDEBUG
+#define SLOGV_IF(cond, ...)   ((void)0)
+#else
+#define SLOGV_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug system log message using the current LOG_TAG.
+ */
+#ifndef SLOGD
+#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGD_IF
+#define SLOGD_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info system log message using the current LOG_TAG.
+ */
+#ifndef SLOGI
+#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGI_IF
+#define SLOGI_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning system log message using the current LOG_TAG.
+ */
+#ifndef SLOGW
+#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGW_IF
+#define SLOGW_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error system log message using the current LOG_TAG.
+ */
+#ifndef SLOGE
+#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGE_IF
+#define SLOGE_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Log a fatal error.  If the given condition fails, this stops program
+ * execution like a normal assertion, but also generating the given message.
+ * It is NOT stripped from release builds.  Note that the condition test
+ * is -inverted- from the normal assert() semantics.
+ */
+#ifndef LOG_ALWAYS_FATAL_IF
+#define LOG_ALWAYS_FATAL_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+#ifndef LOG_ALWAYS_FATAL
+#define LOG_ALWAYS_FATAL(...) \
+    ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
+#endif
+
+/*
+ * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
+ * are stripped out of release builds.
+ */
+#if LOG_NDEBUG
+
+#ifndef LOG_FATAL_IF
+#define LOG_FATAL_IF(cond, ...) ((void)0)
+#endif
+#ifndef LOG_FATAL
+#define LOG_FATAL(...) ((void)0)
+#endif
+
+#else
+
+#ifndef LOG_FATAL_IF
+#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
+#endif
+#ifndef LOG_FATAL
+#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
+#endif
+
+#endif
+
+/*
+ * Assertion that generates a log message when the assertion fails.
+ * Stripped out of release builds.  Uses the current LOG_TAG.
+ */
+#ifndef ALOG_ASSERT
+#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
+//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Basic log message macro.
+ *
+ * Example:
+ *  ALOG(LOG_WARN, NULL, "Failed with error %d", errno);
+ *
+ * The second argument may be NULL or "" to indicate the "global" tag.
+ */
+#ifndef ALOG
+#define ALOG(priority, tag, ...) \
+    LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to specify a number for the priority.
+ */
+#ifndef LOG_PRI
+#define LOG_PRI(priority, tag, ...) \
+    android_printLog(priority, tag, __VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to pass in a varargs ("args" is a va_list).
+ */
+#ifndef LOG_PRI_VA
+#define LOG_PRI_VA(priority, tag, fmt, args) \
+    android_vprintLog(priority, NULL, tag, fmt, args)
+#endif
+
+/*
+ * Conditional given a desired logging priority and tag.
+ */
+#ifndef IF_ALOG
+#define IF_ALOG(priority, tag) \
+    if (android_testLog(ANDROID_##priority, tag))
+// Temporary measure for code still using old LOG macros.
+#ifndef IF_LOG
+#define IF_LOG IF_ALOG
+#endif
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Event logging.
+ */
+
+/*
+ * Event log entry types.  These must match up with the declarations in
+ * java/android/android/util/EventLog.java.
+ */
+typedef enum {
+    EVENT_TYPE_INT      = 0,
+    EVENT_TYPE_LONG     = 1,
+    EVENT_TYPE_STRING   = 2,
+    EVENT_TYPE_LIST     = 3,
+} AndroidEventLogType;
+
+
+#ifndef LOG_EVENT_INT
+#define LOG_EVENT_INT(_tag, _value) {                                       \
+        int intBuf = _value;                                                \
+        (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf,            \
+            sizeof(intBuf));                                                \
+    }
+#endif
+#ifndef LOG_EVENT_LONG
+#define LOG_EVENT_LONG(_tag, _value) {                                      \
+        long long longBuf = _value;                                         \
+        (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf,          \
+            sizeof(longBuf));                                               \
+    }
+#endif
+#ifndef LOG_EVENT_STRING
+#define LOG_EVENT_STRING(_tag, _value)                                      \
+    ((void) 0)  /* not implemented -- must combine len with string */
+#endif
+/* TODO: something for LIST */
+
+/*
+ * ===========================================================================
+ *
+ * The stuff in the rest of this file should not be used directly.
+ */
+
+#define android_printLog(prio, tag, fmt...) \
+    __android_log_print(prio, tag, fmt)
+
+#define android_vprintLog(prio, cond, tag, fmt...) \
+    __android_log_vprint(prio, tag, fmt)
+
+/* XXX Macros to work around syntax errors in places where format string
+ * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF
+ * (happens only in debug builds).
+ */
+
+/* Returns 2nd arg.  Used to substitute default value if caller's vararg list
+ * is empty.
+ */
+#define __android_second(dummy, second, ...)     second
+
+/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
+ * returns nothing.
+ */
+#define __android_rest(first, ...)               , ## __VA_ARGS__
+
+#define android_printAssert(cond, tag, fmt...) \
+    __android_log_assert(cond, tag, \
+        __android_second(0, ## fmt, NULL) __android_rest(fmt))
+
+#define android_writeLog(prio, tag, text) \
+    __android_log_write(prio, tag, text)
+
+#define android_bWriteLog(tag, payload, len) \
+    __android_log_bwrite(tag, payload, len)
+#define android_btWriteLog(tag, type, payload, len) \
+    __android_log_btwrite(tag, type, payload, len)
+
+// TODO: remove these prototypes and their users
+#define android_testLog(prio, tag) (1)
+#define android_writevLog(vec,num) do{}while(0)
+#define android_write1Log(str,len) do{}while (0)
+#define android_setMinPriority(tag, prio) do{}while(0)
+//#define android_logToCallback(func) do{}while(0)
+#define android_logToFile(tag, file) (0)
+#define android_logToFd(tag, fd) (0)
+
+#define android_errorWriteLog(tag, subTag)  do{}while(0)
+
+typedef enum {
+    LOG_ID_MAIN = 0,
+    LOG_ID_RADIO = 1,
+    LOG_ID_EVENTS = 2,
+    LOG_ID_SYSTEM = 3,
+
+    LOG_ID_MAX
+} log_id_t;
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_buf_write(log_id_t bufID, int prio, const char *tag, const char *text);
+int __android_log_buf_print(log_id_t bufID, int prio, const char *tag, const char *fmt, ...);
+int __android_log_buf_vprint(log_id_t bufID, int prio, const char *tag, const char *fmt, va_list ap);
+
+/* Is this a secure build, - defined in liblog. */
+int is_secure_build();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LIBS_CUTILS_LOG_H
diff --git a/include/cutils/logd.h b/include/cutils/logd.h
new file mode 100644
index 0000000..8737639
--- /dev/null
+++ b/include/cutils/logd.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 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_CUTILS_LOGD_H
+#define _ANDROID_CUTILS_LOGD_H
+
+/* the stable/frozen log-related definitions have been
+ * moved to this header, which is exposed by the NDK
+ */
+#include <android/log.h>
+
+/* the rest is only used internally by the system */
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/types.h>
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+#include <cutils/uio.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int __android_log_bwrite(int32_t tag, const void *payload, size_t len);
+int __android_log_btwrite(int32_t tag, char type, const void *payload,
+    size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LOGD_H */
diff --git a/include/cutils/logger.h b/include/cutils/logger.h
new file mode 100644
index 0000000..58523fb
--- /dev/null
+++ b/include/cutils/logger.h
@@ -0,0 +1,47 @@
+/* utils/logger.h
+**
+** Copyright 2007, The Android Open Source Project
+**
+** This file is dual licensed.  It may be redistributed and/or modified
+** under the terms of the Apache 2.0 License OR version 2 of the GNU
+** General Public License.
+*/
+
+#ifndef _UTILS_LOGGER_H
+#define _UTILS_LOGGER_H
+
+#include <stdint.h>
+
+struct logger_entry {
+    uint16_t    len;    /* length of the payload */
+    uint16_t    __pad;  /* no matter what, we get 2 bytes of padding */
+    int32_t     pid;    /* generating process's pid */
+    int32_t     tid;    /* generating process's tid */
+    int32_t     sec;    /* seconds since Epoch */
+    int32_t     nsec;   /* nanoseconds */
+    char        msg[0]; /* the entry's payload */
+};
+
+#define LOGGER_LOG_MAIN		"log_main"
+#define LOGGER_LOG_RADIO	"log_radio"
+#define LOGGER_LOG_EVENTS	"log_events"
+#define LOGGER_LOG_SYSTEM	"log_system"
+
+#define LOGGER_ENTRY_MAX_LEN		(4*1024)
+#define LOGGER_ENTRY_MAX_PAYLOAD	\
+	(LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
+
+#ifdef HAVE_IOCTL
+
+#include <sys/ioctl.h>
+
+#define __LOGGERIO	0xAE
+
+#define LOGGER_GET_LOG_BUF_SIZE		_IO(__LOGGERIO, 1) /* size of log */
+#define LOGGER_GET_LOG_LEN		_IO(__LOGGERIO, 2) /* used log len */
+#define LOGGER_GET_NEXT_ENTRY_LEN	_IO(__LOGGERIO, 3) /* next entry len */
+#define LOGGER_FLUSH_LOG		_IO(__LOGGERIO, 4) /* flush log */
+
+#endif // HAVE_IOCTL
+
+#endif /* _UTILS_LOGGER_H */
diff --git a/include/cutils/logprint.h b/include/cutils/logprint.h
new file mode 100644
index 0000000..d1e4d81
--- /dev/null
+++ b/include/cutils/logprint.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2006 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 _LOGPRINT_H
+#define _LOGPRINT_H
+
+#include <cutils/log.h>
+#include <cutils/logger.h>
+#include <cutils/event_tag_map.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    FORMAT_OFF = 0,
+    FORMAT_BRIEF,
+    FORMAT_PROCESS,
+    FORMAT_TAG,
+    FORMAT_THREAD,
+    FORMAT_RAW,
+    FORMAT_TIME,
+    FORMAT_THREADTIME,
+    FORMAT_LONG,
+} AndroidLogPrintFormat;
+
+typedef struct AndroidLogFormat_t AndroidLogFormat;
+
+typedef struct AndroidLogEntry_t {
+    time_t tv_sec;
+    long tv_nsec;
+    android_LogPriority priority;
+    pid_t pid;
+    pthread_t tid;
+    const char * tag;
+    size_t messageLen;
+    const char * message;
+} AndroidLogEntry;
+
+AndroidLogFormat *android_log_format_new();
+
+void android_log_format_free(AndroidLogFormat *p_format);
+
+void android_log_setPrintFormat(AndroidLogFormat *p_format,
+        AndroidLogPrintFormat format);
+
+/**
+ * Returns FORMAT_OFF on invalid string
+ */
+AndroidLogPrintFormat android_log_formatFromString(const char *s);
+
+/**
+ * filterExpression: a single filter expression
+ * eg "AT:d"
+ *
+ * returns 0 on success and -1 on invalid expression
+ *
+ * Assumes single threaded execution
+ *
+ */
+
+int android_log_addFilterRule(AndroidLogFormat *p_format,
+        const char *filterExpression);
+
+
+/**
+ * filterString: a whitespace-separated set of filter expressions
+ * eg "AT:d *:i"
+ *
+ * returns 0 on success and -1 on invalid expression
+ *
+ * Assumes single threaded execution
+ *
+ */
+
+int android_log_addFilterString(AndroidLogFormat *p_format,
+        const char *filterString);
+
+
+/**
+ * returns 1 if this log line should be printed based on its priority
+ * and tag, and 0 if it should not
+ */
+int android_log_shouldPrintLine (
+        AndroidLogFormat *p_format, const char *tag, android_LogPriority pri);
+
+
+/**
+ * Splits a wire-format buffer into an AndroidLogEntry
+ * entry allocated by caller. Pointers will point directly into buf
+ *
+ * Returns 0 on success and -1 on invalid wire format (entry will be
+ * in unspecified state)
+ */
+int android_log_processLogBuffer(struct logger_entry *buf,
+                                 AndroidLogEntry *entry);
+
+/**
+ * Like android_log_processLogBuffer, but for binary logs.
+ *
+ * If "map" is non-NULL, it will be used to convert the log tag number
+ * into a string.
+ */
+int android_log_processBinaryLogBuffer(struct logger_entry *buf,
+    AndroidLogEntry *entry, const EventTagMap* map, char* messageBuf,
+    int messageBufLen);
+
+
+/**
+ * Formats a log message into a buffer
+ *
+ * Uses defaultBuffer if it can, otherwise malloc()'s a new buffer
+ * If return value != defaultBuffer, caller must call free()
+ * Returns NULL on malloc error
+ */
+
+char *android_log_formatLogLine (
+    AndroidLogFormat *p_format,
+    char *defaultBuffer,
+    size_t defaultBufferSize,
+    const AndroidLogEntry *p_line,
+    size_t *p_outLength);
+
+
+/**
+ * Either print or do not print log line, based on filter
+ *
+ * Assumes single threaded execution
+ *
+ */
+int android_log_printLogLine(
+    AndroidLogFormat *p_format,
+    int fd,
+    const AndroidLogEntry *entry);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*_LOGPRINT_H*/
diff --git a/include/cutils/memory.h b/include/cutils/memory.h
new file mode 100644
index 0000000..4d26882
--- /dev/null
+++ b/include/cutils/memory.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2006 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_CUTILS_MEMORY_H
+#define ANDROID_CUTILS_MEMORY_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* size is given in bytes and must be multiple of 2 */
+void android_memset16(uint16_t* dst, uint16_t value, size_t size);
+
+/* size is given in bytes and must be multiple of 4 */
+void android_memset32(uint32_t* dst, uint32_t value, size_t size);
+
+#if defined(__GLIBC__) || defined(_WIN32)
+/* Declaration of strlcpy() for platforms that don't already have it. */
+size_t strlcpy(char *dst, const char *src, size_t size);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ANDROID_CUTILS_MEMORY_H
diff --git a/include/cutils/misc.h b/include/cutils/misc.h
new file mode 100644
index 0000000..3574dfd
--- /dev/null
+++ b/include/cutils/misc.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 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 __CUTILS_MISC_H
+#define __CUTILS_MISC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+        /* Load an entire file into a malloc'd chunk of memory
+         * that is length_of_file + 1 (null terminator).  If
+         * sz is non-zero, return the size of the file via sz.
+         * Returns 0 on failure.
+         */
+extern void *load_file(const char *fn, unsigned *sz);
+
+        /* Connects your process to the system debugger daemon
+         * so that on a crash it may be logged or interactively
+         * debugged (depending on system settings).
+         */
+extern void debuggerd_connect(void);
+
+
+        /* This is the range of UIDs (and GIDs) that are reserved
+         * for assigning to applications.
+         */
+#define FIRST_APPLICATION_UID 10000
+#define LAST_APPLICATION_UID 99999
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_MISC_H */
diff --git a/include/cutils/mq.h b/include/cutils/mq.h
new file mode 100644
index 0000000..9e56de7
--- /dev/null
+++ b/include/cutils/mq.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/**
+ * IPC messaging library.
+ */
+
+#ifndef __MQ_H
+#define __MQ_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** A message. */
+typedef struct MqMessage MqMessage;
+
+/** A destination to which messages can be sent. */
+typedef struct MqDestination MqDestination;
+
+/* Array of bytes. */
+typedef struct MqBytes MqBytes;
+
+/**
+ * Hears messages.
+ *
+ * @param destination to which the message was sent
+ * @param message the message to hear
+ */
+typedef void MqMessageListener(MqDestination* destination, MqMessage* message);
+
+/**
+ * Hears a destination close.
+ *
+ * @param destination that closed
+ */
+typedef void MqCloseListener(MqDestination* destination);
+
+/** Message functions. */
+
+/**
+ * Creates a new Message.
+ *
+ * @param header as defined by user
+ * @param body as defined by user
+ * @param replyTo destination to which replies should be sent, NULL if none
+ */
+MqMessage* mqCreateMessage(MqBytes header, MqBytes body,
+        MqDestination* replyTo);
+
+/** Sends a message to a destination. */
+void mqSendMessage(MqMessage* message, MqDestination* destination);
+
+/** Destination functions. */
+
+/**
+ * Creates a new destination. Acquires a reference implicitly.
+ *
+ * @param messageListener function to call when a message is recieved
+ * @param closeListener function to call when the destination closes
+ * @param userData user-specific data to associate with the destination.
+ *  Retrieve using mqGetDestinationUserData().
+ */
+MqDestination* mqCreateDestination(MqMessageListener* messageListener,
+        MqCloseListener* closeListener, void* userData);
+
+/**
+ * Gets user data which was associated with the given destination at
+ * construction time.
+ *
+ * It is only valid to call this function in the same process that the
+ * given destination was created in.
+ * This function returns a null pointer if you call it on a destination
+ * created in a remote process.
+ */
+void* mqGetUserData(MqDestination* destination);
+
+/**
+ * Returns 1 if the destination was created in this process, or 0 if
+ * the destination was created in a different process, in which case you have
+ * a remote stub.
+ */
+int mqIsDestinationLocal(MqDestination* destination);
+
+/**
+ * Increments the destination's reference count.
+ */
+void mqKeepDestination(MqDesintation* destination);
+
+/**
+ * Decrements the destination's reference count.
+ */
+void mqFreeDestination(MqDestination* desintation);
+
+/** Registry API. */
+
+/**
+ * Gets the destination bound to a name.
+ */
+MqDestination* mqGetDestination(char* name);
+
+/**
+ * Binds a destination to a name.
+ */
+void mqPutDestination(char* name, MqDestination* desintation);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MQ_H */
diff --git a/include/cutils/mspace.h b/include/cutils/mspace.h
new file mode 100644
index 0000000..b22d9a4
--- /dev/null
+++ b/include/cutils/mspace.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+/* A wrapper file for dlmalloc.h that defines prototypes for the
+ * mspace_*() functions, which provide an interface for creating
+ * multiple heaps.
+ */
+
+#ifndef MSPACE_H_
+#define MSPACE_H_
+
+/* It's a pain getting the mallinfo stuff to work
+ * with Linux, OSX, and klibc, so just turn it off
+ * for now.
+ * TODO: make mallinfo work
+ */
+#define NO_MALLINFO 1
+
+/* Allow setting the maximum heap footprint.
+ */
+#define USE_MAX_ALLOWED_FOOTPRINT 1
+
+#define USE_CONTIGUOUS_MSPACES 1
+#if USE_CONTIGUOUS_MSPACES
+#define HAVE_MMAP 0
+#define HAVE_MORECORE 1
+#define MORECORE_CONTIGUOUS 0
+#endif
+
+#define MSPACES 1
+#define ONLY_MSPACES 1
+#include "dlmalloc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+  mspace_usable_size(void* p);
+
+  Returns the number of bytes you can actually use in
+  an allocated chunk, which may be more than you requested (although
+  often not) due to alignment and minimum size constraints.
+  You can use this many bytes without worrying about
+  overwriting other allocated objects. This is not a particularly great
+  programming practice. mspace_usable_size can be more useful in
+  debugging and assertions, for example:
+
+  p = mspace_malloc(msp, n);
+  assert(mspace_usable_size(msp, p) >= 256);
+*/
+size_t mspace_usable_size(mspace, const void*);
+
+#if USE_CONTIGUOUS_MSPACES
+/*
+  Similar to create_mspace(), but the underlying memory is
+  guaranteed to be contiguous.  No more than max_capacity
+  bytes is ever allocated to the mspace.
+ */
+mspace create_contiguous_mspace(size_t starting_capacity, size_t max_capacity,
+    int locked);
+
+/*
+   Identical to create_contiguous_mspace, but labels the mapping 'mspace/name'
+   instead of 'mspace'
+*/
+mspace create_contiguous_mspace_with_name(size_t starting_capacity,
+    size_t max_capacity, int locked, const char *name);
+
+/*
+   Identical to create_contiguous_mspace, but uses previously mapped memory.
+*/
+mspace create_contiguous_mspace_with_base(size_t starting_capacity,
+    size_t max_capacity, int locked, void *base);
+
+size_t destroy_contiguous_mspace(mspace msp);
+
+/*
+   Returns the position of the "break" within the given mspace.
+*/
+void *contiguous_mspace_sbrk0(mspace msp);
+#endif
+
+/*
+  Call the handler for each block in the specified mspace.
+  chunkptr and chunklen refer to the heap-level chunk including
+  the chunk overhead, and userptr and userlen refer to the
+  user-usable part of the chunk.  If the chunk is free, userptr
+  will be NULL and userlen will be 0.  userlen is not guaranteed
+  to be the same value passed into malloc() for a given chunk;
+  it is >= the requested size.
+ */
+void mspace_walk_heap(mspace msp,
+    void(*handler)(const void *chunkptr, size_t chunklen,
+        const void *userptr, size_t userlen, void *arg), void *harg);
+
+/*
+  mspace_walk_free_pages(handler, harg)
+
+  Calls the provided handler on each free region in the specified
+  mspace.  The memory between start and end are guaranteed not to
+  contain any important data, so the handler is free to alter the
+  contents in any way.  This can be used to advise the OS that large
+  free regions may be swapped out.
+
+  The value in harg will be passed to each call of the handler.
+ */
+void mspace_walk_free_pages(mspace msp,
+    void(*handler)(void *start, void *end, void *arg), void *harg);
+
+#ifdef __cplusplus
+};  /* end of extern "C" */
+#endif
+
+#endif /* MSPACE_H_ */
diff --git a/include/cutils/native_handle.h b/include/cutils/native_handle.h
new file mode 100644
index 0000000..10f5bc0
--- /dev/null
+++ b/include/cutils/native_handle.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2009 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 NATIVE_HANDLE_H_
+#define NATIVE_HANDLE_H_
+
+#include <stdalign.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Declare a char array for use with native_handle_init */
+#define NATIVE_HANDLE_DECLARE_STORAGE(name, maxFds, maxInts) \
+    alignas(native_handle_t) char (name)[                            \
+      sizeof(native_handle_t) + sizeof(int) * ((maxFds) + (maxInts))]
+
+typedef struct native_handle
+{
+    int version;        /* sizeof(native_handle_t) */
+    int numFds;         /* number of file-descriptors at &data[0] */
+    int numInts;        /* number of ints at &data[numFds] */
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
+#endif
+    int data[0];        /* numFds + numInts ints */
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+} native_handle_t;
+
+typedef const native_handle_t* buffer_handle_t;
+
+/*
+ * native_handle_close
+ * 
+ * closes the file descriptors contained in this native_handle_t
+ * 
+ * return 0 on success, or a negative error code on failure
+ * 
+ */
+int native_handle_close(const native_handle_t* h);
+
+/*
+ * native_handle_init
+ *
+ * Initializes a native_handle_t from storage.  storage must be declared with
+ * NATIVE_HANDLE_DECLARE_STORAGE.  numFds and numInts must not respectively
+ * exceed maxFds and maxInts used to declare the storage.
+ */
+native_handle_t* native_handle_init(char* storage, int numFds, int numInts);
+
+/*
+ * native_handle_create
+ * 
+ * creates a native_handle_t and initializes it. must be destroyed with
+ * native_handle_delete().
+ * 
+ */
+native_handle_t* native_handle_create(int numFds, int numInts);
+
+/*
+ * native_handle_clone
+ *
+ * creates a native_handle_t and initializes it from another native_handle_t.
+ * Must be destroyed with native_handle_delete().
+ *
+ */
+native_handle_t* native_handle_clone(const native_handle_t* handle);
+
+/*
+ * native_handle_delete
+ * 
+ * frees a native_handle_t allocated with native_handle_create().
+ * This ONLY frees the memory allocated for the native_handle_t, but doesn't
+ * close the file descriptors; which can be achieved with native_handle_close().
+ * 
+ * return 0 on success, or a negative error code on failure
+ * 
+ */
+int native_handle_delete(native_handle_t* h);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NATIVE_HANDLE_H_ */
diff --git a/include/cutils/open_memstream.h b/include/cutils/open_memstream.h
new file mode 100644
index 0000000..b7998be
--- /dev/null
+++ b/include/cutils/open_memstream.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 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 __CUTILS_OPEN_MEMSTREAM_H__
+#define __CUTILS_OPEN_MEMSTREAM_H__
+
+#include <stdio.h>
+
+#ifndef HAVE_OPEN_MEMSTREAM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+FILE* open_memstream(char** bufp, size_t* sizep);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*!HAVE_OPEN_MEMSTREAM*/
+
+#endif /*__CUTILS_OPEN_MEMSTREAM_H__*/
diff --git a/include/cutils/partition_utils.h b/include/cutils/partition_utils.h
new file mode 100644
index 0000000..597df92
--- /dev/null
+++ b/include/cutils/partition_utils.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef __CUTILS_PARTITION_WIPED_H__
+#define __CUTILS_PARTITION_WIPED_H__
+
+__BEGIN_DECLS
+
+int partition_wiped(char *source);
+void erase_footer(const char *dev_path, long long size);
+
+__END_DECLS
+
+#endif /* __CUTILS_PARTITION_WIPED_H__ */
diff --git a/include/cutils/process_name.h b/include/cutils/process_name.h
new file mode 100644
index 0000000..04bd49d
--- /dev/null
+++ b/include/cutils/process_name.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+/**
+ * Gives the current process a name.
+ */
+
+#ifndef __PROCESS_NAME_H
+#define __PROCESS_NAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Sets the current process name.
+ *
+ * Warning: This leaks a string every time you call it. Use judiciously!
+ */
+void set_process_name(const char* process_name);
+
+/** Gets the current process name. */
+const char* get_process_name(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PROCESS_NAME_H */
diff --git a/include/cutils/properties.h b/include/cutils/properties.h
new file mode 100644
index 0000000..96461c2
--- /dev/null
+++ b/include/cutils/properties.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2006 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 __CUTILS_PROPERTIES_H
+#define __CUTILS_PROPERTIES_H
+
+#include <sys/cdefs.h>
+#include <stddef.h>
+//#include <sys/system_properties.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PROP_NAME_MAX   32
+#define PROP_VALUE_MAX  92
+
+/* System properties are *small* name value pairs managed by the
+** property service.  If your data doesn't fit in the provided
+** space it is not appropriate for a system property.
+**
+** WARNING: system/bionic/include/sys/system_properties.h also defines
+**          these, but with different names.  (TODO: fix that)
+*/
+#define PROPERTY_KEY_MAX   PROP_NAME_MAX
+#define PROPERTY_VALUE_MAX  PROP_VALUE_MAX
+
+/* property_get: returns the length of the value which will never be
+** greater than PROPERTY_VALUE_MAX - 1 and will always be zero terminated.
+** (the length does not include the terminating zero).
+**
+** If the property read fails or returns an empty value, the default
+** value is used (if nonnull).
+*/
+int property_get(const char* key, char* value, const char* default_value);
+
+/* property_get_bool: returns the value of key coerced into a
+** boolean. If the property is not set, then the default value is returned.
+**
+* The following is considered to be true (1):
+**   "1", "true", "y", "yes", "on"
+**
+** The following is considered to be false (0):
+**   "0", "false", "n", "no", "off"
+**
+** The conversion is whitespace-sensitive (e.g. " off" will not be false).
+**
+** If no property with this key is set (or the key is NULL) or the boolean
+** conversion fails, the default value is returned.
+**/
+int8_t property_get_bool(const char *key, int8_t default_value);
+
+/* property_get_int64: returns the value of key truncated and coerced into a
+** int64_t. If the property is not set, then the default value is used.
+**
+** The numeric conversion is identical to strtoimax with the base inferred:
+** - All digits up to the first non-digit characters are read
+** - The longest consecutive prefix of digits is converted to a long
+**
+** Valid strings of digits are:
+** - An optional sign character + or -
+** - An optional prefix indicating the base (otherwise base 10 is assumed)
+**   -- 0 prefix is octal
+**   -- 0x / 0X prefix is hex
+**
+** Leading/trailing whitespace is ignored. Overflow/underflow will cause
+** numeric conversion to fail.
+**
+** If no property with this key is set (or the key is NULL) or the numeric
+** conversion fails, the default value is returned.
+**/
+int64_t property_get_int64(const char *key, int64_t default_value);
+
+/* property_get_int32: returns the value of key truncated and coerced into an
+** int32_t. If the property is not set, then the default value is used.
+**
+** The numeric conversion is identical to strtoimax with the base inferred:
+** - All digits up to the first non-digit characters are read
+** - The longest consecutive prefix of digits is converted to a long
+**
+** Valid strings of digits are:
+** - An optional sign character + or -
+** - An optional prefix indicating the base (otherwise base 10 is assumed)
+**   -- 0 prefix is octal
+**   -- 0x / 0X prefix is hex
+**
+** Leading/trailing whitespace is ignored. Overflow/underflow will cause
+** numeric conversion to fail.
+**
+** If no property with this key is set (or the key is NULL) or the numeric
+** conversion fails, the default value is returned.
+**/
+int32_t property_get_int32(const char *key, int32_t default_value);
+
+/* property_set: returns 0 on success, < 0 on failure
+*/
+int property_set(const char *key, const char *value);
+
+#if 0
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);
+
+#if defined(__BIONIC_FORTIFY)
+#define __property_get_err_str "property_get() called with too small of a buffer"
+
+#if defined(__clang__)
+
+/* Some projects use -Weverything; diagnose_if is clang-specific. */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgcc-compat"
+int property_get(const char* key, char* value, const char* default_value)
+    __clang_error_if(__bos(value) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                         __bos(value) < PROPERTY_VALUE_MAX,
+                     __property_get_err_str);
+#pragma clang diagnostic pop
+
+#else /* defined(__clang__) */
+
+extern int __property_get_real(const char *, char *, const char *)
+    __asm__(__USER_LABEL_PREFIX__ "property_get");
+__errordecl(__property_get_too_small_error, __property_get_err_str);
+
+__BIONIC_FORTIFY_INLINE
+int property_get(const char *key, char *value, const char *default_value) {
+    size_t bos = __bos(value);
+    if (bos < PROPERTY_VALUE_MAX) {
+        __property_get_too_small_error();
+    }
+    return __property_get_real(key, value, default_value);
+}
+
+#endif /* defined(__clang__) */
+
+#undef __property_get_err_str
+#endif /* defined(__BIONIC_FORTIFY) */
+#endif
+
+int property_get(const char* key, char* value, const char* default_value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cutils/qtaguid.h b/include/cutils/qtaguid.h
new file mode 100644
index 0000000..f8550fd
--- /dev/null
+++ b/include/cutils/qtaguid.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef __CUTILS_QTAGUID_H
+#define __CUTILS_QTAGUID_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Set tags (and owning UIDs) for network sockets.
+*/
+extern int qtaguid_tagSocket(int sockfd, int tag, uid_t uid);
+
+/*
+ * Untag a network socket before closing.
+*/
+extern int qtaguid_untagSocket(int sockfd);
+
+/*
+ * For the given uid, switch counter sets.
+ * The kernel only keeps a limited number of sets.
+ * 2 for now.
+ */
+extern int qtaguid_setCounterSet(int counterSetNum, uid_t uid);
+
+/*
+ * Delete all tag info that relates to the given tag an uid.
+ * If the tag is 0, then ALL info about the uid is freeded.
+ * The delete data also affects active tagged socketd, which are
+ * then untagged.
+ * The calling process can only operate on its own tags.
+ * Unless it is part of the happy AID_NET_BW_ACCT group.
+ * In which case it can clobber everything.
+ */
+extern int qtaguid_deleteTagData(int tag, uid_t uid);
+
+/*
+ * Enable/disable qtaguid functionnality at a lower level.
+ * When pacified, the kernel will accept commands but do nothing.
+ */
+extern int qtaguid_setPacifier(int on);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_QTAG_UID_H */
diff --git a/include/cutils/record_stream.h b/include/cutils/record_stream.h
new file mode 100644
index 0000000..d86ecbe
--- /dev/null
+++ b/include/cutils/record_stream.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+/*
+ * A simple utility for reading fixed records out of a stream fd
+ */
+
+#ifndef _CUTILS_RECORD_STREAM_H
+#define _CUTILS_RECORD_STREAM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct RecordStream RecordStream;
+
+extern RecordStream *record_stream_new(int fd, size_t maxRecordLen);
+extern void record_stream_free(RecordStream *p_rs);
+
+extern int record_stream_get_next (RecordStream *p_rs, void ** p_outRecord,
+                                    size_t *p_outRecordLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*_CUTILS_RECORD_STREAM_H*/
+
diff --git a/include/cutils/sched_policy.h b/include/cutils/sched_policy.h
new file mode 100644
index 0000000..218078e
--- /dev/null
+++ b/include/cutils/sched_policy.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 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 __CUTILS_SCHED_POLICY_H
+#define __CUTILS_SCHED_POLICY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    SP_BACKGROUND = 0,
+    SP_FOREGROUND = 1,
+} SchedPolicy;
+
+extern int set_sched_policy(int tid, SchedPolicy policy);
+extern int get_sched_policy(int tid, SchedPolicy *policy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_SCHED_POLICY_H */
diff --git a/include/cutils/selector.h b/include/cutils/selector.h
new file mode 100644
index 0000000..25b514c
--- /dev/null
+++ b/include/cutils/selector.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/**
+ * Framework for multiplexing I/O. A selector manages a set of file
+ * descriptors and calls out to user-provided callback functions to read and
+ * write data and handle errors.
+ */
+
+#ifndef __SELECTOR_H
+#define __SELECTOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+/**
+ * Manages SelectableFds and invokes their callbacks at appropriate times.
+ */
+typedef struct Selector Selector;
+
+/**
+ * A selectable descriptor. Contains callbacks which the selector can invoke
+ * before calling select(), when the descriptor is readable or writable, and
+ * when the descriptor contains out-of-band data. Simply set a callback to
+ * NULL if you're not interested in that particular event.
+ *
+ * A selectable descriptor can indicate that it needs to be removed from the
+ * selector by setting the 'remove' flag. The selector will remove the
+ * descriptor at a later time and invoke the onRemove() callback.
+ *
+ * SelectableFd fields should only be modified from the selector loop.
+ */
+typedef struct SelectableFd SelectableFd;
+struct SelectableFd {
+
+    /** The file descriptor itself. */
+    int fd;
+
+    /** Pointer to user-specific data. Can be NULL. */
+    void* data;
+
+    /**
+     * Set this flag when you no longer wish to be selected. The selector
+     * will invoke onRemove() when the descriptor is actually removed.
+     */
+    bool remove;
+
+    /**
+     * Invoked by the selector before calling select. You can set up other
+     * callbacks from here as necessary.
+     */
+    void (*beforeSelect)(SelectableFd* self);
+
+    /**
+     * Invoked by the selector when the descriptor has data available. Set to
+     * NULL to indicate that you're not interested in reading.
+     */
+    void (*onReadable)(SelectableFd* self);
+
+    /**
+     * Invoked by the selector when the descriptor can accept data. Set to
+     * NULL to indicate that you're not interested in writing.
+     */
+    void (*onWritable)(SelectableFd* self);
+
+    /**
+     * Invoked by the selector when out-of-band (OOB) data is available. Set to
+     * NULL to indicate that you're not interested in OOB data.
+     */
+    void (*onExcept)(SelectableFd* self);
+
+    /**
+     * Invoked by the selector after the descriptor is removed from the
+     * selector but before the selector frees the SelectableFd memory.
+     */
+    void (*onRemove)(SelectableFd* self);
+
+    /**
+     * The selector which selected this fd. Set by the selector itself.
+     */
+    Selector* selector;
+};
+
+/**
+ * Creates a new selector
+ */
+Selector* selectorCreate(void);
+
+/**
+ * Creates a new selectable fd, adds it to the given selector and returns a
+ * pointer. Outside of 'selector' and 'fd', all fields are set to 0 or NULL
+ * by default.
+ *
+ * The selectable fd should only be modified from the selector loop thread.
+ */
+SelectableFd* selectorAdd(Selector* selector, int fd);
+
+/**
+ * Wakes up the selector even though no I/O events occurred. Use this
+ * to indicate that you're ready to write to a descriptor.
+ */
+void selectorWakeUp(Selector* selector);
+
+/**
+ * Loops continuously selecting file descriptors and firing events.
+ * Does not return.
+ */
+void selectorLoop(Selector* selector);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SELECTOR_H */
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
new file mode 100644
index 0000000..6feccfe
--- /dev/null
+++ b/include/cutils/sockets.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2006 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 __CUTILS_SOCKETS_H
+#define __CUTILS_SOCKETS_H
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+
+#include <sys/socket.h>
+
+#define ANDROID_SOCKET_ENV_PREFIX	"ANDROID_SOCKET_"
+#define ANDROID_SOCKET_DIR		"/dev/socket"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * android_get_control_socket - simple helper function to get the file
+ * descriptor of our init-managed Unix domain socket. `name' is the name of the
+ * socket, as given in init.rc. Returns -1 on error.
+ *
+ * This is inline and not in libcutils proper because we want to use this in
+ * third-party daemons with minimal modification.
+ */
+static inline int android_get_control_socket(const char *name)
+{
+	char key[64] = ANDROID_SOCKET_ENV_PREFIX;
+	const char *val;
+	int fd;
+
+	/* build our environment variable, counting cycles like a wolf ... */
+#if HAVE_STRLCPY
+	strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
+		name,
+		sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
+#else	/* for the host, which may lack the almightly strncpy ... */
+	strncpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
+		name,
+		sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
+	key[sizeof(key)-1] = '\0';
+#endif
+
+	val = getenv(key);
+	if (!val)
+		return -1;
+
+	errno = 0;
+	fd = strtol(val, NULL, 10);
+	if (errno)
+		return -1;
+
+	return fd;
+}
+
+/*
+ * See also android.os.LocalSocketAddress.Namespace
+ */
+// Linux "abstract" (non-filesystem) namespace
+#define ANDROID_SOCKET_NAMESPACE_ABSTRACT 0
+// Android "reserved" (/dev/socket) namespace
+#define ANDROID_SOCKET_NAMESPACE_RESERVED 1
+// Normal filesystem namespace
+#define ANDROID_SOCKET_NAMESPACE_FILESYSTEM 2
+
+extern int socket_loopback_client(int port, int type);
+extern int socket_network_client(const char *host, int port, int type);
+extern int socket_loopback_server(int port, int type);
+extern int socket_local_server(const char *name, int namespaceId, int type);
+extern int socket_local_server_bind(int s, const char *name, int namespaceId);
+extern int socket_local_client_connect(int fd,
+        const char *name, int namespaceId, int type);
+extern int socket_local_client(const char *name, int namespaceId, int type);
+extern int socket_inaddr_any_server(int port, int type);
+
+/*
+ * socket_peer_is_trusted - Takes a socket which is presumed to be a
+ * connected local socket (e.g. AF_LOCAL) and returns whether the peer
+ * (the userid that owns the process on the other end of that socket)
+ * is one of the two trusted userids, root or shell.
+ *
+ * Note: This only works as advertised on the Android OS and always
+ * just returns true when called on other operating systems.
+ */
+extern bool socket_peer_is_trusted(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_SOCKETS_H */
diff --git a/include/cutils/str_parms.h b/include/cutils/str_parms.h
new file mode 100644
index 0000000..aa1435a
--- /dev/null
+++ b/include/cutils/str_parms.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#ifndef __CUTILS_STR_PARMS_H
+#define __CUTILS_STR_PARMS_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+struct str_parms;
+
+struct str_parms *str_parms_create(void);
+struct str_parms *str_parms_create_str(const char *_string);
+void str_parms_destroy(struct str_parms *str_parms);
+
+void str_parms_del(struct str_parms *str_parms, const char *key);
+
+int str_parms_add_str(struct str_parms *str_parms, const char *key,
+                      const char *value);
+int str_parms_add_int(struct str_parms *str_parms, const char *key, int value);
+
+int str_parms_add_float(struct str_parms *str_parms, const char *key,
+                        float value);
+
+// Returns non-zero if the str_parms contains the specified key.
+int str_parms_has_key(struct str_parms *str_parms, const char *key);
+
+// Gets value associated with the specified key (if present), placing it in the buffer
+// pointed to by the out_val parameter.  Returns the length of the returned string value.
+// If 'key' isn't in the parms, then return -ENOENT (-2) and leave 'out_val' untouched.
+int str_parms_get_str(struct str_parms *str_parms, const char *key,
+                      char *out_val, int len);
+int str_parms_get_int(struct str_parms *str_parms, const char *key,
+                      int *out_val);
+int str_parms_get_float(struct str_parms *str_parms, const char *key,
+                        float *out_val);
+
+char *str_parms_to_str(struct str_parms *str_parms);
+
+/* debug */
+void str_parms_dump(struct str_parms *str_parms);
+
+__END_DECLS
+
+#endif /* __CUTILS_STR_PARMS_H */
diff --git a/include/cutils/threads.h b/include/cutils/threads.h
new file mode 100644
index 0000000..5727494
--- /dev/null
+++ b/include/cutils/threads.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2007 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 _LIBS_CUTILS_THREADS_H
+#define _LIBS_CUTILS_THREADS_H
+
+#include  <sys/types.h>
+
+#if !defined(_WIN32)
+#include <pthread.h>
+#else
+#include <windows.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***********************************************************************/
+/***********************************************************************/
+/*****                                                             *****/
+/*****         local thread storage                                *****/
+/*****                                                             *****/
+/***********************************************************************/
+/***********************************************************************/
+
+extern pid_t gettid();
+
+#if !defined(_WIN32)
+
+typedef struct {
+    pthread_mutex_t   lock;
+    int               has_tls;
+    pthread_key_t     tls;
+} thread_store_t;
+
+#define  THREAD_STORE_INITIALIZER  { PTHREAD_MUTEX_INITIALIZER, 0, 0 }
+
+#else // !defined(_WIN32)
+
+typedef struct {
+    int               lock_init;
+    int               has_tls;
+    DWORD             tls;
+    CRITICAL_SECTION  lock;
+} thread_store_t;
+
+#define  THREAD_STORE_INITIALIZER  { 0, 0, 0, {0, 0, 0, 0, 0, 0} }
+
+#endif // !defined(_WIN32)
+
+typedef void  (*thread_store_destruct_t)(void*  value);
+
+extern void*  thread_store_get(thread_store_t*  store);
+
+extern void   thread_store_set(thread_store_t*          store,
+                               void*                    value,
+                               thread_store_destruct_t  destroy);
+
+/***********************************************************************/
+/***********************************************************************/
+/*****                                                             *****/
+/*****         mutexes                                             *****/
+/*****                                                             *****/
+/***********************************************************************/
+/***********************************************************************/
+
+#if !defined(_WIN32)
+
+typedef pthread_mutex_t   mutex_t;
+
+#define  MUTEX_INITIALIZER  PTHREAD_MUTEX_INITIALIZER
+
+static __inline__ void  mutex_lock(mutex_t*  lock)
+{
+    pthread_mutex_lock(lock);
+}
+static __inline__ void  mutex_unlock(mutex_t*  lock)
+{
+    pthread_mutex_unlock(lock);
+}
+static __inline__ int  mutex_init(mutex_t*  lock)
+{
+    return pthread_mutex_init(lock, NULL);
+}
+static __inline__ void mutex_destroy(mutex_t*  lock)
+{
+    pthread_mutex_destroy(lock);
+}
+
+#else // !defined(_WIN32)
+
+typedef struct {
+    int                init;
+    CRITICAL_SECTION   lock[1];
+} mutex_t;
+
+#define  MUTEX_INITIALIZER  { 0, {{ NULL, 0, 0, NULL, NULL, 0 }} }
+
+static __inline__ void  mutex_lock(mutex_t*  lock)
+{
+    if (!lock->init) {
+        lock->init = 1;
+        InitializeCriticalSection( lock->lock );
+        lock->init = 2;
+    } else while (lock->init != 2)
+        Sleep(10);
+
+    EnterCriticalSection(lock->lock);
+}
+
+static __inline__ void  mutex_unlock(mutex_t*  lock)
+{
+    LeaveCriticalSection(lock->lock);
+}
+static __inline__ int  mutex_init(mutex_t*  lock)
+{
+    InitializeCriticalSection(lock->lock);
+    lock->init = 2;
+    return 0;
+}
+static __inline__ void  mutex_destroy(mutex_t*  lock)
+{
+    if (lock->init) {
+        lock->init = 0;
+        DeleteCriticalSection(lock->lock);
+    }
+}
+#endif // !defined(_WIN32)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBS_CUTILS_THREADS_H */
diff --git a/include/cutils/tztime.h b/include/cutils/tztime.h
new file mode 100644
index 0000000..14bbc1d
--- /dev/null
+++ b/include/cutils/tztime.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2006 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 _CUTILS_TZTIME_H
+#define _CUTILS_TZTIME_H
+
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+time_t mktime_tz(struct tm * const tmp, char const * tz);
+void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz);
+
+#if !defined(HAVE_ANDROID_OS) || HAVE_GLIBC
+/* the following is defined in <time.h> in Bionic */
+
+struct strftime_locale {
+    const char *mon[12];    /* short names */
+    const char *month[12];  /* long names */
+    const char *standalone_month[12];  /* long standalone names */
+    const char *wday[7];    /* short names */
+    const char *weekday[7]; /* long names */
+    const char *X_fmt;
+    const char *x_fmt;
+    const char *c_fmt;
+    const char *am;
+    const char *pm;
+    const char *date_fmt;
+};
+
+size_t strftime_tz(char *s, size_t max, const char *format, const struct tm *tm, const struct strftime_locale *locale);
+
+#endif /* !HAVE_ANDROID_OS || HAVE_GLIBC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_TZTIME_H */
diff --git a/include/cutils/uevent.h b/include/cutils/uevent.h
new file mode 100644
index 0000000..4ebc300
--- /dev/null
+++ b/include/cutils/uevent.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef __CUTILS_UEVENT_H
+#define __CUTILS_UEVENT_H
+
+#include <stdbool.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int uevent_open_socket(int buf_sz, bool passcred);
+ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_UEVENT_H */
diff --git a/include/cutils/uio.h b/include/cutils/uio.h
new file mode 100644
index 0000000..4691a13
--- /dev/null
+++ b/include/cutils/uio.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+//
+// implementation of sys/uio.h for platforms that don't have it (Win32)
+//
+#ifndef _LIBS_CUTILS_UIO_H
+#define _LIBS_CUTILS_UIO_H
+
+#define HAVE_SYS_UIO_H
+
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+/*
+struct iovec {
+    const void*  iov_base;
+    size_t       iov_len;
+};
+
+extern int  readv( int  fd, struct iovec*  vecs, int  count );
+*/
+extern int  writev( int  fd, const struct iovec*  vecs, int  count );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !HAVE_SYS_UIO_H */
+
+#endif /* _LIBS_UTILS_UIO_H */
+
diff --git a/include/cutils/zygote.h b/include/cutils/zygote.h
new file mode 100644
index 0000000..22721a6
--- /dev/null
+++ b/include/cutils/zygote.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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 __CUTILS_ZYGOTE_H
+#define __CUTILS_ZYGOTE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
+int zygote_run(int argc, const char **argv);
+int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_ZYGOTE_H */
diff --git a/include/media/AudioBufferProvider.h b/include/media/AudioBufferProvider.h
new file mode 100644
index 0000000..458d170
--- /dev/null
+++ b/include/media/AudioBufferProvider.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2007 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_BUFFER_PROVIDER_H
+#define ANDROID_AUDIO_BUFFER_PROVIDER_H
+
+#include <utils/Errors.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class AudioBufferProvider
+{
+public:
+
+    // FIXME merge with AudioTrackShared::Buffer, AudioTrack::Buffer, and AudioRecord::Buffer
+    //       and rename getNextBuffer() to obtainBuffer()
+    struct Buffer {
+        Buffer() : raw(NULL), frameCount(0) { }
+        union {
+            void*       raw;
+            short*      i16;
+            int8_t*     i8;
+        };
+        size_t frameCount;
+    };
+
+    virtual ~AudioBufferProvider() {}
+
+    // On entry:
+    //  buffer              != NULL
+    //  buffer->raw         unused
+    //  buffer->frameCount  maximum number of desired frames
+    // On successful return:
+    //  status              NO_ERROR
+    //  buffer->raw         non-NULL pointer to buffer->frameCount contiguous available frames
+    //  buffer->frameCount  number of contiguous available frames at buffer->raw,
+    //                      0 < buffer->frameCount <= entry value
+    // On error return:
+    //  status              != NO_ERROR
+    //  buffer->raw         NULL
+    //  buffer->frameCount  0
+    virtual status_t getNextBuffer(Buffer* buffer) = 0;
+
+    // Release (a portion of) the buffer previously obtained by getNextBuffer().
+    // It is permissible to call releaseBuffer() multiple times per getNextBuffer().
+    // On entry:
+    //  buffer->frameCount  number of frames to release, must be <= number of frames
+    //                      obtained but not yet released
+    //  buffer->raw         unused
+    // On return:
+    //  buffer->frameCount  0; implementation MUST set to zero
+    //  buffer->raw         undefined; implementation is PERMITTED to set to any value,
+    //                      so if caller needs to continue using this buffer it must
+    //                      keep track of the pointer itself
+    virtual void releaseBuffer(Buffer* buffer) = 0;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_AUDIO_BUFFER_PROVIDER_H
diff --git a/include/media/AudioResampler.h b/include/media/AudioResampler.h
new file mode 100644
index 0000000..c4627e8
--- /dev/null
+++ b/include/media/AudioResampler.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2007 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_RESAMPLER_H
+#define ANDROID_AUDIO_RESAMPLER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/compiler.h>
+#include <utils/Compat.h>
+
+#include <media/AudioBufferProvider.h>
+#include <system/audio.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class ANDROID_API AudioResampler {
+public:
+    // Determines quality of SRC.
+    //  LOW_QUALITY: linear interpolator (1st order)
+    //  MED_QUALITY: cubic interpolator (3rd order)
+    //  HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz)
+    // NOTE: high quality SRC will only be supported for
+    // certain fixed rate conversions. Sample rate cannot be
+    // changed dynamically.
+    enum src_quality {
+        DEFAULT_QUALITY=0,
+        LOW_QUALITY=1,
+        MED_QUALITY=2,
+        HIGH_QUALITY=3,
+        VERY_HIGH_QUALITY=4,
+        DYN_LOW_QUALITY=5,
+        DYN_MED_QUALITY=6,
+        DYN_HIGH_QUALITY=7,
+    };
+
+    static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
+
+    static AudioResampler* create(audio_format_t format, int inChannelCount,
+            int32_t sampleRate, src_quality quality=DEFAULT_QUALITY);
+
+    virtual ~AudioResampler();
+
+    virtual void init() = 0;
+    virtual void setSampleRate(int32_t inSampleRate);
+    virtual void setVolume(float left, float right);
+
+    // Resample int16_t samples from provider and accumulate into 'out'.
+    // A mono provider delivers a sequence of samples.
+    // A stereo provider delivers a sequence of interleaved pairs of samples.
+    //
+    // In either case, 'out' holds interleaved pairs of fixed-point Q4.27.
+    // That is, for a mono provider, there is an implicit up-channeling.
+    // Since this method accumulates, the caller is responsible for clearing 'out' initially.
+    //
+    // For a float resampler, 'out' holds interleaved pairs of float samples.
+    //
+    // Multichannel interleaved frames for n > 2 is supported for quality DYN_LOW_QUALITY,
+    // DYN_MED_QUALITY, and DYN_HIGH_QUALITY.
+    //
+    // Returns the number of frames resampled into the out buffer.
+    virtual size_t resample(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider) = 0;
+
+    virtual void reset();
+    virtual size_t getUnreleasedFrames() const { return mInputIndex; }
+
+    // called from destructor, so must not be virtual
+    src_quality getQuality() const { return mQuality; }
+
+protected:
+    // number of bits for phase fraction - 30 bits allows nearly 2x downsampling
+    static const int kNumPhaseBits = 30;
+
+    // phase mask for fraction
+    static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1;
+
+    // multiplier to calculate fixed point phase increment
+    static const double kPhaseMultiplier;
+
+    AudioResampler(int inChannelCount, int32_t sampleRate, src_quality quality);
+
+    // prevent copying
+    AudioResampler(const AudioResampler&);
+    AudioResampler& operator=(const AudioResampler&);
+
+    const int32_t mChannelCount;
+    const int32_t mSampleRate;
+    int32_t mInSampleRate;
+    AudioBufferProvider::Buffer mBuffer;
+    union {
+        int16_t mVolume[2];
+        uint32_t mVolumeRL;
+    };
+    int16_t mTargetVolume[2];
+    size_t mInputIndex;
+    int32_t mPhaseIncrement;
+    uint32_t mPhaseFraction;
+
+    // returns the inFrameCount required to generate outFrameCount frames.
+    //
+    // Placed here to be a consistent for all resamplers.
+    //
+    // Right now, we use the upper bound without regards to the current state of the
+    // input buffer using integer arithmetic, as follows:
+    //
+    // (static_cast<uint64_t>(outFrameCount)*mInSampleRate + (mSampleRate - 1))/mSampleRate;
+    //
+    // The double precision equivalent (float may not be precise enough):
+    // ceil(static_cast<double>(outFrameCount) * mInSampleRate / mSampleRate);
+    //
+    // this relies on the fact that the mPhaseIncrement is rounded down from
+    // #phases * mInSampleRate/mSampleRate and the fact that Sum(Floor(x)) <= Floor(Sum(x)).
+    // http://www.proofwiki.org/wiki/Sum_of_Floors_Not_Greater_Than_Floor_of_Sums
+    //
+    // (so long as double precision is computed accurately enough to be considered
+    // greater than or equal to the Floor(x) value in int32_t arithmetic; thus this
+    // will not necessarily hold for floats).
+    //
+    // TODO:
+    // Greater accuracy and a tight bound is obtained by:
+    // 1) subtract and adjust for the current state of the AudioBufferProvider buffer.
+    // 2) using the exact integer formula where (ignoring 64b casting)
+    //  inFrameCount = (mPhaseIncrement * (outFrameCount - 1) + mPhaseFraction) / phaseWrapLimit;
+    //  phaseWrapLimit is the wraparound (1 << kNumPhaseBits), if not specified explicitly.
+    //
+    inline size_t getInFrameCountRequired(size_t outFrameCount) {
+        return (static_cast<uint64_t>(outFrameCount)*mInSampleRate
+                + (mSampleRate - 1))/mSampleRate;
+    }
+
+    inline float clampFloatVol(float volume) {
+        if (volume > UNITY_GAIN_FLOAT) {
+            return UNITY_GAIN_FLOAT;
+        } else if (volume >= 0.) {
+            return volume;
+        }
+        return 0.;  // NaN or negative volume maps to 0.
+    }
+
+private:
+    const src_quality mQuality;
+
+    // Return 'true' if the quality level is supported without explicit request
+    static bool qualityIsSupported(src_quality quality);
+
+    // For pthread_once()
+    static void init_routine();
+
+    // Return the estimated CPU load for specific resampler in MHz.
+    // The absolute number is irrelevant, it's the relative values that matter.
+    static uint32_t qualityMHz(src_quality quality);
+};
+
+// ----------------------------------------------------------------------------
+} // namespace android
+
+#endif // ANDROID_AUDIO_RESAMPLER_H
diff --git a/include/private/private.h b/include/private/private.h
new file mode 100644
index 0000000..d10d1ea
--- /dev/null
+++ b/include/private/private.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 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_PRIVATE_H
+#define ANDROID_AUDIO_PRIVATE_H
+
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+/* Defines not necessary for external use but kept here to be common
+ * to the audio_utils library.
+ */
+
+/* struct representation of 3 bytes for packed PCM 24 bit data.
+ * The naming follows the ARM NEON convention.
+ */
+typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
+
+__END_DECLS
+
+#endif /*ANDROID_AUDIO_PRIVATE_H*/
diff --git a/include/resampler.h b/include/resampler.h
new file mode 100644
index 0000000..559e020
--- /dev/null
+++ b/include/resampler.h
@@ -0,0 +1,109 @@
+/*
+** Copyright 2008, 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_RESAMPLER_H
+#define ANDROID_RESAMPLER_H
+
+#include <stdint.h>
+#include <sys/time.h>
+
+__BEGIN_DECLS
+
+
+#define RESAMPLER_QUALITY_MAX 10
+#define RESAMPLER_QUALITY_MIN 0
+#define RESAMPLER_QUALITY_DEFAULT 4
+#define RESAMPLER_QUALITY_VOIP 3
+#define RESAMPLER_QUALITY_DESKTOP 5
+
+struct resampler_buffer {
+    union {
+        void*       raw;
+        short*      i16;
+        int8_t*     i8;
+    };
+    size_t frame_count;
+};
+
+/** call back interface used by the resampler to get new data */
+struct resampler_buffer_provider
+{
+    /**
+     *  get a new buffer of data:
+     *   as input: buffer->frame_count is the number of frames requested
+     *   as output: buffer->frame_count is the number of frames returned
+     *              buffer->raw points to data returned
+     */
+    int (*get_next_buffer)(struct resampler_buffer_provider *provider,
+            struct resampler_buffer *buffer);
+    /**
+     *  release a consumed buffer of data:
+     *   as input: buffer->frame_count is the number of frames released
+     *             buffer->raw points to data released
+     */
+    void (*release_buffer)(struct resampler_buffer_provider *provider,
+            struct resampler_buffer *buffer);
+};
+
+/** resampler interface */
+struct resampler_itfe {
+    /**
+     * reset resampler state
+     */
+    void (*reset)(struct resampler_itfe *resampler);
+    /**
+     * resample input from buffer provider and output at most *outFrameCount to out buffer.
+     * *outFrameCount is updated with the actual number of frames produced.
+     */
+    int (*resample_from_provider)(struct resampler_itfe *resampler,
+                    int16_t *out,
+                    size_t *outFrameCount);
+    /**
+     * resample at most *inFrameCount frames from in buffer and output at most
+     * *outFrameCount to out buffer. *inFrameCount and *outFrameCount are updated respectively
+     * with the number of frames remaining in input and written to output.
+     */
+    int (*resample_from_input)(struct resampler_itfe *resampler,
+                    int16_t *in,
+                    size_t *inFrameCount,
+                    int16_t *out,
+                    size_t *outFrameCount);
+    /**
+     * \return the latency introduced by the resampler in ns.
+     */
+    int32_t (*delay_ns)(struct resampler_itfe *resampler);
+};
+
+/**
+ * create a resampler according to input parameters passed.
+ * If resampler_buffer_provider is not NULL only resample_from_provider() can be called.
+ * If resampler_buffer_provider is NULL only resample_from_input() can be called.
+ */
+int create_resampler(uint32_t inSampleRate,
+          uint32_t outSampleRate,
+          uint32_t channelCount,
+          uint32_t quality,
+          struct resampler_buffer_provider *provider,
+          struct resampler_itfe **);
+
+/**
+ * release resampler resources.
+ */
+void release_resampler(struct resampler_itfe *);
+
+__END_DECLS
+
+#endif // ANDROID_RESAMPLER_H
diff --git a/include/speex/arch.h b/include/speex/arch.h
new file mode 100644
index 0000000..e911422
--- /dev/null
+++ b/include/speex/arch.h
@@ -0,0 +1,240 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file arch.h
+   @brief Various architecture definitions Speex
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ARCH_H
+#define ARCH_H
+
+#ifndef SPEEX_VERSION
+#define SPEEX_MAJOR_VERSION 1         /**< Major Speex version. */
+#define SPEEX_MINOR_VERSION 1         /**< Minor Speex version. */
+#define SPEEX_MICRO_VERSION 15        /**< Micro Speex version. */
+#define SPEEX_EXTRA_VERSION ""        /**< Extra Speex version. */
+#define SPEEX_VERSION "speex-1.2beta3"  /**< Speex version string. */
+#endif
+
+/* A couple test to catch stupid option combinations */
+#ifdef FIXED_POINT
+
+#ifdef FLOATING_POINT
+#error You cannot compile as floating point and fixed point at the same time
+#endif
+#ifdef _USE_SSE
+#error SSE is only for floating-point
+#endif
+#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
+#error Make up your mind. What CPU do you have?
+#endif
+#ifdef VORBIS_PSYCHO
+#error Vorbis-psy model currently not implemented in fixed-point
+#endif
+
+#else
+
+#ifndef FLOATING_POINT
+#error You now need to define either FIXED_POINT or FLOATING_POINT
+#endif
+#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
+#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
+#endif
+#ifdef FIXED_POINT_DEBUG
+#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
+#endif
+
+
+#endif
+
+#ifndef OUTSIDE_SPEEX
+#include "speex/speex_types.h"
+#endif
+
+#define ABS(x) ((x) < 0 ? (-(x)) : (x))      /**< Absolute integer value. */
+#define ABS16(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 16-bit value.  */
+#define MIN16(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define MAX16(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define ABS32(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 32-bit value.  */
+#define MIN32(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+#define MAX32(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+
+#ifdef FIXED_POINT
+
+typedef spx_int16_t spx_word16_t;
+typedef spx_int32_t   spx_word32_t;
+typedef spx_word32_t spx_mem_t;
+typedef spx_word16_t spx_coef_t;
+typedef spx_word16_t spx_lsp_t;
+typedef spx_word32_t spx_sig_t;
+
+#define Q15ONE 32767
+
+#define LPC_SCALING  8192
+#define SIG_SCALING  16384
+#define LSP_SCALING  8192.
+#define GAMMA_SCALING 32768.
+#define GAIN_SCALING 64
+#define GAIN_SCALING_1 0.015625
+
+#define LPC_SHIFT    13
+#define LSP_SHIFT    13
+#define SIG_SHIFT    14
+#define GAIN_SHIFT   6
+
+#define VERY_SMALL 0
+#define VERY_LARGE32 ((spx_word32_t)2147483647)
+#define VERY_LARGE16 ((spx_word16_t)32767)
+#define Q15_ONE ((spx_word16_t)32767)
+
+
+#ifdef FIXED_DEBUG
+#include "fixed_debug.h"
+#else
+
+#include "fixed_generic.h"
+
+#ifdef ARM5E_ASM
+#include "fixed_arm5e.h"
+#elif defined (ARM4_ASM)
+#include "fixed_arm4.h"
+#elif defined (BFIN_ASM)
+#include "fixed_bfin.h"
+#endif
+
+#endif
+
+
+#else
+
+typedef float spx_mem_t;
+typedef float spx_coef_t;
+typedef float spx_lsp_t;
+typedef float spx_sig_t;
+typedef float spx_word16_t;
+typedef float spx_word32_t;
+
+#define Q15ONE 1.0f
+#define LPC_SCALING  1.f
+#define SIG_SCALING  1.f
+#define LSP_SCALING  1.f
+#define GAMMA_SCALING 1.f
+#define GAIN_SCALING 1.f
+#define GAIN_SCALING_1 1.f
+
+
+#define VERY_SMALL 1e-15f
+#define VERY_LARGE32 1e15f
+#define VERY_LARGE16 1e15f
+#define Q15_ONE ((spx_word16_t)1.f)
+
+#define QCONST16(x,bits) (x)
+#define QCONST32(x,bits) (x)
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define EXTRACT16(x) (x)
+#define EXTEND32(x) (x)
+#define SHR16(a,shift) (a)
+#define SHL16(a,shift) (a)
+#define SHR32(a,shift) (a)
+#define SHL32(a,shift) (a)
+#define PSHR16(a,shift) (a)
+#define PSHR32(a,shift) (a)
+#define VSHR32(a,shift) (a)
+#define SATURATE16(x,a) (x)
+#define SATURATE32(x,a) (x)
+#define SATURATE32PSHR(x,shift,a) (x)
+
+#define PSHR(a,shift)       (a)
+#define SHR(a,shift)       (a)
+#define SHL(a,shift)       (a)
+#define SATURATE(x,a) (x)
+
+#define ADD16(a,b) ((a)+(b))
+#define SUB16(a,b) ((a)-(b))
+#define ADD32(a,b) ((a)+(b))
+#define SUB32(a,b) ((a)-(b))
+#define MULT16_16_16(a,b)     ((a)*(b))
+#define MULT16_16(a,b)     ((spx_word32_t)(a)*(spx_word32_t)(b))
+#define MAC16_16(c,a,b)     ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
+
+#define MULT16_32_Q11(a,b)     ((a)*(b))
+#define MULT16_32_Q13(a,b)     ((a)*(b))
+#define MULT16_32_Q14(a,b)     ((a)*(b))
+#define MULT16_32_Q15(a,b)     ((a)*(b))
+#define MULT16_32_P15(a,b)     ((a)*(b))
+
+#define MAC16_32_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_32_Q15(c,a,b)     ((c)+(a)*(b))
+
+#define MAC16_16_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_Q13(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_P13(c,a,b)     ((c)+(a)*(b))
+#define MULT16_16_Q11_32(a,b)     ((a)*(b))
+#define MULT16_16_Q13(a,b)     ((a)*(b))
+#define MULT16_16_Q14(a,b)     ((a)*(b))
+#define MULT16_16_Q15(a,b)     ((a)*(b))
+#define MULT16_16_P15(a,b)     ((a)*(b))
+#define MULT16_16_P13(a,b)     ((a)*(b))
+#define MULT16_16_P14(a,b)     ((a)*(b))
+
+#define DIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define PDIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define DIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+#define PDIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+
+
+#endif
+
+
+#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+/* 2 on TI C5x DSP */
+#define BYTES_PER_CHAR 2 
+#define BITS_PER_CHAR 16
+#define LOG2_BITS_PER_CHAR 4
+
+#else 
+
+#define BYTES_PER_CHAR 1
+#define BITS_PER_CHAR 8
+#define LOG2_BITS_PER_CHAR 3
+
+#endif
+
+
+
+#ifdef FIXED_DEBUG
+extern long long spx_mips;
+#endif
+
+
+#endif
diff --git a/include/speex/fixed_generic.h b/include/speex/fixed_generic.h
new file mode 100644
index 0000000..0e012e9
--- /dev/null
+++ b/include/speex/fixed_generic.h
@@ -0,0 +1,110 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file fixed_generic.h
+   @brief Generic fixed-point operations
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_GENERIC_H
+#define FIXED_GENERIC_H
+
+#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
+#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define EXTRACT16(x) ((spx_word16_t)(x))
+#define EXTEND32(x) ((spx_word32_t)(x))
+#define SHR16(a,shift) ((a) >> (shift))
+#define SHL16(a,shift) ((a) << (shift))
+#define SHR32(a,shift) ((a) >> (shift))
+#define SHL32(a,shift) ((a) << (shift))
+#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift))
+#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
+#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
+#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+
+#define SATURATE32PSHR(x,shift,a) (((x)>=(SHL32(a,shift))) ? (a) : \
+                                   (x)<=-(SHL32(a,shift)) ? -(a) : \
+                                   (PSHR32(x, shift)))
+
+#define SHR(a,shift) ((a) >> (shift))
+#define SHL(a,shift) ((spx_word32_t)(a) << (shift))
+#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
+#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+
+
+#define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b)))
+#define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b))
+#define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b))
+#define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b))
+
+
+/* result fits in 16 bits */
+#define MULT16_16_16(a,b)     ((((spx_word16_t)(a))*((spx_word16_t)(b))))
+
+/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */
+#define MULT16_16(a,b)     (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b)))
+
+#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
+#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
+#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
+#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
+
+#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))
+#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)))
+
+#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
+#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
+#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
+
+
+#define MAC16_16_Q11(c,a,b)     (ADD32((c),SHR(MULT16_16((a),(b)),11)))
+#define MAC16_16_Q13(c,a,b)     (ADD32((c),SHR(MULT16_16((a),(b)),13)))
+#define MAC16_16_P13(c,a,b)     (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13)))
+
+#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
+#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
+#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
+#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
+
+#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
+#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
+#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
+
+#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15))
+
+#define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b))))
+#define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b))))
+#define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b)))
+#define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b)))
+
+#endif
diff --git a/include/speex/os_support.h b/include/speex/os_support.h
new file mode 100644
index 0000000..6b74b0c
--- /dev/null
+++ b/include/speex/os_support.h
@@ -0,0 +1,169 @@
+/* Copyright (C) 2007 Jean-Marc Valin
+      
+   File: os_support.h
+   This is the (tiny) OS abstraction layer. Aside from math.h, this is the
+   only place where system headers are allowed.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef OS_SUPPORT_H
+#define OS_SUPPORT_H
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef OS_SUPPORT_CUSTOM
+#include "os_support_custom.h"
+#endif
+
+/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free 
+    NOTE: speex_alloc needs to CLEAR THE MEMORY */
+#ifndef OVERRIDE_SPEEX_ALLOC
+static inline void *speex_alloc (int size)
+{
+   /* WARNING: this is not equivalent to malloc(). If you want to use malloc() 
+      or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise
+      you will experience strange bugs */
+   return calloc(size,1);
+}
+#endif
+
+/** Same as speex_alloc, except that the area is only needed inside a Speex call (might cause problem with wideband though) */
+#ifndef OVERRIDE_SPEEX_ALLOC_SCRATCH
+static inline void *speex_alloc_scratch (int size)
+{
+   /* Scratch space doesn't need to be cleared */
+   return calloc(size,1);
+}
+#endif
+
+/** Speex wrapper for realloc. To do your own dynamic allocation, all you need to do is replace this function, speex_alloc and speex_free */
+#ifndef OVERRIDE_SPEEX_REALLOC
+static inline void *speex_realloc (void *ptr, int size)
+{
+   return realloc(ptr, size);
+}
+#endif
+
+/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_alloc */
+#ifndef OVERRIDE_SPEEX_FREE
+static inline void speex_free (void *ptr)
+{
+   free(ptr);
+}
+#endif
+
+/** Same as speex_free, except that the area is only needed inside a Speex call (might cause problem with wideband though) */
+#ifndef OVERRIDE_SPEEX_FREE_SCRATCH
+static inline void speex_free_scratch (void *ptr)
+{
+   free(ptr);
+}
+#endif
+
+/** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking  */
+#ifndef OVERRIDE_SPEEX_COPY
+#define SPEEX_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
+#endif
+
+/** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term 
+    provides compile-time type checking */
+#ifndef OVERRIDE_SPEEX_MOVE
+#define SPEEX_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
+#endif
+
+/** Set n bytes of memory to value of c, starting at address s */
+#ifndef OVERRIDE_SPEEX_MEMSET
+#define SPEEX_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst))))
+#endif
+
+
+#ifndef OVERRIDE_SPEEX_FATAL
+static inline void _speex_fatal(const char *str, const char *file, int line)
+{
+   fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
+   exit(1);
+}
+#endif
+
+#ifndef OVERRIDE_SPEEX_WARNING
+static inline void speex_warning(const char *str)
+{
+#ifndef DISABLE_WARNINGS
+   fprintf (stderr, "warning: %s\n", str);
+#endif
+}
+#endif
+
+#ifndef OVERRIDE_SPEEX_WARNING_INT
+static inline void speex_warning_int(const char *str, int val)
+{
+#ifndef DISABLE_WARNINGS
+   fprintf (stderr, "warning: %s %d\n", str, val);
+#endif
+}
+#endif
+
+#ifndef OVERRIDE_SPEEX_NOTIFY
+static inline void speex_notify(const char *str)
+{
+#ifndef DISABLE_NOTIFICATIONS
+   fprintf (stderr, "notification: %s\n", str);
+#endif
+}
+#endif
+
+#ifndef OVERRIDE_SPEEX_PUTC
+/** Speex wrapper for putc */
+static inline void _speex_putc(int ch, void *file)
+{
+   FILE *f = (FILE *)file;
+   fprintf(f, "%c", ch);
+}
+#endif
+
+#define speex_fatal(str) _speex_fatal(str, __FILE__, __LINE__);
+#define speex_assert(cond) {if (!(cond)) {speex_fatal("assertion failed: " #cond);}}
+
+#ifndef RELEASE
+static inline void print_vec(float *vec, int len, char *name)
+{
+   int i;
+   printf ("%s ", name);
+   for (i=0;i<len;i++)
+      printf (" %f", vec[i]);
+   printf ("\n");
+}
+#endif
+
+#endif
+
diff --git a/include/speex/resample_neon.h b/include/speex/resample_neon.h
new file mode 100644
index 0000000..b651d5d
--- /dev/null
+++ b/include/speex/resample_neon.h
@@ -0,0 +1,188 @@
+/* Copyright (C) 2007-2008 Jean-Marc Valin
+ * Copyright (C) 2008 Thorvald Natvig
+ * Copyright (C) 2011 Jyri Sarha, Texas Instruments
+ */
+/**
+   @file resample_neon.h
+   @brief Resampler functions (NEON version)
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <arm_neon.h>
+
+#ifdef FIXED_POINT
+static inline int32_t saturate_32bit_to_16bit(int32_t a) {
+    int32_t ret;
+    asm volatile ("vmov.s32 d24[0], %[a]\n"
+                  "vqmovn.s32 d24, q12\n"
+                  "vmov.s16 %[ret], d24[0]\n"
+                  : [ret] "=&r" (ret)
+                  : [a] "r" (a)
+                  : "q12", "d24", "d25" );
+    return ret;
+}
+#undef WORD2INT
+#define WORD2INT(x) (saturate_32bit_to_16bit(x))
+
+#define OVERRIDE_INNER_PRODUCT_SINGLE
+static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
+{
+    int32_t ret;
+    uint32_t remainder = len % 16;
+    len = len - remainder;
+
+    asm volatile ("	 cmp %[len], #0\n"
+		  "	 bne 1f\n"
+		  "	 vld1.16 {d16}, [%[a]]!\n"
+		  "	 vld1.16 {d20}, [%[b]]!\n"
+		  "	 subs %[remainder], %[remainder], #4\n"
+		  "	 vmull.s16 q0, d16, d20\n"
+		  "      beq 5f\n"
+		  "	 b 4f\n"
+		  "1:"
+		  "	 vld1.16 {d16, d17, d18, d19}, [%[a]]!\n"
+		  "	 vld1.16 {d20, d21, d22, d23}, [%[b]]!\n"
+		  "	 subs %[len], %[len], #16\n"
+		  "	 vmull.s16 q0, d16, d20\n"
+		  "	 vmlal.s16 q0, d17, d21\n"
+		  "	 vmlal.s16 q0, d18, d22\n"
+		  "	 vmlal.s16 q0, d19, d23\n"
+		  "	 beq 3f\n"
+		  "2:"
+		  "	 vld1.16 {d16, d17, d18, d19}, [%[a]]!\n"
+		  "	 vld1.16 {d20, d21, d22, d23}, [%[b]]!\n"
+		  "	 subs %[len], %[len], #16\n"
+		  "	 vmlal.s16 q0, d16, d20\n"
+		  "	 vmlal.s16 q0, d17, d21\n"
+		  "	 vmlal.s16 q0, d18, d22\n"
+		  "	 vmlal.s16 q0, d19, d23\n"
+		  "	 bne 2b\n"
+		  "3:"
+		  "	 cmp %[remainder], #0\n"
+		  "	 beq 5f\n"
+		  "4:"
+		  "	 vld1.16 {d16}, [%[a]]!\n"
+		  "	 vld1.16 {d20}, [%[b]]!\n"
+		  "	 subs %[remainder], %[remainder], #4\n"
+		  "	 vmlal.s16 q0, d16, d20\n"
+		  "	 bne 4b\n"
+		  "5:"
+		  "	 vaddl.s32 q0, d0, d1\n"
+		  "	 vadd.s64 d0, d0, d1\n"
+		  "	 vqmovn.s64 d0, q0\n"
+		  "	 vqrshrn.s32 d0, q0, #15\n"
+		  "	 vmov.s16 %[ret], d0[0]\n"
+		  : [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b),
+		    [len] "+r" (len), [remainder] "+r" (remainder)
+		  :
+		  : "cc", "q0",
+		    "d16", "d17", "d18", "d19",
+		    "d20", "d21", "d22", "d23");
+    return ret;
+}
+
+#elif defined(FLOATING_POINT)
+
+static inline int32_t saturate_float_to_16bit(float a) {
+    int32_t ret;
+    asm ("vmov.f32 d24[0], %[a]\n"
+         "vcvt.s32.f32 d24, d24, #15\n"
+         "vqrshrn.s32 d24, q12, #15\n"
+         "vmov.s16 %[ret], d24[0]\n"
+         : [ret] "=&r" (ret)
+         : [a] "r" (a)
+         : "q12", "d24", "d25" );
+    return ret;
+}
+#undef WORD2INT
+#define WORD2INT(x) (saturate_float_to_16bit(x))
+
+#define OVERRIDE_INNER_PRODUCT_SINGLE
+static inline float inner_product_single(const float *a, const float *b, unsigned int len)
+{
+    float ret;
+    uint32_t remainder = len % 16;
+    len = len - remainder;
+
+    asm volatile ("	 cmp %[len], #0\n"
+		  "	 bne 1f\n"
+		  "	 vld1.32 {q4}, [%[a]]!\n"
+		  "	 vld1.32 {q8}, [%[b]]!\n"
+		  "	 subs %[remainder], %[remainder], #4\n"
+		  "	 vmul.f32 q0, q4, q8\n"
+		  "      beq 5f\n"
+		  "	 b 4f\n"
+		  "1:"
+		  "	 vld1.32 {q4, q5}, [%[a]]!\n"
+		  "	 vld1.32 {q8, q9}, [%[b]]!\n"
+		  "	 vld1.32 {q6, q7}, [%[a]]!\n"
+		  "	 vld1.32 {q10, q11}, [%[b]]!\n"
+		  "	 subs %[len], %[len], #16\n"
+		  "	 vmul.f32 q0, q4, q8\n"
+		  "	 vmul.f32 q1, q5, q9\n"
+		  "	 vmul.f32 q2, q6, q10\n"
+		  "	 vmul.f32 q3, q7, q11\n"
+		  "	 beq 3f\n"
+		  "2:"
+		  "	 vld1.32 {q4, q5}, [%[a]]!\n"
+		  "	 vld1.32 {q8, q9}, [%[b]]!\n"
+		  "	 vld1.32 {q6, q7}, [%[a]]!\n"
+		  "	 vld1.32 {q10, q11}, [%[b]]!\n"
+		  "	 subs %[len], %[len], #16\n"
+		  "	 vmla.f32 q0, q4, q8\n"
+		  "	 vmla.f32 q1, q5, q9\n"
+		  "	 vmla.f32 q2, q6, q10\n"
+		  "	 vmla.f32 q3, q7, q11\n"
+		  "	 bne 2b\n"
+		  "3:"
+		  "	 vadd.f32 q4, q0, q1\n"
+		  "	 vadd.f32 q5, q2, q3\n"
+		  "	 vadd.f32 q0, q4, q5\n"
+		  "	 cmp %[remainder], #0\n"
+		  "	 beq 5f\n"
+		  "4:"
+		  "	 vld1.32 {q6}, [%[a]]!\n"
+		  "	 vld1.32 {q10}, [%[b]]!\n"
+		  "	 subs %[remainder], %[remainder], #4\n"
+		  "	 vmla.f32 q0, q6, q10\n"
+		  "	 bne 4b\n"
+		  "5:"
+		  "	 vadd.f32 d0, d0, d1\n"
+		  "	 vpadd.f32 d0, d0, d0\n"
+		  "	 vmov.f32 %[ret], d0[0]\n"
+		  : [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b),
+		    [len] "+l" (len), [remainder] "+l" (remainder)
+		  :
+		  : "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8",
+		    "q9", "q10", "q11");
+    return ret;
+}
+
+#endif
diff --git a/include/speex/speex_config_types.h b/include/speex/speex_config_types.h
new file mode 100644
index 0000000..bd54854
--- /dev/null
+++ b/include/speex/speex_config_types.h
@@ -0,0 +1,11 @@
+#ifndef __SPEEX_TYPES_H__
+#define __SPEEX_TYPES_H__
+
+/* these are filled in by configure */
+typedef short spx_int16_t;
+typedef unsigned short spx_uint16_t;
+typedef int spx_int32_t;
+typedef unsigned int spx_uint32_t;
+
+#endif
+
diff --git a/include/speex/speex_resampler.h b/include/speex/speex_resampler.h
new file mode 100644
index 0000000..54eef8d
--- /dev/null
+++ b/include/speex/speex_resampler.h
@@ -0,0 +1,340 @@
+/* Copyright (C) 2007 Jean-Marc Valin
+      
+   File: speex_resampler.h
+   Resampling code
+      
+   The design goals of this code are:
+      - Very fast algorithm
+      - Low memory requirement
+      - Good *perceptual* quality (and not best SNR)
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef SPEEX_RESAMPLER_H
+#define SPEEX_RESAMPLER_H
+
+#ifdef OUTSIDE_SPEEX
+
+/********* WARNING: MENTAL SANITY ENDS HERE *************/
+
+/* If the resampler is defined outside of Speex, we change the symbol names so that 
+   there won't be any clash if linking with Speex later on. */
+
+/* #define RANDOM_PREFIX your software name here */
+#ifndef RANDOM_PREFIX
+#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes"
+#endif
+
+#define CAT_PREFIX2(a,b) a ## b
+#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b)
+      
+#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init)
+#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac)
+#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy)
+#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float)
+#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int)
+#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float)
+#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int)
+#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate)
+#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate)
+#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac)
+#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio)
+#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality)
+#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality)
+#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride)
+#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride)
+#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride)
+#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride)
+#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency)
+#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency)
+#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
+#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
+#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
+
+#define spx_int16_t short
+#define spx_int32_t int
+#define spx_uint16_t unsigned short
+#define spx_uint32_t unsigned int
+      
+#else /* OUTSIDE_SPEEX */
+
+#include "speex/speex_types.h"
+
+#endif /* OUTSIDE_SPEEX */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SPEEX_RESAMPLER_QUALITY_MAX 10
+#define SPEEX_RESAMPLER_QUALITY_MIN 0
+#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4
+#define SPEEX_RESAMPLER_QUALITY_VOIP 3
+#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
+
+enum {
+   RESAMPLER_ERR_SUCCESS         = 0,
+   RESAMPLER_ERR_ALLOC_FAILED    = 1,
+   RESAMPLER_ERR_BAD_STATE       = 2,
+   RESAMPLER_ERR_INVALID_ARG     = 3,
+   RESAMPLER_ERR_PTR_OVERLAP     = 4,
+   
+   RESAMPLER_ERR_MAX_ERROR
+};
+
+struct SpeexResamplerState_;
+typedef struct SpeexResamplerState_ SpeexResamplerState;
+
+/** Create a new resampler with integer input and output rates.
+ * @param nb_channels Number of channels to be processed
+ * @param in_rate Input sampling rate (integer number of Hz).
+ * @param out_rate Output sampling rate (integer number of Hz).
+ * @param quality Resampling quality between 0 and 10, where 0 has poor quality
+ * and 10 has very high quality.
+ * @return Newly created resampler state
+ * @retval NULL Error: not enough memory
+ */
+SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, 
+                                          spx_uint32_t in_rate, 
+                                          spx_uint32_t out_rate, 
+                                          int quality,
+                                          int *err);
+
+/** Create a new resampler with fractional input/output rates. The sampling 
+ * rate ratio is an arbitrary rational number with both the numerator and 
+ * denominator being 32-bit integers.
+ * @param nb_channels Number of channels to be processed
+ * @param ratio_num Numerator of the sampling rate ratio
+ * @param ratio_den Denominator of the sampling rate ratio
+ * @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
+ * @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
+ * @param quality Resampling quality between 0 and 10, where 0 has poor quality
+ * and 10 has very high quality.
+ * @return Newly created resampler state
+ * @retval NULL Error: not enough memory
+ */
+SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, 
+                                               spx_uint32_t ratio_num, 
+                                               spx_uint32_t ratio_den, 
+                                               spx_uint32_t in_rate, 
+                                               spx_uint32_t out_rate, 
+                                               int quality,
+                                               int *err);
+
+/** Destroy a resampler state.
+ * @param st Resampler state
+ */
+void speex_resampler_destroy(SpeexResamplerState *st);
+
+/** Resample a float array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param channel_index Index of the channel to process for the multi-channel 
+ * base (0 otherwise)
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the 
+ * number of samples processed
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written
+ */
+int speex_resampler_process_float(SpeexResamplerState *st, 
+                                   spx_uint32_t channel_index, 
+                                   const float *in, 
+                                   spx_uint32_t *in_len, 
+                                   float *out, 
+                                   spx_uint32_t *out_len);
+
+/** Resample an int array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param channel_index Index of the channel to process for the multi-channel 
+ * base (0 otherwise)
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written
+ */
+int speex_resampler_process_int(SpeexResamplerState *st, 
+                                 spx_uint32_t channel_index, 
+                                 const spx_int16_t *in, 
+                                 spx_uint32_t *in_len, 
+                                 spx_int16_t *out, 
+                                 spx_uint32_t *out_len);
+
+/** Resample an interleaved float array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed. This is all per-channel.
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written.
+ * This is all per-channel.
+ */
+int speex_resampler_process_interleaved_float(SpeexResamplerState *st, 
+                                               const float *in, 
+                                               spx_uint32_t *in_len, 
+                                               float *out, 
+                                               spx_uint32_t *out_len);
+
+/** Resample an interleaved int array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed. This is all per-channel.
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written.
+ * This is all per-channel.
+ */
+int speex_resampler_process_interleaved_int(SpeexResamplerState *st, 
+                                             const spx_int16_t *in, 
+                                             spx_uint32_t *in_len, 
+                                             spx_int16_t *out, 
+                                             spx_uint32_t *out_len);
+
+/** Set (change) the input/output sampling rates (integer value).
+ * @param st Resampler state
+ * @param in_rate Input sampling rate (integer number of Hz).
+ * @param out_rate Output sampling rate (integer number of Hz).
+ */
+int speex_resampler_set_rate(SpeexResamplerState *st, 
+                              spx_uint32_t in_rate, 
+                              spx_uint32_t out_rate);
+
+/** Get the current input/output sampling rates (integer value).
+ * @param st Resampler state
+ * @param in_rate Input sampling rate (integer number of Hz) copied.
+ * @param out_rate Output sampling rate (integer number of Hz) copied.
+ */
+void speex_resampler_get_rate(SpeexResamplerState *st, 
+                              spx_uint32_t *in_rate, 
+                              spx_uint32_t *out_rate);
+
+/** Set (change) the input/output sampling rates and resampling ratio 
+ * (fractional values in Hz supported).
+ * @param st Resampler state
+ * @param ratio_num Numerator of the sampling rate ratio
+ * @param ratio_den Denominator of the sampling rate ratio
+ * @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
+ * @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
+ */
+int speex_resampler_set_rate_frac(SpeexResamplerState *st, 
+                                   spx_uint32_t ratio_num, 
+                                   spx_uint32_t ratio_den, 
+                                   spx_uint32_t in_rate, 
+                                   spx_uint32_t out_rate);
+
+/** Get the current resampling ratio. This will be reduced to the least
+ * common denominator.
+ * @param st Resampler state
+ * @param ratio_num Numerator of the sampling rate ratio copied
+ * @param ratio_den Denominator of the sampling rate ratio copied
+ */
+void speex_resampler_get_ratio(SpeexResamplerState *st, 
+                               spx_uint32_t *ratio_num, 
+                               spx_uint32_t *ratio_den);
+
+/** Set (change) the conversion quality.
+ * @param st Resampler state
+ * @param quality Resampling quality between 0 and 10, where 0 has poor 
+ * quality and 10 has very high quality.
+ */
+int speex_resampler_set_quality(SpeexResamplerState *st, 
+                                 int quality);
+
+/** Get the conversion quality.
+ * @param st Resampler state
+ * @param quality Resampling quality between 0 and 10, where 0 has poor 
+ * quality and 10 has very high quality.
+ */
+void speex_resampler_get_quality(SpeexResamplerState *st, 
+                                 int *quality);
+
+/** Set (change) the input stride.
+ * @param st Resampler state
+ * @param stride Input stride
+ */
+void speex_resampler_set_input_stride(SpeexResamplerState *st, 
+                                      spx_uint32_t stride);
+
+/** Get the input stride.
+ * @param st Resampler state
+ * @param stride Input stride copied
+ */
+void speex_resampler_get_input_stride(SpeexResamplerState *st, 
+                                      spx_uint32_t *stride);
+
+/** Set (change) the output stride.
+ * @param st Resampler state
+ * @param stride Output stride
+ */
+void speex_resampler_set_output_stride(SpeexResamplerState *st, 
+                                      spx_uint32_t stride);
+
+/** Get the output stride.
+ * @param st Resampler state copied
+ * @param stride Output stride
+ */
+void speex_resampler_get_output_stride(SpeexResamplerState *st, 
+                                      spx_uint32_t *stride);
+
+/** Get the latency in input samples introduced by the resampler.
+ * @param st Resampler state
+ */
+int speex_resampler_get_input_latency(SpeexResamplerState *st);
+
+/** Get the latency in output samples introduced by the resampler.
+ * @param st Resampler state
+ */
+int speex_resampler_get_output_latency(SpeexResamplerState *st);
+
+/** Make sure that the first samples to go out of the resamplers don't have 
+ * leading zeros. This is only useful before starting to use a newly created 
+ * resampler. It is recommended to use that when resampling an audio file, as
+ * it will generate a file with the same length. For real-time processing,
+ * it is probably easier not to use this call (so that the output duration
+ * is the same for the first frame).
+ * @param st Resampler state
+ */
+int speex_resampler_skip_zeros(SpeexResamplerState *st);
+
+/** Reset a resampler so a new (unrelated) stream can be processed.
+ * @param st Resampler state
+ */
+int speex_resampler_reset_mem(SpeexResamplerState *st);
+
+/** Returns the English meaning for an error code
+ * @param err Error code
+ * @return English string
+ */
+const char *speex_resampler_strerror(int err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/speex/speex_types.h b/include/speex/speex_types.h
new file mode 100644
index 0000000..852fed8
--- /dev/null
+++ b/include/speex/speex_types.h
@@ -0,0 +1,126 @@
+/* speex_types.h taken from libogg */
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
+ *                                                                  *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
+ *                                                                  *
+ ********************************************************************
+
+ function: #ifdef jail to whip a few platforms into the UNIX ideal.
+ last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $
+
+ ********************************************************************/
+/**
+   @file speex_types.h
+   @brief Speex types
+*/
+#ifndef _SPEEX_TYPES_H
+#define _SPEEX_TYPES_H
+
+#if defined(_WIN32) 
+
+#  if defined(__CYGWIN__)
+#    include <_G_config.h>
+     typedef _G_int32_t spx_int32_t;
+     typedef _G_uint32_t spx_uint32_t;
+     typedef _G_int16_t spx_int16_t;
+     typedef _G_uint16_t spx_uint16_t;
+#  elif defined(__MINGW32__)
+     typedef short spx_int16_t;
+     typedef unsigned short spx_uint16_t;
+     typedef int spx_int32_t;
+     typedef unsigned int spx_uint32_t;
+#  elif defined(__MWERKS__)
+     typedef int spx_int32_t;
+     typedef unsigned int spx_uint32_t;
+     typedef short spx_int16_t;
+     typedef unsigned short spx_uint16_t;
+#  else
+     /* MSVC/Borland */
+     typedef __int32 spx_int32_t;
+     typedef unsigned __int32 spx_uint32_t;
+     typedef __int16 spx_int16_t;
+     typedef unsigned __int16 spx_uint16_t;
+#  endif
+
+#elif defined(__MACOS__)
+
+#  include <sys/types.h>
+   typedef SInt16 spx_int16_t;
+   typedef UInt16 spx_uint16_t;
+   typedef SInt32 spx_int32_t;
+   typedef UInt32 spx_uint32_t;
+
+#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
+
+#  include <sys/types.h>
+   typedef int16_t spx_int16_t;
+   typedef u_int16_t spx_uint16_t;
+   typedef int32_t spx_int32_t;
+   typedef u_int32_t spx_uint32_t;
+
+#elif defined(__BEOS__)
+
+   /* Be */
+#  include <inttypes.h>
+   typedef int16_t spx_int16_t;
+   typedef u_int16_t spx_uint16_t;
+   typedef int32_t spx_int32_t;
+   typedef u_int32_t spx_uint32_t;
+
+#elif defined (__EMX__)
+
+   /* OS/2 GCC */
+   typedef short spx_int16_t;
+   typedef unsigned short spx_uint16_t;
+   typedef int spx_int32_t;
+   typedef unsigned int spx_uint32_t;
+
+#elif defined (DJGPP)
+
+   /* DJGPP */
+   typedef short spx_int16_t;
+   typedef int spx_int32_t;
+   typedef unsigned int spx_uint32_t;
+
+#elif defined(R5900)
+
+   /* PS2 EE */
+   typedef int spx_int32_t;
+   typedef unsigned spx_uint32_t;
+   typedef short spx_int16_t;
+
+#elif defined(__SYMBIAN32__)
+
+   /* Symbian GCC */
+   typedef signed short spx_int16_t;
+   typedef unsigned short spx_uint16_t;
+   typedef signed int spx_int32_t;
+   typedef unsigned int spx_uint32_t;
+
+#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+   typedef short spx_int16_t;
+   typedef unsigned short spx_uint16_t;
+   typedef long spx_int32_t;
+   typedef unsigned long spx_uint32_t;
+
+#elif defined(CONFIG_TI_C6X)
+
+   typedef short spx_int16_t;
+   typedef unsigned short spx_uint16_t;
+   typedef int spx_int32_t;
+   typedef unsigned int spx_uint32_t;
+
+#else
+
+#  include <speex/speex_config_types.h>
+
+#endif
+
+#endif  /* _SPEEX_TYPES_H */
diff --git a/include/speex/stack_alloc.h b/include/speex/stack_alloc.h
new file mode 100644
index 0000000..5264e66
--- /dev/null
+++ b/include/speex/stack_alloc.h
@@ -0,0 +1,115 @@
+/* Copyright (C) 2002 Jean-Marc Valin */
+/**
+   @file stack_alloc.h
+   @brief Temporary memory allocation on stack
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef STACK_ALLOC_H
+#define STACK_ALLOC_H
+
+#ifdef USE_ALLOCA
+# ifdef WIN32
+#  include <malloc.h>
+# else
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   include <stdlib.h>
+#  endif
+# endif
+#endif
+
+/**
+ * @def ALIGN(stack, size)
+ *
+ * Aligns the stack to a 'size' boundary
+ *
+ * @param stack Stack
+ * @param size  New size boundary
+ */
+
+/**
+ * @def PUSH(stack, size, type)
+ *
+ * Allocates 'size' elements of type 'type' on the stack
+ *
+ * @param stack Stack
+ * @param size  Number of elements
+ * @param type  Type of element
+ */
+
+/**
+ * @def VARDECL(var)
+ *
+ * Declare variable on stack
+ *
+ * @param var Variable to declare
+ */
+
+/**
+ * @def ALLOC(var, size, type)
+ *
+ * Allocate 'size' elements of 'type' on stack
+ *
+ * @param var  Name of variable to allocate
+ * @param size Number of elements
+ * @param type Type of element
+ */
+
+#ifdef ENABLE_VALGRIND
+
+#include <valgrind/memcheck.h>
+
+#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
+
+#define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
+
+#else
+
+#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
+
+#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
+
+#endif
+
+#if defined(VAR_ARRAYS)
+#define VARDECL(var) 
+#define ALLOC(var, size, type) type var[size]
+#elif defined(USE_ALLOCA)
+#define VARDECL(var) var
+#define ALLOC(var, size, type) var = alloca(sizeof(type)*(size))
+#else
+#define VARDECL(var) var
+#define ALLOC(var, size, type) var = PUSH(stack, size, type)
+#endif
+
+
+#endif
diff --git a/include/system/audio-base-utils.h b/include/system/audio-base-utils.h
new file mode 100644
index 0000000..016a085
--- /dev/null
+++ b/include/system/audio-base-utils.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2018 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_BASE_UTILS_H
+#define ANDROID_AUDIO_BASE_UTILS_H
+
+#include "audio-base.h"
+
+/** Define helper values to iterate over enum, extend them or checking value validity.
+ *  Those values are compatible with the O corresponding enum values.
+ *  They are not macro like similar values in audio.h to avoid conflicting
+ *  with the libhardware_legacy audio.h.
+ */
+enum {
+    /** Number of audio stream available to vendors. */
+    AUDIO_STREAM_PUBLIC_CNT = AUDIO_STREAM_ACCESSIBILITY + 1,
+
+#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
+    /** Total number of stream handled by the policy*/
+    AUDIO_STREAM_FOR_POLICY_CNT= AUDIO_STREAM_REROUTING + 1,
+#endif
+
+   /** Total number of stream. */
+    AUDIO_STREAM_CNT          = AUDIO_STREAM_PATCH + 1,
+
+    AUDIO_SOURCE_MAX          = AUDIO_SOURCE_UNPROCESSED,
+    AUDIO_SOURCE_CNT          = AUDIO_SOURCE_MAX + 1,
+
+    AUDIO_MODE_MAX            = AUDIO_MODE_IN_COMMUNICATION,
+    AUDIO_MODE_CNT            = AUDIO_MODE_MAX + 1,
+
+    /** For retrocompatibility AUDIO_MODE_* and AUDIO_STREAM_* must be signed. */
+    AUDIO_DETAIL_NEGATIVE_VALUE = -1,
+};
+
+enum {
+    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 |
+                                AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT |
+                                AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT,
+
+    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 |
+                                AUDIO_CHANNEL_IN_BACK_LEFT |
+                                AUDIO_CHANNEL_IN_BACK_RIGHT |
+                                AUDIO_CHANNEL_IN_CENTER |
+                                AUDIO_CHANNEL_IN_LOW_FREQUENCY |
+                                AUDIO_CHANNEL_IN_TOP_LEFT |
+                                AUDIO_CHANNEL_IN_TOP_RIGHT,
+
+    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_PROXY |
+                                AUDIO_DEVICE_OUT_USB_HEADSET |
+                                AUDIO_DEVICE_OUT_HEARING_AID |
+                                AUDIO_DEVICE_OUT_ECHO_CANCELLER |
+                                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 |
+                                AUDIO_DEVICE_OUT_USB_HEADSET,
+
+    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_PROXY |
+                                AUDIO_DEVICE_IN_USB_HEADSET |
+                                AUDIO_DEVICE_IN_BLUETOOTH_BLE |
+                                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 |
+                                AUDIO_DEVICE_IN_USB_HEADSET,
+
+    AUDIO_USAGE_MAX           = AUDIO_USAGE_ASSISTANT,
+    AUDIO_USAGE_CNT           = AUDIO_USAGE_ASSISTANT + 1,
+
+    AUDIO_PORT_CONFIG_ALL     = AUDIO_PORT_CONFIG_SAMPLE_RATE |
+                                AUDIO_PORT_CONFIG_CHANNEL_MASK |
+                                AUDIO_PORT_CONFIG_FORMAT |
+                                AUDIO_PORT_CONFIG_GAIN,
+}; // enum
+
+
+#endif  // ANDROID_AUDIO_BASE_UTILS_H
diff --git a/include/system/audio-base.h b/include/system/audio-base.h
new file mode 100644
index 0000000..4eb2808
--- /dev/null
+++ b/include/system/audio-base.h
@@ -0,0 +1,457 @@
+// This file is autogenerated by hidl-gen
+// then manualy edited for retrocompatiblity
+// Source: android.hardware.audio.common@4.0
+// Root: android.hardware:hardware/interfaces
+
+#ifndef HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_COMMON_V4_0_EXPORTED_CONSTANTS_H_
+#define HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_COMMON_V4_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,
+#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
+    /** For dynamic policy output mixes. Only used by the audio policy */
+    AUDIO_STREAM_REROUTING = 11,
+    /** For audio flinger tracks volume. Only used by the audioflinger */
+    AUDIO_STREAM_PATCH = 12,
+#endif // AUDIO_NO_SYSTEM_DECLARATIONS
+} 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_FM_TUNER = 1998,
+#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
+    /**
+     * A low-priority, preemptible audio source for for background software
+     * hotword detection. Same tuning as VOICE_RECOGNITION.
+     * Used only internally by the framework.
+     */
+    AUDIO_SOURCE_HOTWORD = 1999,
+#endif // AUDIO_NO_SYSTEM_DECLARATIONS
+} 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             = 0xFFFFFFFFu,
+    AUDIO_FORMAT_DEFAULT             = 0,
+    AUDIO_FORMAT_PCM                 = 0x00000000u,
+    AUDIO_FORMAT_MP3                 = 0x01000000u,
+    AUDIO_FORMAT_AMR_NB              = 0x02000000u,
+    AUDIO_FORMAT_AMR_WB              = 0x03000000u,
+    AUDIO_FORMAT_AAC                 = 0x04000000u,
+    AUDIO_FORMAT_HE_AAC_V1           = 0x05000000u,
+    AUDIO_FORMAT_HE_AAC_V2           = 0x06000000u,
+    AUDIO_FORMAT_VORBIS              = 0x07000000u,
+    AUDIO_FORMAT_OPUS                = 0x08000000u,
+    AUDIO_FORMAT_AC3                 = 0x09000000u,
+    AUDIO_FORMAT_E_AC3               = 0x0A000000u,
+    AUDIO_FORMAT_DTS                 = 0x0B000000u,
+    AUDIO_FORMAT_DTS_HD              = 0x0C000000u,
+    AUDIO_FORMAT_IEC61937            = 0x0D000000u,
+    AUDIO_FORMAT_DOLBY_TRUEHD        = 0x0E000000u,
+    AUDIO_FORMAT_EVRC                = 0x10000000u,
+    AUDIO_FORMAT_EVRCB               = 0x11000000u,
+    AUDIO_FORMAT_EVRCWB              = 0x12000000u,
+    AUDIO_FORMAT_EVRCNW              = 0x13000000u,
+    AUDIO_FORMAT_AAC_ADIF            = 0x14000000u,
+    AUDIO_FORMAT_WMA                 = 0x15000000u,
+    AUDIO_FORMAT_WMA_PRO             = 0x16000000u,
+    AUDIO_FORMAT_AMR_WB_PLUS         = 0x17000000u,
+    AUDIO_FORMAT_MP2                 = 0x18000000u,
+    AUDIO_FORMAT_QCELP               = 0x19000000u,
+    AUDIO_FORMAT_DSD                 = 0x1A000000u,
+    AUDIO_FORMAT_FLAC                = 0x1B000000u,
+    AUDIO_FORMAT_ALAC                = 0x1C000000u,
+    AUDIO_FORMAT_APE                 = 0x1D000000u,
+    AUDIO_FORMAT_AAC_ADTS            = 0x1E000000u,
+    AUDIO_FORMAT_SBC                 = 0x1F000000u,
+    AUDIO_FORMAT_APTX                = 0x20000000u,
+    AUDIO_FORMAT_APTX_HD             = 0x21000000u,
+    AUDIO_FORMAT_AC4                 = 0x22000000u,
+    AUDIO_FORMAT_LDAC                = 0x23000000u,
+    AUDIO_FORMAT_MAT                 = 0x24000000u,
+    AUDIO_FORMAT_MAIN_MASK           = 0xFF000000u,
+    AUDIO_FORMAT_SUB_MASK            = 0x00FFFFFFu,
+
+    /* Subformats */
+    AUDIO_FORMAT_PCM_SUB_16_BIT        = 0x1u,
+    AUDIO_FORMAT_PCM_SUB_8_BIT         = 0x2u,
+    AUDIO_FORMAT_PCM_SUB_32_BIT        = 0x3u,
+    AUDIO_FORMAT_PCM_SUB_8_24_BIT      = 0x4u,
+    AUDIO_FORMAT_PCM_SUB_FLOAT         = 0x5u,
+    AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED = 0x6u,
+
+    AUDIO_FORMAT_MP3_SUB_NONE          = 0x0u,
+
+    AUDIO_FORMAT_AMR_SUB_NONE          = 0x0u,
+
+    AUDIO_FORMAT_AAC_SUB_MAIN          = 0x1u,
+    AUDIO_FORMAT_AAC_SUB_LC            = 0x2u,
+    AUDIO_FORMAT_AAC_SUB_SSR           = 0x4u,
+    AUDIO_FORMAT_AAC_SUB_LTP           = 0x8u,
+    AUDIO_FORMAT_AAC_SUB_HE_V1         = 0x10u,
+    AUDIO_FORMAT_AAC_SUB_SCALABLE      = 0x20u,
+    AUDIO_FORMAT_AAC_SUB_ERLC          = 0x40u,
+    AUDIO_FORMAT_AAC_SUB_LD            = 0x80u,
+    AUDIO_FORMAT_AAC_SUB_HE_V2         = 0x100u,
+    AUDIO_FORMAT_AAC_SUB_ELD           = 0x200u,
+    AUDIO_FORMAT_AAC_SUB_XHE           = 0x300u,
+
+    AUDIO_FORMAT_VORBIS_SUB_NONE       = 0x0u,
+
+    AUDIO_FORMAT_E_AC3_SUB_JOC         = 0x1u,
+
+    AUDIO_FORMAT_MAT_SUB_1_0           = 0x1u,
+    AUDIO_FORMAT_MAT_SUB_2_0           = 0x2u,
+    AUDIO_FORMAT_MAT_SUB_2_1           = 0x3u,
+
+    /* Aliases */
+    AUDIO_FORMAT_PCM_16_BIT            = 0x1u,        // (PCM | PCM_SUB_16_BIT)
+    AUDIO_FORMAT_PCM_8_BIT             = 0x2u,        // (PCM | PCM_SUB_8_BIT)
+    AUDIO_FORMAT_PCM_32_BIT            = 0x3u,        // (PCM | PCM_SUB_32_BIT)
+    AUDIO_FORMAT_PCM_8_24_BIT          = 0x4u,        // (PCM | PCM_SUB_8_24_BIT)
+    AUDIO_FORMAT_PCM_FLOAT             = 0x5u,        // (PCM | PCM_SUB_FLOAT)
+    AUDIO_FORMAT_PCM_24_BIT_PACKED     = 0x6u,        // (PCM | PCM_SUB_24_BIT_PACKED)
+    AUDIO_FORMAT_AAC_MAIN              = 0x4000001u,  // (AAC | AAC_SUB_MAIN)
+    AUDIO_FORMAT_AAC_LC                = 0x4000002u,  // (AAC | AAC_SUB_LC)
+    AUDIO_FORMAT_AAC_SSR               = 0x4000004u,  // (AAC | AAC_SUB_SSR)
+    AUDIO_FORMAT_AAC_LTP               = 0x4000008u,  // (AAC | AAC_SUB_LTP)
+    AUDIO_FORMAT_AAC_HE_V1             = 0x4000010u,  // (AAC | AAC_SUB_HE_V1)
+    AUDIO_FORMAT_AAC_SCALABLE          = 0x4000020u,  // (AAC | AAC_SUB_SCALABLE)
+    AUDIO_FORMAT_AAC_ERLC              = 0x4000040u,  // (AAC | AAC_SUB_ERLC)
+    AUDIO_FORMAT_AAC_LD                = 0x4000080u,  // (AAC | AAC_SUB_LD)
+    AUDIO_FORMAT_AAC_HE_V2             = 0x4000100u,  // (AAC | AAC_SUB_HE_V2)
+    AUDIO_FORMAT_AAC_ELD               = 0x4000200u,  // (AAC | AAC_SUB_ELD)
+    AUDIO_FORMAT_AAC_XHE               = 0x4000300u,  // (AAC | AAC_SUB_XHE)
+    AUDIO_FORMAT_AAC_ADTS_MAIN         = 0x1e000001u, // (AAC_ADTS | AAC_SUB_MAIN)
+    AUDIO_FORMAT_AAC_ADTS_LC           = 0x1e000002u, // (AAC_ADTS | AAC_SUB_LC)
+    AUDIO_FORMAT_AAC_ADTS_SSR          = 0x1e000004u, // (AAC_ADTS | AAC_SUB_SSR)
+    AUDIO_FORMAT_AAC_ADTS_LTP          = 0x1e000008u, // (AAC_ADTS | AAC_SUB_LTP)
+    AUDIO_FORMAT_AAC_ADTS_HE_V1        = 0x1e000010u, // (AAC_ADTS | AAC_SUB_HE_V1)
+    AUDIO_FORMAT_AAC_ADTS_SCALABLE     = 0x1e000020u, // (AAC_ADTS | AAC_SUB_SCALABLE)
+    AUDIO_FORMAT_AAC_ADTS_ERLC         = 0x1e000040u, // (AAC_ADTS | AAC_SUB_ERLC)
+    AUDIO_FORMAT_AAC_ADTS_LD           = 0x1e000080u, // (AAC_ADTS | AAC_SUB_LD)
+    AUDIO_FORMAT_AAC_ADTS_HE_V2        = 0x1e000100u, // (AAC_ADTS | AAC_SUB_HE_V2)
+    AUDIO_FORMAT_AAC_ADTS_ELD          = 0x1e000200u, // (AAC_ADTS | AAC_SUB_ELD)
+    AUDIO_FORMAT_AAC_ADTS_XHE          = 0x1e000300u, // (AAC_ADTS | AAC_SUB_XHE)
+    AUDIO_FORMAT_E_AC3_JOC             = 0xA000001u,  // (E_AC3 | E_AC3_SUB_JOC)
+    AUDIO_FORMAT_MAT_1_0               = 0x24000001u, // (MAT | MAT_SUB_1_0)
+    AUDIO_FORMAT_MAT_2_0               = 0x24000002u, // (MAT | MAT_SUB_2_0)
+    AUDIO_FORMAT_MAT_2_1               = 0x24000003u, // (MAT | MAT_SUB_2_1)
+} audio_format_t;
+
+enum {
+    FCC_2 = 2,
+    FCC_8 = 8,
+};
+
+enum {
+    AUDIO_CHANNEL_REPRESENTATION_POSITION   = 0x0u,
+    AUDIO_CHANNEL_REPRESENTATION_INDEX      = 0x2u,
+    AUDIO_CHANNEL_NONE                      = 0x0u,
+    AUDIO_CHANNEL_INVALID                   = 0xC0000000u,
+
+    AUDIO_CHANNEL_OUT_FRONT_LEFT            = 0x1u,
+    AUDIO_CHANNEL_OUT_FRONT_RIGHT           = 0x2u,
+    AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4u,
+    AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8u,
+    AUDIO_CHANNEL_OUT_BACK_LEFT             = 0x10u,
+    AUDIO_CHANNEL_OUT_BACK_RIGHT            = 0x20u,
+    AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER  = 0x40u,
+    AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80u,
+    AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100u,
+    AUDIO_CHANNEL_OUT_SIDE_LEFT             = 0x200u,
+    AUDIO_CHANNEL_OUT_SIDE_RIGHT            = 0x400u,
+    AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800u,
+    AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT        = 0x1000u,
+    AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000u,
+    AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT       = 0x4000u,
+    AUDIO_CHANNEL_OUT_TOP_BACK_LEFT         = 0x8000u,
+    AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000u,
+    AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT        = 0x20000u,
+    AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT         = 0x40000u,
+    AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT        = 0x80000u,
+    AUDIO_CHANNEL_OUT_MONO                  = 0x1u,     // OUT_FRONT_LEFT
+    AUDIO_CHANNEL_OUT_STEREO                = 0x3u,     // OUT_FRONT_LEFT | OUT_FRONT_RIGHT
+    AUDIO_CHANNEL_OUT_2POINT1               = 0xBu,     // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_LOW_FREQUENCY
+    AUDIO_CHANNEL_OUT_2POINT0POINT2         = 0xC0003u, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT
+    AUDIO_CHANNEL_OUT_2POINT1POINT2         = 0xC000Bu, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT | OUT_LOW_FREQUENCY
+    AUDIO_CHANNEL_OUT_3POINT0POINT2         = 0xC0007u, // OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT
+    AUDIO_CHANNEL_OUT_3POINT1POINT2         = 0xC000Fu, // OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT | OUT_LOW_FREQUENCY
+    AUDIO_CHANNEL_OUT_QUAD                  = 0x33u,    // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_BACK_LEFT | OUT_BACK_RIGHT
+    AUDIO_CHANNEL_OUT_QUAD_BACK             = 0x33u,    // OUT_QUAD
+    AUDIO_CHANNEL_OUT_QUAD_SIDE             = 0x603u,   // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_SIDE_LEFT | OUT_SIDE_RIGHT
+    AUDIO_CHANNEL_OUT_SURROUND              = 0x107u,   // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_BACK_CENTER
+    AUDIO_CHANNEL_OUT_PENTA                 = 0x37u,    // OUT_QUAD | OUT_FRONT_CENTER
+    AUDIO_CHANNEL_OUT_5POINT1               = 0x3Fu,    // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_BACK_LEFT | OUT_BACK_RIGHT
+    AUDIO_CHANNEL_OUT_5POINT1_BACK          = 0x3Fu,    // OUT_5POINT1
+    AUDIO_CHANNEL_OUT_5POINT1_SIDE          = 0x60Fu,   // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_SIDE_LEFT | OUT_SIDE_RIGHT
+    AUDIO_CHANNEL_OUT_5POINT1POINT2         = 0xC003Fu, // OUT_5POINT1 | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT
+    AUDIO_CHANNEL_OUT_5POINT1POINT4         = 0x2D03Fu, // OUT_5POINT1 | OUT_TOP_FRONT_LEFT | OUT_TOP_FRONT_RIGHT | OUT_TOP_BACK_LEFT | OUT_TOP_BACK_RIGHT
+    AUDIO_CHANNEL_OUT_6POINT1               = 0x13Fu,   // 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               = 0x63Fu,   // 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_7POINT1POINT2         = 0xC063Fu, // OUT_7POINT1 | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT
+    AUDIO_CHANNEL_OUT_7POINT1POINT4         = 0x2D63Fu, // OUT_7POINT1 | OUT_TOP_FRONT_LEFT | OUT_TOP_FRONT_RIGHT | OUT_TOP_BACK_LEFT | OUT_TOP_BACK_RIGHT
+
+    AUDIO_CHANNEL_IN_LEFT                   = 0x4u,
+    AUDIO_CHANNEL_IN_RIGHT                  = 0x8u,
+    AUDIO_CHANNEL_IN_FRONT                  = 0x10u,
+    AUDIO_CHANNEL_IN_BACK                   = 0x20u,
+    AUDIO_CHANNEL_IN_LEFT_PROCESSED         = 0x40u,
+    AUDIO_CHANNEL_IN_RIGHT_PROCESSED        = 0x80u,
+    AUDIO_CHANNEL_IN_FRONT_PROCESSED        = 0x100u,
+    AUDIO_CHANNEL_IN_BACK_PROCESSED         = 0x200u,
+    AUDIO_CHANNEL_IN_PRESSURE               = 0x400u,
+    AUDIO_CHANNEL_IN_X_AXIS                 = 0x800u,
+    AUDIO_CHANNEL_IN_Y_AXIS                 = 0x1000u,
+    AUDIO_CHANNEL_IN_Z_AXIS                 = 0x2000u,
+    AUDIO_CHANNEL_IN_BACK_LEFT              = 0x10000u,
+    AUDIO_CHANNEL_IN_BACK_RIGHT             = 0x20000u,
+    AUDIO_CHANNEL_IN_CENTER                 = 0x40000u,
+    AUDIO_CHANNEL_IN_LOW_FREQUENCY          = 0x100000u,
+    AUDIO_CHANNEL_IN_TOP_LEFT               = 0x200000u,
+    AUDIO_CHANNEL_IN_TOP_RIGHT              = 0x400000u,
+    AUDIO_CHANNEL_IN_VOICE_UPLINK           = 0x4000u,
+    AUDIO_CHANNEL_IN_VOICE_DNLINK           = 0x8000u,
+    AUDIO_CHANNEL_IN_MONO                   = 0x10u,     // IN_FRONT
+    AUDIO_CHANNEL_IN_STEREO                 = 0xCu,      // IN_LEFT | IN_RIGHT
+    AUDIO_CHANNEL_IN_FRONT_BACK             = 0x30u,     // IN_FRONT | IN_BACK
+    AUDIO_CHANNEL_IN_6                      = 0xFCu,     // IN_LEFT | IN_RIGHT | IN_FRONT | IN_BACK | IN_LEFT_PROCESSED | IN_RIGHT_PROCESSED
+    AUDIO_CHANNEL_IN_2POINT0POINT2          = 0x60000Cu, // IN_LEFT | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT
+    AUDIO_CHANNEL_IN_2POINT1POINT2          = 0x70000Cu, // IN_LEFT | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT | IN_LOW_FREQUENCY
+    AUDIO_CHANNEL_IN_3POINT0POINT2          = 0x64000Cu, // IN_LEFT | IN_CENTER | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT
+    AUDIO_CHANNEL_IN_3POINT1POINT2          = 0x74000Cu, // IN_LEFT | IN_CENTER | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT | IN_LOW_FREQUENCY
+    AUDIO_CHANNEL_IN_5POINT1                = 0x17000Cu, // IN_LEFT | IN_CENTER | IN_RIGHT | IN_BACK_LEFT | IN_BACK_RIGHT | IN_LOW_FREQUENCY
+    AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO      = 0x4010u,   // IN_VOICE_UPLINK | IN_MONO
+    AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO      = 0x8010u,   // IN_VOICE_DNLINK | IN_MONO
+    AUDIO_CHANNEL_IN_VOICE_CALL_MONO        = 0xC010u,   // IN_VOICE_UPLINK_MONO | IN_VOICE_DNLINK_MONO
+
+    AUDIO_CHANNEL_COUNT_MAX                 = 30u,
+    AUDIO_CHANNEL_INDEX_HDR                 = 0x80000000u, // REPRESENTATION_INDEX << COUNT_MAX
+    AUDIO_CHANNEL_INDEX_MASK_1              = 0x80000001u, // INDEX_HDR | (1 << 1) - 1
+    AUDIO_CHANNEL_INDEX_MASK_2              = 0x80000003u, // INDEX_HDR | (1 << 2) - 1
+    AUDIO_CHANNEL_INDEX_MASK_3              = 0x80000007u, // INDEX_HDR | (1 << 3) - 1
+    AUDIO_CHANNEL_INDEX_MASK_4              = 0x8000000Fu, // INDEX_HDR | (1 << 4) - 1
+    AUDIO_CHANNEL_INDEX_MASK_5              = 0x8000001Fu, // INDEX_HDR | (1 << 5) - 1
+    AUDIO_CHANNEL_INDEX_MASK_6              = 0x8000003Fu, // INDEX_HDR | (1 << 6) - 1
+    AUDIO_CHANNEL_INDEX_MASK_7              = 0x8000007Fu, // INDEX_HDR | (1 << 7) - 1
+    AUDIO_CHANNEL_INDEX_MASK_8              = 0x800000FFu, // INDEX_HDR | (1 << 8) - 1
+};
+
+typedef enum {
+#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
+    AUDIO_MODE_INVALID = -2, // (-2)
+    AUDIO_MODE_CURRENT = -1, // (-1)
+#endif // AUDIO_NO_SYSTEM_DECLARATIONS
+    AUDIO_MODE_NORMAL = 0,
+    AUDIO_MODE_RINGTONE = 1,
+    AUDIO_MODE_IN_CALL = 2,
+    AUDIO_MODE_IN_COMMUNICATION = 3,
+} audio_mode_t;
+
+enum {
+    AUDIO_DEVICE_NONE                          = 0x0u,
+    AUDIO_DEVICE_BIT_IN                        = 0x80000000u,
+    AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000u,
+
+    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1u,
+    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2u,
+    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4u,
+    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8u,
+    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10u,
+    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20u,
+    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT      = 0x40u,
+    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP            = 0x80u,
+    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100u,
+    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER    = 0x200u,
+    AUDIO_DEVICE_OUT_AUX_DIGITAL               = 0x400u,
+    AUDIO_DEVICE_OUT_HDMI                      = 0x400u,      // OUT_AUX_DIGITAL
+    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET         = 0x800u,
+    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET         = 0x1000u,
+    AUDIO_DEVICE_OUT_USB_ACCESSORY             = 0x2000u,
+    AUDIO_DEVICE_OUT_USB_DEVICE                = 0x4000u,
+    AUDIO_DEVICE_OUT_REMOTE_SUBMIX             = 0x8000u,
+    AUDIO_DEVICE_OUT_TELEPHONY_TX              = 0x10000u,
+    AUDIO_DEVICE_OUT_LINE                      = 0x20000u,
+    AUDIO_DEVICE_OUT_HDMI_ARC                  = 0x40000u,
+    AUDIO_DEVICE_OUT_SPDIF                     = 0x80000u,
+    AUDIO_DEVICE_OUT_FM                        = 0x100000u,
+    AUDIO_DEVICE_OUT_AUX_LINE                  = 0x200000u,
+    AUDIO_DEVICE_OUT_SPEAKER_SAFE              = 0x400000u,
+    AUDIO_DEVICE_OUT_IP                        = 0x800000u,
+    AUDIO_DEVICE_OUT_BUS                       = 0x1000000u,
+    AUDIO_DEVICE_OUT_PROXY                     = 0x2000000u,
+    AUDIO_DEVICE_OUT_USB_HEADSET               = 0x4000000u,
+    AUDIO_DEVICE_OUT_HEARING_AID               = 0x8000000u,
+    AUDIO_DEVICE_OUT_ECHO_CANCELLER            = 0x10000000u,
+    AUDIO_DEVICE_OUT_DEFAULT                   = 0x40000000u, // BIT_DEFAULT
+
+    AUDIO_DEVICE_IN_COMMUNICATION              = 0x80000001u, // BIT_IN | 0x1
+    AUDIO_DEVICE_IN_AMBIENT                    = 0x80000002u, // BIT_IN | 0x2
+    AUDIO_DEVICE_IN_BUILTIN_MIC                = 0x80000004u, // BIT_IN | 0x4
+    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET      = 0x80000008u, // BIT_IN | 0x8
+    AUDIO_DEVICE_IN_WIRED_HEADSET              = 0x80000010u, // BIT_IN | 0x10
+    AUDIO_DEVICE_IN_AUX_DIGITAL                = 0x80000020u, // BIT_IN | 0x20
+    AUDIO_DEVICE_IN_HDMI                       = 0x80000020u, // IN_AUX_DIGITAL
+    AUDIO_DEVICE_IN_VOICE_CALL                 = 0x80000040u, // BIT_IN | 0x40
+    AUDIO_DEVICE_IN_TELEPHONY_RX               = 0x80000040u, // IN_VOICE_CALL
+    AUDIO_DEVICE_IN_BACK_MIC                   = 0x80000080u, // BIT_IN | 0x80
+    AUDIO_DEVICE_IN_REMOTE_SUBMIX              = 0x80000100u, // BIT_IN | 0x100
+    AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET          = 0x80000200u, // BIT_IN | 0x200
+    AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET          = 0x80000400u, // BIT_IN | 0x400
+    AUDIO_DEVICE_IN_USB_ACCESSORY              = 0x80000800u, // BIT_IN | 0x800
+    AUDIO_DEVICE_IN_USB_DEVICE                 = 0x80001000u, // BIT_IN | 0x1000
+    AUDIO_DEVICE_IN_FM_TUNER                   = 0x80002000u, // BIT_IN | 0x2000
+    AUDIO_DEVICE_IN_TV_TUNER                   = 0x80004000u, // BIT_IN | 0x4000
+    AUDIO_DEVICE_IN_LINE                       = 0x80008000u, // BIT_IN | 0x8000
+    AUDIO_DEVICE_IN_SPDIF                      = 0x80010000u, // BIT_IN | 0x10000
+    AUDIO_DEVICE_IN_BLUETOOTH_A2DP             = 0x80020000u, // BIT_IN | 0x20000
+    AUDIO_DEVICE_IN_LOOPBACK                   = 0x80040000u, // BIT_IN | 0x40000
+    AUDIO_DEVICE_IN_IP                         = 0x80080000u, // BIT_IN | 0x80000
+    AUDIO_DEVICE_IN_BUS                        = 0x80100000u, // BIT_IN | 0x100000
+    AUDIO_DEVICE_IN_PROXY                      = 0x81000000u, // BIT_IN | 0x1000000
+    AUDIO_DEVICE_IN_USB_HEADSET                = 0x82000000u, // BIT_IN | 0x2000000
+    AUDIO_DEVICE_IN_BLUETOOTH_BLE              = 0x84000000u, // BIT_IN | 0x4000000
+    AUDIO_DEVICE_IN_DEFAULT                    = 0xC0000000u, // BIT_IN | BIT_DEFAULT
+};
+
+typedef enum {
+    AUDIO_OUTPUT_FLAG_NONE             = 0x0,
+    AUDIO_OUTPUT_FLAG_DIRECT           = 0x1,
+    AUDIO_OUTPUT_FLAG_PRIMARY          = 0x2,
+    AUDIO_OUTPUT_FLAG_FAST             = 0x4,
+    AUDIO_OUTPUT_FLAG_DEEP_BUFFER      = 0x8,
+    AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10,
+    AUDIO_OUTPUT_FLAG_NON_BLOCKING     = 0x20,
+    AUDIO_OUTPUT_FLAG_HW_AV_SYNC       = 0x40,
+    AUDIO_OUTPUT_FLAG_TTS              = 0x80,
+    AUDIO_OUTPUT_FLAG_RAW              = 0x100,
+    AUDIO_OUTPUT_FLAG_SYNC             = 0x200,
+    AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO  = 0x400,
+    AUDIO_OUTPUT_FLAG_DIRECT_PCM       = 0x2000,
+    AUDIO_OUTPUT_FLAG_MMAP_NOIRQ       = 0x4000,
+    AUDIO_OUTPUT_FLAG_VOIP_RX          = 0x8000,
+    AUDIO_OUTPUT_FLAG_INCALL_MUSIC     = 0x10000,
+} audio_output_flags_t;
+
+typedef enum {
+    AUDIO_INPUT_FLAG_NONE       = 0x0,
+    AUDIO_INPUT_FLAG_FAST       = 0x1,
+    AUDIO_INPUT_FLAG_HW_HOTWORD = 0x2,
+    AUDIO_INPUT_FLAG_RAW        = 0x4,
+    AUDIO_INPUT_FLAG_SYNC       = 0x8,
+    AUDIO_INPUT_FLAG_MMAP_NOIRQ = 0x10,
+    AUDIO_INPUT_FLAG_VOIP_TX    = 0x20,
+    AUDIO_INPUT_FLAG_HW_AV_SYNC = 0x40,
+#ifndef AUDIO_NO_SYSTEM_DECLARATIONS  // TODO: Expose at HAL interface, remove FRAMEWORK_FLAGS mask
+    AUDIO_INPUT_FLAG_DIRECT     = 0x80,
+    AUDIO_INPUT_FRAMEWORK_FLAGS = AUDIO_INPUT_FLAG_DIRECT,
+#endif
+} 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,
+#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
+    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7,
+    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8,
+    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9,
+    AUDIO_USAGE_NOTIFICATION_EVENT = 10,
+#endif // AUDIO_NO_SYSTEM_DECLARATIONS
+    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_t;
+
+typedef enum {
+    AUDIO_CONTENT_TYPE_UNKNOWN = 0u,
+    AUDIO_CONTENT_TYPE_SPEECH = 1u,
+    AUDIO_CONTENT_TYPE_MUSIC = 2u,
+    AUDIO_CONTENT_TYPE_MOVIE = 3u,
+    AUDIO_CONTENT_TYPE_SONIFICATION = 4u,
+} audio_content_type_t;
+
+enum {
+    AUDIO_GAIN_MODE_JOINT    = 0x1u,
+    AUDIO_GAIN_MODE_CHANNELS = 0x2u,
+    AUDIO_GAIN_MODE_RAMP     = 0x4u,
+};
+
+typedef enum {
+    AUDIO_PORT_ROLE_NONE = 0,
+    AUDIO_PORT_ROLE_SOURCE = 1, // (::android::hardware::audio::common::V4_0::AudioPortRole.NONE implicitly + 1)
+    AUDIO_PORT_ROLE_SINK = 2, // (::android::hardware::audio::common::V4_0::AudioPortRole.SOURCE implicitly + 1)
+} audio_port_role_t;
+
+typedef enum {
+    AUDIO_PORT_TYPE_NONE = 0,
+    AUDIO_PORT_TYPE_DEVICE = 1, // (::android::hardware::audio::common::V4_0::AudioPortType.NONE implicitly + 1)
+    AUDIO_PORT_TYPE_MIX = 2, // (::android::hardware::audio::common::V4_0::AudioPortType.DEVICE implicitly + 1)
+    AUDIO_PORT_TYPE_SESSION = 3, // (::android::hardware::audio::common::V4_0::AudioPortType.MIX implicitly + 1)
+} audio_port_type_t;
+
+enum {
+    AUDIO_PORT_CONFIG_SAMPLE_RATE  = 0x1u,
+    AUDIO_PORT_CONFIG_CHANNEL_MASK = 0x2u,
+    AUDIO_PORT_CONFIG_FORMAT       = 0x4u,
+    AUDIO_PORT_CONFIG_GAIN         = 0x8u,
+#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
+    AUDIO_PORT_CONFIG_FLAGS        = 0x10u,  // Absent from AudioPortConfigMask, framework only.
+#endif
+};
+
+typedef enum {
+    AUDIO_LATENCY_LOW = 0,
+    AUDIO_LATENCY_NORMAL = 1, // (::android::hardware::audio::common::V4_0::AudioMixLatencyClass.LOW implicitly + 1)
+} audio_mix_latency_class_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_COMMON_V4_0_EXPORTED_CONSTANTS_H_
diff --git a/include/system/audio.h b/include/system/audio.h
new file mode 100644
index 0000000..2295c3d
--- /dev/null
+++ b/include/system/audio.h
@@ -0,0 +1,1390 @@
+/*
+ * 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.
+ */
+
+
+#ifndef ANDROID_AUDIO_CORE_H
+#define ANDROID_AUDIO_CORE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <cutils/bitops.h>
+
+#include "audio-base.h"
+#include "audio-base-utils.h"
+
+__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;
+
+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,
+    AUDIO_FLAG_BEACON                     = 0x8,
+    AUDIO_FLAG_HW_AV_SYNC                 = 0x10,
+    AUDIO_FLAG_HW_HOTWORD                 = 0x20,
+    AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY = 0x40,
+    AUDIO_FLAG_BYPASS_MUTE                = 0x80,
+    AUDIO_FLAG_LOW_LATENCY                = 0x100,
+    AUDIO_FLAG_DEEP_BUFFER                = 0x200,
+};
+
+/* Audio attributes */
+#define AUDIO_ATTRIBUTES_TAGS_MAX_SIZE 256
+typedef struct {
+    audio_content_type_t content_type;
+    audio_usage_t        usage;
+    audio_source_t       source;
+    audio_flags_mask_t   flags;
+    char                 tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE]; /* UTF8 */
+} __attribute__((packed)) audio_attributes_t; // sent through Binder;
+
+/* 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
+ * in a different namespace than AudioFlinger unique IDs.
+ */
+typedef int audio_unique_id_t;
+
+/* Possible uses for an audio_unique_id_t */
+typedef enum {
+    AUDIO_UNIQUE_ID_USE_UNSPECIFIED = 0,
+    AUDIO_UNIQUE_ID_USE_SESSION = 1,    // for allocated sessions, not special AUDIO_SESSION_*
+    AUDIO_UNIQUE_ID_USE_MODULE = 2,
+    AUDIO_UNIQUE_ID_USE_EFFECT = 3,
+    AUDIO_UNIQUE_ID_USE_PATCH = 4,
+    AUDIO_UNIQUE_ID_USE_OUTPUT = 5,
+    AUDIO_UNIQUE_ID_USE_INPUT = 6,
+    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;
+
+/* Return the use of an audio_unique_id_t */
+static inline audio_unique_id_use_t audio_unique_id_get_use(audio_unique_id_t id)
+{
+    return (audio_unique_id_use_t) (id & AUDIO_UNIQUE_ID_USE_MASK);
+}
+
+/* Reserved audio_unique_id_t values.  FIXME: not a complete list. */
+#define AUDIO_UNIQUE_ID_ALLOCATE AUDIO_SESSION_ALLOCATE
+
+/* 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.
+ *
+ * audio_channel_mask_t is an opaque type and its internal layout should not
+ * be assumed as it may change in the future.
+ * Instead, always use the functions declared in this header to examine.
+ *
+ * These are the current representations:
+ *
+ *   AUDIO_CHANNEL_REPRESENTATION_POSITION
+ *     is a channel mask representation for position assignment.
+ *     Each low-order bit corresponds to the spatial position of a transducer (output),
+ *     or interpretation of channel (input).
+ *     The user of a channel mask needs to know the context of whether it is for output or input.
+ *     The constants AUDIO_CHANNEL_OUT_* or AUDIO_CHANNEL_IN_* apply to the bits portion.
+ *     It is not permitted for no bits to be set.
+ *
+ *   AUDIO_CHANNEL_REPRESENTATION_INDEX
+ *     is a channel mask representation for index assignment.
+ *     Each low-order bit corresponds to a selected channel.
+ *     There is no platform interpretation of the various bits.
+ *     There is no concept of output or input.
+ *     It is not permitted for no bits to be set.
+ *
+ * All other representations are reserved for future use.
+ *
+ * Warning: current representation distinguishes between input and output, but this will not the be
+ * case in future revisions of the platform. Wherever there is an ambiguity between input and output
+ * that is currently resolved by checking the channel mask, the implementer should look for ways to
+ * fix it with additional information outside of the mask.
+ */
+typedef uint32_t audio_channel_mask_t;
+
+/* log(2) of maximum number of representations, not part of public API */
+#define AUDIO_CHANNEL_REPRESENTATION_LOG2   2
+
+/* 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)
+{
+    // The right shift should be sufficient, but also "and" for safety in case mask is not 32 bits
+    return (audio_channel_representation_t)
+            ((channel >> AUDIO_CHANNEL_COUNT_MAX) & ((1 << AUDIO_CHANNEL_REPRESENTATION_LOG2) - 1));
+}
+
+/* Returns true if the channel mask is valid,
+ * or returns false for AUDIO_CHANNEL_NONE, AUDIO_CHANNEL_INVALID, and other invalid values.
+ * This function is unable to determine whether a channel mask for position assignment
+ * is invalid because an output mask has an invalid output bit set,
+ * or because an input mask has an invalid input bit set.
+ * All other APIs that take a channel mask assume that it is valid.
+ */
+static inline bool audio_channel_mask_is_valid(audio_channel_mask_t channel)
+{
+    uint32_t bits = audio_channel_mask_get_bits(channel);
+    audio_channel_representation_t representation = audio_channel_mask_get_representation(channel);
+    switch (representation) {
+    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+        break;
+    default:
+        bits = 0;
+        break;
+    }
+    return bits != 0;
+}
+
+/* Not part of public API */
+static inline audio_channel_mask_t audio_channel_mask_from_representation_and_bits(
+        audio_channel_representation_t representation, uint32_t bits)
+{
+    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,
+};
+
+/* This enum is deprecated */
+typedef enum {
+    AUDIO_IN_ACOUSTICS_NONE          = 0,
+    AUDIO_IN_ACOUSTICS_AGC_ENABLE    = 0x0001,
+    AUDIO_IN_ACOUSTICS_AGC_DISABLE   = 0,
+    AUDIO_IN_ACOUSTICS_NS_ENABLE     = 0x0002,
+    AUDIO_IN_ACOUSTICS_NS_DISABLE    = 0,
+    AUDIO_IN_ACOUSTICS_TX_IIR_ENABLE = 0x0004,
+    AUDIO_IN_ACOUSTICS_TX_DISABLE    = 0,
+} audio_in_acoustics_t;
+
+typedef uint32_t audio_devices_t;
+/**
+ * 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.
+ */
+#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.
+ */
+#define AUDIO_DEVICE_IN_STUB AUDIO_DEVICE_IN_DEFAULT
+
+/* Additional information about compressed streams offloaded to
+ * hardware playback
+ * The version and size fields must be initialized by the caller by using
+ * one of the constants defined here.
+ * Must be aligned to transmit as raw memory through Binder.
+ */
+typedef struct {
+    uint16_t version;                   // version of the info structure
+    uint16_t size;                      // total size of the structure including version and size
+    uint32_t sample_rate;               // sample rate in Hz
+    audio_channel_mask_t channel_mask;  // channel mask
+    audio_format_t format;              // audio format
+    audio_stream_type_t stream_type;    // stream type
+    uint32_t bit_rate;                  // bit rate in bits per second
+    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;
+} __attribute__((aligned(8))) audio_offload_info_t;
+
+#define AUDIO_MAKE_OFFLOAD_INFO_VERSION(maj,min) \
+            ((((maj) & 0xff) << 8) | ((min) & 0xff))
+
+#define AUDIO_OFFLOAD_INFO_VERSION_0_1 AUDIO_MAKE_OFFLOAD_INFO_VERSION(0, 1)
+#define AUDIO_OFFLOAD_INFO_VERSION_CURRENT AUDIO_OFFLOAD_INFO_VERSION_0_1
+
+static const audio_offload_info_t AUDIO_INFO_INITIALIZER = {
+    /* .version = */ AUDIO_OFFLOAD_INFO_VERSION_CURRENT,
+    /* .size = */ sizeof(audio_offload_info_t),
+    /* .sample_rate = */ 0,
+    /* .channel_mask = */ 0,
+    /* .format = */ AUDIO_FORMAT_DEFAULT,
+    /* .stream_type = */ AUDIO_STREAM_VOICE_CALL,
+    /* .bit_rate = */ 0,
+    /* .duration_us = */ 0,
+    /* .has_video = */ false,
+    /* .is_streaming = */ false,
+    /* .bit_width = */ 16,
+    /* .offload_buffer_size = */ 0,
+    /* .usage = */ AUDIO_USAGE_UNKNOWN
+};
+
+/* common audio stream configuration parameters
+ * You should memset() the entire structure to zero before use to
+ * ensure forward compatibility
+ * Must be aligned to transmit as raw memory through Binder.
+ */
+struct __attribute__((aligned(8))) audio_config {
+    uint32_t sample_rate;
+    audio_channel_mask_t channel_mask;
+    audio_format_t  format;
+    audio_offload_info_t offload_info;
+    uint32_t frame_count;
+};
+typedef struct audio_config audio_config_t;
+
+static const audio_config_t AUDIO_CONFIG_INITIALIZER = {
+    /* .sample_rate = */ 0,
+    /* .channel_mask = */ AUDIO_CHANNEL_NONE,
+    /* .format = */ AUDIO_FORMAT_DEFAULT,
+    /* .offload_info = */ {
+        /* .version = */ AUDIO_OFFLOAD_INFO_VERSION_CURRENT,
+        /* .size = */ sizeof(audio_offload_info_t),
+        /* .sample_rate = */ 0,
+        /* .channel_mask = */ 0,
+        /* .format = */ AUDIO_FORMAT_DEFAULT,
+        /* .stream_type = */ AUDIO_STREAM_VOICE_CALL,
+        /* .bit_rate = */ 0,
+        /* .duration_us = */ 0,
+        /* .has_video = */ false,
+        /* .is_streaming = */ false,
+        /* .bit_width = */ 16,
+        /* .offload_buffer_size = */ 0,
+        /* .usage = */ AUDIO_USAGE_UNKNOWN
+    },
+    /* .frame_count = */ 0,
+};
+
+struct audio_config_base {
+    uint32_t sample_rate;
+    audio_channel_mask_t channel_mask;
+    audio_format_t  format;
+};
+
+typedef struct audio_config_base audio_config_base_t;
+
+static const audio_config_base_t AUDIO_CONFIG_BASE_INITIALIZER = {
+    /* .sample_rate = */ 0,
+    /* .channel_mask = */ AUDIO_CHANNEL_NONE,
+    /* .format = */ AUDIO_FORMAT_DEFAULT
+};
+
+/* audio hw module handle functions or structures referencing a module */
+typedef int audio_module_handle_t;
+
+/******************************
+ *  Volume control
+ *****************************/
+
+/** 3 dB headroom are allowed on float samples (3db = 10^(3/20) = 1.412538).
+* See: https://developer.android.com/reference/android/media/AudioTrack.html#write(float[], int, int, int)
+*/
+#define FLOAT_NOMINAL_RANGE_HEADROOM 1.412538
+
+/* If the audio hardware supports gain control on some audio paths,
+ * the platform can expose them in the audio_policy.conf file. The audio HAL
+ * will then implement gain control functions that will use the following data
+ * structures. */
+
+typedef uint32_t audio_gain_mode_t;
+
+
+/* An audio_gain struct is a representation of a gain stage.
+ * A gain stage is always attached to an audio port. */
+struct audio_gain  {
+    audio_gain_mode_t    mode;          /* e.g. AUDIO_GAIN_MODE_JOINT */
+    audio_channel_mask_t channel_mask;  /* channels which gain an be controlled.
+                                           N/A if AUDIO_GAIN_MODE_CHANNELS is not supported */
+    int                  min_value;     /* minimum gain value in millibels */
+    int                  max_value;     /* maximum gain value in millibels */
+    int                  default_value; /* default gain value in millibels */
+    unsigned int         step_value;    /* gain step in millibels */
+    unsigned int         min_ramp_ms;   /* minimum ramp duration in ms */
+    unsigned int         max_ramp_ms;   /* maximum ramp duration in ms */
+};
+
+/* The gain configuration structure is used to get or set the gain values of a
+ * given port */
+struct audio_gain_config  {
+    int                  index;             /* index of the corresponding audio_gain in the
+                                               audio_port gains[] table */
+    audio_gain_mode_t    mode;              /* mode requested for this command */
+    audio_channel_mask_t channel_mask;      /* channels which gain value follows.
+                                               N/A in joint mode */
+
+    // note this "8" is not FCC_8, so it won't need to be changed for > 8 channels
+    int                  values[sizeof(audio_channel_mask_t) * 8]; /* gain values in millibels
+                                               for each channel ordered from LSb to MSb in
+                                               channel mask. The number of values is 1 in joint
+                                               mode or popcount(channel_mask) */
+    unsigned int         ramp_duration_ms; /* ramp duration in ms */
+};
+
+/******************************
+ *  Routing control
+ *****************************/
+
+/* Types defined here are used to describe an audio source or sink at internal
+ * framework interfaces (audio policy, patch panel) or at the audio HAL.
+ * Sink and sources are grouped in a concept of “audio port” representing an
+ * audio end point at the edge of the system managed by the module exposing
+ * the interface. */
+
+/* Each port has a unique ID or handle allocated by policy manager */
+typedef int audio_port_handle_t;
+
+/* the maximum length for the human-readable device name */
+#define AUDIO_PORT_MAX_NAME_LEN 128
+
+/* a union to store port configuration flags. Declared as a type so can be reused
+   in framework code */
+union audio_io_flags {
+    audio_input_flags_t  input;
+    audio_output_flags_t output;
+};
+
+/* maximum audio device address length */
+#define AUDIO_DEVICE_MAX_ADDRESS_LEN 32
+
+/* extension for audio port configuration structure when the audio port is a
+ * hardware device */
+struct audio_port_config_device_ext {
+    audio_module_handle_t hw_module;                /* module the device is attached to */
+    audio_devices_t       type;                     /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */
+    char                  address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; /* device address. "" if N/A */
+};
+
+/* extension for audio port configuration structure when the audio port is a
+ * sub mix */
+struct audio_port_config_mix_ext {
+    audio_module_handle_t hw_module;    /* module the stream is attached to */
+    audio_io_handle_t handle;           /* I/O handle of the input/output stream */
+    union {
+        //TODO: change use case for output streams: use strategy and mixer attributes
+        audio_stream_type_t stream;
+        audio_source_t      source;
+    } usecase;
+};
+
+/* extension for audio port configuration structure when the audio port is an
+ * audio session */
+struct audio_port_config_session_ext {
+    audio_session_t   session; /* audio session */
+};
+
+/* audio port configuration structure used to specify a particular configuration of
+ * an audio port */
+struct audio_port_config {
+    audio_port_handle_t      id;           /* port unique ID */
+    audio_port_role_t        role;         /* sink or source */
+    audio_port_type_t        type;         /* device, mix ... */
+    unsigned int             config_mask;  /* e.g AUDIO_PORT_CONFIG_ALL */
+    unsigned int             sample_rate;  /* sampling rate in Hz */
+    audio_channel_mask_t     channel_mask; /* channel mask if applicable */
+    audio_format_t           format;       /* format if applicable */
+    struct audio_gain_config gain;         /* gain to apply if applicable */
+#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
+    union audio_io_flags     flags;        /* framework only: HW_AV_SYNC, DIRECT, ... */
+#endif
+    union {
+        struct audio_port_config_device_ext  device;  /* device specific info */
+        struct audio_port_config_mix_ext     mix;     /* mix specific info */
+        struct audio_port_config_session_ext session; /* session specific info */
+    } ext;
+};
+
+
+/* max number of sampling rates in audio port */
+#define AUDIO_PORT_MAX_SAMPLING_RATES 32
+/* max number of channel masks in audio port */
+#define AUDIO_PORT_MAX_CHANNEL_MASKS 32
+/* max number of audio formats in audio port */
+#define AUDIO_PORT_MAX_FORMATS 32
+/* max number of gain controls in audio port */
+#define AUDIO_PORT_MAX_GAINS 16
+
+/* extension for audio port structure when the audio port is a hardware device */
+struct audio_port_device_ext {
+    audio_module_handle_t hw_module;    /* module the device is attached to */
+    audio_devices_t       type;         /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */
+    char                  address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+};
+
+/* 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 */
+    audio_io_handle_t         handle;        /* I/O handle of the input.output stream */
+    audio_mix_latency_class_t latency_class; /* latency class */
+    // other attributes: routing strategies
+};
+
+/* extension for audio port structure when the audio port is an audio session */
+struct audio_port_session_ext {
+    audio_session_t   session; /* audio session */
+};
+
+struct audio_port {
+    audio_port_handle_t      id;                /* port unique ID */
+    audio_port_role_t        role;              /* sink or source */
+    audio_port_type_t        type;              /* device, mix ... */
+    char                     name[AUDIO_PORT_MAX_NAME_LEN];
+    unsigned int             num_sample_rates;  /* number of sampling rates in following array */
+    unsigned int             sample_rates[AUDIO_PORT_MAX_SAMPLING_RATES];
+    unsigned int             num_channel_masks; /* number of channel masks in following array */
+    audio_channel_mask_t     channel_masks[AUDIO_PORT_MAX_CHANNEL_MASKS];
+    unsigned int             num_formats;       /* number of formats in following array */
+    audio_format_t           formats[AUDIO_PORT_MAX_FORMATS];
+    unsigned int             num_gains;         /* number of gains in following array */
+    struct audio_gain        gains[AUDIO_PORT_MAX_GAINS];
+    struct audio_port_config active_config;     /* current audio port configuration */
+    union {
+        struct audio_port_device_ext  device;
+        struct audio_port_mix_ext     mix;
+        struct audio_port_session_ext session;
+    } ext;
+};
+
+/* An audio patch represents a connection between one or more source ports and
+ * one or more sink ports. Patches are connected and disconnected by audio policy manager or by
+ * applications via framework APIs.
+ * Each patch is identified by a handle at the interface used to create that patch. For instance,
+ * when a patch is created by the audio HAL, the HAL allocates and returns a handle.
+ * This handle is unique to a given audio HAL hardware module.
+ * 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 int audio_patch_handle_t;
+
+#define AUDIO_PATCH_PORTS_MAX   16
+
+struct audio_patch {
+    audio_patch_handle_t id;            /* patch unique ID */
+    unsigned int      num_sources;      /* number of sources in following array */
+    struct audio_port_config sources[AUDIO_PATCH_PORTS_MAX];
+    unsigned int      num_sinks;        /* number of sinks in following array */
+    struct audio_port_config sinks[AUDIO_PATCH_PORTS_MAX];
+};
+
+
+
+/* a HW synchronization source returned by the audio HAL */
+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 */
+};
+
+/** Metadata of a record track for an in stream. */
+typedef struct playback_track_metadata {
+    audio_usage_t usage;
+    audio_content_type_t content_type;
+    float gain; // Normalized linear volume. 0=silence, 1=0dbfs...
+} playback_track_metadata_t;
+
+/** Metadata of a playback track for an out stream. */
+typedef struct record_track_metadata {
+    audio_source_t source;
+    float gain; // Normalized linear volume. 0=silence, 1=0dbfs...
+} record_track_metadata_t;
+
+
+/******************************
+ *  Helper functions
+ *****************************/
+
+static inline bool audio_is_output_device(audio_devices_t device)
+{
+    if (((device & AUDIO_DEVICE_BIT_IN) == 0) &&
+            (popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0))
+        return true;
+    else
+        return false;
+}
+
+static inline bool audio_is_input_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_ALL) == 0))
+            return true;
+    }
+    return false;
+}
+
+static inline bool audio_is_output_devices(audio_devices_t device)
+{
+    return (device & AUDIO_DEVICE_BIT_IN) == 0;
+}
+
+static inline bool audio_is_a2dp_in_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if ((popcount(device) == 1) && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP))
+            return true;
+    }
+    return false;
+}
+
+static inline bool audio_is_a2dp_out_device(audio_devices_t device)
+{
+    if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_A2DP))
+        return true;
+    else
+        return false;
+}
+
+// Deprecated - use audio_is_a2dp_out_device() instead
+static inline bool audio_is_a2dp_device(audio_devices_t device)
+{
+    return audio_is_a2dp_out_device(device);
+}
+
+static inline bool audio_is_bluetooth_sco_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) == 0) {
+        if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL_SCO) == 0))
+            return true;
+    } else {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) == 0))
+            return true;
+    }
+
+    return false;
+}
+
+static inline bool audio_is_hearing_aid_out_device(audio_devices_t device)
+{
+    return device == AUDIO_DEVICE_OUT_HEARING_AID;
+}
+
+static inline bool audio_is_usb_out_device(audio_devices_t device)
+{
+    return ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_USB));
+}
+
+static inline bool audio_is_usb_in_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if (popcount(device) == 1 && (device & AUDIO_DEVICE_IN_ALL_USB) != 0)
+            return true;
+    }
+    return false;
+}
+
+/* OBSOLETE - use audio_is_usb_out_device() instead. */
+static inline bool audio_is_usb_device(audio_devices_t device)
+{
+    return audio_is_usb_out_device(device);
+}
+
+static inline bool audio_is_remote_submix_device(audio_devices_t device)
+{
+    if ((audio_is_output_devices(device) &&
+         (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) == AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
+        || (!audio_is_output_devices(device) &&
+         (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) == AUDIO_DEVICE_IN_REMOTE_SUBMIX))
+        return true;
+    else
+        return false;
+}
+
+/* Returns true if:
+ *  representation is valid, and
+ *  there is at least one channel bit set which _could_ correspond to an input channel, and
+ *  there are no channel bits set which could _not_ correspond to an input channel.
+ * Otherwise returns false.
+ */
+static inline bool audio_is_input_channel(audio_channel_mask_t channel)
+{
+    uint32_t bits = audio_channel_mask_get_bits(channel);
+    switch (audio_channel_mask_get_representation(channel)) {
+    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+        if (bits & ~AUDIO_CHANNEL_IN_ALL) {
+            bits = 0;
+        }
+        // fall through
+    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+        return bits != 0;
+    default:
+        return false;
+    }
+}
+
+/* Returns true if:
+ *  representation is valid, and
+ *  there is at least one channel bit set which _could_ correspond to an output channel, and
+ *  there are no channel bits set which could _not_ correspond to an output channel.
+ * Otherwise returns false.
+ */
+static inline bool audio_is_output_channel(audio_channel_mask_t channel)
+{
+    uint32_t bits = audio_channel_mask_get_bits(channel);
+    switch (audio_channel_mask_get_representation(channel)) {
+    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+        if (bits & ~AUDIO_CHANNEL_OUT_ALL) {
+            bits = 0;
+        }
+        // fall through
+    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+        return bits != 0;
+    default:
+        return false;
+    }
+}
+
+/* Returns the number of channels from an input channel mask,
+ * used in the context of audio input or recording.
+ * If a channel bit is set which could _not_ correspond to an input channel,
+ * it is excluded from the count.
+ * Returns zero if the representation is invalid.
+ */
+static inline uint32_t audio_channel_count_from_in_mask(audio_channel_mask_t channel)
+{
+    uint32_t bits = audio_channel_mask_get_bits(channel);
+    switch (audio_channel_mask_get_representation(channel)) {
+    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+        // TODO: We can now merge with from_out_mask and remove anding
+        bits &= AUDIO_CHANNEL_IN_ALL;
+        // fall through
+    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+        return popcount(bits);
+    default:
+        return 0;
+    }
+}
+
+/* Returns the number of channels from an output channel mask,
+ * used in the context of audio output or playback.
+ * If a channel bit is set which could _not_ correspond to an output channel,
+ * it is excluded from the count.
+ * Returns zero if the representation is invalid.
+ */
+static inline uint32_t audio_channel_count_from_out_mask(audio_channel_mask_t channel)
+{
+    uint32_t bits = audio_channel_mask_get_bits(channel);
+    switch (audio_channel_mask_get_representation(channel)) {
+    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+        // TODO: We can now merge with from_in_mask and remove anding
+        bits &= AUDIO_CHANNEL_OUT_ALL;
+        // fall through
+    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+        return popcount(bits);
+    default:
+        return 0;
+    }
+}
+
+/* Derive a channel mask for index assignment from a channel count.
+ * Returns the matching channel mask,
+ * or AUDIO_CHANNEL_NONE if the channel count is zero,
+ * or AUDIO_CHANNEL_INVALID if the channel count exceeds AUDIO_CHANNEL_COUNT_MAX.
+ */
+static inline audio_channel_mask_t audio_channel_mask_for_index_assignment_from_count(
+        uint32_t channel_count)
+{
+    if (channel_count == 0) {
+        return AUDIO_CHANNEL_NONE;
+    }
+    if (channel_count > AUDIO_CHANNEL_COUNT_MAX) {
+        return AUDIO_CHANNEL_INVALID;
+    }
+    uint32_t bits = (1 << channel_count) - 1;
+    return audio_channel_mask_from_representation_and_bits(
+            AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
+}
+
+/* Derive an output channel mask for position assignment from a channel count.
+ * This is to be used when the content channel mask is unknown. The 1, 2, 4, 5, 6, 7 and 8 channel
+ * cases are mapped to the standard game/home-theater layouts, but note that 4 is mapped to quad,
+ * and not stereo + FC + mono surround. A channel count of 3 is arbitrarily mapped to stereo + FC
+ * for continuity with stereo.
+ * Returns the matching channel mask,
+ * or AUDIO_CHANNEL_NONE if the channel count is zero,
+ * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the
+ * configurations for which a default output channel mask is defined.
+ */
+static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t channel_count)
+{
+    uint32_t bits;
+    switch (channel_count) {
+    case 0:
+        return AUDIO_CHANNEL_NONE;
+    case 1:
+        bits = AUDIO_CHANNEL_OUT_MONO;
+        break;
+    case 2:
+        bits = AUDIO_CHANNEL_OUT_STEREO;
+        break;
+    case 3:
+        bits = AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER;
+        break;
+    case 4: // 4.0
+        bits = AUDIO_CHANNEL_OUT_QUAD;
+        break;
+    case 5: // 5.0
+        bits = AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER;
+        break;
+    case 6: // 5.1
+        bits = AUDIO_CHANNEL_OUT_5POINT1;
+        break;
+    case 7: // 6.1
+        bits = AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER;
+        break;
+    case 8:
+        bits = AUDIO_CHANNEL_OUT_7POINT1;
+        break;
+    // FIXME FCC_8
+    default:
+        return AUDIO_CHANNEL_INVALID;
+    }
+    return audio_channel_mask_from_representation_and_bits(
+            AUDIO_CHANNEL_REPRESENTATION_POSITION, bits);
+}
+
+/* Derive a default input channel mask from a channel count.
+ * Assumes a position mask for mono and stereo, or an index mask for channel counts > 2.
+ * Returns the matching channel mask,
+ * or AUDIO_CHANNEL_NONE if the channel count is zero,
+ * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the
+ * configurations for which a default input channel mask is defined.
+ */
+static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t channel_count)
+{
+    uint32_t bits;
+    switch (channel_count) {
+    case 0:
+        return AUDIO_CHANNEL_NONE;
+    case 1:
+        bits = AUDIO_CHANNEL_IN_MONO;
+        break;
+    case 2:
+        bits = AUDIO_CHANNEL_IN_STEREO;
+        break;
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+        // FIXME FCC_8
+        return audio_channel_mask_for_index_assignment_from_count(channel_count);
+    default:
+        return AUDIO_CHANNEL_INVALID;
+    }
+    return audio_channel_mask_from_representation_and_bits(
+            AUDIO_CHANNEL_REPRESENTATION_POSITION, bits);
+}
+
+static inline audio_channel_mask_t audio_channel_mask_in_to_out(audio_channel_mask_t in)
+{
+    switch (in) {
+    case AUDIO_CHANNEL_IN_MONO:
+        return AUDIO_CHANNEL_OUT_MONO;
+    case AUDIO_CHANNEL_IN_STEREO:
+        return AUDIO_CHANNEL_OUT_STEREO;
+    case AUDIO_CHANNEL_IN_5POINT1:
+        return AUDIO_CHANNEL_OUT_5POINT1;
+    case AUDIO_CHANNEL_IN_3POINT1POINT2:
+        return AUDIO_CHANNEL_OUT_3POINT1POINT2;
+    case AUDIO_CHANNEL_IN_3POINT0POINT2:
+        return AUDIO_CHANNEL_OUT_3POINT0POINT2;
+    case AUDIO_CHANNEL_IN_2POINT1POINT2:
+        return AUDIO_CHANNEL_OUT_2POINT1POINT2;
+    case AUDIO_CHANNEL_IN_2POINT0POINT2:
+        return AUDIO_CHANNEL_OUT_2POINT0POINT2;
+    default:
+        return AUDIO_CHANNEL_INVALID;
+    }
+}
+
+static inline audio_channel_mask_t audio_channel_mask_out_to_in(audio_channel_mask_t out)
+{
+    switch (out) {
+    case AUDIO_CHANNEL_OUT_MONO:
+        return AUDIO_CHANNEL_IN_MONO;
+    case AUDIO_CHANNEL_OUT_STEREO:
+        return AUDIO_CHANNEL_IN_STEREO;
+    case AUDIO_CHANNEL_OUT_5POINT1:
+        return AUDIO_CHANNEL_IN_5POINT1;
+    case AUDIO_CHANNEL_OUT_3POINT1POINT2:
+        return AUDIO_CHANNEL_IN_3POINT1POINT2;
+    case AUDIO_CHANNEL_OUT_3POINT0POINT2:
+        return AUDIO_CHANNEL_IN_3POINT0POINT2;
+    case AUDIO_CHANNEL_OUT_2POINT1POINT2:
+        return AUDIO_CHANNEL_IN_2POINT1POINT2;
+    case AUDIO_CHANNEL_OUT_2POINT0POINT2:
+        return AUDIO_CHANNEL_IN_2POINT0POINT2;
+    default:
+        return AUDIO_CHANNEL_INVALID;
+    }
+}
+
+static inline bool audio_is_valid_format(audio_format_t format)
+{
+    switch (format & AUDIO_FORMAT_MAIN_MASK) {
+    case AUDIO_FORMAT_PCM:
+        switch (format) {
+        case AUDIO_FORMAT_PCM_16_BIT:
+        case AUDIO_FORMAT_PCM_8_BIT:
+        case AUDIO_FORMAT_PCM_32_BIT:
+        case AUDIO_FORMAT_PCM_8_24_BIT:
+        case AUDIO_FORMAT_PCM_FLOAT:
+        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+            return true;
+        default:
+            return false;
+        }
+        /* not reached */
+    case AUDIO_FORMAT_MP3:
+    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_AAC_ELD:
+    case AUDIO_FORMAT_AAC_XHE:
+    case AUDIO_FORMAT_VORBIS:
+    case AUDIO_FORMAT_OPUS:
+    case AUDIO_FORMAT_AC3:
+    case AUDIO_FORMAT_E_AC3:
+    case AUDIO_FORMAT_DTS:
+    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:
+    case AUDIO_FORMAT_E_AC3_JOC:
+    case AUDIO_FORMAT_MAT_1_0:
+    case AUDIO_FORMAT_MAT_2_0:
+    case AUDIO_FORMAT_MAT_2_1:
+        return true;
+    default:
+        return false;
+    }
+}
+
+/**
+ * Extract the primary format, eg. PCM, AC3, etc.
+ */
+static inline audio_format_t audio_get_main_format(audio_format_t format)
+{
+    return (audio_format_t)(format & AUDIO_FORMAT_MAIN_MASK);
+}
+
+/**
+ * Is the data plain PCM samples that can be scaled and mixed?
+ */
+static inline bool audio_is_linear_pcm(audio_format_t format)
+{
+    return (audio_get_main_format(format) == AUDIO_FORMAT_PCM);
+}
+
+/**
+ * For this format, is the number of PCM audio frames directly proportional
+ * to the number of data bytes?
+ *
+ * In other words, is the format transported as PCM audio samples,
+ * but not necessarily scalable or mixable.
+ * This returns true for real PCM, but also for AUDIO_FORMAT_IEC61937,
+ * which is transported as 16 bit PCM audio, but where the encoded data
+ * cannot be mixed or scaled.
+ */
+static inline bool audio_has_proportional_frames(audio_format_t format)
+{
+    audio_format_t mainFormat = audio_get_main_format(format);
+    return (mainFormat == AUDIO_FORMAT_PCM
+            || mainFormat == AUDIO_FORMAT_IEC61937);
+}
+
+static inline size_t audio_bytes_per_sample(audio_format_t format)
+{
+    size_t size = 0;
+
+    switch (format) {
+    case AUDIO_FORMAT_PCM_32_BIT:
+    case AUDIO_FORMAT_PCM_8_24_BIT:
+        size = sizeof(int32_t);
+        break;
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+        size = sizeof(uint8_t) * 3;
+        break;
+    case AUDIO_FORMAT_PCM_16_BIT:
+    case AUDIO_FORMAT_IEC61937:
+        size = sizeof(int16_t);
+        break;
+    case AUDIO_FORMAT_PCM_8_BIT:
+        size = sizeof(uint8_t);
+        break;
+    case AUDIO_FORMAT_PCM_FLOAT:
+        size = sizeof(float);
+        break;
+    default:
+        break;
+    }
+    return size;
+}
+
+static inline size_t audio_bytes_per_frame(uint32_t channel_count, audio_format_t format)
+{
+    // cannot overflow for reasonable channel_count
+    return channel_count * audio_bytes_per_sample(format);
+}
+
+/* converts device address to string sent to audio HAL via set_parameters */
+static inline char *audio_device_address_to_parameter(audio_devices_t device, const char *address)
+{
+    const size_t kSize = AUDIO_DEVICE_MAX_ADDRESS_LEN + sizeof("a2dp_sink_address=");
+    char param[kSize];
+
+    if (device & AUDIO_DEVICE_OUT_ALL_A2DP)
+        snprintf(param, kSize, "%s=%s", "a2dp_sink_address", address);
+    else if (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
+        snprintf(param, kSize, "%s=%s", "mix", address);
+    else
+        snprintf(param, kSize, "%s", address);
+
+    return strdup(param);
+}
+
+static inline bool audio_device_is_digital(audio_devices_t device) {
+    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+        // input
+        return (~AUDIO_DEVICE_BIT_IN & device & (AUDIO_DEVICE_IN_ALL_USB |
+                          AUDIO_DEVICE_IN_HDMI |
+                          AUDIO_DEVICE_IN_SPDIF |
+                          AUDIO_DEVICE_IN_IP |
+                          AUDIO_DEVICE_IN_BUS)) != 0;
+    } else {
+        // output
+        return (device & (AUDIO_DEVICE_OUT_ALL_USB |
+                          AUDIO_DEVICE_OUT_HDMI |
+                          AUDIO_DEVICE_OUT_HDMI_ARC |
+                          AUDIO_DEVICE_OUT_SPDIF |
+                          AUDIO_DEVICE_OUT_IP |
+                          AUDIO_DEVICE_OUT_BUS)) != 0;
+    }
+}
+
+#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
+
+static inline bool audio_gain_config_are_equal(
+        const struct audio_gain_config *lhs, const struct audio_gain_config *rhs) {
+    if (lhs->mode != rhs->mode) return false;
+    switch (lhs->mode) {
+    case AUDIO_GAIN_MODE_JOINT:
+        if (lhs->values[0] != rhs->values[0]) return false;
+        break;
+    case AUDIO_GAIN_MODE_CHANNELS:
+    case AUDIO_GAIN_MODE_RAMP:
+        if (lhs->channel_mask != rhs->channel_mask) return false;
+        for (int i = 0; i < popcount(lhs->channel_mask); ++i) {
+            if (lhs->values[i] != rhs->values[i]) return false;
+        }
+        break;
+    default: return false;
+    }
+    return lhs->ramp_duration_ms == rhs->ramp_duration_ms;
+}
+
+static inline bool audio_port_config_has_input_direction(const struct audio_port_config *port_cfg) {
+    switch (port_cfg->type) {
+    case AUDIO_PORT_TYPE_DEVICE:
+        switch (port_cfg->role) {
+        case AUDIO_PORT_ROLE_SOURCE: return true;
+        case AUDIO_PORT_ROLE_SINK: return false;
+        default: return false;
+        }
+    case AUDIO_PORT_TYPE_MIX:
+        switch (port_cfg->role) {
+        case AUDIO_PORT_ROLE_SOURCE: return false;
+        case AUDIO_PORT_ROLE_SINK: return true;
+        default: return false;
+        }
+    default: return false;
+    }
+}
+
+static inline bool audio_port_configs_are_equal(
+        const struct audio_port_config *lhs, const struct audio_port_config *rhs) {
+    if (lhs->role != rhs->role || lhs->type != rhs->type) return false;
+    switch (lhs->type) {
+    case AUDIO_PORT_TYPE_NONE: break;
+    case AUDIO_PORT_TYPE_DEVICE:
+        if (lhs->ext.device.hw_module != rhs->ext.device.hw_module ||
+                lhs->ext.device.type != rhs->ext.device.type ||
+                strncmp(lhs->ext.device.address, rhs->ext.device.address,
+                        AUDIO_DEVICE_MAX_ADDRESS_LEN) != 0) {
+            return false;
+        }
+        break;
+    case AUDIO_PORT_TYPE_MIX:
+        if (lhs->ext.mix.hw_module != rhs->ext.mix.hw_module ||
+                lhs->ext.mix.handle != rhs->ext.mix.handle) return false;
+        if (lhs->role == AUDIO_PORT_ROLE_SOURCE &&
+                lhs->ext.mix.usecase.stream != rhs->ext.mix.usecase.stream) return false;
+        else if (lhs->role == AUDIO_PORT_ROLE_SINK &&
+                lhs->ext.mix.usecase.source != rhs->ext.mix.usecase.source) return false;
+        break;
+    case AUDIO_PORT_TYPE_SESSION:
+        if (lhs->ext.session.session != rhs->ext.session.session) return false;
+        break;
+    default: return false;
+    }
+    return lhs->config_mask == rhs->config_mask &&
+            ((lhs->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) == 0 ||
+                    lhs->sample_rate == rhs->sample_rate) &&
+            ((lhs->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) == 0 ||
+                    lhs->channel_mask == rhs->channel_mask) &&
+            ((lhs->config_mask & AUDIO_PORT_CONFIG_FORMAT) == 0 ||
+                    lhs->format == rhs->format) &&
+            ((lhs->config_mask & AUDIO_PORT_CONFIG_GAIN) == 0 ||
+                    audio_gain_config_are_equal(&lhs->gain, &rhs->gain)) &&
+            ((lhs->config_mask & AUDIO_PORT_CONFIG_FLAGS) == 0 ||
+                    (audio_port_config_has_input_direction(lhs) ?
+                            lhs->flags.input == rhs->flags.input :
+                            lhs->flags.output == rhs->flags.output));
+}
+
+static inline bool audio_port_config_has_hw_av_sync(const struct audio_port_config *port_cfg) {
+    if (!(port_cfg->config_mask & AUDIO_PORT_CONFIG_FLAGS)) {
+        return false;
+    }
+    return audio_port_config_has_input_direction(port_cfg) ?
+            port_cfg->flags.input & AUDIO_INPUT_FLAG_HW_AV_SYNC
+            : port_cfg->flags.output & AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+}
+
+static inline bool audio_patch_has_hw_av_sync(const struct audio_patch *patch) {
+    for (unsigned int i = 0; i < patch->num_sources; ++i) {
+        if (audio_port_config_has_hw_av_sync(&patch->sources[i])) return true;
+    }
+    for (unsigned int i = 0; i < patch->num_sinks; ++i) {
+        if (audio_port_config_has_hw_av_sync(&patch->sinks[i])) return true;
+    }
+    return false;
+}
+
+static inline bool audio_patch_is_valid(const struct audio_patch *patch) {
+    // Note that patch can have no sinks.
+    return patch->num_sources != 0 && patch->num_sources <= AUDIO_PATCH_PORTS_MAX &&
+            patch->num_sinks <= AUDIO_PATCH_PORTS_MAX;
+}
+
+// Note that when checking for equality the order of ports must match.
+// Patches will not be equivalent if they contain the same ports but they are permuted differently.
+static inline bool audio_patches_are_equal(
+        const struct audio_patch *lhs, const struct audio_patch *rhs) {
+    if (!audio_patch_is_valid(lhs) || !audio_patch_is_valid(rhs)) return false;
+    if (lhs->num_sources != rhs->num_sources || lhs->num_sinks != rhs->num_sinks) return false;
+    for (unsigned int i = 0; i < lhs->num_sources; ++i) {
+        if (!audio_port_configs_are_equal(&lhs->sources[i], &rhs->sources[i])) return false;
+    }
+    for (unsigned int i = 0; i < lhs->num_sinks; ++i) {
+        if (!audio_port_configs_are_equal(&lhs->sinks[i], &rhs->sinks[i])) return false;
+    }
+    return true;
+}
+
+#endif
+
+// 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;
+
+//TODO: audio_microphone_location_t need to move to HAL v4.0
+typedef enum {
+    AUDIO_MICROPHONE_LOCATION_UNKNOWN = 0,
+    AUDIO_MICROPHONE_LOCATION_MAINBODY = 1,
+    AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE = 2,
+    AUDIO_MICROPHONE_LOCATION_PERIPHERAL = 3,
+    AUDIO_MICROPHONE_LOCATION_CNT = 4,
+} audio_microphone_location_t;
+
+//TODO: audio_microphone_directionality_t need to move to HAL v4.0
+typedef enum {
+    AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN = 0,
+    AUDIO_MICROPHONE_DIRECTIONALITY_OMNI = 1,
+    AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL = 2,
+    AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID = 3,
+    AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID = 4,
+    AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID = 5,
+    AUDIO_MICROPHONE_DIRECTIONALITY_CNT = 6,
+} audio_microphone_directionality_t;
+
+/* A 3D point which could be used to represent geometric location
+ * or orientation of a microphone.
+ */
+struct audio_microphone_coordinate {
+    float x;
+    float y;
+    float z;
+};
+
+/* An number to indicate which group the microphone locate. Main body is
+ * usually group 0. Developer could use this value to group the microphones
+ * that locate on the same peripheral or attachments.
+ */
+typedef int audio_microphone_group_t;
+
+typedef enum {
+    AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED = 0,
+    AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT = 1,
+    AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED = 2,
+    AUDIO_MICROPHONE_CHANNEL_MAPPING_CNT = 3,
+} audio_microphone_channel_mapping_t;
+
+/* the maximum length for the microphone id */
+#define AUDIO_MICROPHONE_ID_MAX_LEN 32
+/* max number of frequency responses in a frequency response table */
+#define AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES 256
+/* max number of microphone */
+#define AUDIO_MICROPHONE_MAX_COUNT 32
+/* the value of unknown spl */
+#define AUDIO_MICROPHONE_SPL_UNKNOWN -FLT_MAX
+/* the value of unknown sensitivity */
+#define AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN -FLT_MAX
+/* the value of unknown coordinate */
+#define AUDIO_MICROPHONE_COORDINATE_UNKNOWN -FLT_MAX
+/* the value used as address when the address of bottom microphone is empty */
+#define AUDIO_BOTTOM_MICROPHONE_ADDRESS "bottom"
+/* the value used as address when the address of back microphone is empty */
+#define AUDIO_BACK_MICROPHONE_ADDRESS "back"
+
+struct audio_microphone_characteristic_t {
+    char                               device_id[AUDIO_MICROPHONE_ID_MAX_LEN];
+    audio_port_handle_t                id;
+    audio_devices_t                    device;
+    char                               address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+    audio_microphone_channel_mapping_t channel_mapping[AUDIO_CHANNEL_COUNT_MAX];
+    audio_microphone_location_t        location;
+    audio_microphone_group_t           group;
+    unsigned int                       index_in_the_group;
+    float                              sensitivity;
+    float                              max_spl;
+    float                              min_spl;
+    audio_microphone_directionality_t  directionality;
+    unsigned int                       num_frequency_responses;
+    float frequency_responses[2][AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES];
+    struct audio_microphone_coordinate geometric_location;
+    struct audio_microphone_coordinate orientation;
+};
+
+__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"
+#define AUDIO_HARDWARE_MODULE_ID_HEARING_AID "hearing_aid"
+#define AUDIO_HARDWARE_MODULE_ID_MSD "msd"
+
+/**
+ * Multi-Stream Decoder (MSD) HAL service name. MSD HAL is used to mix
+ * encoded streams together with PCM streams, producing re-encoded
+ * streams or PCM streams.
+ *
+ * The service must register itself using this name, and audioserver
+ * tries to instantiate a device factory using this name as well.
+ * Note that the HIDL implementation library file name *must* have the
+ * suffix "msd" in order to be picked up by HIDL that is:
+ *
+ *   android.hardware.audio@x.x-implmsd.so
+ */
+#define AUDIO_HAL_SERVICE_NAME_MSD "msd"
+
+/**
+ * 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"
+
+/* User's preferred audio language setting (in ISO 639-2/T three-letter string code)
+ * used to select a specific language presentation for next generation audio codecs. */
+#define AUDIO_PARAMETER_KEY_AUDIO_LANGUAGE_PREFERRED "audio_language_preferred"
+
+/**
+ *  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 */
+
+/* Request the presentation id to be decoded by a next gen audio decoder */
+#define AUDIO_PARAMETER_STREAM_PRESENTATION_ID "presentation_id" /* int32_t */
+
+/* Request the program id to be decoded by a next gen audio decoder */
+#define AUDIO_PARAMETER_STREAM_PROGRAM_ID "program_id"           /* int32_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 "|"
+
+/* Reconfigure offloaded A2DP codec */
+#define AUDIO_PARAMETER_RECONFIG_A2DP "reconfigA2dp"
+/* Query if HwModule supports reconfiguration of offloaded A2DP codec */
+#define AUDIO_PARAMETER_A2DP_RECONFIG_SUPPORTED "isReconfigA2dpSupported"
+
+/**
+ * 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/include/system/audio_effect-base.h b/include/system/audio_effect-base.h
new file mode 100644
index 0000000..7a6a593
--- /dev/null
+++ b/include/system/audio_effect-base.h
@@ -0,0 +1,99 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+// Source: android.hardware.audio.effect@4.0
+// Root: android.hardware:hardware/interfaces
+
+#ifndef HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EXPORTED_CONSTANTS_H_
+#define HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_EFFECT_V4_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, // (::android::hardware::audio::effect::V4_0::EffectBufferAccess.ACCESS_WRITE implicitly + 1)
+    EFFECT_BUFFER_ACCESS_ACCUMULATE = 2, // (::android::hardware::audio::effect::V4_0::EffectBufferAccess.ACCESS_READ implicitly + 1)
+} effect_buffer_access_e;
+
+enum {
+    EFFECT_CONFIG_BUFFER = 1,
+    EFFECT_CONFIG_SMP_RATE = 2,
+    EFFECT_CONFIG_CHANNELS = 4,
+    EFFECT_CONFIG_FORMAT = 8,
+    EFFECT_CONFIG_ACC_MODE = 16,
+};
+
+typedef enum {
+    EFFECT_FEATURE_AUX_CHANNELS = 0,
+    EFFECT_FEATURE_CNT = 1, // (::android::hardware::audio::effect::V4_0::EffectFeature.AUX_CHANNELS implicitly + 1)
+} effect_feature_e;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EXPORTED_CONSTANTS_H_
diff --git a/include/system/audio_effect.h b/include/system/audio_effect.h
new file mode 100644
index 0000000..4cdc773
--- /dev/null
+++ b/include/system/audio_effect.h
@@ -0,0 +1,536 @@
+/*
+ * 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;
+
+#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | \
+                           EFFECT_CONFIG_SMP_RATE | \
+                           EFFECT_CONFIG_CHANNELS | \
+                           EFFECT_CONFIG_FORMAT | \
+                           EFFECT_CONFIG_ACC_MODE)
+
+/////////////////////////////////////////////////
+//      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
+        float*      f32;        // pointer to float 32 bit data at 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/include/utils/Errors.h b/include/utils/Errors.h
new file mode 100644
index 0000000..16e1fa2
--- /dev/null
+++ b/include/utils/Errors.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 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_ERRORS_H
+#define ANDROID_ERRORS_H
+
+#include <sys/types.h>
+#include <errno.h>
+
+namespace android {
+
+// use this type to return error codes
+#ifdef _WIN32
+typedef int         status_t;
+#else
+typedef int32_t     status_t;
+#endif
+
+/* the MS C runtime lacks a few error codes */
+
+/*
+ * Error codes. 
+ * All error codes are negative values.
+ */
+
+// Win32 #defines NO_ERROR as well.  It has the same value, so there's no
+// real conflict, though it's a bit awkward.
+#ifdef _WIN32
+# undef NO_ERROR
+#endif
+
+enum {
+    OK                = 0,    // Everything's swell.
+    NO_ERROR          = 0,    // No errors.
+
+    UNKNOWN_ERROR       = (-2147483647-1), // INT32_MIN value
+
+    NO_MEMORY           = -ENOMEM,
+    INVALID_OPERATION   = -ENOSYS,
+    BAD_VALUE           = -EINVAL,
+    BAD_TYPE            = (UNKNOWN_ERROR + 1),
+    NAME_NOT_FOUND      = -ENOENT,
+    PERMISSION_DENIED   = -EPERM,
+    NO_INIT             = -ENODEV,
+    ALREADY_EXISTS      = -EEXIST,
+    DEAD_OBJECT         = -EPIPE,
+    FAILED_TRANSACTION  = (UNKNOWN_ERROR + 2),
+#if !defined(_WIN32)
+    BAD_INDEX           = -EOVERFLOW,
+    NOT_ENOUGH_DATA     = -ENODATA,
+    WOULD_BLOCK         = -EWOULDBLOCK, 
+    TIMED_OUT           = -ETIMEDOUT,
+    UNKNOWN_TRANSACTION = -EBADMSG,
+#else    
+    BAD_INDEX           = -E2BIG,
+    NOT_ENOUGH_DATA     = (UNKNOWN_ERROR + 3),
+    WOULD_BLOCK         = (UNKNOWN_ERROR + 4),
+    TIMED_OUT           = (UNKNOWN_ERROR + 5),
+    UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6),
+#endif    
+    FDS_NOT_ALLOWED     = (UNKNOWN_ERROR + 7),
+    UNEXPECTED_NULL     = (UNKNOWN_ERROR + 8),
+};
+
+// Restore define; enumeration is in "android" namespace, so the value defined
+// there won't work for Win32 code in a different namespace.
+#ifdef _WIN32
+# define NO_ERROR 0L
+#endif
+
+}; // namespace android
+    
+// ---------------------------------------------------------------------------
+    
+#endif // ANDROID_ERRORS_H
diff --git a/src/cutils/CMakeLists.txt b/src/cutils/CMakeLists.txt
new file mode 100644
index 0000000..d436aea
--- /dev/null
+++ b/src/cutils/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 3.8)
+
+#############################################
+# libcutils
+#############################################
+add_library(cutils SHARED
+        hashmap.cpp
+        str_parms.cpp
+        threads.cpp
+        properties.cpp
+)
+
+target_include_directories(cutils PRIVATE
+	./include)
+
+add_library(cutils_static STATIC
+	strlcpy.c)
+
+target_include_directories(cutils_static PRIVATE
+	./include)
+
+target_link_libraries(cutils
+	-Wl,--whole-archive cutils_static -Wl,--no-whole-archive)
+
+install(TARGETS cutils
+        LIBRARY DESTINATION "lib")
diff --git a/src/cutils/Makefile b/src/cutils/Makefile
new file mode 100644
index 0000000..3114740
--- /dev/null
+++ b/src/cutils/Makefile
@@ -0,0 +1,74 @@
+################################################################################

+# Device/Makefile

+#

+# This Makefile builds the libs

+#

+################################################################################

+OUT_ROOT ?= dist

+

+CUTILS_DIR = $(AML_COMMON_DIR)/cutils

+

+################################################################################

+# libcutils.so - common src files

+################################################################################

+CUTILS_SRC_DIR = $(CUTILS_DIR)

+cutils_SRCS = \

+	$(CUTILS_SRC_DIR)/hashmap.cpp \

+	$(CUTILS_SRC_DIR)/strlcpy.c \

+	$(CUTILS_SRC_DIR)/str_parms.cpp \

+	$(CUTILS_SRC_DIR)/threads.cpp \

+	$(CUTILS_SRC_DIR)/properties.cpp \

+	$(NULL)

+

+liblog_SRCS += $(wildcard $(CUTILS_SRC_DIR)/liblog/*.c)

+cutils_SRCS += $(liblog_SRCS)

+

+logcat_SRCS = $(CUTILS_SRC_DIR)/logcat.cpp $(liblog_SRCS)

+

+#TODO: Add more include directories here, if necessary.

+INCLUDES += \

+	-I$(CUTILS_DIR)/include \

+	-I$(CUTILS_DIR)/liblog/include

+CFLAGS += -DHAVE_SYS_UIO_H -DHAVE_IOCTL

+

+ALL_SRCS = $(libcutils_SRCS) $(logcat_SRCS)

+

+include $(ROKU_PORT_COMMON_DIR)/build/define_target.mk

+

+comma = ,

+$(eval $(call DEFINE_TARGET,libcutils.so,$(cutils_SRCS),,-lpthread -lstdc++ -fPIC -shared -Wl$(comma)-z$(comma)defs -Wl$(comma)--build-id,lib))

+$(eval $(call DEFINE_TARGET,logcat,$(logcat_SRCS),,-lpthread -lstdc++ -fPIC -Wl$(comma)-z$(comma)defs -Wl$(comma)--build-id,lib))

+

+# ---------------------------------------------------------------------

+#  Build rules

+all: $(VENDOR_ALL_TARGETS)

+# Compile .c file.

+# Simultaneously create .d file (see http://make.mad-scientist.net/papers/advanced-auto-dependency-generation).

+$(OUT_ROOT)/%.o: %.c $(OUT_ROOT)/%.d

+	mkdir -p $(dir $@)

+	$(CC) -MT $@ -MMD -MP -MF $(OUT_ROOT)/$*.Td  $(CFLAGS) $(INCLUDES) -c -o $@ $<

+	mv -f $(OUT_ROOT)/$*.Td $(OUT_ROOT)/$*.d && touch $@

+# Compile .cpp file.

+# Simultaneously create .d file (see http://make.mad-scientist.net/papers/advanced-auto-dependency-generation).

+$(OUT_ROOT)/%.o: %.cpp $(OUT_ROOT)/%.d

+	@mkdir -p $(dir $@)

+	$(CXX) -MT $@ -MMD -MP -MF $(OUT_ROOT)/$*.Td  $(CFLAGS) $(INCLUDES) -c -o $@ $<

+	mv -f $(OUT_ROOT)/$*.Td $(OUT_ROOT)/$*.d && touch $@

+$(OUT_ROOT)/%.d: ;

+.PRECIOUS: $(OUT_ROOT)/%.d

+.PHONY: clean distclean install

+

+include $(wildcard $(patsubst %,$(OUT_ROOT)/%.d,$(basename $(cutils_SRCS))))

+

+clean:

+	-rm -rf $(OUT_ROOT) $(CLEAN_FILES)

+	mkdir -p $(OUT_ROOT)

+

+distclean:

+	-rm   $(DESTDIR)/usr/lib/libcutils.so

+	-rm   $(DESTDIR)/usr/bin/logcat

+

+install:

+	mkdir -p $(DESTDIR)/usr/lib

+	cp $(OUT_ROOT)/libcutils.so  $(DESTDIR)/usr/lib/

+	cp $(OUT_ROOT)/logcat $(DESTDIR)/usr/bin

diff --git a/src/cutils/cutils.mk b/src/cutils/cutils.mk
new file mode 100644
index 0000000..46afb3c
--- /dev/null
+++ b/src/cutils/cutils.mk
@@ -0,0 +1,30 @@
+CUTILS_PROJDIR  := $(AML_COMMON_DIR)/cutils
+CUTILS_OSS_LIC  := CLOSED
+CUTILS_DEPENDS  := #Add dependencies here. E.g. PAL_DEPENDS := platform
+CUTILS_BINARIES := usr/lib/libcutils.so usr/bin/logcat
+CUTILS_ADD_SRC  := $(ROKU_OS_INCLUDE_DIRS)
+
+$(eval $(call prep_proj,CUTILS,cutils,$(CUTILS_PROJDIR),$(CUTILS_ADD_SRC)))
+
+LDFLAGS = $(addprefix -L, $(ROKU_3PARTY_LIB_DIRS))
+CUTILS_MAKE_OPTIONS = \
+	CC=$(CC) \
+	CXX=$(CXX) \
+	OUT_ROOT=$(CUTILS_MAKEDIR) \
+	PORTING_KIT_OS=$(PORTING_KIT_OS) \
+	LDFLAGS="$(LDFLAGS)" \
+	PLATFORMDIR=$(PLATFORMDIR) \
+	AML_COMMON_DIR=$(AML_COMMON_DIR) \
+	ROKU_PORT_COMMON_DIR=$(ROKU_PORT_COMMON_DIR)
+
+cutils-configure:
+cutils-build:
+	(PATH=$(CROSSTOOLS_BIN):$(PATH) \
+	$(MAKE) -C $(CUTILS_PROJDIR) $(CUTILS_MAKE_OPTIONS) all)
+
+cutils-install:
+	$(MAKE) -C $(CUTILS_PROJDIR) DESTDIR=$(CUTILS_INSTDIR) $(CUTILS_MAKE_OPTIONS) DESTDIR=$(ROKU_STAGING_DIR)/$(CUTILS_DESTDIR) install
+
+cutils-clean:
+	[ -e $(CUTILS_PROJDIR)/Makefile ] && $(MAKE) -C $(CUTILS_PROJDIR) $(CUTILS_MAKE_OPTIONS) clean || true
+	[ -e $(CUTILS_PROJDIR)/Makefile ] && $(MAKE) -C $(CUTILS_PROJDIR) $(CUTILS_MAKE_OPTIONS) DESTDIR=$(ROKU_STAGING_DIR)/$(CUTILS_DESTDIR) distclean || true
diff --git a/src/cutils/hashmap.cpp b/src/cutils/hashmap.cpp
new file mode 100644
index 0000000..65b6ab1
--- /dev/null
+++ b/src/cutils/hashmap.cpp
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2007 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 <cutils/hashmap.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <cutils/threads.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+typedef struct Entry Entry;
+struct Entry {
+    void* key;
+    int hash;
+    void* value;
+    Entry* next;
+};
+
+struct Hashmap {
+    Entry** buckets;
+    size_t bucketCount;
+    int (*hash)(void* key);
+    bool (*equals)(void* keyA, void* keyB);
+    mutex_t lock; 
+    size_t size;
+};
+
+Hashmap* hashmapCreate(size_t initialCapacity,
+        int (*hash)(void* key), bool (*equals)(void* keyA, void* keyB)) {
+    assert(hash != NULL);
+    assert(equals != NULL);
+    
+    Hashmap* map = static_cast<Hashmap*>(malloc(sizeof(Hashmap)));
+    if (map == NULL) {
+        return NULL;
+    }
+    
+    // 0.75 load factor.
+    size_t minimumBucketCount = initialCapacity * 4 / 3;
+    map->bucketCount = 1;
+    while (map->bucketCount <= minimumBucketCount) {
+        // Bucket count must be power of 2.
+        map->bucketCount <<= 1; 
+    }
+
+    map->buckets = static_cast<Entry**>(calloc(map->bucketCount, sizeof(Entry*)));
+    if (map->buckets == NULL) {
+        free(map);
+        return NULL;
+    }
+    
+    map->size = 0;
+
+    map->hash = hash;
+    map->equals = equals;
+    
+    mutex_init(&map->lock);
+    
+    return map;
+}
+
+/**
+ * Hashes the given key.
+ */
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
+static inline int hashKey(Hashmap* map, void* key) {
+    int h = map->hash(key);
+
+    // We apply this secondary hashing discovered by Doug Lea to defend
+    // against bad hashes.
+    h += ~(h << 9);
+    h ^= (((unsigned int) h) >> 14);
+    h += (h << 4);
+    h ^= (((unsigned int) h) >> 10);
+       
+    return h;
+}
+
+size_t hashmapSize(Hashmap* map) {
+    return map->size;
+}
+
+static inline size_t calculateIndex(size_t bucketCount, int hash) {
+    return ((size_t) hash) & (bucketCount - 1);
+}
+
+static void expandIfNecessary(Hashmap* map) {
+    // If the load factor exceeds 0.75...
+    if (map->size > (map->bucketCount * 3 / 4)) {
+        // Start off with a 0.33 load factor.
+        size_t newBucketCount = map->bucketCount << 1;
+        Entry** newBuckets = static_cast<Entry**>(calloc(newBucketCount, sizeof(Entry*)));
+        if (newBuckets == NULL) {
+            // Abort expansion.
+            return;
+        }
+        
+        // Move over existing entries.
+        size_t i;
+        for (i = 0; i < map->bucketCount; i++) {
+            Entry* entry = map->buckets[i];
+            while (entry != NULL) {
+                Entry* next = entry->next;
+                size_t index = calculateIndex(newBucketCount, entry->hash);
+                entry->next = newBuckets[index];
+                newBuckets[index] = entry;
+                entry = next;
+            }
+        }
+
+        // Copy over internals.
+        free(map->buckets);
+        map->buckets = newBuckets;
+        map->bucketCount = newBucketCount;
+    }
+}
+
+void hashmapLock(Hashmap* map) {
+    mutex_lock(&map->lock);
+}
+
+void hashmapUnlock(Hashmap* map) {
+    mutex_unlock(&map->lock);
+}
+
+void hashmapFree(Hashmap* map) {
+    size_t i;
+    for (i = 0; i < map->bucketCount; i++) {
+        Entry* entry = map->buckets[i];
+        while (entry != NULL) {
+            Entry* next = entry->next;
+            free(entry);
+            entry = next;
+        }
+    }
+    free(map->buckets);
+    mutex_destroy(&map->lock);
+    free(map);
+}
+
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
+/* FIXME: relies on signed integer overflow, which is undefined behavior */
+int hashmapHash(void* key, size_t keySize) {
+    int h = keySize;
+    char* data = (char*) key;
+    size_t i;
+    for (i = 0; i < keySize; i++) {
+        h = h * 31 + *data;
+        data++;
+    }
+    return h;
+}
+
+static Entry* createEntry(void* key, int hash, void* value) {
+    Entry* entry = static_cast<Entry*>(malloc(sizeof(Entry)));
+    if (entry == NULL) {
+        return NULL;
+    }
+    entry->key = key;
+    entry->hash = hash;
+    entry->value = value;
+    entry->next = NULL;
+    return entry;
+}
+
+static inline bool equalKeys(void* keyA, int hashA, void* keyB, int hashB,
+        bool (*equals)(void*, void*)) {
+    if (keyA == keyB) {
+        return true;
+    }
+    if (hashA != hashB) {
+        return false;
+    }
+    return equals(keyA, keyB);
+}
+
+void* hashmapPut(Hashmap* map, void* key, void* value) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    Entry** p = &(map->buckets[index]);
+    while (true) {
+        Entry* current = *p;
+
+        // Add a new entry.
+        if (current == NULL) {
+            *p = createEntry(key, hash, value);
+            if (*p == NULL) {
+                errno = ENOMEM;
+                return NULL;
+            }
+            map->size++;
+            expandIfNecessary(map);
+            return NULL;
+        }
+
+        // Replace existing entry.
+        if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
+            void* oldValue = current->value;
+            current->value = value;
+            return oldValue;
+        }
+
+        // Move to next entry.
+        p = &current->next;
+    }
+}
+
+void* hashmapGet(Hashmap* map, void* key) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    Entry* entry = map->buckets[index];
+    while (entry != NULL) {
+        if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
+            return entry->value;
+        }
+        entry = entry->next;
+    }
+
+    return NULL;
+}
+
+bool hashmapContainsKey(Hashmap* map, void* key) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    Entry* entry = map->buckets[index];
+    while (entry != NULL) {
+        if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
+            return true;
+        }
+        entry = entry->next;
+    }
+
+    return false;
+}
+
+void* hashmapMemoize(Hashmap* map, void* key, 
+        void* (*initialValue)(void* key, void* context), void* context) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    Entry** p = &(map->buckets[index]);
+    while (true) {
+        Entry* current = *p;
+
+        // Add a new entry.
+        if (current == NULL) {
+            *p = createEntry(key, hash, NULL);
+            if (*p == NULL) {
+                errno = ENOMEM;
+                return NULL;
+            }
+            void* value = initialValue(key, context);
+            (*p)->value = value;
+            map->size++;
+            expandIfNecessary(map);
+            return value;
+        }
+
+        // Return existing value.
+        if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
+            return current->value;
+        }
+
+        // Move to next entry.
+        p = &current->next;
+    }
+}
+
+void* hashmapRemove(Hashmap* map, void* key) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    // Pointer to the current entry.
+    Entry** p = &(map->buckets[index]);
+    Entry* current;
+    while ((current = *p) != NULL) {
+        if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
+            void* value = current->value;
+            *p = current->next;
+            free(current);
+            map->size--;
+            return value;
+        }
+
+        p = &current->next;
+    }
+
+    return NULL;
+}
+
+void hashmapForEach(Hashmap* map, 
+        bool (*callback)(void* key, void* value, void* context),
+        void* context) {
+    size_t i;
+    for (i = 0; i < map->bucketCount; i++) {
+        Entry* entry = map->buckets[i];
+        while (entry != NULL) {
+            Entry *next = entry->next;
+            if (!callback(entry->key, entry->value, context)) {
+                return;
+            }
+            entry = next;
+        }
+    }
+}
+
+size_t hashmapCurrentCapacity(Hashmap* map) {
+    size_t bucketCount = map->bucketCount;
+    return bucketCount * 3 / 4;
+}
+
+size_t hashmapCountCollisions(Hashmap* map) {
+    size_t collisions = 0;
+    size_t i;
+    for (i = 0; i < map->bucketCount; i++) {
+        Entry* entry = map->buckets[i];
+        while (entry != NULL) {
+            if (entry->next != NULL) {
+                collisions++;
+            }
+            entry = entry->next;
+        }
+    }
+    return collisions;
+}
+
+int hashmapIntHash(void* key) {
+    // Return the key value itself.
+    return *((int*) key);
+}
+
+bool hashmapIntEquals(void* keyA, void* keyB) {
+    int a = *((int*) keyA);
+    int b = *((int*) keyB);
+    return a == b;
+}
diff --git a/src/cutils/logcat.cpp b/src/cutils/logcat.cpp
new file mode 100644
index 0000000..225c15e
--- /dev/null
+++ b/src/cutils/logcat.cpp
@@ -0,0 +1,789 @@
+// Copyright 2006 The Android Open Source Project
+
+#include <cutils/logger.h>
+#include <cutils/logd.h>
+#include <cutils/sockets.h>
+#include <cutils/logprint.h>
+#include <cutils/event_tag_map.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <errno.h>
+#include <assert.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+
+#define DEFAULT_LOG_ROTATE_SIZE_KBYTES 16
+#define DEFAULT_MAX_ROTATED_LOGS 4
+
+static AndroidLogFormat * g_logformat;
+static bool g_nonblock = false;
+static int g_tail_lines = 0;
+
+/* logd prefixes records with a length field */
+#define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t)
+
+#define LOG_FILE_DIR    "/dev/log_"
+
+struct queued_entry_t {
+    union {
+        unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
+        struct logger_entry entry __attribute__((aligned(4)));
+    };
+    queued_entry_t* next;
+
+    queued_entry_t() {
+        next = NULL;
+    }
+};
+
+static int cmp(queued_entry_t* a, queued_entry_t* b) {
+    int n = a->entry.sec - b->entry.sec;
+    if (n != 0) {
+        return n;
+    }
+    return a->entry.nsec - b->entry.nsec;
+}
+
+struct log_device_t {
+    char* device;
+    bool binary;
+    int fd;
+    bool printed;
+    char label;
+
+    queued_entry_t* queue;
+    log_device_t* next;
+
+    log_device_t(char* d, bool b, char l) {
+        device = d;
+        binary = b;
+        label = l;
+        queue = NULL;
+        next = NULL;
+        printed = false;
+    }
+
+    void enqueue(queued_entry_t* entry) {
+        if (this->queue == NULL) {
+            this->queue = entry;
+        } else {
+            queued_entry_t** e = &this->queue;
+            while (*e && cmp(entry, *e) >= 0) {
+                e = &((*e)->next);
+            }
+            entry->next = *e;
+            *e = entry;
+        }
+    }
+};
+
+namespace android {
+
+/* Global Variables */
+
+static const char * g_outputFileName = NULL;
+static int g_logRotateSizeKBytes = 0;                   // 0 means "no log rotation"
+static int g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded"
+static int g_outFD = -1;
+static off_t g_outByteCount = 0;
+static int g_printBinary = 0;
+static int g_devCount = 0;
+
+static EventTagMap* g_eventTagMap = NULL;
+
+static int openLogFile (const char *pathname)
+{
+    return open(g_outputFileName, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
+}
+
+static void rotateLogs()
+{
+    int err;
+
+    // Can't rotate logs if we're not outputting to a file
+    if (g_outputFileName == NULL) {
+        return;
+    }
+
+    close(g_outFD);
+
+    for (int i = g_maxRotatedLogs ; i > 0 ; i--) {
+        char *file0, *file1;
+
+        asprintf(&file1, "%s.%d", g_outputFileName, i);
+
+        if (i - 1 == 0) {
+            asprintf(&file0, "%s", g_outputFileName);
+        } else {
+            asprintf(&file0, "%s.%d", g_outputFileName, i - 1);
+        }
+
+        err = rename (file0, file1);
+
+        if (err < 0 && errno != ENOENT) {
+            perror("while rotating log files");
+        }
+
+        free(file1);
+        free(file0);
+    }
+
+    g_outFD = openLogFile (g_outputFileName);
+
+    if (g_outFD < 0) {
+        perror ("couldn't open output file");
+        exit(-1);
+    }
+
+    g_outByteCount = 0;
+
+}
+
+void printBinary(struct logger_entry *buf)
+{
+    size_t size = sizeof(logger_entry) + buf->len;
+    int ret;
+
+    do {
+        ret = write(g_outFD, buf, size);
+    } while (ret < 0 && errno == EINTR);
+}
+
+static void processBuffer(log_device_t* dev, struct logger_entry *buf)
+{
+    int bytesWritten = 0;
+    int err;
+    AndroidLogEntry entry;
+    char binaryMsgBuf[1024];
+
+    if (dev->binary) {
+        err = android_log_processBinaryLogBuffer(buf, &entry, g_eventTagMap,
+                binaryMsgBuf, sizeof(binaryMsgBuf));
+        //printf(">>> pri=%d len=%d msg='%s'\n",
+        //    entry.priority, entry.messageLen, entry.message);
+    } else {
+        err = android_log_processLogBuffer(buf, &entry);
+    }
+    if (err < 0) {
+        goto error;
+    }
+
+    if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.priority)) {
+        if (false && g_devCount > 1) {
+            binaryMsgBuf[0] = dev->label;
+            binaryMsgBuf[1] = ' ';
+            bytesWritten = write(g_outFD, binaryMsgBuf, 2);
+            if (bytesWritten < 0) {
+                perror("output error");
+                exit(-1);
+            }
+        }
+
+        bytesWritten = android_log_printLogLine(g_logformat, g_outFD, &entry);
+
+        if (bytesWritten < 0) {
+            perror("output error");
+            exit(-1);
+        }
+    }
+
+    g_outByteCount += bytesWritten;
+
+    if (g_logRotateSizeKBytes > 0
+        && (g_outByteCount / 1024) >= g_logRotateSizeKBytes
+    ) {
+        rotateLogs();
+    }
+
+error:
+    //fprintf (stderr, "Error processing record\n");
+    return;
+}
+
+static void chooseFirst(log_device_t* dev, log_device_t** firstdev) {
+    for (*firstdev = NULL; dev != NULL; dev = dev->next) {
+        if (dev->queue != NULL && (*firstdev == NULL || cmp(dev->queue, (*firstdev)->queue) < 0)) {
+            *firstdev = dev;
+        }
+    }
+}
+
+static void maybePrintStart(log_device_t* dev) {
+    if (!dev->printed) {
+        dev->printed = true;
+        if (g_devCount > 1 && !g_printBinary) {
+            char buf[1024];
+            snprintf(buf, sizeof(buf), "--------- beginning of %s\n", dev->device);
+            if (write(g_outFD, buf, strlen(buf)) < 0) {
+                perror("output error");
+                exit(-1);
+            }
+        }
+    }
+}
+
+static void skipNextEntry(log_device_t* dev) {
+    maybePrintStart(dev);
+    queued_entry_t* entry = dev->queue;
+    dev->queue = entry->next;
+    delete entry;
+}
+
+static void printNextEntry(log_device_t* dev) {
+    maybePrintStart(dev);
+    if (g_printBinary) {
+        printBinary(&dev->queue->entry);
+    } else {
+        processBuffer(dev, &dev->queue->entry);
+    }
+    skipNextEntry(dev);
+}
+
+static void readLogLines(log_device_t* devices)
+{
+    log_device_t* dev;
+    int max = 0;
+    int ret;
+    int queued_lines = 0;
+    bool sleep = false;
+
+    int result;
+    fd_set readset;
+
+    for (dev=devices; dev; dev = dev->next) {
+        if (dev->fd > max) {
+            max = dev->fd;
+        }
+    }
+
+    while (1) {
+        do {
+            timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR.
+            FD_ZERO(&readset);
+            for (dev=devices; dev; dev = dev->next) {
+                FD_SET(dev->fd, &readset);
+            }
+            result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout);
+        } while (result == -1 && errno == EINTR);
+
+        if (result >= 0) {
+            for (dev=devices; dev; dev = dev->next) {
+                if (FD_ISSET(dev->fd, &readset)) {
+                    queued_entry_t* entry = new queued_entry_t();
+                    /* NOTE: driver guarantees we read exactly one full entry */
+                    ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN);
+                    if (ret < 0) {
+                        if (errno == EINTR) {
+                            delete entry;
+                            goto next;
+                        }
+                        if (errno == EAGAIN) {
+                            delete entry;
+                            break;
+                        }
+                        perror("logcat read");
+                        exit(EXIT_FAILURE);
+                    }
+                    else if (!ret) {
+                        fprintf(stderr, "read: Unexpected EOF!\n");
+                        exit(EXIT_FAILURE);
+                    }
+                    else if (entry->entry.len != ret - sizeof(struct logger_entry)) {
+                        fprintf(stderr, "read: unexpected length. Expected %d, got %d\n",
+                                entry->entry.len, ret - sizeof(struct logger_entry));
+                        exit(EXIT_FAILURE);
+                    }
+
+                    entry->entry.msg[entry->entry.len] = '\0';
+
+                    dev->enqueue(entry);
+                    ++queued_lines;
+                }
+            }
+
+            if (result == 0) {
+                // we did our short timeout trick and there's nothing new
+                // print everything we have and wait for more data
+                sleep = true;
+                while (true) {
+                    chooseFirst(devices, &dev);
+                    if (dev == NULL) {
+                        break;
+                    }
+                    if (g_tail_lines == 0 || queued_lines <= g_tail_lines) {
+                        printNextEntry(dev);
+                    } else {
+                        skipNextEntry(dev);
+                    }
+                    --queued_lines;
+                }
+
+                // the caller requested to just dump the log and exit
+                if (g_nonblock) {
+                    return;
+                }
+            } else {
+                // print all that aren't the last in their list
+                sleep = false;
+                while (g_tail_lines == 0 || queued_lines > g_tail_lines) {
+                    chooseFirst(devices, &dev);
+                    if (dev == NULL || dev->queue->next == NULL) {
+                        break;
+                    }
+                    if (g_tail_lines == 0) {
+                        printNextEntry(dev);
+                    } else {
+                        skipNextEntry(dev);
+                    }
+                    --queued_lines;
+                }
+            }
+        }
+next:
+        ;
+    }
+}
+
+static int clearLog(int logfd)
+{
+    return ioctl(logfd, LOGGER_FLUSH_LOG);
+}
+
+/* returns the total size of the log's ring buffer */
+static int getLogSize(int logfd)
+{
+    return ioctl(logfd, LOGGER_GET_LOG_BUF_SIZE);
+}
+
+/* returns the readable size of the log's ring buffer (that is, amount of the log consumed) */
+static int getLogReadableSize(int logfd)
+{
+    return ioctl(logfd, LOGGER_GET_LOG_LEN);
+}
+
+static void setupOutput()
+{
+
+    if (g_outputFileName == NULL) {
+        g_outFD = STDOUT_FILENO;
+
+    } else {
+        struct stat statbuf;
+
+        g_outFD = openLogFile (g_outputFileName);
+
+        if (g_outFD < 0) {
+            perror ("couldn't open output file");
+            exit(-1);
+        }
+
+        fstat(g_outFD, &statbuf);
+
+        g_outByteCount = statbuf.st_size;
+    }
+}
+
+static void show_help(const char *cmd)
+{
+    fprintf(stderr,"Usage: %s [options] [filterspecs]\n", cmd);
+
+    fprintf(stderr, "options include:\n"
+                    "  -s              Set default filter to silent.\n"
+                    "                  Like specifying filterspec '*:s'\n"
+                    "  -f <filename>   Log to file. Default to stdout\n"
+                    "  -r [<kbytes>]   Rotate log every kbytes. (16 if unspecified). Requires -f\n"
+                    "  -n <count>      Sets max number of rotated logs to <count>, default 4\n"
+                    "  -v <format>     Sets the log print format, where <format> is one of:\n\n"
+                    "                  brief process tag thread raw time threadtime long\n\n"
+                    "  -c              clear (flush) the entire log and exit\n"
+                    "  -d              dump the log and then exit (don't block)\n"
+                    "  -t <count>      print only the most recent <count> lines (implies -d)\n"
+                    "  -g              get the size of the log's ring buffer and exit\n"
+                    "  -b <buffer>     Request alternate ring buffer, 'main', 'system', 'radio'\n"
+                    "                  or 'events'. Multiple -b parameters are allowed and the\n"
+                    "                  results are interleaved. The default is -b main -b system.\n"
+                    "  -B              output the log in binary");
+
+
+    fprintf(stderr,"\nfilterspecs are a series of \n"
+                   "  <tag>[:priority]\n\n"
+                   "where <tag> is a log component tag (or * for all) and priority is:\n"
+                   "  V    Verbose\n"
+                   "  D    Debug\n"
+                   "  I    Info\n"
+                   "  W    Warn\n"
+                   "  E    Error\n"
+                   "  F    Fatal\n"
+                   "  S    Silent (supress all output)\n"
+                   "\n'*' means '*:d' and <tag> by itself means <tag>:v\n"
+                   "\nIf not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.\n"
+                   "If no filterspec is found, filter defaults to '*:I'\n"
+                   "\nIf not specified with -v, format is set from ANDROID_PRINTF_LOG\n"
+                   "or defaults to \"brief\"\n\n");
+
+
+
+}
+
+
+} /* namespace android */
+
+static int setLogFormat(const char * formatString)
+{
+    static AndroidLogPrintFormat format;
+
+    format = android_log_formatFromString(formatString);
+
+    if (format == FORMAT_OFF) {
+        // FORMAT_OFF means invalid string
+        return -1;
+    }
+
+    android_log_setPrintFormat(g_logformat, format);
+
+    return 0;
+}
+
+//extern "C" void logprint_run_tests(void);
+
+int main(int argc, char **argv)
+{
+    int err;
+    int hasSetLogFormat = 0;
+    int clearLog = 0;
+    int getLogSize = 0;
+    int mode = O_RDONLY;
+    const char *forceFilters = NULL;
+    log_device_t* devices = NULL;
+    log_device_t* dev;
+    bool needBinary = false;
+
+    g_logformat = android_log_format_new();
+
+    if (argc == 2 && 0 == strcmp(argv[1], "--test")) {
+       // logprint_run_tests();
+        exit(0);
+    }
+
+    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
+        android::show_help(argv[0]);
+        exit(0);
+    }
+
+    for (;;) {
+        int ret;
+
+        ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:B");
+
+        if (ret < 0) {
+            break;
+        }
+
+        switch (ret) {
+            case 's':
+                // default to all silent
+                android_log_addFilterRule(g_logformat, "*:s");
+            break;
+
+            case 'c':
+                clearLog = 1;
+                mode = O_WRONLY;
+            break;
+
+            case 'd':
+                g_nonblock = true;
+            break;
+
+            case 't':
+                g_nonblock = true;
+                g_tail_lines = atoi(optarg);
+            break;
+
+            case 'g':
+                getLogSize = 1;
+            break;
+
+            case 'b': {
+                char* buf = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1);
+                strcpy(buf, LOG_FILE_DIR);
+                strcat(buf, optarg);
+
+                bool binary = strcmp(optarg, "events") == 0;
+                if (binary) {
+                    needBinary = true;
+                }
+
+                if (devices) {
+                    dev = devices;
+                    while (dev->next) {
+                        dev = dev->next;
+                    }
+                    dev->next = new log_device_t(buf, binary, optarg[0]);
+                } else {
+                    devices = new log_device_t(buf, binary, optarg[0]);
+                }
+                android::g_devCount++;
+            }
+            break;
+
+            case 'B':
+                android::g_printBinary = 1;
+            break;
+
+            case 'f':
+                // redirect output to a file
+
+                android::g_outputFileName = optarg;
+
+            break;
+
+            case 'r':
+                if (optarg == NULL) {
+                    android::g_logRotateSizeKBytes
+                                = DEFAULT_LOG_ROTATE_SIZE_KBYTES;
+                } else {
+                    long logRotateSize;
+                    char *lastDigit;
+
+                    if (!isdigit(optarg[0])) {
+                        fprintf(stderr,"Invalid parameter to -r\n");
+                        android::show_help(argv[0]);
+                        exit(-1);
+                    }
+                    android::g_logRotateSizeKBytes = atoi(optarg);
+                }
+            break;
+
+            case 'n':
+                if (!isdigit(optarg[0])) {
+                    fprintf(stderr,"Invalid parameter to -r\n");
+                    android::show_help(argv[0]);
+                    exit(-1);
+                }
+
+                android::g_maxRotatedLogs = atoi(optarg);
+            break;
+
+            case 'v':
+                err = setLogFormat (optarg);
+                if (err < 0) {
+                    fprintf(stderr,"Invalid parameter to -v\n");
+                    android::show_help(argv[0]);
+                    exit(-1);
+                }
+
+                hasSetLogFormat = 1;
+            break;
+
+            case 'Q':
+                /* this is a *hidden* option used to start a version of logcat                 */
+                /* in an emulated device only. it basically looks for androidboot.logcat=      */
+                /* on the kernel command line. If something is found, it extracts a log filter */
+                /* and uses it to run the program. If nothing is found, the program should     */
+                /* quit immediately                                                            */
+#define  KERNEL_OPTION  "androidboot.logcat="
+#define  CONSOLE_OPTION "androidboot.console="
+                {
+                    int          fd;
+                    char*        logcat;
+                    char*        console;
+                    int          force_exit = 1;
+                    static char  cmdline[2048];
+
+                    fd = open("/proc/cmdline", O_RDONLY);
+                    if (fd >= 0) {
+                        int  n = read(fd, cmdline, sizeof(cmdline)-1 );
+                        if (n < 0) n = 0;
+                        cmdline[n] = 0;
+                        close(fd);
+                    } else {
+                        cmdline[0] = 0;
+                    }
+
+                    logcat  = strstr( cmdline, KERNEL_OPTION );
+                    console = strstr( cmdline, CONSOLE_OPTION );
+                    if (logcat != NULL) {
+                        char*  p = logcat + sizeof(KERNEL_OPTION)-1;;
+                        char*  q = strpbrk( p, " \t\n\r" );;
+
+                        if (q != NULL)
+                            *q = 0;
+
+                        forceFilters = p;
+                        force_exit   = 0;
+                    }
+                    /* if nothing found or invalid filters, exit quietly */
+                    if (force_exit)
+                        exit(0);
+
+                    /* redirect our output to the emulator console */
+                    if (console) {
+                        char*  p = console + sizeof(CONSOLE_OPTION)-1;
+                        char*  q = strpbrk( p, " \t\n\r" );
+                        char   devname[64];
+                        int    len;
+
+                        if (q != NULL) {
+                            len = q - p;
+                        } else
+                            len = strlen(p);
+
+                        len = snprintf( devname, sizeof(devname), "/dev/%.*s", len, p );
+                        fprintf(stderr, "logcat using %s (%d)\n", devname, len);
+                        if (len < (int)sizeof(devname)) {
+                            fd = open( devname, O_WRONLY );
+                            if (fd >= 0) {
+                                dup2(fd, 1);
+                                dup2(fd, 2);
+                                close(fd);
+                            }
+                        }
+                    }
+                }
+                break;
+
+            default:
+                fprintf(stderr,"Unrecognized Option\n");
+                android::show_help(argv[0]);
+                exit(-1);
+            break;
+        }
+    }
+
+    if (!devices) {
+        devices = new log_device_t(strdup("/dev/" LOGGER_LOG_MAIN), false, 'm');
+        android::g_devCount = 1;
+        int accessmode =
+                  (mode & O_RDONLY) ? R_OK : 0
+                | (mode & O_WRONLY) ? W_OK : 0;
+        // only add this if it's available
+        if (0 == access("/dev/" LOGGER_LOG_SYSTEM, accessmode)) {
+            devices->next = new log_device_t(strdup("/dev/" LOGGER_LOG_SYSTEM), false, 's');
+            android::g_devCount++;
+        }
+    }
+
+    if (android::g_logRotateSizeKBytes != 0
+        && android::g_outputFileName == NULL
+    ) {
+        fprintf(stderr,"-r requires -f as well\n");
+        android::show_help(argv[0]);
+        exit(-1);
+    }
+
+    android::setupOutput();
+
+    if (hasSetLogFormat == 0) {
+        const char* logFormat = getenv("ANDROID_PRINTF_LOG");
+
+        if (logFormat != NULL) {
+            err = setLogFormat(logFormat);
+
+            if (err < 0) {
+                fprintf(stderr, "invalid format in ANDROID_PRINTF_LOG '%s'\n",
+                                    logFormat);
+            }
+        }
+    }
+
+    if (forceFilters) {
+        err = android_log_addFilterString(g_logformat, forceFilters);
+        if (err < 0) {
+            fprintf (stderr, "Invalid filter expression in -logcat option\n");
+            exit(0);
+        }
+    } else if (argc == optind) {
+        // Add from environment variable
+        char *env_tags_orig = getenv("ANDROID_LOG_TAGS");
+
+        if (env_tags_orig != NULL) {
+            err = android_log_addFilterString(g_logformat, env_tags_orig);
+
+            if (err < 0) {
+                fprintf(stderr, "Invalid filter expression in"
+                                    " ANDROID_LOG_TAGS\n");
+                android::show_help(argv[0]);
+                exit(-1);
+            }
+        }
+    } else {
+        // Add from commandline
+        for (int i = optind ; i < argc ; i++) {
+            err = android_log_addFilterString(g_logformat, argv[i]);
+
+            if (err < 0) {
+                fprintf (stderr, "Invalid filter expression '%s'\n", argv[i]);
+                android::show_help(argv[0]);
+                exit(-1);
+            }
+        }
+    }
+
+    dev = devices;
+    while (dev) {
+        dev->fd = open(dev->device, mode);
+        if (dev->fd < 0) {
+            fprintf(stderr, "Unable to open log device '%s': %s\n",
+                dev->device, strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+
+        if (clearLog) {
+            int ret;
+            ret = android::clearLog(dev->fd);
+            if (ret) {
+                perror("ioctl");
+                exit(EXIT_FAILURE);
+            }
+        }
+
+        if (getLogSize) {
+            int size, readable;
+
+            size = android::getLogSize(dev->fd);
+            if (size < 0) {
+                perror("ioctl");
+                exit(EXIT_FAILURE);
+            }
+
+            readable = android::getLogReadableSize(dev->fd);
+            if (readable < 0) {
+                perror("ioctl");
+                exit(EXIT_FAILURE);
+            }
+
+            printf("%s: ring buffer is %dKb (%dKb consumed), "
+                   "max entry is %db, max payload is %db\n", dev->device,
+                   size / 1024, readable / 1024,
+                   (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD);
+        }
+
+        dev = dev->next;
+    }
+
+    if (getLogSize) {
+        exit(0);
+    }
+    if (clearLog) {
+        exit(0);
+    }
+
+    //LOG_EVENT_INT(10, 12345);
+    //LOG_EVENT_LONG(11, 0x1122334455667788LL);
+    //LOG_EVENT_STRING(0, "whassup, doc?");
+
+    if (needBinary)
+        android::g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE);
+
+    android::readLogLines(devices);
+
+    return 0;
+}
diff --git a/src/cutils/properties.cpp b/src/cutils/properties.cpp
new file mode 100644
index 0000000..40bcc6e
--- /dev/null
+++ b/src/cutils/properties.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2006 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 <cutils/properties.h>
+
+#define LOG_TAG "properties"
+// #define LOG_NDEBUG 0
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+//#include <cutils/sockets.h>
+#include <cutils/log.h>
+
+int8_t property_get_bool(const char *key, int8_t default_value) {
+    if (!key) {
+        return default_value;
+    }
+
+    int8_t result = default_value;
+    char buf[PROPERTY_VALUE_MAX] = {'\0'};
+
+    int len = property_get(key, buf, "");
+    if (len == 1) {
+        char ch = buf[0];
+        if (ch == '0' || ch == 'n') {
+            result = false;
+        } else if (ch == '1' || ch == 'y') {
+            result = true;
+        }
+    } else if (len > 1) {
+        if (!strcmp(buf, "no") || !strcmp(buf, "false") || !strcmp(buf, "off")) {
+            result = false;
+        } else if (!strcmp(buf, "yes") || !strcmp(buf, "true") || !strcmp(buf, "on")) {
+            result = true;
+        }
+    }
+
+    return result;
+}
+
+// Convert string property to int (default if fails); return default value if out of bounds
+static intmax_t property_get_imax(const char *key, intmax_t lower_bound, intmax_t upper_bound,
+                                  intmax_t default_value) {
+    if (!key) {
+        return default_value;
+    }
+
+    intmax_t result = default_value;
+    char buf[PROPERTY_VALUE_MAX] = {'\0'};
+    char *end = NULL;
+
+    int len = property_get(key, buf, "");
+    if (len > 0) {
+        int tmp = errno;
+        errno = 0;
+
+        // Infer base automatically
+        result = strtoimax(buf, &end, /*base*/ 0);
+        if ((result == INTMAX_MIN || result == INTMAX_MAX) && errno == ERANGE) {
+            // Over or underflow
+            result = default_value;
+            ALOGV("%s(%s,%" PRIdMAX ") - overflow", __FUNCTION__, key, default_value);
+        } else if (result < lower_bound || result > upper_bound) {
+            // Out of range of requested bounds
+            result = default_value;
+            ALOGV("%s(%s,%" PRIdMAX ") - out of range", __FUNCTION__, key, default_value);
+        } else if (end == buf) {
+            // Numeric conversion failed
+            result = default_value;
+            ALOGV("%s(%s,%" PRIdMAX ") - numeric conversion failed", __FUNCTION__, key,
+                  default_value);
+        }
+
+        errno = tmp;
+    }
+
+    return result;
+}
+
+int64_t property_get_int64(const char *key, int64_t default_value) {
+    return (int64_t)property_get_imax(key, INT64_MIN, INT64_MAX, default_value);
+}
+
+int32_t property_get_int32(const char *key, int32_t default_value) {
+    return (int32_t)property_get_imax(key, INT32_MIN, INT32_MAX, default_value);
+}
+
+//#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+//#include <sys/_system_properties.h>
+
+int property_set(const char *key, const char *value) {
+    //return __system_property_set(key, value);
+    return setenv(key, value, 1);
+}
+
+int property_get(const char *key, char *value, const char *default_value) {
+#if 0
+    int len = __system_property_get(key, value);
+    if (len > 0) {
+        return len;
+    }
+#endif
+
+    int i, len;
+    char key_buf[PROPERTY_VALUE_MAX];
+    const char *buf;
+
+    /* convert '.' in property name to '_' */
+    memset(key_buf, 0, sizeof(key_buf));
+    strncpy(key_buf, key, PROPERTY_VALUE_MAX - 1);
+    len = strlen(key_buf);
+    for (i = 0; i < len; i++) {
+        if (key_buf[i] == '.')
+            key_buf[i] = '_';
+    }
+
+    len = 0;
+    buf = getenv(key_buf);
+    if (buf) {
+        len = strlen(strncpy(value, buf, PROPERTY_VALUE_MAX - 1));
+        value[len] = '\0';
+        return len;
+    }
+
+    if (default_value) {
+        len = strnlen(default_value, PROPERTY_VALUE_MAX - 1);
+        memcpy(value, default_value, len);
+        value[len] = '\0';
+    }
+    return len;
+}
+
+#if 0
+struct callback_data {
+    void (*callback)(const char* name, const char* value, void* cookie);
+    void* cookie;
+};
+
+static void trampoline(void* raw_data, const char* name, const char* value, unsigned /*serial*/) {
+    callback_data* data = reinterpret_cast<callback_data*>(raw_data);
+    data->callback(name, value, data->cookie);
+}
+
+static void property_list_callback(const prop_info* pi, void* data) {
+    __system_property_read_callback(pi, trampoline, data);
+}
+
+int property_list(void (*fn)(const char* name, const char* value, void* cookie), void* cookie) {
+    callback_data data = { fn, cookie };
+    return __system_property_foreach(property_list_callback, &data);
+}
+#endif
+
diff --git a/src/cutils/str_parms.cpp b/src/cutils/str_parms.cpp
new file mode 100644
index 0000000..995733e
--- /dev/null
+++ b/src/cutils/str_parms.cpp
@@ -0,0 +1,375 @@
+/*
+ * 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.
+ */
+
+#include <cutils/str_parms.h>
+
+#define LOG_TAG "str_params"
+//#define LOG_NDEBUG 0
+
+#define _GNU_SOURCE 1
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/hashmap.h>
+#include <cutils/memory.h>
+//#include <log/log.h>
+#define ALOGV(...)
+#define ALOGI(...)
+
+/* When an object is allocated but not freed in a function,
+ * because its ownership is released to other object like a hashmap,
+ * call RELEASE_OWNERSHIP to tell the clang analyzer and avoid
+ * false warnings about potential memory leak.
+ * For now, a "temporary" assignment to global variables
+ * is enough to confuse the clang static analyzer.
+ */
+#ifdef __clang_analyzer__
+static void *released_pointer;
+#define RELEASE_OWNERSHIP(x) { released_pointer = x; released_pointer = 0; }
+#else
+#define RELEASE_OWNERSHIP(x)
+#endif
+
+struct str_parms {
+    Hashmap *map;
+};
+
+
+static bool str_eq(void *key_a, void *key_b)
+{
+    return !strcmp((const char *)key_a, (const char *)key_b);
+}
+
+/* use djb hash unless we find it inadequate */
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
+static int str_hash_fn(void *str)
+{
+    uint32_t hash = 5381;
+
+    for (char* p = static_cast<char*>(str); p && *p; p++)
+        hash = ((hash << 5) + hash) + *p;
+    return (int)hash;
+}
+
+struct str_parms *str_parms_create(void)
+{
+    str_parms* s = static_cast<str_parms*>(calloc(1, sizeof(str_parms)));
+    if (!s) return NULL;
+
+    s->map = hashmapCreate(5, str_hash_fn, str_eq);
+    if (!s->map) {
+        free(s);
+        return NULL;
+    }
+
+    return s;
+}
+
+struct remove_ctxt {
+    struct str_parms *str_parms;
+    const char *key;
+};
+
+static bool remove_pair(void *key, void *value, void *context)
+{
+    remove_ctxt* ctxt = static_cast<remove_ctxt*>(context);
+    bool should_continue;
+
+    /*
+     * - if key is not supplied, then we are removing all entries,
+     *   so remove key and continue (i.e. return true)
+     * - if key is supplied and matches, then remove it and don't
+     *   continue (return false). Otherwise, return true and keep searching
+     *   for key.
+     *
+     */
+    if (!ctxt->key) {
+        should_continue = true;
+        goto do_remove;
+    } else if (!strcmp(ctxt->key, static_cast<const char*>(key))) {
+        should_continue = false;
+        goto do_remove;
+    }
+
+    return true;
+
+do_remove:
+    hashmapRemove(ctxt->str_parms->map, key);
+    free(key);
+    free(value);
+    return should_continue;
+}
+
+void str_parms_del(struct str_parms *str_parms, const char *key)
+{
+    struct remove_ctxt ctxt = {
+        .str_parms = str_parms,
+        .key = key,
+    };
+    hashmapForEach(str_parms->map, remove_pair, &ctxt);
+}
+
+void str_parms_destroy(struct str_parms *str_parms)
+{
+    struct remove_ctxt ctxt = {
+        .str_parms = str_parms,
+    };
+
+    hashmapForEach(str_parms->map, remove_pair, &ctxt);
+    hashmapFree(str_parms->map);
+    free(str_parms);
+}
+
+struct str_parms *str_parms_create_str(const char *_string)
+{
+    struct str_parms *str_parms;
+    char *str;
+    char *kvpair;
+    char *tmpstr;
+    int items = 0;
+
+    str_parms = str_parms_create();
+    if (!str_parms)
+        goto err_create_str_parms;
+
+    str = strdup(_string);
+    if (!str)
+        goto err_strdup;
+
+    ALOGV("%s: source string == '%s'\n", __func__, _string);
+
+    kvpair = strtok_r(str, ";", &tmpstr);
+    while (kvpair && *kvpair) {
+        char *eq = strchr(kvpair, '='); /* would love strchrnul */
+        char *value;
+        char *key;
+        void *old_val;
+
+        if (eq == kvpair)
+            goto next_pair;
+
+        if (eq) {
+            key = strndup(kvpair, eq - kvpair);
+            if (*(++eq))
+                value = strdup(eq);
+            else
+                value = strdup("");
+        } else {
+            key = strdup(kvpair);
+            value = strdup("");
+        }
+
+        /* if we replaced a value, free it */
+        old_val = hashmapPut(str_parms->map, key, value);
+        RELEASE_OWNERSHIP(value);
+        if (old_val) {
+            free(old_val);
+            free(key);
+        } else {
+            RELEASE_OWNERSHIP(key);
+        }
+
+        items++;
+next_pair:
+        kvpair = strtok_r(NULL, ";", &tmpstr);
+    }
+
+    if (!items)
+        ALOGV("%s: no items found in string\n", __func__);
+
+    free(str);
+
+    return str_parms;
+
+err_strdup:
+    str_parms_destroy(str_parms);
+err_create_str_parms:
+    return NULL;
+}
+
+int str_parms_add_str(struct str_parms *str_parms, const char *key,
+                      const char *value)
+{
+    void *tmp_key = NULL;
+    void *tmp_val = NULL;
+    void *old_val = NULL;
+
+    // strdup and hashmapPut both set errno on failure.
+    // Set errno to 0 so we can recognize whether anything went wrong.
+    int saved_errno = errno;
+    errno = 0;
+
+    tmp_key = strdup(key);
+    if (tmp_key == NULL) {
+        goto clean_up;
+    }
+
+    tmp_val = strdup(value);
+    if (tmp_val == NULL) {
+        goto clean_up;
+    }
+
+    old_val = hashmapPut(str_parms->map, tmp_key, tmp_val);
+    if (old_val == NULL) {
+        // Did hashmapPut fail?
+        if (errno == ENOMEM) {
+            goto clean_up;
+        }
+        // For new keys, hashmap takes ownership of tmp_key and tmp_val.
+        RELEASE_OWNERSHIP(tmp_key);
+        RELEASE_OWNERSHIP(tmp_val);
+        tmp_key = tmp_val = NULL;
+    } else {
+        // For existing keys, hashmap takes ownership of tmp_val.
+        // (It also gives up ownership of old_val.)
+        RELEASE_OWNERSHIP(tmp_val);
+        tmp_val = NULL;
+    }
+
+clean_up:
+    free(tmp_key);
+    free(tmp_val);
+    free(old_val);
+    int result = -errno;
+    errno = saved_errno;
+    return result;
+}
+
+int str_parms_add_int(struct str_parms *str_parms, const char *key, int value)
+{
+    char val_str[12];
+    int ret;
+
+    ret = snprintf(val_str, sizeof(val_str), "%d", value);
+    if (ret < 0)
+        return -EINVAL;
+
+    ret = str_parms_add_str(str_parms, key, val_str);
+    return ret;
+}
+
+int str_parms_add_float(struct str_parms *str_parms, const char *key,
+                        float value)
+{
+    char val_str[23];
+    int ret;
+
+    ret = snprintf(val_str, sizeof(val_str), "%.10f", value);
+    if (ret < 0)
+        return -EINVAL;
+
+    ret = str_parms_add_str(str_parms, key, val_str);
+    return ret;
+}
+
+int str_parms_has_key(struct str_parms *str_parms, const char *key) {
+    return hashmapGet(str_parms->map, (void *)key) != NULL;
+}
+
+int str_parms_get_str(struct str_parms *str_parms, const char *key, char *val,
+                      int len)
+{
+    // TODO: hashmapGet should take a const* key.
+    char* value = static_cast<char*>(hashmapGet(str_parms->map, (void*)key));
+    if (value)
+        return strlcpy(val, value, len);
+
+    return -ENOENT;
+}
+
+int str_parms_get_int(struct str_parms *str_parms, const char *key, int *val)
+{
+    char *end;
+
+    // TODO: hashmapGet should take a const* key.
+    char* value = static_cast<char*>(hashmapGet(str_parms->map, (void*)key));
+    if (!value)
+        return -ENOENT;
+
+    *val = (int)strtol(value, &end, 0);
+    if (*value != '\0' && *end == '\0')
+        return 0;
+
+    return -EINVAL;
+}
+
+int str_parms_get_float(struct str_parms *str_parms, const char *key,
+                        float *val)
+{
+    float out;
+    char *end;
+
+    // TODO: hashmapGet should take a const* key.
+    char* value = static_cast<char*>(hashmapGet(str_parms->map, (void*)(key)));
+    if (!value)
+        return -ENOENT;
+
+    out = strtof(value, &end);
+    if (*value == '\0' || *end != '\0')
+        return -EINVAL;
+
+    *val = out;
+    return 0;
+}
+
+static bool combine_strings(void *key, void *value, void *context)
+{
+    char** old_str = static_cast<char**>(context);
+    char *new_str;
+    int ret;
+
+    ret = asprintf(&new_str, "%s%s%s=%s",
+                   *old_str ? *old_str : "",
+                   *old_str ? ";" : "",
+                   (char *)key,
+                   (char *)value);
+    if (*old_str)
+        free(*old_str);
+
+    if (ret >= 0) {
+        *old_str = new_str;
+        return true;
+    }
+
+    *old_str = NULL;
+    return false;
+}
+
+char *str_parms_to_str(struct str_parms *str_parms)
+{
+    char *str = NULL;
+
+    if (hashmapSize(str_parms->map) > 0)
+        hashmapForEach(str_parms->map, combine_strings, &str);
+    else
+        str = strdup("");
+    return str;
+}
+
+static bool dump_entry(void* key, void* value, void* /*context*/) {
+    ALOGI("key: '%s' value: '%s'\n", (char *)key, (char *)value);
+    return true;
+}
+
+void str_parms_dump(struct str_parms *str_parms)
+{
+    hashmapForEach(str_parms->map, dump_entry, str_parms);
+}
diff --git a/src/cutils/strlcpy.c b/src/cutils/strlcpy.c
new file mode 100644
index 0000000..c66246c
--- /dev/null
+++ b/src/cutils/strlcpy.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#if defined(__GLIBC__) || defined(_WIN32)
+
+#include <string.h>
+
+#include <cutils/memory.h>
+
+/* Implementation of strlcpy() for platforms that don't already have it. */
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0) {
+		while (--n != 0) {
+			if ((*d++ = *s++) == '\0')
+				break;
+		}
+  }
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
+
+#endif
diff --git a/src/cutils/threads.cpp b/src/cutils/threads.cpp
new file mode 100644
index 0000000..a7e6b2d
--- /dev/null
+++ b/src/cutils/threads.cpp
@@ -0,0 +1,111 @@
+/*
+** Copyright (C) 2007, 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 <cutils/threads.h>
+
+// For gettid.
+#if defined(__APPLE__)
+#include "AvailabilityMacros.h"  // For MAC_OS_X_VERSION_MAX_ALLOWED
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <unistd.h>
+#elif defined(__linux__) && !defined(__ANDROID__)
+#include <syscall.h>
+#include <unistd.h>
+#elif defined(_WIN32)
+#include <windows.h>
+#endif
+
+// No definition needed for Android because we'll just pick up bionic's copy.
+#ifndef __ANDROID__
+pid_t gettid() {
+#if defined(__APPLE__)
+  uint64_t tid;
+  pthread_threadid_np(NULL, &tid);
+  return tid;
+#elif defined(__linux__)
+  return syscall(__NR_gettid);
+#elif defined(_WIN32)
+  return GetCurrentThreadId();
+#endif
+}
+#endif  // __ANDROID__
+
+#if !defined(_WIN32)
+
+void*  thread_store_get( thread_store_t*  store )
+{
+    if (!store->has_tls)
+        return NULL;
+
+    return pthread_getspecific( store->tls );
+}
+
+extern void   thread_store_set( thread_store_t*          store,
+                                void*                    value,
+                                thread_store_destruct_t  destroy)
+{
+    pthread_mutex_lock( &store->lock );
+    if (!store->has_tls) {
+        if (pthread_key_create( &store->tls, destroy) != 0) {
+            pthread_mutex_unlock(&store->lock);
+            return;
+        }
+        store->has_tls = 1;
+    }
+    pthread_mutex_unlock( &store->lock );
+
+    pthread_setspecific( store->tls, value );
+}
+
+#else /* !defined(_WIN32) */
+void*  thread_store_get( thread_store_t*  store )
+{
+    if (!store->has_tls)
+        return NULL;
+
+    return (void*) TlsGetValue( store->tls );
+}
+
+void   thread_store_set( thread_store_t*          store,
+                         void*                    value,
+                         thread_store_destruct_t  /*destroy*/ )
+{
+    /* XXX: can't use destructor on thread exit */
+    if (!store->lock_init) {
+        store->lock_init = -1;
+        InitializeCriticalSection( &store->lock );
+        store->lock_init = -2;
+    } else while (store->lock_init != -2) {
+        Sleep(10); /* 10ms */
+    }
+
+    EnterCriticalSection( &store->lock );
+    if (!store->has_tls) {
+        store->tls = TlsAlloc();
+        if (store->tls == TLS_OUT_OF_INDEXES) {
+            LeaveCriticalSection( &store->lock );
+            return;
+        }
+        store->has_tls = 1;
+    }
+    LeaveCriticalSection( &store->lock );
+
+    TlsSetValue( store->tls, value );
+}
+#endif /* !defined(_WIN32) */
diff --git a/src/primitives.c b/src/primitives.c
new file mode 100644
index 0000000..8e92fdf
--- /dev/null
+++ b/src/primitives.c
@@ -0,0 +1,610 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+#include <cutils/bitops.h>  /* for popcount() */
+#include <audio_utils/primitives.h>
+#include "private/private.h"
+
+void ditherAndClamp(int32_t *out, const int32_t *sums, size_t pairs)
+{
+    for (; pairs > 0; --pairs) {
+        const int32_t l = clamp16(*sums++ >> 12);
+        const int32_t r = clamp16(*sums++ >> 12);
+        *out++ = (r << 16) | (l & 0xFFFF);
+    }
+}
+
+void memcpy_to_i16_from_q4_27(int16_t *dst, const int32_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = clamp16(*src++ >> 12);
+    }
+}
+
+void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count)
+{
+    dst += count;
+    src += count;
+    for (; count > 0; --count) {
+        *--dst = (int16_t)(*--src - 0x80) << 8;
+    }
+}
+
+void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = (*src++ >> 8) + 0x80;
+    }
+}
+
+void memcpy_to_u8_from_float(uint8_t *dst, const float *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = clamp8_from_float(*src++);
+    }
+}
+
+void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = *src++ >> 16;
+    }
+}
+
+void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = clamp16_from_float(*src++);
+    }
+}
+
+void memcpy_to_float_from_q4_27(float *dst, const int32_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = float_from_q4_27(*src++);
+    }
+}
+
+void memcpy_to_float_from_i16(float *dst, const int16_t *src, size_t count)
+{
+    dst += count;
+    src += count;
+    for (; count > 0; --count) {
+        *--dst = float_from_i16(*--src);
+    }
+}
+
+void memcpy_to_float_from_u8(float *dst, const uint8_t *src, size_t count)
+{
+    dst += count;
+    src += count;
+    for (; count > 0; --count) {
+        *--dst = float_from_u8(*--src);
+    }
+}
+
+void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count)
+{
+    dst += count;
+    src += count * 3;
+    for (; count > 0; --count) {
+        src -= 3;
+        *--dst = float_from_p24(src);
+    }
+}
+
+void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+#if HAVE_BIG_ENDIAN
+        *dst++ = src[1] | (src[0] << 8);
+#else
+        *dst++ = src[1] | (src[2] << 8);
+#endif
+        src += 3;
+    }
+}
+
+void memcpy_to_i32_from_p24(int32_t *dst, const uint8_t *src, size_t count)
+{
+    dst += count;
+    src += count * 3;
+    for (; count > 0; --count) {
+        src -= 3;
+#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);
+#endif
+    }
+}
+
+void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count)
+{
+    dst += count * 3;
+    src += count;
+    for (; count > 0; --count) {
+        dst -= 3;
+        const int16_t sample = *--src;
+#if HAVE_BIG_ENDIAN
+        dst[0] = sample >> 8;
+        dst[1] = sample;
+        dst[2] = 0;
+#else
+        dst[0] = 0;
+        dst[1] = sample;
+        dst[2] = sample >> 8;
+#endif
+    }
+}
+
+void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count)
+{
+    for (; count > 0; --count) {
+        int32_t ival = clamp24_from_float(*src++);
+
+#if HAVE_BIG_ENDIAN
+        *dst++ = ival >> 16;
+        *dst++ = ival >> 8;
+        *dst++ = ival;
+#else
+        *dst++ = ival;
+        *dst++ = ival >> 8;
+        *dst++ = ival >> 16;
+#endif
+    }
+}
+
+void memcpy_to_p24_from_q8_23(uint8_t *dst, const int32_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        int32_t ival = clamp24_from_q8_23(*src++);
+
+#if HAVE_BIG_ENDIAN
+        *dst++ = ival >> 16;
+        *dst++ = ival >> 8;
+        *dst++ = ival;
+#else
+        *dst++ = ival;
+        *dst++ = ival >> 8;
+        *dst++ = ival >> 16;
+#endif
+    }
+}
+
+void memcpy_to_p24_from_i32(uint8_t *dst, const int32_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        int32_t ival = *src++ >> 8;
+
+#if HAVE_BIG_ENDIAN
+        *dst++ = ival >> 16;
+        *dst++ = ival >> 8;
+        *dst++ = ival;
+#else
+        *dst++ = ival;
+        *dst++ = ival >> 8;
+        *dst++ = ival >> 16;
+#endif
+    }
+}
+
+void memcpy_to_q8_23_from_i16(int32_t *dst, const int16_t *src, size_t count)
+{
+    dst += count;
+    src += count;
+    for (; count > 0; --count) {
+        *--dst = (int32_t)*--src << 8;
+    }
+}
+
+void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = clamp24_from_float(*src++);
+    }
+}
+
+void memcpy_to_q8_23_from_p24(int32_t *dst, const uint8_t *src, size_t count)
+{
+    dst += count;
+    src += count * 3;
+    for (; count > 0; --count) {
+        src -= 3;
+#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];
+#endif
+    }
+}
+
+void memcpy_to_q4_27_from_float(int32_t *dst, const float *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = clampq4_27_from_float(*src++);
+    }
+}
+
+void memcpy_to_i16_from_q8_23(int16_t *dst, const int32_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = clamp16(*src++ >> 8);
+    }
+}
+
+void memcpy_to_float_from_q8_23(float *dst, const int32_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = float_from_q8_23(*src++);
+    }
+}
+
+void memcpy_to_i32_from_i16(int32_t *dst, const int16_t *src, size_t count)
+{
+    dst += count;
+    src += count;
+    for (; count > 0; --count) {
+        *--dst = (int32_t)*--src << 16;
+    }
+}
+
+void memcpy_to_i32_from_float(int32_t *dst, const float *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = clamp32_from_float(*src++);
+    }
+}
+
+void memcpy_to_float_from_i32(float *dst, const int32_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = float_from_i32(*src++);
+    }
+}
+
+void memcpy_to_float_from_float_with_clamping(float *dst, const float *src, size_t count,
+                                              float absMax) {
+    // Note: using NEON intrinsics (vminq_f32, vld1q_f32...) did NOT accelerate
+    // the function when benchmarked. The compiler already vectorize using FMINNM f32x4 & similar.
+    // Note: clamping induce a ~20% overhead compared to memcpy for count in [64, 512]
+    //       See primitives_benchmark
+    for (; count > 0; --count) {
+        const float sample = *src++;
+        *dst++ = fmax(-absMax, fmin(absMax, sample));
+    }
+}
+
+void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count)
+{
+    for (; count > 0; --count) {
+        *dst++ = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
+        src += 2;
+    }
+}
+
+void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count)
+{
+    dst += count * 2;
+    src += count;
+    for (; count > 0; --count) {
+        const int32_t temp = *--src;
+        dst -= 2;
+        dst[0] = temp;
+        dst[1] = temp;
+    }
+}
+
+void downmix_to_mono_float_from_stereo_float(float *dst, const float *src, size_t frames)
+{
+    for (; frames > 0; --frames) {
+        *dst++ = (src[0] + src[1]) * 0.5;
+        src += 2;
+    }
+}
+
+void upmix_to_stereo_float_from_mono_float(float *dst, const float *src, size_t frames)
+{
+    dst += frames * 2;
+    src += frames;
+    for (; frames > 0; --frames) {
+        const float temp = *--src;
+        dst -= 2;
+        dst[0] = temp;
+        dst[1] = temp;
+    }
+}
+
+size_t nonZeroMono32(const int32_t *samples, size_t count)
+{
+    size_t nonZero = 0;
+    for (; count > 0; --count) {
+        nonZero += *samples++ != 0;
+    }
+    return nonZero;
+}
+
+size_t nonZeroMono16(const int16_t *samples, size_t count)
+{
+    size_t nonZero = 0;
+    for (; count > 0; --count) {
+        nonZero += *samples++ != 0;
+    }
+    return nonZero;
+}
+
+size_t nonZeroStereo32(const int32_t *frames, size_t count)
+{
+    size_t nonZero = 0;
+    for (; count > 0; --count) {
+        nonZero += frames[0] != 0 || frames[1] != 0;
+        frames += 2;
+    }
+    return nonZero;
+}
+
+size_t nonZeroStereo16(const int16_t *frames, size_t count)
+{
+    size_t nonZero = 0;
+    for (; count > 0; --count) {
+        nonZero += frames[0] != 0 || frames[1] != 0;
+        frames += 2;
+    }
+    return nonZero;
+}
+
+/*
+ * C macro to do channel mask copying independent of dst/src sample type.
+ * Don't pass in any expressions for the macro arguments here.
+ */
+#define copy_frame_by_mask(dst, dmask, src, smask, count, zero) \
+{ \
+    uint32_t bit, ormask; \
+    for (; (count) > 0; --(count)) { \
+        ormask = (dmask) | (smask); \
+        while (ormask) { \
+            bit = ormask & -ormask; /* get lowest bit */ \
+            ormask ^= bit; /* remove lowest bit */ \
+            if ((dmask) & bit) { \
+                *(dst)++ = (smask) & bit ? *(src)++ : (zero); \
+            } else { /* source channel only */ \
+                ++(src); \
+            } \
+        } \
+    } \
+}
+
+void memcpy_by_channel_mask(void *dst, uint32_t dst_mask,
+        const void *src, uint32_t src_mask, size_t sample_size, size_t count)
+{
+#if 0
+    /* alternate way of handling memcpy_by_channel_mask by using the idxary */
+    int8_t idxary[32];
+    uint32_t src_channels = popcount(src_mask);
+    uint32_t dst_channels =
+            memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask);
+
+    memcpy_by_idxary(dst, dst_channels, src, src_channels, idxary, sample_size, count);
+#else
+    if (dst_mask == src_mask) {
+        memcpy(dst, src, sample_size * popcount(dst_mask) * count);
+        return;
+    }
+    switch (sample_size) {
+    case 1: {
+        uint8_t *udst = (uint8_t*)dst;
+        const uint8_t *usrc = (const uint8_t*)src;
+
+        copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
+    } break;
+    case 2: {
+        uint16_t *udst = (uint16_t*)dst;
+        const uint16_t *usrc = (const uint16_t*)src;
+
+        copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
+    } break;
+    case 3: { /* could be slow.  use a struct to represent 3 bytes of data. */
+        uint8x3_t *udst = (uint8x3_t*)dst;
+        const uint8x3_t *usrc = (const uint8x3_t*)src;
+        static const uint8x3_t zero; /* tricky - we use this to zero out a sample */
+
+        copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, zero);
+    } break;
+    case 4: {
+        uint32_t *udst = (uint32_t*)dst;
+        const uint32_t *usrc = (const uint32_t*)src;
+
+        copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
+    } break;
+    default:
+        abort(); /* illegal value */
+        break;
+    }
+#endif
+}
+
+/*
+ * C macro to do copying by index array, to rearrange samples
+ * within a frame.  This is independent of src/dst sample type.
+ * Don't pass in any expressions for the macro arguments here.
+ */
+#define copy_frame_by_idx(dst, dst_channels, src, src_channels, idxary, count, zero) \
+{ \
+    unsigned i; \
+    int index; \
+    for (; (count) > 0; --(count)) { \
+        for (i = 0; i < (dst_channels); ++i) { \
+            index = (idxary)[i]; \
+            *(dst)++ = index < 0 ? (zero) : (src)[index]; \
+        } \
+        (src) += (src_channels); \
+    } \
+}
+
+void memcpy_by_index_array(void *dst, uint32_t dst_channels,
+        const void *src, uint32_t src_channels,
+        const int8_t *idxary, size_t sample_size, size_t count)
+{
+    switch (sample_size) {
+    case 1: {
+        uint8_t *udst = (uint8_t*)dst;
+        const uint8_t *usrc = (const uint8_t*)src;
+
+        copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
+    } break;
+    case 2: {
+        uint16_t *udst = (uint16_t*)dst;
+        const uint16_t *usrc = (const uint16_t*)src;
+
+        copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
+    } break;
+    case 3: { /* could be slow.  use a struct to represent 3 bytes of data. */
+        uint8x3_t *udst = (uint8x3_t*)dst;
+        const uint8x3_t *usrc = (const uint8x3_t*)src;
+        static const uint8x3_t zero;
+
+        copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, zero);
+    } break;
+    case 4: {
+        uint32_t *udst = (uint32_t*)dst;
+        const uint32_t *usrc = (const uint32_t*)src;
+
+        copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
+    } break;
+    default:
+        abort(); /* illegal value */
+        break;
+    }
+}
+
+size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
+        uint32_t dst_mask, uint32_t src_mask)
+{
+    size_t n = 0;
+    int srcidx = 0;
+    uint32_t bit, ormask = src_mask | dst_mask;
+
+    while (ormask && n < idxcount) {
+        bit = ormask & -ormask;          /* get lowest bit */
+        ormask ^= bit;                   /* remove lowest bit */
+        if (src_mask & dst_mask & bit) { /* matching channel */
+            idxary[n++] = srcidx++;
+        } else if (src_mask & bit) {     /* source channel only */
+            ++srcidx;
+        } else {                         /* destination channel only */
+            idxary[n++] = -1;
+        }
+    }
+    return n + popcount(ormask & dst_mask);
+}
+
+size_t memcpy_by_index_array_initialization_src_index(int8_t *idxary, size_t idxcount,
+        uint32_t dst_mask, uint32_t src_mask) {
+    size_t dst_count = popcount(dst_mask);
+    if (idxcount == 0) {
+        return dst_count;
+    }
+    if (dst_count > idxcount) {
+        dst_count = idxcount;
+    }
+
+    size_t src_idx, dst_idx;
+    for (src_idx = 0, dst_idx = 0; dst_idx < dst_count; ++dst_idx) {
+        if (src_mask & 1) {
+            idxary[dst_idx] = src_idx++;
+        } else {
+            idxary[dst_idx] = -1;
+        }
+        src_mask >>= 1;
+    }
+    return dst_idx;
+}
+
+size_t memcpy_by_index_array_initialization_dst_index(int8_t *idxary, size_t idxcount,
+        uint32_t dst_mask, uint32_t src_mask) {
+    size_t src_idx, dst_idx;
+    size_t dst_count = __builtin_popcount(dst_mask);
+    size_t src_count = __builtin_popcount(src_mask);
+    if (idxcount == 0) {
+        return dst_count;
+    }
+    if (dst_count > idxcount) {
+        dst_count = idxcount;
+    }
+    for (src_idx = 0, dst_idx = 0; dst_idx < dst_count; ++src_idx) {
+        if (dst_mask & 1) {
+            idxary[dst_idx++] = src_idx < src_count ? (signed)src_idx : -1;
+        }
+        dst_mask >>= 1;
+    }
+    return dst_idx;
+}
+
+void accumulate_i16(int16_t *dst, const int16_t *src, size_t count) {
+    while (count--) {
+        *dst = clamp16((int32_t)*dst + *src++);
+        ++dst;
+    }
+}
+
+void accumulate_u8(uint8_t *dst, const uint8_t *src, size_t count) {
+    int32_t sum;
+    for (; count > 0; --count) {
+        // 8-bit samples are centered around 0x80.
+        sum = *dst + *src++ - 0x80;
+        // Clamp to [0, 0xff].
+        *dst++ = (sum & 0x100) ? (~sum >> 9) : sum;
+    }
+}
+
+void accumulate_p24(uint8_t *dst, const uint8_t *src, size_t count) {
+    for (; count > 0; --count) {
+        // Unpack.
+        int32_t dst_q8_23 = 0;
+        int32_t src_q8_23 = 0;
+        memcpy_to_q8_23_from_p24(&dst_q8_23, dst, 1);
+        memcpy_to_q8_23_from_p24(&src_q8_23, src, 1);
+
+        // Accumulate and overwrite.
+        dst_q8_23 += src_q8_23;
+        memcpy_to_p24_from_q8_23(dst, &dst_q8_23, 1);
+
+        // Move on to next sample.
+        dst += 3;
+        src += 3;
+  }
+}
+
+void accumulate_q8_23(int32_t *dst, const int32_t *src, size_t count) {
+    for (; count > 0; --count) {
+        *dst = clamp24_from_q8_23(*dst + *src++);
+        ++dst;
+    }
+}
+
+void accumulate_i32(int32_t *dst, const int32_t *src, size_t count) {
+    for (; count > 0; --count) {
+        *dst = clamp32((int64_t)*dst + *src++);
+        ++dst;
+    }
+}
+
+void accumulate_float(float *dst, const float *src, size_t count) {
+    for (; count > 0; --count) {
+        *dst++ += *src++;
+    }
+}
diff --git a/src/resampler.c b/src/resampler.c
new file mode 100644
index 0000000..43ba895
--- /dev/null
+++ b/src/resampler.c
@@ -0,0 +1,265 @@
+/*
+** Copyright 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "resampler"
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <cutils/log.h>
+
+#include <system/audio.h>
+#include <audio_utils/resampler.h>
+#include <speex/speex_resampler.h>
+
+struct resampler {
+    struct resampler_itfe itfe;
+    SpeexResamplerState *speex_resampler;       // handle on speex resampler
+    struct resampler_buffer_provider *provider; // buffer provider installed by client
+    uint32_t in_sample_rate;                    // input sampling rate in Hz
+    uint32_t out_sample_rate;                   // output sampling rate in Hz
+    uint32_t channel_count;                     // number of channels (interleaved)
+    int16_t *in_buf;                            // input buffer
+    size_t in_buf_size;                         // input buffer size
+    size_t frames_in;                           // number of frames in input buffer
+    size_t frames_rq;                           // cached number of output frames
+    size_t frames_needed;                       // minimum number of input frames to produce
+                                                // frames_rq output frames
+    int32_t speex_delay_ns;                     // delay introduced by speex resampler in ns
+};
+
+
+//------------------------------------------------------------------------------
+// speex based resampler
+//------------------------------------------------------------------------------
+
+static void resampler_reset(struct resampler_itfe *resampler)
+{
+    struct resampler *rsmp = (struct resampler *)resampler;
+
+    rsmp->frames_in = 0;
+    rsmp->frames_rq = 0;
+
+    if (rsmp != NULL && rsmp->speex_resampler != NULL) {
+        speex_resampler_reset_mem(rsmp->speex_resampler);
+    }
+}
+
+static int32_t resampler_delay_ns(struct resampler_itfe *resampler)
+{
+    struct resampler *rsmp = (struct resampler *)resampler;
+
+    int32_t delay = (int32_t)((1000000000 * (int64_t)rsmp->frames_in) / rsmp->in_sample_rate);
+    delay += rsmp->speex_delay_ns;
+
+    return delay;
+}
+
+// outputs a number of frames less or equal to *outFrameCount and updates *outFrameCount
+// with the actual number of frames produced.
+int resampler_resample_from_provider(struct resampler_itfe *resampler,
+                       int16_t *out,
+                       size_t *outFrameCount)
+{
+    struct resampler *rsmp = (struct resampler *)resampler;
+
+    if (rsmp == NULL || out == NULL || outFrameCount == NULL) {
+        return -EINVAL;
+    }
+    if (rsmp->provider == NULL) {
+        *outFrameCount = 0;
+        return -ENOSYS;
+    }
+
+    size_t framesRq = *outFrameCount;
+    // update and cache the number of frames needed at the input sampling rate to produce
+    // the number of frames requested at the output sampling rate
+    if (framesRq != rsmp->frames_rq) {
+        rsmp->frames_needed = (framesRq * rsmp->in_sample_rate) / rsmp->out_sample_rate + 1;
+        rsmp->frames_rq = framesRq;
+    }
+
+    size_t framesWr = 0;
+    spx_uint32_t inFrames = 0;
+    while (framesWr < framesRq) {
+        if (rsmp->frames_in < rsmp->frames_needed) {
+            // make sure that the number of frames present in rsmp->in_buf (rsmp->frames_in) is at
+            // least the number of frames needed to produce the number of frames requested at
+            // the output sampling rate
+            if (rsmp->in_buf_size < rsmp->frames_needed) {
+                rsmp->in_buf_size = rsmp->frames_needed;
+                rsmp->in_buf = (int16_t *)realloc(rsmp->in_buf,
+                                        rsmp->in_buf_size * rsmp->channel_count * sizeof(int16_t));
+            }
+            struct resampler_buffer buf;
+            buf.frame_count = rsmp->frames_needed - rsmp->frames_in;
+            rsmp->provider->get_next_buffer(rsmp->provider, &buf);
+            if (buf.raw == NULL) {
+                break;
+            }
+            memcpy(rsmp->in_buf + rsmp->frames_in * rsmp->channel_count,
+                    buf.raw,
+                    buf.frame_count * rsmp->channel_count * sizeof(int16_t));
+            rsmp->frames_in += buf.frame_count;
+            rsmp->provider->release_buffer(rsmp->provider, &buf);
+        }
+
+        spx_uint32_t outFrames = framesRq - framesWr;
+        inFrames = rsmp->frames_in;
+        if (rsmp->channel_count == 1) {
+            speex_resampler_process_int(rsmp->speex_resampler,
+                                        0,
+                                        rsmp->in_buf,
+                                        &inFrames,
+                                        out + framesWr,
+                                        &outFrames);
+        } else {
+            speex_resampler_process_interleaved_int(rsmp->speex_resampler,
+                                        rsmp->in_buf,
+                                        &inFrames,
+                                        out + framesWr * rsmp->channel_count,
+                                        &outFrames);
+        }
+        framesWr += outFrames;
+        rsmp->frames_in -= inFrames;
+        ALOGW_IF((framesWr != framesRq) && (rsmp->frames_in != 0),
+                "ReSampler::resample() remaining %zu frames in and %zu frames out",
+                rsmp->frames_in, (framesRq - framesWr));
+    }
+    if (rsmp->frames_in) {
+        memmove(rsmp->in_buf,
+                rsmp->in_buf + inFrames * rsmp->channel_count,
+                rsmp->frames_in * rsmp->channel_count * sizeof(int16_t));
+    }
+    *outFrameCount = framesWr;
+
+    return 0;
+}
+
+int resampler_resample_from_input(struct resampler_itfe *resampler,
+                                  int16_t *in,
+                                  size_t *inFrameCount,
+                                  int16_t *out,
+                                  size_t *outFrameCount)
+{
+    struct resampler *rsmp = (struct resampler *)resampler;
+
+    if (rsmp == NULL || in == NULL || inFrameCount == NULL ||
+            out == NULL || outFrameCount == NULL) {
+        return -EINVAL;
+    }
+    if (rsmp->provider != NULL) {
+        *outFrameCount = 0;
+        return -ENOSYS;
+    }
+
+    if (rsmp->channel_count == 1) {
+        speex_resampler_process_int(rsmp->speex_resampler,
+                                    0,
+                                    in,
+                                    (spx_uint32_t *)inFrameCount,
+                                    out,
+                                    (spx_uint32_t *)outFrameCount);
+    } else {
+        speex_resampler_process_interleaved_int(rsmp->speex_resampler,
+                                                in,
+                                                (spx_uint32_t *)inFrameCount,
+                                                out,
+                                                (spx_uint32_t *)outFrameCount);
+    }
+
+    ALOGV("resampler_resample_from_input() DONE in %zu out %zu", *inFrameCount, *outFrameCount);
+
+    return 0;
+}
+
+int create_resampler(uint32_t inSampleRate,
+                    uint32_t outSampleRate,
+                    uint32_t channelCount,
+                    uint32_t quality,
+                    struct resampler_buffer_provider* provider,
+                    struct resampler_itfe **resampler)
+{
+    int error;
+    struct resampler *rsmp;
+
+    ALOGV("create_resampler() In SR %d Out SR %d channels %d",
+         inSampleRate, outSampleRate, channelCount);
+
+    if (resampler == NULL) {
+        return -EINVAL;
+    }
+
+    *resampler = NULL;
+
+    if (quality <= RESAMPLER_QUALITY_MIN || quality >= RESAMPLER_QUALITY_MAX) {
+        return -EINVAL;
+    }
+
+    rsmp = (struct resampler *)calloc(1, sizeof(struct resampler));
+
+    rsmp->speex_resampler = speex_resampler_init(channelCount,
+                                      inSampleRate,
+                                      outSampleRate,
+                                      quality,
+                                      &error);
+    if (rsmp->speex_resampler == NULL) {
+        ALOGW("ReSampler: Cannot create speex resampler: %s", speex_resampler_strerror(error));
+        free(rsmp);
+        return -ENODEV;
+    }
+
+    rsmp->itfe.reset = resampler_reset;
+    rsmp->itfe.resample_from_provider = resampler_resample_from_provider;
+    rsmp->itfe.resample_from_input = resampler_resample_from_input;
+    rsmp->itfe.delay_ns = resampler_delay_ns;
+
+    rsmp->provider = provider;
+    rsmp->in_sample_rate = inSampleRate;
+    rsmp->out_sample_rate = outSampleRate;
+    rsmp->channel_count = channelCount;
+    rsmp->in_buf = NULL;
+    rsmp->in_buf_size = 0;
+
+    resampler_reset(&rsmp->itfe);
+
+    int frames = speex_resampler_get_input_latency(rsmp->speex_resampler);
+    rsmp->speex_delay_ns = (int32_t)((1000000000 * (int64_t)frames) / rsmp->in_sample_rate);
+    frames = speex_resampler_get_output_latency(rsmp->speex_resampler);
+    rsmp->speex_delay_ns += (int32_t)((1000000000 * (int64_t)frames) / rsmp->out_sample_rate);
+
+    *resampler = &rsmp->itfe;
+    ALOGV("create_resampler() DONE rsmp %p &rsmp->itfe %p speex %p",
+         rsmp, &rsmp->itfe, rsmp->speex_resampler);
+    return 0;
+}
+
+void release_resampler(struct resampler_itfe *resampler)
+{
+    struct resampler *rsmp = (struct resampler *)resampler;
+
+    if (rsmp == NULL) {
+        return;
+    }
+
+    free(rsmp->in_buf);
+
+    if (rsmp->speex_resampler != NULL) {
+        speex_resampler_destroy(rsmp->speex_resampler);
+    }
+    free(rsmp);
+}
diff --git a/src/spdif/AC3FrameScanner.cpp b/src/spdif/AC3FrameScanner.cpp
new file mode 100644
index 0000000..6c92099
--- /dev/null
+++ b/src/spdif/AC3FrameScanner.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2014, 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_TAG "AudioSPDIF"
+
+#include <string.h>
+
+#include <cutils/log.h>
+#include <audio_utils/spdif/FrameScanner.h>
+
+#include "AC3FrameScanner.h"
+
+namespace android {
+
+// These values are from the AC3 spec. Do not change them.
+
+const uint8_t AC3FrameScanner::kSyncBytes[] = { 0x0B, 0x77 };
+
+const uint16_t AC3FrameScanner::kAC3SampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES]
+    = { 48000, 44100, 32000 };
+
+// Table contains number of 16-bit words in an AC3 frame.
+// From AC3 spec table 5.13
+const uint16_t AC3FrameScanner::kAC3FrameSizeTable[AC3_NUM_FRAME_SIZE_TABLE_ENTRIES]
+        [AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES] = {
+    { 64, 69, 96 },
+    { 64, 70, 96 },
+    { 80, 87, 120 },
+    { 80, 88, 120 },
+    { 96, 104, 144 },
+    { 96, 105, 144 },
+    { 112, 121, 168 },
+    { 112, 122, 168 },
+    { 128, 139, 192 },
+    { 128, 140, 192 },
+    { 160, 174, 240 },
+    { 160, 175, 240 },
+    { 192, 208, 288 },
+    { 192, 209, 288 },
+    { 224, 243, 336 },
+    { 224, 244, 336 },
+    { 256, 278, 384 },
+    { 256, 279, 384 },
+    { 320, 348, 480 },
+    { 320, 349, 480 },
+    { 384, 417, 576 },
+    { 384, 418, 576 },
+    { 448, 487, 672 },
+    { 448, 488, 672 },
+    { 512, 557, 768 },
+    { 512, 558, 768 },
+    { 640, 696, 960 },
+    { 640, 697, 960 },
+    { 768, 835, 1152 },
+    { 768, 836, 1152 },
+    { 896, 975, 1344 },
+    { 896, 976, 1344 },
+    { 1024, 1114, 1536 },
+    { 1024, 1115, 1536 },
+    { 1152, 1253, 1728 },
+    { 1152, 1254, 1728 },
+    { 1280, 1393, 1920 },
+    { 1280, 1394, 1920 }
+};
+
+const uint16_t AC3FrameScanner::kEAC3ReducedSampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES]
+        = { 24000, 22050, 16000 };
+
+const uint16_t
+        AC3FrameScanner::kEAC3BlocksPerFrameTable[EAC3_NUM_BLOCKS_PER_FRAME_TABLE_ENTRIES]
+        = { 1, 2, 3, 6 };
+
+// Defined in IEC61937-2
+#define SPDIF_DATA_TYPE_AC3     1
+#define SPDIF_DATA_TYPE_E_AC3  21
+#define AC3_STREAM_TYPE_0       0
+#define AC3_STREAM_TYPE_1       1
+#define AC3_STREAM_TYPE_2       2
+// -----------------------------------------------------------------------------
+
+// Scanner for AC3 byte streams.
+AC3FrameScanner::AC3FrameScanner(audio_format_t format)
+ : FrameScanner(SPDIF_DATA_TYPE_AC3,
+        AC3FrameScanner::kSyncBytes,
+        sizeof(AC3FrameScanner::kSyncBytes), 6)
+ , mStreamType(0)
+ , mSubstreamID(0)
+ , mFormat(format)
+{
+    mAudioBlocksPerSyncFrame = 6;
+    memset(mSubstreamBlockCounts, 0, sizeof(mSubstreamBlockCounts));
+}
+
+AC3FrameScanner::~AC3FrameScanner()
+{
+}
+
+int AC3FrameScanner::getSampleFramesPerSyncFrame() const
+{
+    return mRateMultiplier
+            * AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK * AC3_PCM_FRAMES_PER_BLOCK;
+}
+
+void AC3FrameScanner::resetBurst()
+{
+    for (int i = 0; i < EAC3_MAX_SUBSTREAMS; i++) {
+        if (mSubstreamBlockCounts[i] >= AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK) {
+            mSubstreamBlockCounts[i] -= AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK;
+        } else if (mSubstreamBlockCounts[i] > 0) {
+            ALOGW("EAC3 substream[%d] has only %d audio blocks!",
+                i, mSubstreamBlockCounts[i]);
+            mSubstreamBlockCounts[i] = 0;
+        }
+    }
+}
+
+// Per IEC 61973-3:5.3.3, for E-AC3 burst-length shall be in bytes.
+uint16_t AC3FrameScanner::convertBytesToLengthCode(uint16_t numBytes) const
+{
+    return (mDataType == SPDIF_DATA_TYPE_E_AC3) ? numBytes : numBytes * 8;
+}
+
+// per IEC 61973-3 Paragraph 5.3.3
+// We have to send 6 audio blocks on all active substreams.
+// Substream zero must be the first.
+// We don't know if we have all the blocks we need until we see
+// the 7th block of substream#0.
+bool AC3FrameScanner::isFirstInBurst()
+{
+    if (mDataType == SPDIF_DATA_TYPE_E_AC3) {
+        if (((mStreamType == AC3_STREAM_TYPE_0)
+                || (mStreamType == AC3_STREAM_TYPE_2))
+                && (mSubstreamID == 0)
+                // The ">" is intentional. We have to see the beginning
+                // of the block in the next burst before we can send
+                // the current burst.
+                && (mSubstreamBlockCounts[0] > AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AC3FrameScanner::isLastInBurst()
+{
+    // For EAC3 we don't know if we are the end until we see a
+    // frame that must be at the beginning. See isFirstInBurst().
+    return (mDataType != SPDIF_DATA_TYPE_E_AC3); // Just one AC3 frame per burst.
+}
+
+// TODO Use BitFieldParser
+
+// Parse AC3 header.
+// Detect whether the stream is AC3 or EAC3. Extract data depending on type.
+//
+// @return true if valid
+bool AC3FrameScanner::parseHeader()
+{
+    // Interpret bsid based on paragraph E2.3.1.6 of EAC3 spec.
+    uint32_t bsid = mHeaderBuffer[5] >> 3; // bitstream ID
+    // Check BSID to see if this is EAC3 or regular AC3.
+    // These arbitrary BSID numbers do not have any names in the spec.
+    if ((bsid > 10) && (bsid <= 16)) {
+        mDataType = SPDIF_DATA_TYPE_E_AC3;
+    } else if (bsid <= 8) {
+        mDataType = SPDIF_DATA_TYPE_AC3;
+    } else {
+        ALOGW("AC3 bsid = %d not supported", bsid);
+        return false;
+    }
+
+    // bitstream mode, main, commentary, etc.
+    uint32_t bsmod = mHeaderBuffer[5] & 7;
+    mDataTypeInfo = bsmod; // as per IEC61937-3, table 3.
+
+    // The names fscod, frmsiz are from the AC3 spec.
+    uint32_t fscod = mHeaderBuffer[4] >> 6;
+    if (mDataType == SPDIF_DATA_TYPE_E_AC3) {
+        mStreamType = mHeaderBuffer[2] >> 6; // strmtyp in spec
+        mSubstreamID = (mHeaderBuffer[2] >> 3) & 0x07;
+
+        // Frame size is explicit in EAC3. Paragraph E2.3.1.3
+        uint32_t frmsiz = ((mHeaderBuffer[2] & 0x07) << 8) + mHeaderBuffer[3];
+        mFrameSizeBytes = (frmsiz + 1) * sizeof(int16_t);
+
+        uint32_t numblkscod = 3; // 6 blocks default
+        if (fscod == 3) {
+            uint32_t fscod2 = (mHeaderBuffer[4] >> 4) & 0x03;
+            if (fscod2 >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
+                ALOGW("Invalid EAC3 fscod2 = %d", fscod2);
+                return false;
+            } else {
+                mSampleRate = kEAC3ReducedSampleRateTable[fscod2];
+            }
+        } else {
+            mSampleRate = kAC3SampleRateTable[fscod];
+            numblkscod = (mHeaderBuffer[4] >> 4) & 0x03;
+        }
+        mRateMultiplier = EAC3_RATE_MULTIPLIER; // per IEC 61973-3 Paragraph 5.3.3
+        // Don't send data burst until we have 6 blocks per substream.
+        mAudioBlocksPerSyncFrame = kEAC3BlocksPerFrameTable[numblkscod];
+        // Keep track of how many audio blocks we have for each substream.
+        // This should be safe because mSubstreamID is ANDed with 0x07 above.
+        // And the array is allocated as [8].
+        if ((mStreamType == AC3_STREAM_TYPE_0)
+                || (mStreamType == AC3_STREAM_TYPE_2)) {
+            mSubstreamBlockCounts[mSubstreamID] += mAudioBlocksPerSyncFrame;
+        }
+
+        // Print enough so we can see all the substreams.
+        ALOGD_IF((mFormatDumpCount < 3*8 ),
+                "EAC3 mStreamType = %d, mSubstreamID = %d",
+                mStreamType, mSubstreamID);
+    } else { // regular AC3
+        // Extract sample rate and frame size from codes.
+        uint32_t frmsizcod = mHeaderBuffer[4] & 0x3F; // frame size code
+
+        if (fscod >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
+            ALOGW("Invalid AC3 sampleRateCode = %d", fscod);
+            return false;
+        } else if (frmsizcod >= AC3_NUM_FRAME_SIZE_TABLE_ENTRIES) {
+            ALOGW("Invalid AC3 frameSizeCode = %d", frmsizcod);
+            return false;
+        } else {
+            mSampleRate = kAC3SampleRateTable[fscod];
+            mRateMultiplier = 1;
+            mFrameSizeBytes = sizeof(uint16_t)
+                    * kAC3FrameSizeTable[frmsizcod][fscod];
+        }
+        mAudioBlocksPerSyncFrame = 6;
+        if (mFormat == AUDIO_FORMAT_E_AC3) {
+            ALOGV("Its a Ac3 substream in EAC3 stream");
+            mStreamType = 2;
+            mSubstreamID = 0;
+            mSubstreamBlockCounts[0] += mAudioBlocksPerSyncFrame;
+            mDataType = SPDIF_DATA_TYPE_E_AC3;
+            mRateMultiplier = EAC3_RATE_MULTIPLIER;
+        }
+    }
+    ALOGI_IF((mFormatDumpCount == 0),
+            "AC3 frame rate = %d * %d, size = %zu, audioBlocksPerSyncFrame = %d",
+            mSampleRate, mRateMultiplier, mFrameSizeBytes, mAudioBlocksPerSyncFrame);
+    mFormatDumpCount++;
+    return true;
+}
+
+}  // namespace android
diff --git a/src/spdif/AC3FrameScanner.h b/src/spdif/AC3FrameScanner.h
new file mode 100644
index 0000000..a73a860
--- /dev/null
+++ b/src/spdif/AC3FrameScanner.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2014, 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_AC3_FRAME_SCANNER_H
+#define ANDROID_AUDIO_AC3_FRAME_SCANNER_H
+
+#include <stdint.h>
+#include <system/audio.h>
+#include <audio_utils/spdif/FrameScanner.h>
+
+namespace android {
+
+#define AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES          3
+#define AC3_NUM_FRAME_SIZE_TABLE_ENTRIES          38
+#define AC3_PCM_FRAMES_PER_BLOCK                 256
+#define AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK        6
+#define EAC3_RATE_MULTIPLIER                       4
+#define EAC3_NUM_SAMPLE_RATE_TABLE_ENTRIES         3
+#define EAC3_NUM_BLOCKS_PER_FRAME_TABLE_ENTRIES   38
+#define EAC3_MAX_SUBSTREAMS                        8
+
+class AC3FrameScanner : public FrameScanner
+{
+public:
+    explicit AC3FrameScanner(audio_format_t format);
+    virtual ~AC3FrameScanner();
+
+    virtual int getMaxChannels()   const { return 5 + 1; } // 5.1 surround
+
+    virtual int getMaxSampleFramesPerSyncFrame() const { return EAC3_RATE_MULTIPLIER
+            * AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK * AC3_PCM_FRAMES_PER_BLOCK; }
+    virtual int getSampleFramesPerSyncFrame() const;
+
+    virtual bool isFirstInBurst();
+    virtual bool isLastInBurst();
+    virtual void resetBurst();
+
+    virtual uint16_t convertBytesToLengthCode(uint16_t numBytes) const;
+
+protected:
+    // Keep track of how many of each substream blocks have been accumulated.
+    // We need all of each substream before sending block data burst.
+    uint8_t   mSubstreamBlockCounts[EAC3_MAX_SUBSTREAMS];
+    int       mAudioBlocksPerSyncFrame;
+    // The type of EAC3 stream as per EAC3 spec paragraph 2.3.1.1
+    uint32_t  mStreamType;
+    // substream index
+    uint32_t  mSubstreamID;
+    audio_format_t mFormat;
+
+    // used to recognize the start of an AC3 sync frame
+    static const uint8_t  kSyncBytes[];
+    // sample rates from AC3 spec table 5.1
+    static const uint16_t kAC3SampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES];
+    // frame sizes from AC3 spec table 5.13
+    static const uint16_t kAC3FrameSizeTable[AC3_NUM_FRAME_SIZE_TABLE_ENTRIES]
+            [AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES];
+    // sample rates from EAC3 spec table E2.3
+    static const uint16_t kEAC3ReducedSampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES];
+    // audio blocks per frame from EAC3 spec table E2.4
+    static const uint16_t kEAC3BlocksPerFrameTable[EAC3_NUM_BLOCKS_PER_FRAME_TABLE_ENTRIES];
+
+    virtual bool parseHeader();
+};
+
+}  // namespace android
+
+#endif  // ANDROID_AUDIO_AC3_FRAME_SCANNER_H
diff --git a/src/spdif/BitFieldParser.cpp b/src/spdif/BitFieldParser.cpp
new file mode 100644
index 0000000..d513320
--- /dev/null
+++ b/src/spdif/BitFieldParser.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright 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_TAG "AudioSPDIF"
+//#define LOG_NDEBUG 0
+
+#include <string.h>
+#include <assert.h>
+
+#include <cutils/log.h>
+#include "BitFieldParser.h"
+
+namespace android {
+
+BitFieldParser::BitFieldParser(uint8_t *data)
+ : mData(data)
+ , mBitCursor(0)
+{
+}
+
+BitFieldParser::~BitFieldParser()
+{
+}
+
+uint32_t BitFieldParser::readBits(uint32_t numBits)
+{
+    ALOG_ASSERT(numBits <= 32);
+
+    // Extract some bits from the current byte.
+    uint32_t byteCursor = mBitCursor >> 3; // 8 bits per byte
+    uint8_t byte = mData[byteCursor];
+
+    uint32_t bitsLeftInByte = 8 - (mBitCursor & 7);
+    uint32_t bitsFromByte = (bitsLeftInByte < numBits) ? bitsLeftInByte : numBits;
+    uint32_t result = byte >> (bitsLeftInByte - bitsFromByte);
+    result &= (1 << bitsFromByte) - 1; // mask
+    mBitCursor += bitsFromByte;
+
+    uint32_t bitsRemaining = numBits - bitsFromByte;
+    if (bitsRemaining == 0) {
+        return result;
+    } else {
+        // Use recursion to get remaining bits.
+        return (result << bitsRemaining) | readBits(bitsRemaining);
+    }
+}
+
+}  // namespace android
diff --git a/src/spdif/BitFieldParser.h b/src/spdif/BitFieldParser.h
new file mode 100644
index 0000000..3f6fe59
--- /dev/null
+++ b/src/spdif/BitFieldParser.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef ANDROID_AUDIO_BIT_FIELD_PARSER_H
+#define ANDROID_AUDIO_BIT_FIELD_PARSER_H
+
+#include <stdint.h>
+
+namespace android {
+
+/**
+ * Extract bit fields from a byte array.
+ */
+class BitFieldParser {
+public:
+
+    explicit BitFieldParser(uint8_t *data);
+    virtual ~BitFieldParser();
+
+    /**
+     * Read numBits bits from the data array.
+     * Fields may span byte boundaries but may not exceed 32-bits.
+     * Note that the caller must ensure that there is suffcient data.
+     * Assume data is organized as BigEndian format.
+     */
+    uint32_t readBits(uint32_t numBits);
+
+    /*
+     * When the cursor is zero it points to a position right before
+     * the most significant bit.
+     * When the cursor is seven it points to a position right before
+     * the least significant bit.
+     */
+    uint32_t getBitCursor() const { return mBitCursor; }
+
+private:
+    uint8_t *mData;
+    uint32_t mBitCursor;
+};
+
+
+}  // namespace android
+
+#endif  // ANDROID_AUDIO_BIT_FIELD_PARSER_H
diff --git a/src/spdif/DTSFrameScanner.cpp b/src/spdif/DTSFrameScanner.cpp
new file mode 100644
index 0000000..941e8b9
--- /dev/null
+++ b/src/spdif/DTSFrameScanner.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright 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_TAG "AudioSPDIF"
+//#define LOG_NDEBUG 0
+
+#include <assert.h>
+#include <string.h>
+
+#include <cutils/log.h>
+#include <audio_utils/spdif/FrameScanner.h>
+
+#include "BitFieldParser.h"
+#include "DTSFrameScanner.h"
+
+namespace android {
+
+// TODO Handle termination frames.
+// TODO assert if parse past end of header buffer
+// TODO Handle DTS_HD
+
+const uint8_t DTSFrameScanner::kSyncBytes[] =
+        { 0x7F, 0xFE, 0x80, 0x01 };
+
+const int32_t DTSFrameScanner::kDTSSampleRateTable[DTS_NUM_SAMPLE_RATE_TABLE_ENTRIES]
+        = { -1, 8000, 16000, 32000, -1, -1,
+        11025, 22050, 44100, -1, -1, 12000, 24000, 48000, -1, -1 };
+
+// Defined in IEC61937-2
+#define IEC61937_DATA_TYPE_DTS_I        11
+#define IEC61937_DATA_TYPE_DTS_II       12
+#define IEC61937_DATA_TYPE_DTS_III      13
+#define IEC61937_DATA_TYPE_DTS_IV       17
+
+#define IEC61937_MAX_SAMPLES_TYPE_I    512
+#define IEC61937_MAX_SAMPLES_TYPE_II  1024
+#define IEC61937_MAX_SAMPLES_TYPE_III 2048
+
+// Limits defined in DTS spec paragraph 5.3.1
+#define DTS_MINIMUM_NBLKS                5
+#define DTS_MINIMUM_FSIZE               95
+
+#define DTS_HEADER_BYTES_NEEDED         12
+
+// Scanner for DTS byte streams.
+DTSFrameScanner::DTSFrameScanner()
+ : FrameScanner(IEC61937_DATA_TYPE_DTS_I,
+    DTSFrameScanner::kSyncBytes,
+    sizeof(DTSFrameScanner::kSyncBytes),
+    DTS_HEADER_BYTES_NEEDED)
+ , mSampleFramesPerSyncFrame(0)
+{
+}
+
+DTSFrameScanner::~DTSFrameScanner()
+{
+}
+
+// Parse DTS header.
+// Detect whether the stream is DTS or DTS_HD. Extract data depending on type.
+// Sets mDataType, mFrameSizeBytes,
+//      mSampleRate, mRateMultiplier, mLengthCode.
+//
+// @return true if valid
+bool DTSFrameScanner::parseHeader()
+{
+    BitFieldParser parser(&mHeaderBuffer[mSyncLength]);
+
+    // These variables are named after the fields in the DTS spec 5.3.1
+    // Extract field in order.
+    (void) /* uint32_t ftype = */ parser.readBits(1);
+    (void) /* uint32_t deficit = */ parser.readBits(5); // "short"
+    uint32_t cpf = parser.readBits(1);
+    uint32_t nblks = parser.readBits(7);
+    uint32_t fsize = parser.readBits(14);
+    (void) /* uint32_t amode = */ parser.readBits(6);
+    uint32_t sfreq = parser.readBits(4);
+    // make sure we did not read past collected data
+    ALOG_ASSERT((mSyncLength + ((parser.getBitCursor() + 7) >> 3))
+            <= mHeaderLength);
+
+    // Validate fields.
+    if (cpf != 0) {
+        ALOGE("DTSFrameScanner: ERROR - CPF not zero!");
+        return false;
+    }
+    if (nblks < DTS_MINIMUM_NBLKS) {
+        ALOGE("DTSFrameScanner: ERROR - nblks = %u", nblks);
+        return false;
+    }
+    if (fsize < DTS_MINIMUM_FSIZE) {
+        ALOGE("DTSFrameScanner: ERROR - fsize = %u", fsize);
+        return false;
+    }
+
+    int32_t sampleRate = kDTSSampleRateTable[sfreq];
+    if (sampleRate < 0) {
+        ALOGE("DTSFrameScanner: ERROR - invalid sampleRate[%u] = %d", sfreq, sampleRate);
+        return false;
+    }
+    mSampleRate = (uint32_t) sampleRate;
+
+    mSampleFramesPerSyncFrame = (nblks + 1) * DTS_PCM_FRAMES_PER_BLOCK;
+    if (mSampleFramesPerSyncFrame <= IEC61937_MAX_SAMPLES_TYPE_I) {
+        mDataType = IEC61937_DATA_TYPE_DTS_I;
+    } else if (mSampleFramesPerSyncFrame <= IEC61937_MAX_SAMPLES_TYPE_II) {
+        mDataType = IEC61937_DATA_TYPE_DTS_II;
+    } else if (mSampleFramesPerSyncFrame <= IEC61937_MAX_SAMPLES_TYPE_III) {
+        mDataType = IEC61937_DATA_TYPE_DTS_III;
+    } else {
+        mDataType = IEC61937_DATA_TYPE_DTS_IV;
+        // TODO set bits 8,10
+    }
+
+    mFrameSizeBytes = fsize + 1;
+
+    mRateMultiplier = 1; // TODO what about "frequency extension"?
+    ALOGI_IF((mFormatDumpCount == 0),
+            "DTS frame rate = %d * %d, size = %zu",
+            mSampleRate, mRateMultiplier, mFrameSizeBytes);
+    mFormatDumpCount++;
+    return true;
+}
+
+
+}  // namespace android
diff --git a/src/spdif/DTSFrameScanner.h b/src/spdif/DTSFrameScanner.h
new file mode 100644
index 0000000..883ded9
--- /dev/null
+++ b/src/spdif/DTSFrameScanner.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef ANDROID_AUDIO_DTS_FRAME_SCANNER_H
+#define ANDROID_AUDIO_DTS_FRAME_SCANNER_H
+
+#include <stdint.h>
+#include <audio_utils/spdif/FrameScanner.h>
+
+namespace android {
+
+#define DTS_NUM_SAMPLE_RATE_TABLE_ENTRIES      16
+#define DTS_PCM_FRAMES_PER_BLOCK               32
+#define DTS_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK   128
+
+class DTSFrameScanner : public FrameScanner
+{
+public:
+    DTSFrameScanner();
+    virtual ~DTSFrameScanner();
+
+    virtual int getMaxChannels()   const { return 5 + 1; }
+
+    virtual int getMaxSampleFramesPerSyncFrame() const {
+        return  DTS_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK * DTS_PCM_FRAMES_PER_BLOCK;
+    }
+
+    virtual int getSampleFramesPerSyncFrame() const {
+        return mSampleFramesPerSyncFrame;
+    }
+
+    virtual bool isFirstInBurst() { return true; }
+    virtual bool isLastInBurst() { return true; }
+    virtual void resetBurst()  { }
+
+protected:
+
+    int mSampleFramesPerSyncFrame;
+
+    virtual bool parseHeader();
+
+    static const uint8_t kSyncBytes[];
+    static const int32_t kDTSSampleRateTable[];
+
+};
+
+}  // namespace android
+#endif  // ANDROID_AUDIO_DTS_FRAME_SCANNER_H
diff --git a/src/spdif/FrameScanner.cpp b/src/spdif/FrameScanner.cpp
new file mode 100644
index 0000000..c13d960
--- /dev/null
+++ b/src/spdif/FrameScanner.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2014, 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_TAG "AudioSPDIF"
+
+#include <string.h>
+#include <assert.h>
+
+#include <cutils/log.h>
+#include <audio_utils/spdif/FrameScanner.h>
+
+namespace android {
+
+FrameScanner::FrameScanner(int dataType,
+            const uint8_t *syncBytes,
+            uint32_t syncLength,
+            uint32_t headerLength)
+ : mBytesSkipped(0)
+ , mSyncBytes(syncBytes)
+ , mSyncLength(syncLength)
+ , mHeaderLength(headerLength)
+ , mCursor(0)
+ , mFormatDumpCount(0)
+ , mSampleRate(0)
+ , mRateMultiplier(1)
+ , mFrameSizeBytes(0)
+ , mDataType(dataType)
+ , mDataTypeInfo(0)
+{
+}
+
+FrameScanner::~FrameScanner()
+{
+}
+
+// State machine that scans for headers in a byte stream.
+// @return true if we have detected a complete and valid header.
+bool FrameScanner::scan(uint8_t byte)
+{
+    bool result = false;
+    ALOGV("FrameScanner: byte = 0x%02X, mCursor = %d", byte, mCursor);
+    assert(mCursor < sizeof(mHeaderBuffer));
+    if (mCursor < mSyncLength) {
+        // match sync word
+        if (byte == mSyncBytes[mCursor]) {
+            mHeaderBuffer[mCursor++] = byte;
+        } else {
+            mBytesSkipped += 1; // skip unsynchronized data
+            mCursor = 0;
+        }
+    } else if (mCursor < mHeaderLength) {
+        // gather header for parsing
+        mHeaderBuffer[mCursor++] = byte;
+        if (mCursor >= mHeaderLength) {
+            if (parseHeader()) {
+                result = true;
+            } else {
+                ALOGE("FrameScanner: ERROR - parseHeader() failed.");
+            }
+            mCursor = 0;
+        }
+    }
+    return result;
+}
+
+}  // namespace android
diff --git a/src/spdif/SPDIFEncoder.cpp b/src/spdif/SPDIFEncoder.cpp
new file mode 100644
index 0000000..221a072
--- /dev/null
+++ b/src/spdif/SPDIFEncoder.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2014, 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 <stdint.h>
+#include <string.h>
+
+#define LOG_TAG "AudioSPDIF"
+#include <cutils/log.h>
+#include <audio_utils/spdif/SPDIFEncoder.h>
+
+#include "AC3FrameScanner.h"
+#include "DTSFrameScanner.h"
+
+namespace android {
+
+// Burst Preamble defined in IEC61937-1
+const uint16_t SPDIFEncoder::kSPDIFSync1 = 0xF872; // Pa
+const uint16_t SPDIFEncoder::kSPDIFSync2 = 0x4E1F; // Pb
+
+static int32_t sEndianDetector = 1;
+#define isLittleEndian()  (*((uint8_t *)&sEndianDetector))
+
+SPDIFEncoder::SPDIFEncoder(audio_format_t format)
+  : mFramer(NULL)
+  , mSampleRate(48000)
+  , mBurstBuffer(NULL)
+  , mBurstBufferSizeBytes(0)
+  , mRateMultiplier(1)
+  , mBurstFrames(0)
+  , mByteCursor(0)
+  , mBitstreamNumber(0)
+  , mPayloadBytesPending(0)
+  , mScanning(true)
+{
+    switch(format) {
+        case AUDIO_FORMAT_AC3:
+        case AUDIO_FORMAT_E_AC3:
+            mFramer = new AC3FrameScanner(format);
+            break;
+        case AUDIO_FORMAT_DTS:
+        case AUDIO_FORMAT_DTS_HD:
+            mFramer = new DTSFrameScanner();
+            break;
+        default:
+            break;
+    }
+
+    // This a programmer error. Call isFormatSupported() first.
+    LOG_ALWAYS_FATAL_IF((mFramer == NULL),
+        "SPDIFEncoder: invalid audio format = 0x%08X", format);
+
+    mBurstBufferSizeBytes = sizeof(uint16_t)
+            * SPDIF_ENCODED_CHANNEL_COUNT
+            * mFramer->getMaxSampleFramesPerSyncFrame();
+
+    ALOGI("SPDIFEncoder: mBurstBufferSizeBytes = %zu, littleEndian = %d",
+            mBurstBufferSizeBytes, isLittleEndian());
+    mBurstBuffer = new uint16_t[mBurstBufferSizeBytes >> 1];
+    clearBurstBuffer();
+}
+
+SPDIFEncoder::SPDIFEncoder()
+    : SPDIFEncoder(AUDIO_FORMAT_AC3)
+{
+}
+
+SPDIFEncoder::~SPDIFEncoder()
+{
+    delete[] mBurstBuffer;
+    delete mFramer;
+}
+
+bool SPDIFEncoder::isFormatSupported(audio_format_t format)
+{
+    switch(format) {
+        case AUDIO_FORMAT_AC3:
+        case AUDIO_FORMAT_E_AC3:
+        case AUDIO_FORMAT_DTS:
+        case AUDIO_FORMAT_DTS_HD:
+            return true;
+        default:
+            return false;
+    }
+}
+
+int SPDIFEncoder::getBytesPerOutputFrame()
+{
+    return SPDIF_ENCODED_CHANNEL_COUNT * sizeof(int16_t);
+}
+
+void SPDIFEncoder::writeBurstBufferShorts(const uint16_t *buffer, size_t numShorts)
+{
+    // avoid static analyser warning
+    LOG_ALWAYS_FATAL_IF((mBurstBuffer == NULL), "mBurstBuffer never allocated");
+    mByteCursor = (mByteCursor + 1) & ~1; // round up to even byte
+    size_t bytesToWrite = numShorts * sizeof(uint16_t);
+    if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
+        ALOGE("SPDIFEncoder: Burst buffer overflow!");
+        reset();
+        return;
+    }
+    memcpy(&mBurstBuffer[mByteCursor >> 1], buffer, bytesToWrite);
+    mByteCursor += bytesToWrite;
+}
+
+// Pack the bytes into the short buffer in the order:
+//   byte[0] -> short[0] MSB
+//   byte[1] -> short[0] LSB
+//   byte[2] -> short[1] MSB
+//   byte[3] -> short[1] LSB
+//   etcetera
+// This way they should come out in the correct order for SPDIF on both
+// Big and Little Endian CPUs.
+void SPDIFEncoder::writeBurstBufferBytes(const uint8_t *buffer, size_t numBytes)
+{
+    size_t bytesToWrite = numBytes;
+    if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
+        ALOGE("SPDIFEncoder: Burst buffer overflow!");
+        clearBurstBuffer();
+        return;
+    }
+    uint16_t pad = mBurstBuffer[mByteCursor >> 1];
+    for (size_t i = 0; i < bytesToWrite; i++) {
+        if (mByteCursor & 1 ) {
+            pad |= *buffer++; // put second byte in LSB
+            mBurstBuffer[mByteCursor >> 1] = pad;
+            pad = 0;
+        } else {
+            pad |= (*buffer++) << 8; // put first byte in MSB
+        }
+        mByteCursor++;
+    }
+    // Save partially filled short.
+    if (mByteCursor & 1 ){
+        mBurstBuffer[mByteCursor >> 1] = pad;
+    }
+}
+
+void SPDIFEncoder::sendZeroPad()
+{
+    // Pad remainder of burst with zeros.
+    size_t burstSize = mFramer->getSampleFramesPerSyncFrame() * sizeof(uint16_t)
+            * SPDIF_ENCODED_CHANNEL_COUNT;
+    if (mByteCursor > burstSize) {
+        ALOGE("SPDIFEncoder: Burst buffer, contents too large!");
+        clearBurstBuffer();
+    } else {
+        // We don't have to write zeros because buffer already set to zero
+        // by clearBurstBuffer(). Just pretend we wrote zeros by
+        // incrementing cursor.
+        mByteCursor = burstSize;
+    }
+}
+
+void SPDIFEncoder::reset()
+{
+    ALOGV("SPDIFEncoder: reset()");
+    clearBurstBuffer();
+    if (mFramer != NULL) {
+        mFramer->resetBurst();
+    }
+    mPayloadBytesPending = 0;
+    mScanning = true;
+}
+
+void SPDIFEncoder::flushBurstBuffer()
+{
+    const int preambleSize = 4 * sizeof(uint16_t);
+    if (mByteCursor > preambleSize) {
+        // Set lengthCode for valid payload before zeroPad.
+        uint16_t numBytes = (mByteCursor - preambleSize);
+        mBurstBuffer[3] = mFramer->convertBytesToLengthCode(numBytes);
+
+        sendZeroPad();
+        writeOutput(mBurstBuffer, mByteCursor);
+    }
+    reset();
+}
+
+void SPDIFEncoder::clearBurstBuffer()
+{
+    if (mBurstBuffer) {
+        memset(mBurstBuffer, 0, mBurstBufferSizeBytes);
+    }
+    mByteCursor = 0;
+}
+
+void SPDIFEncoder::startDataBurst()
+{
+    // Encode IEC61937-1 Burst Preamble
+    uint16_t preamble[4];
+
+    uint16_t burstInfo = (mBitstreamNumber << 13)
+        | (mFramer->getDataTypeInfo() << 8)
+        | mFramer->getDataType();
+
+    mRateMultiplier = mFramer->getRateMultiplier();
+
+    preamble[0] = kSPDIFSync1;
+    preamble[1] = kSPDIFSync2;
+    preamble[2] = burstInfo;
+    preamble[3] = 0; // lengthCode - This will get set after the buffer is full.
+    writeBurstBufferShorts(preamble, 4);
+}
+
+size_t SPDIFEncoder::startSyncFrame()
+{
+    // Write start of encoded frame that was buffered in frame detector.
+    size_t syncSize = mFramer->getHeaderSizeBytes();
+    writeBurstBufferBytes(mFramer->getHeaderAddress(), syncSize);
+    return mFramer->getFrameSizeBytes() - syncSize;
+}
+
+// Wraps raw encoded data into a data burst.
+ssize_t SPDIFEncoder::write( const void *buffer, size_t numBytes )
+{
+    size_t bytesLeft = numBytes;
+    const uint8_t *data = (const uint8_t *)buffer;
+    ALOGV("SPDIFEncoder: mScanning = %d, write(buffer[0] = 0x%02X, numBytes = %zu)",
+        mScanning, (uint) *data, numBytes);
+    while (bytesLeft > 0) {
+        if (mScanning) {
+        // Look for beginning of next encoded frame.
+            if (mFramer->scan(*data)) {
+                if (mByteCursor == 0) {
+                    startDataBurst();
+                } else if (mFramer->isFirstInBurst()) {
+                    // Make sure that this frame is at the beginning of the data burst.
+                    flushBurstBuffer();
+                    startDataBurst();
+                }
+                mPayloadBytesPending = startSyncFrame();
+                mScanning = false;
+            }
+            data++;
+            bytesLeft--;
+        } else {
+            // Write payload until we hit end of frame.
+            size_t bytesToWrite = bytesLeft;
+            // Only write as many as we need to finish the frame.
+            if (bytesToWrite > mPayloadBytesPending) {
+                bytesToWrite = mPayloadBytesPending;
+            }
+            writeBurstBufferBytes(data, bytesToWrite);
+
+            data += bytesToWrite;
+            bytesLeft -= bytesToWrite;
+            mPayloadBytesPending -= bytesToWrite;
+
+            // If we have all the payload then send a data burst.
+            if (mPayloadBytesPending == 0) {
+                if (mFramer->isLastInBurst()) {
+                    flushBurstBuffer();
+                }
+                mScanning = true;
+            }
+        }
+    }
+    return numBytes;
+}
+
+}  // namespace android
diff --git a/src/speexresample/resample.c b/src/speexresample/resample.c
new file mode 100644
index 0000000..1eeef20
--- /dev/null
+++ b/src/speexresample/resample.c
@@ -0,0 +1,1140 @@
+/* Copyright (C) 2007-2008 Jean-Marc Valin
+   Copyright (C) 2008      Thorvald Natvig
+      
+   File: resample.c
+   Arbitrary resampling code
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+   The design goals of this code are:
+      - Very fast algorithm
+      - SIMD-friendly algorithm
+      - Low memory requirement
+      - Good *perceptual* quality (and not best SNR)
+
+   Warning: This resampler is relatively new. Although I think I got rid of 
+   all the major bugs and I don't expect the API to change anymore, there
+   may be something I've missed. So use with caution.
+
+   This algorithm is based on this original resampling algorithm:
+   Smith, Julius O. Digital Audio Resampling Home Page
+   Center for Computer Research in Music and Acoustics (CCRMA), 
+   Stanford University, 2007.
+   Web published at http://www-ccrma.stanford.edu/~jos/resample/.
+
+   There is one main difference, though. This resampler uses cubic 
+   interpolation instead of linear interpolation in the above paper. This
+   makes the table much smaller and makes it possible to compute that table
+   on a per-stream basis. In turn, being able to tweak the table for each 
+   stream makes it possible to both reduce complexity on simple ratios 
+   (e.g. 2/3), and get rid of the rounding operations in the inner loop. 
+   The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef OUTSIDE_SPEEX
+#include <stdlib.h>
+static void *speex_alloc (int size) {return calloc(size,1);}
+static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
+static void speex_free (void *ptr) {free(ptr);}
+#include "speex_resampler.h"
+#include "arch.h"
+#else /* OUTSIDE_SPEEX */
+               
+#include "speex/speex_resampler.h"
+#include "arch.h"
+#include "os_support.h"
+#endif /* OUTSIDE_SPEEX */
+
+#include "stack_alloc.h"
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159263
+#endif
+
+#ifdef FIXED_POINT
+#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))  
+#else
+#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))  
+#endif
+               
+#define IMAX(a,b) ((a) > (b) ? (a) : (b))
+#define IMIN(a,b) ((a) < (b) ? (a) : (b))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef _USE_SSE
+#include "resample_sse.h"
+#endif
+
+#ifdef _USE_NEON
+#include "resample_neon.h"
+#endif
+
+/* Numer of elements to allocate on the stack */
+#ifdef VAR_ARRAYS
+#define FIXED_STACK_ALLOC 8192
+#else
+#define FIXED_STACK_ALLOC 1024
+#endif
+
+typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
+
+struct SpeexResamplerState_ {
+   spx_uint32_t in_rate;
+   spx_uint32_t out_rate;
+   spx_uint32_t num_rate;
+   spx_uint32_t den_rate;
+   
+   int    quality;
+   spx_uint32_t nb_channels;
+   spx_uint32_t filt_len;
+   spx_uint32_t mem_alloc_size;
+   spx_uint32_t buffer_size;
+   int          int_advance;
+   int          frac_advance;
+   float  cutoff;
+   spx_uint32_t oversample;
+   int          initialised;
+   int          started;
+   
+   /* These are per-channel */
+   spx_int32_t  *last_sample;
+   spx_uint32_t *samp_frac_num;
+   spx_uint32_t *magic_samples;
+   
+   spx_word16_t *mem;
+   spx_word16_t *sinc_table;
+   spx_uint32_t sinc_table_length;
+   resampler_basic_func resampler_ptr;
+         
+   int    in_stride;
+   int    out_stride;
+} ;
+
+static double kaiser12_table[68] = {
+   0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
+   0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
+   0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
+   0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
+   0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
+   0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
+   0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
+   0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
+   0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
+   0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
+   0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
+   0.00001000, 0.00000000};
+/*
+static double kaiser12_table[36] = {
+   0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
+   0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
+   0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
+   0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
+   0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
+   0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
+*/
+static double kaiser10_table[36] = {
+   0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
+   0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
+   0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
+   0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
+   0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
+   0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};
+
+static double kaiser8_table[36] = {
+   0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
+   0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
+   0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
+   0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
+   0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
+   0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
+   
+static double kaiser6_table[36] = {
+   0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
+   0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
+   0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
+   0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
+   0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
+   0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};
+
+struct FuncDef {
+   double *table;
+   int oversample;
+};
+      
+static struct FuncDef _KAISER12 = {kaiser12_table, 64};
+#define KAISER12 (&_KAISER12)
+/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
+#define KAISER12 (&_KAISER12)*/
+static struct FuncDef _KAISER10 = {kaiser10_table, 32};
+#define KAISER10 (&_KAISER10)
+static struct FuncDef _KAISER8 = {kaiser8_table, 32};
+#define KAISER8 (&_KAISER8)
+static struct FuncDef _KAISER6 = {kaiser6_table, 32};
+#define KAISER6 (&_KAISER6)
+
+struct QualityMapping {
+   int base_length;
+   int oversample;
+   float downsample_bandwidth;
+   float upsample_bandwidth;
+   struct FuncDef *window_func;
+};
+
+
+/* This table maps conversion quality to internal parameters. There are two
+   reasons that explain why the up-sampling bandwidth is larger than the 
+   down-sampling bandwidth:
+   1) When up-sampling, we can assume that the spectrum is already attenuated
+      close to the Nyquist rate (from an A/D or a previous resampling filter)
+   2) Any aliasing that occurs very close to the Nyquist rate will be masked
+      by the sinusoids/noise just below the Nyquist rate (guaranteed only for
+      up-sampling).
+*/
+static const struct QualityMapping quality_map[11] = {
+   {  8,  4, 0.830f, 0.860f, KAISER6 }, /* Q0 */
+   { 16,  4, 0.850f, 0.880f, KAISER6 }, /* Q1 */
+   { 32,  4, 0.882f, 0.910f, KAISER6 }, /* Q2 */  /* 82.3% cutoff ( ~60 dB stop) 6  */
+   { 48,  8, 0.895f, 0.917f, KAISER8 }, /* Q3 */  /* 84.9% cutoff ( ~80 dB stop) 8  */
+   { 64,  8, 0.921f, 0.940f, KAISER8 }, /* Q4 */  /* 88.7% cutoff ( ~80 dB stop) 8  */
+   { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */  /* 89.1% cutoff (~100 dB stop) 10 */
+   { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */  /* 91.5% cutoff (~100 dB stop) 10 */
+   {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */  /* 93.1% cutoff (~100 dB stop) 10 */
+   {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */  /* 94.5% cutoff (~100 dB stop) 10 */
+   {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */  /* 95.5% cutoff (~100 dB stop) 10 */
+   {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
+};
+/*8,24,40,56,80,104,128,160,200,256,320*/
+static double compute_func(float x, struct FuncDef *func)
+{
+   float y, frac;
+   double interp[4];
+   int ind; 
+   y = x*func->oversample;
+   ind = (int)floor(y);
+   frac = (y-ind);
+   /* CSE with handle the repeated powers */
+   interp[3] =  -0.1666666667*frac + 0.1666666667*(frac*frac*frac);
+   interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac);
+   /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
+   interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
+   /* Just to make sure we don't have rounding problems */
+   interp[1] = 1.f-interp[3]-interp[2]-interp[0];
+   
+   /*sum = frac*accum[1] + (1-frac)*accum[2];*/
+   return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
+}
+
+#if 0
+#include <stdio.h>
+int main(int argc, char **argv)
+{
+   int i;
+   for (i=0;i<256;i++)
+   {
+      printf ("%f\n", compute_func(i/256., KAISER12));
+   }
+   return 0;
+}
+#endif
+
+#ifdef FIXED_POINT
+/* The slow way of computing a sinc for the table. Should improve that some day */
+static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
+{
+   /*fprintf (stderr, "%f ", x);*/
+   float xx = x * cutoff;
+   if (fabs(x)<1e-6f)
+      return WORD2INT(32768.*cutoff);
+   else if (fabs(x) > .5f*N)
+      return 0;
+   /*FIXME: Can it really be any slower than this? */
+   return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func));
+}
+#else
+/* The slow way of computing a sinc for the table. Should improve that some day */
+static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
+{
+   /*fprintf (stderr, "%f ", x);*/
+   float xx = x * cutoff;
+   if (fabs(x)<1e-6)
+      return cutoff;
+   else if (fabs(x) > .5*N)
+      return 0;
+   /*FIXME: Can it really be any slower than this? */
+   return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func);
+}
+#endif
+
+#ifdef FIXED_POINT
+static void cubic_coef(spx_word16_t x, spx_word16_t interp[4])
+{
+   /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+   but I know it's MMSE-optimal on a sinc */
+   spx_word16_t x2, x3;
+   x2 = MULT16_16_P15(x, x);
+   x3 = MULT16_16_P15(x, x2);
+   interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15);
+   interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1));
+   interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15);
+   /* Just to make sure we don't have rounding problems */
+   interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3];
+   if (interp[2]<32767)
+      interp[2]+=1;
+}
+#else
+static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
+{
+   /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+   but I know it's MMSE-optimal on a sinc */
+   interp[0] =  -0.16667f*frac + 0.16667f*frac*frac*frac;
+   interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac;
+   /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
+   interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac;
+   /* Just to make sure we don't have rounding problems */
+   interp[2] = 1.-interp[0]-interp[1]-interp[3];
+}
+#endif
+
+static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   const int N = st->filt_len;
+   int out_sample = 0;
+   int last_sample = st->last_sample[channel_index];
+   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+   const spx_word16_t *sinc_table = st->sinc_table;
+   const int out_stride = st->out_stride;
+   const int int_advance = st->int_advance;
+   const int frac_advance = st->frac_advance;
+   const spx_uint32_t den_rate = st->den_rate;
+   spx_word32_t sum;
+
+   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
+   {
+      const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
+      const spx_word16_t *iptr = & in[last_sample];
+
+#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
+      float accum[4] = {0,0,0,0};
+
+      for(int j=0;j<N;j+=4) {
+        accum[0] += sinc[j]*iptr[j];
+        accum[1] += sinc[j+1]*iptr[j+1];
+        accum[2] += sinc[j+2]*iptr[j+2];
+        accum[3] += sinc[j+3]*iptr[j+3];
+      }
+      sum = accum[0] + accum[1] + accum[2] + accum[3];
+      sum = SATURATE32PSHR(sum, 15, 32767);
+#else
+      sum = inner_product_single(sinc, iptr, N);
+#endif
+
+      out[out_stride * out_sample++] = sum;
+      last_sample += int_advance;
+      samp_frac_num += frac_advance;
+      if (samp_frac_num >= den_rate)
+      {
+         samp_frac_num -= den_rate;
+         last_sample++;
+      }
+   }
+
+   st->last_sample[channel_index] = last_sample;
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+}
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   const int N = st->filt_len;
+   int out_sample = 0;
+   int last_sample = st->last_sample[channel_index];
+   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+   const spx_word16_t *sinc_table = st->sinc_table;
+   const int out_stride = st->out_stride;
+   const int int_advance = st->int_advance;
+   const int frac_advance = st->frac_advance;
+   const spx_uint32_t den_rate = st->den_rate;
+   double sum;
+   int j;
+
+   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
+   {
+      const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
+      const spx_word16_t *iptr = & in[last_sample];
+
+#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
+      double accum[4] = {0,0,0,0};
+
+      for(j=0;j<N;j+=4) {
+        accum[0] += sinc[j]*iptr[j];
+        accum[1] += sinc[j+1]*iptr[j+1];
+        accum[2] += sinc[j+2]*iptr[j+2];
+        accum[3] += sinc[j+3]*iptr[j+3];
+      }
+      sum = accum[0] + accum[1] + accum[2] + accum[3];
+#else
+      sum = inner_product_double(sinc, iptr, N);
+#endif
+
+      out[out_stride * out_sample++] = PSHR32(sum, 15);
+      last_sample += int_advance;
+      samp_frac_num += frac_advance;
+      if (samp_frac_num >= den_rate)
+      {
+         samp_frac_num -= den_rate;
+         last_sample++;
+      }
+   }
+
+   st->last_sample[channel_index] = last_sample;
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+}
+#endif
+
+static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   const int N = st->filt_len;
+   int out_sample = 0;
+   int last_sample = st->last_sample[channel_index];
+   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+   const int out_stride = st->out_stride;
+   const int int_advance = st->int_advance;
+   const int frac_advance = st->frac_advance;
+   const spx_uint32_t den_rate = st->den_rate;
+   int j;
+   spx_word32_t sum;
+
+   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
+   {
+      const spx_word16_t *iptr = & in[last_sample];
+
+      const int offset = samp_frac_num*st->oversample/st->den_rate;
+#ifdef FIXED_POINT
+      const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
+#else
+      const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
+#endif
+      spx_word16_t interp[4];
+
+
+#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
+      spx_word32_t accum[4] = {0,0,0,0};
+
+      for(j=0;j<N;j++) {
+        const spx_word16_t curr_in=iptr[j];
+        accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
+        accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
+        accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
+        accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
+      }
+
+      cubic_coef(frac, interp);
+      sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
+      sum = SATURATE32PSHR(sum, 15, 32767);
+#else
+      cubic_coef(frac, interp);
+      sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
+#endif
+      
+      out[out_stride * out_sample++] = sum;
+      last_sample += int_advance;
+      samp_frac_num += frac_advance;
+      if (samp_frac_num >= den_rate)
+      {
+         samp_frac_num -= den_rate;
+         last_sample++;
+      }
+   }
+
+   st->last_sample[channel_index] = last_sample;
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+}
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   const int N = st->filt_len;
+   int out_sample = 0;
+   int last_sample = st->last_sample[channel_index];
+   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+   const int out_stride = st->out_stride;
+   const int int_advance = st->int_advance;
+   const int frac_advance = st->frac_advance;
+   const spx_uint32_t den_rate = st->den_rate;
+   int j;
+   spx_word32_t sum;
+
+   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
+   {
+      const spx_word16_t *iptr = & in[last_sample];
+
+      const int offset = samp_frac_num*st->oversample/st->den_rate;
+#ifdef FIXED_POINT
+      const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
+#else
+      const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
+#endif
+      spx_word16_t interp[4];
+
+
+#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
+      double accum[4] = {0,0,0,0};
+
+      for(j=0;j<N;j++) {
+        const double curr_in=iptr[j];
+        accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
+        accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
+        accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
+        accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
+      }
+
+      cubic_coef(frac, interp);
+      sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
+#else
+      cubic_coef(frac, interp);
+      sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
+#endif
+      
+      out[out_stride * out_sample++] = PSHR32(sum,15);
+      last_sample += int_advance;
+      samp_frac_num += frac_advance;
+      if (samp_frac_num >= den_rate)
+      {
+         samp_frac_num -= den_rate;
+         last_sample++;
+      }
+   }
+
+   st->last_sample[channel_index] = last_sample;
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+}
+#endif
+
+static void update_filter(SpeexResamplerState *st)
+{
+   spx_uint32_t old_length;
+   
+   old_length = st->filt_len;
+   st->oversample = quality_map[st->quality].oversample;
+   st->filt_len = quality_map[st->quality].base_length;
+   
+   if (st->num_rate > st->den_rate)
+   {
+      /* down-sampling */
+      st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
+      /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
+      st->filt_len = st->filt_len*st->num_rate / st->den_rate;
+      /* Round down to make sure we have a multiple of 4 */
+      st->filt_len &= (~0x3);
+      if (2*st->den_rate < st->num_rate)
+         st->oversample >>= 1;
+      if (4*st->den_rate < st->num_rate)
+         st->oversample >>= 1;
+      if (8*st->den_rate < st->num_rate)
+         st->oversample >>= 1;
+      if (16*st->den_rate < st->num_rate)
+         st->oversample >>= 1;
+      if (st->oversample < 1)
+         st->oversample = 1;
+   } else {
+      /* up-sampling */
+      st->cutoff = quality_map[st->quality].upsample_bandwidth;
+   }
+   
+   /* Choose the resampling type that requires the least amount of memory */
+#ifdef RESAMPLE_FORCE_FULL_SINC_TABLE
+   if (1)
+#else
+   if (st->den_rate <= st->oversample)
+#endif
+   {
+      spx_uint32_t i;
+      if (!st->sinc_table)
+         st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t));
+      else if (st->sinc_table_length < st->filt_len*st->den_rate)
+      {
+         st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t));
+         st->sinc_table_length = st->filt_len*st->den_rate;
+      }
+      for (i=0;i<st->den_rate;i++)
+      {
+         spx_int32_t j;
+         for (j=0;j<st->filt_len;j++)
+         {
+            st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-(spx_int32_t)st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func);
+         }
+      }
+#ifdef FIXED_POINT
+      st->resampler_ptr = resampler_basic_direct_single;
+#else
+      if (st->quality>8)
+         st->resampler_ptr = resampler_basic_direct_double;
+      else
+         st->resampler_ptr = resampler_basic_direct_single;
+#endif
+      /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/
+   } else {
+      spx_int32_t i;
+      if (!st->sinc_table)
+         st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
+      else if (st->sinc_table_length < st->filt_len*st->oversample+8)
+      {
+         st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
+         st->sinc_table_length = st->filt_len*st->oversample+8;
+      }
+      for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++)
+         st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func);
+#ifdef FIXED_POINT
+      st->resampler_ptr = resampler_basic_interpolate_single;
+#else
+      if (st->quality>8)
+         st->resampler_ptr = resampler_basic_interpolate_double;
+      else
+         st->resampler_ptr = resampler_basic_interpolate_single;
+#endif
+      /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/
+   }
+   st->int_advance = st->num_rate/st->den_rate;
+   st->frac_advance = st->num_rate%st->den_rate;
+
+   
+   /* Here's the place where we update the filter memory to take into account
+      the change in filter length. It's probably the messiest part of the code
+      due to handling of lots of corner cases. */
+   if (!st->mem)
+   {
+      spx_uint32_t i;
+      st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
+      st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
+      for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
+         st->mem[i] = 0;
+      /*speex_warning("init filter");*/
+   } else if (!st->started)
+   {
+      spx_uint32_t i;
+      st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
+      st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
+      for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
+         st->mem[i] = 0;
+      /*speex_warning("reinit filter");*/
+   } else if (st->filt_len > old_length)
+   {
+      spx_int32_t i;
+      /* Increase the filter length */
+      /*speex_warning("increase filter size");*/
+      int old_alloc_size = st->mem_alloc_size;
+      if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size)
+      {
+         st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
+         st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
+      }
+      for (i=st->nb_channels-1;i>=0;i--)
+      {
+         spx_int32_t j;
+         spx_uint32_t olen = old_length;
+         /*if (st->magic_samples[i])*/
+         {
+            /* Try and remove the magic samples as if nothing had happened */
+            
+            /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
+            olen = old_length + 2*st->magic_samples[i];
+            for (j=old_length-2+st->magic_samples[i];j>=0;j--)
+               st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
+            for (j=0;j<st->magic_samples[i];j++)
+               st->mem[i*st->mem_alloc_size+j] = 0;
+            st->magic_samples[i] = 0;
+         }
+         if (st->filt_len > olen)
+         {
+            /* If the new filter length is still bigger than the "augmented" length */
+            /* Copy data going backward */
+            for (j=0;j<olen-1;j++)
+               st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
+            /* Then put zeros for lack of anything better */
+            for (;j<st->filt_len-1;j++)
+               st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
+            /* Adjust last_sample */
+            st->last_sample[i] += (st->filt_len - olen)/2;
+         } else {
+            /* Put back some of the magic! */
+            st->magic_samples[i] = (olen - st->filt_len)/2;
+            for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
+               st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
+         }
+      }
+   } else if (st->filt_len < old_length)
+   {
+      spx_uint32_t i;
+      /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
+         samples so they can be used directly as input the next time(s) */
+      for (i=0;i<st->nb_channels;i++)
+      {
+         spx_uint32_t j;
+         spx_uint32_t old_magic = st->magic_samples[i];
+         st->magic_samples[i] = (old_length - st->filt_len)/2;
+         /* We must copy some of the memory that's no longer used */
+         /* Copy data going backward */
+         for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++)
+            st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
+         st->magic_samples[i] += old_magic;
+      }
+   }
+
+}
+
+EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
+{
+   return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
+}
+
+EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
+{
+   spx_uint32_t i;
+   SpeexResamplerState *st;
+   if (quality > 10 || quality < 0)
+   {
+      if (err)
+         *err = RESAMPLER_ERR_INVALID_ARG;
+      return NULL;
+   }
+   st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
+   st->initialised = 0;
+   st->started = 0;
+   st->in_rate = 0;
+   st->out_rate = 0;
+   st->num_rate = 0;
+   st->den_rate = 0;
+   st->quality = -1;
+   st->sinc_table_length = 0;
+   st->mem_alloc_size = 0;
+   st->filt_len = 0;
+   st->mem = 0;
+   st->resampler_ptr = 0;
+         
+   st->cutoff = 1.f;
+   st->nb_channels = nb_channels;
+   st->in_stride = 1;
+   st->out_stride = 1;
+   
+#ifdef FIXED_POINT
+   st->buffer_size = 160;
+#else
+   st->buffer_size = 160;
+#endif
+   
+   /* Per channel data */
+   st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
+   st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
+   st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
+   for (i=0;i<nb_channels;i++)
+   {
+      st->last_sample[i] = 0;
+      st->magic_samples[i] = 0;
+      st->samp_frac_num[i] = 0;
+   }
+
+   speex_resampler_set_quality(st, quality);
+   speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
+
+   
+   update_filter(st);
+   
+   st->initialised = 1;
+   if (err)
+      *err = RESAMPLER_ERR_SUCCESS;
+
+   return st;
+}
+
+EXPORT void speex_resampler_destroy(SpeexResamplerState *st)
+{
+   speex_free(st->mem);
+   speex_free(st->sinc_table);
+   speex_free(st->last_sample);
+   speex_free(st->magic_samples);
+   speex_free(st->samp_frac_num);
+   speex_free(st);
+}
+
+static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   int j=0;
+   const int N = st->filt_len;
+   int out_sample = 0;
+   spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
+   spx_uint32_t ilen;
+   
+   st->started = 1;
+   
+   /* Call the right resampler through the function ptr */
+   out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len);
+   
+   if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
+      *in_len = st->last_sample[channel_index];
+   *out_len = out_sample;
+   st->last_sample[channel_index] -= *in_len;
+   
+   ilen = *in_len;
+
+   for(j=0;j<N-1;++j)
+     mem[j] = mem[j+ilen];
+
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) {
+   spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
+   spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
+   const int N = st->filt_len;
+   
+   speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len);
+
+   st->magic_samples[channel_index] -= tmp_in_len;
+   
+   /* If we couldn't process all "magic" input samples, save the rest for next time */
+   if (st->magic_samples[channel_index])
+   {
+      spx_uint32_t i;
+      for (i=0;i<st->magic_samples[channel_index];i++)
+         mem[N-1+i]=mem[N-1+i+tmp_in_len];
+   }
+   *out += out_len*st->out_stride;
+   return out_len;
+}
+
+#ifdef FIXED_POINT
+EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
+#else
+EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
+#endif
+{
+   int j;
+   spx_uint32_t ilen = *in_len;
+   spx_uint32_t olen = *out_len;
+   spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
+   const int filt_offs = st->filt_len - 1;
+   const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
+   const int istride = st->in_stride;
+
+   if (st->magic_samples[channel_index]) 
+      olen -= speex_resampler_magic(st, channel_index, &out, olen);
+   if (! st->magic_samples[channel_index]) {
+      while (ilen && olen) {
+        spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
+        spx_uint32_t ochunk = olen;
+ 
+        if (in) {
+           for(j=0;j<ichunk;++j)
+              x[j+filt_offs]=in[j*istride];
+        } else {
+          for(j=0;j<ichunk;++j)
+            x[j+filt_offs]=0;
+        }
+        speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk);
+        ilen -= ichunk;
+        olen -= ochunk;
+        out += ochunk * st->out_stride;
+        if (in)
+           in += ichunk * istride;
+      }
+   }
+   *in_len -= ilen;
+   *out_len -= olen;
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+#ifdef FIXED_POINT
+EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
+#else
+EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
+#endif
+{
+   int j;
+   const int istride_save = st->in_stride;
+   const int ostride_save = st->out_stride;
+   spx_uint32_t ilen = *in_len;
+   spx_uint32_t olen = *out_len;
+   spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
+   const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
+#ifdef VAR_ARRAYS
+   const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
+   VARDECL(spx_word16_t *ystack);
+   ALLOC(ystack, ylen, spx_word16_t);
+#else
+   const unsigned int ylen = FIXED_STACK_ALLOC;
+   spx_word16_t ystack[FIXED_STACK_ALLOC];
+#endif
+
+   st->out_stride = 1;
+   
+   while (ilen && olen) {
+     spx_word16_t *y = ystack;
+     spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
+     spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
+     spx_uint32_t omagic = 0;
+
+     if (st->magic_samples[channel_index]) {
+       omagic = speex_resampler_magic(st, channel_index, &y, ochunk);
+       ochunk -= omagic;
+       olen -= omagic;
+     }
+     if (! st->magic_samples[channel_index]) {
+       if (in) {
+         for(j=0;j<ichunk;++j)
+#ifdef FIXED_POINT
+           x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]);
+#else
+           x[j+st->filt_len-1]=in[j*istride_save];
+#endif
+       } else {
+         for(j=0;j<ichunk;++j)
+           x[j+st->filt_len-1]=0;
+       }
+
+       speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk);
+     } else {
+       ichunk = 0;
+       ochunk = 0;
+     }
+
+     for (j=0;j<ochunk+omagic;++j)
+#ifdef FIXED_POINT
+        out[j*ostride_save] = ystack[j];
+#else
+        out[j*ostride_save] = WORD2INT(ystack[j]);
+#endif
+     
+     ilen -= ichunk;
+     olen -= ochunk;
+     out += (ochunk+omagic) * ostride_save;
+     if (in)
+       in += ichunk * istride_save;
+   }
+   st->out_stride = ostride_save;
+   *in_len -= ilen;
+   *out_len -= olen;
+
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
+{
+   spx_uint32_t i;
+   int istride_save, ostride_save;
+   spx_uint32_t bak_len = *out_len;
+   istride_save = st->in_stride;
+   ostride_save = st->out_stride;
+   st->in_stride = st->out_stride = st->nb_channels;
+   for (i=0;i<st->nb_channels;i++)
+   {
+      *out_len = bak_len;
+      if (in != NULL)
+         speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
+      else
+         speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len);
+   }
+   st->in_stride = istride_save;
+   st->out_stride = ostride_save;
+   return RESAMPLER_ERR_SUCCESS;
+}
+               
+EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
+{
+   spx_uint32_t i;
+   int istride_save, ostride_save;
+   spx_uint32_t bak_len = *out_len;
+   istride_save = st->in_stride;
+   ostride_save = st->out_stride;
+   st->in_stride = st->out_stride = st->nb_channels;
+   for (i=0;i<st->nb_channels;i++)
+   {
+      *out_len = bak_len;
+      if (in != NULL)
+         speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
+      else
+         speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len);
+   }
+   st->in_stride = istride_save;
+   st->out_stride = ostride_save;
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
+{
+   return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
+}
+
+EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
+{
+   *in_rate = st->in_rate;
+   *out_rate = st->out_rate;
+}
+
+EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
+{
+   spx_uint32_t fact;
+   spx_uint32_t old_den;
+   spx_uint32_t i;
+   if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
+      return RESAMPLER_ERR_SUCCESS;
+   
+   old_den = st->den_rate;
+   st->in_rate = in_rate;
+   st->out_rate = out_rate;
+   st->num_rate = ratio_num;
+   st->den_rate = ratio_den;
+   /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
+   for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
+   {
+      while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
+      {
+         st->num_rate /= fact;
+         st->den_rate /= fact;
+      }
+   }
+      
+   if (old_den > 0)
+   {
+      for (i=0;i<st->nb_channels;i++)
+      {
+         st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
+         /* Safety net */
+         if (st->samp_frac_num[i] >= st->den_rate)
+            st->samp_frac_num[i] = st->den_rate-1;
+      }
+   }
+   
+   if (st->initialised)
+      update_filter(st);
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
+{
+   *ratio_num = st->num_rate;
+   *ratio_den = st->den_rate;
+}
+
+EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
+{
+   if (quality > 10 || quality < 0)
+      return RESAMPLER_ERR_INVALID_ARG;
+   if (st->quality == quality)
+      return RESAMPLER_ERR_SUCCESS;
+   st->quality = quality;
+   if (st->initialised)
+      update_filter(st);
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
+{
+   *quality = st->quality;
+}
+
+EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
+{
+   st->in_stride = stride;
+}
+
+EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
+{
+   *stride = st->in_stride;
+}
+
+EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
+{
+   st->out_stride = stride;
+}
+
+EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
+{
+   *stride = st->out_stride;
+}
+
+EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st)
+{
+  return st->filt_len / 2;
+}
+
+EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st)
+{
+  return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;
+}
+
+EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st)
+{
+   spx_uint32_t i;
+   for (i=0;i<st->nb_channels;i++)
+      st->last_sample[i] = st->filt_len/2;
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st)
+{
+   spx_uint32_t i;
+   for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
+      st->mem[i] = 0;
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT const char *speex_resampler_strerror(int err)
+{
+   switch (err)
+   {
+      case RESAMPLER_ERR_SUCCESS:
+         return "Success.";
+      case RESAMPLER_ERR_ALLOC_FAILED:
+         return "Memory allocation failed.";
+      case RESAMPLER_ERR_BAD_STATE:
+         return "Bad resampler state.";
+      case RESAMPLER_ERR_INVALID_ARG:
+         return "Invalid argument.";
+      case RESAMPLER_ERR_PTR_OVERLAP:
+         return "Input and output buffers overlap.";
+      default:
+         return "Unknown error. Bad error code or strange version mismatch.";
+   }
+}