1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <algorithm> 20 #include <memory> 21 #include <unordered_map> 22 23 #include <android-base/logging.h> 24 25 #include "PreProcessingContext.h" 26 #include "PreProcessingTypes.h" 27 28 namespace aidl::android::hardware::audio::effect { 29 30 /** 31 * @brief Maintain all effect pre-processing sessions. 32 * 33 * Sessions are identified with the session ID, maximum of MAX_BUNDLE_SESSIONS is supported by the 34 * pre-processing implementation. 35 */ 36 class PreProcessingSession { 37 public: getPreProcessingSession()38 static PreProcessingSession& getPreProcessingSession() { 39 static PreProcessingSession instance; 40 return instance; 41 } 42 43 static bool findPreProcessingTypeInList( 44 std::vector<std::shared_ptr<PreProcessingContext>>& list, 45 const PreProcessingEffectType& type, bool remove = false) { 46 auto itor = std::find_if(list.begin(), list.end(), 47 [type](const std::shared_ptr<PreProcessingContext>& bundle) { 48 return bundle->getPreProcessingType() == type; 49 }); 50 if (itor == list.end()) { 51 return false; 52 } 53 if (remove) { 54 (*itor)->deInit(); 55 list.erase(itor); 56 } 57 return true; 58 } 59 60 /** 61 * Create a certain type of PreProcessingContext in shared_ptr container, each session must not 62 * have more than one session for each type. 63 */ createSession(const PreProcessingEffectType & type,int statusDepth,const Parameter::Common & common)64 std::shared_ptr<PreProcessingContext> createSession(const PreProcessingEffectType& type, 65 int statusDepth, 66 const Parameter::Common& common) { 67 int sessionId = common.session; 68 LOG(DEBUG) << __func__ << type << " with sessionId " << sessionId; 69 if (mSessionMap.count(sessionId) == 0 && mSessionMap.size() >= MAX_PRE_PROC_SESSIONS) { 70 LOG(ERROR) << __func__ << " exceed max bundle session"; 71 return nullptr; 72 } 73 74 if (mSessionMap.count(sessionId)) { 75 if (findPreProcessingTypeInList(mSessionMap[sessionId], type)) { 76 LOG(ERROR) << __func__ << type << " already exist in session " << sessionId; 77 return nullptr; 78 } 79 } 80 81 auto& list = mSessionMap[sessionId]; 82 auto context = std::make_shared<PreProcessingContext>(statusDepth, common, type); 83 RETURN_VALUE_IF(!context, nullptr, "failedToCreateContext"); 84 85 RetCode ret = context->init(common); 86 if (RetCode::SUCCESS != ret) { 87 LOG(ERROR) << __func__ << " context init ret " << ret; 88 return nullptr; 89 } 90 list.push_back(context); 91 return context; 92 } 93 releaseSession(const PreProcessingEffectType & type,int sessionId)94 void releaseSession(const PreProcessingEffectType& type, int sessionId) { 95 LOG(DEBUG) << __func__ << type << " sessionId " << sessionId; 96 if (mSessionMap.count(sessionId)) { 97 auto& list = mSessionMap[sessionId]; 98 if (!findPreProcessingTypeInList(list, type, true /* remove */)) { 99 LOG(ERROR) << __func__ << " can't find " << type << "in session " << sessionId; 100 return; 101 } 102 if (list.empty()) { 103 mSessionMap.erase(sessionId); 104 } 105 } 106 } 107 108 private: 109 // Max session number supported. 110 static constexpr int MAX_PRE_PROC_SESSIONS = 8; 111 std::unordered_map<int /* session ID */, std::vector<std::shared_ptr<PreProcessingContext>>> 112 mSessionMap; 113 }; 114 } // namespace aidl::android::hardware::audio::effect 115