1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "transaction/rs_transaction_handler.h"
17
18 #include <cstdlib>
19
20 #ifdef ROSEN_OHOS
21 #include "mem_mgr_client.h"
22 #endif
23 #include "rs_trace.h"
24
25 #include "platform/common/rs_log.h"
26 #include "transaction/rs_transaction_proxy.h"
27
28 namespace OHOS {
29 namespace Rosen {
SetRenderThreadClient(std::unique_ptr<RSIRenderClient> & renderThreadClient)30 void RSTransactionHandler::SetRenderThreadClient(std::unique_ptr<RSIRenderClient>& renderThreadClient)
31 {
32 if (renderThreadClient != nullptr) {
33 renderThreadClient_ = std::move(renderThreadClient);
34 }
35 }
36
SetRenderServiceClient(const std::shared_ptr<RSIRenderClient> & renderServiceClient)37 void RSTransactionHandler::SetRenderServiceClient(const std::shared_ptr<RSIRenderClient>& renderServiceClient)
38 {
39 if (renderServiceClient != nullptr) {
40 renderServiceClient_ = renderServiceClient;
41 }
42 }
43
AddCommand(std::unique_ptr<RSCommand> & command,bool isRenderServiceCommand,FollowType followType,NodeId nodeId)44 void RSTransactionHandler::AddCommand(
45 std::unique_ptr<RSCommand>& command, bool isRenderServiceCommand, FollowType followType, NodeId nodeId)
46 {
47 if ((renderServiceClient_ == nullptr && renderThreadClient_ == nullptr) || command == nullptr) {
48 RS_LOGE("RSTransactionHandler::add command fail, (renderServiceClient_ and renderThreadClient_ is nullptr)"
49 " or command is nullptr");
50 return;
51 }
52
53 std::unique_lock<std::mutex> cmdLock(mutex_);
54
55 RS_LOGI_IF(DEBUG_NODE,
56 "RSTransactionHandler::add command nodeId:%{public}" PRIu64 " isRenderServiceCommand:%{public}d"
57 " followType:%{public}hu",
58 nodeId, isRenderServiceCommand, followType);
59 if (renderServiceClient_ != nullptr && (isRenderServiceCommand || renderThreadClient_ == nullptr)) {
60 AddRemoteCommand(command, nodeId, followType);
61 return;
62 }
63
64 if (!isRenderServiceCommand) {
65 AddCommonCommand(command);
66 return;
67 }
68 ROSEN_LOGE("RSTransactionHandler::AddCommand failed, isRenderServiceCommand:%{public}d %{public}s",
69 isRenderServiceCommand, command->PrintType().c_str());
70 }
71
AddCommandFromRT(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)72 void RSTransactionHandler::AddCommandFromRT(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
73 {
74 if (renderServiceClient_ == nullptr || command == nullptr) {
75 return;
76 }
77
78 {
79 std::unique_lock<std::mutex> cmdLock(mutexForRT_);
80 implicitTransactionDataFromRT_->AddCommand(command, nodeId, followType);
81 }
82 }
83
ExecuteSynchronousTask(const std::shared_ptr<RSSyncTask> & task,bool isRenderServiceTask)84 void RSTransactionHandler::ExecuteSynchronousTask(const std::shared_ptr<RSSyncTask>& task, bool isRenderServiceTask)
85 {
86 if (!task) {
87 ROSEN_LOGE("RSTransactionHandler::ExecuteSynchronousTask failed, the task is not exist.");
88 return;
89 }
90
91 if (renderServiceClient_ && isRenderServiceTask) {
92 renderServiceClient_->ExecuteSynchronousTask(task);
93 return;
94 }
95
96 if (renderThreadClient_ && (!isRenderServiceTask)) {
97 renderThreadClient_->ExecuteSynchronousTask(task);
98 return;
99 }
100
101 ROSEN_LOGE(
102 "RSTransactionHandler::ExecuteSynchronousTask failed, isRenderServiceTask is %{public}d.", isRenderServiceTask);
103 }
104
FlushImplicitTransaction(uint64_t timestamp,const std::string & abilityName)105 void RSTransactionHandler::FlushImplicitTransaction(uint64_t timestamp, const std::string& abilityName)
106 {
107 std::unique_lock<std::mutex> cmdLock(mutex_);
108 if (!implicitRemoteTransactionDataStack_.empty() && needSync_) {
109 RS_LOGE_LIMIT(__func__, __line__, "FlushImplicitTransaction failed, DataStack not empty");
110 return;
111 }
112 timestamp_ = std::max(timestamp, timestamp_);
113 if (renderThreadClient_ != nullptr && !implicitCommonTransactionData_->IsEmpty()) {
114 implicitCommonTransactionData_->timestamp_ = timestamp_;
115 implicitCommonTransactionData_->abilityName_ = abilityName;
116 renderThreadClient_->CommitTransaction(implicitCommonTransactionData_);
117 implicitCommonTransactionData_ = std::make_unique<RSTransactionData>();
118 } else {
119 if (flushEmptyCallback_) {
120 flushEmptyCallback_(timestamp_);
121 }
122 }
123
124 if (renderServiceClient_ != nullptr && !implicitRemoteTransactionData_->IsEmpty()) {
125 implicitRemoteTransactionData_->timestamp_ = timestamp_;
126 renderServiceClient_->CommitTransaction(implicitRemoteTransactionData_);
127 transactionDataIndex_ = implicitRemoteTransactionData_->GetIndex();
128 implicitRemoteTransactionData_ = std::make_unique<RSTransactionData>();
129 } else {
130 RS_LOGE_LIMIT(__func__, __line__,
131 "FlushImplicitTransaction return, [renderServiceClient_:%{public}d,"
132 " transactionData empty:%{public}d]",
133 renderServiceClient_ != nullptr, implicitRemoteTransactionData_->IsEmpty());
134 }
135 }
136
GetTransactionDataIndex() const137 uint32_t RSTransactionHandler::GetTransactionDataIndex() const
138 {
139 return transactionDataIndex_;
140 }
141
IsEmpty() const142 bool RSTransactionHandler::IsEmpty() const
143 {
144 bool isEmpty = true;
145 std::unique_lock<std::mutex> cmdLock(mutex_);
146 if (implicitCommonTransactionData_) {
147 isEmpty &= implicitCommonTransactionData_->IsEmpty();
148 }
149 if (implicitRemoteTransactionData_) {
150 isEmpty &= implicitRemoteTransactionData_->IsEmpty();
151 }
152 isEmpty &= implicitCommonTransactionDataStack_.empty();
153 isEmpty &= implicitRemoteTransactionDataStack_.empty();
154 return isEmpty;
155 }
156
FlushImplicitTransactionFromRT(uint64_t timestamp)157 void RSTransactionHandler::FlushImplicitTransactionFromRT(uint64_t timestamp)
158 {
159 std::unique_lock<std::mutex> cmdLock(mutexForRT_);
160 if (renderServiceClient_ != nullptr && !implicitTransactionDataFromRT_->IsEmpty()) {
161 implicitTransactionDataFromRT_->timestamp_ = timestamp;
162 renderServiceClient_->CommitTransaction(implicitTransactionDataFromRT_);
163 implicitTransactionDataFromRT_ = std::make_unique<RSTransactionData>();
164 }
165 }
166
StartSyncTransaction()167 void RSTransactionHandler::StartSyncTransaction()
168 {
169 needSync_ = true;
170 }
171
CloseSyncTransaction()172 void RSTransactionHandler::CloseSyncTransaction()
173 {
174 needSync_ = false;
175 }
176
StartCloseSyncTransactionFallbackTask(std::shared_ptr<AppExecFwk::EventHandler> handler,bool isOpen)177 void RSTransactionHandler::StartCloseSyncTransactionFallbackTask(
178 std::shared_ptr<AppExecFwk::EventHandler> handler, bool isOpen)
179 {
180 std::unique_lock<std::mutex> cmdLock(mutex_);
181 static uint32_t num = 0;
182 const std::string name = "CloseSyncTransactionFallbackTask";
183 const int timeOutDelay = 5000;
184 if (!handler) {
185 ROSEN_LOGD("StartCloseSyncTransactionFallbackTask handler is null");
186 return;
187 }
188 if (isOpen) {
189 num++;
190 auto taskName = name + std::to_string(num);
191 taskNames_.push(taskName);
192 auto task = [this]() {
193 RS_TRACE_NAME("CloseSyncTransaction timeout");
194 ROSEN_LOGE("CloseSyncTransaction timeout");
195 auto transactionProxy = RSTransactionProxy::GetInstance(); // planning
196 if (transactionProxy != nullptr) {
197 transactionProxy->CommitSyncTransaction();
198 transactionProxy->CloseSyncTransaction();
199 }
200 if (!taskNames_.empty()) {
201 taskNames_.pop();
202 }
203 };
204 handler->PostTask(task, taskName, timeOutDelay);
205 } else {
206 if (!taskNames_.empty()) {
207 handler->RemoveTask(taskNames_.front());
208 taskNames_.pop();
209 }
210 }
211 }
212
Begin()213 void RSTransactionHandler::Begin()
214 {
215 std::unique_lock<std::mutex> cmdLock(mutex_);
216 implicitCommonTransactionDataStack_.emplace(std::make_unique<RSTransactionData>());
217 implicitRemoteTransactionDataStack_.emplace(std::make_unique<RSTransactionData>());
218 if (needSync_) {
219 implicitCommonTransactionDataStack_.top()->MarkNeedSync();
220 implicitRemoteTransactionDataStack_.top()->MarkNeedSync();
221 }
222 }
223
Commit(uint64_t timestamp)224 void RSTransactionHandler::Commit(uint64_t timestamp)
225 {
226 std::unique_lock<std::mutex> cmdLock(mutex_);
227 if (!implicitCommonTransactionDataStack_.empty()) {
228 implicitCommonTransactionDataStack_.pop();
229 }
230
231 if (!implicitRemoteTransactionDataStack_.empty()) {
232 if (renderServiceClient_ != nullptr && !implicitRemoteTransactionDataStack_.top()->IsEmpty()) {
233 implicitRemoteTransactionDataStack_.top()->timestamp_ = timestamp;
234 renderServiceClient_->CommitTransaction(implicitRemoteTransactionDataStack_.top());
235 }
236 implicitRemoteTransactionDataStack_.pop();
237 }
238 }
239
CommitSyncTransaction(uint64_t timestamp,const std::string & abilityName)240 void RSTransactionHandler::CommitSyncTransaction(uint64_t timestamp, const std::string& abilityName)
241 {
242 std::unique_lock<std::mutex> cmdLock(mutex_);
243 timestamp_ = std::max(timestamp, timestamp_);
244 if (!implicitCommonTransactionDataStack_.empty()) {
245 if (renderThreadClient_ != nullptr && (!implicitCommonTransactionDataStack_.top()->IsEmpty() ||
246 implicitCommonTransactionDataStack_.top()->IsNeedSync())) {
247 implicitCommonTransactionDataStack_.top()->timestamp_ = timestamp;
248 implicitCommonTransactionDataStack_.top()->abilityName_ = abilityName;
249 implicitCommonTransactionDataStack_.top()->SetSyncId(syncId_);
250 renderThreadClient_->CommitTransaction(implicitCommonTransactionDataStack_.top());
251 }
252 implicitCommonTransactionDataStack_.pop();
253 }
254
255 if (!implicitRemoteTransactionDataStack_.empty()) {
256 if (renderServiceClient_ != nullptr && (!implicitRemoteTransactionDataStack_.top()->IsEmpty() ||
257 implicitRemoteTransactionDataStack_.top()->IsNeedSync())) {
258 implicitRemoteTransactionDataStack_.top()->timestamp_ = timestamp;
259 implicitRemoteTransactionDataStack_.top()->SetSyncId(syncId_);
260 renderServiceClient_->CommitTransaction(implicitRemoteTransactionDataStack_.top());
261 }
262 implicitRemoteTransactionDataStack_.pop();
263 }
264 }
265
MarkTransactionNeedSync()266 void RSTransactionHandler::MarkTransactionNeedSync()
267 {
268 std::unique_lock<std::mutex> cmdLock(mutex_);
269 if (!implicitCommonTransactionDataStack_.empty()) {
270 implicitCommonTransactionDataStack_.top()->MarkNeedSync();
271 }
272
273 if (!implicitRemoteTransactionDataStack_.empty()) {
274 implicitRemoteTransactionDataStack_.top()->MarkNeedSync();
275 }
276 }
277
MarkTransactionNeedCloseSync(const int32_t transactionCount)278 void RSTransactionHandler::MarkTransactionNeedCloseSync(const int32_t transactionCount)
279 {
280 std::unique_lock<std::mutex> cmdLock(mutex_);
281 if (!implicitCommonTransactionDataStack_.empty()) {
282 implicitCommonTransactionDataStack_.top()->MarkNeedSync();
283 implicitCommonTransactionDataStack_.top()->MarkNeedCloseSync();
284 implicitCommonTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
285 }
286
287 if (!implicitRemoteTransactionDataStack_.empty()) {
288 implicitRemoteTransactionDataStack_.top()->MarkNeedSync();
289 implicitRemoteTransactionDataStack_.top()->MarkNeedCloseSync();
290 implicitRemoteTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
291 }
292 }
293
SetSyncTransactionNum(const int32_t transactionCount)294 void RSTransactionHandler::SetSyncTransactionNum(const int32_t transactionCount)
295 {
296 std::unique_lock<std::mutex> cmdLock(mutex_);
297 if (!implicitCommonTransactionDataStack_.empty()) {
298 implicitCommonTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
299 }
300
301 if (!implicitRemoteTransactionDataStack_.empty()) {
302 implicitRemoteTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
303 }
304 }
305
SetParentPid(const int32_t parentPid)306 void RSTransactionHandler::SetParentPid(const int32_t parentPid)
307 {
308 std::unique_lock<std::mutex> cmdLock(mutex_);
309 if (!implicitCommonTransactionDataStack_.empty()) {
310 implicitCommonTransactionDataStack_.top()->SetParentPid(parentPid);
311 }
312
313 if (!implicitRemoteTransactionDataStack_.empty()) {
314 implicitRemoteTransactionDataStack_.top()->SetParentPid(parentPid);
315 }
316 }
317
AddCommonCommand(std::unique_ptr<RSCommand> & command)318 void RSTransactionHandler::AddCommonCommand(std::unique_ptr<RSCommand>& command)
319 {
320 if (!implicitCommonTransactionDataStack_.empty()) {
321 implicitCommonTransactionDataStack_.top()->AddCommand(command, 0, FollowType::NONE);
322 return;
323 }
324 implicitCommonTransactionData_->AddCommand(command, 0, FollowType::NONE);
325 }
326
AddRemoteCommand(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)327 void RSTransactionHandler::AddRemoteCommand(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
328 {
329 if (!implicitRemoteTransactionDataStack_.empty()) {
330 implicitRemoteTransactionDataStack_.top()->AddCommand(command, nodeId, followType);
331 return;
332 }
333 implicitRemoteTransactionData_->AddCommand(command, nodeId, followType);
334 }
335
336 } // namespace Rosen
337 } // namespace OHOS
338