replace common qcom sources with samsung ones

This commit is contained in:
SaschaNes
2025-08-12 22:13:00 +02:00
parent ba24dcded9
commit 6f7753de11
5682 changed files with 2450203 additions and 103634 deletions

View File

@@ -0,0 +1,420 @@
/*
* 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
*/
#ifndef STREAM_H_
#define STREAM_H_
#include "PalDefs.h"
#include <algorithm>
#include <vector>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <memory>
#include <mutex>
#include <exception>
#include <semaphore.h>
#include <errno.h>
#ifdef LINUX_ENABLED
#include <condition_variable>
#endif
#include "PalCommon.h"
typedef enum {
DATA_MODE_SHMEM = 0,
DATA_MODE_BLOCKING ,
DATA_MODE_NONBLOCKING
} dataFlags;
typedef enum {
STREAM_IDLE = 0,
STREAM_INIT,
STREAM_OPENED,
STREAM_STARTED,
STREAM_PAUSED,
STREAM_SUSPENDED,
STREAM_STOPPED
} stream_state_t;
#define BUF_SIZE_PLAYBACK 1024
#define BUF_SIZE_CAPTURE 960
#define AUDIO_CAPTURE_PERIOD_DURATION_MSEC 20
#define DEEP_BUFFER_OUTPUT_PERIOD_DURATION 40
#define PCM_OFFLOAD_OUTPUT_PERIOD_DURATION 80
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
#define NO_OF_BUF 4
#define MUTE_TAG 0
#define UNMUTE_TAG 1
#define PAUSE_TAG 2
#define RESUME_TAG 3
#define MFC_SR_8K 4
#define MFC_SR_16K 5
#define MFC_SR_32K 6
#define MFC_SR_44K 7
#define MFC_SR_48K 8
#define MFC_SR_96K 9
#define MFC_SR_192K 10
#define MFC_SR_384K 11
#define ECNS_ON_TAG 12
#define ECNS_OFF_TAG 13
#define EC_ON_TAG 14
#define NS_ON_TAG 15
#define CHS_1 16
#define CHS_2 17
#define CHS_3 18
#define CHS_4 19
#define CHS_5 20
#define CHS_6 21
#define CHS_7 22
#define CHS_8 23
#define BW_16 24
#define BW_24 25
#define BW_32 26
#define TTY_MODE 27
#define VOICE_SLOW_TALK_OFF 28
#define VOICE_SLOW_TALK_ON 29
#define VOICE_VOLUME_BOOST 30
#define SPKR_PROT_ENABLE 31
#define INCALL_RECORD_UPLINK 32
#define INCALL_RECORD_DOWNLINK 33
#define INCALL_RECORD_UPLINK_DOWNLINK_MONO 34
#define INCALL_RECORD_UPLINK_DOWNLINK_STEREO 35
#define SPKR_VI_ENABLE 36
#define VOICE_HD_VOICE 37
#define LPI_LOGGING_ON 38
#define LPI_LOGGING_OFF 39
#define DEVICE_MUTE 40
#define DEVICE_UNMUTE 41
#define CHANNEL_INFO 42
#define CHARGE_CONCURRENCY_ON_TAG 43
#define CHARGE_CONCURRENCY_OFF_TAG 44
#define DEVICEPP_MUTE 45
#define DEVICEPP_UNMUTE 46
#define ORIENTATION_TAG 47
#define HANDSET_PROT_ENABLE 48
#define HAPTICS_VI_ENABLE 49
#define HAPTICS_PROT_ENABLE 50
#define CRS_CALL_VOLUME 51
#ifdef SEC_AUDIO_BARGEIN_MODE
#define BARGEIN_MODE_TAG 52
#endif
#ifdef SEC_AUDIO_INTERPRETER_MODE
#define INTERPRETER_MODE_TAG 53
#endif
#ifdef SEC_AUDIO_CALL_ASR_PERFORMANCE
#define INCALL_RECORD_UPLINK_DOWNLINK_QUADRO 54
#endif
#ifdef SEC_AUDIO_CALL_VOIP
#define VOICE_MIC_MODE 100
#endif
#define INVALID_TAG -1
/* This sleep is added to give time to kernel and
* spf to recover from SSR so that audio-hal will
* not continously try to open a session if it fails
* during SSR.
*/
#define SSR_RECOVERY 10000
/* Soft pause has to wait for ramp period to ensure volume stepping finishes.
* This period of time was previously consumed in elite before acknowleging
* pause completion. But it's not the case in Gecko.
* FIXME: load the ramp period config from acdb.
*/
#define VOLUME_RAMP_PERIOD (200*1000)
/*
* The sleep is required for mute to ramp down.
*/
#define MUTE_RAMP_PERIOD (40*1000)
#define DEFAULT_RAMP_PERIOD 0x28 //40ms
class Device;
class ResourceManager;
class Session;
class Stream
{
protected:
uint32_t mNoOfDevices;
std::vector <std::shared_ptr<Device>> mDevices; // current running devices
std::vector <std::shared_ptr<Device>> mPalDevices; // pal devices set from client, which may differ from mDevices
Session* session;
struct pal_stream_attributes* mStreamAttr;
bool deviceMuteStateRx = false;
bool deviceMuteStateTx = false;
int mGainLevel;
int mOrientation = 0;
std::mutex mStreamMutex;
static std::mutex mBaseStreamMutex; //TBD change this. as having a single static mutex for all instances of Stream is incorrect. Replace
static std::shared_ptr<ResourceManager> rm;
struct modifier_kv *mModifiers;
uint32_t mNoOfModifiers;
std::string mStreamSelector;
std::string mDevPPSelector;
size_t inBufSize = BUF_SIZE_CAPTURE;
size_t outBufSize = BUF_SIZE_PLAYBACK;
size_t inBufCount = NO_OF_BUF;
size_t outBufCount = NO_OF_BUF;
size_t outMaxMetadataSz;
size_t inMaxMetadataSz;
stream_state_t currentState;
stream_state_t cachedState;
uint32_t mInstanceID = 0;
static std::condition_variable pauseCV;
static std::mutex pauseMutex;
bool mutexLockedbyRm = false;
bool mDutyCycleEnable = false;
bool skipSSRHandling = false;
sem_t mInUse;
int connectToDefaultDevice(Stream* streamHandle, uint32_t dir);
#ifdef SEC_AUDIO_BARGEIN_MODE
int mBargeinMode = 0;
#endif
#ifdef SEC_AUDIO_INTERPRETER_MODE
int mInterpreterMode = 0;
#endif
#ifdef SEC_AUDIO_SOUND_TRIGGER_TYPE
bool mIsHotwordRecord = false;
#endif
public:
virtual ~Stream() {};
struct pal_volume_data* mVolumeData = NULL;
#ifdef SEC_AUDIO_CALL_VOIP
struct pal_param_voip_mic_mode* mMicMode = NULL;
#endif
pal_stream_callback streamCb;
uint64_t cookie;
bool isPaused = false;
bool a2dpMuted = false;
bool unMutePending = false;
bool a2dpPaused = false;
bool force_nlpi_vote = false;
bool isMMap = false;
std::vector<pal_device_id_t> suspendedOutDevIds;
std::vector<pal_device_id_t> suspendedInDevIds;
virtual int32_t open() = 0;
virtual int32_t close() = 0;
virtual int32_t start() = 0;
virtual int32_t stop() = 0;
virtual int32_t prepare() = 0;
virtual int32_t drain(pal_drain_type_t type __unused) {return 0;}
virtual int32_t setStreamAttributes(struct pal_stream_attributes *sattr) = 0;
virtual int32_t setVolume(struct pal_volume_data *volume) = 0;
virtual int32_t mute(bool state) = 0;
virtual int32_t mute_l(bool state) = 0;
virtual int32_t getDeviceMute(pal_stream_direction_t dir, bool *state) {return 0;};
virtual int32_t setDeviceMute(pal_stream_direction_t dir, bool state) {return 0;};
virtual int32_t pause() = 0;
virtual int32_t pause_l() = 0;
virtual int32_t resume() = 0;
virtual int32_t resume_l() = 0;
virtual int32_t flush() {return 0;}
virtual int32_t suspend() {return 0;}
virtual int32_t read(struct pal_buffer *buf) = 0;
virtual int32_t addRemoveEffect(pal_audio_effect_t effect, bool enable) = 0; //TBD: make this non virtual and prrovide implementation as StreamPCM and StreamCompressed are doing the same things
virtual int32_t setParameters(uint32_t param_id, void *payload) = 0;
virtual int32_t write(struct pal_buffer *buf) = 0; //TBD: make this non virtual and prrovide implementation as StreamPCM and StreamCompressed are doing the same things
virtual int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) = 0;
virtual int32_t getCallBack(pal_stream_callback *cb) = 0;
virtual int32_t getParameters(uint32_t param_id, void **payload) = 0;
virtual int32_t setECRef(std::shared_ptr<Device> dev, bool is_enable) = 0;
virtual int32_t setECRef_l(std::shared_ptr<Device> dev, bool is_enable) = 0;
virtual int32_t ssrDownHandler() = 0;
virtual int32_t ssrUpHandler() = 0;
virtual int32_t createMmapBuffer(int32_t min_size_frames __unused,
struct pal_mmap_buffer *info __unused) {return -EINVAL;}
virtual int32_t GetMmapPosition(struct pal_mmap_position *position __unused) {return -EINVAL;}
virtual int32_t getTagsWithModuleInfo(size_t *size __unused, uint8_t *payload __unused) {return -EINVAL;};
virtual uint32_t GetNumEvents() { return 0; }
virtual uint32_t GetOutputToken() { return 0; }
virtual uint32_t GetPayloadSize() { return 0; }
virtual bool ConfigSupportLPI() {return true;}; //Only LPI streams can update their vote to NLPI
int32_t getStreamAttributes(struct pal_stream_attributes *sattr);
int32_t getModifiers(struct modifier_kv *modifiers,uint32_t *noOfModifiers);
const std::string& getStreamSelector() const;
const std::string& getDevicePPSelector() const;
int32_t getStreamType(pal_stream_type_t* streamType);
int32_t getStreamDirection(pal_stream_direction_t *dir);
uint32_t getRenderLatency();
uint32_t getLatency();
int32_t getAssociatedDevices(std::vector <std::shared_ptr<Device>> &adevices);
int32_t getAssociatedOutDevices(std::vector <std::shared_ptr<Device>> &adevices);
int32_t getAssociatedInDevices(std::vector <std::shared_ptr<Device>> &adevices);
int32_t getPalDevices(std::vector <std::shared_ptr<Device>> &PalDevices);
void removePalDevice(Stream *streamHandle, int palDevId);
void clearOutPalDevices(Stream *streamHandle);
void addPalDevice(Stream* streamHandle, struct pal_device *dattr);
int32_t getSoundCardId();
int32_t getAssociatedSession(Session** session);
int32_t setBufInfo(pal_buffer_config *in_buffer_config,
pal_buffer_config *out_buffer_config);
int32_t getBufInfo(size_t *in_buf_size, size_t *in_buf_count,
size_t *out_buf_size, size_t *out_buf_count);
int32_t getMaxMetadataSz(size_t *in_max_metadata_sz, size_t *out_max_metadata_sz);
int32_t getBufSize(size_t *in_buf_size, size_t *out_buf_size);
int32_t getVolumeData(struct pal_volume_data *vData);
void setGainLevel(int level) { mGainLevel = level; };
int getGainLevel() { return mGainLevel; };
void setDutyCycleEnable(bool enable) { mDutyCycleEnable = enable; };
bool getDutyCycleEnable() { return mDutyCycleEnable; };
void setOrientation(int orientation) { mOrientation = orientation; };
int getOrientation() { return mOrientation; };
/* static so that this method can be accessed wihtout object */
static Stream* create(struct pal_stream_attributes *sattr, struct pal_device *dattr,
uint32_t no_of_devices, struct modifier_kv *modifiers, uint32_t no_of_modifiers);
bool isStreamAudioOutFmtSupported(pal_audio_fmt_t format);
int32_t getTimestamp(struct pal_session_time *stime);
int32_t handleBTDeviceNotReadyToDummy(bool& a2dpSuspend);
int32_t handleBTDeviceNotReady(bool& a2dpSuspend);
int disconnectStreamDevice(Stream* streamHandle, pal_device_id_t dev_id);
virtual int disconnectStreamDevice_l(Stream* streamHandle, pal_device_id_t dev_id);
int connectStreamDevice(Stream* streamHandle, struct pal_device *dattr);
virtual int connectStreamDevice_l(Stream* streamHandle, struct pal_device *dattr);
int switchDevice(Stream* streamHandle, uint32_t no_of_devices, struct pal_device *deviceArray);
bool isGKVMatch(pal_key_vector_t* gkv);
int32_t getEffectParameters(void *effect_query, size_t *payload_size);
uint32_t getInstanceId() { return mInstanceID; }
inline void setInstanceId(uint32_t sid) { mInstanceID = sid; }
int initStreamSmph();
int deinitStreamSmph();
int postStreamSmph();
int waitStreamSmph();
bool checkStreamMatch(pal_device_id_t pal_device_id,
pal_stream_type_t pal_stream_type);
bool isStreamSSRDownFeasibile();
#ifdef SEC_AUDIO_COMMON
bool checkStreamEffectMatch(pal_device_id_t pal_device_id,
pal_stream_type_t pal_stream_type,
uint32_t param_id);
#endif
int32_t getEffectParameters(void *effect_query);
int32_t setEffectParameters(void *effect_param);
int32_t rwACDBParameters(void *payload, uint32_t sampleRate,
bool isParamWrite);
stream_state_t getCurState() { return currentState; }
bool isActive() { return currentState == STREAM_STARTED; }
bool isAlive() { return currentState != STREAM_IDLE; }
bool isA2dpMuted() { return a2dpMuted; }
/* Detection stream related APIs */
virtual int32_t Resume(bool is_internal = false) { return 0; }
virtual int32_t Pause(bool is_internal = false) { return 0; }
virtual int32_t HandleConcurrentStream(bool active) { return 0; }
virtual int32_t DisconnectDevice(pal_device_id_t device_id) { return 0; }
virtual int32_t ConnectDevice(pal_device_id_t device_id) { return 0; }
virtual uint32_t getCallbackEventId() { return 0; }
static void handleSoftPauseCallBack(uint64_t hdl, uint32_t event_id, void *data,
uint32_t event_size);
static void handleStreamException(struct pal_stream_attributes *attributes,
pal_stream_callback cb, uint64_t cookie);
void lockStreamMutex() {
mStreamMutex.lock();
mutexLockedbyRm = true;
};
void unlockStreamMutex() {
mutexLockedbyRm = false;
mStreamMutex.unlock();
};
bool isMutexLockedbyRm() { return mutexLockedbyRm; }
/* GetPalDevice only applies to Sound Trigger streams */
std::shared_ptr<Device> GetPalDevice(Stream *streamHandle, pal_device_id_t dev_id);
void setCachedState(stream_state_t state);
void clearmDevices();
void removemDevice(int palDevId);
void addmDevice(struct pal_device *dattr);
#ifdef SEC_AUDIO_BARGEIN_MODE
void setBargeinMode(int bargein_mode) { mBargeinMode = bargein_mode; };
int getBargeinMode() { return mBargeinMode; }
#endif
#ifdef SEC_AUDIO_CALL_VOIP
void setMicMode(struct pal_param_voip_mic_mode *mode) { mMicMode = mode; };
int32_t getMicMode(struct pal_param_voip_mic_mode *vData);
#endif
#ifdef SEC_AUDIO_INTERPRETER_MODE
void setInterpreterMode(int interpreter_mode) { mInterpreterMode = interpreter_mode; };
int getInterpreterMode() { return mInterpreterMode; }
#endif
#ifdef SEC_AUDIO_SOUND_TRIGGER_TYPE
bool isHotwordRecord() { return mIsHotwordRecord; }
#endif
};
class StreamNonTunnel : public Stream
{
public:
StreamNonTunnel(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
const uint32_t no_of_devices,
const struct modifier_kv *modifiers, const uint32_t no_of_modifiers,
const std::shared_ptr<ResourceManager> rm);
virtual ~StreamNonTunnel();
int32_t open() override;
int32_t close() override;
int32_t start() override;
int32_t stop() override;
int32_t prepare() override;
int32_t setStreamAttributes( struct pal_stream_attributes *sattr __unused) {return 0;};
int32_t setVolume( struct pal_volume_data *volume __unused) {return 0;};
int32_t mute(bool state __unused) {return 0;};
int32_t mute_l(bool state __unused) {return 0;};
int32_t pause() {return 0;};
int32_t pause_l() {return 0;};
int32_t resume() {return 0;};
int32_t resume_l() {return 0;};
int32_t drain(pal_drain_type_t type) override;
int32_t flush();
int32_t suspend() override;
int32_t getTagsWithModuleInfo(size_t *size , uint8_t *payload) override;
int32_t setBufInfo(size_t *in_buf_size, size_t in_buf_count,
size_t *out_buf_size, size_t out_buf_count);
int32_t addRemoveEffect(pal_audio_effect_t effect __unused, bool enable __unused) {return 0;};
int32_t read(struct pal_buffer *buf) override;
int32_t write(struct pal_buffer *buf) override;
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
int32_t getCallBack(pal_stream_callback *cb) override;
int32_t getParameters(uint32_t param_id, void **payload) override;
int32_t setParameters(uint32_t param_id, void *payload) override;
static int32_t isSampleRateSupported(uint32_t sampleRate);
static int32_t isChannelSupported(uint32_t numChannels);
static int32_t isBitWidthSupported(uint32_t bitWidth);
int32_t setECRef(std::shared_ptr<Device> dev __unused, bool is_enable __unused) {return 0;};
int32_t setECRef_l(std::shared_ptr<Device> dev __unused, bool is_enable __unused) {return 0;};
int32_t ssrDownHandler() override;
int32_t ssrUpHandler() override;
private:
/*This notifies that the system went through/is in a ssr*/
bool ssrInNTMode;
};
#endif//STREAM_H_

View File

