• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 <condition_variable>
20 #include <memory>
21 #include <mutex>
22 #include <vector>
23 
24 #include <gui/LayerState.h>
25 #include <system/window.h>
26 
27 namespace android {
28 
29 class CountDownLatch;
30 
31 struct TransactionState {
32     TransactionState() = default;
33 
TransactionStateTransactionState34     TransactionState(const FrameTimelineInfo& frameTimelineInfo,
35                      const Vector<ComposerState>& composerStates,
36                      const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
37                      const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands,
38                      int64_t desiredPresentTime, bool isAutoTimestamp,
39                      const client_cache_t& uncacheBuffer, int64_t postTime, uint32_t permissions,
40                      bool hasListenerCallbacks, std::vector<ListenerCallbacks> listenerCallbacks,
41                      int originPid, int originUid, uint64_t transactionId)
42           : frameTimelineInfo(frameTimelineInfo),
43             states(composerStates),
44             displays(displayStates),
45             flags(transactionFlags),
46             applyToken(applyToken),
47             inputWindowCommands(inputWindowCommands),
48             desiredPresentTime(desiredPresentTime),
49             isAutoTimestamp(isAutoTimestamp),
50             buffer(uncacheBuffer),
51             postTime(postTime),
52             permissions(permissions),
53             hasListenerCallbacks(hasListenerCallbacks),
54             listenerCallbacks(listenerCallbacks),
55             originPid(originPid),
56             originUid(originUid),
57             id(transactionId) {}
58 
59     // Invokes `void(const layer_state_t&)` visitor for matching layers.
60     template <typename Visitor>
traverseStatesWithBuffersTransactionState61     void traverseStatesWithBuffers(Visitor&& visitor) const {
62         for (const auto& [state] : states) {
63             if (state.hasBufferChanges() && state.hasValidBuffer() && state.surface) {
64                 visitor(state);
65             }
66         }
67     }
68 
69     // TODO(b/185535769): Remove FrameHint. Instead, reset the idle timer (of the relevant physical
70     // display) on the main thread if commit leads to composite. Then, RefreshRateOverlay should be
71     // able to setFrameRate once, rather than for each transaction.
isFrameActiveTransactionState72     bool isFrameActive() const {
73         if (!displays.empty()) return true;
74 
75         for (const auto& [state] : states) {
76             if (state.frameRateCompatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE) {
77                 return true;
78             }
79         }
80 
81         return false;
82     }
83 
84     FrameTimelineInfo frameTimelineInfo;
85     Vector<ComposerState> states;
86     Vector<DisplayState> displays;
87     uint32_t flags;
88     sp<IBinder> applyToken;
89     InputWindowCommands inputWindowCommands;
90     int64_t desiredPresentTime;
91     bool isAutoTimestamp;
92     client_cache_t buffer;
93     int64_t postTime;
94     uint32_t permissions;
95     bool hasListenerCallbacks;
96     std::vector<ListenerCallbacks> listenerCallbacks;
97     int originPid;
98     int originUid;
99     uint64_t id;
100     std::shared_ptr<CountDownLatch> transactionCommittedSignal;
101     int64_t queueTime = 0;
102     bool sentFenceTimeoutWarning = false;
103 };
104 
105 class CountDownLatch {
106 public:
107     enum {
108         eSyncTransaction = 1 << 0,
109         eSyncInputWindows = 1 << 1,
110     };
CountDownLatch(uint32_t flags)111     explicit CountDownLatch(uint32_t flags) : mFlags(flags) {}
112 
113     // True if there is no waiting condition after count down.
countDown(uint32_t flag)114     bool countDown(uint32_t flag) {
115         std::unique_lock<std::mutex> lock(mMutex);
116         if (mFlags == 0) {
117             return true;
118         }
119         mFlags &= ~flag;
120         if (mFlags == 0) {
121             mCountDownComplete.notify_all();
122             return true;
123         }
124         return false;
125     }
126 
127     // Return true if triggered.
wait_until(const std::chrono::nanoseconds & timeout)128     bool wait_until(const std::chrono::nanoseconds& timeout) const {
129         std::unique_lock<std::mutex> lock(mMutex);
130         const auto untilTime = std::chrono::system_clock::now() + timeout;
131         while (mFlags != 0) {
132             // Conditional variables can be woken up sporadically, so we check count
133             // to verify the wakeup was triggered by |countDown|.
134             if (std::cv_status::timeout == mCountDownComplete.wait_until(lock, untilTime)) {
135                 return false;
136             }
137         }
138         return true;
139     }
140 
141 private:
142     uint32_t mFlags;
143     mutable std::condition_variable mCountDownComplete;
144     mutable std::mutex mMutex;
145 };
146 
147 } // namespace android
148