Merge tag 'AUDIO.LA.8.0.r1-09700-KAILUA.0' of https://git.codelinaro.org/clo/la/platform/hardware/qcom/audio-ar into lineage-21.0-caf-sm8550

AUDIO.LA.8.0.r1-09700-KAILUA.0

* tag 'AUDIO.LA.8.0.r1-09700-KAILUA.0' of https://git.codelinaro.org/clo/la/platform/hardware/qcom/audio-ar:
  AHAL: battery_listener: Add support for health hidl interface
  HAL : Buffer Count Increase for ICMD
  HAL : update set_volume logic in AudioStream.cpp
  AHAL: fix channel mask for right channel
  hal: check for active input streams before assigning nullptr
  audio_extn: return error when AGM service not initialized properly

Change-Id: Ic4e8031317e366e3510ef436f6b769c9df63eef4
diff --git a/hal/AudioDevice.cpp b/hal/AudioDevice.cpp
index 9071cf7..0283d5c 100644
--- a/hal/AudioDevice.cpp
+++ b/hal/AudioDevice.cpp
@@ -623,12 +623,16 @@
     auto iter =
         std::find(stream_in_list_.begin(), stream_in_list_.end(), stream);
     if (iter == stream_in_list_.end()) {
-        AHAL_ERR("invalid output stream");
+        AHAL_ERR("invalid input stream");
     } else {
-        if (voice_) {
-            voice_->stream_in_primary_ = nullptr;
-        }
         stream_in_list_.erase(iter);
+        if (voice_) {
+            if (stream_in_list_.size() == 0) {
+                voice_->stream_in_primary_ = nullptr;
+            } else {
+                voice_->stream_in_primary_ = stream_in_list_[0];
+            }
+        }
     }
     in_list_mutex.unlock();
 }
diff --git a/hal/AudioStream.cpp b/hal/AudioStream.cpp
index bb0af27..0bec4fc 100644
--- a/hal/AudioStream.cpp
+++ b/hal/AudioStream.cpp
@@ -2610,9 +2610,9 @@
         volume_ = NULL;
     }
 
