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 .didBuildFunc =
64 [weakThis]() {
65 auto self = weakThis.promote();
66 CHECK_NULL_VOID(self);
67 ContainerScope scope(self->instanceId_);
68 self->cjView_->OnDidBuild();
69 },
70 .renderFunc = [weakThis](int64_t deadline, bool& isTimeout) -> RefPtr<AceType> {
71 auto self = weakThis.promote();
72 CHECK_NULL_RETURN(self, nullptr);
73 ContainerScope scope(self->instanceId_);
74 if (!self->isFirstRender_) {
75 LOGW("the view has already called initial render");
76 return nullptr;
77 }
78 self->isFirstRender_ = false;
79 return self->InitialUIRender();
80 },
81 .updateFunc = [weakThis]() -> void {
82 auto self = weakThis.promote();
83 CHECK_NULL_VOID(self);
84 ContainerScope scope(self->instanceId_);
85 if (!self->needsUpdate_) {
86 LOGW("the view does not need to update");
87 return;
88 }
89 self->needsUpdate_ = false;
90 self->cjView_->Rerender();
91 for (const UpdateTask& updateTask : self->pendingUpdateTasks_) {
92 ViewPartialUpdateModel::GetInstance()->FlushUpdateTask(updateTask);
93 }
94 self->pendingUpdateTasks_.clear();
95 },
96 .removeFunc = [weakThis]() {
97 auto self = weakThis.promote();
98 CHECK_NULL_VOID(self);
99 self->Destroy();
100 },
101 .reloadFunc = [weakThis](bool deep) {
102 auto self = weakThis.promote();
103 CHECK_NULL_VOID(self);
104 ContainerScope scope(self->instanceId_);
105 self->cjView_->Reload(deep);
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 .recycleCustomNodeFunc = [weakThis](const RefPtr<NG::CustomNodeBase>& recycleNode) -> void {
114 auto self = weakThis.promote();
115 CHECK_NULL_VOID(self);
116 ContainerScope scope(self->instanceId_);
117 auto name = self->GetRecycleCustomNodeName();
118 if (name.empty()) {
119 return;
120 }
121 auto recycleUINode = AceType::DynamicCast<NG::UINode>(recycleNode);
122 recycleUINode->SetActive(false);
123 self->SetRecycleCustomNode(recycleNode);
124 self->cjView_->RecycleSelf(name);
125 if (!recycleNode->HasRecycleRenderFunc() && self->recycleCustomNode_) {
126 recycleUINode->SetJSViewActive(false, false, true);
127 self->cjView_->AboutToRecycle();
128 }
129 recycleNode->ResetRecycle();
130 },
131 .recycleFunc =
132 [weakThis]() {
133 auto self = weakThis.promote();
134 CHECK_NULL_VOID(self);
135 ContainerScope scope(self->instanceId_);
136 self->cjView_->AboutToRecycle();
137 },
138 .reuseFunc =
139 [weakThis](void* params) {
140 auto self = weakThis.promote();
141 CHECK_NULL_VOID(self);
142 ContainerScope scope(self->instanceId_);
143 // only support string yet in cj
144 std::string* val = static_cast<std::string*>(params);
145 CHECK_NULL_VOID(val);
146 self->cjView_->AboutToReuse(*val);
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
256 auto customNodeBase = AceType::DynamicCast<NG::CustomNodeBase>(node);
257 if (customNodeBase) {
258 customNodeBase->SetReuseId(nodeName);
259 }
260 auto* stack = NG::ViewStackProcessor::GetInstance();
261 auto dummyNode = NG::RecycleDummyNode::WrapRecycleDummyNode(node, stack->GetRecycleNodeId());
262 ViewStackModel::GetInstance()->Push(dummyNode, true);
263 }
264
CleanUpAbandonedChild()265 void NativeView::CleanUpAbandonedChild()
266 {
267 LOGD("NativeView::CleanUpAbandonedChild");
268 }
269
FireOnShow()270 void NativeView::FireOnShow()
271 {
272 if (!cjView_) {
273 LOGE("NativeView::FireOnShow fail, no cj view on %{public}" PRId64 ".", GetID());
274 return;
275 }
276 {
277 cjView_->OnShow();
278 }
279 }
280
FireOnHide()281 void NativeView::FireOnHide()
282 {
283 if (!cjView_) {
284 LOGE("NativeView::FireOnHide fail, no cj view on %{public}" PRId64 ".", GetID());
285 return;
286 }
287 {
288 cjView_->OnHide();
289 }
290 }
291
FireOnBackPress()292 bool NativeView::FireOnBackPress()
293 {
294 if (!cjView_) {
295 LOGE("NativeView::FireOnBackPress fail, no cj view on %{public}" PRId64 ".", GetID());
296 return false;
297 }
298 {
299 return cjView_->OnBackPress();
300 }
301 }
302
FireOnTransition()303 void NativeView::FireOnTransition()
304 {
305 if (!cjView_) {
306 LOGE("NativeView::FireOnTransition fail, no cj view on %{public}" PRId64 ".", GetID());
307 return;
308 }
309 cjView_->OnTransition();
310 }
311
ExecuteUpdateWithValueParams(const std::string & jsonData)312 void NativeView::ExecuteUpdateWithValueParams(const std::string& jsonData)
313 {
314 if (!cjView_) {
315 LOGE("NativeView::ExecuteUpdateWithValueParams fail, no cj view on %{public}" PRId64 ".", GetID());
316 return;
317 }
318 cjView_->UpdateWithJson(jsonData);
319 }
320
Reload(bool deep)321 void RemoteView::Reload(bool deep)
322 {
323 auto forceCompleteRerenderFunc =
324 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewForceCompleteRerender;
325 if (!forceCompleteRerenderFunc) {
326 LOGE("CJFunc: RemoteView::ForceCompleteRerender is empty.");
327 return;
328 }
329 forceCompleteRerenderFunc(GetID(), deep);
330 }
331
VoidCallback(void (* cjFunc)(int64_t),const char * funcName)332 void RemoteView::VoidCallback(void (*cjFunc)(int64_t), const char* funcName)
333 {
334 if (!cjFunc) {
335 LOGE("CJFunc: RemoteView::%{public}s is empty.", funcName);
336 return;
337 }
338 cjFunc(GetID());
339 }
340
Render()341 void RemoteView::Render()
342 {
343 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewRender, "Render");
344 }
345
Rerender()346 void RemoteView::Rerender()
347 {
348 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewRerender, "Rerender");
349 }
350
OnShow()351 void RemoteView::OnShow()
352 {
353 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnShow, "OnShow");
354 }
355
OnHide()356 void RemoteView::OnHide()
357 {
358 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnHide, "OnHide");
359 }
360
OnBackPress()361 bool RemoteView::OnBackPress()
362 {
363 auto onBackPressFunc = CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnBackPress;
364 if (!onBackPressFunc) {
365 LOGE("CJFunc: RemoteView::OnBackPress is empty.");
366 return false;
367 }
368 return onBackPressFunc(GetID());
369 }
370
UpdateWithJson(const std::string & value)371 void RemoteView::UpdateWithJson(const std::string& value)
372 {
373 auto updateWithJsonFunc =
374 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewUpdateWithJson;
375 if (!updateWithJsonFunc) {
376 LOGE("CJFunc: RemoteView::UpdateWithJson is empty.");
377 return;
378 }
379 updateWithJsonFunc(GetID(), value.c_str());
380 }
381
OnAppear()382 void RemoteView::OnAppear()
383 {
384 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAppear, "OnAppear");
385 }
386
OnTransition()387 void RemoteView::OnTransition()
388 {
389 VoidCallback(
390 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnTransition, "OnTransition");
391 }
392
OnAboutToRender()393 void RemoteView::OnAboutToRender()
394 {
395 VoidCallback(
396 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAboutToRender, "OnAboutToRender");
397 }
398
OnAboutToBeDeleted()399 void RemoteView::OnAboutToBeDeleted()
400 {
401 VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAboutToBeDeleted,
402 "OnAboutToBeDeleted");
403 }
404
OnAfterRender()405 void RemoteView::OnAfterRender()
406 {
407 VoidCallback(
408 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAfterRender, "OnAfterRender");
409 }
410
OnDisappear()411 void RemoteView::OnDisappear()
412 {
413 VoidCallback(
414 CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnDisappear, "OnDisappear");
415 }
416
OnDidBuild()417 void RemoteView::OnDidBuild()
418 {
419 VoidCallback(
420 CJRuntimeDelegate::GetInstance()->GetCJFuncsV2().atCOHOSAceFrameworkRemoteViewOnDidBuild, "OnDidBuild");
421 }
422
AboutToReuse(const std::string & value)423 void RemoteView::AboutToReuse(const std::string& value)
424 {
425 auto aboutToReuseFunc = CJRuntimeDelegate::GetInstance()->GetCJFuncsV2().atCOHOSAceFrameworkRemoteViewAboutToReuse;
426 if (!aboutToReuseFunc) {
427 LOGE("CJFunc: RemoteView::AboutToReuse is empty.");
428 return;
429 }
430 aboutToReuseFunc(GetID(), value.c_str());
431 }
432
AboutToRecycle()433 void RemoteView::AboutToRecycle()
434 {
435 VoidCallback(
436 CJRuntimeDelegate::GetInstance()->GetCJFuncsV2().atCOHOSAceFrameworkRemoteViewAboutToRecycle, "AboutToRecycle");
437 }
438
RecycleSelf(const std::string & value)439 void RemoteView::RecycleSelf(const std::string& value)
440 {
441 auto recycleSelfFunc = CJRuntimeDelegate::GetInstance()->GetCJFuncsV2().atCOHOSAceFrameworkRemoteViewRecycleSelf;
442 if (!recycleSelfFunc) {
443 LOGE("CJFunc: RemoteView::RecycleSelf is empty.");
444 return;
445 }
446 recycleSelfFunc(GetID(), value.c_str());
447 }
448 } // namespace OHOS::Ace::Framework
449