1 /*
2 * Copyright (c) 2021-2022 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 "vsync_station.h"
17
18 #include "window_frame_trace.h"
19 #include "transaction/rs_interfaces.h"
20 #include "ui/rs_frame_rate_linker.h"
21 #include "window_manager_hilog.h"
22
23 using namespace FRAME_TRACE;
24
25 namespace OHOS {
26 namespace Rosen {
27 namespace {
28 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "VsyncStation"};
29 const std::string VSYNC_TIME_OUT_TASK = "vsync_time_out_task";
30 constexpr int64_t VSYNC_TIME_OUT_MILLISECONDS = 600;
31 }
WM_IMPLEMENT_SINGLE_INSTANCE(VsyncStation)32 WM_IMPLEMENT_SINGLE_INSTANCE(VsyncStation)
33
34 void VsyncStation::RequestVsync(const std::shared_ptr<VsyncCallback>& vsyncCallback)
35 {
36 {
37 std::lock_guard<std::mutex> lock(mtx_);
38 if (destroyed_) {
39 return;
40 }
41 vsyncCallbacks_.insert(vsyncCallback);
42
43 Init();
44 if (hasRequestedVsync_) {
45 return;
46 }
47 hasRequestedVsync_ = true;
48 if (vsyncHandler_) {
49 vsyncHandler_->RemoveTask(VSYNC_TIME_OUT_TASK);
50 vsyncHandler_->PostTask(vsyncTimeoutCallback_, VSYNC_TIME_OUT_TASK, VSYNC_TIME_OUT_MILLISECONDS);
51 }
52 }
53 WindowFrameTraceImpl::GetInstance()->VsyncStartFrameTrace();
54 receiver_->RequestNextVSync(frameCallback_);
55 }
56
GetVSyncPeriod()57 int64_t VsyncStation::GetVSyncPeriod()
58 {
59 {
60 std::lock_guard<std::mutex> lock(mtx_);
61 Init();
62 }
63 int64_t period = 0;
64 if (receiver_ != nullptr) {
65 receiver_->GetVSyncPeriod(period);
66 }
67 return period;
68 }
69
FlushFrameRate(uint32_t rate,bool immediate)70 void VsyncStation::FlushFrameRate(uint32_t rate, bool immediate)
71 {
72 if (frameRateLinker_) {
73 WLOGD("VsyncStation::FlushFrameRate %{public}d", rate);
74 FrameRateRange range = {0, RANGE_MAX_REFRESHRATE, rate};
75 if (immediate) {
76 frameRateLinker_->UpdateFrameRateRangeImme(range);
77 } else {
78 frameRateLinker_->UpdateFrameRateRange(range);
79 }
80 }
81 }
82
Init()83 void VsyncStation::Init()
84 {
85 if (!hasInitVsyncReceiver_ || !vsyncHandler_) {
86 auto mainEventRunner = AppExecFwk::EventRunner::GetMainEventRunner();
87 if (mainEventRunner != nullptr && isMainHandlerAvailable_) {
88 WLOGI("MainEventRunner is available");
89 vsyncHandler_ = std::make_shared<AppExecFwk::EventHandler>(mainEventRunner);
90 } else {
91 WLOGI("MainEventRunner is not available");
92 if (!vsyncHandler_) {
93 vsyncHandler_ = std::make_shared<AppExecFwk::EventHandler>(
94 AppExecFwk::EventRunner::Create(VSYNC_THREAD_ID));
95 }
96 }
97 auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();
98 frameRateLinker_ = OHOS::Rosen::RSFrameRateLinker::Create();
99 while (receiver_ == nullptr) {
100 receiver_ = rsClient.CreateVSyncReceiver("WM_" + std::to_string(::getprocpid()), frameRateLinker_->GetId(),
101 vsyncHandler_);
102 }
103 receiver_->Init();
104 hasInitVsyncReceiver_ = true;
105 }
106 }
107
RemoveCallback()108 void VsyncStation::RemoveCallback()
109 {
110 WLOGI("Remove Vsync callback");
111 std::lock_guard<std::mutex> lock(mtx_);
112 vsyncCallbacks_.clear();
113 }
114
VsyncCallbackInner(int64_t timestamp)115 void VsyncStation::VsyncCallbackInner(int64_t timestamp)
116 {
117 std::unordered_set<std::shared_ptr<VsyncCallback>> vsyncCallbacks;
118 {
119 std::lock_guard<std::mutex> lock(mtx_);
120 hasRequestedVsync_ = false;
121 vsyncCallbacks = vsyncCallbacks_;
122 vsyncCallbacks_.clear();
123 vsyncHandler_->RemoveTask(VSYNC_TIME_OUT_TASK);
124 }
125 for (const auto& callback: vsyncCallbacks) {
126 if (callback && callback->onCallback) {
127 callback->onCallback(timestamp);
128 }
129 }
130 }
131
OnVsync(int64_t timestamp,void * client)132 void VsyncStation::OnVsync(int64_t timestamp, void* client)
133 {
134 auto vsyncClient = static_cast<VsyncStation*>(client);
135 if (vsyncClient) {
136 vsyncClient->VsyncCallbackInner(timestamp);
137 WindowFrameTraceImpl::GetInstance()->VsyncStopFrameTrace();
138 } else {
139 WLOGFE("VsyncClient is null");
140 }
141 }
142
OnVsyncTimeOut()143 void VsyncStation::OnVsyncTimeOut()
144 {
145 WLOGD("Vsync time out");
146 std::lock_guard<std::mutex> lock(mtx_);
147 hasRequestedVsync_ = false;
148 }
149 }
150 }
151