/* * Copyright 2024 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 #include #include #include namespace android::adpf { class SessionLayerMap { public: // Inform the SessionLayerMap about dead sessions void notifySessionsDied(std::vector& sessionIds); // Inform the SessionLayerMap about dead layers void notifyLayersDied(std::vector& layers); // Associate a session with a specific set of layer ids bool bindSessionIDToLayers(int sessionId, const std::vector& layerIds); // Get the set of sessions that are mapped to a specific layer id void getAssociatedSessions(int32_t layerId, std::vector& sessionIdsOut); // Get the set of layers that are currently being tracked void getCurrentlyRelevantLayers(std::unordered_set& currentlyRelevantLayers); private: struct MappedType { MappedType(int32_t id, std::unordered_map& otherList) : mId(id), mOtherList(otherList) {}; MappedType() = delete; ~MappedType() { swapLinks({}); } // Replace the set of associated IDs for this mapped type with a different set of IDs, // updating only associations which have changed between the two sets void swapLinks(std::set&& incoming) { auto&& oldIter = mLinks.begin(); auto&& newIter = incoming.begin(); // Dump all outdated values and insert new ones while (oldIter != mLinks.end() || newIter != incoming.end()) { // If there is a value in the new set but not the old set // We should have already ensured what we're linking to exists if (oldIter == mLinks.end() || (newIter != incoming.end() && *newIter < *oldIter)) { addRemoteAssociation(*newIter); ++newIter; continue; } // If there is a value in the old set but not the new set if (newIter == incoming.end() || (oldIter != mLinks.end() && *oldIter < *newIter)) { dropRemoteAssociation(*oldIter); ++oldIter; continue; } // If they're the same, skip if (*oldIter == *newIter) { ++oldIter; ++newIter; continue; } } mLinks.swap(incoming); } void addRemoteAssociation(int32_t other) { auto&& iter = mOtherList.find(other); if (iter != mOtherList.end()) { iter->second.mLinks.insert(mId); } else { ALOGE("Existing entry in SessionLayerMap, link failed"); } } void dropRemoteAssociation(int32_t other) { auto&& iter = mOtherList.find(other); if (iter != mOtherList.end()) { iter->second.mLinks.erase(mId); if (iter->second.mLinks.empty()) { // This only erases them from the map, not from general tracking mOtherList.erase(iter); } } else { ALOGE("Missing entry in SessionLayerMap, unlinking failed"); } } int32_t mId; std::set mLinks; std::unordered_map& mOtherList; }; std::unordered_map mSessions; std::unordered_map mLayers; }; } // namespace android::adpf