Merge "Fix issues crashing with Fatal signal when calling getFormat"
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 6f2351f..c5fc646 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -20,4 +20,5 @@
     name: "libcamera2ndk.ndk",
     symbol_file: "libcamera2ndk.map.txt",
     first_version: "24",
+    unversioned_until: "current",
 }
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
new file mode 100644
index 0000000..03dce0c
--- /dev/null
+++ b/media/libaudioclient/Android.bp
@@ -0,0 +1,45 @@
+cc_library_shared {
+    name: "libaudioclient",
+    srcs: [
+        "AudioEffect.cpp",
+        "AudioPolicy.cpp",
+        "AudioRecord.cpp",
+        "AudioSystem.cpp",
+        "AudioTrack.cpp",
+        "AudioTrackShared.cpp",
+        "IAudioFlinger.cpp",
+        "IAudioFlingerClient.cpp",
+        "IAudioPolicyService.cpp",
+        "IAudioPolicyServiceClient.cpp",
+        "IAudioRecord.cpp",
+        "IAudioTrack.cpp",
+        "IEffect.cpp",
+        "IEffectClient.cpp",
+        "ToneGenerator.cpp",
+    ],
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libutils",
+        "libbinder",
+        "libdl",
+        "libaudioutils",
+    ],
+    export_shared_lib_headers: ["libbinder"],
+    // for memory heap analysis
+    static_libs: [
+        "libc_malloc_debug_backtrace",
+        "libc_logging",
+    ],
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+    sanitize: {
+        misc_undefined : [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libaudioclient/Android.mk b/media/libaudioclient/Android.mk
deleted file mode 100644
index 348ab50..0000000
--- a/media/libaudioclient/Android.mk
+++ /dev/null
@@ -1,50 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES += \
-    AudioEffect.cpp \
-    AudioPolicy.cpp \
-    AudioRecord.cpp \
-    AudioSystem.cpp \
-    AudioTrack.cpp \
-    AudioTrackShared.cpp \
-    IAudioFlinger.cpp \
-    IAudioFlingerClient.cpp \
-    IAudioPolicyService.cpp \
-    IAudioPolicyServiceClient.cpp \
-    IAudioRecord.cpp \
-    IAudioTrack.cpp \
-    IEffect.cpp \
-    IEffectClient.cpp \
-    ToneGenerator.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-	liblog libcutils libutils libbinder \
-        libdl libaudioutils \
-
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder
-
-# for memory heap analysis
-LOCAL_STATIC_LIBRARIES := libc_malloc_debug_backtrace libc_logging
-
-LOCAL_MODULE:= libaudioclient
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_C_INCLUDES := \
-    $(TOP)/frameworks/native/include/media/openmax \
-    $(TOP)/frameworks/av/include/media/ \
-    $(TOP)/frameworks/av/media/libstagefright \
-    $(TOP)/frameworks/av/media/libmedia/aidl \
-    $(call include-path-for, audio-utils)
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    frameworks/av/include/media \
-    frameworks/av/media/libmedia/aidl
-
-LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
-LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 222189a..0ac5726 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -835,10 +835,15 @@
                     static_cast <audio_policy_dev_state_t>(data.readInt32());
             const char *device_address = data.readCString();
             const char *device_name = data.readCString();
-            reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
-                                                                              state,
-                                                                              device_address,
-                                                                              device_name)));
+            if (device_address == nullptr || device_name == nullptr) {
+                ALOGE("Bad Binder transaction: SET_DEVICE_CONNECTION_STATE for device %u", device);
+                reply->writeInt32(static_cast<int32_t> (BAD_VALUE));
+            } else {
+                reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
+                                                                                  state,
+                                                                                  device_address,
+                                                                                  device_name)));
+            }
             return NO_ERROR;
         } break;
 
@@ -847,8 +852,13 @@
             audio_devices_t device =
                     static_cast<audio_devices_t> (data.readInt32());
             const char *device_address = data.readCString();
