• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_receiver.h"
17 #include <memory>
18 #include <mutex>
19 #include <unistd.h>
20 #include <scoped_bytrace.h>
21 #include <fcntl.h>
22 #include <hitrace_meter.h>
23 
24 #include "accesstoken_kit.h"
25 #include "event_handler.h"
26 #include "graphic_common.h"
27 #include "ipc_skeleton.h"
28 #include "parameters.h"
29 #include "rs_frame_report_ext.h"
30 #include "vsync_log.h"
31 #include "sandbox_utils.h"
32 #include <rs_trace.h>
33 #include "qos.h"
34 
35 namespace OHOS {
36 namespace Rosen {
37 namespace {
38 constexpr int32_t INVALID_FD = -1;
39 static const int32_t APP_VSYNC_PRIORITY = system::GetIntParameter("const.graphic.app_vsync_priority", -1);
40 }
VSyncReceiver(const sptr<IVSyncConnection> & conn,const sptr<IRemoteObject> & token,const std::shared_ptr<OHOS::AppExecFwk::EventHandler> & looper,const std::string & name)41 VSyncReceiver::VSyncReceiver(const sptr<IVSyncConnection>& conn,
42     const sptr<IRemoteObject>& token,
43     const std::shared_ptr<OHOS::AppExecFwk::EventHandler>& looper,
44     const std::string& name)
45     : connection_(conn), token_(token), looper_(looper),
46     listener_(std::make_shared<VSyncCallBackListener>()),
47     init_(false),
48     fd_(INVALID_FD),
49     name_(name)
50 {
51 };
52 
RegisterFileDescriptorListener()53 void VSyncReceiver::RegisterFileDescriptorListener()
54 {
55     auto selfToken = IPCSkeleton::GetSelfTokenID();
56     auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(static_cast<uint32_t>(selfToken));
57     bool isAppMainThread = (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) && (getpid() == gettid());
58     if (isAppMainThread && (static_cast<int32_t>(AppExecFwk::EventQueue::Priority::VIP) <= APP_VSYNC_PRIORITY) &&
59         (static_cast<int32_t>(AppExecFwk::EventQueue::Priority::IDLE) >= APP_VSYNC_PRIORITY)) {
60         listener_->SetDeamonWaiter();
61         listener_->SetType(AppExecFwk::FileDescriptorListener::ListenerType::LTYPE_VSYNC);
62         looper_->AddFileDescriptorListener(fd_, AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT, listener_, "vSyncTask",
63             static_cast<AppExecFwk::EventQueue::Priority>(APP_VSYNC_PRIORITY));
64     } else {
65         looper_->AddFileDescriptorListener(fd_, AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT, listener_, "vSyncTask");
66     }
67 }
68 
Init()69 VsyncError VSyncReceiver::Init()
70 {
71     std::lock_guard<std::mutex> locker(initMutex_);
72     if (init_) {
73         return VSYNC_ERROR_OK;
74     }
75     if (connection_ == nullptr) {
76         return VSYNC_ERROR_NULLPTR;
77     }
78 
79     if (looper_ == nullptr) {
80         std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("OS_VSyncThread");
81         if (runner == nullptr) {
82             return VSYNC_ERROR_API_FAILED;
83         }
84         looper_ = std::make_shared<AppExecFwk::EventHandler>(runner);
85         runner->Run();
86         looper_->PostTask([] {
87             SetThreadQos(QOS::QosLevel::QOS_USER_INTERACTIVE);
88         });
89     }
90 
91     VsyncError ret = connection_->GetReceiveFd(fd_);
92     if (ret != VSYNC_ERROR_OK) {
93         return ret;
94     }
95 
96     int32_t retVal = fcntl(fd_, F_SETFL, O_NONBLOCK); // set fd to NonBlock mode
97     if (retVal != 0) {
98         VLOGW("%{public}s fcntl set fd_:%{public}d NonBlock failed, retVal:%{public}d, errno:%{public}d",
99             __func__, fd_, retVal, errno);
100     }
101 
102     listener_->SetName(name_);
103     listener_->RegisterFdShutDownCallback([this](int32_t fileDescriptor) {
104         std::lock_guard<std::mutex> locker(initMutex_);
105         if (fileDescriptor != fd_) {
106             VLOGE("OnShutdown Invalid fileDescriptor:%{public}d, fd_:%{public}d", fileDescriptor, fd_);
107             return;
108         }
109         RemoveAndCloseFdLocked();
110     });
111     listener_->RegisterReadableCallback([this](int32_t fileDescriptor) -> bool {
112         std::lock_guard<std::mutex> locker(initMutex_);
113         if (fileDescriptor != fd_) {
114             VLOGE("OnReadable Invalid fileDescriptor:%{public}d, fd_:%{public}d", fileDescriptor, fd_);
115             return false;
116         }
117         return true;
118     });
119 
120     RegisterFileDescriptorListener();
121     init_ = true;
122     return VSYNC_ERROR_OK;
123 }
124 
~VSyncReceiver()125 VSyncReceiver::~VSyncReceiver()
126 {
127     listener_->RegisterFdShutDownCallback(nullptr);
128     listener_->RegisterReadableCallback(nullptr);
129     std::lock_guard<std::mutex> locker(initMutex_);
130     RemoveAndCloseFdLocked();
131     DestroyLocked();
132 }
133 
RemoveAndCloseFdLocked()134 void VSyncReceiver::RemoveAndCloseFdLocked()
135 {
136     if (looper_ != nullptr) {
137         looper_->RemoveFileDescriptorListener(fd_);
138         VLOGI("%{public}s looper remove fd listener, fd=%{public}d", __func__, fd_);
139     }
140 
141     std::lock_guard<std::mutex> locker(listener_->fdMutex_);
142     if (fd_ >= 0) {
143         close(fd_);
144         listener_->SetFdClosedFlagLocked(true);
145         fd_ = INVALID_FD;
146     }
147 }
148 
RequestNextVSync(FrameCallback callback)149 VsyncError VSyncReceiver::RequestNextVSync(FrameCallback callback)
150 {
151     return RequestNextVSync(callback, "unknown", 0);
152 }
153 
RequestNextVSync(FrameCallback callback,const std::string & fromWhom,int64_t lastVSyncTS)154 VsyncError VSyncReceiver::RequestNextVSync(FrameCallback callback, const std::string &fromWhom, int64_t lastVSyncTS)
155 {
156     std::lock_guard<std::mutex> locker(initMutex_);
157     if (!init_) {
158         VLOGE("%{public}s not init", __func__);
159         return VSYNC_ERROR_NOT_INIT;
160     }
161     listener_->SetCallback(callback);
162     listener_->SetRNVFlag(true);
163     ScopedDebugTrace func("VSyncReceiver::RequestNextVSync:" + name_);
164     if (OHOS::Rosen::RsFrameReportExt::GetInstance().GetEnable()) {
165         OHOS::Rosen::RsFrameReportExt::GetInstance().RequestNextVSync();
166     }
167     return connection_->RequestNextVSync(fromWhom, lastVSyncTS);
168 }
169 
RequestNextVSyncWithMultiCallback(FrameCallback callback)170 VsyncError VSyncReceiver::RequestNextVSyncWithMultiCallback(FrameCallback callback)
171 {
172     std::lock_guard<std::mutex> locker(initMutex_);
173     if (!init_) {
174         VLOGE("%{public}s not init", __func__);
175         return VSYNC_ERROR_NOT_INIT;
176     }
177     listener_->AddCallback(callback);
178     listener_->SetRNVFlag(true);
179     ScopedDebugTrace func("VSyncReceiver::RequestNextVSync:" + name_);
180     if (OHOS::Rosen::RsFrameReportExt::GetInstance().GetEnable()) {
181         OHOS::Rosen::RsFrameReportExt::GetInstance().RequestNextVSync();
182     }
183     return connection_->RequestNextVSync();
184 }
185 
SetVSyncRate(FrameCallback callback,int32_t rate)186 VsyncError VSyncReceiver::SetVSyncRate(FrameCallback callback, int32_t rate)
187 {
188     std::lock_guard<std::mutex> locker(initMutex_);
189     if (!init_) {
190         return VSYNC_ERROR_API_FAILED;
191     }
192     listener_->SetCallback(callback);
193     return connection_->SetVSyncRate(rate);
194 }
195 
196 /* 设置每帧回调 */
SetVsyncCallBackForEveryFrame(FrameCallback callback,bool isOpen)197 VsyncError VSyncReceiver::SetVsyncCallBackForEveryFrame(FrameCallback callback, bool isOpen)
198 {
199     if (isOpen) {
200         return SetVSyncRate(callback, 1);
201     } else {
202         return SetVSyncRate(callback, -1);
203     }
204 }
205 
GetVSyncPeriod(int64_t & period)206 VsyncError VSyncReceiver::GetVSyncPeriod(int64_t &period)
207 {
208     int64_t timeStamp;
209     return GetVSyncPeriodAndLastTimeStamp(period, timeStamp);
210 }
211 
GetVSyncPeriodAndLastTimeStamp(int64_t & period,int64_t & timeStamp,bool isThreadShared)212 VsyncError VSyncReceiver::GetVSyncPeriodAndLastTimeStamp(int64_t &period, int64_t &timeStamp, bool isThreadShared)
213 {
214     std::lock_guard<std::mutex> locker(initMutex_);
215     if (!init_) {
216         VLOGE("%{public}s not init", __func__);
217         return VSYNC_ERROR_NOT_INIT;
218     }
219     if (isThreadShared == false) {
220         int64_t periodNotShared = listener_->GetPeriod();
221         int64_t timeStampNotShared = listener_->GetTimeStamp();
222         if (periodNotShared == 0 || timeStampNotShared == 0) {
223             VLOGD("%{public}s Hardware vsync is not available. please try again later!", __func__);
224             return VSYNC_ERROR_UNKOWN;
225         }
226         period = periodNotShared;
227         timeStamp = timeStampNotShared;
228     } else {
229         int64_t periodShared = listener_->GetPeriodShared();
230         int64_t timeStampShared = listener_->GetTimeStampShared();
231         if (periodShared == 0 || timeStampShared == 0) {
232             VLOGD("%{public}s Hardware vsync is not available. please try again later!", __func__);
233             return VSYNC_ERROR_UNKOWN;
234         }
235         period = periodShared;
236         timeStamp = timeStampShared;
237     }
238     RS_TRACE_NAME_FMT("VSyncReceiver:period:%ld timeStamp:%ld isThreadShared:%d", period, timeStamp, isThreadShared);
239     return VSYNC_ERROR_OK;
240 }
241 
CloseVsyncReceiverFd()242 void VSyncReceiver::CloseVsyncReceiverFd()
243 {
244     std::lock_guard<std::mutex> locker(initMutex_);
245     RemoveAndCloseFdLocked();
246 }
247 
DestroyLocked()248 VsyncError VSyncReceiver::DestroyLocked()
249 {
250     if (connection_ == nullptr) {
251         return VSYNC_ERROR_API_FAILED;
252     }
253     return connection_->Destroy();
254 }
255 
IsRequestedNextVSync()256 bool VSyncReceiver::IsRequestedNextVSync()
257 {
258     std::lock_guard<std::mutex> locker(initMutex_);
259     if (!init_) {
260         return false;
261     }
262     return listener_->GetRNVFlag();
263 }
264 
SetUiDvsyncSwitch(bool dvsyncSwitch)265 VsyncError VSyncReceiver::SetUiDvsyncSwitch(bool dvsyncSwitch)
266 {
267     std::lock_guard<std::mutex> locker(initMutex_);
268     if (!init_) {
269         return VSYNC_ERROR_API_FAILED;
270     }
271     return connection_->SetUiDvsyncSwitch(dvsyncSwitch);
272 }
273 
SetUiDvsyncConfig(int32_t bufferCount)274 VsyncError VSyncReceiver::SetUiDvsyncConfig(int32_t bufferCount)
275 {
276     std::lock_guard<std::mutex> locker(initMutex_);
277     if (!init_) {
278         return VSYNC_ERROR_API_FAILED;
279     }
280     VLOGI("%{public}s bufferCount:%{public}d", __func__, bufferCount);
281     return connection_->SetUiDvsyncConfig(bufferCount);
282 }
283 
SetNativeDVSyncSwitch(bool dvsyncSwitch)284 VsyncError VSyncReceiver::SetNativeDVSyncSwitch(bool dvsyncSwitch)
285 {
286     std::lock_guard<std::mutex> locker(initMutex_);
287     if (!init_) {
288         return VSYNC_ERROR_API_FAILED;
289     }
290     return connection_->SetNativeDVSyncSwitch(dvsyncSwitch);
291 }
292 } // namespace Rosen
293 } // namespace OHOS
294