blob: d971d041762b07827e21a242a19e64824a162422 [file] [log] [blame]
/*
* 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 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() { 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() override;
int32_t Pause() override;
int32_t HandleConcurrentStream(bool active) override;
int32_t EnableLPI(bool is_enable) 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);
std::shared_ptr<Device> GetPalDevice(pal_device_id_t dev_id, bool use_rm_profile);
void SetEngineDetectionData(struct acd_context_event *event);
struct acd_recognition_cfg *GetRecognitionConfig();
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<StreamConfig> 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_;
bool use_lpi_;
protected:
std::thread notification_thread_handler_;
std::mutex mutex_;
std::condition_variable cv_;
bool exit_thread_;
};
#endif // STREAMACD_H_