-            reply->writeInt32(static_cast<uint32_t> (getDeviceConnectionState(device,
-                                                                              device_address)));
+            if (device_address == nullptr) {
+                ALOGE("Bad Binder transaction: GET_DEVICE_CONNECTION_STATE for device %u", device);
+                reply->writeInt32(static_cast<int32_t> (AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+            } else {
+                reply->writeInt32(static_cast<uint32_t> (getDeviceConnectionState(device,
+                                                                                  device_address)));
+            }
             return NO_ERROR;
         } break;
 
@@ -858,9 +868,14 @@
                     static_cast <audio_devices_t>(data.readInt32());
             const char *device_address = data.readCString();
             const char *device_name = data.readCString();
-            reply->writeInt32(static_cast<uint32_t> (handleDeviceConfigChange(device,
-                                                                              device_address,
-                                                                              device_name)));
+            if (device_address == nullptr || device_name == nullptr) {
+                ALOGE("Bad Binder transaction: HANDLE_DEVICE_CONFIG_CHANGE for device %u", device);
+                reply->writeInt32(static_cast<int32_t> (BAD_VALUE));
+            } else {
+                reply->writeInt32(static_cast<uint32_t> (handleDeviceConfigChange(device,
+                                                                                  device_address,
+                                                                                  device_name)));
+            }
             return NO_ERROR;
         } break;
 
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index fff20e7..5b74845 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -22,7 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "EffectDownmix.h"
 
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index 2d2596d..ba20ac2 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -24,10 +24,10 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/config_utils.h>
 #include <cutils/misc.h>
 #include <cutils/properties.h>
+#include <log/log.h>
 
 #include <audio_effects/audio_effects_conf.h>
 
diff --git a/media/libeffects/loudness/dsp/core/dynamic_range_compression-inl.h b/media/libeffects/loudness/dsp/core/dynamic_range_compression-inl.h
index 4f9f438..7ea05938 100644
--- a/media/libeffects/loudness/dsp/core/dynamic_range_compression-inl.h
+++ b/media/libeffects/loudness/dsp/core/dynamic_range_compression-inl.h
@@ -21,7 +21,7 @@
 #endif
 //#define LOG_NDEBUG 0
 
-#include <android/log.h>
+#include <log/log.h>
 
 namespace le_fx {
 
diff --git a/media/libeffects/loudness/dsp/core/interpolator_base-inl.h b/media/libeffects/loudness/dsp/core/interpolator_base-inl.h
index bdb6818..fb87c79 100644
--- a/media/libeffects/loudness/dsp/core/interpolator_base-inl.h
+++ b/media/libeffects/loudness/dsp/core/interpolator_base-inl.h
@@ -21,7 +21,7 @@
 #endif
 //#define LOG_NDEBUG 0
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "dsp/core/basic.h"
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
old mode 100644
new mode 100755
index c9bcfc3..9de5c26
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3288,13 +3288,22 @@
 
 void MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
     int64_t trakDurationUs = getDurationUs();
+    int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
     mOwner->beginBox("mdhd");
-    mOwner->writeInt32(0);             // version=0, flags=0
-    mOwner->writeInt32(now);           // creation time
-    mOwner->writeInt32(now);           // modification time
-    mOwner->writeInt32(mTimeScale);    // media timescale
-    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
-    mOwner->writeInt32(mdhdDuration);  // use media timescale
+
+    if (mdhdDuration > UINT32_MAX) {
+        mOwner->writeInt32((1 << 24));            // version=1, flags=0
+        mOwner->writeInt64((int64_t)now);         // creation time
+        mOwner->writeInt64((int64_t)now);         // modification time
+        mOwner->writeInt32(mTimeScale);           // media timescale
+        mOwner->writeInt64(mdhdDuration);         // media timescale
+    } else {
+        mOwner->writeInt32(0);                      // version=0, flags=0
+        mOwner->writeInt32(now);                    // creation time
+        mOwner->writeInt32(now);                    // modification time
+        mOwner->writeInt32(mTimeScale);             // media timescale
+        mOwner->writeInt32((int32_t)mdhdDuration);  // use media timescale
+    }
     // Language follows the three letter standard ISO-639-2/T
     // 'e', 'n', 'g' for "English", for instance.
     // Each character is packed as the difference between its ASCII value and 0x60.
diff --git a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
index 9d9cd3b..5a47510 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
@@ -60,7 +60,7 @@
 ; INCLUDES
 ----------------------------------------------------------------------------*/
 #define LOG_TAG "a_refl"
-#include <android/log.h>
+#include <log/log.h>
 
 #include "a_refl.h"
 #include "typedef.h"
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
index 5baa2a2..8393d79 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
@@ -18,7 +18,7 @@
 
 #define LOG_TAG "conceal"
 
-#include "android/log.h"
+#include "log/log.h"
 
 #include "mp4dec_lib.h" /* video decoder function prototypes */
 #include "vlc_decode.h"
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index 861b85a..793695a 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -256,10 +256,6 @@
 
         return NULL;
     }