-    if (left == right) {
-        volume_ = (struct pal_volume_data *)malloc(sizeof(struct pal_volume_data)
-                    +sizeof(struct pal_channel_vol_kv));
+    if (audio_channel_count_from_out_mask(config_.channel_mask) == 1) {
+        volume_ = (struct pal_volume_data *)calloc(1, sizeof(struct pal_volume_data)
+                +sizeof(struct pal_channel_vol_kv));
         if (!volume_) {
             AHAL_ERR("Failed to allocate mem for volume_");
             ret = -ENOMEM;
@@ -2620,9 +2620,15 @@
         }
         volume_->no_of_volpair = 1;
         volume_->volume_pair[0].channel_mask = 0x03;
-        volume_->volume_pair[0].vol = left;
+
+        if (config_.channel_mask == 0x1)
+            volume_->volume_pair[0].vol = left;
+        else if (config_.channel_mask == 0x2)
+            volume_->volume_pair[0].vol = right;
+        else
+            volume_->volume_pair[0].vol = (left + right)/2.0;
     } else {
-        volume_ = (struct pal_volume_data *)malloc(sizeof(struct pal_volume_data)
+        volume_ = (struct pal_volume_data *)calloc(1, sizeof(struct pal_volume_data)
                     +sizeof(struct pal_channel_vol_kv) * 2);
         if (!volume_) {
             AHAL_ERR("Failed to allocate mem for volume_");
@@ -2632,7 +2638,7 @@
         volume_->no_of_volpair = 2;
         volume_->volume_pair[0].channel_mask = 0x01;
         volume_->volume_pair[0].vol = left;
-        volume_->volume_pair[1].channel_mask = 0x10;
+        volume_->volume_pair[1].channel_mask = 0x02;
         volume_->volume_pair[1].vol = right;
     }
 
@@ -3201,8 +3207,15 @@
     } else
         outBufSize = StreamOutPrimary::GetBufferSize();
 
-    if (usecase_ == USECASE_AUDIO_PLAYBACK_LOW_LATENCY)
-        outBufCount = LOW_LATENCY_PLAYBACK_PERIOD_COUNT;
+    if (usecase_ == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) {
+        if (streamAttributes_.type == PAL_STREAM_VOICE_CALL_MUSIC) {
+            outBufCount = LOW_LATENCY_ICMD_PLAYBACK_PERIOD_COUNT;
+            AHAL_DBG("LOW_LATENCY_ICMD - Buffer Count : %d", outBufCount);
+        }
+        else {
+            outBufCount = LOW_LATENCY_PLAYBACK_PERIOD_COUNT;
+        }
+    }
     else if (usecase_ == USECASE_AUDIO_PLAYBACK_OFFLOAD2)
         outBufCount = PCM_OFFLOAD_PLAYBACK_PERIOD_COUNT;
     else if (usecase_ == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)
diff --git a/hal/AudioStream.h b/hal/AudioStream.h
index e65ce28..ca8eba8 100644
--- a/hal/AudioStream.h
+++ b/hal/AudioStream.h
@@ -98,6 +98,7 @@
 #define DEFAULT_OUTPUT_SAMPLING_RATE    48000
 #define LOW_LATENCY_PLAYBACK_PERIOD_SIZE 240 /** 5ms; frames */
 #define LOW_LATENCY_PLAYBACK_PERIOD_COUNT 2
+#define LOW_LATENCY_ICMD_PLAYBACK_PERIOD_COUNT 4 /** In Call Music **/
 
 #define PCM_OFFLOAD_PLAYBACK_PERIOD_COUNT 2 /** Direct PCM */
 #define DEEP_BUFFER_PLAYBACK_PERIOD_COUNT 2 /** Deep Buffer*/
diff --git a/hal/audio_extn/Android.mk b/hal/audio_extn/Android.mk
index 62e5796..75ecc37 100644
--- a/hal/audio_extn/Android.mk
+++ b/hal/audio_extn/Android.mk
@@ -96,6 +96,12 @@
     -Wno-unused-function \
     -Wno-unused-variable
 
+# Define HEALTH_AIDL for targets other than anorak.
+ifneq ($(TARGET_BOARD_PLATFORM), anorak)
+    LOCAL_CFLAGS += -DHEALTH_AIDL
+    $(warning "Using AIDL HEALTH")
+endif
+
 LOCAL_SHARED_LIBRARIES := \
     android.hardware.health@1.0 \
     android.hardware.health@2.0 \
@@ -111,6 +117,12 @@
     liblog \
     libutils \
 
+ifneq ($(TARGET_BOARD_PLATFORM), anorak)
+    LOCAL_SHARED_LIBRARIES += \
+        android.hardware.health-V1-ndk \
+        libbinder_ndk
+endif
+
 LOCAL_STATIC_LIBRARIES := libhealthhalutils
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/hal/audio_extn/AudioExtn.cpp b/hal/audio_extn/AudioExtn.cpp
index 896666a..edd7f67 100644
--- a/hal/audio_extn/AudioExtn.cpp
+++ b/hal/audio_extn/AudioExtn.cpp
@@ -807,6 +807,9 @@
         } else {
             AHAL_DBG("successfully registered AGM service");
         }
+    } else {
+        AHAL_ERR("Failed to initialize AGM service");
+        return -EINVAL;
     }
 #endif
     /* to register other hidls */
diff --git a/hal/audio_extn/battery_listener.cpp b/hal/audio_extn/battery_listener.cpp
index 9c6b338..1250e78 100644
--- a/hal/audio_extn/battery_listener.cpp
+++ b/hal/audio_extn/battery_listener.cpp
@@ -28,23 +28,45 @@
 *
 * Changes from Qualcomm Innovation Center are provided under the following license:
 *
-* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause-Clear
 */
 #define LOG_TAG "audio_hw::BatteryListener"
 #include <log/log.h>
+#ifdef HEALTH_AIDL
 #include <android/binder_manager.h>
 #include <aidl/android/hardware/health/IHealth.h>
 #include <aidl/android/hardware/health/IHealthInfoCallback.h>
 #include <aidl/android/hardware/health/BnHealthInfoCallback.h>
+#else
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hardware/health/2.1/IHealth.h>
+#include <android/hardware/health/2.1/IHealthInfoCallback.h>
+#include <healthhalutils/HealthHalUtils.h>
+#include <hidl/HidlTransportSupport.h>
+#endif
+
 #include <thread>
 #include "battery_listener.h"
 
+#ifdef HEALTH_AIDL
 using aidl::android::hardware::health::BatteryStatus;
 using aidl::android::hardware::health::HealthInfo;
 using aidl::android::hardware::health::IHealthInfoCallback;
 using aidl::android::hardware::health::BnHealthInfoCallback;
 using aidl::android::hardware::health::IHealth;
