• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_adapter_impl.h"
17 
18 #include <dlfcn.h>
19 
20 #include "aafwk_browser_client_adapter_impl.h"
21 #include "application_context.h"
22 #include "nweb_log.h"
23 #include "res_sched_client_adapter.h"
24 #include "system_properties_adapter_impl.h"
25 #include "transaction/rs_interfaces.h"
26 
27 namespace OHOS::NWeb {
28 namespace {
29 const std::string THREAD_NAME = "VSync-webview";
30 constexpr int32_t WEBVIEW_FRAME_RATE_TYPE = 4;
31 const std::string APS_CLIENT_SO = "/system/lib64/libaps_client.z.so";
32 #if defined(NWEB_GRAPHIC_2D_EXT_ENABLE)
33 constexpr int32_t APS_MANAGER_CLOSE_ALL = 2;
34 #endif
35 }
36 
37 void (*VSyncAdapterImpl::callback_)() = nullptr;
38 void (*VSyncAdapterImpl::onVsyncEndCallback_)() = nullptr;
39 
~VSyncAdapterImpl()40 VSyncAdapterImpl::~VSyncAdapterImpl()
41 {
42     if (vsyncHandler_) {
43         UninitAPSClient();
44         vsyncHandler_->RemoveAllEvents();
45         auto runner = vsyncHandler_->GetEventRunner();
46         if (runner) {
47             runner->Stop();
48             ResSchedClientAdapter::ReportKeyThread(ResSchedStatusAdapter::THREAD_DESTROYED,
49                 getprocpid(), runner->GetKernelThreadId(), ResSchedRoleAdapter::USER_INTERACT);
50         }
51         vsyncHandler_ = nullptr;
52     }
53     hasReportedKeyThread_ = false;
54 }
55 
GetInstance()56 VSyncAdapterImpl& VSyncAdapterImpl::GetInstance()
57 {
58     static VSyncAdapterImpl instance;
59     return instance;
60 }
61 
Init()62 VSyncErrorCode VSyncAdapterImpl::Init()
63 {
64     if (!receiver_) {
65         if (!vsyncHandler_) {
66             std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create(THREAD_NAME);
67             vsyncHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
68             runner->Run();
69         }
70         auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();
71         frameRateLinker_ = OHOS::Rosen::RSFrameRateLinker::Create();
72         receiver_ = rsClient.CreateVSyncReceiver(
73             "NWeb_" + std::to_string(::getprocpid()), frameRateLinker_->GetId(), vsyncHandler_);
74         if (!receiver_) {
75             WVLOG_E("CreateVSyncReceiver failed");
76             return VSyncErrorCode::ERROR;
77         }
78         VsyncError ret = receiver_->Init();
79         if (ret != VsyncError::GSERROR_OK) {
80             receiver_ = nullptr;
81             WVLOG_E("vsync receiver init failed, ret=%{public}d", ret);
82             return VSyncErrorCode::ERROR;
83         }
84     }
85     return VSyncErrorCode::SUCCESS;
86 }
87 
RequestVsync(void * data,NWebVSyncCb cb)88 VSyncErrorCode VSyncAdapterImpl::RequestVsync(void* data, NWebVSyncCb cb)
89 {
90     if (Init() != VSyncErrorCode::SUCCESS) {
91         WVLOG_E("NWebWindowAdapter init fail");
92         return VSyncErrorCode::ERROR;
93     }
94 
95     if (!hasReportedKeyThread_) {
96         auto runner = vsyncHandler_->GetEventRunner();
97         // At this point, the threadId corresponding to eventrunner may not be available,
98         // so need to confirm it several times
99         if (runner && runner->GetKernelThreadId() != 0) {
100             if (!isGPUProcess_) {
101                 ResSchedClientAdapter::ReportKeyThread(ResSchedStatusAdapter::THREAD_CREATED,
102                 getprocpid(), runner->GetKernelThreadId(), ResSchedRoleAdapter::USER_INTERACT);
103             } else {
104                 AafwkBrowserClientAdapterImpl::GetInstance().ReportThread(ResSchedStatusAdapter::THREAD_CREATED,
105                 getprocpid(), runner->GetKernelThreadId(), ResSchedRoleAdapter::USER_INTERACT);
106             }
107             hasReportedKeyThread_ = true;
108         }
109     }
110 
111     std::lock_guard<std::mutex> lock(mtx_);
112     vsyncCallbacks_.insert({data, cb});
113 
114     if (hasRequestedVsync_) {
115         return VSyncErrorCode::SUCCESS;
116     }
117 
118     VsyncError ret = receiver_->RequestNextVSync(frameCallback_);
119     if (ret != VsyncError::GSERROR_OK) {
120         WVLOG_E("NWebWindowAdapter RequestNextVSync fail, ret=%{public}d", ret);
121         return VSyncErrorCode::ERROR;
122     }
123     hasRequestedVsync_ = true;
124     return VSyncErrorCode::SUCCESS;
125 }
126 
OnVsync(int64_t timestamp,void * client)127 void VSyncAdapterImpl::OnVsync(int64_t timestamp, void* client)
128 {
129     auto vsyncClient = static_cast<VSyncAdapterImpl*>(client);
130     if (vsyncClient) {
131         if (callback_) {
132             callback_();
133         }
134         vsyncClient->VsyncCallbackInner(timestamp);
135         if (onVsyncEndCallback_) {
136             onVsyncEndCallback_();
137         }
138     } else {
139         WVLOG_E("VsyncClient is null");
140     }
141 }
142 
VsyncCallbackInner(int64_t timestamp)143 void VSyncAdapterImpl::VsyncCallbackInner(int64_t timestamp)
144 {
145     std::unordered_map<void*, NWebVSyncCb> vsyncCallbacks;
146     std::lock_guard<std::mutex> lock(mtx_);
147     vsyncCallbacks = vsyncCallbacks_;
148     vsyncCallbacks_.clear();
149 
150     for (const auto& callback : vsyncCallbacks) {
151         auto func = callback.second;
152         if (func) {
153             func(timestamp, callback.first);
154         }
155     }
156     hasRequestedVsync_ = false;
157 }
158 
GetVSyncPeriod()159 int64_t VSyncAdapterImpl::GetVSyncPeriod()
160 {
161     int64_t period = 0;
162     if (Init() != VSyncErrorCode::SUCCESS) {
163         WVLOG_E("NWebWindowAdapter init fail");
164         return period;
165     }
166 
167     VsyncError ret = receiver_->GetVSyncPeriod(period);
168     if (ret != VsyncError::GSERROR_OK) {
169         WVLOG_E("NWebWindowAdapter GetVSyncPeriod fail, ret=%{public}d", ret);
170     }
171     return period;
172 }
173 
SetFrameRateLinkerEnable(bool enabled)174 void VSyncAdapterImpl::SetFrameRateLinkerEnable(bool enabled)
175 {
176     WVLOG_D("NWebWindowAdapter SetFrameRateLinkerEnable enabled=%{public}d", enabled);
177     if (frameRateLinkerEnable_ == enabled) {
178         return;
179     }
180 
181     if (frameRateLinker_) {
182         if (!enabled) {
183             Rosen::FrameRateRange range = {0, RANGE_MAX_REFRESHRATE, 0, WEBVIEW_FRAME_RATE_TYPE,
184                 Rosen::ComponentScene::WEBVIEW};
185             frameRateLinker_->UpdateFrameRateRangeImme(range);
186         }
187         frameRateLinker_->SetEnable(enabled);
188         frameRateLinkerEnable_ = enabled;
189     }
190 }
191 
SetFramePreferredRate(int32_t preferredRate)192 void VSyncAdapterImpl::SetFramePreferredRate(int32_t preferredRate)
193 {
194     Rosen::FrameRateRange range = {0, RANGE_MAX_REFRESHRATE, preferredRate, WEBVIEW_FRAME_RATE_TYPE,
195         Rosen::ComponentScene::WEBVIEW};
196     if (frameRateLinker_ && frameRateLinker_->IsEnable()) {
197         WVLOG_D("NWebWindowAdapter SetFramePreferredRate preferredRate=%{public}d", preferredRate);
198         frameRateLinker_->UpdateFrameRateRangeImme(range);
199     }
200 }
201 
SetOnVsyncCallback(void (* callback)())202 void VSyncAdapterImpl::SetOnVsyncCallback(void (*callback)())
203 {
204     WVLOG_D("callback function: %{public}ld", (long)callback);
205     callback_ = callback;
206 }
207 
SetIsGPUProcess(bool isGPU)208 void VSyncAdapterImpl::SetIsGPUProcess(bool isGPU)
209 {
210     isGPUProcess_ = isGPU;
211 }
212 
SetOnVsyncEndCallback(void (* onVsyncEndCallback)())213 void VSyncAdapterImpl::SetOnVsyncEndCallback(void (*onVsyncEndCallback)())
214 {
215     WVLOG_D("callback function: %{public}ld", (long)onVsyncEndCallback);
216     onVsyncEndCallback_ = onVsyncEndCallback;
217 }
218 
SetScene(const std::string & sceneName,uint32_t state)219 void VSyncAdapterImpl::SetScene(const std::string& sceneName, uint32_t state) {
220     WVLOG_D("APSManagerAdapterImpl SetScene sceneName=%{public}s state=%{public}u", sceneName.c_str(), state);
221     if (!apsClientHandler_) {
222         InitAPSClient();
223     }
224     if (pkgName_.empty()) {
225         auto appInfo = AbilityRuntime::ApplicationContext::GetInstance()->GetApplicationInfo();
226         if (appInfo != nullptr) {
227             pkgName_ = appInfo->bundleName.c_str();
228         }
229     }
230     if (setApsSceneFunc_) {
231         setApsSceneFunc_(pkgName_, sceneName, state);
232     }
233 }
234 
InitAPSClient()235 void VSyncAdapterImpl::InitAPSClient()
236 {
237     apsClientHandler_ = dlopen(APS_CLIENT_SO.c_str(), RTLD_NOW);
238     if (!apsClientHandler_) {
239         WVLOG_E("APSManagerClient not found");
240         return;
241     }
242     setApsSceneFunc_ = reinterpret_cast<SetApsSceneFuncType>(dlsym(apsClientHandler_, "SetApsScene"));
243     if (!setApsSceneFunc_) {
244         WVLOG_E("APSManagerClient not found");
245         dlclose(apsClientHandler_);
246     }
247 }
248 
UninitAPSClient()249 void VSyncAdapterImpl::UninitAPSClient()
250 {
251     if (setApsSceneFunc_) {
252         dlclose(apsClientHandler_);
253         setApsSceneFunc_ = nullptr;
254         apsClientHandler_ = nullptr;
255     }
256 }
257 
SetDVSyncSwitch(bool dvsyncSwitch)258 void VSyncAdapterImpl::SetDVSyncSwitch(bool dvsyncSwitch)
259 {
260     if (Init() != VSyncErrorCode::SUCCESS) {
261         WVLOG_E("NWebWindowAdatrper init fail!");
262         return;
263     }
264 
265     if (!receiver_) {
266         WVLOG_E("NWebWindowAdatrper SetDVSyncSwitch: receiver_ is nullptr!");
267         return;
268     } else if (OHOS::NWeb::SystemPropertiesAdapterImpl::GetInstance().GetBoolParameter("web.ohos.dvsync", false)) {
269         WVLOG_D("NWebWindowAdatrper SetDVSyncSwitch: dvsyncSwitch = %{public}d", dvsyncSwitch);
270         VsyncError ret = receiver_->SetNativeDVSyncSwitch(dvsyncSwitch);
271         if (ret != VsyncError::GSERROR_OK) {
272             WVLOG_E("SetNativeDVSyncSwitch failed, ret = %{public}d", ret);
273             return;
274         }
275     } else {
276         WVLOG_D("NWebWindowAdatrper SetDVSyncSwitch Disabled!");
277     }
278 }
279 } // namespace OHOS::NWeb
280