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 #include <android-base/thread_annotations.h> 25 26 #include "PreProcessingContext.h" 27 #include "PreProcessingTypes.h" 28 29 namespace aidl::android::hardware::audio::effect { 30 31 /** 32 * @brief Maintain all effect pre-processing sessions. 33 * 34 * Sessions are identified with the session ID, maximum of MAX_BUNDLE_SESSIONS is supported by the 35 * pre-processing implementation. 36 */ 37 class PreProcessingSession { 38 public: getPreProcessingSession()39 static PreProcessingSession& getPreProcessingSession() { 40 static PreProcessingSession instance; 41 return instance; 42 } 43 44 static bool findPreProcessingTypeInList( 45 std::vector<std::shared_ptr<PreProcessingContext>>& list, 46 const PreProcessingEffectType& type, bool remove = false) { 47 auto itor = std::find_if(list.begin(), list.end(), 48 [type](const std::shared_ptr<PreProcessingContext>& bundle) { 49 return bundle->getPreProcessingType() == type; 50 }); 51 if (itor == list.end()) { 52 return false; 53 } 54 if (remove) { 55 (*itor)->deInit(); 56 list.erase(itor); 57 } 58 return true; 59 } 60 61 /** 62 * Create a certain type of PreProcessingContext in shared_ptr container, each session must not 63 * have more than one session for each type. 64 */ createSession(const PreProcessingEffectType & type,int statusDepth,const Parameter::Common & common)65 std::shared_ptr<PreProcessingContext> createSession(const PreProcessingEffectType& type, 66 int statusDepth, 67 const Parameter::Common& common) { 68 int sessionId = common.session; 69 LOG(DEBUG) << __func__ << type << " with sessionId " << sessionId; 70 std::lock_guard lg(mMutex); 71 if (mSessionMap.count(sessionId) == 0 && mSessionMap.size() >= MAX_PRE_PROC_SESSIONS) { 72 LOG(ERROR) << __func__ << " exceed max bundle session"; 73 return nullptr; 74 } 75 76 if (mSessionMap.count(sessionId)) { 77 if (findPreProcessingTypeInList(mSessionMap[sessionId], type)) { 78 LOG(ERROR) << __func__ << type << " already exist in session " << sessionId; 79 return nullptr; 80 } 81 } 82 83 auto& list = mSessionMap[sessionId]; 84 auto context = std::make_shared<PreProcessingContext>(statusDepth, common, type); 85 RETURN_VALUE_IF(!context, nullptr, "failedToCreateContext"); 86 87 RetCode ret = context->init(common); 88 if (RetCode::SUCCESS != ret) { 89 LOG(ERROR) << __func__ << " context init ret " << ret; 90 return nullptr; 91 } 92 list.push_back(context); 93 return context; 94 } 95 releaseSession(const PreProcessingEffectType & type,int sessionId)96 void releaseSession(const PreProcessingEffectType& type, int sessionId) { 97 LOG(DEBUG) << __func__ << type << " sessionId " << sessionId; 98 std::lock_guard lg(mMutex); 99 if (mSessionMap.count(sessionId)) { 100 auto& list = mSessionMap[sessionId]; 101 if (!findPreProcessingTypeInList(list, type, true /* remove */)) { 102 LOG(ERROR) << __func__ << " can't find " << type << "in session " << sessionId; 103 return; 104 } 105 if (list.empty()) { 106 mSessionMap.erase(sessionId); 107 } 108 } 109 } 110 111 private: 112 // Lock for mSessionMap access. 113 std::mutex mMutex; 114 // Max session number supported. 115 static constexpr int MAX_PRE_PROC_SESSIONS = 8; 116 std::unordered_map<int /* session ID */, std::vector<std::shared_ptr<PreProcessingContext>>> 117 mSessionMap GUARDED_BY(mMutex); 118 }; 119 } // namespace aidl::android::hardware::audio::effect 120