@@ -0,0 +1,475 @@
/*
* 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 are provided under the following license:
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef STREAMACD_H_
#define STREAMACD_H_
#include <utility>
#include <map>
#include "Stream.h"
#include "ACDPlatformInfo.h"
#include "SoundTriggerUtils.h"
#include "ContextDetectionEngine.h"
class ContextDetectionEngine;
typedef enum {
ACD_STATE_NONE,
ACD_STATE_SSR,
ACD_STATE_IDLE,
ACD_STATE_LOADED,
ACD_STATE_ACTIVE,
ACD_STATE_DETECTED,
} acd_state_id_t;
static const std::map<int32_t, std::string> acdStateNameMap
{
{ACD_STATE_NONE, std::string{"ACD_STATE_NONE"}},
{ACD_STATE_SSR, std::string{"ACD_STATE_SSR"}},
{ACD_STATE_IDLE, std::string{"ACD_STATE_IDLE"}},
{ACD_STATE_LOADED, std::string{"ACD_STATE_LOADED"}},
{ACD_STATE_ACTIVE, std::string{"ACD_STATE_ACTIVE"}},
{ACD_STATE_DETECTED, std::string{"ACD_STATE_DETECTED"}}
};
enum {
ACD_EV_LOAD_SOUND_MODEL,
ACD_EV_UNLOAD_SOUND_MODEL,
ACD_EV_RECOGNITION_CONFIG,
ACD_EV_CONTEXT_CONFIG,
ACD_EV_START_RECOGNITION,
ACD_EV_STOP_RECOGNITION,
ACD_EV_DETECTED,
ACD_EV_PAUSE,
ACD_EV_RESUME,
ACD_EV_DEVICE_CONNECTED,
ACD_EV_DEVICE_DISCONNECTED,
ACD_EV_SSR_OFFLINE,
ACD_EV_SSR_ONLINE,
ACD_EV_CONCURRENT_STREAM,
ACD_EV_EC_REF,
};
class ResourceManager;
class StreamACD : public Stream {
public:
StreamACD(struct pal_stream_attributes *sattr,
struct pal_device *dattr,
uint32_t no_of_devices,
struct modifier_kv *modifiers __unused,
uint32_t no_of_modifiers __unused,
std::shared_ptr<ResourceManager> rm);
~StreamACD();
int32_t open() { palStateEnqueue(this, PAL_STATE_OPENED, 0); return 0; }
int32_t close() override;
int32_t prepare() override { return 0; }
int32_t start() override;
int32_t stop() override;
int32_t getTagsWithModuleInfo(size_t *size, uint8_t *payload) override;
int32_t setStreamAttributes(struct pal_stream_attributes *sattr __unused) {
return 0;
}
int32_t setVolume(struct pal_volume_data * volume __unused) { return 0; }
int32_t mute(bool state __unused) override { return 0; }
int32_t mute_l(bool state __unused) override { return 0; }
int32_t pause() override { return 0; }
int32_t pause_l() override { return 0; }
int32_t resume() override { return 0; }
int32_t resume_l() override { return 0; }
int32_t read(struct pal_buffer *buf __unused) {return 0; }
int32_t write(struct pal_buffer *buf __unused) { return 0; }
int32_t DisconnectDevice(pal_device_id_t device_id) override;
int32_t ConnectDevice(pal_device_id_t device_id) override;
int32_t setECRef(std::shared_ptr<Device> dev, bool is_enable);
int32_t setECRef_l(std::shared_ptr<Device> dev, bool is_enable);
int32_t ssrDownHandler();
int32_t ssrUpHandler();
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
int32_t getCallBack(pal_stream_callback *cb) override;
int32_t getParameters(uint32_t param_id, void **payload) override;
int32_t setParameters(uint32_t param_id, void *payload) override;
int32_t addRemoveEffect(pal_audio_effect_t effec __unused,
bool enable __unused) {
return -ENOSYS;
}
int32_t Resume(bool is_internal __unused) override;
int32_t Pause(bool is_internal __unused) override;
int32_t HandleConcurrentStream(bool active) override;
pal_device_id_t GetAvailCaptureDevice();
std::shared_ptr<CaptureProfile> GetCurrentCaptureProfile();
void CacheEventData(struct acd_context_event *event);
void SendCachedEventData();
void PopulateCallbackPayload(struct acd_context_event *event, void *payload);
int32_t GetCurrentStateId();
void TransitTo(int32_t state_id);
void GetUUID(class SoundTriggerUUID *uuid,
const struct st_uuid *vendor_uuid);
void SetEngineDetectionData(struct acd_context_event *event);
struct acd_recognition_cfg *GetRecognitionConfig();
struct st_uuid GetVendorUuid();
private:
class ACDEventConfigData {
public:
ACDEventConfigData() {}
virtual ~ACDEventConfigData() {}
};
class ACDEventConfig {
public:
explicit ACDEventConfig(int32_t ev_id)
: id_(ev_id), data_(nullptr) {}
virtual ~ACDEventConfig() {}
int32_t id_; // event id
std::shared_ptr<ACDEventConfigData> data_; // event specific data
};
class ACDLoadEventConfigData : public ACDEventConfigData {
public:
ACDLoadEventConfigData(void *data): data_(data) {}
~ACDLoadEventConfigData() {}
void *data_;
};
class ACDLoadEventConfig : public ACDEventConfig {
public:
ACDLoadEventConfig(void *data)
: ACDEventConfig(ACD_EV_LOAD_SOUND_MODEL) {
data_ = std::make_shared<ACDLoadEventConfigData>(data);
}
~ACDLoadEventConfig() {}
};
class ACDUnloadEventConfig : public ACDEventConfig {
public:
ACDUnloadEventConfig() : ACDEventConfig(ACD_EV_UNLOAD_SOUND_MODEL) {}
~ACDUnloadEventConfig() {}
};
class ACDRecognitionCfgEventConfigData : public ACDEventConfigData {
public:
ACDRecognitionCfgEventConfigData(void *data): data_(data) {}
~ACDRecognitionCfgEventConfigData() {}
void *data_;
};
class ACDRecognitionCfgEventConfig : public ACDEventConfig {
public:
ACDRecognitionCfgEventConfig(void *data)
: ACDEventConfig(ACD_EV_RECOGNITION_CONFIG) {
data_ = std::make_shared<ACDRecognitionCfgEventConfigData>(data);
}
~ACDRecognitionCfgEventConfig() {}
};
class ACDContextCfgEventConfigData : public ACDEventConfigData {
public:
ACDContextCfgEventConfigData(void *data): data_(data) {}
~ACDContextCfgEventConfigData() {}
void *data_;
};
class ACDContextCfgEventConfig : public ACDEventConfig {
public:
ACDContextCfgEventConfig(void *data)
: ACDEventConfig(ACD_EV_CONTEXT_CONFIG) {
data_ = std::make_shared<ACDContextCfgEventConfigData>(data);
}
~ACDContextCfgEventConfig() {}
};
class ACDStartRecognitionEventConfigData : public ACDEventConfigData {
public:
ACDStartRecognitionEventConfigData(int32_t rs) : restart_(rs) {}
~ACDStartRecognitionEventConfigData() {}
bool restart_;
};
class ACDStartRecognitionEventConfig : public ACDEventConfig {
public:
ACDStartRecognitionEventConfig(bool restart)
: ACDEventConfig(ACD_EV_START_RECOGNITION) {
data_ = std::make_shared<ACDStartRecognitionEventConfigData>(restart);
}
~ACDStartRecognitionEventConfig() {}
};
class ACDStopRecognitionEventConfigData : public ACDEventConfigData {
public:
ACDStopRecognitionEventConfigData(bool deferred) : deferred_(deferred) {}
~ACDStopRecognitionEventConfigData() {}
bool deferred_;
};
class ACDStopRecognitionEventConfig : public ACDEventConfig {
public:
ACDStopRecognitionEventConfig(bool deferred)
: ACDEventConfig(ACD_EV_STOP_RECOGNITION) {
data_ = std::make_shared<ACDStopRecognitionEventConfigData>(deferred);
}
~ACDStopRecognitionEventConfig() {}
};
class ACDDetectedEventConfigData : public ACDEventConfigData {
public:
ACDDetectedEventConfigData(void *data) : data_(data) {}
~ACDDetectedEventConfigData() {}
void *data_;
};
class ACDDetectedEventConfig : public ACDEventConfig {
public:
ACDDetectedEventConfig(void *data) : ACDEventConfig(ACD_EV_DETECTED) {
data_ = std::make_shared<ACDDetectedEventConfigData>(data);
}
~ACDDetectedEventConfig() {}
};
class ACDConcurrentStreamEventConfigData : public ACDEventConfigData {
public:
ACDConcurrentStreamEventConfigData(bool active)
: is_active_(active) {}
~ACDConcurrentStreamEventConfigData() {}
bool is_active_;
};
class ACDConcurrentStreamEventConfig : public ACDEventConfig {
public:
ACDConcurrentStreamEventConfig (bool active)
: ACDEventConfig(ACD_EV_CONCURRENT_STREAM) {
data_ = std::make_shared<ACDConcurrentStreamEventConfigData>(active);
}
~ACDConcurrentStreamEventConfig () {}
};
class ACDPauseEventConfig : public ACDEventConfig {
public:
ACDPauseEventConfig() : ACDEventConfig(ACD_EV_PAUSE) { }
~ACDPauseEventConfig() {}
};
class ACDResumeEventConfig : public ACDEventConfig {
public:
ACDResumeEventConfig() : ACDEventConfig(ACD_EV_RESUME) { }
~ACDResumeEventConfig() {}
};
class ACDDeviceConnectedEventConfigData : public ACDEventConfigData {
public:
ACDDeviceConnectedEventConfigData(pal_device_id_t id)
: dev_id_(id) {}
~ACDDeviceConnectedEventConfigData() {}
pal_device_id_t dev_id_;
};
class ACDDeviceConnectedEventConfig : public ACDEventConfig {
public:
ACDDeviceConnectedEventConfig(pal_device_id_t id)
: ACDEventConfig(ACD_EV_DEVICE_CONNECTED) {
data_ = std::make_shared<ACDDeviceConnectedEventConfigData>(id);
}
~ACDDeviceConnectedEventConfig() {}
};
class ACDDeviceDisconnectedEventConfigData : public ACDEventConfigData {
public:
ACDDeviceDisconnectedEventConfigData(pal_device_id_t id)
: dev_id_(id) {}
~ACDDeviceDisconnectedEventConfigData() {}
pal_device_id_t dev_id_;
};
class ACDDeviceDisconnectedEventConfig : public ACDEventConfig {
public:
ACDDeviceDisconnectedEventConfig(pal_device_id_t id)
: ACDEventConfig(ACD_EV_DEVICE_DISCONNECTED) {
data_ = std::make_shared<ACDDeviceDisconnectedEventConfigData>(id);
}
~ACDDeviceDisconnectedEventConfig() {}
};
class ACDECRefEventConfigData : public ACDEventConfigData {
public:
ACDECRefEventConfigData(std::shared_ptr<Device> dev, bool is_enable)
: dev_(dev), is_enable_(is_enable) {}
~ACDECRefEventConfigData() {}
std::shared_ptr<Device> dev_;
bool is_enable_;
};
class ACDECRefEventConfig : public ACDEventConfig {
public:
ACDECRefEventConfig(std::shared_ptr<Device> dev, bool is_enable)
: ACDEventConfig(ACD_EV_EC_REF) {
data_ = std::make_shared<ACDECRefEventConfigData>(dev, is_enable);
}
~ACDECRefEventConfig() {}
};
class ACDSSROfflineConfig : public ACDEventConfig {
public:
ACDSSROfflineConfig() : ACDEventConfig(ACD_EV_SSR_OFFLINE) { }
~ACDSSROfflineConfig() {}
};
class ACDSSROnlineConfig : public ACDEventConfig {
public:
ACDSSROnlineConfig() : ACDEventConfig(ACD_EV_SSR_ONLINE) { }
~ACDSSROnlineConfig() {}
};
class ACDState {
public:
ACDState(StreamACD& acd_stream, int32_t state_id)
: acd_stream_(acd_stream), state_id_(state_id) {}
virtual ~ACDState() {}
int32_t GetStateId() { return state_id_; }
protected:
virtual int32_t ProcessEvent(std::shared_ptr<ACDEventConfig> ev_cfg) = 0;
void TransitTo(int32_t state_id) { acd_stream_.TransitTo(state_id); }
private:
StreamACD& acd_stream_;
int32_t state_id_;
friend class StreamACD;
};
class ACDIdle : public ACDState {
public:
ACDIdle(StreamACD& acd_stream)
: ACDState(acd_stream, ACD_STATE_IDLE) {}
~ACDIdle() {}
int32_t ProcessEvent(std::shared_ptr<ACDEventConfig> ev_cfg) override;
};
class ACDLoaded : public ACDState {
public:
ACDLoaded(StreamACD& acd_stream)
: ACDState(acd_stream, ACD_STATE_LOADED) {}
~ACDLoaded() {}
int32_t ProcessEvent(std::shared_ptr<ACDEventConfig> ev_cfg) override;
};
class ACDActive : public ACDState {
public:
ACDActive(StreamACD& acd_stream)
: ACDState(acd_stream, ACD_STATE_ACTIVE) {}
~ACDActive() {}
int32_t ProcessEvent(std::shared_ptr<ACDEventConfig> ev_cfg) override;
};
class ACDDetected : public ACDState {
public:
ACDDetected(StreamACD& acd_stream)
: ACDState(acd_stream, ACD_STATE_DETECTED) {}
~ACDDetected() {}
int32_t ProcessEvent(std::shared_ptr<ACDEventConfig> ev_cfg) override;
};
class ACDSSR : public ACDState {
public:
ACDSSR(StreamACD& acd_stream)
: ACDState(acd_stream, ACD_STATE_SSR) {}
~ACDSSR() {}
int32_t ProcessEvent(std::shared_ptr<ACDEventConfig> ev_cfg) override;
};
void AddState(ACDState* state);
int32_t GetPreviousStateId();
int32_t ProcessInternalEvent(std::shared_ptr<ACDEventConfig> ev_cfg);
int32_t SetupStreamConfig(const struct st_uuid *vendor_uuid);
int32_t UpdateRecognitionConfig(struct acd_recognition_cfg *config);
int32_t UpdateContextConfig(struct pal_param_context_list *config);
int32_t SendRecognitionConfig(struct acd_recognition_cfg *config);
int32_t SendContextConfig(struct pal_param_context_list *config);
int32_t SetupDetectionEngine();
int32_t GenerateCallbackEvent(struct pal_acd_recognition_event **event,
uint32_t *event_size);
static void EventNotificationThread(StreamACD *stream);
std::shared_ptr<ACDStreamConfig> sm_cfg_;
std::shared_ptr<ACDPlatformInfo> acd_info_;
std::shared_ptr<CaptureProfile> cap_prof_;
std::shared_ptr<ContextDetectionEngine> engine_;
struct acd_recognition_cfg *rec_config_;
struct pal_param_context_list *context_config_;
struct pal_st_recognition_event *cached_event_data_;
bool paused_;
bool device_opened_;
pal_stream_callback callback_;
uint64_t cookie_;
ACDState *acd_idle_;
ACDState *acd_loaded_;
ACDState *acd_active;
ACDState *acd_detected_;
ACDState *acd_ssr_;
ACDState *cur_state_;
ACDState *prev_state_;
acd_state_id_t state_for_restore_;
bool notificationInProgress = false;
bool deferredNotification = false;
std::map<uint32_t, ACDState*> acd_states_;
protected:
std::thread notification_thread_handler_;
std::mutex mutex_;
std::condition_variable cv_;
bool exit_thread_;
};
#endif // STREAMACD_H_

View File

@@ -0,0 +1,113 @@
/*
* 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 are provided under the following license:
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 STREAMTUNNEL_H_
#define STREAMTUNNEL_H_
#include "Stream.h"
class ResourceManager;
class Device;
class Session;
class StreamACDB : public Stream
{
public:
StreamACDB(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
uint32_t instance_id, const std::shared_ptr<ResourceManager> rm); //make this just pass parameters to Stream and avoid duplicating code between STREAMTUNNEL and StreamCompress
//STREAMTUNNEL();
~StreamACDB();
int32_t open() override;
int32_t close() override;
int32_t start() override;
int32_t stop() override;
int32_t prepare() override;
int32_t setStreamAttributes( struct pal_stream_attributes *sattr) override;
int32_t setVolume( struct pal_volume_data *volume) override;
int32_t mute(bool state) override;
int32_t mute_l(bool state) override;
int32_t pause() override;
int32_t pause_l() override;
int32_t resume() override;
int32_t resume_l() override;
int32_t flush();
int32_t addRemoveEffect(pal_audio_effect_t effect, bool enable) override;
int32_t read(struct pal_buffer *buf) override;
int32_t write(struct pal_buffer *buf) override;
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
int32_t getCallBack(pal_stream_callback *cb) override;
int32_t getParameters(uint32_t param_id, void **payload) override;
int32_t setParameters(uint32_t param_id, void *payload) override;
int32_t setECRef(std::shared_ptr<Device> dev, bool is_enable) override;
int32_t setECRef_l(std::shared_ptr<Device> dev, bool is_enable) override;
int32_t ssrDownHandler() override;
int32_t ssrUpHandler() override;
int32_t createMmapBuffer(int32_t min_size_frames,
struct pal_mmap_buffer *info) override;
int32_t GetMmapPosition(struct pal_mmap_position *position) override;
int32_t rwACDBParam(pal_device_id_t palDeviceId,
pal_stream_type_t palStreamType, uint32_t sampleRate,
uint32_t instanceId,
void *payload, bool isParamWrite);
};
#endif//STREAMTUNNEL_H_

View File

@@ -0,0 +1,423 @@
/*
* 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) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef STREAMASR_H_
#define STREAMASR_H_
#include <utility>
#include <map>
#include "Stream.h"
#include "ASRPlatformInfo.h"
#include "ResourceManager.h"
#include "ASREngine.h"
#include "asr_module_calibration_api.h"
typedef enum {
ASR_STATE_NONE,
ASR_STATE_IDLE,
ASR_STATE_LOADED,
ASR_STATE_ACTIVE,
ASR_STATE_SSR,
} asrStateIdT;
static const std::map<int32_t, std::string> asrStateNameMap
{
{ASR_STATE_NONE, std::string{"ASR_STATE_NONE"}},
{ASR_STATE_IDLE, std::string{"ASR_STATE_IDLE"}},
{ASR_STATE_LOADED, std::string{"ASR_STATE_LOADED"}},
{ASR_STATE_ACTIVE, std::string{"ASR_STATE_ACTIVE"}},
{ASR_STATE_SSR, std::string{"ASR_STATE_SSR"}},
};
enum {
ASR_EV_LOAD_SOUND_MODEL,
ASR_EV_UNLOAD_SOUND_MODEL,
ASR_EV_SPEECH_CONFIG,
ASR_EV_START_SPEECH_RECOGNITION,
ASR_EV_STOP_SPEECH_RECOGNITION,
ASR_EV_FORCE_OUTPUT,
ASR_EV_PAUSE,
ASR_EV_RESUME,
ASR_EV_DEVICE_CONNECTED,
ASR_EV_DEVICE_DISCONNECTED,
ASR_EV_SSR_OFFLINE,
ASR_EV_SSR_ONLINE,
ASR_EV_CONCURRENT_STREAM,
ASR_EV_EC_REF,
};
class ASREngine;
class StreamASR : public Stream {
public:
StreamASR(struct pal_stream_attributes *sattr,
struct pal_device *dattr,
uint32_t noOfDevices,
struct modifier_kv *modifiers __unused,
uint32_t no_of_modifiers __unused,
std::shared_ptr<ResourceManager> rm);
~StreamASR();
int32_t open() { return 0; }
int32_t close() override;
int32_t prepare() override { return 0; }
int32_t start() override;
int32_t stop() override;
static int32_t isSampleRateSupported(uint32_t sampleRate);
static int32_t isChannelSupported(uint32_t numChannels);
static int32_t isBitWidthSupported(uint32_t bitWidth);
int32_t setVolume(struct pal_volume_data * volume __unused) { return 0; }
int32_t mute(bool state __unused) override { return 0; }
int32_t mute_l(bool state __unused) override { return 0; }
int32_t pause() override { return 0; }
int32_t pause_l() override { return 0; }
int32_t resume() override { return 0; }
int32_t resume_l() override { return 0; }
int32_t read(struct pal_buffer *buf __unused) {return 0; }
int32_t write(struct pal_buffer *buf __unused) { return 0; }
int32_t DisconnectDevice(pal_device_id_t deviceId) override;
int32_t ConnectDevice(pal_device_id_t deviceId) override;
int32_t setECRef(std::shared_ptr<Device> dev, bool isEnable);
int32_t setECRef_l(std::shared_ptr<Device> dev, bool isEnable);
int32_t ssrDownHandler() override;
int32_t ssrUpHandler() override;
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
int32_t getCallBack(pal_stream_callback *cb) override { return 0; }
int32_t getParameters(uint32_t paramId, void **payload) override { return 0; }
int32_t setParameters(uint32_t paramId, void *payload) override;
int32_t Resume(bool isInternal = false) override;
int32_t Pause(bool isInternal = false) override;
int32_t HandleConcurrentStream(bool active) override;
int32_t addRemoveEffect(pal_audio_effect_t effec __unused,
bool enable __unused) {
return -ENOSYS;
}
int32_t setStreamAttributes(struct pal_stream_attributes *sattr __unused) {
return 0;
}
uint32_t GetNumEvents() override;
uint32_t GetOutputToken() override;
uint32_t GetPayloadSize() override;
int32_t SetupStreamConfig(const struct st_uuid *vendorUuid);
int32_t SetupDetectionEngine();
pal_device_id_t GetAvailCaptureDevice();
std::shared_ptr<CaptureProfile> GetCurrentCaptureProfile();
int32_t GetCurrentStateId();
void TransitTo(int32_t stateId);
void GetUUID(class SoundTriggerUUID *uuid, const struct st_uuid *vendorUuid);
void HandleEventData(struct pal_asr_event *event, size_t eventSize);
void sendAbort();
bool compareConfig(struct pal_asr_config *oldConfig, struct pal_asr_config *newConfig);
struct st_uuid GetVendorUuid() { return qcAsrUuid; }
param_id_asr_config_t* GetSpeechConfig() { return recConfig;}
param_id_asr_output_config_t* GetOutputConfig() { return outputConfig; }
param_id_asr_input_threshold_t* GetInputBufConfig() { return inputConfig; }
private:
class ASREventData {
public:
ASREventData() {}
virtual ~ASREventData() {}
};
class ASREventConfig {
public:
explicit ASREventConfig(int32_t evId) : id(evId) {}
virtual ~ASREventConfig() {}
int32_t id; // event id
std::shared_ptr<ASREventData> data; // event specific data
};
class ASRLoadEventData : public ASREventData {
public:
ASRLoadEventData(void *data) : model(data){};
~ASRLoadEventData() {}
void *model;
};
class ASRLoadEventConfig : public ASREventConfig {
public:
ASRLoadEventConfig(void *dataParam)
: ASREventConfig(ASR_EV_LOAD_SOUND_MODEL) {
data = std::make_shared<ASRLoadEventData>(dataParam);
}
~ASRLoadEventConfig() {}
};
class ASRUnloadEventConfig : public ASREventConfig {
public:
ASRUnloadEventConfig() : ASREventConfig(ASR_EV_UNLOAD_SOUND_MODEL) {}
~ASRUnloadEventConfig() {}
};
class ASRSpeechCfgEventData : public ASREventData {
public:
ASRSpeechCfgEventData(void *data) : config(data){}
~ASRSpeechCfgEventData() {}
void *config;
};
class ASRSpeechCfgEventConfig : public ASREventConfig {
public:
ASRSpeechCfgEventConfig(void *dataParam) : ASREventConfig(ASR_EV_SPEECH_CONFIG) {
data = std::make_shared<ASRSpeechCfgEventData>(dataParam);
}
~ASRSpeechCfgEventConfig() {}
};
class ASRStartRecognitionEventConfig : public ASREventConfig {
public:
ASRStartRecognitionEventConfig()
: ASREventConfig(ASR_EV_START_SPEECH_RECOGNITION) {
}
~ASRStartRecognitionEventConfig() {}
};
class ASRStopRecognitionEventConfig : public ASREventConfig {
public:
ASRStopRecognitionEventConfig()
: ASREventConfig(ASR_EV_STOP_SPEECH_RECOGNITION) {
}
~ASRStopRecognitionEventConfig() {}
};
class ASRForceOutputConfig : public ASREventConfig {
public:
ASRForceOutputConfig()
: ASREventConfig(ASR_EV_FORCE_OUTPUT) {
}
~ASRForceOutputConfig() {}
};
class ASRConcurrentStreamEventData : public ASREventData {
public:
ASRConcurrentStreamEventData(bool data) : active(data){};
~ASRConcurrentStreamEventData() {}
bool active;
};
class ASRConcurrentStreamEventConfig : public ASREventConfig {
public:
ASRConcurrentStreamEventConfig (bool active)
: ASREventConfig(ASR_EV_CONCURRENT_STREAM) {
data = std::make_shared<ASRConcurrentStreamEventData>(active);
}
~ASRConcurrentStreamEventConfig () {}
};
class ASRPauseEventConfig : public ASREventConfig {
public:
ASRPauseEventConfig() : ASREventConfig(ASR_EV_PAUSE) { }
~ASRPauseEventConfig() {}
};
class ASRResumeEventConfig : public ASREventConfig {
public:
ASRResumeEventConfig() : ASREventConfig(ASR_EV_RESUME) { }
~ASRResumeEventConfig() {}
};
class ASRDeviceConnectedEventData : public ASREventData {
public:
ASRDeviceConnectedEventData(pal_device_id_t dId) : devId(dId){};
~ASRDeviceConnectedEventData() {}
pal_device_id_t devId;
};
class ASRDeviceConnectedEventConfig : public ASREventConfig {
public:
ASRDeviceConnectedEventConfig(pal_device_id_t id)
: ASREventConfig(ASR_EV_DEVICE_CONNECTED) {
data = std::make_shared<ASRDeviceConnectedEventData>(id);
}
~ASRDeviceConnectedEventConfig() {}
};
class ASRDeviceDisconnectedEventData : public ASREventData {
public:
ASRDeviceDisconnectedEventData(pal_device_id_t dId) : devId(dId){};
~ASRDeviceDisconnectedEventData() {}
pal_device_id_t devId;
};
class ASRDeviceDisconnectedEventConfig : public ASREventConfig {
public:
ASRDeviceDisconnectedEventConfig(pal_device_id_t id)
: ASREventConfig(ASR_EV_DEVICE_DISCONNECTED) {
data = std::make_shared<ASRDeviceDisconnectedEventData>(id);
}
~ASRDeviceDisconnectedEventConfig() {}
};
class ASRECRefEventData : public ASREventData {
public:
ASRECRefEventData(std::shared_ptr<Device> dev, bool isEnable)
: dev(dev), isEnable(isEnable) {}
~ASRECRefEventData() {}
std::shared_ptr<Device> dev;
bool isEnable;
};
class ASRECRefEventConfig : public ASREventConfig {
public:
ASRECRefEventConfig(std::shared_ptr<Device> dev, bool isEnable)
: ASREventConfig(ASR_EV_EC_REF) {
data = std::make_shared<ASRECRefEventData>(dev, isEnable);
}
~ASRECRefEventConfig() {}
};
class ASRSSROfflineConfig : public ASREventConfig {
public:
ASRSSROfflineConfig() : ASREventConfig(ASR_EV_SSR_OFFLINE) { }
~ASRSSROfflineConfig() {}
};
class ASRSSROnlineConfig : public ASREventConfig {
public:
ASRSSROnlineConfig() : ASREventConfig(ASR_EV_SSR_ONLINE) { }
~ASRSSROnlineConfig() {}
};
class ASRState {
public:
ASRState(StreamASR& asrStream, int32_t stateId)
: asrStream(asrStream), stateId(stateId) {}
virtual ~ASRState() {}
int32_t GetStateId() { return stateId; }
protected:
virtual int32_t ProcessEvent(std::shared_ptr<ASREventConfig> evCfg) = 0;
void TransitTo(int32_t stateId) { asrStream.TransitTo(stateId); }
private:
StreamASR& asrStream;
int32_t stateId;
friend class StreamASR;
};
class ASRIdle : public ASRState {
public:
ASRIdle(StreamASR& asrStream)
: ASRState(asrStream, ASR_STATE_IDLE) {}
~ASRIdle() {}
int32_t ProcessEvent(std::shared_ptr<ASREventConfig> evCfg) override;
};
class ASRLoaded : public ASRState {
public:
ASRLoaded(StreamASR& asrStream)
: ASRState(asrStream, ASR_STATE_LOADED) {}
~ASRLoaded() {}
int32_t ProcessEvent(std::shared_ptr<ASREventConfig> evCfg) override;
};
class ASRActive : public ASRState {
public:
ASRActive(StreamASR& asrStream)
: ASRState(asrStream, ASR_STATE_ACTIVE) {}
~ASRActive() {}
int32_t ProcessEvent(std::shared_ptr<ASREventConfig> evCfg) override;
};
class ASRSSR : public ASRState {
public:
ASRSSR(StreamASR& asrStream)
: ASRState(asrStream, ASR_STATE_SSR) {}
~ASRSSR() {}
int32_t ProcessEvent(std::shared_ptr<ASREventConfig> evCfg) override;
};
static void EventNotificationThread(StreamASR *stream);
void AddState(ASRState* state);
bool UseLpiCaptureProfile();
int32_t GetPreviousStateId();
int32_t ProcessInternalEvent(std::shared_ptr<ASREventConfig> evCfg);
int32_t SetRecognitionConfig(struct pal_asr_config *config);
int32_t GenerateCallbackEvent(struct pal_asr_event **event,
uint32_t *eventSize);
/* Currently model is not loaded from HLOS, hence using this hardcoded UUID,
* Later when loading is supported, we need to remove it from here, and
* get it from model, to check which sm_config it supports to
*/
static constexpr struct st_uuid qcAsrUuid =
{ 0x018ebfb8, 0x1364, 0x7417, 0xb92e, {0xf6, 0xab, 0x16, 0xb5, 0x54, 0x31} };
std::shared_ptr<ASRStreamConfig> smCfg;
std::shared_ptr<ASRCommonConfig> cmCfg;
std::shared_ptr<ASRPlatformInfo> asrInfo;
std::shared_ptr<CaptureProfile> capProf;
std::shared_ptr<ASREngine> engine;
struct pal_asr_config *palRecConfig;
param_id_asr_config_t *recConfig;
param_id_asr_output_config_t *outputConfig;
param_id_asr_input_threshold_t *inputConfig;
bool paused;
bool deviceOpened;
pal_stream_callback callback;
uint64_t cookie;
ASRState *asrIdle;
ASRState *asrLoaded;
ASRState *asrActive;
ASRState *asrSsr;
ASRState *curState;
ASRState *prevState;
asrStateIdT stateToRestore;
std::map<uint32_t, ASRState*> asrStates;
std::condition_variable cv;
};
#endif // STREAMASR_H_

