/* * Copyright (c) 2019-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. * * Changes from Qualcomm Innovation Center, Inc. are provided under the following license: * * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause-Clear * */ #define ATRACE_TAG (ATRACE_TAG_AUDIO | ATRACE_TAG_HAL) #define LOG_TAG "PAL: API" #include #include #include #include #include #include #include #include "Stream.h" #include "Device.h" #include "ResourceManager.h" #include "PalCommon.h" #include "mem_logger.h" #include "PerfLock.h" #ifdef SEC_AUDIO_ADD_FOR_DEBUG #include "USBAudio.h" #endif class Stream; /** * Get PAL version in the form of Major and Minor number * seperated by period. * * @return the version string in the form of Major and Minor * e.g '1.0' */ const char* pal_get_version( ){ return PAL_VERSION; } static std::mutex pal_mutex; static uint32_t pal_init_ref_cnt = 0; static void notify_concurrent_stream(pal_stream_type_t type, pal_stream_direction_t dir, bool active) { std::shared_ptr rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG,"Resource manager unavailable"); return; } PAL_DBG(LOG_TAG, "Notify concurrent stream type %d, direction %d, active %d", type, dir, active); rm->ConcurrentStreamStatus(type, dir, active); } /* * pal_init - Initialize PAL * * Return 0 on success or error code otherwise * * Prerequisites * None. */ int32_t pal_init(void) { ATRACE_CALL(); PAL_DBG(LOG_TAG, "Enter."); int32_t ret = 0; std::shared_ptr ri = NULL; pal_mutex.lock(); if (pal_init_ref_cnt++ > 0) { PAL_DBG(LOG_TAG, "PAL already initialized, cnt: %d", pal_init_ref_cnt); goto exit; } try { ri = ResourceManager::getInstance(); } catch (const std::exception& e) { PAL_ERR(LOG_TAG, "pal init failed: %s", e.what()); ret = -EINVAL; goto exit; } ret = ri->initSndMonitor(); if (ret != 0) { PAL_ERR(LOG_TAG, "snd monitor init failed"); goto exit; } ri->init(); ret = ri->initContextManager(); if (ret != 0) { PAL_ERR(LOG_TAG, "ContextManager init failed, error:%d", ret); goto exit; } exit: pal_mutex.unlock(); PAL_DBG(LOG_TAG, "Exit. exit status : %d ", ret); return ret; } /* * pal_deinit - De-initialize PAL * * Prerequisites * PAL must be initialized. */ void pal_deinit(void) { ATRACE_CALL(); PAL_DBG(LOG_TAG, "Enter."); std::shared_ptr rm = NULL; pal_mutex.lock(); if (pal_init_ref_cnt > 0) { pal_init_ref_cnt--; PAL_DBG(LOG_TAG, "decrease pal ref cnt to %d", pal_init_ref_cnt); if (pal_init_ref_cnt > 0) goto exit; } else { PAL_ERR(LOG_TAG, "pal not initialized yet"); goto exit; } try { rm = ResourceManager::getInstance(); } catch (const std::exception& e) { PAL_ERR(LOG_TAG, "ResourceManager::getInstance() failed: %s", e.what()); goto exit; } kpiEnqueue(__func__, true); rm->deInitContextManager(); kpiEnqueue(__func__, false); ResourceManager::deinit(); exit: pal_mutex.unlock(); PAL_DBG(LOG_TAG, "Exit."); return; } int32_t pal_register_for_events(pal_audio_event_callback cb_event) { std::shared_ptr rm = NULL; Stream *stream = NULL; pal_callback_config_t config = {}; std::vector streams; struct pal_stream_attributes sAttr; std::vector > palDevices; PAL_DBG(LOG_TAG, "Enter. register callback events"); rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG,"Resource manager instance unavailable"); return -EINVAL; } rm->callback_event = cb_event; if (cb_event == NULL) { return 0; } if (rm->getActiveStream(streams, NULL) == 0) { for (int i = 0; i < streams.size(); i++) { stream = static_cast(streams[i]); stream->getPalDevices(palDevices); stream->getStreamAttributes(&sAttr); config.streamAttributes = sAttr; if(!palDevices.empty()) { config.currentDevices = (pal_device_id_t *) calloc(palDevices.size(), sizeof(pal_device_id_t)); int currentDeviceNumber = 0; for (auto &dev : palDevices) { config.currentDevices[currentDeviceNumber] = ((pal_device_id_t)dev->getSndDeviceId()); currentDeviceNumber++; } } rm->callback_event(&config, PAL_NOTIFY_START, true); if (config.currentDevices) free(config.currentDevices); } } PAL_DBG(LOG_TAG, "Exit"); return 0; } int32_t pal_stream_open(struct pal_stream_attributes *attributes, uint32_t no_of_devices, struct pal_device *devices, uint32_t no_of_modifiers, struct modifier_kv *modifiers, pal_stream_callback cb, uint64_t cookie, pal_stream_handle_t **stream_handle) { PerfLock perflock(__func__); ATRACE_CALL(); uint64_t *stream = NULL; Stream *s = NULL; int status = 0; struct pal_stream_attributes sAttr = {}; std::shared_ptr rm = NULL; rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; return status; } if (!attributes) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status); return status; } PAL_INFO(LOG_TAG, "Enter, stream type:%d", attributes->type); kpiEnqueue(__func__, true); #ifdef SOC_PERIPHERAL_PROT if (ResourceManager::isTZSecureZone) { PAL_DBG(LOG_TAG, "In secure zone, so stop the usecase"); status = -ENODEV; goto exit; } #endif try { s = Stream::create(attributes, devices, no_of_devices, modifiers, no_of_modifiers); } catch (const std::exception& e) { status = -EINVAL; PAL_ERR(LOG_TAG, "Stream create failed: %s", e.what()); Stream::handleStreamException(attributes, cb, cookie); goto exit; } if (!s) { status = -EINVAL; PAL_ERR(LOG_TAG, "stream creation failed status %d", status); goto exit; } status = s->open(); if (0 != status) { PAL_ERR(LOG_TAG, "pal_stream_open failed with status %d", status); if (s->close() != 0) { PAL_ERR(LOG_TAG, "stream closed failed."); } delete s; goto exit; } s->getStreamAttributes(&sAttr); #ifdef SEC_AUDIO_EARLYDROP_PATCH if (sAttr.type != PAL_STREAM_NON_TUNNEL && sAttr.type != PAL_STREAM_VOICE_CALL) rm->voteSleepMonitor(s, true); #endif #ifdef SEC_AUDIO_SOUND_TRIGGER_TYPE if (s->isHotwordRecord()) { notify_concurrent_stream(PAL_STREAM_HOTWORD, sAttr.direction, true); } else { notify_concurrent_stream(sAttr.type, sAttr.direction, true); } #else notify_concurrent_stream(sAttr.type, sAttr.direction, true); #endif if (cb) s->registerCallBack(cb, cookie); rm->initStreamUserCounter(s); stream = reinterpret_cast(s); *stream_handle = stream; exit: #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_INFO(LOG_TAG, "Exit. Value of stream_handle %pK, status %d : %s(%d)", stream, status, streamNameLUT.at(attributes->type).c_str(), attributes->type); #else PAL_INFO(LOG_TAG, "Exit. Value of stream_handle %pK, status %d", stream, status); #endif kpiEnqueue(__func__, false); return status; } int32_t pal_stream_close(pal_stream_handle_t *stream_handle) { ATRACE_CALL(); Stream *s = NULL; int status = 0; struct pal_stream_attributes sAttr = {}; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } PAL_INFO(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; return status; } rm->lockActiveStream(); if (!rm->isActiveStream(stream_handle)) { status = -EINVAL; rm->unlockActiveStream(); return status; } rm->unlockActiveStream(); s = reinterpret_cast(stream_handle); s->setCachedState(STREAM_IDLE); status = s->close(); if (rm->deactivateStreamUserCounter(s)) { PAL_ERR(LOG_TAG, "stream is being closed by another client"); return 0; } if (0 != status) { PAL_ERR(LOG_TAG, "stream closed failed. status %d", status); goto exit; } exit: s->getStreamAttributes(&sAttr); #ifdef SEC_AUDIO_SOUND_TRIGGER_TYPE if (s->isHotwordRecord()) { notify_concurrent_stream(PAL_STREAM_HOTWORD, sAttr.direction, false); } else { notify_concurrent_stream(sAttr.type, sAttr.direction, false); } #else notify_concurrent_stream(sAttr.type, sAttr.direction, false); #endif #ifdef SEC_AUDIO_EARLYDROP_PATCH if (sAttr.type != PAL_STREAM_NON_TUNNEL && sAttr.type != PAL_STREAM_VOICE_CALL) rm->voteSleepMonitor(s, false); #endif if (sAttr.type == PAL_STREAM_VOICE_CALL) rm->isCRSCallEnabled = false; rm->eraseStreamUserCounter(s); delete s; PAL_INFO(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_start(pal_stream_handle_t *stream_handle) { PerfLock perflock(__func__); ATRACE_CALL(); Stream *s = NULL; struct pal_stream_attributes sAttr = {}; std::vector > palDevices; std::shared_ptr rm = NULL; pal_callback_config_t config = {}; int status; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } PAL_INFO(LOG_TAG, "Enter. Stream handle %pK", stream_handle); #ifdef SOC_PERIPHERAL_PROT if (ResourceManager::isTZSecureZone) { PAL_DBG(LOG_TAG, "In secure zone, so stop the usecase"); status = -ENODEV; goto exit; } #endif rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; goto exit; } kpiEnqueue(__func__, true); rm->lockActiveStream(); if (!rm->isActiveStream(stream_handle)) { rm->unlockActiveStream(); status = -EINVAL; goto exit; } s = reinterpret_cast(stream_handle); status = rm->increaseStreamUserCounter(s); if (0 != status) { rm->unlockActiveStream(); PAL_ERR(LOG_TAG, "failed to increase stream user count"); goto exit; } rm->unlockActiveStream(); s->getStreamAttributes(&sAttr); s->getPalDevices(palDevices); if (sAttr.type == PAL_STREAM_VOICE_UI) rm->handleDeferredSwitch(); status = s->start(); rm->lockActiveStream(); rm->decreaseStreamUserCounter(s); rm->unlockActiveStream(); if (0 != status) { PAL_ERR(LOG_TAG, "stream start failed. status %d", status); goto exit; } if (rm->callback_event != NULL) { config.streamAttributes = sAttr; int32_t currentDeviceNumber = 0; if(!palDevices.empty()) { config.currentDevices = (pal_device_id_t *) calloc(palDevices.size(), sizeof(pal_device_id_t)); } if (!config.currentDevices) { PAL_ERR(LOG_TAG, "Memory alloc failed"); goto exit; } for (auto &dev : palDevices) { config.currentDevices[currentDeviceNumber] = ((pal_device_id_t)dev->getSndDeviceId()); currentDeviceNumber++; } config.noOfCurrentDevices = currentDeviceNumber; rm->callback_event(&config, PAL_NOTIFY_START, false); if (config.currentDevices) free(config.currentDevices); } exit: PAL_INFO(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_stop(pal_stream_handle_t *stream_handle) { ATRACE_CALL(); Stream *s = NULL; struct pal_stream_attributes sAttr = {}; std::shared_ptr rm = NULL; std::vector > palDevices; pal_callback_config_t config = {}; int status; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } PAL_INFO(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; goto exit; } kpiEnqueue(__func__, true); rm->lockActiveStream(); if (!rm->isActiveStream(stream_handle)) { rm->unlockActiveStream(); status = -EINVAL; goto exit; } s = reinterpret_cast(stream_handle); status = rm->increaseStreamUserCounter(s); if (0 != status) { rm->unlockActiveStream(); PAL_ERR(LOG_TAG, "failed to increase stream user count"); goto exit; } rm->unlockActiveStream(); s->getStreamAttributes(&sAttr); s->getPalDevices(palDevices); s->setCachedState(STREAM_STOPPED); status = s->stop(); rm->lockActiveStream(); rm->decreaseStreamUserCounter(s); rm->unlockActiveStream(); if (0 != status) { PAL_ERR(LOG_TAG, "stream stop failed. status : %d", status); goto exit; } if (rm->callback_event != NULL) { int32_t currentDeviceNumber = 0; if(!palDevices.empty()) config.currentDevices = (pal_device_id_t *) calloc(palDevices.size(), sizeof(pal_device_id_t)); if (!config.currentDevices) { PAL_ERR(LOG_TAG, "Memory alloc failed"); goto exit; } for (auto &dev : palDevices) { config.currentDevices[currentDeviceNumber] = ((pal_device_id_t)dev->getSndDeviceId()); currentDeviceNumber++; } config.noOfCurrentDevices = currentDeviceNumber; config.streamAttributes = sAttr; rm->callback_event(&config, PAL_NOTIFY_STOP, false); if (config.currentDevices) free(config.currentDevices); } exit: PAL_INFO(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } ssize_t pal_stream_write(pal_stream_handle_t *stream_handle, struct pal_buffer *buf) { Stream *s = NULL; int status; if (!stream_handle || !buf) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status); return status; } PAL_VERBOSE(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); s = reinterpret_cast(stream_handle); status = s->write(buf); if (status < 0) { PAL_ERR(LOG_TAG, "stream write failed status %d", status); return status; } PAL_VERBOSE(LOG_TAG, "Exit. status %d", status); return status; } ssize_t pal_stream_read(pal_stream_handle_t *stream_handle, struct pal_buffer *buf) { Stream *s = NULL; int status; if (!stream_handle || !buf) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status); return status; } PAL_VERBOSE(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); s = reinterpret_cast(stream_handle); status = s->read(buf); if (status < 0) { PAL_ERR(LOG_TAG, "stream read failed status %d", status); return status; } PAL_VERBOSE(LOG_TAG, "Exit. status %d", status); return status; } int32_t pal_stream_get_param(pal_stream_handle_t *stream_handle, uint32_t param_id, pal_param_payload **param_payload) { Stream *s = NULL; std::shared_ptr rm = NULL; int status; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_VERBOSE(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); #else PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); #endif kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->getParameters(param_id, (void **)param_payload); if (0 != status) { PAL_ERR(LOG_TAG, "get parameters failed status %d param_id %u", status, param_id); kpiEnqueue(__func__, false); return status; } #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_VERBOSE(LOG_TAG, "Exit. status %d", status); #else PAL_DBG(LOG_TAG, "Exit. status %d", status); #endif kpiEnqueue(__func__, false); return status; } int32_t pal_stream_set_param(pal_stream_handle_t *stream_handle, uint32_t param_id, pal_param_payload *param_payload) { Stream *s = NULL; int status; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle, status %d", status); return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK param_id %d", stream_handle, param_id); s = reinterpret_cast(stream_handle); if (PAL_PARAM_ID_UIEFFECT == param_id) { status = s->setEffectParameters((void *)param_payload); } else { status = s->setParameters(param_id, (void *)param_payload); } if (0 != status) { PAL_ERR(LOG_TAG, "set parameters failed status %d param_id %u", status, param_id); return status; } rm = ResourceManager::getInstance(); if (!rm) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } kpiEnqueue(__func__, true); if (param_id == PAL_PARAM_ID_STOP_BUFFERING) { PAL_DBG(LOG_TAG, "Buffering stopped, handle deferred LPI<->NLPI switch"); rm->handleDeferredSwitch(); #ifdef SEC_AUDIO_SOUND_TRIGGER_TYPE rm->notifyClientSoundTriggerResourceAvailable(); #endif } PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_set_volume(pal_stream_handle_t *stream_handle, struct pal_volume_data *volume) { Stream *s = NULL; int status; std::shared_ptr rm = NULL; rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; return status; } if (!stream_handle || !volume || volume->no_of_volpair > PAL_MAX_CHANNELS_SUPPORTED) { status = -EINVAL; PAL_ERR(LOG_TAG,"Invalid input parameters status %d", status); return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); rm->lockActiveStream(); if (!rm->isActiveStream(stream_handle)) { rm->unlockActiveStream(); status = -EINVAL; return status; } s = reinterpret_cast(stream_handle); status = rm->increaseStreamUserCounter(s); if (0 != status) { rm->unlockActiveStream(); PAL_ERR(LOG_TAG, "failed to increase stream user count"); return status; } rm->unlockActiveStream(); s->lockStreamMutex(); status = s->setVolume(volume); s->unlockStreamMutex(); rm->lockActiveStream(); rm->decreaseStreamUserCounter(s); rm->unlockActiveStream(); if (0 != status) { PAL_ERR(LOG_TAG, "setVolume failed with status %d", status); kpiEnqueue(__func__, false); return status; } PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_set_mute(pal_stream_handle_t *stream_handle, bool state) { Stream *s = NULL; std::shared_ptr rm = NULL; int status = 0; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); rm->lockActiveStream(); if (!rm->isActiveStream(stream_handle)) { rm->unlockActiveStream(); status = -EINVAL; goto exit; } s = reinterpret_cast(stream_handle); status = rm->increaseStreamUserCounter(s); if (0 != status) { rm->unlockActiveStream(); PAL_ERR(LOG_TAG, "failed to increase stream user count"); goto exit; } rm->unlockActiveStream(); status = s->mute(state); rm->lockActiveStream(); rm->decreaseStreamUserCounter(s); rm->unlockActiveStream(); if (0 != status) { PAL_ERR(LOG_TAG, "mute failed with status %d", status); goto exit; } exit: PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_pause(pal_stream_handle_t *stream_handle) { Stream *s = NULL; int status; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->pause(); if (0 != status) { PAL_ERR(LOG_TAG, "pal_stream_pause failed with status %d", status); kpiEnqueue(__func__, false); return status; } PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_resume(pal_stream_handle_t *stream_handle) { Stream *s = NULL; int status; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->resume(); if (0 != status) { PAL_ERR(LOG_TAG, "resume failed with status %d", status); kpiEnqueue(__func__, false); return status; } PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_drain(pal_stream_handle_t *stream_handle, pal_drain_type_t type) { Stream *s = NULL; int status; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; goto exit; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); rm->lockActiveStream(); if (!rm->isActiveStream(stream_handle)) { rm->unlockActiveStream(); status = -EINVAL; goto exit; } s = reinterpret_cast(stream_handle); status = rm->increaseStreamUserCounter(s); if (0 != status) { rm->unlockActiveStream(); PAL_ERR(LOG_TAG, "failed to increase stream user count"); goto exit; } rm->unlockActiveStream(); status = s->drain(type); rm->lockActiveStream(); rm->decreaseStreamUserCounter(s); rm->unlockActiveStream(); if (0 != status) { PAL_ERR(LOG_TAG, "drain failed with status %d", status); goto exit; } exit: PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_flush(pal_stream_handle_t *stream_handle) { Stream *s = NULL; int status; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->flush(); if (0 != status) { PAL_ERR(LOG_TAG, "flush failed with status %d", status); kpiEnqueue(__func__, false); return status; } PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_suspend(pal_stream_handle_t *stream_handle) { Stream *s = NULL; int status; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->suspend(); if (0 != status) { PAL_ERR(LOG_TAG, "suspend failed with status %d", status); } PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_set_buffer_size (pal_stream_handle_t *stream_handle, pal_buffer_config *in_buffer_cfg, pal_buffer_config *out_buffer_cfg) { Stream *s = NULL; int status; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->setBufInfo(in_buffer_cfg, out_buffer_cfg); if (0 != status) { PAL_ERR(LOG_TAG, "pal_stream_set_buffer_size failed with status %d", status); kpiEnqueue(__func__, false); return status; } PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_get_buffer_size(pal_stream_handle_t *stream_handle, size_t *in_buf_size, size_t *out_buf_size) { Stream *s = NULL; int status; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status); return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); s = reinterpret_cast(stream_handle); status = s->getBufSize(in_buf_size, out_buf_size); if (0 != status) { PAL_ERR(LOG_TAG, "pal_stream_get_buffer_size failed with status %d", status); return status; } PAL_DBG(LOG_TAG, "Exit. status %d", status); return status; } int32_t pal_get_timestamp(pal_stream_handle_t *stream_handle, struct pal_session_time *stime) { Stream *s = NULL; int status = -EINVAL; std::shared_ptr rm = NULL; if (!stream_handle) { PAL_ERR(LOG_TAG, "Invalid input parameters status %d\n", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK\n", stream_handle); kpiEnqueue(__func__, true); rm->lockActiveStream(); if (rm->isActiveStream(stream_handle)) { s = reinterpret_cast(stream_handle); status = s->getTimestamp(stime); } else { PAL_ERR(LOG_TAG, "stream handle in stale state.\n"); } rm->unlockActiveStream(); if (0 != status) { PAL_ERR(LOG_TAG, "pal_get_timestamp failed with status %d\n", status); kpiEnqueue(__func__, false); return status; } PAL_VERBOSE(LOG_TAG, "stime->session_time.value_lsw = %u, stime->session_time.value_msw = %u \n", stime->session_time.value_lsw, stime->session_time.value_msw); PAL_VERBOSE(LOG_TAG, "stime->absolute_time.value_lsw = %u, stime->absolute_time.value_msw = %u \n", stime->absolute_time.value_lsw, stime->absolute_time.value_msw); PAL_VERBOSE(LOG_TAG, "stime->timestamp.value_lsw = %u, stime->timestamp.value_msw = %u \n", stime->timestamp.value_lsw, stime->timestamp.value_msw); PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_add_remove_effect(pal_stream_handle_t *stream_handle, pal_audio_effect_t effect, bool enable) { Stream *s = NULL; int status = 0; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { PAL_ERR(LOG_TAG, "Invalid resource manager"); status = -EINVAL; return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->addRemoveEffect(effect, enable); if (0 != status) { PAL_ERR(LOG_TAG, "pal_add_effect failed with status %d", status); kpiEnqueue(__func__, false); return status; } PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_set_device(pal_stream_handle_t *stream_handle, uint32_t no_of_devices, struct pal_device *devices) { ATRACE_CALL(); int status = -EINVAL; Stream *s = NULL; std::shared_ptr rm = NULL; struct pal_stream_attributes sattr = {}; struct pal_device_info devinfo = {}; struct pal_device *pDevices = NULL; struct pal_device curPalDevAttr; pal_callback_config_t config = {}; std::vector > aDevices, palDevices; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } if (no_of_devices == 0 || !devices) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid device status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } PAL_INFO(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); rm->lockActiveStream(); if (!rm->isActiveStream(stream_handle)) { rm->unlockActiveStream(); status = -EINVAL; return status; } /* Choose best device config for this stream */ /* TODO: Decide whether to update device config or not based on flag */ s = reinterpret_cast(stream_handle); status = rm->increaseStreamUserCounter(s); if (0 != status) { rm->unlockActiveStream(); PAL_ERR(LOG_TAG, "failed to increase stream user count"); return status; } rm->unlockActiveStream(); s->getStreamAttributes(&sattr); // device switch will be handled in global param setting for SVA if (sattr.type == PAL_STREAM_VOICE_UI) { PAL_DBG(LOG_TAG, "Device switch handles in global param set, skip here"); goto exit; } if (sattr.type == PAL_STREAM_VOICE_CALL_RECORD || sattr.type == PAL_STREAM_VOICE_CALL_MUSIC) { PAL_DBG(LOG_TAG, "Device switch skipped for Incall record/music stream"); status = 0; goto exit; } s->lockStreamMutex(); s->getAssociatedDevices(aDevices); s->getPalDevices(palDevices); if (!aDevices.empty() && !palDevices.empty()) { std::set activeDevices, curPalDevices; std::set newDevices; bool force_switch = s->isA2dpMuted(); for (auto &dev : aDevices) activeDevices.insert((pal_device_id_t)dev->getSndDeviceId()); for (auto &dev : palDevices) { curPalDevices.insert((pal_device_id_t)dev->getSndDeviceId()); // check if custom key matches for same device for (int i = 0; i < no_of_devices; i++) { if (dev->getSndDeviceId() == devices[i].id) { dev->getDeviceAttributes(&curPalDevAttr, s); if (strcmp(devices[i].custom_config.custom_key, curPalDevAttr.custom_config.custom_key) != 0) { PAL_DBG(LOG_TAG, "diff custom key found, force device switch"); force_switch = true; break; } } } if (force_switch) break; } /* * When headset is disconnected the music playback pauses * and the policy manager sends routing=0. But if the headset is connected * back before the standby time, it can not switch device to headset any more * because current pal device is headset which equals new device when resuming playback. * So routing to default device first during handling routing = 0 msg will guarantee * the device switch to headset can be executed once headset is connected again. */ if (devices[0].id == PAL_DEVICE_NONE && (rm->isDisconnectedDeviceStillActive(curPalDevices,activeDevices, PAL_DEVICE_OUT_USB_DEVICE) || rm->isDisconnectedDeviceStillActive(curPalDevices,activeDevices, PAL_DEVICE_OUT_USB_HEADSET) || rm->isDisconnectedDeviceStillActive(curPalDevices,activeDevices, PAL_DEVICE_OUT_WIRED_HEADPHONE) || rm->isDisconnectedDeviceStillActive(curPalDevices,activeDevices, PAL_DEVICE_OUT_WIRED_HEADSET))) { devices[0].id = PAL_DEVICE_OUT_SPEAKER; } if (!force_switch) { for (int i = 0; i < no_of_devices; i++) { newDevices.insert(devices[i].id); #ifdef SEC_AUDIO_USB_GAIN_CONTROL if ((no_of_devices > 1) && (sattr.type == PAL_STREAM_GENERIC) && (devices[i].id == PAL_DEVICE_OUT_USB_HEADSET)) { PAL_DBG(LOG_TAG, "always switch device for usb combo device"); force_switch = true; break; } #endif if ((devices[i].id == PAL_DEVICE_OUT_BLUETOOTH_A2DP) || (devices[i].id == PAL_DEVICE_OUT_BLUETOOTH_SCO) || (devices[i].id == PAL_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) { PAL_DBG(LOG_TAG, "always switch device for bt device"); force_switch = true; break; } } } if (!force_switch && (activeDevices == newDevices) && (curPalDevices == newDevices)) { status = 0; PAL_DBG(LOG_TAG, "devices are same, no need to switch"); s->unlockStreamMutex(); goto exit; } } s->unlockStreamMutex(); pDevices = (struct pal_device *) calloc(no_of_devices, sizeof(struct pal_device)); if (!pDevices) { status = -ENOMEM; PAL_ERR(LOG_TAG, "Memory alloc failed"); goto exit; } ar_mem_cpy(pDevices, no_of_devices * sizeof(struct pal_device), devices, no_of_devices * sizeof(struct pal_device)); for (int i = 0; i < no_of_devices; i++) { if (strlen(pDevices[i].custom_config.custom_key)) { PAL_DBG(LOG_TAG, "Device has custom key %s", pDevices[i].custom_config.custom_key); } else { PAL_DBG(LOG_TAG, "Device has no custom key"); strlcpy(pDevices[i].custom_config.custom_key, "", PAL_MAX_CUSTOM_KEY_SIZE); } status = rm->getDeviceConfig((struct pal_device *)&pDevices[i], &sattr); if (status) { PAL_ERR(LOG_TAG, "Failed to get Device config, err: %d", status); goto exit; } } // TODO: Check with RM if the same device is being used by other stream with different // configuration then update corresponding stream device configuration also based on priority. PAL_DBG(LOG_TAG, "Stream handle :%pK no_of_devices %d first_device id %d", stream_handle, no_of_devices, pDevices[0].id); status = s->switchDevice(s, no_of_devices, pDevices); if (0 != status) { PAL_ERR(LOG_TAG, "failed with status %d", status); goto exit; } else { if (rm->callback_event != NULL) { config.streamAttributes = sattr; int32_t prevDeviceNumber = 0; config.prevDevices = (pal_device_id_t *) calloc(aDevices.size(), sizeof(pal_device_id_t)); if (!config.prevDevices) { PAL_ERR(LOG_TAG, "Memory alloc failed"); goto exit; } if(!aDevices.empty()){ for (auto &dev : aDevices) { config.prevDevices[prevDeviceNumber] = ((pal_device_id_t)dev->getSndDeviceId()); prevDeviceNumber++; } } config.noOfPrevDevices = prevDeviceNumber; config.currentDevices = (pal_device_id_t *) calloc(no_of_devices, sizeof(pal_device_id_t)); if (!config.currentDevices) { PAL_ERR(LOG_TAG, "Memory alloc failed"); if (config.prevDevices) free(config.prevDevices); goto exit; } for (int currentDeviceNumber = 0; currentDeviceNumber < no_of_devices; currentDeviceNumber++) { config.currentDevices[currentDeviceNumber] = devices[currentDeviceNumber].id; } config.noOfCurrentDevices = no_of_devices; rm->callback_event(&config, PAL_NOTIFY_DEVICESWITCH, false); if (config.prevDevices) free(config.prevDevices); if (config.currentDevices) free(config.currentDevices); } } exit: rm->lockActiveStream(); rm->decreaseStreamUserCounter(s); rm->unlockActiveStream(); if (pDevices) free(pDevices); PAL_INFO(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_stream_get_tags_with_module_info(pal_stream_handle_t *stream_handle, size_t *size, uint8_t *payload) { int status = 0; Stream *s = NULL; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid stream handle status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->getTagsWithModuleInfo(size, payload); PAL_DBG(LOG_TAG, "Exit. Stream handle: %pK, status %d", stream_handle, status); kpiEnqueue(__func__, false); return status; } int32_t pal_set_param(uint32_t param_id, void *param_payload, size_t payload_size) { PAL_INFO(LOG_TAG, "Enter: param id %d", param_id); //SEC_AUDIO_ADD_FOR_DEBUG : PAL_DBG -> PAL_INFO int status = 0; std::shared_ptr rm = NULL; rm = ResourceManager::getInstance(); if (rm) { kpiEnqueue(__func__, true); status = rm->setParameter(param_id, param_payload, payload_size); if (0 != status) { #if defined (SEC_AUDIO_ADD_FOR_DEBUG) && defined (SEC_AUDIO_AMP_SDHMS) if (param_id != PAL_PARAM_ID_SPEAKER_AMP_TEMPERATURE_RCV && param_id != PAL_PARAM_ID_SPEAKER_AMP_TEMPERATURE_SPK) #endif PAL_ERR(LOG_TAG, "Failed to set global parameter %u, status %d", param_id, status); } kpiEnqueue(__func__, false); } else { PAL_ERR(LOG_TAG, "Pal has not been initialized yet"); status = -EINVAL; } PAL_DBG(LOG_TAG, "Exit, status %d", status); return status; } int32_t pal_get_param(uint32_t param_id, void **param_payload, size_t *payload_size, void *query) { int status = 0; std::shared_ptr rm = NULL; rm = ResourceManager::getInstance(); #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_VERBOSE(LOG_TAG, "Enter:"); #else PAL_DBG(LOG_TAG, "Enter:"); #endif if (rm) { kpiEnqueue(__func__, true); status = rm->getParameter(param_id, param_payload, payload_size, query); if (0 != status) { #if defined (SEC_AUDIO_ADD_FOR_DEBUG) && defined (SEC_AUDIO_AMP_SDHMS) if (param_id != PAL_PARAM_ID_SPEAKER_AMP_TEMPERATURE_RCV && param_id != PAL_PARAM_ID_SPEAKER_AMP_TEMPERATURE_SPK) #endif PAL_ERR(LOG_TAG, "Failed to get global parameter %u, status %d", param_id, status); } kpiEnqueue(__func__, false); } else { PAL_ERR(LOG_TAG, "Pal has not been initialized yet"); status = -EINVAL; } #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_VERBOSE(LOG_TAG, "Exit, status %d", status); #else PAL_DBG(LOG_TAG, "Exit, status %d", status); #endif return status; } int32_t pal_stream_get_mmap_position(pal_stream_handle_t *stream_handle, struct pal_mmap_position *position) { Stream *s = NULL; int status; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_VERBOSE(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); #else PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); #endif kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->GetMmapPosition(position); if (0 != status) { PAL_ERR(LOG_TAG, "pal_stream_get_mmap_position failed with status %d", status); return status; } #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_VERBOSE(LOG_TAG, "Exit. status %d", status); #else PAL_DBG(LOG_TAG, "Exit. status %d", status); #endif kpiEnqueue(__func__, false); return status; } int32_t pal_stream_create_mmap_buffer(pal_stream_handle_t *stream_handle, int32_t min_size_frames, struct pal_mmap_buffer *info) { ATRACE_CALL(); Stream *s = NULL; int status; std::shared_ptr rm = NULL; if (!stream_handle) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status); return status; } rm = ResourceManager::getInstance(); if (!rm) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); kpiEnqueue(__func__, true); s = reinterpret_cast(stream_handle); status = s->createMmapBuffer(min_size_frames, info); if (0 != status) { PAL_ERR(LOG_TAG, "pal_stream_create_mmap_buffer failed with status %d", status); return status; } PAL_DBG(LOG_TAG, "Exit. status %d", status); kpiEnqueue(__func__, false); return status; } int32_t pal_register_global_callback(pal_global_callback cb, uint64_t cookie) { int status = 0; std::shared_ptr rm = NULL; PAL_DBG(LOG_TAG, "Enter. global callback %pK", cb); rm = ResourceManager::getInstance(); if (!rm) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } kpiEnqueue(__func__, true); if (cb != NULL) { rm->globalCb = cb; rm->cookie = cookie; } PAL_DBG(LOG_TAG, "Exit"); kpiEnqueue(__func__, false); return status; } int32_t pal_gef_rw_param(uint32_t param_id, void *param_payload, size_t payload_size, pal_device_id_t pal_device_id, pal_stream_type_t pal_stream_type, unsigned int dir) { int status = 0; std::shared_ptr rm = NULL; rm = ResourceManager::getInstance(); if (!rm) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid resource manager"); return status; } #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_VERBOSE(LOG_TAG, "Enter."); #else PAL_DBG(LOG_TAG, "Enter."); #endif if (rm) { kpiEnqueue(__func__, true); if (GEF_PARAM_WRITE == dir) { status = rm->setParameter(param_id, param_payload, payload_size, pal_device_id, pal_stream_type); if (0 != status) { #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_INFO(LOG_TAG, "set global parameter %u, status %d", param_id, status); #else PAL_ERR(LOG_TAG, "Failed to set global parameter %u, status %d", param_id, status); #endif } } else { status = rm->getParameter(param_id, param_payload, payload_size, pal_device_id, pal_stream_type); if (0 != status) { #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_INFO(LOG_TAG, "set global parameter %u, status %d", param_id, status); #else PAL_ERR(LOG_TAG, "Failed to set global parameter %u, status %d", param_id, status); #endif } } kpiEnqueue(__func__, false); } else { PAL_ERR(LOG_TAG, "Pal has not been initialized yet"); status = -EINVAL; } #ifdef SEC_AUDIO_ADD_FOR_DEBUG PAL_VERBOSE(LOG_TAG, "Exit:"); #else PAL_DBG(LOG_TAG, "Exit:"); #endif return status; } int32_t pal_gef_rw_param_acdb(uint32_t param_id __unused, void *param_payload, size_t payload_size __unused, pal_device_id_t pal_device_id, pal_stream_type_t pal_stream_type, uint32_t sample_rate, uint32_t instance_id, uint32_t dir, bool is_play ) { int status = 0; std::shared_ptr rm = NULL; rm = ResourceManager::getInstance(); PAL_DBG(LOG_TAG, "Enter."); if (rm) { kpiEnqueue(__func__, true); status = rm->rwParameterACDB(param_id, param_payload, payload_size, pal_device_id, pal_stream_type, sample_rate, instance_id, dir, is_play); if (0 != status) { PAL_ERR(LOG_TAG, "Failed to rw global parameter %u, status %d", param_id, status); } kpiEnqueue(__func__, false); } else { PAL_ERR(LOG_TAG, "Pal has not been initialized yet"); status = -EINVAL; } PAL_DBG(LOG_TAG, "Exit, status %d", status); return status; } int32_t pal_stream_get_device(pal_stream_handle_t *stream_handle, uint32_t no_of_devices, struct pal_device *devices){ std::vector> associatedDevices; std::vector palDevices; int status; int device_count = 0; Stream *s = NULL; if (!stream_handle || !devices) { status = -EINVAL; PAL_ERR(LOG_TAG, "Invalid input parameters status %d", status); return status; } PAL_DBG(LOG_TAG, "Enter. Stream handle :%pK", stream_handle); s = reinterpret_cast(stream_handle); status = s->getAssociatedDevices(associatedDevices); if (0 != status) { PAL_ERR(LOG_TAG,"getAssociatedDevices Failed\n"); return status; } device_count = associatedDevices.size(); if (no_of_devices < device_count) { status = -EINVAL; PAL_ERR(LOG_TAG, "Not enough memory allocated for %d devices", device_count); return status; } palDevices.resize(device_count); for (int i = 0; i < device_count; i++) { associatedDevices[i]->getDeviceAttributes(&palDevices[i]); } ar_mem_cpy(devices, sizeof(struct pal_device) * device_count, &palDevices[0], sizeof(struct pal_device) * device_count); /* Return the number of devices assosicated with the stream */ status = device_count; PAL_DBG(LOG_TAG, "Exit. status %d", status); return status; } int32_t pal_stream_get_volume(pal_stream_handle_t *stream_handle, struct pal_volume_data *volume){ PAL_ERR(LOG_TAG, "error: API: pal_stream_get_volume not implemented"); return -ENOSYS; } int32_t pal_stream_get_mute(pal_stream_handle_t *stream_handle, bool *state){ PAL_ERR(LOG_TAG, "error: API: pal_stream_get_mute not implemented"); return -ENOSYS; } int32_t pal_get_mic_mute(bool *state){ PAL_ERR(LOG_TAG, "error: API: pal_get_mic_mute not implemented"); return -ENOSYS; } int32_t pal_set_mic_mute(bool state){ PAL_ERR(LOG_TAG, "error: API: pal_set_mic_mute not implemented"); return -ENOSYS; } #ifdef SEC_AUDIO_COMMON int pal_active_device_count(pal_device_id_t deviceId) { int32_t device_count = 0; std::shared_ptr rm = NULL; rm = ResourceManager::getInstance(); std::shared_ptr dev = nullptr; struct pal_device devAttr = {}; devAttr.id = deviceId; dev = Device::getInstance(&devAttr, rm); if (!dev) { PAL_DBG(LOG_TAG, "device(%) is not available", deviceId); goto exit; } if (rm) { bool active = rm->isDeviceActive(devAttr.id); if (active) { device_count = dev->getDeviceCount(); } } exit: PAL_DBG(LOG_TAG, "%s count is %d", deviceNameLUT.at(deviceId).c_str(), device_count); return device_count; } void pal_dump(int fd) { std::shared_ptr rm = NULL; rm = ResourceManager::getInstance(); #ifdef SEC_AUDIO_ADD_FOR_DEBUG std::shared_ptr dev = nullptr; struct pal_device devAttr = {}; #endif dprintf(fd, " \n"); dprintf(fd, "pal : \n"); if (rm) { rm->dump(fd); } #ifdef SEC_AUDIO_ADD_FOR_DEBUG devAttr.id = PAL_DEVICE_OUT_USB_HEADSET; dev = Device::getInstance(&devAttr, rm); if (dev) { dev->dump(fd); } #if defined (ENABLE_TFA98XX_SUPPORT) || defined (ENABLE_TAS_SPK_PROT) devAttr.id = PAL_DEVICE_OUT_SPEAKER; dev = Device::getInstance(&devAttr, rm); if (dev) { dev->dump(fd); } #endif #endif } #endif