summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/PowerAdvisor/SessionLayerMap.h
blob: 51808a65fc628b117b50d15940c864c33c8b8e71 (plain)
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