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 "core/components/camera/camera_element.h"
17 
18 #if defined(PREVIEW)
19 #include "base/i18n/localization.h"
20 #endif
21 #include "core/components/video/render_texture.h"
22 
23 namespace OHOS::Ace {
24 namespace {
25 
26 const char CALLBACK_COMPLETE[] = "complete";
27 const char IS_SUCCESS[] = "isSucceed";
28 const char PHOTO_PATH[] = "uri";
29 const char NULL_STRING[] = "";
30 const char ERROR_MSG[] = "errormsg";
31 const char ERROR_CODE[] = "errorcode";
32 
GetStringFromMap(const std::map<std::string,std::string> & map,const std::string & key)33 inline std::string GetStringFromMap(const std::map<std::string, std::string>& map, const std::string& key)
34 {
35     auto iter = map.find(key);
36     if (iter != map.end()) {
37         return iter->second;
38     }
39     return NULL_STRING;
40 }
41 
42 #ifndef OHOS_STANDARD_SYSTEM
GetSizeFromQuality(const std::string & quality)43 inline int32_t GetSizeFromQuality(const std::string& quality)
44 {
45     int32_t qualityInt;
46     if (quality == "high") {
47         qualityInt = 2;
48     } else if (quality == "low") {
49         qualityInt = 0;
50     } else {
51         qualityInt = 1;
52     }
53     return qualityInt;
54 }
55 #endif
56 
57 } // namespace
58 
~CameraElement()59 CameraElement::~CameraElement()
60 {
61     ReleasePlatformResource();
62 }
63 
ReleasePlatformResource()64 void CameraElement::ReleasePlatformResource()
65 {
66 #ifdef OHOS_STANDARD_SYSTEM
67     StopPreview();
68     if (camera_) {
69         camera_->Release();
70         camera_.Reset();
71     }
72 #else
73     callbackIds_.clear();
74     auto context = context_.Upgrade();
75     if (!context) {
76         return;
77     }
78 
79     if (texture_) {
80         auto platformTaskExecutor =
81             SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
82 
83         // Release camera first.
84         if (camera_) {
85             ReleaseDeclarativePara();
86             camera_->Release();
87 
88             if (platformTaskExecutor.IsRunOnCurrentThread()) {
89                 camera_.Reset();
90             } else {
91                 // Make sure it's destroyed when it's release task done.
92                 platformTaskExecutor.PostTask([camera = camera_]() {}, "ArkUICameraResourceRelease");
93             }
94         }
95 
96         if (platformTaskExecutor.IsRunOnCurrentThread()) {
97             texture_->Release();
98             texture_.Reset();
99         } else {
100 #if defined(ENABLE_NATIVE_VIEW)
101             texture_->Release();
102             // Make sure it's destroyed when it's release task done.
103             platformTaskExecutor.PostTask([texture = texture_]() {}, "ArkUICameraTextureReleaseCheck");
104 #else
105             auto gpuTaskExecutor =
106                 SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::GPU);
107             // Release texture after paint.
108             auto weak = AceType::WeakClaim(AceType::RawPtr(texture_));
109             gpuTaskExecutor.PostTask([weak, platformTaskExecutor]() {
110                 auto texture = weak.Upgrade();
111                 if (texture == nullptr) {
112                     LOGE("texture is nullptr");
113                     return;
114                 }
115                 texture->Release();
116                 // Make sure it's destroyed when it's release task done.
117                 platformTaskExecutor.PostTask([texture]() {}, "ArkUICameraTextureReleaseCheck");
118             }, "ArkUICameraTextureRelease");
119 #endif
120         }
121     }
122 #endif
123 }
124 
Prepare(const WeakPtr<Element> & parent)125 void CameraElement::Prepare(const WeakPtr<Element>& parent)
126 {
127     auto themeManager = GetThemeManager();
128     if (!themeManager) {
129         return;
130     }
131 
132     auto cameraComponent = AceType::DynamicCast<CameraComponent>(component_);
133     theme_ = themeManager->GetTheme<CameraTheme>();
134     if (cameraComponent) {
135 #ifndef OHOS_STANDARD_SYSTEM
136         InitDeclarativePara(cameraComponent);
137 #endif
138 #if defined(PREVIEW)
139         textDirection_ = cameraComponent->GetTextDirection();
140 #endif
141         InitEvent(cameraComponent);
142         SetMethodCall(cameraComponent);
143         CreatePlatformResource();
144     }
145 
146     RenderElement::Prepare(parent);
147     if (renderNode_) {
148         auto renderTexture = AceType::DynamicCast<RenderTexture>(renderNode_);
149         renderTexture->SetTextureSizeChange(
150             [weak = WeakClaim(this)](int64_t textureId, int32_t textureWidth, int32_t textureHeight) {
151                 auto cameraElement = weak.Upgrade();
152                 if (cameraElement) {
153                     cameraElement->OnTextureSize(textureId, textureWidth, textureHeight);
154                 }
155             });
156         renderTexture->SetHiddenChangeEvent(
157             [weak = WeakClaim(this)](bool hidden) {
158                 auto cameraElement = weak.Upgrade();
159                 if (cameraElement) {
160                     cameraElement->HiddenChange(hidden);
161                 }
162             });
163 #if OHOS_STANDARD_SYSTEM
164         renderTexture->SetTextureOffsetChange(
165             [weak = WeakClaim(this)](int64_t textureId, int32_t x, int32_t y) {
166                 auto cameraElement = weak.Upgrade();
167                 if (cameraElement) {
168                     cameraElement->OnTextureOffset(textureId, x, y);
169                 }
170             });
171 #else
172         renderTexture->SetIsAddGaussianFuzzy(false);
173 #endif
174     }
175 }
176 
HiddenChange(bool hidden)177 void CameraElement::HiddenChange(bool hidden)
178 {
179     if (cameraState_ == CameraState::STATE_DISABLE) {
180         LOGE("CameraElement: CameraState is not enable when hidden change.");
181         return;
182     }
183 
184     if (hidden) {
185         LOGI("CameraElement::HiddenChange: hidden.");
186         ReleasePlatformResource();
187     } else {
188         LOGI("CameraElement::HiddenChange: show.");
189         CreatePlatformResource();
190     }
191 }
192 
InitEvent(const RefPtr<CameraComponent> & cameraComponent)193 void CameraElement::InitEvent(const RefPtr<CameraComponent>& cameraComponent)
194 {
195     if (!cameraComponent->GetErrorEventId().IsEmpty()) {
196         onError_ = AceAsyncEvent<void(const std::string&)>::Create(cameraComponent->GetErrorEventId(), context_);
197     }
198 }
199 
OnTextureSize(int64_t textureId,int32_t textureWidth,int32_t textureHeight)200 void CameraElement::OnTextureSize(int64_t textureId, int32_t textureWidth, int32_t textureHeight)
201 {
202     LOGI("CameraElement::OnTextureSize");
203     auto renderTexture = AceType::DynamicCast<RenderTexture>(renderNode_);
204     if (!renderTexture || !camera_) {
205         LOGI("CameraElement: renderNode is not renderTexture type or camera is null..");
206         return;
207     }
208 
209 #ifdef OHOS_STANDARD_SYSTEM
210     if (renderTexture->GetFit() == ImageFit::FILL) {
211         LOGI("CameraElement:OnTextureSize  %{public}d %{public}d ", textureWidth, textureHeight);
212         camera_->OnCameraSizeChange(textureWidth, textureHeight);
213     }
214 #else
215     if (!texture_) {
216         LOGI("CameraElement: texture is null.");
217         return;
218     }
219 
220     if (renderTexture->IsComponentSize() && renderTexture->GetFit() == ImageFit::FILL) {
221         if (isSetResolution_) {
222             camera_->SetPreViewSize(resolutionWidth_, resolutionHeight_);
223         } else {
224             camera_->SetPreViewSize(textureWidth, textureHeight);
225         }
226         renderTexture->SetIsComponentSize(false);
227     } else {
228         texture_->OnSize(textureId, textureWidth, textureHeight);
229     }
230 #endif
231 }
232 
SetNewComponent(const RefPtr<Component> & newComponent)233 void CameraElement::SetNewComponent(const RefPtr<Component>& newComponent)
234 {
235     if (newComponent == nullptr) {
236         Element::SetNewComponent(newComponent);
237         return;
238     }
239 
240     auto cameraComponent = AceType::DynamicCast<CameraComponent>(newComponent);
241     if (cameraComponent) {
242 #ifdef OHOS_STANDARD_SYSTEM
243         cameraComponent->SetFit(ImageFit::FILL);
244 #else
245         if (devicePosition_ == cameraComponent->GetDevicePosition()) {
246             UpdateCamera(cameraComponent);
247         } else {
248             UpdateCamera(cameraComponent);
249             if (cameraState_ != CameraState::STATE_DISABLE) {
250                 if (renderNode_) {
251                     auto renderTexture = AceType::DynamicCast<RenderTexture>(renderNode_);
252                     if (renderTexture) {
253                         renderTexture->SetIsAddGaussianFuzzy(true);
254                     }
255                 }
256                 CreatePlatformResource();
257             }
258         }
259 #endif
260     }
261     Element::SetNewComponent(newComponent);
262 }
263 
264 #ifdef OHOS_STANDARD_SYSTEM
OnTextureOffset(int64_t textureId,int32_t x,int32_t y)265 void CameraElement::OnTextureOffset(int64_t textureId, int32_t x, int32_t y)
266 {
267     LOGI("CameraElement::OnTextureOffset");
268     auto renderTexture = AceType::DynamicCast<RenderTexture>(renderNode_);
269     if (!renderTexture) {
270         LOGI("CameraElement::OnTextureSize: renderNode is not renderTexture type.");
271         return;
272     }
273 
274     if (camera_ && renderTexture->GetFit() == ImageFit::FILL) {
275         LOGI("Camera:OnTextureOffset %{public}d %{public}d", x, y);
276         camera_->OnCameraOffsetChange(x, y);
277     }
278 }
279 
CreateCamera()280 void CameraElement::CreateCamera()
281 {
282     LOGI("CameraElement::CreateCamera");
283     camera_ = AceType::MakeRefPtr<Camera>(context_);
284     InitListener();
285     camera_->SetRenderNode(GetRenderNode());
286     camera_->Create(nullptr);
287     StartPreview();
288 }
289 
OnRecorderCallBack(const std::map<std::string,std::string> & result)290 void CameraElement::OnRecorderCallBack(const std::map<std::string, std::string>& result)
291 {
292     if (recorderBackId_.empty()) {
293         return;
294     }
295 
296     std::string param = std::string("{\"arguments\":[");
297     if (GetStringFromMap(result, IS_SUCCESS) == "1") {
298         param.append("{\"")
299             .append(PHOTO_PATH)
300             .append("\":\"file://")
301             .append(GetStringFromMap(result, PHOTO_PATH))
302             .append("\"}],\"method\":\"success\"}");
303         ExecuteJsCallback(recorderBackId_, param);
304     } else if (GetStringFromMap(result, IS_SUCCESS) != "1") {
305         param.append("{\"")
306             .append(ERROR_MSG)
307             .append("\":\"")
308             .append(GetStringFromMap(result, ERROR_MSG))
309             .append("\", \"")
310             .append(ERROR_CODE)
311             .append("\":\"")
312             .append(GetStringFromMap(result, ERROR_CODE))
313             .append("\"}],\"method\":\"fail\"}");
314         ExecuteJsCallback(recorderBackId_, param);
315     }
316 
317     std::string complete = std::string("{\"arguments\":[{\"")
318         .append(CALLBACK_COMPLETE)
319         .append("\":\"\"}],\"method\":\"complete\"}");
320     ExecuteJsCallback(recorderBackId_, complete);
321 }
322 
StartPreview()323 void CameraElement::StartPreview()
324 {
325     if (camera_ && !isPreViewing_) {
326         camera_->StartPreview();
327         isPreViewing_ = true;
328     }
329 }
330 
StopPreview()331 void CameraElement::StopPreview()
332 {
333     if (camera_ && isPreViewing_) {
334         camera_->Stop(true);
335         isPreViewing_ = false;
336     }
337 }
338 
TakePhoto(const Size & size)339 void CameraElement::TakePhoto(const Size& size)
340 {
341     if (camera_) {
342         camera_->TakePhoto(size);
343     }
344 }
345 
StartRecord()346 void CameraElement::StartRecord()
347 {
348     LOGI("CameraElement::StartRecord.");
349     if (camera_ && !isRecording_) {
350         camera_->StartRecord();
351         isRecording_ = true;
352     }
353 }
354 
CloseRecorder(const std::string & params)355 void CameraElement::CloseRecorder(const std::string& params)
356 {
357     LOGI("CameraElement::CloseRecorder.");
358     auto context = context_.Upgrade();
359     if (!context) {
360         LOGE("fail to get context");
361         return;
362     }
363 
364     if (camera_ && isRecording_) {
365         recorderBackId_ = params;
366 
367         context->GetTaskExecutor()->PostTask(
368             [weak = WeakClaim(this)] {
369                 auto cameraElement = weak.Upgrade();
370                 if (cameraElement) {
371                     cameraElement->CloseRecorder();
372                 }
373             },
374             TaskExecutor::TaskType::PLATFORM, "ArkUICameraCloseRecorder");
375         isRecording_ = false;
376     }
377 }
378 
CloseRecorder()379 void CameraElement::CloseRecorder()
380 {
381     if (camera_) {
382         LOGI("CameraElement:CloseRecorder Task");
383         camera_->Stop(false);
384     }
385 }
386 
387 #else
UpdateCamera(const RefPtr<CameraComponent> & cameraComponent)388 void CameraElement::UpdateCamera(const RefPtr<CameraComponent> &cameraComponent)
389 {
390     if (flash_ != cameraComponent->GetFlash()) {
391         flash_ = cameraComponent->GetFlash();
392         if (camera_) {
393             camera_->SetFlashMode(flash_);
394         }
395     }
396     devicePosition_ = cameraComponent->GetDevicePosition();
397     if (texture_) {
398         cameraComponent->SetTextureId(texture_->GetId());
399         cameraComponent->SetFit(ImageFit::CONTAIN);
400 
401 #if defined(IOS_PLATFORM)
402         cameraComponent->SetFit(ImageFit::COVER);
403 #endif
404 
405         cameraComponent->SetSrcWidth(preViewWidth_);
406         cameraComponent->SetSrcHeight(preViewHeight_);
407     }
408 }
409 
CreateTexture()410 void CameraElement::CreateTexture()
411 {
412     auto context = context_.Upgrade();
413     if (!context) {
414         return;
415     }
416 
417     auto uiTaskExecutor =
418         SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
419     auto errorCallback = [weak = WeakClaim(this), uiTaskExecutor](
420                              const std::string& errorcode, const std::string& errormsg) {
421         uiTaskExecutor.PostTask([weak, errorcode, errormsg] {
422             auto cameraElement = weak.Upgrade();
423             if (cameraElement) {
424                 cameraElement->OnError(errorcode, errormsg);
425             }
426         }, "ArkUICameraErrorCallback");
427     };
428     texture_ = AceType::MakeRefPtr<Texture>(context_, errorCallback);
429 
430     texture_->Create([weak = WeakClaim(this), errorCallback](int64_t id) mutable {
431         auto cameraElement = weak.Upgrade();
432         if (cameraElement) {
433             cameraElement->CreateCamera(id, std::move(errorCallback));
434         }
435     });
436 }
437 
CreateCamera(int64_t id,ErrorCallback && errorCallback)438 void CameraElement::CreateCamera(int64_t id, ErrorCallback&& errorCallback)
439 {
440     camera_ = AceType::MakeRefPtr<Camera>(id, context_, std::move(errorCallback), devicePosition_);
441     InitListener();
442     if (theme_) {
443         camera_->SetBufferSize(theme_->GetBufferSize());
444     }
445     camera_->SetDeviceOrientation(
446         SystemProperties::GetDeviceOrientation() == DeviceOrientation::PORTRAIT);
447     camera_->Create(nullptr);
448     HandleDeclarativePara();
449 }
450 
OnPreViewSizeChange(int32_t preViewWidth,int32_t preViewHeight)451 void CameraElement::OnPreViewSizeChange(int32_t preViewWidth, int32_t preViewHeight)
452 {
453     auto camera = AceType::MakeRefPtr<CameraComponent>();
454     camera->SetTextureId(texture_->GetId());
455     camera->SetFit(ImageFit::CONTAIN);
456 
457 #if defined(IOS_PLATFORM)
458     camera->SetFit(ImageFit::COVER);
459 #endif
460 
461     camera->SetSrcWidth(preViewWidth);
462     camera->SetSrcHeight(preViewHeight);
463     preViewWidth_ = preViewWidth;
464     preViewHeight_ = preViewHeight;
465 
466     if (renderNode_ != nullptr) {
467         renderNode_->Update(camera);
468     }
469 }
470 
InitDeclarativePara(const RefPtr<CameraComponent> & cameraComponent)471 void CameraElement::InitDeclarativePara(const RefPtr<CameraComponent>& cameraComponent)
472 {
473     auto context = context_.Upgrade();
474     if (!context) {
475         return;
476     }
477 
478     if (context->GetIsDeclarative()) {
479         cameraId_ = cameraComponent->GetCameraId();
480         isSetResolution_ = cameraComponent->IsSetResolution();
481         if (isSetResolution_) {
482             resolutionWidth_ = cameraComponent->GetResolutionWidth();
483             resolutionHeight_ = cameraComponent->GetResolutionHeight();
484         }
485     }
486 }
487 
HandleDeclarativePara()488 void CameraElement::HandleDeclarativePara()
489 {
490     auto context = context_.Upgrade();
491     if (!context) {
492         return;
493     }
494 
495     if (context->GetIsDeclarative() && camera_) {
496         camera_->ChangeCameraComponentId(true, cameraId_);
497     }
498 }
499 
ReleaseDeclarativePara()500 void CameraElement::ReleaseDeclarativePara()
501 {
502     auto context = context_.Upgrade();
503     if (!context) {
504         return;
505     }
506 
507     if (context->GetIsDeclarative() && camera_) {
508         camera_->ChangeCameraComponentId(false, cameraId_);
509     }
510 }
511 
OnTextureRefresh()512 void CameraElement::OnTextureRefresh()
513 {
514     if (renderNode_) {
515         renderNode_->MarkNeedRender();
516     }
517 }
518 #endif
519 
OnPrepared()520 void CameraElement::OnPrepared()
521 {
522     LOGI("CameraElement::OnPrepared");
523     auto renderTexture = AceType::DynamicCast<RenderTexture>(renderNode_);
524     if (!renderTexture) {
525         LOGE("CameraElement: the renderNode is not renderTexture type.");
526         return;
527     }
528 
529     auto camera = AceType::MakeRefPtr<CameraComponent>();
530     camera->SetFit(ImageFit::FILL);
531 #ifndef OHOS_STANDARD_SYSTEM
532     camera->SetTextureId(texture_->GetId());
533     renderTexture->SetIsComponentSize(true);
534 #endif
535     renderTexture->Update(camera);
536     cameraState_ = CameraState::STATE_ENABLE;
537 
538 #ifndef OHOS_STANDARD_SYSTEM
539     renderTexture->OnLayout();
540     camera_->SetFlashMode(flash_);
541 #endif
542 }
543 
CreatePlatformResource()544 void CameraElement::CreatePlatformResource()
545 {
546     cameraState_ = CameraState::STATE_DISABLE;
547     ReleasePlatformResource();
548 
549     auto context = context_.Upgrade();
550     if (!context) {
551         LOGE("fail to get context");
552         return;
553     }
554 
555 #ifdef OHOS_STANDARD_SYSTEM
556     context->GetTaskExecutor()->PostTask(
557         [weak = WeakClaim(this)] {
558             auto cameraElement = weak.Upgrade();
559             if (cameraElement) {
560                 cameraElement->CreateCamera();
561             }
562         },
563         TaskExecutor::TaskType::PLATFORM, "ArkUICameraCreatePlatformResource");
564 #else
565     CreateTexture();
566 #endif
567 }
568 
SetMethodCall(const RefPtr<CameraComponent> & cameraComponent)569 void CameraElement::SetMethodCall(const RefPtr<CameraComponent>& cameraComponent)
570 {
571     auto cameraController = cameraComponent->GetCameraController();
572     if (cameraController) {
573         auto context = context_.Upgrade();
574         if (!context) {
575             return;
576         }
577         auto uiTaskExecutor =
578             SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
579         cameraController->SetTakePhotoImpl(
580             [weak = WeakClaim(this), uiTaskExecutor](
581                 const TakePhotoParams& params) {
582                     uiTaskExecutor.PostTask([weak, params] {
583                         auto cameraElement = weak.Upgrade();
584                         if (cameraElement) {
585                             cameraElement->TakePhoto(params);
586                         }
587                     }, "ArkUICameraControllerTakePhoto");
588         });
589 #ifdef OHOS_STANDARD_SYSTEM
590         cameraController->SetStartRecordImpl(
591             [weak = WeakClaim(this), uiTaskExecutor]() {
592                     uiTaskExecutor.PostTask([weak] {
593                         auto cameraElement = weak.Upgrade();
594                         if (cameraElement) {
595                             cameraElement->StartRecord();
596                         }
597                     }, "ArkUICameraStartRecord");
598         });
599 
600         cameraController->SetCloseRecorderImpl(
601             [weak = WeakClaim(this), uiTaskExecutor](
602                 const std::string& params) {
603                     uiTaskExecutor.PostTask([weak, params] {
604                         auto cameraElement = weak.Upgrade();
605                         if (cameraElement) {
606                             cameraElement->CloseRecorder(params);
607                         }
608                     }, "ArkUICameraControllerCloseRecorder");
609         });
610 #endif
611     }
612 }
613 
InitListener()614 void CameraElement::InitListener()
615 {
616     auto context = context_.Upgrade();
617     if (!context) {
618         return;
619     }
620 
621     if (!camera_) {
622         LOGE("CameraElement::InitListener: camera is null.");
623         return;
624     }
625 
626     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
627     auto takePhotoListener = [weak = WeakClaim(this), uiTaskExecutor](
628         const std::map<std::string, std::string> result) {
629             uiTaskExecutor.PostTask([weak, result] {
630                 auto camera = weak.Upgrade();
631                 if (camera) {
632                     camera->OnTakePhotoCallBack(result);
633                 }
634             }, "ArkUICameraTakePhotoCallBack");
635     };
636     camera_->AddTakePhotoListener(takePhotoListener);
637 
638     auto onError = [weak = WeakClaim(this), uiTaskExecutor](const std::string& errorcode, const std::string& errormsg) {
639         uiTaskExecutor.PostTask([weak, errorcode, errormsg] {
640             auto camera = weak.Upgrade();
641             if (camera) {
642                 camera->OnError(errorcode, errormsg);
643             }
644         }, "ArkUICameraError");
645     };
646     camera_->AddErrorListener(onError);
647 
648     auto preparedCallBack = [weak = WeakClaim(this), uiTaskExecutor]() {
649             uiTaskExecutor.PostTask([weak] {
650                 auto camera = weak.Upgrade();
651                 if (camera) {
652                     camera->OnPrepared();
653                 }
654             }, "ArkUICameraPrepared");
655     };
656     camera_->AddPrepareEventListener(preparedCallBack);
657 
658 #ifdef OHOS_STANDARD_SYSTEM
659     auto recorderCallBack = [weak = WeakClaim(this), uiTaskExecutor](
660         const std::map<std::string, std::string> result) {
661             uiTaskExecutor.PostTask([weak, result] {
662                 auto camera = weak.Upgrade();
663                 if (camera) {
664                     camera->OnRecorderCallBack(result);
665                 }
666             }, "ArkUICameraRecorder");
667     };
668     camera_->AddRecordListener(recorderCallBack);
669 #else
670     auto onSizeChangeListener = [weak = WeakClaim(this), uiTaskExecutor](
671         int32_t preViewWidth, int32_t preViewHeight) {
672             uiTaskExecutor.PostTask([weak, preViewWidth, preViewHeight] {
673                 auto camera = weak.Upgrade();
674                 if (camera) {
675                     camera->OnPreViewSizeChange(preViewWidth, preViewHeight);
676                 }
677             }, "ArkUICameraPreviewSizeChange");
678     };
679     camera_->AddPreViewSizeChang(onSizeChangeListener);
680 
681     if (texture_) {
682         auto onTextureRefresh = [weak = WeakClaim(this), uiTaskExecutor]() {
683             uiTaskExecutor.PostSyncTask([weak] {
684                 auto camera = weak.Upgrade();
685                 if (camera) {
686                     camera->OnTextureRefresh();
687                 }
688             }, "ArkUICameraTextureRefresh");
689         };
690         texture_->SetRefreshListener(onTextureRefresh);
691     }
692 #endif
693 }
694 
OnTakePhotoCallBack(const std::map<std::string,std::string> & result)695 void CameraElement::OnTakePhotoCallBack(const std::map<std::string, std::string>& result)
696 {
697     if (GetStringFromMap(result, IS_SUCCESS) == "1" && !callbackIds_.success.empty()) {
698         std::string param = std::string("{\"")
699                                 .append(PHOTO_PATH)
700                                 .append("\":\"file://")
701                                 .append(GetStringFromMap(result, PHOTO_PATH))
702                                 .append("\"}");
703         ExecuteJsCallback(callbackIds_.success, param);
704     } else if (GetStringFromMap(result, IS_SUCCESS) != "1" && !callbackIds_.fail.empty()) {
705         std::string param = std::string("{\"")
706                                 .append(ERROR_MSG)
707                                 .append("\":\"")
708                                 .append(GetStringFromMap(result, ERROR_MSG))
709                                 .append("\", \"")
710                                 .append(ERROR_CODE)
711                                 .append("\":\"")
712                                 .append(GetStringFromMap(result, ERROR_CODE))
713                                 .append("\"}");
714         ExecuteJsCallback(callbackIds_.fail, param);
715     }
716     if (!callbackIds_.complete.empty()) {
717         std::string param = std::string("{\"").append(CALLBACK_COMPLETE).append("\":\"\"}");
718         ExecuteJsCallback(callbackIds_.complete, param);
719     }
720 }
721 
722 #if defined(PREVIEW)
CreateErrorText(const std::string & errorMsg)723 const RefPtr<Component> CameraElement::CreateErrorText(const std::string& errorMsg)
724 {
725     auto text = AceType::MakeRefPtr<TextComponent>(errorMsg);
726     text->SetTextStyle(theme_->GetErrorTextStyle());
727     text->SetTextDirection(textDirection_);
728 
729     std::list<RefPtr<Component>> childrenAlign;
730     childrenAlign.emplace_back(text);
731 
732     return AceType::MakeRefPtr<AlignComponent>(childrenAlign, Alignment::TOP_CENTER);
733 }
734 
UpdateChildInner(const RefPtr<Component> & childComponent)735 void CameraElement::UpdateChildInner(const RefPtr<Component>& childComponent)
736 {
737     const auto& child = children_.empty() ? nullptr : children_.front();
738     UpdateChild(child, childComponent);
739 }
740 #endif
741 
OnError(const std::string & errorcode,const std::string & errormsg)742 void CameraElement::OnError(const std::string& errorcode, const std::string& errormsg)
743 {
744 #if defined(PREVIEW)
745     std::string errorDescription = "This component is not supported on PC Preview.";
746     UpdateChildInner(CreateErrorText(errorDescription));
747 #endif
748     if (onError_) {
749         std::string param = std::string("\"error\",{\"")
750                                 .append(ERROR_MSG)
751                                 .append("\":\"")
752                                 .append(errormsg)
753                                 .append("\", \"")
754                                 .append(ERROR_CODE)
755                                 .append("\":\"")
756                                 .append(errorcode)
757                                 .append("\"}");
758         onError_(param);
759     }
760     cameraState_ = CameraState::STATE_UNDEFINED;
761 }
762 
TakePhoto(const TakePhotoParams & params)763 void CameraElement::TakePhoto(const TakePhotoParams& params)
764 {
765     if (cameraState_ != CameraState::STATE_ENABLE) {
766         LOGE("CameraState is not enable.");
767         return;
768     }
769 
770     auto context = context_.Upgrade();
771     if (!context) {
772         LOGE("fail to get context");
773         return;
774     }
775 
776     if (!camera_) {
777         LOGE("Camera is null.");
778         return;
779     }
780 
781     callbackIds_.clear();
782     callbackIds_ = params;
783 #ifdef OHOS_STANDARD_SYSTEM
784     context->GetTaskExecutor()->PostTask(
785         [weak = WeakClaim(this)] {
786             auto cameraElement = weak.Upgrade();
787             if (cameraElement) {
788                 cameraElement->TakePhoto(Size());
789             }
790         },
791         TaskExecutor::TaskType::PLATFORM, "ArkUICameraTakePhoto");
792 #else
793         camera_->TakePhoto(GetSizeFromQuality(params.quality));
794 #endif
795 }
796 
ExecuteJsCallback(const std::string & callbackId,const std::string & result)797 void CameraElement::ExecuteJsCallback(const std::string& callbackId, const std::string& result)
798 {
799     auto context = context_.Upgrade();
800     if (!context) {
801         return;
802     }
803     context->SendCallbackMessageToFrontend(callbackId, result);
804     LOGI("CameraElement: ExecuteJsCallback %{public}s %{public}s", callbackId.c_str(), result.c_str());
805 }
806 
807 } // namespace OHOS::Ace
808