blob: 877292f9adb28a7a828b34fec91e6046dc949bc7 [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <algorithm>
#include <memory>
#include <unordered_map>
#include <android-base/logging.h>
#include <android-base/thread_annotations.h>
#include "PreProcessingContext.h"
#include "PreProcessingTypes.h"
namespace aidl::android::hardware::audio::effect {
/**
* @brief Maintain all effect pre-processing sessions.
*
* Sessions are identified with the session ID, maximum of MAX_BUNDLE_SESSIONS is supported by the
* pre-processing implementation.
*/
class PreProcessingSession {
public:
static PreProcessingSession& getPreProcessingSession() {
static PreProcessingSession instance;
return instance;
}
static bool findPreProcessingTypeInList(
std::vector<std::shared_ptr<PreProcessingContext>>& list,
const PreProcessingEffectType& type, bool remove = false) {
auto itor = std::find_if(list.begin(), list.end(),
[type](const std::shared_ptr<PreProcessingContext>& bundle) {
return bundle->getPreProcessingType() == type;
});
if (itor == list.end()) {
return false;
}
if (remove) {
(*itor)->deInit();
list.erase(itor);
}
return true;
}
/**
* Create a certain type of PreProcessingContext in shared_ptr container, each session must not
* have more than one session for each type.
*/
std::shared_ptr<PreProcessingContext> createSession(const PreProcessingEffectType& type,
int statusDepth,
const Parameter::Common& common) {
int sessionId = common.session;
LOG(DEBUG) << __func__ << type << " with sessionId " << sessionId;
std::lock_guard lg(mMutex);
if (mSessionMap.count(sessionId) == 0 && mSessionMap.size() >= MAX_PRE_PROC_SESSIONS) {
LOG(ERROR) << __func__ << " exceed max bundle session";
return nullptr;
}
if (mSessionMap.count(sessionId)) {
if (findPreProcessingTypeInList(mSessionMap[sessionId], type)) {
LOG(ERROR) << __func__ << type << " already exist in session " << sessionId;
return nullptr;
}
}
auto& list = mSessionMap[sessionId];
auto context = std::make_shared<PreProcessingContext>(statusDepth, common, type);
RETURN_VALUE_IF(!context, nullptr, "failedToCreateContext");
RetCode ret = context->init(common);
if (RetCode::SUCCESS != ret) {
LOG(ERROR) << __func__ << " context init ret " << ret;
return nullptr;
}
list.push_back(context);
return context;
}
void releaseSession(const PreProcessingEffectType& type, int sessionId) {
LOG(DEBUG) << __func__ << type << " sessionId " << sessionId;
std::lock_guard lg(mMutex);
if (mSessionMap.count(sessionId)) {
auto& list = mSessionMap[sessionId];
if (!findPreProcessingTypeInList(list, type, true /* remove */)) {
LOG(ERROR) << __func__ << " can't find " << type << "in session " << sessionId;
return;
}
if (list.empty()) {
mSessionMap.erase(sessionId);
}
}
}
private:
// Lock for mSessionMap access.
std::mutex mMutex;
// Max session number supported.
static constexpr int MAX_PRE_PROC_SESSIONS = 8;
std::unordered_map<int /* session ID */, std::vector<std::shared_ptr<PreProcessingContext>>>
mSessionMap GUARDED_BY(mMutex);
};
} // namespace aidl::android::hardware::audio::effect