1 /* 2 * Copyright 2024 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 <log/log.h> 20 #include <set> 21 #include <unordered_map> 22 #include <unordered_set> 23 24 namespace android::adpf { 25 26 class SessionLayerMap { 27 public: 28 // Inform the SessionLayerMap about dead sessions 29 void notifySessionsDied(std::vector<int32_t>& sessionIds); 30 // Inform the SessionLayerMap about dead layers 31 void notifyLayersDied(std::vector<int32_t>& layers); 32 // Associate a session with a specific set of layer ids 33 bool bindSessionIDToLayers(int sessionId, const std::vector<int32_t>& layerIds); 34 // Get the set of sessions that are mapped to a specific layer id 35 void getAssociatedSessions(int32_t layerId, std::vector<int32_t>& sessionIdsOut); 36 // Get the set of layers that are currently being tracked 37 void getCurrentlyRelevantLayers(std::unordered_set<int32_t>& currentlyRelevantLayers); 38 39 private: 40 struct MappedType { MappedTypeMappedType41 MappedType(int32_t id, std::unordered_map<int32_t, MappedType>& otherList) 42 : mId(id), mOtherList(otherList) {}; 43 MappedType() = delete; ~MappedTypeMappedType44 ~MappedType() { swapLinks({}); } 45 46 // Replace the set of associated IDs for this mapped type with a different set of IDs, 47 // updating only associations which have changed between the two sets swapLinksMappedType48 void swapLinks(std::set<int32_t>&& incoming) { 49 auto&& oldIter = mLinks.begin(); 50 auto&& newIter = incoming.begin(); 51 52 // Dump all outdated values and insert new ones 53 while (oldIter != mLinks.end() || newIter != incoming.end()) { 54 // If there is a value in the new set but not the old set 55 // We should have already ensured what we're linking to exists 56 if (oldIter == mLinks.end() || (newIter != incoming.end() && *newIter < *oldIter)) { 57 addRemoteAssociation(*newIter); 58 ++newIter; 59 continue; 60 } 61 62 // If there is a value in the old set but not the new set 63 if (newIter == incoming.end() || (oldIter != mLinks.end() && *oldIter < *newIter)) { 64 dropRemoteAssociation(*oldIter); 65 ++oldIter; 66 continue; 67 } 68 69 // If they're the same, skip 70 if (*oldIter == *newIter) { 71 ++oldIter; 72 ++newIter; 73 continue; 74 } 75 } 76 77 mLinks.swap(incoming); 78 } 79 addRemoteAssociationMappedType80 void addRemoteAssociation(int32_t other) { 81 auto&& iter = mOtherList.find(other); 82 if (iter != mOtherList.end()) { 83 iter->second.mLinks.insert(mId); 84 } else { 85 ALOGE("Existing entry in SessionLayerMap, link failed"); 86 } 87 } 88 dropRemoteAssociationMappedType89 void dropRemoteAssociation(int32_t other) { 90 auto&& iter = mOtherList.find(other); 91 if (iter != mOtherList.end()) { 92 iter->second.mLinks.erase(mId); 93 if (iter->second.mLinks.empty()) { 94 // This only erases them from the map, not from general tracking 95 mOtherList.erase(iter); 96 } 97 } else { 98 ALOGE("Missing entry in SessionLayerMap, unlinking failed"); 99 } 100 } 101 102 int32_t mId; 103 std::set<int> mLinks; 104 std::unordered_map<int32_t, MappedType>& mOtherList; 105 }; 106 107 std::unordered_map<int32_t, MappedType> mSessions; 108 std::unordered_map<int32_t, MappedType> mLayers; 109 }; 110 111 } // namespace android::adpf 112