hal: Add support for audio power policy handling

* Add PowerPolicyClient class to receive policy change notifications

* Add PowerPolicyClient launcher to join ABinder threadpool

* Add functionality to launch powerpolicy extn in a new thread

Change-Id: Ic9349ca7c94fe481b2d7a74536f97e32a7b0fe8e
Signed-off-by: Tahir Dawson <dawson@codeaurora.org>
diff --git a/hal/audio_extn/Android.mk b/hal/audio_extn/Android.mk
index aba6592..db80656 100755
--- a/hal/audio_extn/Android.mk
+++ b/hal/audio_extn/Android.mk
@@ -1139,3 +1139,41 @@
 endif
 include $(BUILD_SHARED_LIBRARY)
 endif
+#-------------------------------------------
+
+#            Build Power_Policy_Client LIB
+#-------------------------------------------
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_POWER_POLICY)),true)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libaudiopowerpolicy
+
+LOCAL_VENDOR_MODULE := true
+
+LOCAL_SRC_FILES:= \
+        PowerPolicyClient.cpp \
+        power_policy_launcher.cpp
+
+LOCAL_C_INCLUDES:= \
+        vendor/qcom/opensource/audio-hal/primary-hal/hal \
+        system/media/audio/include
+
+LOCAL_SHARED_LIBRARIES:= \
+        android.frameworks.automotive.powerpolicy-ndk_platform \
+        libbase \
+        libbinder_ndk \
+        libcutils \
+        liblog \
+        libpowerpolicyclient
+
+ifneq ($(filter kona lahaina holi,$(TARGET_BOARD_PLATFORM)),)
+LOCAL_SANITIZE := integer_overflow
+endif
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DAEMON_SUPPORT)),true)
+  LOCAL_CFLAGS += -DDAEMON_SUPPORT_AUTO
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/hal/audio_extn/PowerPolicyClient.cpp b/hal/audio_extn/PowerPolicyClient.cpp
new file mode 100644
index 0000000..e3a9e22
--- /dev/null
+++ b/hal/audio_extn/PowerPolicyClient.cpp
@@ -0,0 +1,117 @@
+/* Copyright (c) 2021, The Linux Foundation. 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.
+    * Neither the name of The Linux 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.*/
+
+#include "PowerPolicyClient.h"
+
+#include <android-base/logging.h>
+#include <dlfcn.h>
+
+#ifdef DAEMON_SUPPORT_AUTO
+#define LIB_AUDIO_HAL_PLUGIN "libaudiohalpluginclient.so"
+#else
+#define LIB_AUDIO_HAL_PLUGIN "libaudiohalplugin.so"
+#endif
+
+namespace aafap = aidl::android::frameworks::automotive::powerpolicy;
+
+using aafap::CarPowerPolicy;
+using aafap::CarPowerPolicyFilter;
+using aafap::PowerComponent;
+using ::android::frameworks::automotive::powerpolicy::hasComponent;
+using ::ndk::ScopedAStatus;
+
+namespace {
+
+constexpr PowerComponent kAudioComponent = PowerComponent::AUDIO;
+constexpr PowerComponent kMicComponent = PowerComponent::MICROPHONE;
+
+}  // namespace
+
+PowerPolicyClient::PowerPolicyClient() {
+    plugin_handle = dlopen(LIB_AUDIO_HAL_PLUGIN, RTLD_NOW);
+    if (plugin_handle == NULL) {
+        LOG(ERROR) << "Failed to open plugin library";
+        return;
+    }
+
+    hal_plugin_send_msg = (hal_plugin_send_msg_t) dlsym(plugin_handle,
+                                         "audio_hal_plugin_send_msg");
+    if (hal_plugin_send_msg == NULL) {
+        LOG(ERROR) << "dlsym failed for audio_hal_plugin_send_msg";
+        dlclose(plugin_handle);
+        plugin_handle = NULL;
+    }
+
+    LOG(ERROR) << "PowerPolicyClient Initialzed";
+}
+
+PowerPolicyClient::~PowerPolicyClient() {
+    if (plugin_handle != NULL)
+        dlclose(plugin_handle);
+}
+
+void PowerPolicyClient::onInitFailed() {
+    LOG(ERROR) << "Initializing power policy client failed";
+}
+
+std::vector<PowerComponent> PowerPolicyClient::getComponentsOfInterest() {
+    std::vector<PowerComponent> components{kAudioComponent, kMicComponent};
+    return components;
+}
+
+ScopedAStatus PowerPolicyClient::onPolicyChanged(const CarPowerPolicy& powerPolicy) {
+    uint8_t disable = 0;
+
+    if (hasComponent(powerPolicy.enabledComponents, kAudioComponent)) {
+        LOG(ERROR) << "Power policy: Audio component is enabled";
+        disable = 0;
+        if (hal_plugin_send_msg != NULL)
+            hal_plugin_send_msg(AUDIO_HAL_PLUGIN_MSG_SILENT_MODE,
+                                &disable, sizeof(disable));
+    } else if (hasComponent(powerPolicy.disabledComponents, kAudioComponent)) {
+        LOG(ERROR) << "Power policy: Audio component is disabled";
+        disable = 1;
+        if (hal_plugin_send_msg != NULL)
+            hal_plugin_send_msg(AUDIO_HAL_PLUGIN_MSG_SILENT_MODE,
+                                &disable, sizeof(disable));
+    }
+
+    if (hasComponent(powerPolicy.enabledComponents, kMicComponent)) {
+        LOG(ERROR) << "Power policy: Microphone component is enabled";
+        disable = 0;
+        if (hal_plugin_send_msg != NULL)
+            hal_plugin_send_msg(AUDIO_HAL_PLUGIN_MSG_MIC_STATE,
+                                &disable, sizeof(disable));
+    } else if (hasComponent(powerPolicy.disabledComponents, kMicComponent)) {
+        disable = 1;
+        if (hal_plugin_send_msg != NULL)
+            hal_plugin_send_msg(AUDIO_HAL_PLUGIN_MSG_MIC_STATE,
+                                &disable, sizeof(disable));
+        LOG(ERROR) << "Power policy: Microphone component is disabled";
+    }
+    return ScopedAStatus::ok();
+}
diff --git a/hal/audio_extn/PowerPolicyClient.h b/hal/audio_extn/PowerPolicyClient.h
new file mode 100644
index 0000000..da0b434
--- /dev/null
+++ b/hal/audio_extn/PowerPolicyClient.h
@@ -0,0 +1,53 @@
+/* Copyright (c) 2021, The Linux Foundation. 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.
+    * Neither the name of The Linux 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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 QTI_AUDIO_POWERPOLICYCLIENT_H_
+#define QTI_AUDIO_POWERPOLICYCLIENT_H_
+
+#include "PowerPolicyClientBase.h"
+#include "audio_hal_plugin.h"
+
+typedef int32_t (*hal_plugin_send_msg_t) (audio_hal_plugin_msg_type_t, void*, uint32_t);
+
+class PowerPolicyClient
+    : public ::android::frameworks::automotive::powerpolicy::PowerPolicyClientBase {
+  public:
+    explicit PowerPolicyClient();
+    ~PowerPolicyClient();
+
+    void onInitFailed();
+    std::vector<::aidl::android::frameworks::automotive::powerpolicy::PowerComponent>
+    getComponentsOfInterest() override;
+    ::ndk::ScopedAStatus onPolicyChanged(
+            const ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicy&) override;
+
+  private:
+        void* plugin_handle;
+        hal_plugin_send_msg_t hal_plugin_send_msg;
+};
+
+#endif  // QTI_AUDIO_POWERPOLICYCLIENT_H_
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index d3b2935..bcde112 100755
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -6438,7 +6438,75 @@
 
 // END: Synth ========================================================================
 
+// START: Power Policy Client ======================================================================
+#ifdef __LP64__
+#define POWER_POLICY_LIB_PATH "/vendor/lib64/libaudiopowerpolicy.so"
+#else
+#define POWER_POLICY_LIB_PATH "/vendor/lib/libaudiopowerpolicy.so"
+#endif
 
+static void* power_policy_lib_handle;
+typedef int (*launch_power_policy_t) ();
+static launch_power_policy_t launch_power_policy;
+
+static void* power_policy_thread_func(void* arg __unused) {
+    if (launch_power_policy == NULL) {
+        ALOGE("%s: Power Policy launcher is NULL", __func__);
+        goto exit;
+    }
+    ALOGD("%s: Launching Power Policy Client", __func__);
+    launch_power_policy();
+
+exit:
+    pthread_exit(NULL);
+}
+
+static int power_policy_feature_init(bool is_feature_enabled)
+{
+    pthread_t tid;
+    pthread_attr_t attr;
+
+    ALOGD("%s: Called with feature %s", __func__,
+                  is_feature_enabled ? "Enabled" : "NOT Enabled");
+    if (is_feature_enabled) {
+        // dlopen lib
+        power_policy_lib_handle = dlopen(POWER_POLICY_LIB_PATH, RTLD_NOW);
+
+        if (!power_policy_lib_handle) {
+            ALOGE("%s: dlopen failed", __func__);
+            goto feature_disabled;
+        }
+        if (!(launch_power_policy = (launch_power_policy_t)dlsym(
+                                    power_policy_lib_handle, "launchPowerPolicyClient")))
+        {
+            ALOGE("%s: dlsym failed", __func__);
+            goto feature_disabled;
+        }
+
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+        if (pthread_create(&tid, &attr, power_policy_thread_func, NULL))
+        {
+            ALOGE("%s: Failed to create power policy thread", __func__);
+            goto feature_disabled;
+        }
+        ALOGD("%s:: ---- Feature Power Policy Client is Enabled ----", __func__);
+        return 0;
+    }
+
+feature_disabled:
+    if (power_policy_lib_handle) {
+        dlclose(power_policy_lib_handle);
+        power_policy_lib_handle = NULL;
+    }
+
+    launch_power_policy = NULL;
+
+    ALOGW(":: %s: ---- Feature Power Policy Client is disabled ----", __func__);
+    return -ENOSYS;
+
+// END: Power Policy Client ======================================================================
+}
 void audio_extn_feature_init()
 {
     vendor_enhanced_info = audio_extn_utils_get_vendor_enhanced_info();
@@ -6563,6 +6631,9 @@
     synth_feature_init(
         property_get_bool("vendor.audio.feature.synth.enable",
                        false));
+    power_policy_feature_init(
+        property_get_bool("vendor.audio.feature.powerpolicy.enable",
+                       false));
 }
 
 void audio_extn_set_parameters(struct audio_device *adev,
diff --git a/hal/audio_extn/power_policy_launcher.cpp b/hal/audio_extn/power_policy_launcher.cpp
new file mode 100644
index 0000000..a85f30c
--- /dev/null
+++ b/hal/audio_extn/power_policy_launcher.cpp
@@ -0,0 +1,51 @@
+/* Copyright (c) 2021, The Linux Foundation. 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.
+    * Neither the name of The Linux 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.*/
+
+#include "PowerPolicyClient.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <log/log.h>
+
+extern "C" {
+
+    int launchPowerPolicyClient() {
+        ALOGD("%s: power policy launcher called", __func__);
+        ABinderProcess_setThreadPoolMaxThreadCount(0);
+        std::shared_ptr<PowerPolicyClient> powerPolicyClient =
+                ::ndk::SharedRefBase::make<PowerPolicyClient>();
+        ALOGD("%s:Instantiating power policy client from launcher", __func__);
+        powerPolicyClient->init();
+        ALOGD("%s: Power Policy class inited, joining threadpool", __func__);
+
+        ABinderProcess_joinThreadPool();
+
+        LOG(ERROR) << "Error in PowerPolicyClient binder thread";
+        return EXIT_FAILURE; // should not reach
+    }
+}
diff --git a/hal/audio_hal_plugin.h b/hal/audio_hal_plugin.h
index 3d77b23..1f56a2f 100644
--- a/hal/audio_hal_plugin.h
+++ b/hal/audio_hal_plugin.h
@@ -87,6 +87,7 @@
     AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ_SUBBANDS, /**< get EQ subbands params */
     AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_GET_CMD, /**< pass through get cmds */
     AUDIO_HAL_PLUGIN_MSG_SILENT_MODE, /**<set silent boot mode */
+    AUDIO_HAL_PLUGIN_MSG_MIC_STATE, /**< enable or disable codec mic */
     AUDIO_HAL_PLUGIN_MSG_MAX
 } audio_hal_plugin_msg_type_t;