audiohal: Always load A2DP module locally

This makes legitimate unix socket interaction between A2DP
module and the Bluetooth stack.

Implemented by allowing both "local" and "hidl" interface
wrappers to co-exist for devices and streams. A "hybrid" device
factory is introduced to create an appropriate implementation
of a device depending on the requested module name.

Bug: 37640821
Test: Play Music over BT headset
Change-Id: I5592961dd5b56840418fb122680979d11a261b6c
diff --git a/media/libaudiohal/Android.mk b/media/libaudiohal/Android.mk
index 68a1f7b..e592169 100644
--- a/media/libaudiohal/Android.mk
+++ b/media/libaudiohal/Android.mk
@@ -5,30 +5,37 @@
 LOCAL_SHARED_LIBRARIES := \
     libcutils   \
     liblog      \
-    libutils
+    libutils    \
+    libhardware
+
+LOCAL_SRC_FILES := \
+    DeviceHalLocal.cpp          \
+    DevicesFactoryHalHybrid.cpp \
+    DevicesFactoryHalLocal.cpp  \
+    StreamHalLocal.cpp
+
+LOCAL_CFLAGS := -Wall -Werror
 
 ifeq ($(USE_LEGACY_LOCAL_AUDIO_HAL), true)
 
 # Use audiohal directly w/o hwbinder middleware.
 # This is for performance comparison and debugging only.
 
-LOCAL_SRC_FILES := \
-    DeviceHalLocal.cpp          \
-    DevicesFactoryHalLocal.cpp  \
+LOCAL_SRC_FILES += \
     EffectBufferHalLocal.cpp    \
-    EffectHalLocal.cpp          \
     EffectsFactoryHalLocal.cpp  \
-    StreamHalLocal.cpp
+    EffectHalLocal.cpp
 
 LOCAL_SHARED_LIBRARIES += \
-    libeffects  \
-    libhardware
+    libeffects
+
+LOCAL_CFLAGS += -DUSE_LEGACY_LOCAL_AUDIO_HAL
 
 else  # if !USE_LEGACY_LOCAL_AUDIO_HAL
 
-LOCAL_SRC_FILES := \
+LOCAL_SRC_FILES += \
     ConversionHelperHidl.cpp   \
-    HalDeathHandlerHidl.cpp   \
+    HalDeathHandlerHidl.cpp    \
     DeviceHalHidl.cpp          \
     DevicesFactoryHalHidl.cpp  \
     EffectBufferHalHidl.cpp    \
@@ -60,6 +67,4 @@
 
 LOCAL_MODULE := libaudiohal
 