View File

@@ -0,0 +1,91 @@
/*
* 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.
*/
#ifndef STREAMCOMMON_H_
#define STREAMCOMMON_H_
#include "Stream.h"
#define GET_DIR_STR(X) (X == PAL_AUDIO_OUTPUT)? "RX": (X == PAL_AUDIO_INPUT)? "TX": "TX_RX"
class ResourceManager;
class Device;
class Session;
/*
* use this common class to pass parameters to Stream,
* which avoids duplicating codes between StreamContextProxy,
* StreamUltraSound, and StreamSensorPCMData.
*/
class StreamCommon : public Stream
{
public:
StreamCommon(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
const uint32_t no_of_devices, const struct modifier_kv *modifiers,
const uint32_t no_of_modifiers, const std::shared_ptr<ResourceManager> rm);
~StreamCommon();
uint64_t cookie_;
pal_stream_callback callback_= 0;
int32_t open() override;
int32_t close() override;
int32_t start() override;
int32_t stop() override;
int32_t prepare() override {return 0;}
int32_t setStreamAttributes( struct pal_stream_attributes *sattr __unused) override {return 0;}
int32_t setVolume( struct pal_volume_data *volume) override;
int32_t mute(bool state __unused) override {return 0;}
int32_t mute_l(bool state __unused) override {return 0;}
int32_t pause() override {return 0;}
int32_t pause_l() override {return 0;}
int32_t resume() override {return 0;}
int32_t resume_l() override {return 0;}
int32_t flush() {return 0;}
int32_t addRemoveEffect(pal_audio_effect_t effect __unused, bool enable __unused) override {return 0;}
int32_t read(struct pal_buffer *buf __unused) override {return 0;}
int32_t write(struct pal_buffer *buf __unused) override {return 0;}
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
int32_t getCallBack(pal_stream_callback *cb __unused) override {return 0;}
int32_t getParameters(uint32_t param_id __unused, void **payload __unused) override {return 0;}
int32_t setParameters(uint32_t param_id __unused, void *payload __unused) override {return 0;}
int32_t setECRef(std::shared_ptr<Device> dev __unused, bool is_enable __unused) override {return 0;}
int32_t setECRef_l(std::shared_ptr<Device> dev __unused, bool is_enable __unused) override {return 0;}
int32_t ssrDownHandler() override;
int32_t ssrUpHandler() override;
int32_t createMmapBuffer(int32_t min_size_frames __unused,
struct pal_mmap_buffer *info __unused) override {return 0;}
int32_t GetMmapPosition(struct pal_mmap_position *position __unused) override {return 0;}
int32_t start_device();
int32_t startSession();
int32_t getTagsWithModuleInfo(size_t *size, uint8_t *payload);
static int32_t isSampleRateSupported(uint32_t sampleRate __unused) {return 0;}
static int32_t isChannelSupported(uint32_t numChannels __unused) {return 0;}
static int32_t isBitWidthSupported(uint32_t bitWidth __unused) {return 0;}
};
#endif//STREAMCOMMON_H_

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2022, 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 are provided under the following license:
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef StreamCommonProxy_H_
#define StreamCommonProxy_H_
#include "StreamCommon.h"
class ResourceManager;
class Device;
class Session;
class StreamCommonProxy : public StreamCommon
{
public:
StreamCommonProxy(const struct pal_stream_attributes *sattr, struct pal_device *dattr __unused,
const uint32_t no_of_devices __unused,
const struct modifier_kv *modifiers __unused, const uint32_t no_of_modifiers __unused,
const std::shared_ptr<ResourceManager> rm);
virtual ~StreamCommonProxy();
int32_t getParameters(uint32_t param_id, void **payload);
};
#endif//StreamCommonProxy_H_

View File

