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