+#else
+using android::hardware::interfacesEqual;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::health::V1_0::BatteryStatus;
+using android::hardware::health::V1_0::toString;
+using android::hardware::health::V2_1::HealthInfo;
+using android::hardware::health::V2_1::IHealthInfoCallback;
+using android::hardware::health::V2_1::IHealth;
+using android::hardware::health::V2_0::Result;
+using android::hidl::manager::V1_0::IServiceManager;
+#endif
 using namespace std::literals::chrono_literals;
 
 namespace android {
@@ -52,6 +74,7 @@
 #define GET_HEALTH_SVC_RETRY_CNT 5
 #define GET_HEALTH_SVC_WAIT_TIME_MS 500
 
+#ifdef HEALTH_AIDL
 struct BatteryListenerImpl : public BnHealthInfoCallback {
     typedef std::function<void(bool)> cb_fn_t;
     BatteryListenerImpl(cb_fn_t cb);
@@ -81,17 +104,55 @@
 
 static std::shared_ptr<BatteryListenerImpl> batteryListener;
 
+#else
+struct BatteryListenerImpl : public hardware::health::V2_1::IHealthInfoCallback,
+                             public hardware::hidl_death_recipient {
+    typedef std::function<void(bool)> cb_fn_t;
+    BatteryListenerImpl(cb_fn_t cb);
+    virtual ~BatteryListenerImpl ();
+    virtual hardware::Return<void> healthInfoChanged(
+            const hardware::health::V2_0::HealthInfo& info);
+    virtual hardware::Return<void> healthInfoChanged_2_1(
+            const hardware::health::V2_1::HealthInfo& info);
+    virtual void serviceDied(uint64_t cookie,
+                             const wp<hidl::base::V1_0::IBase>& who);
+    bool isCharging() {
+        std::lock_guard<std::mutex> _l(mLock);
+        return statusToBool(mStatus);
+    }
+    void reset();
+  private:
+    sp<hardware::health::V2_1::IHealth> mHealth;
+    status_t init();
+    BatteryStatus mStatus;
+    cb_fn_t mCb;
+    std::mutex mLock;
+    std::condition_variable mCond;
+    std::unique_ptr<std::thread> mThread;
+    bool mDone;
+    bool statusToBool(const BatteryStatus &s) const {
+        return (s == BatteryStatus::CHARGING) ||
+               (s ==  BatteryStatus::FULL);
+    }
+};
+#endif
 status_t BatteryListenerImpl::init()
 {
     int tries = 0;
+#ifdef HEALTH_AIDL
     auto service_name = std::string() + IHealth::descriptor + "/default";
+ #endif
 
     if (mHealth != NULL)
         return INVALID_OPERATION;
 
     do {
+#ifdef HEALTH_AIDL
         mHealth = IHealth::fromBinder(ndk::SpAIBinder(
             AServiceManager_getService(service_name.c_str())));
+#else
+            mHealth = IHealth::getService();
+#endif
         if (mHealth != NULL)
             break;
         usleep(GET_HEALTH_SVC_WAIT_TIME_MS * 1000);
@@ -105,7 +166,17 @@
         ALOGI("Get health service in %d tries", tries);
     }
     mStatus = BatteryStatus::UNKNOWN;
+#ifdef HEALTH_AIDL
     auto ret = mHealth->getChargeStatus(&mStatus);
+#else
+    auto ret = mHealth->getChargeStatus([&](Result r, BatteryStatus status) {
+        if (r != Result::SUCCESS) {
+            ALOGE("batterylistener: cannot get battery status");
+            return;
+        }
+        mStatus = status;
+    });
+#endif
     if (!ret.isOk())
         ALOGE("batterylistener: get charge status transaction error");
 
@@ -148,6 +219,7 @@
                 }
             }
         });
+#ifdef HEALTH_AIDL
     mHealth->registerCallback(batteryListener);
     binder_status_t binder_status = AIBinder_linkToDeath(
         mHealth->asBinder().get(), mDeathRecipient.get(), this);
@@ -156,9 +228,14 @@
             static_cast<int>(binder_status));
         return NO_INIT;
     }
+#else
+    mHealth->registerCallback(this);
+    mHealth->linkToDeath(this, 0 /* cookie */);
+#endif
     return NO_ERROR;
 }
 
+#ifdef HEALTH_AIDL
 BatteryListenerImpl::BatteryListenerImpl(cb_fn_t cb) :
         mCb(cb),
         mDeathRecipient(AIBinder_DeathRecipient_new(BatteryListenerImpl::serviceDied))
@@ -166,29 +243,44 @@
 
 }
 
