blob: 9e09bc2644f3ec000e4378154c764d4308a6749b [file] [log] [blame]
Anton Ivanov15bfd3d2025-03-03 17:54:37 -08001/*
2 * Copyright (C) 2025 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#define LOG_TAG "TransactionState"
18#include <gui/LayerState.h>
19#include <gui/SurfaceComposerClient.h>
20#include <gui/TransactionState.h>
21#include <private/gui/ParcelUtils.h>
22#include <algorithm>
23
24namespace android {
25
26status_t TransactionState::writeToParcel(Parcel* parcel) const {
27 SAFE_PARCEL(parcel->writeUint64, mId);
28 SAFE_PARCEL(parcel->writeUint32, mFlags);
29 SAFE_PARCEL(parcel->writeInt64, mDesiredPresentTime);
30 SAFE_PARCEL(parcel->writeBool, mIsAutoTimestamp);
31 SAFE_PARCEL(parcel->writeParcelable, mFrameTimelineInfo);
32 SAFE_PARCEL(parcel->writeStrongBinder, mApplyToken);
33 SAFE_PARCEL(parcel->writeBool, mMayContainBuffer);
34 SAFE_PARCEL(parcel->writeBool, mLogCallPoints);
35
36 SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mDisplayStates.size()));
37 for (auto const& displayState : mDisplayStates) {
38 displayState.write(*parcel);
39 }
40 SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mComposerStates.size()));
41 for (auto const& composerState : mComposerStates) {
42 composerState.write(*parcel);
43 }
44
45 mInputWindowCommands.write(*parcel);
46 SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mUncacheBuffers.size()));
47 for (const client_cache_t& uncacheBuffer : mUncacheBuffers) {
48 SAFE_PARCEL(parcel->writeStrongBinder, uncacheBuffer.token.promote());
49 SAFE_PARCEL(parcel->writeUint64, uncacheBuffer.id);
50 }
51
52 SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mMergedTransactionIds.size()));
53 for (auto mergedTransactionId : mMergedTransactionIds) {
54 SAFE_PARCEL(parcel->writeUint64, mergedTransactionId);
55 }
56
57 SAFE_PARCEL(parcel->writeBool, mHasListenerCallbacks);
58 SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mListenerCallbacks.size()));
59 for (const auto& [listener, callbackIds] : mListenerCallbacks) {
60 SAFE_PARCEL(parcel->writeStrongBinder, listener);
61 SAFE_PARCEL(parcel->writeParcelableVector, callbackIds);
62 }
63
64 return NO_ERROR;
65}
66
67status_t TransactionState::readFromParcel(const Parcel* parcel) {
68 SAFE_PARCEL(parcel->readUint64, &mId);
69 SAFE_PARCEL(parcel->readUint32, &mFlags);
70 SAFE_PARCEL(parcel->readInt64, &mDesiredPresentTime);
71 SAFE_PARCEL(parcel->readBool, &mIsAutoTimestamp);
72 SAFE_PARCEL(parcel->readParcelable, &mFrameTimelineInfo);
73 SAFE_PARCEL(parcel->readNullableStrongBinder, &mApplyToken);
74 SAFE_PARCEL(parcel->readBool, &mMayContainBuffer);
75 SAFE_PARCEL(parcel->readBool, &mLogCallPoints);
76
77 uint32_t count;
78 SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize())
79 mDisplayStates.clear();
80 mDisplayStates.reserve(count);
81 for (size_t i = 0; i < count; i++) {
82 DisplayState displayState;
83 if (displayState.read(*parcel) == BAD_VALUE) {
84 return BAD_VALUE;
85 }
86 mDisplayStates.emplace_back(std::move(displayState));
87 }
88
89 SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize())
90 mComposerStates.clear();
91 mComposerStates.reserve(count);
92 for (size_t i = 0; i < count; i++) {
93 ComposerState composerState;
94 if (composerState.read(*parcel) == BAD_VALUE) {
95 return BAD_VALUE;
96 }
97 mComposerStates.emplace_back(std::move(composerState));
98 }
99
100 if (status_t status = mInputWindowCommands.read(*parcel) != NO_ERROR) {
101 return status;
102 }
103
104 SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize())
105 mUncacheBuffers.clear();
106 mUncacheBuffers.reserve(count);
107 for (size_t i = 0; i < count; i++) {
108 client_cache_t client_cache;
109 sp<IBinder> tmpBinder;
110 SAFE_PARCEL(parcel->readStrongBinder, &tmpBinder);
111 client_cache.token = tmpBinder;
112 SAFE_PARCEL(parcel->readUint64, &client_cache.id);
113 mUncacheBuffers.emplace_back(std::move(client_cache));
114 }
115
116 SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize())
117 mMergedTransactionIds.clear();
118 mMergedTransactionIds.resize(count);
119 for (size_t i = 0; i < count; i++) {
120 SAFE_PARCEL(parcel->readUint64, &mMergedTransactionIds[i]);
121 }
122
123 SAFE_PARCEL(parcel->readBool, &mHasListenerCallbacks);
124 SAFE_PARCEL_READ_SIZE(parcel->readUint32, &count, parcel->dataSize());
125 mListenerCallbacks.clear();
126 mListenerCallbacks.reserve(count);
127 for (uint32_t i = 0; i < count; i++) {
128 sp<IBinder> tmpBinder;
129 SAFE_PARCEL(parcel->readStrongBinder, &tmpBinder);
130 std::vector<CallbackId> callbackIds;
131 SAFE_PARCEL(parcel->readParcelableVector, &callbackIds);
132 mListenerCallbacks.emplace_back(tmpBinder, callbackIds);
133 }
134
135 return NO_ERROR;
136}
137
138void TransactionState::merge(TransactionState&& other,
139 const std::function<void(layer_state_t&)>& onBufferOverwrite) {
140 while (mMergedTransactionIds.size() + other.mMergedTransactionIds.size() >
141 MAX_MERGE_HISTORY_LENGTH - 1 &&
142 mMergedTransactionIds.size() > 0) {
143 mMergedTransactionIds.pop_back();
144 }
145 if (other.mMergedTransactionIds.size() == MAX_MERGE_HISTORY_LENGTH) {
146 mMergedTransactionIds.insert(mMergedTransactionIds.begin(),
147 other.mMergedTransactionIds.begin(),
148 other.mMergedTransactionIds.end() - 1);
149 } else if (other.mMergedTransactionIds.size() > 0u) {
150 mMergedTransactionIds.insert(mMergedTransactionIds.begin(),
151 other.mMergedTransactionIds.begin(),
152 other.mMergedTransactionIds.end());
153 }
154 mMergedTransactionIds.insert(mMergedTransactionIds.begin(), other.mId);
155
156 for (auto const& otherState : other.mComposerStates) {
157 if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(),
158 [&otherState](const auto& composerState) {
159 return composerState.state.surface ==
160 otherState.state.surface;
161 });
162 it != mComposerStates.end()) {
163 if (otherState.state.what & layer_state_t::eBufferChanged) {
164 onBufferOverwrite(it->state);
165 }
166 it->state.merge(otherState.state);
167 } else {
168 mComposerStates.push_back(otherState);
169 }
170 }
171
172 for (auto const& state : other.mDisplayStates) {
173 if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(),
174 [&state](const auto& displayState) {
175 return displayState.token == state.token;
176 });
177 it != mDisplayStates.end()) {
178 it->merge(state);
179 } else {
180 mDisplayStates.push_back(state);
181 }
182 }
183
184 for (const auto& cacheId : other.mUncacheBuffers) {
185 mUncacheBuffers.push_back(cacheId);
186 }
187
188 mInputWindowCommands.merge(other.mInputWindowCommands);
189 // TODO(b/385156191) Consider merging desired present time.
190 mFlags |= other.mFlags;
191 mMayContainBuffer |= other.mMayContainBuffer;
192 mLogCallPoints |= other.mLogCallPoints;
193
194 // mApplyToken is explicitly not merged. Token should be set before applying the transactions to
195 // make synchronization decisions a bit simpler.
196 mergeFrameTimelineInfo(other.mFrameTimelineInfo);
197 other.clear();
198}
199
200// copied from FrameTimelineInfo::merge()
201void TransactionState::mergeFrameTimelineInfo(const FrameTimelineInfo& other) {
202 // When merging vsync Ids we take the oldest valid one
203 if (mFrameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID &&
204 other.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
205 if (other.vsyncId > mFrameTimelineInfo.vsyncId) {
206 mFrameTimelineInfo = other;
207 }
208 } else if (mFrameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
209 mFrameTimelineInfo = other;
210 }
211}
212
213void TransactionState::clear() {
214 mComposerStates.clear();
215 mDisplayStates.clear();
216 mListenerCallbacks.clear();
217 mHasListenerCallbacks = false;
218 mInputWindowCommands.clear();
219 mUncacheBuffers.clear();
220 mDesiredPresentTime = 0;
221 mIsAutoTimestamp = true;
222 mApplyToken = nullptr;
223 mFrameTimelineInfo = {};
224 mMergedTransactionIds.clear();
225 mFlags = 0;
226 mMayContainBuffer = false;
227 mLogCallPoints = false;
228}
229
230layer_state_t* TransactionState::getLayerState(const sp<SurfaceControl>& sc) {
231 auto handle = sc->getLayerStateHandle();
232 if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(),
233 [&handle](const auto& composerState) {
234 return composerState.state.surface == handle;
235 });
236 it != mComposerStates.end()) {
237 return &it->state;
238 }
239
240 // we don't have it, add an initialized layer_state to our list
241 ComposerState s;
242 s.state.surface = handle;
243 s.state.layerId = sc->getLayerId();
244 mComposerStates.push_back(s);
245
246 return &mComposerStates.back().state;
247}
248
249DisplayState& TransactionState::getDisplayState(const sp<IBinder>& token) {
250 if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(),
251 [token](const auto& display) { return display.token == token; });
252 it != mDisplayStates.end()) {
253 return *it;
254 }
255
256 // If display state doesn't exist, add a new one.
257 DisplayState s;
258 s.token = token;
259 mDisplayStates.push_back(s);
260 return mDisplayStates.back();
261}
262
263}; // namespace android