-
-    if (curPlaylistHash != NULL) {
-        memcpy(curPlaylistHash, hash, sizeof(hash));
-    }
 #endif
 
     sp<M3UParser> playlist =
@@ -271,6 +267,13 @@
         return NULL;
     }
 
+#if defined(__ANDROID__)
+    if (curPlaylistHash != NULL) {
+
+        memcpy(curPlaylistHash, hash, sizeof(hash));
+    }
+#endif
+
     return playlist;
 }
 
diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.cpp b/media/libstagefright/wifi-display/rtp/RTPSender.cpp
index c66a898..83af393 100644
--- a/media/libstagefright/wifi-display/rtp/RTPSender.cpp
+++ b/media/libstagefright/wifi-display/rtp/RTPSender.cpp
@@ -762,10 +762,16 @@
     return OK;
 }
 
-status_t RTPSender::parseAPP(const uint8_t *data, size_t size __unused) {
-    if (!memcmp("late", &data[8], 4)) {
-        int64_t avgLatencyUs = (int64_t)U64_AT(&data[12]);
-        int64_t maxLatencyUs = (int64_t)U64_AT(&data[20]);
+status_t RTPSender::parseAPP(const uint8_t *data, size_t size) {
+    static const size_t late_offset = 8;
+    static const char late_string[] = "late";
+    static const size_t avgLatencyUs_offset = late_offset + sizeof(late_string) - 1;
+    static const size_t maxLatencyUs_offset = avgLatencyUs_offset + sizeof(int64_t);
+
+    if ((size >= (maxLatencyUs_offset + sizeof(int64_t)))
+            && !memcmp(late_string, &data[late_offset], sizeof(late_string) - 1)) {
+        int64_t avgLatencyUs = (int64_t)U64_AT(&data[avgLatencyUs_offset]);
+        int64_t maxLatencyUs = (int64_t)U64_AT(&data[maxLatencyUs_offset]);
 
         sp<AMessage> notify = mNotify->dup();
         notify->setInt32("what", kWhatInformSender);
diff --git a/media/mtp/AsyncIO.cpp b/media/mtp/AsyncIO.cpp
index a1a98ab..e77ad38 100644
--- a/media/mtp/AsyncIO.cpp
+++ b/media/mtp/AsyncIO.cpp
@@ -37,15 +37,17 @@
 }
 
 void splice_read_func(struct aiocb *aiocbp) {
+    loff_t long_offset = aiocbp->aio_offset;
     aiocbp->ret = TEMP_FAILURE_RETRY(splice(aiocbp->aio_fildes,
-                (off64_t*) &aiocbp->aio_offset, aiocbp->aio_sink,
+                &long_offset, aiocbp->aio_sink,
                 NULL, aiocbp->aio_nbytes, 0));
     if (aiocbp->ret == -1) aiocbp->error = errno;
 }
 
 void splice_write_func(struct aiocb *aiocbp) {
+    loff_t long_offset = aiocbp->aio_offset;
     aiocbp->ret = TEMP_FAILURE_RETRY(splice(aiocbp->aio_fildes, NULL,
-                aiocbp->aio_sink, (off64_t*) &aiocbp->aio_offset,
+                aiocbp->aio_sink, &long_offset,
                 aiocbp->aio_nbytes, 0));
     if (aiocbp->ret == -1) aiocbp->error = errno;
 }
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 10314e9..d11a10d 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -38,6 +38,8 @@
 #define cpu_to_le16(x)  htole16(x)
 #define cpu_to_le32(x)  htole32(x)
 
+#define FUNCTIONFS_ENDPOINT_ALLOC       _IOR('g', 131, __u32)
+
 namespace {
 
 constexpr char FFS_MTP_EP_IN[] = "/dev/usb-ffs/mtp/ep1";
@@ -467,6 +469,24 @@
     mLock.unlock();
 }
 
+class ScopedEndpointBufferAlloc {
+private:
+    const int mFd;
+    const unsigned int mAllocSize;
+public:
+    ScopedEndpointBufferAlloc(int fd, unsigned alloc_size) :
+        mFd(fd),
+        mAllocSize(alloc_size) {
+        if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mAllocSize)))
+            PLOG(DEBUG) << "FFS endpoint alloc failed!";
+    }
+
+    ~ScopedEndpointBufferAlloc() {
+        if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(0)))
+            PLOG(DEBUG) << "FFS endpoint alloc reset failed!";
+    }
+};
+
 /* Read from USB and write to a local file. */
 int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
     // When receiving files, the incoming length is given in 32 bits.
