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,