@@ -0,0 +1,83 @@
/*
* 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 are provided under the following license:
*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef STREAMCOMPRESS_H_
#define STREAMCOMPRESS_H_
#include "Stream.h"
class ResourceManager;
class Device;
class Session;
class StreamCompress : public Stream
{
public:
StreamCompress(const struct pal_stream_attributes *sattr, struct pal_device *dattr, const uint32_t no_of_devices,
const struct modifier_kv *modifiers, const uint32_t no_of_modifiers, const std::shared_ptr<ResourceManager> rm);
~StreamCompress();
int32_t open() override;
int32_t close() override;
int32_t start() override;
int32_t stop() override;
int32_t prepare() override;
int32_t pause() override;
int32_t pause_l() override;
int32_t resume() override;
int32_t resume_l() override;
int32_t drain(pal_drain_type_t type);
int32_t flush();
int32_t setStreamAttributes(struct pal_stream_attributes *sattr) override;
int32_t setVolume( struct pal_volume_data *volume) override;
int32_t mute(bool state) override;
int32_t mute_l(bool state) override;
int32_t getDeviceMute(pal_stream_direction_t dir __unused, bool *state __unused) override {return 0;}
int32_t setDeviceMute(pal_stream_direction_t dir __unused, bool state __unused) override {return 0;}
int32_t read(struct pal_buffer *buf) override;
int32_t write(struct pal_buffer *buf) override;
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
int32_t getCallBack(pal_stream_callback *cb) override;
int32_t getParameters(uint32_t param_id, void **payload) override;
int32_t setParameters(uint32_t param_id, void *payload) override;
static int32_t isSampleRateSupported(uint32_t sampleRate);
static int32_t isChannelSupported(uint32_t numChannels);
static int32_t isBitWidthSupported(uint32_t bitWidth);
int32_t addRemoveEffect(pal_audio_effect_t effect, bool enable) override;
int32_t setECRef(std::shared_ptr<Device> dev, bool is_enable) override;
int32_t setECRef_l(std::shared_ptr<Device> dev, bool is_enable) override;
int32_t ssrDownHandler() override;
int32_t ssrUpHandler() override;
};
#endif//STREAMCOMPRESS_H_

View File

@@ -0,0 +1,57 @@
/*
* 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 STREAMCONTEXTPROXY_H_
#define STREAMCONTEXTPROXY_H_
#include "StreamCommon.h"
class ResourceManager;
class Device;
class Session;
class StreamContextProxy : public StreamCommon
{
public:
StreamContextProxy(const struct pal_stream_attributes *sattr, struct pal_device *dattr __unused,
const uint32_t no_of_devices __unused,
const struct modifier_kv *modifiers __unused, const uint32_t no_of_modifiers __unused,
const std::shared_ptr<ResourceManager> rm); //make this just pass parameters to Stream and avoid duplicating code between StreamPCM and StreamCompress
//StreamContextProxy();
virtual ~StreamContextProxy();
int32_t setParameters(uint32_t param_id, void *payload);
int32_t setVolume( struct pal_volume_data *volume __unused) {return 0;}
private:
void ParseASPSEventPayload(uint32_t event_id,
uint32_t event_size, void *data);
static void HandleCallBack(uint64_t hdl, uint32_t event_id, void *data,
uint32_t event_size);
};
#endif//STREAMCONTEXTPROXY_H_

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 STREAMHAPTICS_H_
#define STREAMHAPTICS_H_
#include "StreamPCM.h"
#include "ResourceManager.h"
#include "Device.h"
#include "Session.h"
class StreamHaptics : public StreamPCM
{
public:
StreamHaptics(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
const uint32_t no_of_devices, const struct modifier_kv *modifiers,
const uint32_t no_of_modifiers, const std::shared_ptr<ResourceManager> rm);
~StreamHaptics();
uint64_t cookie_;
pal_stream_callback callback_= 0;
int32_t setParameters(uint32_t param_id, void *payload);
int32_t start();
int32_t ssrDownHandler() override;
int32_t ssrUpHandler() override;
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
private:
static void HandleCallBack(uint64_t hdl, uint32_t event_id,
void *data, uint32_t event_size);
void HandleEvent(uint32_t event_id, void *data, uint32_t event_size);
int32_t HandleHapticsConcurrency(struct pal_stream_attributes *sattr);
};
#endif//STREAMHAPTICS_H_

View File

@@ -0,0 +1,85 @@
/*
* 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 are provided under the following license:
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef STREAMINCALL_H_
#define STREAMINCALL_H_
#include "Stream.h"
class ResourceManager;
class Device;
class Session;
class StreamInCall : public Stream
{
public:
StreamInCall(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
const uint32_t no_of_devices,
const struct modifier_kv *modifiers, const uint32_t no_of_modifiers,
const std::shared_ptr<ResourceManager> rm); //make this just pass parameters to Stream and avoid duplicating code between StreamInCall and StreamCompress
//StreamInCall();
virtual ~StreamInCall();
int32_t open() override;
int32_t close() override;
int32_t start() override;
int32_t stop() override;
int32_t prepare() override;
int32_t setStreamAttributes( struct pal_stream_attributes *sattr) override;
int32_t setVolume( struct pal_volume_data *volume) override;
int32_t mute(bool state) override;
int32_t mute_l(bool state) override;
int32_t getDeviceMute(pal_stream_direction_t dir __unused, bool *state __unused) override {return 0;}
int32_t setDeviceMute(pal_stream_direction_t dir __unused, bool state __unused) override {return 0;}
int32_t pause() override;
int32_t pause_l() override;
int32_t resume() override;
int32_t resume_l() override;
int32_t flush();
int32_t addRemoveEffect(pal_audio_effect_t effect, bool enable) override;
int32_t read(struct pal_buffer *buf) override;
int32_t write(struct pal_buffer *buf) override;
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
int32_t getCallBack(pal_stream_callback *cb) override;
int32_t getParameters(uint32_t param_id, void **payload) override;
int32_t setParameters(uint32_t param_id, void *payload) override;
static int32_t isSampleRateSupported(uint32_t sampleRate);
static int32_t isChannelSupported(uint32_t numChannels);
static int32_t isBitWidthSupported(uint32_t bitWidth);
int32_t setECRef(std::shared_ptr<Device> dev, bool is_enable) override;
int32_t setECRef_l(std::shared_ptr<Device> dev, bool is_enable) override;
int32_t ssrDownHandler() override;
int32_t ssrUpHandler() override;
int32_t reconfigureModule(uint32_t tagID, const char* BE, struct sessionToPayloadParam *data);
};
#endif//StreamInCall_H_

View File

@@ -0,0 +1,88 @@
/*
* 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 are provided under the following license:
*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef STREAMPCM_H_
#define STREAMPCM_H_
#include "Stream.h"
class ResourceManager;
class Device;
class Session;
class StreamPCM : public Stream
{
public:
StreamPCM(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
const uint32_t no_of_devices,
const struct modifier_kv *modifiers, const uint32_t no_of_modifiers,
const std::shared_ptr<ResourceManager> rm); //make this just pass parameters to Stream and avoid duplicating code between StreamPCM and StreamCompress
~StreamPCM();
int32_t open() override;
int32_t close() override;
int32_t start() override;
int32_t stop() override;
int32_t prepare() override;
int32_t setStreamAttributes( struct pal_stream_attributes *sattr) override;
int32_t setVolume( struct pal_volume_data *volume) override;
int32_t mute(bool state) override;
int32_t mute_l(bool state) override;
int32_t getDeviceMute(pal_stream_direction_t dir, bool *state) override;
int32_t setDeviceMute(pal_stream_direction_t dir, bool state) override;
int32_t pause() override;
int32_t pause_l() override;
int32_t resume() override;
int32_t resume_l() override;
int32_t flush();
int32_t addRemoveEffect(pal_audio_effect_t effect, bool enable) override;
int32_t read(struct pal_buffer *buf) override;
int32_t write(struct pal_buffer *buf) override;
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
int32_t getCallBack(pal_stream_callback *cb) override;
int32_t getParameters(uint32_t param_id, void **payload) override;
int32_t setParameters(uint32_t param_id, void *payload) override;
int32_t setECRef(std::shared_ptr<Device> dev, bool is_enable) override;
int32_t setECRef_l(std::shared_ptr<Device> dev, bool is_enable) override;
int32_t ssrDownHandler() override;
int32_t ssrUpHandler() override;
int32_t createMmapBuffer(int32_t min_size_frames,
struct pal_mmap_buffer *info) override;
int32_t GetMmapPosition(struct pal_mmap_position *position) override;
static int32_t isSampleRateSupported(uint32_t sampleRate);
static int32_t isChannelSupported(uint32_t numChannels);
static int32_t isBitWidthSupported(uint32_t bitWidth);
};
#endif//STREAMPCM_H_

View File

@@ -0,0 +1,83 @@
/*
* 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.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef StreamSensorPCMData_H_
#define StreamSensorPCMData_H_
#include "Device.h"
#include "Session.h"
#include "StreamCommon.h"
#include "ACDPlatformInfo.h"
class StreamSensorPCMData : public StreamCommon
{
public:
StreamSensorPCMData(const struct pal_stream_attributes *sattr __unused,
struct pal_device *dattr __unused,
const uint32_t no_of_devices __unused,
const struct modifier_kv *modifiers __unused,
const uint32_t no_of_modifiers __unused,
const std::shared_ptr<ResourceManager> rm);
~StreamSensorPCMData();
std::shared_ptr<CaptureProfile> GetCurrentCaptureProfile();
int32_t addRemoveEffect(pal_audio_effect_t effect, bool enable);
int32_t open() override;
int32_t start() override;
int32_t stop() override;
int32_t close() override;
int32_t Resume(bool is_internal __unused) override;
int32_t Pause(bool is_internal __unused) override;
int32_t HandleConcurrentStream(bool active) override;
int32_t DisconnectDevice(pal_device_id_t device_id) override;
int32_t ConnectDevice(pal_device_id_t device_id) override;
pal_device_id_t GetAvailCaptureDevice();
struct st_uuid GetVendorUuid();
private:
void GetUUID(class SoundTriggerUUID *uuid, const struct st_uuid *vendor_uuid);
int32_t SetupStreamConfig(const struct st_uuid *vendor_uuid);
int32_t DisconnectDevice_l(pal_device_id_t device_id);
int32_t ConnectDevice_l(pal_device_id_t device_id);
int32_t setECRef(std::shared_ptr<Device> dev, bool is_enable);
int32_t setECRef_l(std::shared_ptr<Device> dev, bool is_enable);
int32_t setParameters(uint32_t param_id, void *payload);
std::shared_ptr<ACDStreamConfig> sm_cfg_;
std::shared_ptr<ACDPlatformInfo> acd_info_;
std::shared_ptr<CaptureProfile> cap_prof_;
uint32_t pcm_data_stream_effect;
uint32_t pcm_data_buffering;
bool paused_;
};
#endif//StreamSensorPCMData_H_

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef STREAMSENSORRENDERER_H_
#define STREAMSENSORRENDERER_H_
#include "StreamCommon.h"
#include "ResourceManager.h"
#include "Device.h"
#include "Session.h"
class StreamSensorRenderer : public StreamCommon
{
public:
StreamSensorRenderer(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
const uint32_t no_of_devices, const struct modifier_kv *modifiers,
const uint32_t no_of_modifiers, const std::shared_ptr<ResourceManager> rm);
~StreamSensorRenderer();
};
#endif//STREAMSENSORRENDERER_H_

View File

@@ -0,0 +1,628 @@
/*
* 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 are provided under the following license:
*
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef STREAMSOUNDTRIGGER_H_
#define STREAMSOUNDTRIGGER_H_
#include <utility>
#include <map>
#include "Stream.h"
#include "PalRingBuffer.h"
#include "SoundTriggerEngine.h"
#include "VoiceUIPlatformInfo.h"
#include "detection_cmn_api.h"
#include "mma_api.h"
enum {
ENGINE_IDLE = 0x0,
GMM_DETECTED = 0x1,
KEYWORD_DETECTION_SUCCESS = 0x2,
KEYWORD_DETECTION_REJECT = 0x4,
USER_VERIFICATION_SUCCESS = 0x8,
USER_VERIFICATION_REJECT = 0x10,
KEYWORD_DETECTION_PENDING = 0x20,
USER_VERIFICATION_PENDING = 0x40,
DETECTION_TYPE_SS = 0x1E,
DETECTION_TYPE_ALL = 0x1F,
};
typedef enum {
ST_STATE_NONE,
ST_STATE_IDLE,
ST_STATE_LOADED,
ST_STATE_ACTIVE,
ST_STATE_DETECTED,
ST_STATE_BUFFERING,
ST_STATE_SSR,
} st_state_id_t;
static const std::map<int32_t, std::string> stStateNameMap
{
{ST_STATE_NONE, std::string{"ST_STATE_NONE"}},
{ST_STATE_IDLE, std::string{"ST_STATE_IDLE"}},
{ST_STATE_LOADED, std::string{"ST_STATE_LOADED"}},
{ST_STATE_ACTIVE, std::string{"ST_STATE_ACTIVE"}},
{ST_STATE_DETECTED, std::string{"ST_STATE_DETECTED"}},
{ST_STATE_BUFFERING, std::string{"ST_STATE_BUFFERING"}},
{ST_STATE_SSR, std::string{"ST_STATE_SSR"}}
};
enum {
ST_EV_LOAD_SOUND_MODEL,
ST_EV_UNLOAD_SOUND_MODEL,
ST_EV_RECOGNITION_CONFIG,
ST_EV_START_RECOGNITION,
ST_EV_RESTART_RECOGNITION,
ST_EV_STOP_RECOGNITION,
ST_EV_DETECTED,
ST_EV_READ_BUFFER,
ST_EV_STOP_BUFFERING,
ST_EV_PAUSE,
ST_EV_RESUME,
ST_EV_DEVICE_CONNECTED,
ST_EV_DEVICE_DISCONNECTED,
ST_EV_SSR_OFFLINE,
ST_EV_SSR_ONLINE,
ST_EV_CONCURRENT_STREAM,
ST_EV_EC_REF,
ST_EV_INTERNAL_PAUSE,
ST_EV_INTERNAL_RESUME,
};
class ResourceManager;
class SoundModelInfo;
class VoiceUIInterface;
class StreamSoundTrigger : public Stream
{
public:
StreamSoundTrigger(struct pal_stream_attributes *sattr,
struct pal_device *dattr,
uint32_t no_of_devices,
struct modifier_kv *modifiers __unused,
uint32_t no_of_modifiers __unused,
std::shared_ptr<ResourceManager> rm);
~StreamSoundTrigger();
int32_t open() { return 0; }
int32_t close() override;
int32_t start() override;
int32_t stop() override;
int32_t prepare() override { return 0; }
int32_t ssrDownHandler() override;
int32_t ssrUpHandler() override;
int32_t setStreamAttributes(struct pal_stream_attributes *sattr __unused) {
return 0;
}
int32_t setVolume(struct pal_volume_data * volume __unused) { return 0; }
int32_t mute(bool state __unused) override { return 0; }
int32_t mute_l(bool state __unused) override { return 0; }
int32_t getDeviceMute(pal_stream_direction_t dir __unused, bool *state __unused) override {return 0;}
int32_t setDeviceMute(pal_stream_direction_t dir __unused, bool state __unused) override {return 0;}
int32_t pause() override { return 0; }
int32_t pause_l() override { return 0; }
int32_t resume() override { return 0; }
int32_t resume_l() override { return 0; }
int32_t read(struct pal_buffer *buf) override;
int32_t write(struct pal_buffer *buf __unused) { return 0; }
int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override;
int32_t getCallBack(pal_stream_callback *cb) override;
int32_t getParameters(uint32_t param_id, void **payload) override;
int32_t setParameters(uint32_t param_id, void *payload) override;
int32_t addRemoveEffect(pal_audio_effect_t effec __unused,
bool enable __unused) {
return -ENOSYS;
}
bool isStarted();
void SetDetectedToEngines(bool detected);
int32_t SetEngineDetectionState(int32_t state);
static int32_t isSampleRateSupported(uint32_t sampleRate);
static int32_t isChannelSupported(uint32_t numChannels);
static int32_t isBitWidthSupported(uint32_t bitWidth);
std::shared_ptr<CaptureProfile> GetCurrentCaptureProfile();
int32_t DisconnectDevice(pal_device_id_t device_id) override;
int32_t ConnectDevice(pal_device_id_t device_id) override;
int disconnectStreamDevice_l(Stream* streamHandle,
pal_device_id_t dev_id) override;
int connectStreamDevice_l(Stream* streamHandle,
struct pal_device *dattr) override;
int32_t Resume(bool is_internal = false) override;
int32_t Pause(bool is_internal = false) override;
int32_t GetCurrentStateId();
int32_t HandleConcurrentStream(bool active);
int32_t setECRef(std::shared_ptr<Device> dev, bool is_enable) override;
int32_t setECRef_l(std::shared_ptr<Device> dev, bool is_enable) override;
bool ConfigSupportLPI() override;
uint32_t getCallbackEventId() override;
void TransitTo(int32_t state_id);
friend class PalRingBufferReader;
bool IsCaptureRequested() { return capture_requested_; }
uint32_t GetRecognitionMode() { return recognition_mode_; }
uint32_t GetHistBufDuration() { return hist_buf_duration_; }
uint32_t GetPreRollDuration() { return pre_roll_duration_; }
uint32_t GetModelId(){ return model_id_; }
void SetModelId(uint32_t model_id) { model_id_ = model_id; }
uint32_t GetInstanceId();
bool IsStreamInBuffering() {
return (capture_requested_ && reader_ &&
(GetCurrentStateId() == ST_STATE_BUFFERING)) &&
(reader_->isEnabled() || reader_->isPrepared());
}
struct st_uuid GetVendorUuid();
void *GetGSLEngine() {
if (gsl_engine_)
return (void *)gsl_engine_.get();
else
return nullptr;
}
std::vector<PalRingBufferReader *> GetReaders() { return reader_list_;}
private:
class EngineCfg {
public:
EngineCfg(int32_t id, std::shared_ptr<SoundTriggerEngine> engine,
void *data, int32_t size)
: id_(id), engine_(engine), sm_data_(data), sm_size_(size) {}
~EngineCfg() {}
std::shared_ptr<SoundTriggerEngine> GetEngine() const {
return engine_;
}
int32_t GetEngineId() const { return id_; }
int32_t id_;
std::shared_ptr<SoundTriggerEngine> engine_;
void *sm_data_;
int32_t sm_size_;
};
class StEventConfigData {
public:
StEventConfigData() {}
virtual ~StEventConfigData() {}
};
class StEventConfig {
public:
explicit StEventConfig(int32_t ev_id)
: id_(ev_id), data_(nullptr) {}
virtual ~StEventConfig() {}
int32_t id_; // event id
std::shared_ptr<StEventConfigData> data_; // event specific data
};
class StLoadEventConfigData : public StEventConfigData {
public:
StLoadEventConfigData(void *data): data_(data) {}
~StLoadEventConfigData() {}
void *data_;
};
class StLoadEventConfig : public StEventConfig {
public:
StLoadEventConfig(void *data)
: StEventConfig(ST_EV_LOAD_SOUND_MODEL) {
data_ = std::make_shared<StLoadEventConfigData>(data);
}
~StLoadEventConfig() {}
};
class StUnloadEventConfig : public StEventConfig {
public:
StUnloadEventConfig() : StEventConfig(ST_EV_UNLOAD_SOUND_MODEL) {}
~StUnloadEventConfig() {}
};
class StRecognitionCfgEventConfigData : public StEventConfigData {
public:
StRecognitionCfgEventConfigData(void *data): data_(data) {}
~StRecognitionCfgEventConfigData() {}
void *data_;
};
class StRecognitionCfgEventConfig : public StEventConfig {
public:
StRecognitionCfgEventConfig(void *data)
: StEventConfig(ST_EV_RECOGNITION_CONFIG) {
data_ = std::make_shared<StRecognitionCfgEventConfigData>(data);
}
~StRecognitionCfgEventConfig() {}
};
class StStartRecognitionEventConfigData : public StEventConfigData {
public:
StStartRecognitionEventConfigData(int32_t rs) : restart_(rs) {}
~StStartRecognitionEventConfigData() {}
bool restart_;
};
class StStartRecognitionEventConfig : public StEventConfig {
public:
StStartRecognitionEventConfig(bool restart)
: StEventConfig(ST_EV_START_RECOGNITION) {
data_ = std::make_shared<StStartRecognitionEventConfigData>(restart);
}
~StStartRecognitionEventConfig() {}
};
class StStopRecognitionEventConfigData : public StEventConfigData {
public:
StStopRecognitionEventConfigData(bool deferred) : deferred_(deferred) {}
~StStopRecognitionEventConfigData() {}
bool deferred_;
};
class StStopRecognitionEventConfig : public StEventConfig {
public:
StStopRecognitionEventConfig(bool deferred)
: StEventConfig(ST_EV_STOP_RECOGNITION) {
data_ = std::make_shared<StStopRecognitionEventConfigData>(deferred);
}
~StStopRecognitionEventConfig() {}
};
class StDetectedEventConfigData : public StEventConfigData {
public:
StDetectedEventConfigData(int32_t type) : det_type_(type) {}
~StDetectedEventConfigData() {}
int32_t det_type_;
};
class StDetectedEventConfig : public StEventConfig {
public:
StDetectedEventConfig(int32_t type) : StEventConfig(ST_EV_DETECTED) {
data_ = std::make_shared<StDetectedEventConfigData>(type);
}
~StDetectedEventConfig() {}
};
class StReadBufferEventConfigData : public StEventConfigData {
public:
StReadBufferEventConfigData(void *data) : data_(data) {}
~StReadBufferEventConfigData() {}
void *data_;
};
class StReadBufferEventConfig : public StEventConfig {
public:
StReadBufferEventConfig(void *data) : StEventConfig(ST_EV_READ_BUFFER) {
data_ = std::make_shared<StReadBufferEventConfigData>(data);
}
~StReadBufferEventConfig() {}
};
class StStopBufferingEventConfig : public StEventConfig {
public:
StStopBufferingEventConfig () : StEventConfig(ST_EV_STOP_BUFFERING) {}
~StStopBufferingEventConfig () {}
};
class StConcurrentStreamEventConfigData : public StEventConfigData {
public:
StConcurrentStreamEventConfigData(bool active)
: is_active_(active) {}
~StConcurrentStreamEventConfigData() {}
bool is_active_;
};
class StConcurrentStreamEventConfig : public StEventConfig {
public:
StConcurrentStreamEventConfig (bool active)
: StEventConfig(ST_EV_CONCURRENT_STREAM) {
data_ = std::make_shared<StConcurrentStreamEventConfigData>(active);
}
~StConcurrentStreamEventConfig () {}
};
class StPauseEventConfig : public StEventConfig {
public:
StPauseEventConfig() : StEventConfig(ST_EV_PAUSE) { }
~StPauseEventConfig() {}
};
class StResumeEventConfig : public StEventConfig {
public:
StResumeEventConfig() : StEventConfig(ST_EV_RESUME) { }
~StResumeEventConfig() {}
};
class StInternalPauseEventConfig : public StEventConfig {
public:
StInternalPauseEventConfig() : StEventConfig(ST_EV_INTERNAL_PAUSE) { }
~StInternalPauseEventConfig() {}
};
class StInternalResumeEventConfig : public StEventConfig {
public:
StInternalResumeEventConfig() : StEventConfig(ST_EV_INTERNAL_RESUME) { }
~StInternalResumeEventConfig() {}
};
class StECRefEventConfigData : public StEventConfigData {
public:
StECRefEventConfigData(std::shared_ptr<Device> dev, bool is_enable)
: dev_(dev), is_enable_(is_enable) {}
~StECRefEventConfigData() {}
std::shared_ptr<Device> dev_;
bool is_enable_;
};
class StECRefEventConfig : public StEventConfig {
public:
StECRefEventConfig(std::shared_ptr<Device> dev, bool is_enable)
: StEventConfig(ST_EV_EC_REF) {
data_ = std::make_shared<StECRefEventConfigData>(dev, is_enable);
}
~StECRefEventConfig() {}
};
class StDeviceConnectedEventConfigData : public StEventConfigData {
public:
StDeviceConnectedEventConfigData(pal_device_id_t id)
: dev_id_(id) {}
~StDeviceConnectedEventConfigData() {}
pal_device_id_t dev_id_;
};
class StDeviceConnectedEventConfig : public StEventConfig {
public:
StDeviceConnectedEventConfig(pal_device_id_t id)
: StEventConfig(ST_EV_DEVICE_CONNECTED) {
data_ = std::make_shared<StDeviceConnectedEventConfigData>(id);
}
~StDeviceConnectedEventConfig() {}
};
class StDeviceDisconnectedEventConfigData : public StEventConfigData {
public:
StDeviceDisconnectedEventConfigData(pal_device_id_t id)
: dev_id_(id) {}
~StDeviceDisconnectedEventConfigData() {}
pal_device_id_t dev_id_;
};
class StDeviceDisconnectedEventConfig : public StEventConfig {
public:
StDeviceDisconnectedEventConfig(pal_device_id_t id)
: StEventConfig(ST_EV_DEVICE_DISCONNECTED) {
data_ = std::make_shared<StDeviceDisconnectedEventConfigData>(id);
}
~StDeviceDisconnectedEventConfig() {}
};
class StSSROfflineConfig : public StEventConfig {
public:
StSSROfflineConfig() : StEventConfig(ST_EV_SSR_OFFLINE) { }
~StSSROfflineConfig() {}
};
class StSSROnlineConfig : public StEventConfig {
public:
StSSROnlineConfig() : StEventConfig(ST_EV_SSR_ONLINE) { }
~StSSROnlineConfig() {}
};
class StState {
public:
StState(StreamSoundTrigger& st_stream, int32_t state_id)
: st_stream_(st_stream), state_id_(state_id) {}
virtual ~StState() {}
int32_t GetStateId() { return state_id_; }
protected:
virtual int32_t ProcessEvent(std::shared_ptr<StEventConfig> ev_cfg) = 0;
void TransitTo(int32_t state_id) { st_stream_.TransitTo(state_id); }
private:
StreamSoundTrigger& st_stream_;
int32_t state_id_;
friend class StreamSoundTrigger;
};
class StIdle : public StState {
public:
StIdle(StreamSoundTrigger& st_stream)
: StState(st_stream, ST_STATE_IDLE) {}
~StIdle() {}
int32_t ProcessEvent(std::shared_ptr<StEventConfig> ev_cfg) override;
};
class StLoaded : public StState {
public:
StLoaded(StreamSoundTrigger& st_stream)
: StState(st_stream, ST_STATE_LOADED) {}
~StLoaded() {}
int32_t ProcessEvent(std::shared_ptr<StEventConfig> ev_cfg) override;
};
class StActive : public StState {
public:
StActive(StreamSoundTrigger& st_stream)
: StState(st_stream, ST_STATE_ACTIVE) {}
~StActive() {}
int32_t ProcessEvent(std::shared_ptr<StEventConfig> ev_cfg) override;
};
class StDetected : public StState {
public:
StDetected(StreamSoundTrigger& st_stream)
: StState(st_stream, ST_STATE_DETECTED) {}
~StDetected() {}
int32_t ProcessEvent(std::shared_ptr<StEventConfig> ev_cfg) override;
};
class StBuffering : public StState {
public:
StBuffering(StreamSoundTrigger& st_stream)
: StState(st_stream, ST_STATE_BUFFERING) {}
~StBuffering() {}
int32_t ProcessEvent(std::shared_ptr<StEventConfig> ev_cfg) override;
};
class StSSR : public StState {
public:
StSSR(StreamSoundTrigger& st_stream)
: StState(st_stream, ST_STATE_SSR) {}
~StSSR() {}
int32_t ProcessEvent(std::shared_ptr<StEventConfig> ev_cfg) override;
};
pal_device_id_t GetAvailCaptureDevice();
std::shared_ptr<SoundTriggerEngine> HandleEngineLoad(uint8_t *sm_data,
int32_t sm_size, listen_model_indicator_enum type,
st_module_type_t module_type);
void AddEngine(std::shared_ptr<EngineCfg> engine_cfg);
void updateStreamAttributes();
int32_t UpdateDeviceConfig();
void UpdateModelId(st_module_type_t type);
int32_t LoadSoundModel(struct pal_st_sound_model *sm_data);
int32_t UnloadSoundModel();
int32_t UpdateSoundModel(struct pal_st_sound_model *sm_data);
int32_t SendRecognitionConfig(struct pal_st_recognition_config *config);
int32_t UpdateRecognitionConfig(struct pal_st_recognition_config *config);
bool compareRecognitionConfig(
const struct pal_st_recognition_config *current_config,
struct pal_st_recognition_config *new_config);
int32_t notifyClient(uint32_t detection);
static void TimerThread(StreamSoundTrigger& st_stream);
void PostDelayedStop();
void CancelDelayedStop();
void InternalStopRecognition();
int32_t DisconnectEvent(std::shared_ptr<StEventConfig> ev_cfg,
bool device_switch_event = false);
int32_t ConnectEvent(std::shared_ptr<StEventConfig> ev_cfg);
std::thread timer_thread_;
std::mutex timer_mutex_;
std::condition_variable timer_start_cond_;
std::condition_variable timer_wait_cond_;
bool timer_stop_waiting_;
bool exit_timer_thread_;
bool pending_stop_;
bool paused_;
bool device_opened_;
st_module_type_t model_type_;
void AddState(StState* state);
int32_t GetPreviousStateId();
int32_t ProcessInternalEvent(std::shared_ptr<StEventConfig> ev_cfg);
void GetUUID(class SoundTriggerUUID *uuid, struct pal_st_sound_model *sound_model);
void UpdateCaptureHandleInfo(bool start);
bool IsSameDeviceType(pal_device_id_t dev_id, pal_device_id_t curr_dev_id);
std::shared_ptr<VoiceUIPlatformInfo> vui_ptfm_info_;
std::shared_ptr<VUIStreamConfig> sm_cfg_;
SoundModelInfo* sm_info_;
std::vector<std::shared_ptr<EngineCfg>> engines_;
std::shared_ptr<SoundTriggerEngine> gsl_engine_;
std::shared_ptr<VoiceUIInterface> vui_intf_;
struct vui_intf_t vui_intf_handle_;
pal_st_sound_model_type_t sound_model_type_;
struct pal_st_sound_model *sm_config_;
struct pal_st_recognition_config *rec_config_;
uint32_t recognition_mode_;
uint32_t detection_state_;
uint32_t notification_state_;
pal_stream_callback callback_;
uint64_t cookie_;
PalRingBufferReader *reader_;
uint8_t *gsl_engine_model_;
uint32_t gsl_engine_model_size_;
uint8_t *gsl_conf_levels_;
uint32_t gsl_conf_levels_size_;
StState *st_idle_;
StState *st_loaded_;
StState *st_active;
StState *st_detected_;
StState *st_buffering_;
StState *st_ssr_;
StState *cur_state_;
StState *prev_state_;
st_state_id_t state_for_restore_;
std::map<uint32_t, StState*> st_states_;
std::shared_ptr<CaptureProfile> cap_prof_;
std::shared_ptr<Device> ec_rx_dev_;
uint32_t conf_levels_intf_version_;
std::vector<PalRingBufferReader *> reader_list_;
st_confidence_levels_info *st_conf_levels_;
st_confidence_levels_info_v2 *st_conf_levels_v2_;
bool capture_requested_;
uint32_t hist_buf_duration_;
uint32_t pre_roll_duration_;
uint32_t model_id_;
FILE *lab_fd_;
bool rejection_notified_;
ChronoSteadyClock_t transit_start_time_;
ChronoSteadyClock_t transit_end_time_;
// set to true only when mutex is not locked after callback
bool mutex_unlocked_after_cb_;
// flag to indicate whether we should update common capture profile in RM
bool common_cp_update_disable_;
bool second_stage_processing_;
bool is_backend_shared_;
/*
* Used for device switch case when client need to switch
* to specific device attributes instead of capture profile
* from resourcemanager xml.
*/
struct pal_device *dattr_specified_;
};
#endif // STREAMSOUNDTRIGGER_H_

View File