+#else
+BatteryListenerImpl::BatteryListenerImpl(cb_fn_t cb) :
+        mCb(cb)
+{
+    init();
+}
+#endif
 BatteryListenerImpl::~BatteryListenerImpl()
 {
+#ifdef HEALTH_AIDL
     {
         std::lock_guard<std::mutex> _l(mLock);
         mDone = true;
         mCond.notify_one();
     }
+#endif
     mThread->join();
 }
 
 void BatteryListenerImpl::reset() {
     std::lock_guard<std::mutex> _l(mLock);
     if (mHealth != nullptr) {
+#ifdef HEALTH_AIDL
         mHealth->unregisterCallback(batteryListener);
         binder_status_t status = AIBinder_unlinkToDeath(
             mHealth->asBinder().get(), mDeathRecipient.get(), this);
         if (status != STATUS_OK && status != STATUS_DEAD_OBJECT)
             ALOGE("Cannot unlink to death");
+#else
+        mHealth->unregisterCallback(this);
+        mHealth->unlinkToDeath(this);
+#endif
     }
     mStatus = BatteryStatus::UNKNOWN;
     mDone = true;
     mCond.notify_one();
 }
+#ifdef HEALTH_AIDL
 void BatteryListenerImpl::serviceDied(void *cookie)
 {
     BatteryListenerImpl *listener = reinterpret_cast<BatteryListenerImpl *>(cookie);
@@ -208,11 +300,30 @@
     listener->init();
 }
 
+#else
+void BatteryListenerImpl::serviceDied(uint64_t cookie __unused,
+                                     const wp<hidl::base::V1_0::IBase>& who)
+{
+    {
+        std::lock_guard<std::mutex> _l(mLock);
+        if (mHealth == NULL || !interfacesEqual(mHealth, who.promote())) {
+            ALOGE("health not initialized or unknown interface died");
+            return;
+        }
+        ALOGI("health service died, reinit");
+        mDone = true;
+    }
+    mThread->join();
+    std::lock_guard<std::mutex> _l(mLock);
+    init();
+}
+#endif
 // this callback seems to be a SYNC callback and so
 // waits for return before next event is issued.
 // therefore we need not have a queue to process
 // NOT_CHARGING and CHARGING concurrencies.
 // Replace single var by a list if this assumption is broken
+#ifdef HEALTH_AIDL
 ndk::ScopedAStatus BatteryListenerImpl::healthInfoChanged(const HealthInfo& info)
 {
     ALOGV("healthInfoChanged: %d", info.batteryStatus);
@@ -224,15 +335,45 @@
     return ndk::ScopedAStatus::ok();
 }
 
+#else
+Return<void> BatteryListenerImpl::healthInfoChanged(
+        const hardware::health::V2_0::HealthInfo& info)
+{
+    ALOGV("healthInfoChanged: %d", info.legacy.batteryStatus);
+    std::unique_lock<std::mutex> l(mLock);
+    if (info.legacy.batteryStatus != mStatus) {
+        mStatus = info.legacy.batteryStatus;
+        mCond.notify_one();
+    }
+    return Void();
+}
+
+Return<void> BatteryListenerImpl::healthInfoChanged_2_1(
+        const hardware::health::V2_1::HealthInfo& info) {
+    ALOGV("healthInfoChanged_2_1: %d", info.legacy.legacy.batteryStatus);
+    healthInfoChanged(info.legacy);
+    return Void();
+}
+
+static sp<BatteryListenerImpl> batteryListener;
+#endif
 status_t batteryPropertiesListenerInit(BatteryListenerImpl::cb_fn_t cb)
 {
+#ifdef HEALTH_AIDL
     batteryListener = ndk::SharedRefBase::make<BatteryListenerImpl>(cb);
     return batteryListener->init();
+#else
+    batteryListener = new BatteryListenerImpl(cb);
+    return NO_ERROR;
+#endif
 }
 
 status_t batteryPropertiesListenerDeinit()
 {
     batteryListener->reset();
+#ifndef HEALTH_AIDL
+    batteryListener.clear();
+#endif
     return OK;
 }
 
diff --git a/hal/audio_extn/soundtrigger.cpp b/hal/audio_extn/soundtrigger.cpp
index 8d4602d..bc8db83 100644
--- a/hal/audio_extn/soundtrigger.cpp
+++ b/hal/audio_extn/soundtrigger.cpp
@@ -264,9 +264,9 @@
     return NULL;
 }
 
-extern "C" void check_init_audio_extension()
+extern "C" int check_init_audio_extension()
 {
-    AudioExtn::audio_extn_hidl_init();
+    return AudioExtn::audio_extn_hidl_init();
 }
 
 extern "C" void audio_hw_call_back(sound_trigger_event_type_t event,