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 <cinttypes>
19 #include <utility>
20 
21 #include "base/log/ace_trace.h"
22 #include "bridge/cj_frontend/runtime/cj_runtime_delegate.h"
23 #include "core/components_ng/base/view_partial_update_model.h"
24 #include "core/components_ng/base/view_stack_model.h"
25 #include "core/components_ng/pattern/custom/custom_measure_layout_node.h"
26 
27 namespace OHOS::Ace::Framework {
28 
GetProcessViewId(int64_t id)29 std::string GetProcessViewId(int64_t id)
30 {
31     return ViewStackModel::GetInstance()->ProcessViewId(std::to_string(id));
32 }
33 
NativeView(sptr<RemoteView> cjView)34 NativeView::NativeView(sptr<RemoteView> cjView) : cjView_(std::move(cjView))
35 {
36     LOGD("Native View constructed: %{public}" PRId64 ".", GetID());
37     useNewPipeline_ = Container::IsCurrentUseNewPipeline();
38     instanceId_ = Container::CurrentId();
39 }
40 
~NativeView()41 NativeView::~NativeView()
42 {
43     LOGD("Native View Destroyed: %{public}" PRId64 ".", GetID());
44 };
45 
GetDeletedElemtIds(std::vector<int64_t> & vec)46 void NativeView::GetDeletedElemtIds(std::vector<int64_t>& vec)
47 {
48     LOGD("NativeView, getting elmtIds of all deleted Elements from ElementRegister:");
49 }
50 
DeletedElmtIdsHaveBeenPurged(std::vector<int64_t> & vec)51 void NativeView::DeletedElmtIdsHaveBeenPurged(std::vector<int64_t>& vec)
52 {
53     LOGD("NativeView, getting elmtIds of all deleted Elements from ElementRegister:");
54 }
55 
CreateUI()56 RefPtr<AceType> NativeView::CreateUI()
57 {
58     wptr<NativeView> weakThis = this;
59     NodeInfoPU partialUpdateCallbacks {
60         .appearFunc = [weakThis]() -> void {
61             auto self = weakThis.promote();
62             CHECK_NULL_VOID(self);
63             ContainerScope scope(self->instanceId_);
64             self->cjView_->OnAppear();
65         },
66         .renderFunc = [weakThis]() -> RefPtr<AceType> {
67             auto self = weakThis.promote();
68             CHECK_NULL_RETURN(self, nullptr);
69             ContainerScope scope(self->instanceId_);
70             if (!self->isFirstRender_) {
71                 LOGW("the view has already called initial render");
72                 return nullptr;
73             }
74             self->isFirstRender_ = false;
75             return self->InitialUIRender();
76         },
77         .updateFunc = [weakThis]() -> void {
78             auto self = weakThis.promote();
79             CHECK_NULL_VOID(self);
80             ContainerScope scope(self->instanceId_);
81             if (!self->needsUpdate_) {
82                 LOGW("the view does not need to update");
83                 return;
84             }
85             self->needsUpdate_ = false;
86             self->cjView_->Rerender();
87             for (const UpdateTask& updateTask : self->pendingUpdateTasks_) {
88                 ViewPartialUpdateModel::GetInstance()->FlushUpdateTask(updateTask);
89             }
90             self->pendingUpdateTasks_.clear();
91         },
92         .removeFunc = [weakThis]() {
93             auto self = weakThis.promote();
94             CHECK_NULL_VOID(self);
95             self->Destroy();
96         },
97         .reloadFunc = [weakThis](bool deep) {
98             auto self = weakThis.promote();
99             CHECK_NULL_VOID(self);
100             ContainerScope scope(self->instanceId_);
101             self->cjView_->Reload(deep);
102         },
103         .completeReloadFunc = [weakThis]() -> RefPtr<AceType> {
104             auto view = weakThis.promote();
105             CHECK_NULL_RETURN(view, nullptr);
106             ContainerScope scope(view->instanceId_);
107             return view->InitialUIRender();
108         },
109     };
110     auto node = ViewPartialUpdateModel::GetInstance()->CreateNode(std::move(partialUpdateCallbacks));
111 
112     node_ = node;
113 
114     return node;
115 }
116 
InitialUIRender()117 RefPtr<AceType> NativeView::InitialUIRender()
118 {
119     needsUpdate_ = false;
120     {
121         cjView_->OnAboutToRender();
122     }
123     {
124         cjView_->Render();
125     }
126     {
127         cjView_->OnAfterRender();
128         if (onRenderDone_) {
129             onRenderDone_();
130         }
131     }
132     return ViewStackModel::GetInstance()->Finish();
133 }
134 
SyncInstanceId()135 void NativeView::SyncInstanceId()
136 {
137     restoreInstanceId_ = Container::CurrentId();
138     ContainerScope::UpdateCurrent(instanceId_);
139 }
140 
RestoreInstanceId()141 void NativeView::RestoreInstanceId()
142 {
143     ContainerScope::UpdateCurrent(restoreInstanceId_);
144 }
145 
146 /**
147  * marks the NativeView's composed component as needing update / rerender
148  */
MarkNeedUpdate()149 void NativeView::MarkNeedUpdate()
150 {
151     needsUpdate_ = ViewPartialUpdateModel::GetInstance()->MarkNeedUpdate(node_);
152 }
153 
FlushReload()154 void NativeView::FlushReload()
155 {
156     auto node = node_.Upgrade();
157     if (!node) {
158         LOGE("fail to update due to custom Node is null");
159         return;
160     }
161     if (AceType::InstanceOf<NG::CustomNode>(node)) {
162         auto customNode = AceType::DynamicCast<NG::CustomNode>(node);
163         customNode->FlushReload();
164     }
165 }
166 
FinishUpdateFunc(int32_t elmtId)167 void NativeView::FinishUpdateFunc(int32_t elmtId)
168 {
169     wptr<NativeView> weakThis = this;
170     ViewPartialUpdateModel::GetInstance()->FinishUpdate(node_, elmtId, [weakThis](const UpdateTask& task) {
171         auto cjView = weakThis.promote();
172         if (cjView) {
173             cjView->pendingUpdateTasks_.push_back(task);
174         }
175     });
176 }
177 
Destroy()178 void NativeView::Destroy()
179 {
180     if (!cjView_) {
181         LOGE("NativeView::Destroy error, nativeId: %{public}" PRId64 " cj view not exist.", GetID());
182         return;
183     }
184     LOGD("NativeView::Destroy start, nativeId: %{public}" PRId64 ", cjId: %{public}" PRId64, GetID(), cjView_->GetID());
185     {
186         cjView_->OnDisappear();
187     }
188     {
189         cjView_->OnAboutToBeDeleted();
190     }
191     pendingUpdateTasks_.clear();
192     LOGD("NativeView::Destroy end");
193 }
194 
Create(const sptr<NativeView> & view)195 void NativeView::Create(const sptr<NativeView>& view)
196 {
197     ViewStackModel::GetInstance()->Push(view->CreateUI(), true);
198 }
199 
CleanUpAbandonedChild()200 void NativeView::CleanUpAbandonedChild()
201 {
202     LOGD("NativeView::CleanUpAbandonedChild");
203 }
204 
FireOnShow()205 void NativeView::FireOnShow()
206 {
207     if (!cjView_) {
208         LOGE("NativeView::FireOnShow fail, no cj view on %{public}" PRId64 ".", GetID());
209         return;
210     }
211     {
212         cjView_->OnShow();
213     }
214 }
215 
FireOnHide()216 void NativeView::FireOnHide()
217 {
218     if (!cjView_) {
219         LOGE("NativeView::FireOnHide fail, no cj view on %{public}" PRId64 ".", GetID());
220         return;
221     }
222     {
223         cjView_->OnHide();
224     }
225 }
226 
FireOnBackPress()227 bool NativeView::FireOnBackPress()
228 {
229     if (!cjView_) {
230         LOGE("NativeView::FireOnBackPress fail, no cj view on %{public}" PRId64 ".", GetID());
231         return false;
232     }
233     {
234         return cjView_->OnBackPress();
235     }
236 }
237 
FireOnTransition()238 void NativeView::FireOnTransition()
239 {
240     if (!cjView_) {
241         LOGE("NativeView::FireOnTransition fail, no cj view on %{public}" PRId64 ".", GetID());
242         return;
243     }
244     cjView_->OnTransition();
245 }
246 
ExecuteUpdateWithValueParams(const std::string & jsonData)247 void NativeView::ExecuteUpdateWithValueParams(const std::string& jsonData)
248 {
249     if (!cjView_) {
250         LOGE("NativeView::ExecuteUpdateWithValueParams fail, no cj view on %{public}" PRId64 ".", GetID());
251         return;
252     }
253     cjView_->UpdateWithJson(jsonData);
254 }
255 
Reload(bool deep)256 void RemoteView::Reload(bool deep)
257 {
258     auto forceCompleteRerenderFunc =
259         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewForceCompleteRerender;
260     if (!forceCompleteRerenderFunc) {
261         LOGE("CJFunc: RemoteView::ForceCompleteRerender is empty.");
262         return;
263     }
264     forceCompleteRerenderFunc(GetID(), deep);
265 }
266 
VoidCallback(void (* cjFunc)(int64_t),const char * funcName)267 void RemoteView::VoidCallback(void (*cjFunc)(int64_t), const char* funcName)
268 {
269     if (!cjFunc) {
270         LOGE("CJFunc: RemoteView::%{public}s is empty.", funcName);
271         return;
272     }
273     cjFunc(GetID());
274 }
275 
Render()276 void RemoteView::Render()
277 {
278     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewRender, "Render");
279 }
280 
Rerender()281 void RemoteView::Rerender()
282 {
283     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewRerender, "Rerender");
284 }
285 
OnShow()286 void RemoteView::OnShow()
287 {
288     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnShow, "OnShow");
289 }
290 
OnHide()291 void RemoteView::OnHide()
292 {
293     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnHide, "OnHide");
294 }
295 
OnBackPress()296 bool RemoteView::OnBackPress()
297 {
298     auto onBackPressFunc = CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnBackPress;
299     if (!onBackPressFunc) {
300         LOGE("CJFunc: RemoteView::OnBackPress is empty.");
301         return false;
302     }
303     return onBackPressFunc(GetID());
304 }
305 
UpdateWithJson(const std::string & value)306 void RemoteView::UpdateWithJson(const std::string& value)
307 {
308     auto updateWithJsonFunc =
309         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewUpdateWithJson;
310     if (!updateWithJsonFunc) {
311         LOGE("CJFunc: RemoteView::UpdateWithJson is empty.");
312         return;
313     }
314     updateWithJsonFunc(GetID(), value.c_str());
315 }
316 
OnAppear()317 void RemoteView::OnAppear()
318 {
319     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAppear, "OnAppear");
320 }
321 
OnTransition()322 void RemoteView::OnTransition()
323 {
324     VoidCallback(
325         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnTransition, "OnTransition");
326 }
327 
OnAboutToRender()328 void RemoteView::OnAboutToRender()
329 {
330     VoidCallback(
331         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAboutToRender, "OnAboutToRender");
332 }
333 
OnAboutToBeDeleted()334 void RemoteView::OnAboutToBeDeleted()
335 {
336     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAboutToBeDeleted,
337         "OnAboutToBeDeleted");
338 }
339 
OnAfterRender()340 void RemoteView::OnAfterRender()
341 {
342     VoidCallback(
343         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAfterRender, "OnAfterRender");
344 }
345 
OnDisappear()346 void RemoteView::OnDisappear()
347 {
348     VoidCallback(
349         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnDisappear, "OnDisappear");
350 }
351 
352 } // namespace OHOS::Ace::Framework
353