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 "sandbox_utils.h"
27 #include "transaction/rs_transaction_proxy.h"
28
29 #ifdef _WIN32
30 #include <windows.h>
31 #define gettid GetCurrentThreadId
32 #endif
33
34 #ifdef __APPLE__
35 #define gettid getpid
36 #endif
37
38 #ifdef __gnu_linux__
39 #include <sys/syscall.h>
40 #include <sys/types.h>
41 #define gettid []()->int32_t { return static_cast<int32_t>(syscall(SYS_gettid)); }
42 #endif
43
44 namespace OHOS {
45 namespace Rosen {
46 CommitTransactionCallback RSTransactionHandler::commitTransactionCallback_ = nullptr;
SetRenderThreadClient(std::unique_ptr<RSIRenderClient> & renderThreadClient)47 void RSTransactionHandler::SetRenderThreadClient(std::unique_ptr<RSIRenderClient>& renderThreadClient)
48 {
49 if (renderThreadClient != nullptr) {
50 renderThreadClient_ = std::move(renderThreadClient);
51 }
52 }
53
SetRenderServiceClient(const std::shared_ptr<RSIRenderClient> & renderServiceClient)54 void RSTransactionHandler::SetRenderServiceClient(const std::shared_ptr<RSIRenderClient>& renderServiceClient)
55 {
56 if (renderServiceClient != nullptr) {
57 renderServiceClient_ = renderServiceClient;
58 }
59 }
60
AddCommand(std::unique_ptr<RSCommand> & command,bool isRenderServiceCommand,FollowType followType,NodeId nodeId)61 void RSTransactionHandler::AddCommand(
62 std::unique_ptr<RSCommand>& command, bool isRenderServiceCommand, FollowType followType, NodeId nodeId)
63 {
64 #ifndef SCREENLESS_DEVICE
65 if ((renderServiceClient_ == nullptr && renderThreadClient_ == nullptr) || command == nullptr) {
66 RS_LOGE("RSTransactionHandler::add command fail, (renderServiceClient_ and renderThreadClient_ is nullptr)"
67 " or command is nullptr");
68 return;
69 }
70
71 std::unique_lock<std::mutex> cmdLock(mutex_);
72
73 RS_LOGI_IF(DEBUG_NODE,
74 "RSTransactionHandler::add command nodeId:%{public}" PRIu64 " isRenderServiceCommand:%{public}d"
75 " followType:%{public}hu",
76 nodeId, isRenderServiceCommand, followType);
77 if (renderServiceClient_ != nullptr && isRenderServiceCommand) {
78 AddRemoteCommand(command, nodeId, followType);
79 return;
80 }
81
82 if (!isRenderServiceCommand) {
83 AddCommonCommand(command);
84 return;
85 }
86 ROSEN_LOGE("RSTransactionHandler::AddCommand failed, isRenderServiceCommand:%{public}d %{public}s",
87 isRenderServiceCommand, command->PrintType().c_str());
88 #endif
89 }
90
AddCommandFromRT(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)91 void RSTransactionHandler::AddCommandFromRT(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
92 {
93 if (renderServiceClient_ == nullptr || command == nullptr) {
94 return;
95 }
96
97 {
98 std::unique_lock<std::mutex> cmdLock(mutexForRT_);
99 implicitTransactionDataFromRT_->AddCommand(command, nodeId, followType);
100 }
101 }
102
MoveCommandByNodeId(std::shared_ptr<RSTransactionHandler> transactionHandler,NodeId nodeId)103 void RSTransactionHandler::MoveCommandByNodeId(std::shared_ptr<RSTransactionHandler> transactionHandler, NodeId nodeId)
104 {
105 if (renderServiceClient_ == nullptr && renderThreadClient_ == nullptr) {
106 RS_LOGE("RSTransactionHandler::MoveCommandByNodeId GetCommand fail, (renderServiceClient_ and "
107 "renderThreadClient_ is nullptr)");
108 return;
109 }
110
111 std::unique_lock<std::mutex> cmdLock(mutex_);
112 if (renderServiceClient_ != nullptr) {
113 MoveRemoteCommandByNodeId(transactionHandler, nodeId);
114 }
115 if (renderThreadClient_ != nullptr) {
116 MoveCommonCommandByNodeId(transactionHandler, nodeId);
117 }
118 }
119
ExecuteSynchronousTask(const std::shared_ptr<RSSyncTask> & task,bool isRenderServiceTask)120 void RSTransactionHandler::ExecuteSynchronousTask(const std::shared_ptr<RSSyncTask>& task, bool isRenderServiceTask)
121 {
122 if (!task) {
123 ROSEN_LOGE("RSTransactionHandler::ExecuteSynchronousTask failed, the task is not exist.");
124 return;
125 }
126
127 if (renderServiceClient_ && isRenderServiceTask) {
128 renderServiceClient_->ExecuteSynchronousTask(task);
129 return;
130 }
131
132 if (renderThreadClient_ && (!isRenderServiceTask)) {
133 renderThreadClient_->ExecuteSynchronousTask(task);
134 return;
135 }
136
137 ROSEN_LOGE(
138 "RSTransactionHandler::ExecuteSynchronousTask failed, isRenderServiceTask is %{public}d.", isRenderServiceTask);
139 }
140
SetCommitTransactionCallback(CommitTransactionCallback commitTransactionCallback)141 void RSTransactionHandler::SetCommitTransactionCallback(CommitTransactionCallback commitTransactionCallback)
142 {
143 RSTransactionHandler::commitTransactionCallback_ = commitTransactionCallback;
144 }
145
FlushImplicitTransaction(uint64_t timestamp,const std::string & abilityName,bool dvsyncTimeUpdate,uint64_t dvsyncTime)146 void RSTransactionHandler::FlushImplicitTransaction(uint64_t timestamp, const std::string& abilityName,
147 bool dvsyncTimeUpdate, uint64_t dvsyncTime)
148 {
149 std::unique_lock<std::mutex> cmdLock(mutex_);
150 if (!implicitRemoteTransactionDataStack_.empty() && needSync_) {
151 RS_LOGE_LIMIT(__func__, __line__, "FlushImplicitTransaction failed, DataStack not empty");
152 return;
153 }
154 timestamp_ = std::max(timestamp, timestamp_);
155 thread_local pid_t tid = gettid();
156 if (renderThreadClient_ != nullptr && !implicitCommonTransactionData_->IsEmpty()) {
157 implicitCommonTransactionData_->timestamp_ = timestamp_;
158 implicitCommonTransactionData_->token_ = token_;
159 implicitCommonTransactionData_->tid_ = tid;
160 implicitCommonTransactionData_->abilityName_ = abilityName;
161 renderThreadClient_->CommitTransaction(implicitCommonTransactionData_);
162 implicitCommonTransactionData_ = std::make_unique<RSTransactionData>();
163 } else {
164 if (flushEmptyCallback_) {
165 flushEmptyCallback_(timestamp_);
166 }
167 }
168
169 if (renderServiceClient_ == nullptr || implicitRemoteTransactionData_->IsEmpty()) {
170 return;
171 }
172
173 auto transactionData = std::make_unique<RSTransactionData>();
174 std::swap(implicitRemoteTransactionData_, transactionData);
175 transactionData->timestamp_ = timestamp_;
176 transactionData->token_ = token_;
177 transactionData->tid_ = tid;
178 if (RSSystemProperties::GetHybridRenderEnabled() && RSTransactionHandler::commitTransactionCallback_ != nullptr) {
179 RS_TRACE_NAME_FMT("HybridRender transactionFlag:[%d,%" PRIu64 "]", GetRealPid(), transactionDataIndex_ + 1);
180 RSTransactionHandler::commitTransactionCallback_(renderServiceClient_,
181 std::move(transactionData), transactionDataIndex_, shared_from_this());
182 return;
183 }
184 renderServiceClient_->CommitTransaction(transactionData);
185 transactionDataIndex_ = transactionData->GetIndex();
186 }
187
GetTransactionDataIndex() const188 uint32_t RSTransactionHandler::GetTransactionDataIndex() const
189 {
190 return transactionDataIndex_;
191 }
192
PostTask(const std::function<void ()> & task)193 void RSTransactionHandler::PostTask(const std::function<void()>& task)
194 {
195 PostDelayTask(task, 0);
196 }
197
PostDelayTask(const std::function<void ()> & task,uint32_t delay)198 void RSTransactionHandler::PostDelayTask(const std::function<void()>& task, uint32_t delay)
199 {
200 if (taskRunner_ == nullptr) {
201 return;
202 }
203 taskRunner_(task, delay);
204 }
205
SetUITaskRunner(const TaskRunner & uiTaskRunner)206 void RSTransactionHandler::SetUITaskRunner(const TaskRunner& uiTaskRunner)
207 {
208 taskRunner_ = uiTaskRunner;
209 }
210
IsEmpty() const211 bool RSTransactionHandler::IsEmpty() const
212 {
213 bool isEmpty = true;
214 std::unique_lock<std::mutex> cmdLock(mutex_);
215 if (implicitCommonTransactionData_) {
216 isEmpty &= implicitCommonTransactionData_->IsEmpty();
217 }
218 if (implicitRemoteTransactionData_) {
219 isEmpty &= implicitRemoteTransactionData_->IsEmpty();
220 }
221 isEmpty &= implicitCommonTransactionDataStack_.empty();
222 isEmpty &= implicitRemoteTransactionDataStack_.empty();
223 return isEmpty;
224 }
225
FlushImplicitTransactionFromRT(uint64_t timestamp)226 void RSTransactionHandler::FlushImplicitTransactionFromRT(uint64_t timestamp)
227 {
228 std::unique_lock<std::mutex> cmdLock(mutexForRT_);
229 if (renderServiceClient_ != nullptr && !implicitTransactionDataFromRT_->IsEmpty()) {
230 implicitTransactionDataFromRT_->timestamp_ = timestamp;
231 thread_local pid_t tid = gettid();
232 implicitTransactionDataFromRT_->tid_= tid;
233 renderServiceClient_->CommitTransaction(implicitTransactionDataFromRT_);
234 implicitTransactionDataFromRT_ = std::make_unique<RSTransactionData>();
235 }
236 }
237
StartSyncTransaction()238 void RSTransactionHandler::StartSyncTransaction()
239 {
240 needSync_ = true;
241 }
242
CloseSyncTransaction()243 void RSTransactionHandler::CloseSyncTransaction()
244 {
245 needSync_ = false;
246 }
247
StartCloseSyncTransactionFallbackTask(std::shared_ptr<AppExecFwk::EventHandler> handler,bool isOpen)248 void RSTransactionHandler::StartCloseSyncTransactionFallbackTask(
249 std::shared_ptr<AppExecFwk::EventHandler> handler, bool isOpen)
250 {
251 std::unique_lock<std::mutex> cmdLock(mutex_);
252 static uint32_t num = 0;
253 const std::string name = "CloseSyncTransactionFallbackTask";
254 const int timeOutDelay = 5000;
255 if (!handler) {
256 ROSEN_LOGD("StartCloseSyncTransactionFallbackTask handler is null");
257 return;
258 }
259 if (isOpen) {
260 num++;
261 auto taskName = name + std::to_string(num);
262 taskNames_.push(taskName);
263 auto task = [this]() {
264 RS_TRACE_NAME("CloseSyncTransaction timeout");
265 ROSEN_LOGE("CloseSyncTransaction timeout");
266 auto transactionProxy = RSTransactionProxy::GetInstance(); // planning
267 if (transactionProxy != nullptr) {
268 transactionProxy->CommitSyncTransaction();
269 transactionProxy->CloseSyncTransaction();
270 }
271 if (!taskNames_.empty()) {
272 taskNames_.pop();
273 }
274 };
275 handler->PostTask(task, taskName, timeOutDelay);
276 } else {
277 if (!taskNames_.empty()) {
278 handler->RemoveTask(taskNames_.front());
279 taskNames_.pop();
280 }
281 }
282 }
283
Begin()284 void RSTransactionHandler::Begin()
285 {
286 std::unique_lock<std::mutex> cmdLock(mutex_);
287 implicitCommonTransactionDataStack_.emplace(std::make_unique<RSTransactionData>());
288 implicitRemoteTransactionDataStack_.emplace(std::make_unique<RSTransactionData>());
289 if (needSync_) {
290 implicitCommonTransactionDataStack_.top()->MarkNeedSync();
291 implicitRemoteTransactionDataStack_.top()->MarkNeedSync();
292 }
293 }
294
Commit(uint64_t timestamp)295 void RSTransactionHandler::Commit(uint64_t timestamp)
296 {
297 std::unique_lock<std::mutex> cmdLock(mutex_);
298 if (!implicitCommonTransactionDataStack_.empty()) {
299 implicitCommonTransactionDataStack_.pop();
300 }
301
302 if (!implicitRemoteTransactionDataStack_.empty()) {
303 if (renderServiceClient_ != nullptr && !implicitRemoteTransactionDataStack_.top()->IsEmpty()) {
304 implicitRemoteTransactionDataStack_.top()->timestamp_ = timestamp;
305 thread_local pid_t tid = gettid();
306 implicitRemoteTransactionDataStack_.top()->tid_= tid;
307 renderServiceClient_->CommitTransaction(implicitRemoteTransactionDataStack_.top());
308 }
309 implicitRemoteTransactionDataStack_.pop();
310 }
311 }
312
CommitSyncTransaction(uint64_t timestamp,const std::string & abilityName)313 void RSTransactionHandler::CommitSyncTransaction(uint64_t timestamp, const std::string& abilityName)
314 {
315 std::unique_lock<std::mutex> cmdLock(mutex_);
316 timestamp_ = std::max(timestamp, timestamp_);
317 thread_local pid_t tid = gettid();
318 if (!implicitCommonTransactionDataStack_.empty()) {
319 if (renderThreadClient_ != nullptr && (!implicitCommonTransactionDataStack_.top()->IsEmpty() ||
320 implicitCommonTransactionDataStack_.top()->IsNeedSync())) {
321 implicitCommonTransactionDataStack_.top()->timestamp_ = timestamp;
322 implicitCommonTransactionDataStack_.top()->tid_ = tid;
323 implicitCommonTransactionDataStack_.top()->abilityName_ = abilityName;
324 implicitCommonTransactionDataStack_.top()->SetSyncId(syncId_);
325 renderThreadClient_->CommitTransaction(implicitCommonTransactionDataStack_.top());
326 }
327 implicitCommonTransactionDataStack_.pop();
328 }
329
330 if (!implicitRemoteTransactionDataStack_.empty()) {
331 if (renderServiceClient_ != nullptr && (!implicitRemoteTransactionDataStack_.top()->IsEmpty() ||
332 implicitRemoteTransactionDataStack_.top()->IsNeedSync())) {
333 implicitRemoteTransactionDataStack_.top()->timestamp_ = timestamp;
334 implicitRemoteTransactionDataStack_.top()->tid_ = tid;
335 implicitRemoteTransactionDataStack_.top()->SetSyncId(syncId_);
336 renderServiceClient_->CommitTransaction(implicitRemoteTransactionDataStack_.top());
337 }
338 implicitRemoteTransactionDataStack_.pop();
339 }
340 }
341
MarkTransactionNeedSync()342 void RSTransactionHandler::MarkTransactionNeedSync()
343 {
344 std::unique_lock<std::mutex> cmdLock(mutex_);
345 if (!implicitCommonTransactionDataStack_.empty()) {
346 implicitCommonTransactionDataStack_.top()->MarkNeedSync();
347 }
348
349 if (!implicitRemoteTransactionDataStack_.empty()) {
350 implicitRemoteTransactionDataStack_.top()->MarkNeedSync();
351 }
352 }
353
MarkTransactionNeedCloseSync(const int32_t transactionCount)354 void RSTransactionHandler::MarkTransactionNeedCloseSync(const int32_t transactionCount)
355 {
356 std::unique_lock<std::mutex> cmdLock(mutex_);
357 if (!implicitCommonTransactionDataStack_.empty()) {
358 implicitCommonTransactionDataStack_.top()->MarkNeedSync();
359 implicitCommonTransactionDataStack_.top()->MarkNeedCloseSync();
360 implicitCommonTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
361 }
362
363 if (!implicitRemoteTransactionDataStack_.empty()) {
364 implicitRemoteTransactionDataStack_.top()->MarkNeedSync();
365 implicitRemoteTransactionDataStack_.top()->MarkNeedCloseSync();
366 implicitRemoteTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
367 }
368 }
369
SetSyncTransactionNum(const int32_t transactionCount)370 void RSTransactionHandler::SetSyncTransactionNum(const int32_t transactionCount)
371 {
372 std::unique_lock<std::mutex> cmdLock(mutex_);
373 if (!implicitCommonTransactionDataStack_.empty()) {
374 implicitCommonTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
375 }
376
377 if (!implicitRemoteTransactionDataStack_.empty()) {
378 implicitRemoteTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
379 }
380 }
381
SetParentPid(const int32_t parentPid)382 void RSTransactionHandler::SetParentPid(const int32_t parentPid)
383 {
384 std::unique_lock<std::mutex> cmdLock(mutex_);
385 if (!implicitCommonTransactionDataStack_.empty()) {
386 implicitCommonTransactionDataStack_.top()->SetParentPid(parentPid);
387 }
388
389 if (!implicitRemoteTransactionDataStack_.empty()) {
390 implicitRemoteTransactionDataStack_.top()->SetParentPid(parentPid);
391 }
392 }
393
AddCommonCommand(std::unique_ptr<RSCommand> & command)394 void RSTransactionHandler::AddCommonCommand(std::unique_ptr<RSCommand>& command)
395 {
396 if (!implicitCommonTransactionDataStack_.empty()) {
397 implicitCommonTransactionDataStack_.top()->AddCommand(command, 0, FollowType::NONE);
398 return;
399 }
400 implicitCommonTransactionData_->AddCommand(command, 0, FollowType::NONE);
401 }
402
MoveCommonCommandByNodeId(std::shared_ptr<RSTransactionHandler> transactionHandler,NodeId nodeId)403 void RSTransactionHandler::MoveCommonCommandByNodeId(
404 std::shared_ptr<RSTransactionHandler> transactionHandler, NodeId nodeId)
405 {
406 if (!implicitCommonTransactionDataStack_.empty() &&
407 !transactionHandler->implicitCommonTransactionDataStack_.empty()) {
408 implicitCommonTransactionDataStack_.top()->MoveCommandByNodeId(
409 transactionHandler->implicitCommonTransactionDataStack_.top(), nodeId);
410 }
411 implicitCommonTransactionData_->MoveCommandByNodeId(transactionHandler->implicitCommonTransactionData_, nodeId);
412 }
413
AddRemoteCommand(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)414 void RSTransactionHandler::AddRemoteCommand(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
415 {
416 if (!implicitRemoteTransactionDataStack_.empty()) {
417 implicitRemoteTransactionDataStack_.top()->AddCommand(command, nodeId, followType);
418 return;
419 }
420 implicitRemoteTransactionData_->AddCommand(command, nodeId, followType);
421 }
422
MoveRemoteCommandByNodeId(std::shared_ptr<RSTransactionHandler> transactionHandler,NodeId nodeId)423 void RSTransactionHandler::MoveRemoteCommandByNodeId(
424 std::shared_ptr<RSTransactionHandler> transactionHandler, NodeId nodeId)
425 {
426 if (!implicitRemoteTransactionDataStack_.empty() &&
427 !transactionHandler->implicitRemoteTransactionDataStack_.empty()) {
428 implicitRemoteTransactionDataStack_.top()->MoveCommandByNodeId(
429 transactionHandler->implicitRemoteTransactionDataStack_.top(), nodeId);
430 }
431 implicitRemoteTransactionData_->MoveCommandByNodeId(transactionHandler->implicitRemoteTransactionData_, nodeId);
432 }
433 } // namespace Rosen
434 } // namespace OHOS
435