@@ -494,6 +514,7 @@
     bool write = false;
 
     posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
+    ScopedEndpointBufferAlloc(mBulkOut, mMaxRead);
 
     // Break down the file into pieces that fit in buffers
     while (file_length > 0 || write) {
@@ -609,6 +630,8 @@
     if (writeHandle(mBulkIn, data, packet_size) == -1) return -1;
     if (file_length == 0) return 0;
 
+    ScopedEndpointBufferAlloc(mBulkIn, mMaxWrite);
+
     // Break down the file into pieces that fit in buffers
     while(file_length > 0) {
         if (read) {
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 1ac1eeb..e4e3d8f 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -20,4 +20,5 @@
     name: "libmediandk.ndk",
     symbol_file: "libmediandk.map.txt",
     first_version: "21",
+    unversioned_until: "current",
 }
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index 43624a0..8b7259d 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -22,8 +22,8 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
-#include <android/log.h>
 #include <cutils/properties.h>
+#include <log/log.h>
 
 #include <audio_utils/primitives.h>
 #include "AudioResampler.h"
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
index d27dce7..9fb6699 100644
--- a/services/audioflinger/AudioResamplerCubic.cpp
+++ b/services/audioflinger/AudioResamplerCubic.cpp
@@ -19,7 +19,8 @@
 #include <stdint.h>
 #include <string.h>
 #include <sys/types.h>
-#include <android/log.h>
+
+#include <log/log.h>
 
 #include "AudioResampler.h"
 #include "AudioResamplerCubic.h"
diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp
index b7ca5d9..213cd1a 100644
--- a/services/audioflinger/AudioResamplerDyn.cpp
+++ b/services/audioflinger/AudioResamplerDyn.cpp
@@ -29,9 +29,10 @@
 #include <utils/Log.h>
 #include <audio_utils/primitives.h>
 
-#include "AudioResamplerFirOps.h" // USE_NEON and USE_INLINE_ASSEMBLY defined here
+#include "AudioResamplerFirOps.h" // USE_NEON, USE_SSE and USE_INLINE_ASSEMBLY defined here
 #include "AudioResamplerFirProcess.h"
 #include "AudioResamplerFirProcessNeon.h"
+#include "AudioResamplerFirProcessSSE.h"
 #include "AudioResamplerFirGen.h" // requires math.h
 #include "AudioResamplerDyn.h"
 
diff --git a/services/audioflinger/AudioResamplerFirOps.h b/services/audioflinger/AudioResamplerFirOps.h
index 2a26496..776903c 100644
--- a/services/audioflinger/AudioResamplerFirOps.h
+++ b/services/audioflinger/AudioResamplerFirOps.h
@@ -36,6 +36,13 @@
 #include <arm_neon.h>
 #endif
 
+#if defined(__SSSE3__)  // Should be supported in x86 ABI for both 32 & 64-bit.
+#define USE_SSE (true)
+#include <tmmintrin.h>
+#else
+#define USE_SSE (false)
+#endif
+
 template<typename T, typename U>
 struct is_same
 {
diff --git a/services/audioflinger/AudioResamplerFirProcessSSE.h b/services/audioflinger/AudioResamplerFirProcessSSE.h
new file mode 100644
index 0000000..63ed052
--- /dev/null
+++ b/services/audioflinger/AudioResamplerFirProcessSSE.h
@@ -0,0 +1,215 @@
+/*
+ * 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_RESAMPLER_FIR_PROCESS_SSE_H
+#define ANDROID_AUDIO_RESAMPLER_FIR_PROCESS_SSE_H
+
+namespace android {
+
+// depends on AudioResamplerFirOps.h, AudioResamplerFirProcess.h
+
+#if USE_SSE
+
+#define TO_STRING2(x) #x
+#define TO_STRING(x) TO_STRING2(x)
+// uncomment to print GCC version, may be relevant for intrinsic optimizations
+/* #pragma message ("GCC version: " TO_STRING(__GNUC__) \
+        "." TO_STRING(__GNUC_MINOR__) \
+        "." TO_STRING(__GNUC_PATCHLEVEL__)) */
+
+//
+// SSEx specializations are enabled for Process() and ProcessL() in AudioResamplerFirProcess.h
+//
+
+template <int CHANNELS, int STRIDE, bool FIXED>
+static inline void ProcessSSEIntrinsic(float* out,
+        int count,
+        const float* coefsP,
+        const float* coefsN,
+        const float* sP,
+        const float* sN,
+        const float* volumeLR,
+        float lerpP,
+        const float* coefsP1,
+        const float* coefsN1)
+{
+    ALOG_ASSERT(count > 0 && (count & 7) == 0); // multiple of 8
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CHANNELS == 1 || CHANNELS == 2);
+
+    sP -= CHANNELS*(4-1);   // adjust sP for a loop iteration of four
+
+    __m128 interp;
+    if (!FIXED) {
+        interp = _mm_set1_ps(lerpP);
+    }
+
+    __m128 accL, accR;
+    accL = _mm_setzero_ps();
+    if (CHANNELS == 2) {
+        accR = _mm_setzero_ps();
+    }
+
+    do {
+        __m128 posCoef = _mm_load_ps(coefsP);
+        __m128 negCoef = _mm_load_ps(coefsN);
+        coefsP += 4;
+        coefsN += 4;
+
+        if (!FIXED) { // interpolate
+            __m128 posCoef1 = _mm_load_ps(coefsP1);
+            __m128 negCoef1 = _mm_load_ps(coefsN1);
+            coefsP1 += 4;
+            coefsN1 += 4;
+
+            // Calculate the final coefficient for interpolation
+            // posCoef = interp * (posCoef1 - posCoef) + posCoef
+            // negCoef = interp * (negCoef - negCoef1) + negCoef1
+            posCoef1 = _mm_sub_ps(posCoef1, posCoef);
+            negCoef = _mm_sub_ps(negCoef, negCoef1);
+
+            posCoef1 = _mm_mul_ps(posCoef1, interp);
+            negCoef = _mm_mul_ps(negCoef, interp);
+
+            posCoef = _mm_add_ps(posCoef1, posCoef);
+            negCoef = _mm_add_ps(negCoef, negCoef1);
+        }
+        switch (CHANNELS) {
+        case 1: {
+            __m128 posSamp = _mm_loadu_ps(sP);
+            __m128 negSamp = _mm_loadu_ps(sN);
+            sP -= 4;
+            sN += 4;
+
+            posSamp = _mm_shuffle_ps(posSamp, posSamp, 0x1B);
+            posSamp = _mm_mul_ps(posSamp, posCoef);
+            negSamp = _mm_mul_ps(negSamp, negCoef);
+
+            accL = _mm_add_ps(accL, posSamp);
+            accL = _mm_add_ps(accL, negSamp);
+        } break;
+        case 2: {
+            __m128 posSamp0 = _mm_loadu_ps(sP);
+            __m128 posSamp1 = _mm_loadu_ps(sP+4);
+            __m128 negSamp0 = _mm_loadu_ps(sN);
+            __m128 negSamp1 = _mm_loadu_ps(sN+4);
+            sP -= 8;
+            sN += 8;
+
+            // deinterleave everything and reverse the positives
+            __m128 posSampL = _mm_shuffle_ps(posSamp1, posSamp0, 0x22);
+            __m128 posSampR = _mm_shuffle_ps(posSamp1, posSamp0, 0x77);
+            __m128 negSampL = _mm_shuffle_ps(negSamp0, negSamp1, 0x88);
+            __m128 negSampR = _mm_shuffle_ps(negSamp0, negSamp1, 0xDD);
+
+            posSampL = _mm_mul_ps(posSampL, posCoef);
+            posSampR = _mm_mul_ps(posSampR, posCoef);
+            negSampL = _mm_mul_ps(negSampL, negCoef);
+            negSampR = _mm_mul_ps(negSampR, negCoef);
+
+            accL = _mm_add_ps(accL, posSampL);
+            accR = _mm_add_ps(accR, posSampR);
+            accL = _mm_add_ps(accL, negSampL);
+            accR = _mm_add_ps(accR, negSampR);
+        } break;
+        }
+    } while (count -= 4);
+
+    // multiply by volume and save
+    __m128 vLR = _mm_setzero_ps();
+    __m128 outSamp;
+    vLR = _mm_loadl_pi(vLR, reinterpret_cast<const __m64*>(volumeLR));
+    outSamp = _mm_loadl_pi(vLR, reinterpret_cast<__m64*>(out));
+
+    // combine and funnel down accumulator
+    __m128 outAccum = _mm_setzero_ps();
+    if (CHANNELS == 1) {
+        // duplicate accL to both L and R
+        outAccum = _mm_add_ps(accL, _mm_movehl_ps(accL, accL));
+        outAccum = _mm_add_ps(outAccum, _mm_shuffle_ps(outAccum, outAccum, 0x11));
+    } else if (CHANNELS == 2) {
+        // accR contains R, fold in
+        outAccum = _mm_hadd_ps(accL, accR);
+        outAccum = _mm_hadd_ps(outAccum, outAccum);
+    }
+
+    outAccum = _mm_mul_ps(outAccum, vLR);
+    outSamp = _mm_add_ps(outSamp, outAccum);
+    _mm_storel_pi(reinterpret_cast<__m64*>(out), outSamp);
+}
+
+template<>
+inline void ProcessL<1, 16>(float* const out,
+        int count,
+        const float* coefsP,
+        const float* coefsN,
+        const float* sP,
+        const float* sN,
+        const float* const volumeLR)
+{
+    ProcessSSEIntrinsic<1, 16, true>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            0 /*lerpP*/, NULL /*coefsP1*/, NULL /*coefsN1*/);
+}
+
+template<>
+inline void ProcessL<2, 16>(float* const out,
+        int count,
+        const float* coefsP,
+        const float* coefsN,
+        const float* sP,
+        const float* sN,
+        const float* const volumeLR)
+{
+    ProcessSSEIntrinsic<2, 16, true>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            0 /*lerpP*/, NULL /*coefsP1*/, NULL /*coefsN1*/);
+}
+
+template<>
+inline void Process<1, 16>(float* const out,
+        int count,
+        const float* coefsP,
+        const float* coefsN,
+        const float* coefsP1,
+        const float* coefsN1,
+        const float* sP,
+        const float* sN,
+        float lerpP,
+        const float* const volumeLR)
+{
+    ProcessSSEIntrinsic<1, 16, false>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            lerpP, coefsP1, coefsN1);
+}
+
+template<>
+inline void Process<2, 16>(float* const out,
+        int count,
+        const float* coefsP,
+        const float* coefsN,
+        const float* coefsP1,
+        const float* coefsN1,
+        const float* sP,
+        const float* sN,
+        float lerpP,
+        const float* const volumeLR)
+{
+    ProcessSSEIntrinsic<2, 16, false>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            lerpP, coefsP1, coefsN1);
+}
+
+#endif //USE_SSE
+
+} // namespace android
+
+#endif /*ANDROID_AUDIO_RESAMPLER_FIR_PROCESS_SSE_H*/
diff --git a/services/audioflinger/tests/test_utils.h b/services/audioflinger/tests/test_utils.h
index 283c768..b61a929 100644
--- a/services/audioflinger/tests/test_utils.h
+++ b/services/audioflinger/tests/test_utils.h
@@ -17,6 +17,12 @@
 #ifndef ANDROID_AUDIO_TEST_UTILS_H
 #define ANDROID_AUDIO_TEST_UTILS_H
 
+#ifndef LOG_TAG
+#define LOG_TAG "test_utils"
+#endif
+
+#include <log/log.h>
+
 #include <audio_utils/sndfile.h>
 
 #ifndef ARRAY_SIZE
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8744de8..f64c4f9 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -342,6 +342,9 @@
     ALOGV("handleDeviceConfigChange(() device: 0x%X, address %s name %s",
           device, device_address, device_name);
 
+    // connect/disconnect only 1 device at a time
+    if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
+
     // Check if the device is currently connected
     sp<DeviceDescriptor> devDesc =
             mHwModules.getDeviceDescriptor(device, device_address, device_name);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index b4470c0..c5323d1 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -37,9 +37,6 @@
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
-    if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
-        return BAD_VALUE;
-    }
     if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
             state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
         return BAD_VALUE;
@@ -72,9 +69,6 @@
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
-    if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
-        return BAD_VALUE;
-    }
 
     ALOGV("handleDeviceConfigChange()");
     Mutex::Autolock _l(mLock);