1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
/*
* 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 <log/log.h>
#include <set>
#include <unordered_map>
#include <unordered_set>
namespace android::adpf {
class SessionLayerMap {
public:
// Inform the SessionLayerMap about dead sessions
void notifySessionsDied(std::vector<int32_t>& sessionIds);
// Inform the SessionLayerMap about dead layers
void notifyLayersDied(std::vector<int32_t>& layers);
// Associate a session with a specific set of layer ids
bool bindSessionIDToLayers(int sessionId, const std::vector<int32_t>& layerIds);
// Get the set of sessions that are mapped to a specific layer id
void getAssociatedSessions(int32_t layerId, std::vector<int32_t>& sessionIdsOut);
// Get the set of layers that are currently being tracked
void getCurrentlyRelevantLayers(std::unordered_set<int32_t>& currentlyRelevantLayers);
private:
struct MappedType {
MappedType(int32_t id, std::unordered_map<int32_t, MappedType>& 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<int32_t>&& 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<int> mLinks;
std::unordered_map<int32_t, MappedType>& mOtherList;
};
std::unordered_map<int32_t, MappedType> mSessions;
std::unordered_map<int32_t, MappedType> mLayers;
};
} // namespace android::adpf
|