-LOCAL_CFLAGS := -Wall -Werror
-
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.cpp b/media/libaudiohal/DevicesFactoryHalHidl.cpp
index fc2645e..31da263 100644
--- a/media/libaudiohal/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/DevicesFactoryHalHidl.cpp
@@ -33,11 +33,6 @@
 
 namespace android {
 
-// static
-sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
-    return new DevicesFactoryHalHidl();
-}
-
 DevicesFactoryHalHidl::DevicesFactoryHalHidl() {
     mDevicesFactory = IDevicesFactory::getService();
     if (mDevicesFactory != 0) {
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.h b/media/libaudiohal/DevicesFactoryHalHidl.h
index a26dec1..e2f1ad1 100644
--- a/media/libaudiohal/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/DevicesFactoryHalHidl.h
@@ -36,7 +36,7 @@
     virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
 
   private:
-    friend class DevicesFactoryHalInterface;
+    friend class DevicesFactoryHalHybrid;
 
     sp<IDevicesFactory> mDevicesFactory;
 
diff --git a/media/libaudiohal/DevicesFactoryHalHybrid.cpp b/media/libaudiohal/DevicesFactoryHalHybrid.cpp
new file mode 100644
index 0000000..454b03b
--- /dev/null
+++ b/media/libaudiohal/DevicesFactoryHalHybrid.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DevicesFactoryHalHybrid"
+//#define LOG_NDEBUG 0
+
+#include "DevicesFactoryHalHybrid.h"
+#include "DevicesFactoryHalLocal.h"
+#ifndef USE_LEGACY_LOCAL_AUDIO_HAL
+#include "DevicesFactoryHalHidl.h"
+#endif
+
+namespace android {
+
+// static
+sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
+    return new DevicesFactoryHalHybrid();
+}
+
+DevicesFactoryHalHybrid::DevicesFactoryHalHybrid()
+        : mLocalFactory(new DevicesFactoryHalLocal()),
+          mHidlFactory(
+#ifdef USE_LEGACY_LOCAL_AUDIO_HAL
+                  nullptr
+#else
+                  new DevicesFactoryHalHidl()
+#endif
+                       ) {
+}
+
+DevicesFactoryHalHybrid::~DevicesFactoryHalHybrid() {
+}
+
+status_t DevicesFactoryHalHybrid::openDevice(const char *name, sp<DeviceHalInterface> *device) {
+    if (mHidlFactory != 0 && strcmp(AUDIO_HARDWARE_MODULE_ID_A2DP, name) != 0) {
+        return mHidlFactory->openDevice(name, device);
+    }
+    return mLocalFactory->openDevice(name, device);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/DevicesFactoryHalHybrid.h b/media/libaudiohal/DevicesFactoryHalHybrid.h
new file mode 100644
index 0000000..abd57d6
--- /dev/null
+++ b/media/libaudiohal/DevicesFactoryHalHybrid.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HYBRID_H
+#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HYBRID_H
+
+#include <media/audiohal/DevicesFactoryHalInterface.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class DevicesFactoryHalHybrid : public DevicesFactoryHalInterface
+{
+  public:
+    // Opens a device with the specified name. To close the device, it is
+    // necessary to release references to the returned object.
+    virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
+
+  private:
+    friend class DevicesFactoryHalInterface;
+
+    // Can not be constructed directly by clients.
+    DevicesFactoryHalHybrid();
+
+    virtual ~DevicesFactoryHalHybrid();
+
+    sp<DevicesFactoryHalInterface> mLocalFactory;
+    sp<DevicesFactoryHalInterface> mHidlFactory;
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HYBRID_H
diff --git a/media/libaudiohal/DevicesFactoryHalLocal.cpp b/media/libaudiohal/DevicesFactoryHalLocal.cpp
index cd9a9e7..13a9acd 100644
--- a/media/libaudiohal/DevicesFactoryHalLocal.cpp
+++ b/media/libaudiohal/DevicesFactoryHalLocal.cpp
@@ -27,11 +27,6 @@
 
 namespace android {
 
-// static
-sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
-    return new DevicesFactoryHalLocal();
-}
-
 static status_t load_audio_interface(const char *if_name, audio_hw_device_t **dev)
 {
     const hw_module_t *mod;
diff --git a/media/libaudiohal/DevicesFactoryHalLocal.h b/media/libaudiohal/DevicesFactoryHalLocal.h
index 58ce4ff..b9d18ab 100644
--- a/media/libaudiohal/DevicesFactoryHalLocal.h
+++ b/media/libaudiohal/DevicesFactoryHalLocal.h
@@ -33,7 +33,7 @@
     virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
 
   private:
-    friend class DevicesFactoryHalInterface;
+    friend class DevicesFactoryHalHybrid;
 
     // Can not be constructed directly by clients.
     DevicesFactoryHalLocal() {}
diff --git a/media/libaudiohal/EffectBufferHalHidl.cpp b/media/libaudiohal/EffectBufferHalHidl.cpp
index ef4097a..8b5201b 100644
--- a/media/libaudiohal/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/EffectBufferHalHidl.cpp
@@ -47,7 +47,7 @@
 status_t EffectBufferHalInterface::mirror(
         void* external, size_t size, sp<EffectBufferHalInterface>* buffer) {
     sp<EffectBufferHalInterface> tempBuffer = new EffectBufferHalHidl(size);
-    status_t result = reinterpret_cast<EffectBufferHalHidl*>(tempBuffer.get())->init();
+    status_t result = static_cast<EffectBufferHalHidl*>(tempBuffer.get())->init();
     if (result == OK) {
         tempBuffer->setExternalData(external);
         *buffer = tempBuffer;
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index 7d61443..b49b975 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -209,8 +209,8 @@
 
 status_t EffectHalHidl::setProcessBuffers() {
     Return<Result> ret = mEffect->setProcessBuffers(
-            reinterpret_cast<EffectBufferHalHidl*>(mInBuffer.get())->hidlBuffer(),
-            reinterpret_cast<EffectBufferHalHidl*>(mOutBuffer.get())->hidlBuffer());
+            static_cast<EffectBufferHalHidl*>(mInBuffer.get())->hidlBuffer(),
+            static_cast<EffectBufferHalHidl*>(mOutBuffer.get())->hidlBuffer());
     if (ret.isOk() && ret == Result::OK) {
         mBuffersChanged = false;
         return OK;
diff --git a/media/libaudiohal/EffectHalHidl.h b/media/libaudiohal/EffectHalHidl.h
index 0d011aa..6ffdaf1 100644
--- a/media/libaudiohal/EffectHalHidl.h
+++ b/media/libaudiohal/EffectHalHidl.h
@@ -58,6 +58,9 @@
     // Free resources on the remote side.
     virtual status_t close();
 
+    // Whether it's a local implementation.
+    virtual bool isLocal() const { return false; }
+
     uint64_t effectId() const { return mEffectId; }
 
     static void effectDescriptorToHal(
diff --git a/media/libaudiohal/EffectHalLocal.h b/media/libaudiohal/EffectHalLocal.h
index b499462..693fb50 100644
--- a/media/libaudiohal/EffectHalLocal.h
+++ b/media/libaudiohal/EffectHalLocal.h
@@ -48,6 +48,9 @@
     // Free resources on the remote side.
     virtual status_t close();
 
+    // Whether it's a local implementation.
+    virtual bool isLocal() const { return true; }
+
     effect_handle_t handle() const { return mHandle; }
 
   private:
diff --git a/media/libaudiohal/StreamHalLocal.cpp b/media/libaudiohal/StreamHalLocal.cpp
index b25e518..05800a0 100644
--- a/media/libaudiohal/StreamHalLocal.cpp
+++ b/media/libaudiohal/StreamHalLocal.cpp
@@ -79,11 +79,13 @@
 }
 
 status_t StreamHalLocal::addEffect(sp<EffectHalInterface> effect) {
+    LOG_ALWAYS_FATAL_IF(!effect->isLocal(), "Only local effects can be added for a local stream");
     return mStream->add_audio_effect(mStream,
             static_cast<EffectHalLocal*>(effect.get())->handle());
 }
 
 status_t StreamHalLocal::removeEffect(sp<EffectHalInterface> effect) {
+    LOG_ALWAYS_FATAL_IF(!effect->isLocal(), "Only local effects can be removed for a local stream");
     return mStream->remove_audio_effect(mStream,
             static_cast<EffectHalLocal*>(effect.get())->handle());
 }
@@ -162,7 +164,7 @@
     // correctly the case when the callback is invoked while StreamOutHalLocal's destructor is
     // already running, because the destructor is invoked after the refcount has been atomically
     // decremented.
-    wp<StreamOutHalLocal> weakSelf(reinterpret_cast<StreamOutHalLocal*>(cookie));
+    wp<StreamOutHalLocal> weakSelf(static_cast<StreamOutHalLocal*>(cookie));
     sp<StreamOutHalLocal> self = weakSelf.promote();
     if (self == 0) return 0;
     sp<StreamOutHalInterfaceCallback> callback = self->mCallback.promote();
diff --git a/media/libaudiohal/include/EffectHalInterface.h b/media/libaudiohal/include/EffectHalInterface.h
index 7f9a6fd..92622aa 100644
--- a/media/libaudiohal/include/EffectHalInterface.h
+++ b/media/libaudiohal/include/EffectHalInterface.h
@@ -52,6 +52,9 @@
     // Free resources on the remote side.
     virtual status_t close() = 0;
 
+    // Whether it's a local implementation.
+    virtual bool isLocal() const = 0;
+
   protected:
     // Subclasses can not be constructed directly by clients.
     EffectHalInterface() {}