1 /*
2 * Copyright (c) 2021-2023 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_proxy.h"
17 #include <mutex>
18 #include <stdlib.h>
19
20 #ifdef ROSEN_OHOS
21 #include "hisysevent.h"
22 #include "mem_mgr_client.h"
23 #endif
24 #include "platform/common/rs_log.h"
25 #include "platform/common/rs_system_properties.h"
26 #include "rs_trace.h"
27 #include "sandbox_utils.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 std::once_flag RSTransactionProxy::flag_;
47 RSTransactionProxy* RSTransactionProxy::instance_ = nullptr;
48
GetInstance()49 RSTransactionProxy* RSTransactionProxy::GetInstance()
50 {
51 std::call_once(flag_, &RSTransactionProxy::Init);
52 return instance_;
53 }
54
RSTransactionProxy()55 RSTransactionProxy::RSTransactionProxy()
56 {
57 }
58
~RSTransactionProxy()59 RSTransactionProxy::~RSTransactionProxy()
60 {
61 }
62
Init()63 void RSTransactionProxy::Init()
64 {
65 instance_ = new RSTransactionProxy();
66 ::atexit(&RSTransactionProxy::Destroy);
67 }
68
Destroy()69 void RSTransactionProxy::Destroy()
70 {
71 instance_ = nullptr;
72 }
73
SetRenderThreadClient(std::unique_ptr<RSIRenderClient> & renderThreadClient)74 void RSTransactionProxy::SetRenderThreadClient(std::unique_ptr<RSIRenderClient>& renderThreadClient)
75 {
76 if (renderThreadClient != nullptr) {
77 renderThreadClient_ = std::move(renderThreadClient);
78 }
79 }
80
SetRenderServiceClient(const std::shared_ptr<RSIRenderClient> & renderServiceClient)81 void RSTransactionProxy::SetRenderServiceClient(const std::shared_ptr<RSIRenderClient>& renderServiceClient)
82 {
83 if (renderServiceClient != nullptr) {
84 renderServiceClient_ = renderServiceClient;
85 }
86 }
87
AddCommand(std::unique_ptr<RSCommand> & command,bool isRenderServiceCommand,FollowType followType,NodeId nodeId)88 void RSTransactionProxy::AddCommand(std::unique_ptr<RSCommand>& command, bool isRenderServiceCommand,
89 FollowType followType, NodeId nodeId)
90 {
91 #ifndef SCREENLESS_DEVICE
92 if ((renderServiceClient_ == nullptr && renderThreadClient_ == nullptr) || command == nullptr) {
93 RS_LOGE("RSTransactionProxy::add command fail, (renderServiceClient_ and renderThreadClient_ is nullptr)"
94 " or command is nullptr");
95 return;
96 }
97
98 std::unique_lock<std::mutex> cmdLock(mutex_);
99
100 RS_LOGI_IF(DEBUG_NODE,
101 "RSTransactionProxy::add command nodeId:%{public}" PRIu64 " isRenderServiceCommand:%{public}d"
102 " followType:%{public}hu", nodeId, isRenderServiceCommand, followType);
103 if (renderServiceClient_ != nullptr && (isRenderServiceCommand || renderThreadClient_ == nullptr)) {
104 #ifdef ROSEN_OHOS
105 int appPid = ExtractPid(nodeId);
106 if (isRenderServiceCommand && command->GetSubType() == RSCommandType::ANIMATION &&
107 RSSystemProperties::GetDmaReclaimParam()) {
108 RS_TRACE_NAME_FMT("MemoryStatusChanged from proxy pid[%d]", appPid);
109 Memory::MemMgrClient::GetInstance().MemoryStatusChanged(appPid,
110 static_cast<int32_t>(Memory::MemoryTypeCode::DMABUF),
111 static_cast<int32_t>(Memory::MemoryStatusCode::USED));
112 }
113 #endif
114 AddRemoteCommand(command, nodeId, followType);
115 return;
116 }
117
118 if (!isRenderServiceCommand) {
119 AddCommonCommand(command);
120 return;
121 }
122 ROSEN_LOGE("RSTransactionProxy::AddCommand failed, isRenderServiceCommand:%{public}d %{public}s",
123 isRenderServiceCommand, command->PrintType().c_str());
124 #endif
125 }
126
AddCommandFromRT(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)127 void RSTransactionProxy::AddCommandFromRT(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
128 {
129 if (renderServiceClient_ == nullptr || command == nullptr) {
130 return;
131 }
132
133 {
134 std::unique_lock<std::mutex> cmdLock(mutexForRT_);
135 implicitTransactionDataFromRT_->AddCommand(command, nodeId, followType);
136 }
137 }
138
ExecuteSynchronousTask(const std::shared_ptr<RSSyncTask> & task,bool isRenderServiceTask)139 void RSTransactionProxy::ExecuteSynchronousTask(const std::shared_ptr<RSSyncTask>& task, bool isRenderServiceTask)
140 {
141 if (!task) {
142 ROSEN_LOGE("RSTransactionProxy::ExecuteSynchronousTask failed, the task is not exist.");
143 return;
144 }
145
146 if (renderServiceClient_ && isRenderServiceTask) {
147 renderServiceClient_->ExecuteSynchronousTask(task);
148 return;
149 }
150
151 if (renderThreadClient_ && (!isRenderServiceTask)) {
152 renderThreadClient_->ExecuteSynchronousTask(task);
153 return;
154 }
155
156 ROSEN_LOGE("RSTransactionProxy::ExecuteSynchronousTask failed, isRenderServiceTask is %{public}d.",
157 isRenderServiceTask);
158 }
159
FlushImplicitTransaction(uint64_t timestamp,const std::string & abilityName,bool dvsyncTimeUpdate,uint64_t dvsyncTime)160 void RSTransactionProxy::FlushImplicitTransaction(uint64_t timestamp, const std::string& abilityName,
161 bool dvsyncTimeUpdate, uint64_t dvsyncTime)
162 {
163 std::unique_lock<std::mutex> cmdLock(mutex_);
164 if (!implicitRemoteTransactionDataStack_.empty() && needSync_) {
165 RS_LOGE_LIMIT(__func__, __line__, "FlushImplicitTransaction failed, DataStack not empty");
166 return;
167 }
168 if (dvsyncTimeUpdate) {
169 timestamp_ = timestamp;
170 } else {
171 timestamp_ = std::max(timestamp, timestamp_);
172 }
173 thread_local pid_t tid = gettid();
174 if (renderThreadClient_ != nullptr && !implicitCommonTransactionData_->IsEmpty()) {
175 implicitCommonTransactionData_->timestamp_ = timestamp_;
176 implicitCommonTransactionData_->tid_ = tid;
177 implicitCommonTransactionData_->abilityName_ = abilityName;
178 renderThreadClient_->CommitTransaction(implicitCommonTransactionData_);
179 implicitCommonTransactionData_ = std::make_unique<RSTransactionData>();
180 } else {
181 if (flushEmptyCallback_) {
182 flushEmptyCallback_(timestamp_);
183 }
184 }
185
186 if (renderServiceClient_ == nullptr || implicitRemoteTransactionData_->IsEmpty()) {
187 RS_TRACE_NAME("UI skip");
188 uiSkipCount_++;
189 return;
190 }
191
192 auto transactionData = std::make_unique<RSTransactionData>();
193 std::swap(implicitRemoteTransactionData_, transactionData);
194 transactionData->timestamp_ = timestamp_;
195 transactionData->tid_ = tid;
196 transactionData->dvsyncTimeUpdate_ = dvsyncTimeUpdate;
197 transactionData->dvsyncTime_ = dvsyncTime;
198 if (RSSystemProperties::GetHybridRenderEnabled() && commitTransactionCallback_ != nullptr) {
199 RS_TRACE_NAME_FMT("HybridRender transactionFlag:[%d,%" PRIu64 "]", GetRealPid(), transactionDataIndex_ + 1);
200 commitTransactionCallback_(renderServiceClient_,
201 std::move(transactionData), transactionDataIndex_, nullptr);
202 return;
203 }
204 renderServiceClient_->CommitTransaction(transactionData);
205 transactionDataIndex_ = transactionData->GetIndex();
206 }
207
ReportUiSkipEvent(const std::string & ability,int64_t nowMs,int64_t lastTimestamp)208 void RSTransactionProxy::ReportUiSkipEvent(const std::string& ability, int64_t nowMs, int64_t lastTimestamp)
209 {
210 static std::atomic<uint32_t> lastCount_ = 0;
211 uint32_t nowCount = uiSkipCount_;
212 uint32_t lastCount = lastCount_.exchange(nowCount);
213 int64_t duration = (nowMs > lastTimestamp) ? nowMs - lastTimestamp : 0;
214 if (duration > 60 * 1000 && nowCount > lastCount && nowCount - lastCount > 100) { // 60 * 1000 ms, gt 100 frame
215 int32_t count = static_cast<int32_t>(nowCount - lastCount);
216 RS_LOGE_LIMIT(__func__, __line__, "ui_skip count:%{public}d", count);
217 #ifdef ROSEN_OHOS
218 using namespace OHOS::HiviewDFX;
219 HiSysEventWrite(HiSysEvent::Domain::GRAPHIC, "RS_UI_SKIP_ANOMALY",
220 HiSysEvent::EventType::STATISTIC, "ABILITY", ability, "COUNT", count, "DURATION", duration);
221 #endif
222 }
223 }
224
GetTransactionDataIndex() const225 uint32_t RSTransactionProxy::GetTransactionDataIndex() const
226 {
227 return transactionDataIndex_;
228 }
229
IsEmpty() const230 bool RSTransactionProxy::IsEmpty() const
231 {
232 bool isEmpty = true;
233 std::unique_lock<std::mutex> cmdLock(mutex_);
234 if (implicitCommonTransactionData_) {
235 isEmpty &= implicitCommonTransactionData_->IsEmpty();
236 }
237 if (implicitRemoteTransactionData_) {
238 isEmpty &= implicitRemoteTransactionData_->IsEmpty();
239 }
240 isEmpty &= implicitCommonTransactionDataStack_.empty();
241 isEmpty &= implicitRemoteTransactionDataStack_.empty();
242 return isEmpty;
243 }
244
FlushImplicitTransactionFromRT(uint64_t timestamp)245 void RSTransactionProxy::FlushImplicitTransactionFromRT(uint64_t timestamp)
246 {
247 std::unique_lock<std::mutex> cmdLock(mutexForRT_);
248 if (renderServiceClient_ != nullptr && !implicitTransactionDataFromRT_->IsEmpty()) {
249 implicitTransactionDataFromRT_->timestamp_ = timestamp;
250 thread_local pid_t tid = gettid();
251 implicitTransactionDataFromRT_->tid_ = tid;
252 renderServiceClient_->CommitTransaction(implicitTransactionDataFromRT_);
253 implicitTransactionDataFromRT_ = std::make_unique<RSTransactionData>();
254 }
255 }
256
StartSyncTransaction()257 void RSTransactionProxy::StartSyncTransaction()
258 {
259 needSync_ = true;
260 }
261
CloseSyncTransaction()262 void RSTransactionProxy::CloseSyncTransaction()
263 {
264 needSync_ = false;
265 }
266
StartCloseSyncTransactionFallbackTask(std::shared_ptr<AppExecFwk::EventHandler> handler,bool isOpen)267 void RSTransactionProxy::StartCloseSyncTransactionFallbackTask(
268 std::shared_ptr<AppExecFwk::EventHandler> handler, bool isOpen)
269 {
270 std::unique_lock<std::mutex> cmdLock(mutex_);
271 static uint32_t num = 0;
272 const std::string name = "CloseSyncTransactionFallbackTask";
273 const int timeOutDelay = 5000;
274 if (!handler) {
275 ROSEN_LOGD("StartCloseSyncTransactionFallbackTask handler is null");
276 return;
277 }
278 if (isOpen) {
279 num++;
280 auto taskName = name + std::to_string(num);
281 taskNames_.push(taskName);
282 auto task = [this]() {
283 RS_TRACE_NAME("CloseSyncTransaction timeout");
284 ROSEN_LOGE("CloseSyncTransaction timeout");
285 auto transactionProxy = RSTransactionProxy::GetInstance();
286 if (transactionProxy != nullptr) {
287 transactionProxy->CommitSyncTransaction();
288 transactionProxy->CloseSyncTransaction();
289 }
290 if (!taskNames_.empty()) {
291 taskNames_.pop();
292 }
293 };
294 handler->PostTask(task, taskName, timeOutDelay);
295 } else {
296 if (!taskNames_.empty()) {
297 handler->RemoveTask(taskNames_.front());
298 taskNames_.pop();
299 }
300 }
301 }
302
Begin()303 void RSTransactionProxy::Begin()
304 {
305 std::unique_lock<std::mutex> cmdLock(mutex_);
306 implicitCommonTransactionDataStack_.emplace(std::make_unique<RSTransactionData>());
307 implicitRemoteTransactionDataStack_.emplace(std::make_unique<RSTransactionData>());
308 if (needSync_) {
309 implicitCommonTransactionDataStack_.top()->MarkNeedSync();
310 implicitRemoteTransactionDataStack_.top()->MarkNeedSync();
311 }
312 }
313
Commit(uint64_t timestamp)314 void RSTransactionProxy::Commit(uint64_t timestamp)
315 {
316 std::unique_lock<std::mutex> cmdLock(mutex_);
317 if (!implicitCommonTransactionDataStack_.empty()) {
318 implicitCommonTransactionDataStack_.pop();
319 }
320
321 if (!implicitRemoteTransactionDataStack_.empty()) {
322 if (renderServiceClient_ != nullptr && !implicitRemoteTransactionDataStack_.top()->IsEmpty()) {
323 implicitRemoteTransactionDataStack_.top()->timestamp_ = timestamp;
324 thread_local pid_t tid = gettid();
325 implicitRemoteTransactionDataStack_.top()->tid_ = tid;
326 renderServiceClient_->CommitTransaction(implicitRemoteTransactionDataStack_.top());
327 }
328 implicitRemoteTransactionDataStack_.pop();
329 }
330 }
331
CommitSyncTransaction(uint64_t timestamp,const std::string & abilityName)332 void RSTransactionProxy::CommitSyncTransaction(uint64_t timestamp, const std::string& abilityName)
333 {
334 std::unique_lock<std::mutex> cmdLock(mutex_);
335 timestamp_ = std::max(timestamp, timestamp_);
336 thread_local pid_t tid = gettid();
337 if (!implicitCommonTransactionDataStack_.empty()) {
338 if (renderThreadClient_ != nullptr && (!implicitCommonTransactionDataStack_.top()->IsEmpty() ||
339 implicitCommonTransactionDataStack_.top()->IsNeedSync())) {
340 implicitCommonTransactionDataStack_.top()->timestamp_ = timestamp;
341 implicitCommonTransactionDataStack_.top()->tid_ = tid;
342 implicitCommonTransactionDataStack_.top()->abilityName_ = abilityName;
343 implicitCommonTransactionDataStack_.top()->SetSyncId(syncId_);
344 renderThreadClient_->CommitTransaction(implicitCommonTransactionDataStack_.top());
345 }
346 implicitCommonTransactionDataStack_.pop();
347 }
348
349 if (!implicitRemoteTransactionDataStack_.empty()) {
350 if (renderServiceClient_ != nullptr && (!implicitRemoteTransactionDataStack_.top()->IsEmpty() ||
351 implicitRemoteTransactionDataStack_.top()->IsNeedSync())) {
352 implicitRemoteTransactionDataStack_.top()->timestamp_ = timestamp;
353 implicitRemoteTransactionDataStack_.top()->tid_ = tid;
354 implicitRemoteTransactionDataStack_.top()->SetSyncId(syncId_);
355 renderServiceClient_->CommitTransaction(implicitRemoteTransactionDataStack_.top());
356 }
357 implicitRemoteTransactionDataStack_.pop();
358 }
359 }
360
MarkTransactionNeedSync()361 void RSTransactionProxy::MarkTransactionNeedSync()
362 {
363 std::unique_lock<std::mutex> cmdLock(mutex_);
364 if (!implicitCommonTransactionDataStack_.empty()) {
365 implicitCommonTransactionDataStack_.top()->MarkNeedSync();
366 }
367
368 if (!implicitRemoteTransactionDataStack_.empty()) {
369 implicitRemoteTransactionDataStack_.top()->MarkNeedSync();
370 }
371 }
372
MarkTransactionNeedCloseSync(const int32_t transactionCount)373 void RSTransactionProxy::MarkTransactionNeedCloseSync(const int32_t transactionCount)
374 {
375 std::unique_lock<std::mutex> cmdLock(mutex_);
376 if (!implicitCommonTransactionDataStack_.empty()) {
377 implicitCommonTransactionDataStack_.top()->MarkNeedSync();
378 implicitCommonTransactionDataStack_.top()->MarkNeedCloseSync();
379 implicitCommonTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
380 }
381
382 if (!implicitRemoteTransactionDataStack_.empty()) {
383 implicitRemoteTransactionDataStack_.top()->MarkNeedSync();
384 implicitRemoteTransactionDataStack_.top()->MarkNeedCloseSync();
385 implicitRemoteTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
386 }
387 }
388
SetSyncTransactionNum(const int32_t transactionCount)389 void RSTransactionProxy::SetSyncTransactionNum(const int32_t transactionCount)
390 {
391 std::unique_lock<std::mutex> cmdLock(mutex_);
392 if (!implicitCommonTransactionDataStack_.empty()) {
393 implicitCommonTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
394 }
395
396 if (!implicitRemoteTransactionDataStack_.empty()) {
397 implicitRemoteTransactionDataStack_.top()->SetSyncTransactionNum(transactionCount);
398 }
399 }
400
SetParentPid(const int32_t parentPid)401 void RSTransactionProxy::SetParentPid(const int32_t parentPid)
402 {
403 std::unique_lock<std::mutex> cmdLock(mutex_);
404 if (!implicitCommonTransactionDataStack_.empty()) {
405 implicitCommonTransactionDataStack_.top()->SetParentPid(parentPid);
406 }
407
408 if (!implicitRemoteTransactionDataStack_.empty()) {
409 implicitRemoteTransactionDataStack_.top()->SetParentPid(parentPid);
410 }
411 }
412
AddCommonCommand(std::unique_ptr<RSCommand> & command)413 void RSTransactionProxy::AddCommonCommand(std::unique_ptr<RSCommand> &command)
414 {
415 if (!implicitCommonTransactionDataStack_.empty()) {
416 implicitCommonTransactionDataStack_.top()->AddCommand(command, 0, FollowType::NONE);
417 return;
418 }
419 implicitCommonTransactionData_->AddCommand(command, 0, FollowType::NONE);
420 }
421
AddRemoteCommand(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)422 void RSTransactionProxy::AddRemoteCommand(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
423 {
424 if (!implicitRemoteTransactionDataStack_.empty()) {
425 implicitRemoteTransactionDataStack_.top()->AddCommand(command, nodeId, followType);
426 return;
427 }
428 implicitRemoteTransactionData_->AddCommand(command, nodeId, followType);
429 }
430
431 } // namespace Rosen
432 } // namespace OHOS
433