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