@@ -0,0 +1,54 @@
/*
* 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 STREAMULTRASOUND_H_
#define STREAMULTRASOUND_H_
#include "StreamCommon.h"
#include "ResourceManager.h"
#include "Device.h"
#include "Session.h"
class StreamUltraSound : public StreamCommon
{
public:
StreamUltraSound(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
const uint32_t no_of_devices, const struct modifier_kv *modifiers,
const uint32_t no_of_modifiers, const std::shared_ptr<ResourceManager> rm);
~StreamUltraSound();
int32_t setVolume( struct pal_volume_data *volume __unused) {return 0;}
int32_t setParameters(uint32_t param_id, void *payload);
int32_t stop();
private:
static void HandleCallBack(uint64_t hdl, uint32_t event_id,
void *data, uint32_t event_size);
void HandleEvent(uint32_t event_id, void *data, uint32_t event_size);
};
#endif//STREAMULTRASOUND_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,316 @@
/*
* 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 are provided under the following license:
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/
#define LOG_TAG "PAL: StreamACDB"
#include "StreamACDB.h"
#include "Session.h"
#include "kvh2xml.h"
#include "SessionAlsaPcm.h"
#include "ResourceManager.h"
#include "Device.h"
#include <unistd.h>
#include <chrono>
StreamACDB::StreamACDB(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
uint32_t instance_id, const std::shared_ptr<ResourceManager> rm)
{
mStreamMutex.lock();
uint32_t in_channels = 0, out_channels = 0;
uint32_t attribute_size = 0;
session = NULL;
mGainLevel = -1;
std::shared_ptr<Device> dev = nullptr;
mStreamAttr = (struct pal_stream_attributes *)nullptr;
mDevices.clear();
currentState = STREAM_IDLE;
//Modify cached values only at time of SSR down.
cachedState = STREAM_IDLE;
bool isDeviceConfigUpdated = false;
PAL_DBG(LOG_TAG, "Enter");
//TBD handle modifiers later
mNoOfModifiers = 0; //no_of_modifiers;
mModifiers = (struct modifier_kv *) (NULL);
if (!sattr || !dattr) {
PAL_ERR(LOG_TAG,"invalid arguments");
mStreamMutex.unlock();
throw std::runtime_error("invalid arguments");
}
attribute_size = sizeof(struct pal_stream_attributes);
mStreamAttr = (struct pal_stream_attributes *) calloc(1, attribute_size);
if (!mStreamAttr) {
PAL_ERR(LOG_TAG, "malloc for stream attributes failed %s", strerror(errno));
mStreamMutex.unlock();
throw std::runtime_error("failed to malloc for stream attributes");
}
ar_mem_cpy(mStreamAttr, sizeof(pal_stream_attributes), sattr, sizeof(pal_stream_attributes));
PAL_INFO(LOG_TAG, "Create new ACDBSession");
session = Session::makeACDBSession(rm, sattr);
if (!session) {
PAL_ERR(LOG_TAG, "session creation failed");
free(mStreamAttr);
mStreamMutex.unlock();
throw std::runtime_error("failed to create session object");
}
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit. state %d", currentState);
return;
}
int32_t StreamACDB::open()
{
return 0;
}
int32_t StreamACDB::close()
{
return 0;
}
StreamACDB::~StreamACDB()
{
if (mStreamAttr) {
free(mStreamAttr);
mStreamAttr = (struct pal_stream_attributes *)NULL;
}
if(mVolumeData) {
free(mVolumeData);
mVolumeData = (struct pal_volume_data *)NULL;
}
mDevices.clear();
delete session;
session = nullptr;
}
int32_t StreamACDB::start()
{
return 0;
}
int32_t StreamACDB::stop()
{
return 0;
}
int32_t StreamACDB::prepare()
{
return 0;
}
int32_t StreamACDB::setStreamAttributes(struct pal_stream_attributes *sattr)
{
int32_t status = -EINVAL;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK", session);
if (!sattr)
{
PAL_ERR(LOG_TAG, "NULL stream attributes sent");
goto exit;
}
memset(mStreamAttr, 0, sizeof(struct pal_stream_attributes));
mStreamMutex.lock();
ar_mem_cpy (mStreamAttr, sizeof(struct pal_stream_attributes), sattr,
sizeof(struct pal_stream_attributes));
mStreamMutex.unlock();
status = session->setConfig(this, MODULE, 0); //TODO:gkv or ckv or tkv need to pass
if (0 != status) {
PAL_ERR(LOG_TAG, "session setConfig failed with status %d", status);
goto exit;
}
PAL_DBG(LOG_TAG, "session setConfig successful");
exit:
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
//TBD: move this to Stream, why duplicate code?
int32_t StreamACDB::setVolume(struct pal_volume_data *volume)
{
return 0;
}
int32_t StreamACDB::read(struct pal_buffer* buf)
{
return 0;
}
int32_t StreamACDB::write(struct pal_buffer* buf)
{
return 0;
}
int32_t StreamACDB::registerCallBack(pal_stream_callback /*cb*/, uint64_t /*cookie*/)
{
return 0;
}
int32_t StreamACDB::getCallBack(pal_stream_callback * /*cb*/)
{
return 0;
}
int32_t StreamACDB::getParameters(uint32_t /*param_id*/, void ** /*payload*/)
{
return 0;
}
int32_t StreamACDB::setParameters(uint32_t param_id, void *payload)
{
return 0;
}
int32_t StreamACDB::mute_l(bool state)
{
return 0;
}
int32_t StreamACDB::mute(bool state)
{
return 0;
}
int32_t StreamACDB::pause_l()
{
return 0;
}
int32_t StreamACDB::pause()
{
return 0;
}
int32_t StreamACDB::resume_l()
{
return 0;
}
int32_t StreamACDB::resume()
{
return 0;
}
int32_t StreamACDB::flush()
{
return 0;
}
int32_t StreamACDB::addRemoveEffect(pal_audio_effect_t effect, bool enable)
{
return 0;
}
int32_t StreamACDB::setECRef(std::shared_ptr<Device> dev, bool is_enable)
{
return 0;
}
int32_t StreamACDB::setECRef_l(std::shared_ptr<Device> dev, bool is_enable)
{
return 0;
}
int32_t StreamACDB::ssrDownHandler()
{
return 0;
}
int32_t StreamACDB::ssrUpHandler()
{
return 0;
}
int32_t StreamACDB::createMmapBuffer(int32_t min_size_frames,
struct pal_mmap_buffer *info)
{
return 0;
}
int32_t StreamACDB::GetMmapPosition(struct pal_mmap_position *position)
{
return 0;
}
int32_t StreamACDB::rwACDBParam(pal_device_id_t palDeviceId,
pal_stream_type_t palStreamType, uint32_t sampleRate,
uint32_t instanceId,
void *payload, bool isParamWrite)
{
return session->rwACDBParamTunnel(payload, palDeviceId,
palStreamType, sampleRate, instanceId, isParamWrite, this);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,677 @@
/*
* 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 LOG_TAG "PAL: StreamCommon"
#define RXDIR 0
#define TXDIR 1
#include "StreamCommon.h"
#include "Session.h"
#include "kvh2xml.h"
#include "SessionAlsaPcm.h"
#include "ResourceManager.h"
#include "Device.h"
#include <unistd.h>
StreamCommon::StreamCommon(const struct pal_stream_attributes *sattr, struct pal_device *dattr,
const uint32_t no_of_devices, const struct modifier_kv *modifiers,
const uint32_t no_of_modifiers, const std::shared_ptr<ResourceManager> rm)
{
mStreamMutex.lock();
uint32_t in_channels = 0, out_channels = 0;
uint32_t attribute_size = 0;
if (PAL_CARD_STATUS_DOWN(rm->cardState)) {
PAL_ERR(LOG_TAG, "Error:Sound card offline/standby, can not create stream");
usleep(SSR_RECOVERY);
mStreamMutex.unlock();
throw std::runtime_error("Sound card offline/standby");
}
session = NULL;
mGainLevel = -1;
std::shared_ptr<Device> dev = nullptr;
mStreamAttr = (struct pal_stream_attributes *)nullptr;
mDevices.clear();
currentState = STREAM_IDLE;
//Modify cached values only at time of SSR down.
cachedState = STREAM_IDLE;
cookie_ = 0;
bool isDeviceConfigUpdated = false;
PAL_DBG(LOG_TAG, "Enter");
//TBD handle modifiers later
mNoOfModifiers = 0; //no_of_modifiers;
mModifiers = (struct modifier_kv *) (NULL);
std::ignore = modifiers;
std::ignore = no_of_modifiers;
if (!sattr) {
PAL_ERR(LOG_TAG,"Error:invalid arguments");
mStreamMutex.unlock();
throw std::runtime_error("invalid arguments");
}
attribute_size = sizeof(struct pal_stream_attributes);
mStreamAttr = (struct pal_stream_attributes *) calloc(1, attribute_size);
if (!mStreamAttr) {
PAL_ERR(LOG_TAG, "Error:malloc for stream attributes failed %s", strerror(errno));
mStreamMutex.unlock();
throw std::runtime_error("failed to malloc for stream attributes");
}
memcpy(mStreamAttr, sattr, sizeof(pal_stream_attributes));
if (mStreamAttr->in_media_config.ch_info.channels > PAL_MAX_CHANNELS_SUPPORTED) {
PAL_ERR(LOG_TAG,"Error:in_channels is invalid %d", in_channels);
mStreamAttr->in_media_config.ch_info.channels = PAL_MAX_CHANNELS_SUPPORTED;
}
if (mStreamAttr->out_media_config.ch_info.channels > PAL_MAX_CHANNELS_SUPPORTED) {
PAL_ERR(LOG_TAG,"Error:out_channels is invalid %d", out_channels);
mStreamAttr->out_media_config.ch_info.channels = PAL_MAX_CHANNELS_SUPPORTED;
}
PAL_VERBOSE(LOG_TAG, "Create new Session for stream type %d", sattr->type);
session = Session::makeSession(rm, sattr);
if (!session) {
PAL_ERR(LOG_TAG, "Error:session creation failed");
free(mStreamAttr);
mStreamMutex.unlock();
throw std::runtime_error("failed to create session object");
}
PAL_VERBOSE(LOG_TAG, "Create new Devices with no_of_devices - %d", no_of_devices);
/* update handset/speaker sample rate for UPD with shared backend */
if ((sattr->type == PAL_STREAM_ULTRASOUND ||
sattr->type == PAL_STREAM_SENSOR_PCM_RENDERER) && !rm->IsDedicatedBEForUPDEnabled()) {
struct pal_device devAttr = {};
struct pal_device_info inDeviceInfo;
pal_device_id_t upd_dev[] = {PAL_DEVICE_OUT_SPEAKER, PAL_DEVICE_OUT_HANDSET};
for (int i = 0; i < sizeof(upd_dev)/sizeof(upd_dev[0]); i++) {
devAttr.id = upd_dev[i];
dev = Device::getInstance(&devAttr, rm);
if (!dev)
continue;
rm->getDeviceInfo(devAttr.id, sattr->type, "", &inDeviceInfo);
dev->setSampleRate(inDeviceInfo.samplerate);
if (devAttr.id == PAL_DEVICE_OUT_HANDSET)
dev->setBitWidth(inDeviceInfo.bit_width);
}
}
for (int i = 0; i < no_of_devices; i++) {
//Check with RM if the configuration given can work or not
//for e.g., if incoming stream needs 24 bit device thats also
//being used by another stream, then the other stream should route
dev = Device::getInstance((struct pal_device *)&dattr[i] , rm);
if (!dev) {
PAL_ERR(LOG_TAG, "Error:Device creation failed");
free(mStreamAttr);
//TBD::free session too
mStreamMutex.unlock();
throw std::runtime_error("failed to create device object");
}
dev->insertStreamDeviceAttr(&dattr[i], this);
mPalDevices.push_back(dev);
mStreamMutex.unlock();
// streams with VA MIC is handled in rm::handleConcurrentStreamSwitch()
if (dattr[i].id != PAL_DEVICE_IN_HANDSET_VA_MIC &&
dattr[i].id != PAL_DEVICE_IN_HEADSET_VA_MIC)
isDeviceConfigUpdated = rm->updateDeviceConfig(&dev, &dattr[i], sattr);
mStreamMutex.lock();
if (isDeviceConfigUpdated)
PAL_VERBOSE(LOG_TAG, "Device config updated");
/* Create only update device attributes first time so update here using set*/
/* this will have issues if same device is being currently used by different stream */
mDevices.push_back(dev);
}
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit. state %d", currentState);
return;
}
StreamCommon::~StreamCommon()
{
pal_stream_type_t type = PAL_STREAM_MAX;
PAL_DBG(LOG_TAG, "Enter");
cachedState = STREAM_IDLE;
/* remove the device-stream attribute entry for the stopped stream */
for (int32_t i=0; i < mPalDevices.size(); i++)
mPalDevices[i]->removeStreamDeviceAttr(this);
if (mStreamAttr) {
type = mStreamAttr->type;
free(mStreamAttr);
mStreamAttr = (struct pal_stream_attributes *)NULL;
}
/* restore handset/speaker sample rate to default for UPD with shared backend */
if ((type == PAL_STREAM_ULTRASOUND ||
type == PAL_STREAM_SENSOR_PCM_RENDERER) && !rm->IsDedicatedBEForUPDEnabled()) {
std::shared_ptr<Device> dev = nullptr;
struct pal_device devAttr = {};
pal_device_id_t upd_dev[] = {PAL_DEVICE_OUT_SPEAKER, PAL_DEVICE_OUT_HANDSET};
for (int i = 0; i < sizeof(upd_dev)/sizeof(upd_dev[0]); i++) {
devAttr.id = upd_dev[i];
dev = Device::getInstance(&devAttr, rm);
if (!dev)
continue;
dev->setSampleRate(0);
dev->setBitWidth(0);
}
}
/*switch back to proper config if there is a concurrency and device is still running*/
for (int32_t i=0; i < mDevices.size(); i++)
rm->restoreDevice(mDevices[i]);
mDevices.clear();
mPalDevices.clear();
delete session;
session = nullptr;
PAL_DBG(LOG_TAG, "Exit");
}
int32_t StreamCommon::open()
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK device count - %zu", session,
mDevices.size());
mStreamMutex.lock();
if (PAL_CARD_STATUS_DOWN(rm->cardState)) {
PAL_ERR(LOG_TAG, "Error:Sound card offline/standby, can not open stream");
usleep(SSR_RECOVERY);
status = -EIO;
goto exit;
}
if (currentState == STREAM_IDLE) {
for (int32_t i = 0; i < mDevices.size(); i++) {
status = mDevices[i]->open();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:device open failed with status %d", status);
goto exit;
}
}
status = session->open(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:session open failed with status %d", status);
goto closeDevice;
}
PAL_VERBOSE(LOG_TAG, "session open successful");
currentState = STREAM_INIT;
PAL_DBG(LOG_TAG, "streamLL opened. state %d", currentState);
goto exit;
} else if (currentState == STREAM_INIT) {
PAL_INFO(LOG_TAG, "Stream is already opened, state %d", currentState);
status = 0;
goto exit;
} else {
PAL_ERR(LOG_TAG, "Error:Stream is not in correct state %d", currentState);
//TBD : which error code to return here.
status = -EINVAL;
goto exit;
}
closeDevice:
for (int32_t i = 0; i < mDevices.size(); i++) {
status = mDevices[i]->close();
if (0 != status) {
PAL_ERR(LOG_TAG, "device close is failed with status %d", status);
}
}
exit:
palStateEnqueue(this, PAL_STATE_OPENED, status);
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit ret %d", status)
return status;
}
//TBD: move this to Stream, why duplicate code?
int32_t StreamCommon::close()
{
int32_t status = 0;
mStreamMutex.lock();
if (currentState == STREAM_IDLE) {
PAL_INFO(LOG_TAG, "Stream is already closed");
mStreamMutex.unlock();
return status;
}
PAL_DBG(LOG_TAG, "Enter. session handle - %pK device count - %zu stream_type - %d state %d",
session, mDevices.size(), mStreamAttr->type, currentState);
if (currentState == STREAM_STARTED || currentState == STREAM_PAUSED) {
mStreamMutex.unlock();
status = stop();
if (0 != status)
PAL_ERR(LOG_TAG, "Error:stream stop failed. status %d", status);
mStreamMutex.lock();
}
rm->lockGraph();
status = session->close(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:session close failed with status %d", status);
}
for (int32_t i = 0; i < mDevices.size(); i++) {
status = mDevices[i]->close();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:device close is failed with status %d", status);
}
}
PAL_VERBOSE(LOG_TAG, "closed the devices successfully");
currentState = STREAM_IDLE;
rm->unlockGraph();
rm->checkAndSetDutyCycleParam();
palStateEnqueue(this, PAL_STATE_CLOSED, status);
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit. closed the stream successfully %d status %d",
currentState, status);
return status;
}
//TBD: move this to Stream, why duplicate code?
int32_t StreamCommon::start()
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK mStreamAttr->direction - %d state %d",
session, mStreamAttr->direction, currentState);
mStreamMutex.lock();
if (PAL_CARD_STATUS_DOWN(rm->cardState)) {
cachedState = STREAM_STARTED;
PAL_ERR(LOG_TAG, "Error:Sound card offline/standby. Update the cached state %d",
cachedState);
goto exit;
}
if (currentState == STREAM_INIT || currentState == STREAM_STOPPED) {
rm->lockGraph();
status = start_device();
if (0 != status) {
rm->unlockGraph();
goto exit;
}
PAL_VERBOSE(LOG_TAG, "device started successfully");
status = startSession();
if (0 != status) {
rm->unlockGraph();
goto exit;
}
rm->unlockGraph();
PAL_VERBOSE(LOG_TAG, "session start successful");
/*pcm_open and pcm_start done at once here,
*so directly jump to STREAM_STARTED state.
*/
currentState = STREAM_STARTED;
mStreamMutex.unlock();
rm->lockActiveStream();
mStreamMutex.lock();
for (int i = 0; i < mDevices.size(); i++) {
rm->registerDevice(mDevices[i], this);
}
rm->unlockActiveStream();
rm->checkAndSetDutyCycleParam();
} else if (currentState == STREAM_STARTED) {
PAL_INFO(LOG_TAG, "Stream already started, state %d", currentState);
} else {
PAL_ERR(LOG_TAG, "Error:Stream is not opened yet");
status = -EINVAL;
}
exit:
palStateEnqueue(this, PAL_STATE_STARTED, status);
PAL_DBG(LOG_TAG, "Exit. state %d", currentState);
mStreamMutex.unlock();
return status;
}
int32_t StreamCommon::start_device()
{
int32_t status = 0;
for (int32_t i=0; i < mDevices.size(); i++) {
status = mDevices[i]->start();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%s device start is failed with status %d",
GET_DIR_STR(mStreamAttr->direction), status);
}
}
return status;
}
int32_t StreamCommon::startSession()
{
int32_t status = 0, devStatus = 0;
status = session->prepare(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%s session prepare is failed with status %d",
GET_DIR_STR(mStreamAttr->direction), status);
goto session_fail;
}
PAL_VERBOSE(LOG_TAG, "session prepare successful");
status = session->start(this);
if (errno == -ENETRESET) {
if (PAL_CARD_STATUS_UP(rm->cardState)) {
PAL_ERR(LOG_TAG, "Error:Sound card offline/standby, informing RM");
rm->ssrHandler(CARD_STATUS_OFFLINE);
}
cachedState = STREAM_STARTED;
status = 0;
goto session_fail;
}
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%s session start is failed with status %d",
GET_DIR_STR(mStreamAttr->direction), status);
goto session_fail;
}
goto exit;
session_fail:
for (int32_t i=0; i < mDevices.size(); i++) {
devStatus = mDevices[i]->stop();
if (devStatus)
status = devStatus;
}
exit:
return status;
}
//TBD: move this to Stream, why duplicate code?
int32_t StreamCommon::stop()
{
int32_t status = 0;
mStreamMutex.lock();
PAL_DBG(LOG_TAG, "Enter. session handle - %pK mStreamAttr->direction - %d state %d",
session, mStreamAttr->direction, currentState);
if (currentState == STREAM_STARTED || currentState == STREAM_PAUSED) {
mStreamMutex.unlock();
rm->lockActiveStream();
mStreamMutex.lock();
currentState = STREAM_STOPPED;
for (int i = 0; i < mDevices.size(); i++) {
rm->deregisterDevice(mDevices[i], this);
}
rm->unlockActiveStream();
PAL_VERBOSE(LOG_TAG, "In %s, device count - %zu",
GET_DIR_STR(mStreamAttr->direction), mDevices.size());
rm->lockGraph();
status = session->stop(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%s session stop failed with status %d",
GET_DIR_STR(mStreamAttr->direction), status);
}
PAL_VERBOSE(LOG_TAG, "session stop successful");
for (int32_t i=0; i < mDevices.size(); i++) {
status = mDevices[i]->stop();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%s device stop failed with status %d",
GET_DIR_STR(mStreamAttr->direction), status);
}
}
rm->unlockGraph();
PAL_VERBOSE(LOG_TAG, "devices stop successful");
} else if (currentState == STREAM_STOPPED || currentState == STREAM_IDLE) {
PAL_INFO(LOG_TAG, "Stream is already in Stopped state %d", currentState);
} else {
PAL_ERR(LOG_TAG, "Error:Stream should be in start/pause state, %d", currentState);
status = -EINVAL;
}
palStateEnqueue(this, PAL_STATE_STOPPED, status);
PAL_DBG(LOG_TAG, "Exit. status %d, state %d", status, currentState);
mStreamMutex.unlock();
return status;
}
int32_t StreamCommon::setVolume(struct pal_volume_data *volume)
{
int32_t status = 0;
uint8_t volSize = 0;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK", session);
if (!volume || (volume->no_of_volpair == 0)) {
PAL_ERR(LOG_TAG, "Invalid arguments");
status = -EINVAL;
goto exit;
}
// if already allocated free and reallocate
if (mVolumeData) {
free(mVolumeData);
mVolumeData = NULL;
}
volSize = sizeof(uint32_t) + (sizeof(struct pal_channel_vol_kv) * (volume->no_of_volpair));
mVolumeData = (struct pal_volume_data *)calloc(1, volSize);
if (!mVolumeData) {
status = -ENOMEM;
PAL_ERR(LOG_TAG, "failed to calloc for volume data");
goto exit;
}
/* Allow caching of stream volume as part of mVolumeData
* till the pcm_open is not done or if sound card is offline.
*/
ar_mem_cpy(mVolumeData, volSize, volume, volSize);
for (int32_t i=0; i < (mVolumeData->no_of_volpair); i++) {
PAL_INFO(LOG_TAG, "Volume payload mask:%x vol:%f",
(mVolumeData->volume_pair[i].channel_mask), (mVolumeData->volume_pair[i].vol));
}
if (a2dpMuted) {
PAL_DBG(LOG_TAG, "a2dp muted, just cache volume update");
goto exit;
}
if ((rm->cardState == CARD_STATUS_ONLINE) && (currentState != STREAM_IDLE)
&& (currentState != STREAM_INIT)) {
status = session->setConfig(this, CALIBRATION, TAG_STREAM_VOLUME);
if (0 != status) {
PAL_ERR(LOG_TAG, "session setConfig for VOLUME_TAG failed with status %d",
status);
goto exit;
}
}
exit:
if (volume) {
PAL_DBG(LOG_TAG, "Exit. Volume payload No.of vol pair:%d ch mask:%x gain:%f",
(volume->no_of_volpair), (volume->volume_pair->channel_mask),
(volume->volume_pair->vol));
}
return status;
}
int32_t StreamCommon::registerCallBack(pal_stream_callback cb, uint64_t cookie)
{
callback_ = cb;
cookie_ = cookie;
PAL_VERBOSE(LOG_TAG, "callback_ = %pK", callback_);
return 0;
}
int32_t StreamCommon::getTagsWithModuleInfo(size_t *size, uint8_t *payload)
{
int32_t status = -EINVAL;
PAL_DBG(LOG_TAG, "Enter");
if (!payload) {
PAL_ERR(LOG_TAG, "payload is NULL");
goto exit;
}
if (session)
status = session->getTagsWithModuleInfo(this, size, payload);
else
PAL_ERR(LOG_TAG, "session handle is NULL");
exit:
return status;
}
int32_t StreamCommon::ssrDownHandler()
{
int32_t status = 0;
mStreamMutex.lock();
if (false == isStreamSSRDownFeasibile()) {
mStreamMutex.unlock();
goto skip_down_handling;
}
/* Updating cached state here only if it's STREAM_IDLE,
* Otherwise we can assume it is updated by hal thread
* already.
*/
if (cachedState == STREAM_IDLE)
cachedState = currentState;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK cached State %d",
session, cachedState);
switch (currentState) {
case STREAM_INIT:
case STREAM_STOPPED:
mStreamMutex.unlock();
status = close();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:stream close failed. status %d", status);
goto exit;
}
break;
case STREAM_STARTED:
case STREAM_PAUSED:
mStreamMutex.unlock();
rm->unlockActiveStream();
status = stop();
rm->lockActiveStream();
if (0 != status)
PAL_ERR(LOG_TAG, "Error:stream stop failed. status %d", status);
status = close();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:stream close failed. status %d", status);
goto exit;
}
break;
default:
PAL_ERR(LOG_TAG, "Error:stream state is %d, nothing to handle", currentState);
mStreamMutex.unlock();
goto exit;
}
exit :
currentState = STREAM_IDLE;
skip_down_handling :
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamCommon::ssrUpHandler()
{
int32_t status = 0;
mStreamMutex.lock();
PAL_DBG(LOG_TAG, "Enter. session handle - %pK state %d",
session, cachedState);
if (skipSSRHandling) {
skipSSRHandling = false;
mStreamMutex.unlock();
goto exit;
}
switch (cachedState) {
case STREAM_INIT:
mStreamMutex.unlock();
status = open();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:stream open failed. status %d", status);
goto exit;
}
break;
case STREAM_STARTED:
case STREAM_PAUSED:
{
mStreamMutex.unlock();
status = open();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:stream open failed. status %d", status);
goto exit;
}
rm->unlockActiveStream();
status = start();
rm->lockActiveStream();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:stream start failed. status %d", status);
goto exit;
}
/* For scenario when we get SSR down while handling SSR up,
* status will be 0, so we need to have this additonal check
* to keep the cached state as STREAM_STARTED.
*/
if (currentState != STREAM_STARTED) {
goto exit;
}
}
break;
default:
mStreamMutex.unlock();
PAL_ERR(LOG_TAG, "Error:stream not in correct state to handle %d", cachedState);
break;
}
cachedState = STREAM_IDLE;
exit :
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2022, 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 are provided under the following license:
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#define LOG_TAG "StreamCommonProxy"
#include "StreamCommonProxy.h"
#include "Session.h"
#include "SessionAlsaPcm.h"
#include "ResourceManager.h"
#include <unistd.h>
StreamCommonProxy::StreamCommonProxy(const struct pal_stream_attributes *sattr __unused,
struct pal_device *dattr __unused, const uint32_t no_of_devices __unused,
const struct modifier_kv *modifiers __unused, const uint32_t no_of_modifiers __unused,
const std::shared_ptr<ResourceManager> rm) :
StreamCommon(sattr,dattr,no_of_devices,modifiers,no_of_modifiers,rm)
{
//registering for a callback
rm->registerStream(this);
}
StreamCommonProxy::~StreamCommonProxy() {
rm->deregisterStream(this);
}
int32_t StreamCommonProxy::getParameters(uint32_t param_id, void **payload)
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "get parameter %u", param_id);
switch (param_id) {
case PAL_PARAM_ID_SVA_WAKEUP_MODULE_VERSION:
{
status = session->getParameters(this, 0, param_id, payload);
if (status)
PAL_ERR(LOG_TAG, "Error:getParam failed with %d",
status);
break;
}
default:
PAL_ERR(LOG_TAG, "Error:Unsupported param id %u", param_id);
status = -EINVAL;
break;
}
PAL_DBG(LOG_TAG, "get parameter status %d", status);
return status;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,110 @@
/*
* 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.
*/
#define LOG_TAG "StreamContextProxy"
#include "StreamContextProxy.h"
#include "Session.h"
#include "SessionAlsaPcm.h"
#include "ResourceManager.h"
#include <unistd.h>
StreamContextProxy::StreamContextProxy(const struct pal_stream_attributes *sattr __unused,
struct pal_device *dattr __unused, const uint32_t no_of_devices __unused,
const struct modifier_kv *modifiers __unused, const uint32_t no_of_modifiers __unused,
const std::shared_ptr<ResourceManager> rm) :
StreamCommon(sattr,dattr,no_of_devices,modifiers,no_of_modifiers,rm)
{
//registering for a callback
session->registerCallBack((session_callback)HandleCallBack, (uint64_t) this);
rm->registerStream(this);
}
StreamContextProxy::~StreamContextProxy() {
rm->deregisterStream(this);
}
int32_t StreamContextProxy::setParameters(uint32_t param_id, void *payload)
{
int32_t status = 0;
if (!payload)
{
status = -EINVAL;
PAL_ERR(LOG_TAG, "wrong params");
goto error;
}
PAL_DBG(LOG_TAG, "start, set parameter %u, session handle - %p", param_id, session);
mStreamMutex.lock();
// Stream may not know about tags, so use setParameters instead of setConfig
if (currentState == STREAM_IDLE) {
PAL_ERR(LOG_TAG, "Invalid stream state: IDLE for param ID: %d", param_id);
mStreamMutex.unlock();
return -EINVAL;
}
switch (param_id) {
case PAL_PARAM_ID_MODULE_CONFIG:
{
status = session->setParameters(this, 0, param_id, payload);
if (status)
PAL_ERR(LOG_TAG, "Error:setParam for volume boost failed with %d",
status);
break;
}
default:
PAL_ERR(LOG_TAG, "Error:Unsupported param id %u", param_id);
status = -EINVAL;
break;
}
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "exit, session parameter %u set with status %d", param_id, status);
error:
return status;
}
void StreamContextProxy::ParseASPSEventPayload(uint32_t event_id,
uint32_t event_size, void *data) {
if (callback_) {
PAL_INFO(LOG_TAG, "Notify detection event to client");
callback_((pal_stream_handle_t *)this, event_id, (uint32_t *)data,
event_size, cookie_);
}
}
void StreamContextProxy::HandleCallBack(uint64_t hdl, uint32_t event_id,
void *data, uint32_t event_size) {
StreamContextProxy *ContextProxy = nullptr;
PAL_DBG(LOG_TAG, "Enter, event detected on SPF, event id = 0x%x", event_id);
ContextProxy = (StreamContextProxy *)hdl;
ContextProxy->ParseASPSEventPayload(event_id, event_size, data);
PAL_DBG(LOG_TAG, "Exit");
}

