1 /*
2 * Copyright (c) 2024 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 "bridge/cj_frontend/cppview/native_view.h"
17
18 #include "bridge/cj_frontend/runtime/cj_runtime_delegate.h"
19 #include "core/components_ng/base/view_partial_update_model.h"
20 #include "core/components_ng/base/view_stack_model.h"
21 #include "core/components_ng/pattern/custom/custom_measure_layout_node.h"
22 #include "core/components_ng/pattern/recycle_view/recycle_dummy_node.h"
23
24 namespace OHOS::Ace::Framework {
25
GetProcessViewId(int64_t id)26 std::string GetProcessViewId(int64_t id)
27 {
28 return ViewStackModel::GetInstance()->ProcessViewId(std::to_string(id));
29 }
30
NativeView(sptr<RemoteView> cjView)31 NativeView::NativeView(sptr<RemoteView> cjView) : cjView_(std::move(cjView))
32 {
33 LOGD("Native View constructed: %{public}" PRId64 ".", GetID());
34 useNewPipeline_ = Container::IsCurrentUseNewPipeline();
35 instanceId_ = Container::CurrentId();
36 }
37
~NativeView()38 NativeView::~NativeView()
39 {
40 LOGD("Native View Destroyed: %{public}" PRId64 ".", GetID());
41 };
42
GetDeletedElemtIds(std::vector<int64_t> & vec)43 void NativeView::GetDeletedElemtIds(std::vector<int64_t>& vec)
44 {
45 LOGD("NativeView, getting elmtIds of all deleted Elements from ElementRegister:");
46 }
47
DeletedElmtIdsHaveBeenPurged(std::vector<int64_t> & vec)48 void NativeView::DeletedElmtIdsHaveBeenPurged(std::vector<int64_t>& vec)
49 {
50 LOGD("NativeView, getting elmtIds of all deleted Elements from ElementRegister:");
51 }
52
CreateUI()53 RefPtr<AceType> NativeView::CreateUI()
54 {
55 wptr<NativeView> weakThis = this;
56 NodeInfoPU partialUpdateCallbacks {
57 .appearFunc = [weakThis]() -> void {
58 auto self = weakThis.promote();
59 CHECK_NULL_VOID(self);
60 ContainerScope scope(self->instanceId_);
61 self->cjView_->OnAppear();
62 },
63 .renderFunc = [weakThis](int64_t deadline, bool& isTimeout) -> RefPtr<AceType> {
64 auto self = weakThis.promote();
65 CHECK_NULL_RETURN(self, nullptr);
66 ContainerScope scope(self->instanceId_);
67 if (!self->isFirstRender_) {
68 LOGW("the view has already called initial render");
69 return nullptr;
70 }
71 self->isFirstRender_ = false;
72 return self->InitialUIRender();
73 },
74 .updateFunc = [weakThis]() -> void {
75 auto self = weakThis.promote();
76 CHECK_NULL_VOID(self);
77 ContainerScope scope(self->instanceId_);
78 if (!self->needsUpdate_) {
79 LOGW("the view does not need to update");
80 return;
81 }
82 self->needsUpdate_ = false;
83 self->cjView_->Rerender();
84 for (const UpdateTask& updateTask : self->pendingUpdateTasks_) {
85 ViewPartialUpdateModel::GetInstance()->FlushUpdateTask(updateTask);
86 }
87 self->pendingUpdateTasks_.clear();
88 },
89 .removeFunc = [weakThis]() {
90 auto self = weakThis.promote();
91 CHECK_NULL_VOID(self);
92 self->Destroy();
93 },
94 .reloadFunc = [weakThis](bool deep) {
95 auto self = weakThis.promote();
96 CHECK_NULL_VOID(self);
97 ContainerScope scope(self->instanceId_);
98 self->cjView_->Reload(deep);
99 },
100 .didBuildFunc =
101 [weakThis]() {
102 auto self = weakThis.promote();
103 CHECK_NULL_VOID(self);
104 ContainerScope scope(self->instanceId_);
105 self->cjView_->OnDidBuild();
106 },
107 .completeReloadFunc = [weakThis](int64_t deadline, bool& isTimeout) -> RefPtr<AceType> {
108 auto view = weakThis.promote();
109 CHECK_NULL_RETURN(view, nullptr);
110 ContainerScope scope(view->instanceId_);
111 return view->InitialUIRender();
112 },
113 .recycleFunc =
114 [weakThis]() {
115 auto self = weakThis.promote();
116 CHECK_NULL_VOID(self);
117 ContainerScope scope(self->instanceId_);
118 self->cjView_->AboutToRecycle();
119 },
120 .reuseFunc =
121 [weakThis](void* params) {
122 auto self = weakThis.promote();
123 CHECK_NULL_VOID(self);
124 ContainerScope scope(self->instanceId_);
125 // only support string yet in cj
126 std::string* val = static_cast<std::string*>(params);
127 CHECK_NULL_VOID(val);
128 self->cjView_->AboutToReuse(*val);
129 },
130 .recycleCustomNodeFunc = [weakThis](const RefPtr<NG::CustomNodeBase>& recycleNode) -> void {
131 auto self = weakThis.promote();
132 CHECK_NULL_VOID(self);
133 ContainerScope scope(self->instanceId_);
134 auto name = self->GetRecycleCustomNodeName();
135 if (name.empty()) {
136 return;
137 }
138 auto recycleUINode = AceType::DynamicCast<NG::UINode>(recycleNode);
139 recycleUINode->SetActive(false);
140 self->SetRecycleCustomNode(recycleNode);
141 self->cjView_->RecycleSelf(name);
142 if (!recycleNode->HasRecycleRenderFunc() && self->recycleCustomNode_) {
143 recycleUINode->SetJSViewActive(false, false, true);
144 self->cjView_->AboutToRecycle();
145 }
146 recycleNode->ResetRecycle();
147 },
148 };
149 auto node = ViewPartialUpdateModel::GetInstance()->CreateNode(std::move(partialUpdateCallbacks));
150 node_ = node;
151 return node;
152 }
153
InitialUIRender()154 RefPtr<AceType> NativeView::InitialUIRender()
155 {
156 needsUpdate_ = false;
157 {
158 cjView_->OnAboutToRender();
159 }
160 {
161 cjView_->Render();
162 }
163 {
164 cjView_->OnAfterRender();
165 if (onRenderDone_) {
166 onRenderDone_();
167 }
168 }
169 return ViewStackModel::GetInstance()->Finish();
170 }
171
SyncInstanceId()172 void NativeView::SyncInstanceId()
173 {
174 restoreInstanceId_ = Container::CurrentId();
175 ContainerScope::UpdateCurrent(instanceId_);
176 }
177
RestoreInstanceId()178 void NativeView::RestoreInstanceId()
179 {
180 ContainerScope::UpdateCurrent(restoreInstanceId_);
181 }
182
183 /**
184 * marks the NativeView's composed component as needing update / rerender
185 */
MarkNeedUpdate()186 void NativeView::MarkNeedUpdate()
187 {
188 needsUpdate_ = ViewPartialUpdateModel::GetInstance()->MarkNeedUpdate(node_);
189 }
190
FlushReload()191 void NativeView::FlushReload()
192 {
193 auto node = node_.Upgrade();
194 if (!node) {
195 LOGE("fail to update due to custom Node is null");
196 return;
197 }
198 if (AceType::InstanceOf<NG::CustomNode>(node)) {
199 auto customNode = AceType::DynamicCast<NG::CustomNode>(node);
200 customNode->FlushReload();
201 }
202 }
203
FinishUpdateFunc(int32_t elmtId)204 void NativeView::FinishUpdateFunc(int32_t elmtId)
205 {
206 wptr<NativeView> weakThis = this;
207 ViewPartialUpdateModel::GetInstance()->FinishUpdate(node_, elmtId, [weakThis](const UpdateTask& task) {
208 auto cjView = weakThis.promote();
209 if (cjView) {
210 cjView->pendingUpdateTasks_.push_back(task);
211 }
212 });
213 }
214
Destroy()215 void NativeView::Destroy()
216 {
217 if (!cjView_) {
218 LOGE("NativeView::Destroy error, nativeId: %{public}" PRId64 " cj view not exist.", GetID());
219 return;
220 }
221 LOGD("NativeView::Destroy start, nativeId: %{public}" PRId64 ", cjId: %{public}" PRId64, GetID(), cjView_->GetID());
222 {
223 cjView_->OnDisappear();
224 }
225 {
226 cjView_->OnAboutToBeDeleted();
227 }
228 pendingUpdateTasks_.clear();
229 LOGD("NativeView::Destroy end");
230 }
231
Create(const sptr<NativeView> & view)232 void NativeView::Create(const sptr<NativeView>& view)
233 {
234 ViewStackModel::GetInstance()->Push(view->CreateUI(), true);
235 }
236
CreateRecycle(const sptr<NativeView> & view,bool isRecycling,const std::string & nodeName,std::function<void ()> callback)237 void NativeView::CreateRecycle(
238 const sptr<NativeView>& view, bool isRecycling, const std::string& nodeName, std::function<void()> callback)
239 {
240 auto recycleUpdateFunc = [cjView = view, func = std::move(callback)]() -> void {
241 CHECK_NULL_VOID(cjView);
242 cjView->SetIsRecycleRerender(true);
243 func();
244 cjView->SetIsRecycleRerender(false);
245 };
246 view->SetRecycleCustomNodeName(nodeName);
247 RefPtr<AceType> node;
248
249 if (isRecycling) {
250 node = view->GetCachedRecycleNode();
251 AceType::DynamicCast<NG::CustomNodeBase>(node)->SetRecycleRenderFunc(std::move(recycleUpdateFunc));
252 } else {
253 node = view->CreateUI();
254 }
255 auto* stack = NG::ViewStackProcessor::GetInstance();
256 auto dummyNode = NG::RecycleDummyNode::WrapRecycleDummyNode(node, stack->GetRecycleNodeId());
257 ViewStackModel::GetInstance()->Push(dummyNode, true);
258 }
259
CleanUpAbandonedChild()260 void NativeView::CleanUpAbandonedChild()
261 {
262 LOGD("NativeView::CleanUpAbandonedChild");
263 }
264
FireOnShow()265 void NativeView::FireOnShow()
266 {
267 if (!cjView_) {
268 LOGE("NativeView::FireOnShow fail, no cj view on %{public}" PRId64 ".", GetID());
269 return;
270 }
271 {
272 cjView_->OnShow();
273 }
274 }
275
FireOnHide()276 void NativeView::FireOnHide()
277 {
278 if (!cjView_) {
279 LOGE("NativeView::FireOnHide fail, no cj view on %{public}" PRId64 ".", GetID());
280 return;
281 }
282 {
283 cjView_->OnHide();
284 }
285 }
286
FireOnBackPress()287 bool NativeView::FireOnBackPress()
288 {
289 if (!cjView_) {
290 LOGE("NativeView::FireOnBackPress fail, no cj view on %{public}" PRId64 ".", GetID());
291 return false;
292 }
293 {
294 return cjView_->OnBackPress();
295 }
296 }
297
FireOnTransition()298 void NativeView::FireOnTransition()
299 {
300 if (!cjView_) {
301 LOGE("NativeView::FireOnTransition fail, no cj view on %{public}" PRId64 ".", GetID());
302 return;
303 }
304 cjView_->OnTransition();
305 }
306
ExecuteUpdateWithValueParams(const std::string & jsonData)307 void NativeView::ExecuteUpdateWithValueParams(const std::string& jsonData)
308 {
309 if (!cjView_) {
310 LOGE("NativeView::ExecuteUpdateWithValueParams fail, no cj view on %{public}" PRId64 ".", GetID());
311 return;
312 }
313 cjView_->UpdateWithJson(jsonData);
314 }
315
Reload(bool deep)316 void RemoteView::Reload(bool deep)
317 {
318 auto forceCompleteRerenderFunc =
319 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewForceCompleteRerender;
320 if (!forceCompleteRerenderFunc) {
321 LOGE("CJFunc: RemoteView::ForceCompleteRerender is empty.");
322 return;
323 }
324 forceCompleteRerenderFunc(GetID(), deep);
325 }
326
VoidCallback(void (* cjFunc)(int64_t),const char * funcName)327 void RemoteView::VoidCallback(void (*cjFunc)(int64_t), const char* funcName)
328 {
329 if (!cjFunc) {
330 LOGE("CJFunc: RemoteView::%{public}s is empty.", funcName);
331 return;
332 }
333 cjFunc(GetID());
334 }
335
Render()336 void RemoteView::Render()
337 {
338 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewRender, "Render");
339 }
340
Rerender()341 void RemoteView::Rerender()
342 {
343 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewRerender, "Rerender");
344 }
345
OnShow()346 void RemoteView::OnShow()
347 {
348 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnShow, "OnShow");
349 }
350
OnHide()351 void RemoteView::OnHide()
352 {
353 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnHide, "OnHide");
354 }
355
OnBackPress()356 bool RemoteView::OnBackPress()
357 {
358 auto onBackPressFunc = CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnBackPress;
359 if (!onBackPressFunc) {
360 LOGE("CJFunc: RemoteView::OnBackPress is empty.");
361 return false;
362 }
363 return onBackPressFunc(GetID());
364 }
365
UpdateWithJson(const std::string & value)366 void RemoteView::UpdateWithJson(const std::string& value)
367 {
368 auto updateWithJsonFunc =
369 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewUpdateWithJson;
370 if (!updateWithJsonFunc) {
371 LOGE("CJFunc: RemoteView::UpdateWithJson is empty.");
372 return;
373 }
374 updateWithJsonFunc(GetID(), value.c_str());
375 }
376
OnAppear()377 void RemoteView::OnAppear()
378 {
379 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAppear, "OnAppear");
380 }
381
OnTransition()382 void RemoteView::OnTransition()
383 {
384 VoidCallback(
385 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnTransition, "OnTransition");
386 }
387
OnAboutToRender()388 void RemoteView::OnAboutToRender()
389 {
390 VoidCallback(
391 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAboutToRender, "OnAboutToRender");
392 }
393
OnAboutToBeDeleted()394 void RemoteView::OnAboutToBeDeleted()
395 {
396 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAboutToBeDeleted,
397 "OnAboutToBeDeleted");
398 }
399
OnAfterRender()400 void RemoteView::OnAfterRender()
401 {
402 VoidCallback(
403 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAfterRender, "OnAfterRender");
404 }
405
OnDisappear()406 void RemoteView::OnDisappear()
407 {
408 VoidCallback(
409 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnDisappear, "OnDisappear");
410 }
411
OnDidBuild()412 void RemoteView::OnDidBuild()
413 {
414 VoidCallback(
415 CJRuntimeDelegate::GetInstance()->GetCJFuncsV2().atCOHOSAceFrameworkRemoteViewOnDidBuild, "OnDidBuild");
416 }
417
AboutToReuse(const std::string & value)418 void RemoteView::AboutToReuse(const std::string& value)
419 {
420 auto aboutToReuseFunc = CJRuntimeDelegate::GetInstance()->GetCJFuncsV2().atCOHOSAceFrameworkRemoteViewAboutToReuse;
421 if (!aboutToReuseFunc) {
422 LOGE("CJFunc: RemoteView::AboutToReuse is empty.");
423 return;
424 }
425 aboutToReuseFunc(GetID(), value.c_str());
426 }
427
AboutToRecycle()428 void RemoteView::AboutToRecycle()
429 {
430 VoidCallback(
431 CJRuntimeDelegate::GetInstance()->GetCJFuncsV2().atCOHOSAceFrameworkRemoteViewAboutToRecycle, "AboutToRecycle");
432 }
433
RecycleSelf(const std::string & value)434 void RemoteView::RecycleSelf(const std::string& value)
435 {
436 auto recycleSelfFunc = CJRuntimeDelegate::GetInstance()->GetCJFuncsV2().atCOHOSAceFrameworkRemoteViewRecycleSelf;
437 if (!recycleSelfFunc) {
438 LOGE("CJFunc: RemoteView::RecycleSelf is empty.");
439 return;
440 }
441 recycleSelfFunc(GetID(), value.c_str());
442 }
443 } // namespace OHOS::Ace::Framework
444