• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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