View File

@@ -0,0 +1,482 @@
/*
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/
#define LOG_TAG "PAL: StreamHaptics"
#include "StreamHaptics.h"
#include "Session.h"
#include "SessionAlsaPcm.h"
#include "ResourceManager.h"
#include "Device.h"
#include <unistd.h>
#include "rx_haptics_api.h"
#include "wsa_haptics_vi_api.h"
StreamHaptics::StreamHaptics(const struct pal_stream_attributes *sattr, struct pal_device *dattr __unused,
const uint32_t no_of_devices __unused, const struct modifier_kv *modifiers __unused,
const uint32_t no_of_modifiers __unused, const std::shared_ptr<ResourceManager> rm):
StreamPCM(sattr,dattr,no_of_devices,modifiers,no_of_modifiers,rm)
{
session->registerCallBack((session_callback)HandleCallBack,((uint64_t) this));
}
StreamHaptics::~StreamHaptics()
{
}
int32_t StreamHaptics::setParameters(uint32_t param_id, void *payload)
{
int32_t status = -1;
std::vector <Stream *> activeStreams;
struct pal_stream_attributes ActivesAttr;
Stream *stream = nullptr;
if (!payload)
{
status = -EINVAL;
PAL_ERR(LOG_TAG, "invalid params");
goto error;
}
PAL_DBG(LOG_TAG, "Enter, set parameter %u", param_id);
status = rm->getActiveStream_l(activeStreams, mDevices[0]);
if ((0 != status) || (activeStreams.size() == 0 )) {
PAL_DBG(LOG_TAG, "No Haptics stream is active");
goto error;
} else {
/* If Setparam for touch haptics is called when Ringtone Haptics is active
skip the Setparam for touch haptics*/
PAL_DBG(LOG_TAG, "activestreams size %d",activeStreams.size());
for (int i = 0; i<activeStreams.size(); i++) {
stream = static_cast<Stream *>(activeStreams[i]);
stream->getStreamAttributes(&ActivesAttr);
if (ActivesAttr.info.opt_stream_info.haptics_type == PAL_STREAM_HAPTICS_RINGTONE) {
status = -EINVAL;
goto error;
} else
continue;
}
}
mStreamMutex.lock();
// Stream may not know about tags, so use setParameters instead of setConfig
switch (param_id) {
case PAL_PARAM_ID_HAPTICS_CNFG:
{
status = session->setParameters(NULL, 0, param_id, payload);
if (status)
PAL_ERR(LOG_TAG, "Error:%d, Failed to setParam for registering an event",
status);
break;
}
case PARAM_ID_HAPTICS_WAVE_DESIGNER_STOP_PARAM:
{
status = session->setParameters(NULL, 0, param_id, payload);
if (status)
PAL_ERR(LOG_TAG, "Error:%d, Failed to setParam for registering an event",
status);
break;
}
case PARAM_ID_HAPTICS_WAVE_DESIGNER_UPDATE_PARAM:
{
status = session->setParameters(NULL, 0, param_id, payload);
if (status)
PAL_ERR(LOG_TAG, "Error:%d, Failed to setParam", status);
break;
}
case PARAM_ID_HAPTICS_EX_VI_PERSISTENT:
{
status = mDevices[0]->setParameter(param_id, nullptr);
if (status)
PAL_ERR(LOG_TAG, "Error:%d, Failed to setParam", status);
break;
}
default:
PAL_ERR(LOG_TAG, "Error:Unsupported param id %u", param_id);
status = -EINVAL;
break;
}
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "exit, session parameter %u set with status %d", param_id, status);
error:
return status;
}
int32_t StreamHaptics::start()
{
int32_t status = 0, devStatus = 0, cachedStatus = 0;
int32_t tmp = 0;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK mStreamAttr->direction - %d state %d",
session, mStreamAttr->direction, currentState);
/* check for haptic concurrency*/
if (rm->IsHapticsThroughWSA())
HandleHapticsConcurrency(mStreamAttr);
mStreamMutex.lock();
if (rm->cardState == CARD_STATUS_OFFLINE) {
cachedState = STREAM_STARTED;
PAL_ERR(LOG_TAG, "Sound card offline. Update the cached state %d",
cachedState);
goto exit;
}
if (currentState == STREAM_INIT || currentState == STREAM_STOPPED) {
switch (mStreamAttr->direction) {
case PAL_AUDIO_OUTPUT:
PAL_VERBOSE(LOG_TAG, "Inside PAL_AUDIO_OUTPUT device count - %zu",
mDevices.size());
rm->lockGraph();
/* Any device start success will be treated as positive status.
* This allows stream be played even if one of devices failed to start.
*/
status = -EINVAL;
for (int32_t i=0; i < mDevices.size(); i++) {
devStatus = mDevices[i]->start();
if (devStatus == 0) {
status = 0;
} else {
cachedStatus = devStatus;
tmp = session->disconnectSessionDevice(this, mStreamAttr->type, mDevices[i]);
if (0 != tmp) {
PAL_ERR(LOG_TAG, "disconnectSessionDevice failed:%d", tmp);
}
tmp = mDevices[i]->close();
if (0 != tmp) {
PAL_ERR(LOG_TAG, "device close failed with status %d", tmp);
}
mDevices.erase(mDevices.begin() + i);
i--;
}
}
if (0 != status) {
status = cachedStatus;
PAL_ERR(LOG_TAG, "Rx device start failed with status %d", status);
rm->unlockGraph();
goto exit;
} else {
PAL_VERBOSE(LOG_TAG, "devices started successfully");
}
status = session->prepare(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "Rx session prepare is failed with status %d",
status);
rm->unlockGraph();
goto session_fail;
}
PAL_VERBOSE(LOG_TAG, "session prepare successful");
status = session->start(this);
if (errno == -ENETRESET) {
if (rm->cardState != CARD_STATUS_OFFLINE) {
PAL_ERR(LOG_TAG, "Sound card offline, informing RM");
rm->ssrHandler(CARD_STATUS_OFFLINE);
}
cachedState = STREAM_STARTED;
/* Returning status 0, hal shouldn't be
* informed of failure because we have cached
* the state and will start from STARTED state
* during SSR up Handling.
*/
status = 0;
rm->unlockGraph();
goto session_fail;
}
if (0 != status) {
PAL_ERR(LOG_TAG, "Rx session start is failed with status %d",
status);
rm->unlockGraph();
goto session_fail;
}
PAL_VERBOSE(LOG_TAG, "session start successful");
rm->unlockGraph();
break;
default:
status = -EINVAL;
PAL_ERR(LOG_TAG, "Stream type is not supported, status %d", status);
break;
}
for (int i = 0; i < mDevices.size(); i++) {
rm->registerDevice(mDevices[i], this);
}
/*pcm_open and pcm_start done at once here,
*so directly jump to STREAM_STARTED state.
*/
currentState = STREAM_STARTED;
} else if (currentState == STREAM_STARTED) {
PAL_INFO(LOG_TAG, "Stream already started, state %d", currentState);
goto exit;
} else {
PAL_ERR(LOG_TAG, "Stream is not opened yet");
status = -EINVAL;
goto exit;
}
goto exit;
session_fail:
for (int32_t i=0; i < mDevices.size(); i++) {
devStatus = mDevices[i]->stop();
if (devStatus)
status = devStatus;
rm->deregisterDevice(mDevices[i], this);
}
exit:
palStateEnqueue(this, PAL_STATE_STARTED, status);
PAL_DBG(LOG_TAG, "Exit. state %d, status %d", currentState, status);
mStreamMutex.unlock();
return status;
}
int32_t StreamHaptics::HandleHapticsConcurrency(struct pal_stream_attributes *sattr)
{
std::vector <Stream *> activeStreams;
struct pal_stream_attributes ActivesAttr;
Stream *stream = nullptr;
param_id_haptics_wave_designer_wave_designer_stop_param_t HapticsStopParam;
pal_param_payload *param_payload = nullptr;
Session *ActHapticsSession = nullptr;
struct param_id_haptics_wave_designer_state event_info;
int status = 0;
/* if input stream and the priority stream is same,
go ahead and enable the stream */
status = rm->getActiveStream_l(activeStreams, mDevices[0]);
if ((0 != status) || (activeStreams.size() <= 1)) {
PAL_DBG(LOG_TAG, "No Active Haptics stream is present.");
goto exit;
} else {
/* If incoming stream is Ringtone Haptics and active stream is Touch
stop the Touch haptics and start Ringtone*/
PAL_DBG(LOG_TAG, "activestreams size %d",activeStreams.size());
for (int i = 0; i<activeStreams.size(); i++) {
stream = static_cast<Stream *>(activeStreams[i]);
stream->getStreamAttributes(&ActivesAttr);
if (ActivesAttr.info.opt_stream_info.haptics_type == PAL_STREAM_HAPTICS_TOUCH) {
/* Set the stop haptics param for touch haptics. */
param_payload = (pal_param_payload *) calloc (1,
sizeof(pal_param_payload) +
sizeof(param_id_haptics_wave_designer_wave_designer_stop_param_t));
if (!param_payload)
goto exit;
HapticsStopParam.channel_mask = 1;
param_payload->payload_size =
sizeof(param_id_haptics_wave_designer_wave_designer_stop_param_t);
memcpy(param_payload->payload, &HapticsStopParam, param_payload->payload_size);
stream->getAssociatedSession(&ActHapticsSession);
status = ActHapticsSession->setParameters(NULL, 0,
PARAM_ID_HAPTICS_WAVE_DESIGNER_STOP_PARAM,
(void*)param_payload);
if (status)
PAL_ERR(LOG_TAG, "Error:%d, Stop SetParam is Failed", status);
}
}
}
exit:
return status;
}
int32_t StreamHaptics::registerCallBack(pal_stream_callback cb, uint64_t cookie)
{
callback_ = cb;
cookie_ = cookie;
PAL_VERBOSE(LOG_TAG, "callback_ = %pK", callback_);
return 0;
}
void StreamHaptics::HandleEvent(uint32_t event_id, void *data, uint32_t event_size) {
struct param_id_haptics_wave_designer_state *event_info = nullptr;
event_info = (struct param_id_haptics_wave_designer_state *)data;
uint32_t event_type[2];
event_type[0] = (uint16_t)event_info->state[0];
event_type[1] = (uint16_t)event_info->state[1];
PAL_INFO(LOG_TAG, "event received with value for vib 1 - %d vib 2- %d",
event_type[0], event_type[1]);
if (callback_) {
PAL_INFO(LOG_TAG, "Notify detection event to client");
callback_((pal_stream_handle_t *)this, event_id, event_type,
event_size, cookie_);
}
}
void StreamHaptics::HandleCallBack(uint64_t hdl, uint32_t event_id,
void *data, uint32_t event_size) {
StreamHaptics *StreamHAPTICS = nullptr;
PAL_DBG(LOG_TAG, "Enter, event detected on SPF, event id = 0x%x, event size =%d",
event_id, event_size);
// Handle event form DSP
if (event_id == EVENT_ID_WAVEFORM_STATE) {
StreamHAPTICS = (StreamHaptics *)hdl;
StreamHAPTICS->HandleEvent(event_id, data, event_size);
}
PAL_DBG(LOG_TAG, "Exit");
}
int32_t StreamHaptics::ssrDownHandler()
{
int32_t status = 0;
mStreamMutex.lock();
if (false == isStreamSSRDownFeasibile()) {
mStreamMutex.unlock();
goto skip_down_handling;
}
/* Updating cached state here only if it's STREAM_IDLE,
* Otherwise we can assume it is updated by hal thread
* already.
*/
if (cachedState == STREAM_IDLE)
cachedState = currentState;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK cached State %d",
session, cachedState);
if (currentState == STREAM_INIT || currentState == STREAM_STOPPED) {
mStreamMutex.unlock();
status = close();
if (0 != status) {
PAL_ERR(LOG_TAG, "stream close failed. status %d", status);
goto exit;
}
} else if (currentState == STREAM_STARTED || currentState == STREAM_PAUSED) {
mStreamMutex.unlock();
rm->unlockActiveStream();
status = stop();
rm->lockActiveStream();
if (0 != status)
PAL_ERR(LOG_TAG, "stream stop failed. status %d", status);
status = close();
if (0 != status) {
PAL_ERR(LOG_TAG, "stream close failed. status %d", status);
goto exit;
}
} else {
PAL_ERR(LOG_TAG, "stream state is %d, nothing to handle", currentState);
mStreamMutex.unlock();
goto exit;
}
exit :
currentState = STREAM_IDLE;
skip_down_handling :
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamHaptics::ssrUpHandler()
{
int32_t status = 0;
if (mStreamAttr->info.opt_stream_info.haptics_type != PAL_STREAM_HAPTICS_RINGTONE)
goto skip_up_handling;
mStreamMutex.lock();
PAL_DBG(LOG_TAG, "Enter. session handle - %pK state %d",
session, cachedState);
if (skipSSRHandling) {
skipSSRHandling = false;
mStreamMutex.unlock();
goto skip_up_handling;
}
if (cachedState == STREAM_INIT) {
mStreamMutex.unlock();
status = open();
if (0 != status) {
PAL_ERR(LOG_TAG, "stream open failed. status %d", status);
goto exit;
}
} else if (cachedState == STREAM_STARTED) {
mStreamMutex.unlock();
status = open();
if (0 != status) {
PAL_ERR(LOG_TAG, "stream open failed. status %d", status);
goto exit;
}
rm->unlockActiveStream();
status = start();
rm->lockActiveStream();
if (0 != status) {
PAL_ERR(LOG_TAG, "stream start failed. status %d", status);
goto exit;
}
/* For scenario when we get SSR down while handling SSR up,
* status will be 0, so we need to have this additonal check
* to keep the cached state as STREAM_STARTED.
*/
if (currentState != STREAM_STARTED) {
goto exit;
}
} else if (cachedState == STREAM_PAUSED) {
mStreamMutex.unlock();
status = open();
if (0 != status) {
PAL_ERR(LOG_TAG, "stream open failed. status %d", status);
goto exit;
}
rm->unlockActiveStream();
status = start();
rm->lockActiveStream();
if (0 != status) {
PAL_ERR(LOG_TAG, "stream start failed. status %d", status);
goto exit;
}
if (currentState != STREAM_STARTED)
goto exit;
status = pause();
if (0 != status) {
PAL_ERR(LOG_TAG, "stream set pause failed. status %d", status);
goto exit;
}
} else {
mStreamMutex.unlock();
PAL_ERR(LOG_TAG, "stream not in correct state to handle %d", cachedState);
}
exit :
cachedState = STREAM_IDLE;
skip_up_handling :
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,657 @@
/*
* Copyright (c) 2020-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 are provided under the following license:
*
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#define LOG_TAG "StreamNonTunnel"
#include "Session.h"
#include "kvh2xml.h"
#include "SessionGsl.h"
#include "ResourceManager.h"
#include <unistd.h>
static void handleSessionCallBack(uint64_t hdl, uint32_t event_id, void *data,
uint32_t event_size)
{
Stream *s = NULL;
s = reinterpret_cast<Stream *>(hdl);
if (s->streamCb)
s->streamCb(reinterpret_cast<pal_stream_handle_t *>(s), event_id, (uint32_t *)data,
event_size, s->cookie);
}
StreamNonTunnel::StreamNonTunnel(const struct pal_stream_attributes *sattr, struct pal_device *dattr __unused,
const uint32_t no_of_devices __unused, const struct modifier_kv *modifiers,
const uint32_t no_of_modifiers, const std::shared_ptr<ResourceManager> rm)
{
mStreamMutex.lock();
uint32_t in_channels = 0, out_channels = 0;
uint32_t attribute_size = 0;
if (!sattr) {
PAL_ERR(LOG_TAG,"invalid arguments");
mStreamMutex.unlock();
throw std::runtime_error("invalid arguments");
}
if (PAL_CARD_STATUS_DOWN(rm->cardState)) {
PAL_ERR(LOG_TAG, "Sound card offline/standby, can not create stream");
usleep(SSR_RECOVERY);
mStreamMutex.unlock();
throw std::runtime_error("Sound card offline/standby");
}
session = NULL;
mStreamAttr = (struct pal_stream_attributes *)nullptr;
inMaxMetadataSz = 0;
outMaxMetadataSz = 0;
mDevices.clear();
currentState = STREAM_IDLE;
ssrInNTMode = false;
//Modify cached values only at time of SSR down.
cachedState = STREAM_IDLE;
PAL_DBG(LOG_TAG, "Enter");
//TBD handle modifiers later
mNoOfModifiers = 0; //no_of_modifiers;
mModifiers = (struct modifier_kv *) (NULL);
std::ignore = modifiers;
std::ignore = no_of_modifiers;
attribute_size = sizeof(struct pal_stream_attributes);
mStreamAttr = (struct pal_stream_attributes *) calloc(1, attribute_size);
if (!mStreamAttr) {
PAL_ERR(LOG_TAG, "malloc for stream attributes failed %s", strerror(errno));
mStreamMutex.unlock();
throw std::runtime_error("failed to malloc for stream attributes");
}
ar_mem_cpy(mStreamAttr, sizeof(pal_stream_attributes), sattr, sizeof(pal_stream_attributes));
if (mStreamAttr->in_media_config.ch_info.channels > PAL_MAX_CHANNELS_SUPPORTED) {
PAL_ERR(LOG_TAG,"in_channels is invalid %d", in_channels);
mStreamAttr->in_media_config.ch_info.channels = PAL_MAX_CHANNELS_SUPPORTED;
}
if (mStreamAttr->out_media_config.ch_info.channels > PAL_MAX_CHANNELS_SUPPORTED) {
PAL_ERR(LOG_TAG,"out_channels is invalid %d", out_channels);
mStreamAttr->out_media_config.ch_info.channels = PAL_MAX_CHANNELS_SUPPORTED;
}
PAL_VERBOSE(LOG_TAG, "Create new Session");
session = Session::makeSession(rm, sattr);
if (!session) {
PAL_ERR(LOG_TAG, "session creation failed");
free(mStreamAttr);
mStreamMutex.unlock();
throw std::runtime_error("failed to create session object");
}
session->registerCallBack(handleSessionCallBack, (uint64_t)this);
mStreamMutex.unlock();
rm->registerStream(this);
PAL_DBG(LOG_TAG, "Exit. state %d", currentState);
return;
}
StreamNonTunnel::~StreamNonTunnel()
{
rm->resetStreamInstanceID(this);
rm->deregisterStream(this);
if (mStreamAttr) {
free(mStreamAttr);
mStreamAttr = (struct pal_stream_attributes *)NULL;
}
delete session;
session = nullptr;
}
int32_t StreamNonTunnel::open()
{
int32_t status = 0;
mStreamMutex.lock();
if ((PAL_CARD_STATUS_DOWN(rm->cardState))
|| ssrInNTMode == true) {
PAL_ERR(LOG_TAG, "Sound card offline/standby, can not open stream");
usleep(SSR_RECOVERY);
status = -ENETRESET;
goto exit;
}
if (currentState == STREAM_IDLE) {
PAL_VERBOSE(LOG_TAG, "Enter. session handle - %pK", session);
status = session->open(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "session open failed with status %d", status);
goto exit;
}
PAL_VERBOSE(LOG_TAG, "session open successful");
currentState = STREAM_INIT;
PAL_DBG(LOG_TAG, "Exit. streamLL opened. state %d", currentState);
} else if (currentState == STREAM_INIT) {
PAL_INFO(LOG_TAG, "Stream is already opened, state %d", currentState);
status = 0;
goto exit;
} else {
PAL_ERR(LOG_TAG, "Stream is not in correct state %d", currentState);
//TBD : which error code to return here.
status = -EINVAL;
goto exit;
}
exit:
palStateEnqueue(this, PAL_STATE_OPENED, status);
mStreamMutex.unlock();
return status;
}
int32_t StreamNonTunnel::close()
{
int32_t status = 0;
mStreamMutex.lock();
PAL_INFO(LOG_TAG, "Enter. session handle - %pK state %d",
session, currentState);
if (currentState == STREAM_IDLE) {
PAL_VERBOSE(LOG_TAG, "closed the devices successfully");
goto exit;
} else if (currentState == STREAM_STARTED || currentState == STREAM_PAUSED) {
status = stop();
if (0 != status)
PAL_ERR(LOG_TAG, "stream stop failed. status %d", status);
}
status = session->close(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "session close failed with status %d", status);
}
exit:
currentState = STREAM_IDLE;
palStateEnqueue(this, PAL_STATE_CLOSED, status);
mStreamMutex.unlock();
PAL_INFO(LOG_TAG, "Exit. closed the stream successfully %d status %d",
currentState, status);
return status;
}
//TBD: move this to Stream, why duplicate code?
int32_t StreamNonTunnel::start()
{
int32_t status = 0;
mStreamMutex.lock();
if ((PAL_CARD_STATUS_DOWN(rm->cardState))
|| ssrInNTMode == true) {
PAL_ERR(LOG_TAG, "Sound card offline/standby currentState %d",
currentState);
status = -ENETRESET;
goto exit;
}
PAL_DBG(LOG_TAG, "Enter. session handle - %pK mStreamAttr->direction - %d state %d",
session, mStreamAttr->direction, currentState);
if (currentState == STREAM_INIT || currentState == STREAM_STOPPED ||
currentState == STREAM_SUSPENDED) {
status = session->prepare(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "Rx session prepare is failed with status %d",
status);
goto exit;
}
PAL_VERBOSE(LOG_TAG, "session prepare successful");
status = session->start(this);
if (status == -ENETRESET &&
(PAL_CARD_STATUS_UP(rm->cardState))) {
PAL_ERR(LOG_TAG, "Sound card offline/standby, informing RM");
rm->ssrHandler(CARD_STATUS_OFFLINE);
goto exit;
}
if (0 != status) {
PAL_ERR(LOG_TAG, "Rx session start is failed with status %d",
status);
goto exit;
}
PAL_VERBOSE(LOG_TAG, "session start successful");
currentState = STREAM_STARTED;
} else if (currentState == STREAM_STARTED) {
PAL_INFO(LOG_TAG, "Stream already started, state %d", currentState);
goto exit;
} else {
PAL_ERR(LOG_TAG, "Stream is not opened yet");
status = -EINVAL;
goto exit;
}
PAL_DBG(LOG_TAG, "Exit. state %d", currentState);
exit:
palStateEnqueue(this, PAL_STATE_STARTED, status);
mStreamMutex.unlock();
return status;
}
//TBD: move this to Stream, why duplicate code?
int32_t StreamNonTunnel::stop()
{
int32_t status = 0;
mStreamMutex.lock();
PAL_DBG(LOG_TAG, "Enter. session handle - %pK mStreamAttr->direction - %d state %d",
session, mStreamAttr->direction, currentState);
if (currentState == STREAM_STARTED || currentState == STREAM_PAUSED) {
status = session->stop(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "Rx session stop failed with status %d", status);
}
PAL_VERBOSE(LOG_TAG, "session stop successful");
currentState = STREAM_STOPPED;
} else if (currentState == STREAM_STOPPED || currentState == STREAM_IDLE) {
PAL_INFO(LOG_TAG, "Stream is already in Stopped state %d", currentState);
goto exit;
} else {
PAL_ERR(LOG_TAG, "Stream should be in start/pause state, %d", currentState);
status = -EINVAL;
goto exit;
}
PAL_DBG(LOG_TAG, "Exit. status %d, state %d", status, currentState);
exit:
palStateEnqueue(this, PAL_STATE_STOPPED, status);
mStreamMutex.unlock();
return status;
}
//TBD: move this to Stream, why duplicate code?
int32_t StreamNonTunnel::prepare()
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK", session);
mStreamMutex.lock();
if ((PAL_CARD_STATUS_DOWN(rm->cardState))
|| ssrInNTMode == true) {
PAL_ERR(LOG_TAG, "Sound card offline/standby currentState %d",
currentState);
mStreamMutex.unlock();
return -ENETRESET;
}
status = session->prepare(this);
if (0 != status)
PAL_ERR(LOG_TAG, "session prepare failed with status = %d", status);
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit. status - %d", status);
return status;
}
int32_t StreamNonTunnel::read(struct pal_buffer* buf)
{
int32_t status = 0;
int32_t size;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK, state %d",
session, currentState);
mStreamMutex.lock();
if ((PAL_CARD_STATUS_DOWN(rm->cardState))
|| ssrInNTMode == true) {
PAL_ERR(LOG_TAG, "Sound card offline/standby currentState %d",
currentState);
status = -ENETRESET;
goto exit;
}
if (currentState == STREAM_STARTED) {
status = session->read(this, SHMEM_ENDPOINT, buf, &size);
if (0 != status) {
PAL_ERR(LOG_TAG, "session read is failed with status %d", status);
if (status == -ENETRESET &&
(PAL_CARD_STATUS_UP(rm->cardState))) {
PAL_ERR(LOG_TAG, "Sound card offline/standby, informing RM");
rm->ssrHandler(CARD_STATUS_OFFLINE);
size = buf->size;
PAL_DBG(LOG_TAG, "dropped buffer size - %d", size);
goto exit;
} else if (PAL_CARD_STATUS_DOWN(rm->cardState)) {
size = buf->size;
PAL_DBG(LOG_TAG, "dropped buffer size - %d", size);
goto exit;
} else {
goto exit;
}
}
} else {
PAL_ERR(LOG_TAG, "Stream not started yet, state %d", currentState);
status = -EINVAL;
goto exit;
}
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit. session read successful size - %d", size);
return size;
exit :
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "session read failed status %d", status);
return status;
}
int32_t StreamNonTunnel::write(struct pal_buffer* buf)
{
int32_t status = 0;
int32_t size = 0;
PAL_DBG(LOG_TAG, "Enter. session handle - %pK, state %d",
session, currentState);
mStreamMutex.lock();
// If cached state is not STREAM_IDLE, we are still processing SSR up.
if ((PAL_CARD_STATUS_DOWN(rm->cardState))
|| ssrInNTMode == true) {
size = buf->size;
PAL_DBG(LOG_TAG, "sound card offline/standby dropped buffer size - %d", size);
mStreamMutex.unlock();
return -ENETRESET;
}
mStreamMutex.unlock();
//we should allow writes to go through in Start/Pause state as well.
if ( (currentState == STREAM_STARTED) ||
(currentState == STREAM_PAUSED) ) {
status = session->write(this, SHMEM_ENDPOINT, buf, &size, 0);
if (0 != status) {
PAL_ERR(LOG_TAG, "session write is failed with status %d", status);
/* ENETRESET is the error code returned by AGM during SSR */
if (status == -ENETRESET &&
(PAL_CARD_STATUS_UP(rm->cardState))) {
PAL_ERR(LOG_TAG, "Sound card offline/standby, informing RM");
rm->ssrHandler(CARD_STATUS_OFFLINE);
size = buf->size;
PAL_DBG(LOG_TAG, "dropped buffer size - %d", size);
goto exit;
} else if (PAL_CARD_STATUS_DOWN(rm->cardState)) {
size = buf->size;
PAL_DBG(LOG_TAG, "dropped buffer size - %d", size);
goto exit;
} else {
goto exit;
}
}
PAL_DBG(LOG_TAG, "Exit. session write successful size - %d", size);
return size;
} else {
PAL_ERR(LOG_TAG, "Stream not started yet, state %d", currentState);
if (currentState == STREAM_STOPPED)
status = -EIO;
else
status = -EINVAL;
goto exit;
}
exit :
PAL_DBG(LOG_TAG, "session write failed status %d", status);
return status;
}
int32_t StreamNonTunnel::registerCallBack(pal_stream_callback cb, uint64_t cookie)
{
streamCb = cb;
this->cookie = cookie;
return 0; return 0;
}
int32_t StreamNonTunnel::getTagsWithModuleInfo(size_t *size, uint8_t *payload)
{
int32_t status = 0;
if (*size > 0 && !payload)
{
status = -EINVAL;
PAL_ERR(LOG_TAG, "wrong params");
goto exit;
}
status = session->getTagsWithModuleInfo(this, size, payload);
exit:
return status;
}
int32_t StreamNonTunnel::getCallBack(pal_stream_callback * /*cb*/)
{
return 0;
}
int32_t StreamNonTunnel::getParameters(uint32_t /*param_id*/, void ** /*payload*/)
{
return 0;
}
int32_t StreamNonTunnel::setParameters(uint32_t param_id, void *payload)
{
int32_t status = 0;
if (!payload)
{
status = -EINVAL;
PAL_ERR(LOG_TAG, "wrong params");
goto error;
}
mStreamMutex.lock();
if (currentState == STREAM_IDLE) {
PAL_ERR(LOG_TAG, "Invalid stream state: IDLE for param ID: %d", param_id);
mStreamMutex.unlock();
return -EINVAL;
}
if ((PAL_CARD_STATUS_DOWN(rm->cardState))
|| ssrInNTMode == true) {
PAL_ERR(LOG_TAG, "Sound card offline/standby currentState %d",
currentState);
status = -ENETRESET;
goto error;
}
PAL_DBG(LOG_TAG, "start, set parameter %u, session handle - %p", param_id, session);
// Stream may not know about tags, so use setParameters instead of setConfig
switch (param_id) {
case PAL_PARAM_ID_MODULE_CONFIG:
status = session->setParameters(this, 0, param_id, payload);
break;
default:
PAL_ERR(LOG_TAG, "Unsupported param id %u", param_id);
status = -EINVAL;
break;
}
error:
mStreamMutex.unlock();
PAL_VERBOSE(LOG_TAG, "exit, session parameter %u set with status %d", param_id, status);
return status;
}
int32_t StreamNonTunnel::drain(pal_drain_type_t type)
{
PAL_ERR(LOG_TAG, "drain");
if ((PAL_CARD_STATUS_DOWN(rm->cardState))
|| ssrInNTMode == true) {
PAL_ERR(LOG_TAG, "Sound card offline/standby currentState %d",
currentState);
return -ENETRESET;
}
return session->drain(type);
}
int32_t StreamNonTunnel::flush()
{
int32_t status = 0;
mStreamMutex.lock();
if ((PAL_CARD_STATUS_DOWN(rm->cardState))
|| ssrInNTMode == true) {
PAL_ERR(LOG_TAG, "Sound card offline/standby currentState %d",
currentState);
status = -ENETRESET;
goto exit;
}
status = session->flush();
exit:
mStreamMutex.unlock();
return status;
}
int32_t StreamNonTunnel::suspend()
{
int32_t status = 0;
mStreamMutex.lock();
if ((PAL_CARD_STATUS_DOWN(rm->cardState))
|| ssrInNTMode) {
PAL_ERR(LOG_TAG, "Sound card offline/standby currentState %d",
currentState);
status = -ENETRESET;
goto exit;
}
if (currentState == STREAM_STARTED) {
status = session->suspend(this);
if (status) {
PAL_ERR(LOG_TAG, "Rx session suspend failed with status %d", status);
goto exit;
}
currentState = STREAM_SUSPENDED;
palStateEnqueue(this, PAL_STATE_SUSPENDED, status);
}
exit:
mStreamMutex.unlock();
return status;
}
int32_t StreamNonTunnel::isSampleRateSupported(uint32_t sampleRate)
{
int32_t rc = 0;
PAL_DBG(LOG_TAG, "sampleRate %u", sampleRate);
switch(sampleRate) {
case SAMPLINGRATE_8K:
case SAMPLINGRATE_16K:
case SAMPLINGRATE_22K:
case SAMPLINGRATE_32K:
case SAMPLINGRATE_44K:
case SAMPLINGRATE_48K:
case SAMPLINGRATE_96K:
case SAMPLINGRATE_192K:
case SAMPLINGRATE_384K:
break;
default:
rc = 0;
PAL_VERBOSE(LOG_TAG, "sample rate received %d rc %d", sampleRate, rc);
break;
}
return rc;
}
int32_t StreamNonTunnel::isChannelSupported(uint32_t numChannels)
{
int32_t rc = 0;
PAL_DBG(LOG_TAG, "numChannels %u", numChannels);
switch(numChannels) {
case CHANNELS_1:
case CHANNELS_2:
case CHANNELS_3:
case CHANNELS_4:
case CHANNELS_5:
case CHANNELS_5_1:
case CHANNELS_7:
case CHANNELS_8:
break;
default:
rc = -EINVAL;
PAL_ERR(LOG_TAG, "channels not supported %d rc %d", numChannels, rc);
break;
}
return rc;
}
int32_t StreamNonTunnel::isBitWidthSupported(uint32_t bitWidth)
{
int32_t rc = 0;
PAL_DBG(LOG_TAG, "bitWidth %u", bitWidth);
switch(bitWidth) {
case BITWIDTH_16:
case BITWIDTH_24:
case BITWIDTH_32:
break;
default:
rc = -EINVAL;
PAL_ERR(LOG_TAG, "bit width not supported %d rc %d", bitWidth, rc);
break;
}
return rc;
}
int32_t StreamNonTunnel::ssrDownHandler()
{
int32_t status = 0;
mStreamMutex.lock();
/* In NonTunnelMode once SSR happens, that session is not reusuable
* Hence set the ssr to true and return all subsequent calls with
* -ENETRESET, untill the client sets up a new session.
*
*/
PAL_DBG(LOG_TAG, "Enter. session handle - %pK currentState State %d",
session, currentState);
ssrInNTMode = true;
if (streamCb)
streamCb(reinterpret_cast<pal_stream_handle_t *>(this), PAL_STREAM_CBK_EVENT_ERROR, NULL, 0, this->cookie);
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamNonTunnel::ssrUpHandler()
{
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,841 @@
/*
* 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.
*
* 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 LOG_TAG "PAL: StreamSensorPCMData"
#include "StreamSensorPCMData.h"
#include "Session.h"
#include "kvh2xml.h"
#include "SessionAlsaPcm.h"
#include "ResourceManager.h"
#include "Device.h"
#include <unistd.h>
StreamSensorPCMData::StreamSensorPCMData(const struct pal_stream_attributes *sattr __unused,
struct pal_device *dattr __unused,
const uint32_t no_of_devices __unused,
const struct modifier_kv *modifiers __unused,
const uint32_t no_of_modifiers __unused,
const std::shared_ptr<ResourceManager> rm):
StreamCommon(sattr,dattr,no_of_devices,modifiers,no_of_modifiers,rm)
{
int32_t enable_concurrency_count = 0;
int32_t disable_concurrency_count = 0;
paused_ = false;
PAL_DBG(LOG_TAG, "Enter");
/* get ACD platform info */
acd_info_ = ACDPlatformInfo::GetInstance();
if (!acd_info_) {
PAL_ERR(LOG_TAG, "Error:%d Failed to get acd platform info", -EINVAL);
throw std::runtime_error("Failed to get acd platform info");
}
rm->registerStream(this);
/* Print the concurrency feature flags supported */
PAL_INFO(LOG_TAG, "capture conc enable %d,voice conc enable %d,voip conc enable %d",
acd_info_->GetConcurrentCaptureEnable(),
acd_info_->GetConcurrentVoiceCallEnable(),
acd_info_->GetConcurrentVoipCallEnable());
/* check concurrency count from rm */
rm->GetSoundTriggerConcurrencyCount(PAL_STREAM_SENSOR_PCM_DATA,
&enable_concurrency_count,
&disable_concurrency_count);
/*
* When voice/voip/record is active and concurrency is not
* supported, mark paused as true, so that start stream
* will be skipped and when voice/voip/record stops, stream
* will be resumed.
*/
if (disable_concurrency_count) {
paused_ = true;
}
PAL_DBG(LOG_TAG, "Exit");
}
StreamSensorPCMData::~StreamSensorPCMData()
{
PAL_DBG(LOG_TAG, "Enter");
rm->resetStreamInstanceID(this);
rm->deregisterStream(this);
PAL_DBG(LOG_TAG, "Exit");
}
int32_t StreamSensorPCMData::open()
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "Enter.");
std::lock_guard<std::mutex> lck(mStreamMutex);
if (PAL_CARD_STATUS_DOWN(rm->cardState)) {
PAL_ERR(LOG_TAG, "Error:Sound card offline/standby, can not open stream");
usleep(SSR_RECOVERY);
status = -EIO;
goto exit;
}
if (currentState == STREAM_IDLE) {
currentState = STREAM_INIT;
PAL_DBG(LOG_TAG, "streamLL opened. state %d", currentState);
} else if (currentState == STREAM_INIT) {
PAL_INFO(LOG_TAG, "Stream is already opened, state %d", currentState);
status = 0;
goto exit;
} else {
PAL_ERR(LOG_TAG, "Error:Stream is not in correct state %d", currentState);
status = -EINVAL;
goto exit;
}
exit:
palStateEnqueue(this, PAL_STATE_OPENED, status);
PAL_DBG(LOG_TAG, "Exit ret %d", status);
return status;
}
int32_t StreamSensorPCMData::close()
{
int32_t status = 0;
mStreamMutex.lock();
if (currentState == STREAM_IDLE) {
PAL_INFO(LOG_TAG, "Stream is already closed");
mStreamMutex.unlock();
return status;
}
PAL_DBG(LOG_TAG, "Enter. session handle - %pK device count - %zu stream_type - %d state %d",
session, mDevices.size(), mStreamAttr->type, currentState);
if (currentState == STREAM_STARTED) {
mStreamMutex.unlock();
status = stop();
if (0 != status)
PAL_ERR(LOG_TAG, "Error:stream stop failed. status %d", status);
mStreamMutex.lock();
}
rm->lockGraph();
status = session->close(this);
rm->unlockGraph();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:session close failed with status %d", status);
}
currentState = STREAM_IDLE;
palStateEnqueue(this, PAL_STATE_CLOSED, status);
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit ret %d", status);
return status;
}
int32_t StreamSensorPCMData::start()
{
int32_t status = 0;
bool backend_update = false;
std::shared_ptr<Device> device = nullptr;
PAL_DBG(LOG_TAG,
"Enter. session handle: %pK, state: %d, paused_: %s",
session, currentState, paused_ ? "True" : "False");
std::lock_guard<std::mutex> lck(mStreamMutex);
if (true == paused_) {
PAL_DBG(LOG_TAG,"concurrency is not supported, start the stream later");
goto exit;
}
if (PAL_CARD_STATUS_DOWN(rm->cardState)) {
cachedState = STREAM_STARTED;
PAL_ERR(LOG_TAG, "Error:Sound card offline/standby. Update the cached state %d",
cachedState);
goto exit;
}
if (currentState == STREAM_INIT || currentState == STREAM_STOPPED ||
currentState == STREAM_PAUSED) {
device = GetPalDevice(this, GetAvailCaptureDevice());
if (!device) {
status = -EINVAL;
PAL_ERR(LOG_TAG, "Error:%d Device creation is failed", status);
goto exit;
}
rm->voteSleepMonitor(this, true);
status = device->open();
rm->voteSleepMonitor(this, false);
if (0 != status) {
PAL_ERR(LOG_TAG, "Error: device [%d] open failed with status %d",
device->getSndDeviceId(), status);
goto exit;
}
if (currentState != STREAM_PAUSED) {
mDevices.clear();
mDevices.push_back(device);
status = session->open(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:session open failed with status %d", status);
goto exit;
}
PAL_DBG(LOG_TAG, "session open successful");
/* Do not update capture profile when resuming stream */
backend_update = rm->UpdateSoundTriggerCaptureProfile(this, true);
if (backend_update) {
status = rm->StopOtherDetectionStreams(this);
if (status)
PAL_ERR(LOG_TAG, "Error:%d Failed to stop other Detection streams", status);
status = rm->StartOtherDetectionStreams(this);
if (status)
PAL_ERR(LOG_TAG, "Error:%d Failed to start other Detection streams", status);
}
}
status = device->start();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error: device [%d] start failed with status %d",
device->getSndDeviceId(), status);
device->close();
goto exit;
}
PAL_DBG(LOG_TAG, "device [%d] opened and started successfully",
device->getSndDeviceId());
rm->registerDevice(device, this);
status = startSession();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error: start session failed with status %d", status);
device->stop();
rm->deregisterDevice(device, this);
device->close();
goto exit;
}
PAL_DBG(LOG_TAG, "session start successful");
/*
* pcm_open and pcm_start done at once here,
* so directly jump to STREAM_STARTED state.
*/
currentState = STREAM_STARTED;
} else if (currentState == STREAM_STARTED) {
PAL_INFO(LOG_TAG, "Stream already started, state %d", currentState);
} else {
PAL_ERR(LOG_TAG, "Error:Stream is not opened yet");
status = -EINVAL;
}
exit:
palStateEnqueue(this, PAL_STATE_STARTED, status);
PAL_DBG(LOG_TAG, "Exit. state %d, status %d", currentState, status);
return status;
}
int32_t StreamSensorPCMData::stop()
{
int32_t status = 0;
bool backend_update = false;
PAL_DBG(LOG_TAG, "Enter. session handle: %pK, state: %d, paused_: %s",
session, currentState, paused_ ? "True" : "False");
std::lock_guard<std::mutex> lck(mStreamMutex);
if (currentState == STREAM_STARTED || currentState == STREAM_PAUSED) {
/* Do not update capture profile when pausing stream */
if (false == paused_) {
backend_update = rm->UpdateSoundTriggerCaptureProfile(this, false);
if (backend_update) {
status = rm->StopOtherDetectionStreams(this);
if (status)
PAL_ERR(LOG_TAG, "Error:%d Failed to stop other Detection streams", status);
}
}
status = session->stop(this);
if (status)
PAL_ERR(LOG_TAG, "Error:%s session stop failed with status %d",
GET_DIR_STR(mStreamAttr->direction), status);
for (int32_t i = 0; i < mDevices.size(); i++) {
status = mDevices[i]->stop();
if (status)
PAL_ERR(LOG_TAG, "Error: device [%d] stop failed with status %d",
mDevices[i]->getSndDeviceId(), status);
rm->deregisterDevice(mDevices[i], this);
status = mDevices[i]->close();
if (status)
PAL_ERR(LOG_TAG, "Error: device [%d] close failed with status %d",
mDevices[i]->getSndDeviceId(), status);
PAL_DBG(LOG_TAG, "device [%d] close successful", mDevices[i]->getSndDeviceId());
}
if (backend_update) {
status = rm->StartOtherDetectionStreams(this);
if (status)
PAL_ERR(LOG_TAG, "Error:%d Failed to start other Detection streams", status);
}
currentState = STREAM_STOPPED;
} else if (currentState == STREAM_STOPPED || currentState == STREAM_IDLE) {
PAL_INFO(LOG_TAG, "Stream is already in Stopped/idle state %d", currentState);
} else {
PAL_ERR(LOG_TAG, "Error:Stream should be in start/pause state, %d", currentState);
status = -EINVAL;
}
palStateEnqueue(this, PAL_STATE_STOPPED, status);
PAL_DBG(LOG_TAG, "Exit. status %d, state %d", status, currentState);
return status;
}
int32_t StreamSensorPCMData::Resume(bool is_internal)
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "Enter");
paused_ = false;
status = start();
if (status)
PAL_ERR(LOG_TAG, "Error:%d Resume Stream failed", status);
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamSensorPCMData::Pause(bool is_internal)
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "Enter");
paused_ = true;
status = stop();
if (!status)
{
currentState = STREAM_PAUSED;
}
else
PAL_ERR(LOG_TAG, "Error:%d Pause Stream failed", status);
palStateEnqueue(this, PAL_STATE_PAUSED, status);
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
void StreamSensorPCMData::GetUUID(class SoundTriggerUUID *uuid,
const struct st_uuid *vendor_uuid)
{
uuid->timeLow = (uint32_t)vendor_uuid->timeLow;
uuid->timeMid = (uint16_t)vendor_uuid->timeMid;
uuid->timeHiAndVersion = (uint16_t)vendor_uuid->timeHiAndVersion;
uuid->clockSeq = (uint16_t)vendor_uuid->clockSeq;
uuid->node[0] = (uint8_t)vendor_uuid->node[0];
uuid->node[1] = (uint8_t)vendor_uuid->node[1];
uuid->node[2] = (uint8_t)vendor_uuid->node[2];
uuid->node[3] = (uint8_t)vendor_uuid->node[3];
uuid->node[4] = (uint8_t)vendor_uuid->node[4];
uuid->node[5] = (uint8_t)vendor_uuid->node[5];
PAL_INFO(LOG_TAG, "Input vendor uuid : %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion, uuid->clockSeq,
uuid->node[0], uuid->node[1], uuid->node[2], uuid->node[3], uuid->node[4],
uuid->node[5]);
}
/* Use below UUID for Sensor PCM Data usecase */
static const struct st_uuid qc_sensor_pcm_data_uuid =
{ 0xc88a2c89, 0x7a55, 0x498c, 0x836f, { 0x5d, 0x7e, 0xc8, 0x58, 0x29, 0x90 } };
struct st_uuid StreamSensorPCMData::GetVendorUuid()
{
return qc_sensor_pcm_data_uuid;
}
int32_t StreamSensorPCMData::SetupStreamConfig(const struct st_uuid *vendor_uuid)
{
int32_t status = 0;
class SoundTriggerUUID uuid;
PAL_DBG(LOG_TAG, "Enter");
GetUUID(&uuid, vendor_uuid);
if (NULL == sm_cfg_) {
sm_cfg_ = acd_info_->GetStreamConfig(uuid);
if (!sm_cfg_) {
status = -EINVAL;
goto exit;
}
}
mStreamSelector = sm_cfg_->GetStreamConfigName();
mInstanceID = rm->getStreamInstanceID(this);
exit:
if (status)
PAL_ERR(LOG_TAG, "SetupStreamConfig failed with status %d", status);
PAL_DBG(LOG_TAG, "Exit, status %d, mInstanceID is %d", status, mInstanceID);
return status;
}
pal_device_id_t StreamSensorPCMData::GetAvailCaptureDevice()
{
if (mPalDevices[0] &&
mPalDevices[0]->getSndDeviceId() == PAL_DEVICE_IN_ULTRASOUND_MIC) {
return PAL_DEVICE_IN_ULTRASOUND_MIC;
} else {
if (acd_info_->GetSupportDevSwitch() &&
rm->isDeviceAvailable(PAL_DEVICE_IN_WIRED_HEADSET))
return PAL_DEVICE_IN_HEADSET_VA_MIC;
else
return PAL_DEVICE_IN_HANDSET_VA_MIC;
}
}
std::shared_ptr<CaptureProfile> StreamSensorPCMData::GetCurrentCaptureProfile()
{
std::shared_ptr<CaptureProfile> cap_prof = nullptr;
enum StInputModes input_mode = ST_INPUT_MODE_HANDSET;
enum StOperatingModes operating_mode = ST_OPERATING_MODE_HIGH_PERF_NS;
pal_device_id_t current_capture_device = GetAvailCaptureDevice();
PAL_DBG(LOG_TAG, "Enter");
if (current_capture_device == PAL_DEVICE_IN_HEADSET_VA_MIC)
input_mode = ST_INPUT_MODE_HEADSET;
/* Check lpi here again to determine the actual operating_mode */
if ((DEVICEPP_TX_RAW_LPI == pcm_data_stream_effect ||
DEVICEPP_TX_FLUENCE_FFEC == pcm_data_stream_effect)
&& rm->getLPIUsage())
operating_mode = (current_capture_device == PAL_DEVICE_IN_ULTRASOUND_MIC ?
ST_OPERATING_MODE_LOW_POWER_TX_MACRO : ST_OPERATING_MODE_LOW_POWER);
else if ((DEVICEPP_TX_RAW_LPI == pcm_data_stream_effect ||
DEVICEPP_TX_FLUENCE_FFEC == pcm_data_stream_effect)
&& !rm->getLPIUsage())
operating_mode = (current_capture_device == PAL_DEVICE_IN_ULTRASOUND_MIC ?
ST_OPERATING_MODE_HIGH_PERF_TX_MACRO : ST_OPERATING_MODE_HIGH_PERF);
else if ((DEVICEPP_TX_FLUENCE_FFNS == pcm_data_stream_effect ||
DEVICEPP_TX_FLUENCE_FFECNS == pcm_data_stream_effect)
&& rm->getLPIUsage())
operating_mode = ST_OPERATING_MODE_LOW_POWER_NS;
else if ((DEVICEPP_TX_FLUENCE_FFNS == pcm_data_stream_effect ||
DEVICEPP_TX_FLUENCE_FFECNS == pcm_data_stream_effect)
&& !rm->getLPIUsage())
operating_mode = ST_OPERATING_MODE_HIGH_PERF_NS;
if (current_capture_device == PAL_DEVICE_IN_ULTRASOUND_MIC) {
std::shared_ptr<SoundTriggerPlatformInfo> st_info = nullptr;
std::string capture_profile_name;
uint32_t sample_rate = 0;
uint32_t bit_width = 0;
uint16_t channels = 0;
struct pal_device dev_config = {};
if (mPalDevices[0] &&
mPalDevices[0]->getDeviceAttributes(&dev_config) == 0) {
sample_rate = dev_config.config.sample_rate;
bit_width = dev_config.config.bit_width;
channels = dev_config.config.ch_info.channels;
}
if (channels == 1)
capture_profile_name.append("SINGLE_MIC_");
else if (channels == 2)
capture_profile_name.append("DUAL_MIC_");
if (sample_rate == 48000)
capture_profile_name.append("48KHZ_");
else if (sample_rate == 96000)
capture_profile_name.append("96KHZ_");
if (bit_width == 16)
capture_profile_name.append("16BIT_");
else if (bit_width == 24)
capture_profile_name.append("24BIT_");
if (pcm_data_buffering == 1)
capture_profile_name.append("RAW_LPI_TX_MACRO");
else
capture_profile_name.append("RAW_LPI_NO_BUFFER_TX_MACRO");
PAL_DBG(LOG_TAG, "capture_profile_name: %s", capture_profile_name.c_str());
st_info = SoundTriggerPlatformInfo::GetInstance();
if (st_info)
cap_prof = st_info->GetCaptureProfileFromMap(capture_profile_name);
} else {
cap_prof = sm_cfg_->GetCaptureProfile(std::make_pair(operating_mode, input_mode));
}
if (cap_prof) {
PAL_DBG(LOG_TAG, "cap_prof: %s bw=%d, chs=%d, sr=%d, snd_name=%s, ec_ref=%d",
cap_prof->GetName().c_str(), cap_prof->GetBitWidth(),
cap_prof->GetChannels(), cap_prof->GetSampleRate(),
cap_prof->GetSndName().c_str(), cap_prof->isECRequired());
} else {
PAL_INFO(LOG_TAG, "Invalid capture profile");
}
return cap_prof;
}
int32_t StreamSensorPCMData::addRemoveEffect(pal_audio_effect_t effect, bool enable)
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "Enter. session handle: %pK", session);
std::lock_guard<std::mutex> lck(mStreamMutex);
/* Check lpi here to determine if EC is needed */
if (enable) {
if (PAL_AUDIO_EFFECT_NONE == effect && rm->getLPIUsage()) {
pcm_data_stream_effect = DEVICEPP_TX_RAW_LPI;
} else if (PAL_AUDIO_EFFECT_NS == effect && rm->getLPIUsage()) {
pcm_data_stream_effect = DEVICEPP_TX_FLUENCE_FFNS;
} else if (PAL_AUDIO_EFFECT_NONE == effect && !rm->getLPIUsage()) {
pcm_data_stream_effect = DEVICEPP_TX_FLUENCE_FFEC;
} else if (PAL_AUDIO_EFFECT_NS == effect && !rm->getLPIUsage()) {
pcm_data_stream_effect = DEVICEPP_TX_FLUENCE_FFECNS;
} else {
PAL_ERR(LOG_TAG, "Invalid effect ID %d", effect);
status = -EINVAL;
goto exit;
}
} else {
PAL_DBG(LOG_TAG, "Exit, no stream effect is set");
status = -EINVAL;
goto exit;
}
/* Use QC Sensor PCM Data as default streamConfig */
status = SetupStreamConfig(&qc_sensor_pcm_data_uuid);
if (status)
goto exit;
cap_prof_ = GetCurrentCaptureProfile();
if (cap_prof_) {
mDevPPSelector = cap_prof_->GetName();
} else {
status = -EINVAL;
goto exit;
}
PAL_DBG(LOG_TAG, "Exit. addRemoveEffect successful");
exit:
if (status)
PAL_ERR(LOG_TAG, "addRemoveEffect failed with status %d", status);
return status;
}
int32_t StreamSensorPCMData::HandleConcurrentStream(bool active)
{
int32_t status = 0;
std::shared_ptr<CaptureProfile> new_cap_prof = nullptr;
PAL_DBG(LOG_TAG, "Enter, active:%d", active);
if (active == false)
mStreamMutex.lock();
if (currentState != STREAM_STARTED) {
PAL_INFO(LOG_TAG, "Stream is not in started state");
if (active == true)
mStreamMutex.unlock();
return status;
}
new_cap_prof = GetCurrentCaptureProfile();
if (new_cap_prof && cap_prof_ != new_cap_prof) {
PAL_DBG(LOG_TAG,
"current capture profile %s: dev_id=0x%x, chs=%d, sr=%d, ec_ref=%d\n",
cap_prof_->GetName().c_str(),
cap_prof_->GetDevId(),
cap_prof_->GetChannels(),
cap_prof_->GetSampleRate(),
cap_prof_->isECRequired());
PAL_DBG(LOG_TAG,
"new capture profile %s: dev_id=0x%x, chs=%d, sr=%d, ec_ref=%d\n",
new_cap_prof->GetName().c_str(),
new_cap_prof->GetDevId(),
new_cap_prof->GetChannels(),
new_cap_prof->GetSampleRate(),
new_cap_prof->isECRequired());
if (!active) {
PAL_DBG(LOG_TAG, "disconnect device %d", GetAvailCaptureDevice());
/* disconnect the backend device */
status = DisconnectDevice_l(GetAvailCaptureDevice());
if (status)
PAL_ERR(LOG_TAG, "Error:%d Failed to disconnect device %d",
status, GetAvailCaptureDevice());
} else {
/* store the pre-proc KV selected in the config file */
if (new_cap_prof)
mDevPPSelector = new_cap_prof->GetName();
/* connect the backend device */
PAL_DBG(LOG_TAG, "connect device %d", GetAvailCaptureDevice());
status = ConnectDevice_l(GetAvailCaptureDevice());
if (status)
PAL_ERR(LOG_TAG, "Error:%d Failed to connect device %d",
status, GetAvailCaptureDevice());
}
} else {
PAL_INFO(LOG_TAG, "no action needed, same capture profile");
}
if (active == true)
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamSensorPCMData::DisconnectDevice_l(pal_device_id_t device_id)
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "Enter, device_id: %d", device_id);
if (mDevices[0]->getSndDeviceId() != device_id) {
PAL_ERR(LOG_TAG, "Error:%d Device %d not connected, ignore",
-EINVAL, device_id);
goto exit;
}
this->rm->deregisterDevice(mDevices[0], this);
if (session)
status = session->disconnectSessionDevice(this,
this->mStreamAttr->type,
mDevices[0]);
if (status)
PAL_ERR(LOG_TAG, "Error:%d Failed to disconnect device %d",
status, device_id);
status = mDevices[0]->stop();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%d device stop failed", status);
goto disconnect_err;
}
status = mDevices[0]->close();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%d device close failed", status);
goto disconnect_err;
}
disconnect_err:
mDevices.clear();
exit:
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamSensorPCMData::DisconnectDevice(pal_device_id_t device_id)
{
int32_t status = -EINVAL;
PAL_DBG(LOG_TAG, "Enter, device_id: %d", device_id);
/*
* NOTE: mStreamMutex will be unlocked after ConnectDevice handled
* because device disconnect/connect should be handled sequencely,
* and no other commands from client should be handled between
* device disconnect and connect.
*/
mStreamMutex.lock();
status = DisconnectDevice_l(device_id);
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamSensorPCMData::ConnectDevice_l(pal_device_id_t device_id)
{
int32_t status = 0;
std::shared_ptr<Device> device = nullptr;
PAL_DBG(LOG_TAG, "Enter, device_id: %d", device_id);
if (GetAvailCaptureDevice() != device_id) {
PAL_INFO(LOG_TAG, "Skip, device %d is alreay connected",
GetAvailCaptureDevice());
goto connect_err;
}
device = GetPalDevice(this, device_id);
if (!device) {
status = -EINVAL;
PAL_ERR(LOG_TAG, "Error:%d Device creation is failed", status);
goto connect_err;
}
rm->voteSleepMonitor(this, true);
status = device->open();
rm->voteSleepMonitor(this, false);
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%d device %d open failed", status,
device->getSndDeviceId());
goto connect_err;
}
mDevices.clear();
mDevices.push_back(device);
/* Update capture profile and mDevPPSelector */
cap_prof_ = GetCurrentCaptureProfile();
if (cap_prof_)
mDevPPSelector = cap_prof_->GetName();
else
PAL_ERR(LOG_TAG, "Failed to update capture profile and mDevPPSelector");
if (session)
status = session->setupSessionDevice(this,
this->mStreamAttr->type,
device);
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%d setupSessionDevice for %d failed",
status, device->getSndDeviceId());
device->close();
goto connect_err;
}
status = device->start();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%d device %d start failed",
status, device->getSndDeviceId());
device->close();
goto connect_err;
}
if (session)
status = session->connectSessionDevice(this,
this->mStreamAttr->type,
device);
if (status) {
PAL_ERR(LOG_TAG, "Error:%d Failed to connect device %d",
status, device_id);
device->stop();
device->close();
} else {
this->rm->registerDevice(device, this);
}
connect_err:
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamSensorPCMData::ConnectDevice(pal_device_id_t device_id)
{
int32_t status = -EINVAL;
PAL_DBG(LOG_TAG, "Enter, device_id: %d", device_id);
status = ConnectDevice_l(device_id);
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamSensorPCMData::setECRef_l(std::shared_ptr<Device> dev, bool is_enable)
{
int32_t status = 0;
PAL_DBG(LOG_TAG, "Enter, enable %d", is_enable);
if (!cap_prof_ || !cap_prof_->isECRequired()) {
PAL_DBG(LOG_TAG, "No need to set EC Ref");
goto exit;
}
if (dev && !rm->checkECRef(dev, mDevices[0])) {
PAL_DBG(LOG_TAG, "No need to set EC Ref for unmatching rx device");
goto exit;
}
status = session->setECRef(this, dev, is_enable);
if (status)
PAL_ERR(LOG_TAG, "Error:%d Failed to set EC Ref", status);
exit:
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t StreamSensorPCMData::setECRef(std::shared_ptr<Device> dev, bool is_enable)
{
int32_t status = 0;
std::lock_guard<std::mutex> lck(mStreamMutex);
if (!rm->getLPIUsage())
status = setECRef_l(dev, is_enable);
else
PAL_DBG(LOG_TAG, "set EC Ref will be handled in LPI/NLPI switch");
return status;
}
int32_t StreamSensorPCMData::setParameters(uint32_t param_id, void *payload)
{
int32_t status = 0;
pal_param_payload *param_payload = (pal_param_payload *)payload;
if (!param_payload) {
PAL_ERR(LOG_TAG, "Error: Invalid payload for param ID: %d", param_id);
return -EINVAL;
}
PAL_DBG(LOG_TAG, "Enter, param id %d", param_id);
std::lock_guard<std::mutex> lck(mStreamMutex);
switch (param_id) {
case PAL_PARAM_ID_CUSTOM_CONFIGURATION: {
pcm_data_buffering = *((uint32_t *) param_payload->payload);
break;
}
default: {
status = -EINVAL;
PAL_ERR(LOG_TAG, "Error:%d Unsupported param %u", status, param_id);
break;
}
}
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#define LOG_TAG "PAL: StreamSensorRenderer"
#include "StreamSensorRenderer.h"
#include "Session.h"
#include "SessionAlsaPcm.h"
#include "ResourceManager.h"
#include "Device.h"
#include "us_detect_api.h"
#include <unistd.h>
StreamSensorRenderer::StreamSensorRenderer(const struct pal_stream_attributes *sattr __unused, struct pal_device *dattr __unused,
const uint32_t no_of_devices __unused, const struct modifier_kv *modifiers __unused,
const uint32_t no_of_modifiers __unused, const std::shared_ptr<ResourceManager> rm):
StreamCommon(sattr,dattr,no_of_devices,modifiers,no_of_modifiers,rm)
{
rm->registerStream(this);
}
StreamSensorRenderer::~StreamSensorRenderer()
{
rm->resetStreamInstanceID(this);
rm->deregisterStream(this);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
/*
* 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.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#define LOG_TAG "PAL: StreamUltraSound"
#include "StreamUltraSound.h"
#include "Session.h"
#include "SessionAlsaPcm.h"
#include "ResourceManager.h"
#include "Device.h"
#include "us_detect_api.h"
#include <unistd.h>
StreamUltraSound::StreamUltraSound(const struct pal_stream_attributes *sattr __unused, struct pal_device *dattr __unused,
const uint32_t no_of_devices __unused, const struct modifier_kv *modifiers __unused,
const uint32_t no_of_modifiers __unused, const std::shared_ptr<ResourceManager> rm):
StreamCommon(sattr,dattr,no_of_devices,modifiers,no_of_modifiers,rm)
{
session->registerCallBack((session_callback)HandleCallBack,((uint64_t) this));
rm->registerStream(this);
}
StreamUltraSound::~StreamUltraSound()
{
rm->resetStreamInstanceID(this);
rm->deregisterStream(this);
}
int32_t StreamUltraSound::stop()
{
int32_t status = 0;
mStreamMutex.lock();
PAL_DBG(LOG_TAG, "Enter. session handle - %pK mStreamAttr->direction - %d state %d",
session, mStreamAttr->direction, currentState);
if (currentState == STREAM_STARTED || currentState == STREAM_PAUSED) {
status = session->setParameters(this, DEVICE_POP_SUPPRESSOR,
PAL_PARAM_ID_ULTRASOUND_RAMPDOWN, NULL);
if (0 != status) {
PAL_ERR(LOG_TAG, "SetParameters failed for Rampdown, status = %d", status);
}
/* Adjust the delay based on requirement */
usleep(20000);
for (int i = 0; i < mDevices.size(); i++) {
rm->deregisterDevice(mDevices[i], this);
}
PAL_VERBOSE(LOG_TAG, "In %s, device count - %zu",
GET_DIR_STR(mStreamAttr->direction), mDevices.size());
rm->lockGraph();
status = session->stop(this);
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%s session stop failed with status %d",
GET_DIR_STR(mStreamAttr->direction), status);
}
PAL_VERBOSE(LOG_TAG, "session stop successful");
for (int32_t i=0; i < mDevices.size(); i++) {
status = mDevices[i]->stop();
if (0 != status) {
PAL_ERR(LOG_TAG, "Error:%s device stop failed with status %d",
GET_DIR_STR(mStreamAttr->direction), status);
}
}
rm->unlockGraph();
PAL_VERBOSE(LOG_TAG, "devices stop successful");
currentState = STREAM_STOPPED;
} else if (currentState == STREAM_STOPPED || currentState == STREAM_IDLE) {
PAL_INFO(LOG_TAG, "Stream is already in Stopped state %d", currentState);
} else {
PAL_ERR(LOG_TAG, "Error:Stream should be in start/pause state, %d", currentState);
status = -EINVAL;
}
PAL_DBG(LOG_TAG, "Exit. status %d, state %d", status, currentState);
mStreamMutex.unlock();
return status;
}
int32_t StreamUltraSound::setParameters(uint32_t param_id, void *payload)
{
int32_t status = 0;
if (!payload)
{
status = -EINVAL;
PAL_ERR(LOG_TAG, "invalid params");
goto error;
}
mStreamMutex.lock();
if (currentState == STREAM_IDLE) {
PAL_ERR(LOG_TAG, "Invalid stream state: IDLE for param ID: %d", param_id);
mStreamMutex.unlock();
return -EINVAL;
}
// Stream may not know about tags, so use setParameters instead of setConfig
switch (param_id) {
case PAL_PARAM_ID_UPD_REGISTER_FOR_EVENTS:
{
status = session->setParameters(NULL, 0, param_id, payload);
if (status)
PAL_ERR(LOG_TAG, "Error:%d, Failed to setParam for registering an event",
status);
break;
}
default:
PAL_ERR(LOG_TAG, "Error:Unsupported param id %u", param_id);
status = -EINVAL;
break;
}
mStreamMutex.unlock();
PAL_DBG(LOG_TAG, "exit, session parameter %u set with status %d", param_id, status);
error:
return status;
}
void StreamUltraSound::HandleEvent(uint32_t event_id, void *data, uint32_t event_size) {
struct event_id_upd_detection_event_t *event_info = nullptr;
event_info = (struct event_id_upd_detection_event_t *)data;
uint32_t event_type = event_info->proximity_event_type;
PAL_INFO(LOG_TAG, "%s event received %d",
(event_type == US_DETECT_NEAR)? "NEAR": "FAR", event_type);
if (callback_) {
PAL_INFO(LOG_TAG, "Notify detection event to client");
mStreamMutex.lock();
callback_((pal_stream_handle_t *)this, event_id, &event_type,
event_size, cookie_);
mStreamMutex.unlock();
}
}
void StreamUltraSound::HandleCallBack(uint64_t hdl, uint32_t event_id,
void *data, uint32_t event_size) {
StreamUltraSound *StreamUPD = nullptr;
PAL_DBG(LOG_TAG, "Enter, event detected on SPF, event id = 0x%x, event size =%d",
event_id, event_size);
if (event_id == EVENT_ID_GENERIC_US_DETECTION) {
StreamUPD = (StreamUltraSound *)hdl;
StreamUPD->HandleEvent(event_id, data, event_size);
}
PAL_DBG(LOG_TAG, "Exit");
}