• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2023 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 "photo_post_processor.h"
17 
18 #include <sys/mman.h>
19 
20 #include "auxiliary_picture.h"
21 #include "buffer_extra_data_impl.h"
22 #include "camera_dynamic_loader.h"
23 #include "dp_log.h"
24 #include "dp_timer.h"
25 #include "dp_utils.h"
26 #include "dps_event_report.h"
27 #include "events_monitor.h"
28 #include "foundation/multimedia/media_library/interfaces/inner_api/media_library_helper/include/photo_proxy.h"
29 #include "iproxy_broker.h"
30 #include "iservmgr_hdi.h"
31 #include "picture_proxy.h"
32 #include "securec.h"
33 #include "v1_3/iimage_process_service.h"
34 #include "v1_3/iimage_process_callback.h"
35 #include "v1_3/types.h"
36 
37 namespace OHOS {
38 namespace CameraStandard {
39 namespace DeferredProcessing {
40 namespace {
41     const std::string PHOTO_SERVICE_NAME = "camera_image_process_service";
42     constexpr uint32_t MAX_PROC_TIME_MS = 11 * 1000;
43     constexpr uint32_t MAX_CONSECUTIVE_TIMEOUT_COUNT = 3;
44     constexpr uint32_t MAX_CONSECUTIVE_CRASH_COUNT = 3;
45     constexpr int32_t HDI_VERSION_1 = 1;
46     constexpr int32_t HDI_VERSION_3 = 3;
47 }
48 
MapHdiError(OHOS::HDI::Camera::V1_2::ErrorCode errorCode)49 DpsError MapHdiError(OHOS::HDI::Camera::V1_2::ErrorCode errorCode)
50 {
51     DpsError code = DpsError::DPS_ERROR_IMAGE_PROC_ABNORMAL;
52     switch (errorCode) {
53         case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_INVALID_ID:
54             code = DpsError::DPS_ERROR_IMAGE_PROC_INVALID_PHOTO_ID;
55             break;
56         case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_PROCESS:
57             code = DpsError::DPS_ERROR_IMAGE_PROC_FAILED;
58             break;
59         case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_TIMEOUT:
60             code = DpsError::DPS_ERROR_IMAGE_PROC_TIMEOUT;
61             break;
62         case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_HIGH_TEMPERATURE:
63             code = DpsError::DPS_ERROR_IMAGE_PROC_HIGH_TEMPERATURE;
64             break;
65         case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_ABNORMAL:
66             code = DpsError::DPS_ERROR_IMAGE_PROC_ABNORMAL;
67             break;
68         case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_ABORT:
69             code = DpsError::DPS_ERROR_IMAGE_PROC_INTERRUPTED;
70             break;
71         default:
72             DP_ERR_LOG("unexpected error code: %{public}d.", errorCode);
73             break;
74     }
75     return code;
76 }
77 
MapHdiStatus(OHOS::HDI::Camera::V1_2::SessionStatus statusCode)78 HdiStatus MapHdiStatus(OHOS::HDI::Camera::V1_2::SessionStatus statusCode)
79 {
80     HdiStatus code = HdiStatus::HDI_DISCONNECTED;
81     switch (statusCode) {
82         case OHOS::HDI::Camera::V1_2::SessionStatus::SESSION_STATUS_READY:
83             code = HdiStatus::HDI_READY;
84             break;
85         case OHOS::HDI::Camera::V1_2::SessionStatus::SESSION_STATUS_READY_SPACE_LIMIT_REACHED:
86             code = HdiStatus::HDI_READY_SPACE_LIMIT_REACHED;
87             break;
88         case OHOS::HDI::Camera::V1_2::SessionStatus::SESSSON_STATUS_NOT_READY_TEMPORARILY:
89             code = HdiStatus::HDI_NOT_READY_TEMPORARILY;
90             break;
91         case OHOS::HDI::Camera::V1_2::SessionStatus::SESSION_STATUS_NOT_READY_OVERHEAT:
92             code = HdiStatus::HDI_NOT_READY_OVERHEAT;
93             break;
94         case OHOS::HDI::Camera::V1_2::SessionStatus::SESSION_STATUS_NOT_READY_PREEMPTED:
95             code = HdiStatus::HDI_NOT_READY_PREEMPTED;
96             break;
97         default:
98             DP_ERR_LOG("unexpected error code: %{public}d.", statusCode);
99             break;
100     }
101     return code;
102 }
103 
MapToHdiExecutionMode(ExecutionMode executionMode)104 OHOS::HDI::Camera::V1_2::ExecutionMode MapToHdiExecutionMode(ExecutionMode executionMode)
105 {
106     auto mode = OHOS::HDI::Camera::V1_2::ExecutionMode::LOW_POWER;
107     switch (executionMode) {
108         case ExecutionMode::HIGH_PERFORMANCE:
109             mode = OHOS::HDI::Camera::V1_2::ExecutionMode::HIGH_PREFORMANCE;
110             break;
111         case ExecutionMode::LOAD_BALANCE:
112             mode = OHOS::HDI::Camera::V1_2::ExecutionMode::BALANCED;
113             break;
114         case ExecutionMode::LOW_POWER:
115             mode = OHOS::HDI::Camera::V1_2::ExecutionMode::LOW_POWER;
116             break;
117         default:
118             DP_ERR_LOG("unexpected error code: %{public}d.", executionMode);
119             break;
120     }
121     return mode;
122 }
123 
124 class PhotoPostProcessor::PhotoServiceListener : public HDI::ServiceManager::V1_0::ServStatListenerStub {
125 public:
126     using StatusCallback = std::function<void(const HDI::ServiceManager::V1_0::ServiceStatus&)>;
PhotoServiceListener(const std::weak_ptr<PhotoPostProcessor> & processor)127     explicit PhotoServiceListener(const std::weak_ptr<PhotoPostProcessor>& processor) : processor_(processor)
128     {
129         DP_DEBUG_LOG("entered.");
130     }
131 
OnReceive(const HDI::ServiceManager::V1_0::ServiceStatus & status)132     void OnReceive(const HDI::ServiceManager::V1_0::ServiceStatus& status)
133     {
134         auto process = processor_.lock();
135         DP_CHECK_ERROR_RETURN_LOG(process == nullptr, "photo post process is nullptr.");
136         process->OnServiceChange(status);
137     }
138 
139 private:
140     std::weak_ptr<PhotoPostProcessor> processor_;
141 };
142 
143 class PhotoPostProcessor::SessionDeathRecipient : public IRemoteObject::DeathRecipient {
144 public:
SessionDeathRecipient(const std::weak_ptr<PhotoProcessResult> & processResult)145     explicit SessionDeathRecipient(const std::weak_ptr<PhotoProcessResult>& processResult)
146         : processResult_(processResult)
147     {
148         DP_DEBUG_LOG("entered.");
149     }
150 
OnRemoteDied(const wptr<IRemoteObject> & remote)151     void OnRemoteDied(const wptr<IRemoteObject> &remote) override
152     {
153         if (auto processResult = processResult_.lock()) {
154             processResult->OnPhotoSessionDied();
155         }
156     }
157 
158 private:
159     std::weak_ptr<PhotoProcessResult> processResult_;
160 };
161 
162 class PhotoPostProcessor::PhotoProcessListener : public OHOS::HDI::Camera::V1_3::IImageProcessCallback {
163 public:
PhotoProcessListener(const int32_t userId,const std::weak_ptr<PhotoProcessResult> & processResult)164     explicit PhotoProcessListener(const int32_t userId, const std::weak_ptr<PhotoProcessResult>& processResult)
165         : userId_(userId), processResult_(processResult)
166     {
167         DP_DEBUG_LOG("entered.");
168     }
169 
170     int32_t OnProcessDone(const std::string& imageId, const OHOS::HDI::Camera::V1_2::ImageBufferInfo& buffer) override;
171     int32_t OnProcessDoneExt(const std::string& imageId,
172         const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer) override;
173     int32_t OnError(const std::string& imageId,  OHOS::HDI::Camera::V1_2::ErrorCode errorCode) override;
174     int32_t OnStatusChanged(OHOS::HDI::Camera::V1_2::SessionStatus status) override;
175 
176 private:
177     void ReportEvent(const std::string& imageId);
178     int32_t ProcessBufferInfo(const std::string& imageId, const OHOS::HDI::Camera::V1_2::ImageBufferInfo& buffer);
179     int32_t ProcessBufferInfoExt(const std::string& imageId,
180         const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer);
181     std::shared_ptr<PictureIntf> AssemblePicture(const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer);
182 
183     const int32_t userId_;
184     std::weak_ptr<PhotoProcessResult> processResult_;
185 };
186 
OnProcessDone(const std::string & imageId,const OHOS::HDI::Camera::V1_2::ImageBufferInfo & buffer)187 int32_t PhotoPostProcessor::PhotoProcessListener::OnProcessDone(const std::string& imageId,
188     const OHOS::HDI::Camera::V1_2::ImageBufferInfo& buffer)
189 {
190     DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s", imageId.c_str());
191     auto ret = ProcessBufferInfo(imageId, buffer);
192     if (ret != DP_OK) {
193         DP_ERR_LOG("process done failed imageId: %{public}s.", imageId.c_str());
194         if (auto processResult = processResult_.lock()) {
195             processResult->OnError(imageId, DPS_ERROR_IMAGE_PROC_FAILED);
196         }
197     }
198     return DP_OK;
199 }
200 
ProcessBufferInfo(const std::string & imageId,const OHOS::HDI::Camera::V1_2::ImageBufferInfo & buffer)201 int32_t PhotoPostProcessor::PhotoProcessListener::ProcessBufferInfo(const std::string& imageId,
202     const OHOS::HDI::Camera::V1_2::ImageBufferInfo& buffer)
203 {
204     auto bufferHandle = buffer.imageHandle->GetBufferHandle();
205     DP_CHECK_ERROR_RETURN_RET_LOG(bufferHandle == nullptr, DPS_ERROR_IMAGE_PROC_FAILED, "bufferHandle is nullptr.");
206 
207     int32_t size = bufferHandle->size;
208     int32_t isDegradedImage = 0;
209     int32_t dataSize = size;
210     uint32_t cloudImageEnhanceFlag = 0;
211     if (buffer.metadata) {
212         int32_t retImageQuality = buffer.metadata->Get("isDegradedImage", isDegradedImage);
213         int32_t retDataSize = buffer.metadata->Get("dataSize", dataSize);
214         int32_t retCloudImageEnhanceFlag = buffer.metadata->Get("cloudImageEnhanceFlag",
215             cloudImageEnhanceFlag);
216         DP_DEBUG_LOG("retImageQuality: %{public}d, retDataSize: %{public}d, retCloudImageEnhanceFlag: %{public}d",
217             static_cast<int>(retImageQuality), static_cast<int>(retDataSize),
218             static_cast<int>(retCloudImageEnhanceFlag));
219     }
220     DP_INFO_LOG("DPS_PHOTO: bufferHandle param, size: %{public}d, dataSize: %{public}d, isDegradedImage: %{public}d",
221         size, static_cast<int>(dataSize), isDegradedImage);
222     auto bufferPtr = std::make_shared<SharedBuffer>(dataSize);
223     DP_CHECK_ERROR_RETURN_RET_LOG(bufferPtr->Initialize() != DP_OK, DPS_ERROR_IMAGE_PROC_FAILED,
224         "failed to initialize shared buffer.");
225 
226     auto addr = mmap(nullptr, dataSize, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0);
227     DP_CHECK_ERROR_RETURN_RET_LOG(addr == MAP_FAILED, DPS_ERROR_IMAGE_PROC_FAILED, "failed to mmap shared buffer.");
228 
229     if (bufferPtr->CopyFrom(static_cast<uint8_t*>(addr), dataSize) == DP_OK) {
230         DP_INFO_LOG("DPS_PHOTO: bufferPtr fd: %{public}d, fd: %{public}d, cloudImageEnhanceFlag: %{public}u",
231             bufferHandle->fd, bufferPtr->GetFd(), cloudImageEnhanceFlag);
232         std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>(bufferPtr, dataSize,
233             isDegradedImage == 0, cloudImageEnhanceFlag);
234         auto processResult = processResult_.lock();
235         if (processResult) {
236             processResult->OnProcessDone(imageId, bufferInfo);
237         }
238     }
239     munmap(addr, dataSize);
240     ReportEvent(imageId);
241     return DP_OK;
242 }
243 
CloneBufferHandle(const BufferHandle * handle)244 BufferHandle *CloneBufferHandle(const BufferHandle *handle)
245 {
246     if (handle == nullptr) {
247         DP_ERR_LOG("%{public}s handle is nullptr", __func__);
248         return nullptr;
249     }
250 
251     BufferHandle *newHandle = AllocateBufferHandle(handle->reserveFds, handle->reserveInts);
252     if (newHandle == nullptr) {
253         DP_ERR_LOG("%{public}s AllocateBufferHandle failed, newHandle is nullptr", __func__);
254         return nullptr;
255     }
256 
257     if (handle->fd == -1) {
258         newHandle->fd = handle->fd;
259     } else {
260         newHandle->fd = dup(handle->fd);
261         if (newHandle->fd == -1) {
262             DP_ERR_LOG("CloneBufferHandle dup failed");
263             FreeBufferHandle(newHandle);
264             return nullptr;
265         }
266     }
267     newHandle->width = handle->width;
268     newHandle->stride = handle->stride;
269     newHandle->height = handle->height;
270     newHandle->size = handle->size;
271     newHandle->format = handle->format;
272     newHandle->usage = handle->usage;
273     newHandle->phyAddr = handle->phyAddr;
274 
275     for (uint32_t i = 0; i < newHandle->reserveFds; i++) {
276         newHandle->reserve[i] = dup(handle->reserve[i]);
277         if (newHandle->reserve[i] == -1) {
278             DP_ERR_LOG("CloneBufferHandle dup reserveFds failed");
279             FreeBufferHandle(newHandle);
280             return nullptr;
281         }
282     }
283 
284     if (handle->reserveInts == 0) {
285         DP_ERR_LOG("There is no reserved integer value in old handle, no need to copy");
286         return newHandle;
287     }
288 
289     if (memcpy_s(&newHandle->reserve[newHandle->reserveFds], sizeof(int32_t) * newHandle->reserveInts,
290         &handle->reserve[handle->reserveFds], sizeof(int32_t) * handle->reserveInts) != EOK) {
291         DP_ERR_LOG("CloneBufferHandle memcpy_s failed");
292         FreeBufferHandle(newHandle);
293         return nullptr;
294     }
295     return newHandle;
296 }
297 
TransBufferHandleToSurfaceBuffer(BufferHandle * bufferHandle)298 sptr<SurfaceBuffer> TransBufferHandleToSurfaceBuffer(BufferHandle *bufferHandle)
299 {
300     DP_DEBUG_LOG("entered");
301     DP_CHECK_ERROR_RETURN_RET_LOG(bufferHandle == nullptr, nullptr, "bufferHandle is nullptr.");
302 
303     BufferHandle *newBufferHandle = CloneBufferHandle(bufferHandle);
304     sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
305     surfaceBuffer->SetBufferHandle(newBufferHandle);
306     DP_INFO_LOG("TransBufferHandleToSurfaceBuffer w=%{public}d, h=%{public}d, f=%{public}d",
307         surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight(), surfaceBuffer->GetFormat());
308     return surfaceBuffer;
309 }
310 
SetAuxiliaryPicture(std::shared_ptr<PictureIntf> picture,BufferHandle * bufferHandle,CameraAuxiliaryPictureType type)311 void SetAuxiliaryPicture(std::shared_ptr<PictureIntf> picture, BufferHandle *bufferHandle,
312     CameraAuxiliaryPictureType type)
313 {
314     DP_INFO_LOG("entered, AuxiliaryPictureType type = %{public}d", static_cast<int32_t>(type));
315     DP_CHECK_ERROR_RETURN_LOG(picture == nullptr || bufferHandle == nullptr, "bufferHandle is nullptr.");
316 
317     auto buffer = TransBufferHandleToSurfaceBuffer(bufferHandle);
318     picture->SetAuxiliaryPicture(buffer, type);
319 }
320 
AssemleAuxilaryPicture(const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt & buffer,std::shared_ptr<PictureIntf> & picture)321 void AssemleAuxilaryPicture(const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer,
322     std::shared_ptr<PictureIntf>& picture)
323 {
324     if (buffer.isGainMapValid) {
325         SetAuxiliaryPicture(picture, buffer.gainMapHandle->GetBufferHandle(),
326             CameraAuxiliaryPictureType::GAINMAP);
327     }
328     if (buffer.isDepthMapValid) {
329         SetAuxiliaryPicture(picture, buffer.depthMapHandle->GetBufferHandle(),
330             CameraAuxiliaryPictureType::DEPTH_MAP);
331     }
332     if (buffer.isUnrefocusImageValid) {
333         SetAuxiliaryPicture(picture, buffer.unrefocusImageHandle->GetBufferHandle(),
334             CameraAuxiliaryPictureType::UNREFOCUS_MAP);
335     }
336     if (buffer.isHighBitDepthLinearImageValid) {
337         SetAuxiliaryPicture(picture, buffer.highBitDepthLinearImageHandle->GetBufferHandle(),
338             CameraAuxiliaryPictureType::LINEAR_MAP);
339     }
340     if (buffer.isMakerInfoValid) {
341         auto makerInfoBuffer = TransBufferHandleToSurfaceBuffer(buffer.makerInfoHandle->GetBufferHandle());
342         picture->SetMaintenanceData(makerInfoBuffer);
343     }
344 }
345 
AssemblePicture(const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt & buffer)346 std::shared_ptr<PictureIntf> PhotoPostProcessor::PhotoProcessListener::AssemblePicture(
347     const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer)
348 {
349     int32_t exifDataSize = 0;
350     if (buffer.metadata) {
351         int32_t retExifDataSize = buffer.metadata->Get("exifDataSize", exifDataSize);
352         DP_INFO_LOG("AssemblePicture retExifDataSize: %{public}d, exifDataSize: %{public}d",
353             retExifDataSize, exifDataSize);
354     }
355     auto imageBuffer = TransBufferHandleToSurfaceBuffer(buffer.imageHandle->GetBufferHandle());
356     DP_CHECK_ERROR_RETURN_RET_LOG(imageBuffer == nullptr, nullptr, "bufferHandle is nullptr.");
357     DP_INFO_LOG("AssemblePicture ImageBufferInfoExt valid: gainMap(%{public}d), depthMap(%{public}d), "
358         "unrefocusMap(%{public}d), linearMap(%{public}d), exif(%{public}d), makeInfo(%{public}d)",
359         buffer.isGainMapValid, buffer.isDepthMapValid, buffer.isUnrefocusImageValid,
360         buffer.isHighBitDepthLinearImageValid, buffer.isExifValid, buffer.isMakerInfoValid);
361     std::shared_ptr<PictureIntf> picture = PictureProxy::CreatePictureProxy();
362     DP_CHECK_ERROR_RETURN_RET_LOG(picture == nullptr, nullptr,
363         "pictureProxy use count is not 1");
364     picture->Create(imageBuffer);
365     DP_CHECK_ERROR_RETURN_RET_LOG(picture == nullptr, nullptr, "picture is nullptr.");
366     if (buffer.isExifValid) {
367         auto exifBuffer = TransBufferHandleToSurfaceBuffer(buffer.exifHandle->GetBufferHandle());
368         sptr<BufferExtraData> extraData = new BufferExtraDataImpl();
369         extraData->ExtraSet("exifDataSize", exifDataSize);
370         if (exifBuffer) {
371             exifBuffer->SetExtraData(extraData);
372         }
373         picture->SetExifMetadata(exifBuffer);
374     }
375     if (picture) {
376         AssemleAuxilaryPicture(buffer, picture);
377         picture->RotatePicture();
378     }
379     return picture;
380 }
381 
OnProcessDoneExt(const std::string & imageId,const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt & buffer)382 int32_t PhotoPostProcessor::PhotoProcessListener::OnProcessDoneExt(const std::string& imageId,
383     const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer)
384 {
385     DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s", imageId.c_str());
386     auto ret = ProcessBufferInfoExt(imageId, buffer);
387     if (ret != DP_OK) {
388         DP_ERR_LOG("process done failed imageId: %{public}s.", imageId.c_str());
389         if (auto processResult = processResult_.lock()) {
390             processResult->OnError(imageId, DPS_ERROR_IMAGE_PROC_FAILED);
391         }
392     }
393     return DP_OK;
394 }
395 
ProcessBufferInfoExt(const std::string & imageId,const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt & buffer)396 int32_t PhotoPostProcessor::PhotoProcessListener::ProcessBufferInfoExt(const std::string& imageId,
397     const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer)
398 {
399     auto bufferHandle = buffer.imageHandle->GetBufferHandle();
400     DP_CHECK_ERROR_RETURN_RET_LOG(bufferHandle == nullptr, DPS_ERROR_IMAGE_PROC_FAILED, "bufferHandle is nullptr.");
401 
402     int size = bufferHandle->size;
403     int32_t isDegradedImage = 0;
404     int32_t dataSize = size;
405     int32_t deferredImageFormat = 0;
406     uint32_t cloudImageEnhanceFlag = 0;
407     if (buffer.metadata) {
408         int32_t retImageQuality = buffer.metadata->Get("isDegradedImage", isDegradedImage);
409         int32_t retDataSize = buffer.metadata->Get("dataSize", dataSize);
410         int32_t retFormat = buffer.metadata->Get("deferredImageFormat", deferredImageFormat);
411         int32_t retCloudImageEnhanceFlag = buffer.metadata->Get("cloudImageEnhanceFlag",
412             cloudImageEnhanceFlag);
413         DP_DEBUG_LOG("retImageQuality: %{public}d, retDataSize: %{public}d, retFormat: %{public}d, "
414             "retCloudImageEnhanceFlag: %{public}d", retImageQuality, retDataSize, retFormat,
415             retCloudImageEnhanceFlag);
416     }
417 
418     DP_INFO_LOG("bufferHandle param, bufferHandleSize: %{public}d, dataSize: %{public}d, isDegradedImage: %{public}d, "
419         "deferredImageFormat: %{public}d, cloudImageEnhanceFlag: %{public}u",
420         size, dataSize, isDegradedImage, deferredImageFormat, cloudImageEnhanceFlag);
421     auto processResult = processResult_.lock();
422     if (deferredImageFormat == static_cast<int32_t>(Media::PhotoFormat::YUV)) {
423         std::shared_ptr<PictureIntf> picture = AssemblePicture(buffer);
424         DP_CHECK_ERROR_RETURN_RET_LOG(picture == nullptr, DPS_ERROR_IMAGE_PROC_FAILED,
425             "failed to AssemblePicture.");
426 
427         std::shared_ptr<BufferInfoExt> bufferInfo = std::make_shared<BufferInfoExt>(picture, dataSize,
428             isDegradedImage == 0, cloudImageEnhanceFlag);
429         if (processResult) {
430             processResult->OnProcessDoneExt(imageId, bufferInfo);
431         }
432     } else {
433         auto bufferPtr = std::make_shared<SharedBuffer>(dataSize);
434         DP_CHECK_ERROR_RETURN_RET_LOG(bufferPtr->Initialize() != DP_OK, DPS_ERROR_IMAGE_PROC_FAILED,
435             "failed to initialize shared buffer.");
436 
437         auto addr = mmap(nullptr, dataSize, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0);
438         DP_CHECK_ERROR_RETURN_RET_LOG(addr == MAP_FAILED,
439             DPS_ERROR_IMAGE_PROC_FAILED, "failed to mmap shared buffer.");
440         if (bufferPtr->CopyFrom(static_cast<uint8_t*>(addr), dataSize) == DP_OK) {
441             DP_INFO_LOG("DPS_PHOTO: bufferPtr fd: %{public}d, fd: %{public}d", bufferHandle->fd, bufferPtr->GetFd());
442             std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>(bufferPtr, dataSize,
443                 isDegradedImage == 0, cloudImageEnhanceFlag);
444             if (processResult) {
445                 processResult->OnProcessDone(imageId, bufferInfo);
446             }
447         }
448         munmap(addr, dataSize);
449     }
450     ReportEvent(imageId);
451     return DP_OK;
452 }
453 
OnError(const std::string & imageId,OHOS::HDI::Camera::V1_2::ErrorCode errorCode)454 int32_t PhotoPostProcessor::PhotoProcessListener::OnError(const std::string& imageId,
455     OHOS::HDI::Camera::V1_2::ErrorCode errorCode)
456 {
457     DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s, error: %{public}d", imageId.c_str(), errorCode);
458     if (auto processResult = processResult_.lock()) {
459         DpsError dpsErrorCode = MapHdiError(errorCode);
460         processResult->OnError(imageId, dpsErrorCode);
461     }
462     return DP_OK;
463 }
464 
OnStatusChanged(OHOS::HDI::Camera::V1_2::SessionStatus status)465 int32_t PhotoPostProcessor::PhotoProcessListener::OnStatusChanged(OHOS::HDI::Camera::V1_2::SessionStatus status)
466 {
467     DP_INFO_LOG("DPS_PHOTO: HdiStatus: %{public}d", status);
468     if (auto processResult = processResult_.lock()) {
469         HdiStatus hdiStatus = MapHdiStatus(status);
470         processResult->OnStateChanged(hdiStatus);
471     }
472     return DP_OK;
473 }
474 
ReportEvent(const std::string & imageId)475 void PhotoPostProcessor::PhotoProcessListener::ReportEvent(const std::string& imageId)
476 {
477     DPSEventReport::GetInstance().UpdateProcessDoneTime(imageId, userId_);
478 }
479 
PhotoPostProcessor(const int32_t userId)480 PhotoPostProcessor::PhotoPostProcessor(const int32_t userId)
481     : userId_(userId), serviceListener_(nullptr), processListener_(nullptr), sessionDeathRecipient_(nullptr)
482 {
483     DP_DEBUG_LOG("entered");
484 }
485 
~PhotoPostProcessor()486 PhotoPostProcessor::~PhotoPostProcessor()
487 {
488     DP_DEBUG_LOG("entered");
489     DisconnectService();
490     SetPhotoSession(nullptr);
491     runningWork_.clear();
492     imageId2CrashCount_.clear();
493     removeNeededList_.clear();
494 }
495 
Initialize()496 void PhotoPostProcessor::Initialize()
497 {
498     DP_DEBUG_LOG("entered");
499     processResult_ = std::make_shared<PhotoProcessResult>(userId_);
500     sessionDeathRecipient_ = sptr<SessionDeathRecipient>::MakeSptr(processResult_);
501     processListener_ = sptr<PhotoProcessListener>::MakeSptr(userId_, processResult_);
502     ConnectService();
503 }
504 
GetConcurrency(ExecutionMode mode)505 int32_t PhotoPostProcessor::GetConcurrency(ExecutionMode mode)
506 {
507     int32_t count = 1;
508     auto session = GetPhotoSession();
509     DP_CHECK_ERROR_RETURN_RET_LOG(session == nullptr, count, "photo session is nullptr, count: %{public}d", count);
510 
511     int32_t ret = session->GetCoucurrency(OHOS::HDI::Camera::V1_2::ExecutionMode::BALANCED, count);
512     DP_INFO_LOG("DPS_PHOTO: GetCoucurrency to ive, ret: %{public}d", ret);
513     return count;
514 }
515 
GetPendingImages(std::vector<std::string> & pendingImages)516 bool PhotoPostProcessor::GetPendingImages(std::vector<std::string>& pendingImages)
517 {
518     auto session = GetPhotoSession();
519     DP_CHECK_ERROR_RETURN_RET_LOG(session == nullptr, false, "photo session is nullptr.");
520 
521     int32_t ret = session->GetPendingImages(pendingImages);
522     DP_INFO_LOG("DPS_PHOTO: GetPendingImages to ive, ret: %{public}d", ret);
523     return ret == DP_OK;
524 }
525 
SetExecutionMode(ExecutionMode executionMode)526 void PhotoPostProcessor::SetExecutionMode(ExecutionMode executionMode)
527 {
528     auto session = GetPhotoSession();
529     DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "photo session is nullptr.");
530 
531     int32_t ret = session->SetExecutionMode(MapToHdiExecutionMode(executionMode));
532     DP_INFO_LOG("DPS_PHOTO: SetExecutionMode to ive, ret: %{public}d", ret);
533 }
534 
SetDefaultExecutionMode()535 void PhotoPostProcessor::SetDefaultExecutionMode()
536 {
537     // 采用直接新增方法,不适配1_2 和 1_3 模式的差异点
538     auto session = GetPhotoSession();
539     DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "photo session is nullptr.");
540 
541     int32_t ret = session->SetExecutionMode(
542         static_cast<OHOS::HDI::Camera::V1_2::ExecutionMode>(OHOS::HDI::Camera::V1_3::ExecutionMode::DEFAULT));
543     DP_INFO_LOG("DPS_PHOTO: SetDefaultExecutionMode to ive, ret: %{public}d", ret);
544 }
545 
ProcessImage(const std::string & imageId)546 void PhotoPostProcessor::ProcessImage(const std::string& imageId)
547 {
548     auto session = GetPhotoSession();
549     if (session == nullptr) {
550         DP_ERR_LOG("Failed to process imageId: %{public}s, photo session is nullptr", imageId.c_str());
551         DP_CHECK_EXECUTE(processResult_, processResult_->OnError(imageId, DPS_ERROR_SESSION_NOT_READY_TEMPORARILY));
552         return;
553     }
554 
555     StartTimer(imageId);
556     int32_t ret = session->ProcessImage(imageId);
557     DP_INFO_LOG("DPS_PHOTO: Process photo to ive, imageId: %{public}s, ret: %{public}d", imageId.c_str(), ret);
558 }
559 
RemoveImage(const std::string & imageId)560 void PhotoPostProcessor::RemoveImage(const std::string& imageId)
561 {
562     auto session = GetPhotoSession();
563     if (session == nullptr) {
564         DP_ERR_LOG("photo session is nullptr.");
565         std::lock_guard<std::mutex> lock(removeMutex_);
566         removeNeededList_.emplace_back(imageId);
567         return;
568     }
569 
570     int32_t ret = session->RemoveImage(imageId);
571     DP_INFO_LOG("DPS_PHOTO: Remove photo to ive, imageId: %{public}s, ret: %{public}d", imageId.c_str(), ret);
572     imageId2CrashCount_.erase(imageId);
573     DPSEventReport::GetInstance().UpdateRemoveTime(imageId, userId_);
574 }
575 
Interrupt()576 void PhotoPostProcessor::Interrupt()
577 {
578     auto session = GetPhotoSession();
579     DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "photo session is nullptr.");
580 
581     int32_t ret = session->Interrupt();
582     DP_INFO_LOG("DPS_PHOTO: Interrupt photo to ive, ret: %{public}d", ret);
583 }
584 
Reset()585 void PhotoPostProcessor::Reset()
586 {
587     auto session = GetPhotoSession();
588     DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "photo session is nullptr.");
589 
590     int32_t ret = session->Reset();
591     DP_INFO_LOG("DPS_PHOTO: Reset to ive, ret: %{public}d", ret);
592     consecutiveTimeoutCount_ = 0;
593 }
594 
OnProcessDone(const std::string & imageId,const std::shared_ptr<BufferInfo> & bufferInfo)595 void PhotoPostProcessor::OnProcessDone(const std::string& imageId, const std::shared_ptr<BufferInfo>& bufferInfo)
596 {
597     DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s, consecutiveTimeoutCount: %{public}d",
598         imageId.c_str(), consecutiveTimeoutCount_.load());
599     consecutiveTimeoutCount_ = 0;
600     StopTimer(imageId);
601     if (auto callback = callback_.lock()) {
602         callback->OnProcessDone(userId_, imageId, bufferInfo);
603     }
604 }
605 
OnProcessDoneExt(const std::string & imageId,const std::shared_ptr<BufferInfoExt> & bufferInfo)606 void PhotoPostProcessor::OnProcessDoneExt(const std::string& imageId, const std::shared_ptr<BufferInfoExt>& bufferInfo)
607 {
608     DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s, consecutiveTimeoutCount: %{public}d",
609         imageId.c_str(), consecutiveTimeoutCount_.load());
610     consecutiveTimeoutCount_ = 0;
611     StopTimer(imageId);
612     if (auto callback = callback_.lock()) {
613         callback->OnProcessDoneExt(userId_, imageId, bufferInfo);
614     }
615 }
616 
OnError(const std::string & imageId,DpsError errorCode)617 void PhotoPostProcessor::OnError(const std::string& imageId, DpsError errorCode)
618 {
619     DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s, consecutiveTimeoutCount: %{public}d",
620         imageId.c_str(), consecutiveTimeoutCount_.load());
621     StopTimer(imageId);
622     if (errorCode == DpsError::DPS_ERROR_IMAGE_PROC_TIMEOUT) {
623         consecutiveTimeoutCount_++;
624         if (consecutiveTimeoutCount_ >= static_cast<int>(MAX_CONSECUTIVE_TIMEOUT_COUNT)) {
625             Reset();
626         }
627     } else {
628         consecutiveTimeoutCount_ = 0;
629     }
630 
631     if (auto callback = callback_.lock()) {
632         callback->OnError(userId_, imageId, errorCode);
633     }
634 }
635 
OnStateChanged(HdiStatus hdiStatus)636 void PhotoPostProcessor::OnStateChanged(HdiStatus hdiStatus)
637 {
638     DP_INFO_LOG("DPS_PHOTO: HdiStatus: %{public}d", hdiStatus);
639     EventsMonitor::GetInstance().NotifyImageEnhanceStatus(hdiStatus);
640 }
641 
OnSessionDied()642 void PhotoPostProcessor::OnSessionDied()
643 {
644     DP_INFO_LOG("entered, photo session died!");
645     SetPhotoSession(nullptr);
646     consecutiveTimeoutCount_ = 0;
647     OnStateChanged(HdiStatus::HDI_DISCONNECTED);
648     for (const auto& item : runningWork_) {
649         std::string imageId = item.first;
650         DP_INFO_LOG("Failed to process imageId: %{public}s due to connect service failed", item.first.c_str());
651         if (imageId2CrashCount_.count(item.first) == 0) {
652             imageId2CrashCount_.emplace(item.first, 1);
653         } else {
654             imageId2CrashCount_[item.first] += 1;
655         }
656         DpsError code = DPS_ERROR_SESSION_NOT_READY_TEMPORARILY;
657         if (imageId2CrashCount_[item.first] >= MAX_CONSECUTIVE_CRASH_COUNT) {
658             code = DPS_ERROR_IMAGE_PROC_FAILED;
659         }
660         DP_CHECK_EXECUTE(processResult_, processResult_->OnError(imageId, code));
661     }
662 }
663 
SetCallback(const std::weak_ptr<IImageProcessCallbacks> & callback)664 void PhotoPostProcessor::SetCallback(const std::weak_ptr<IImageProcessCallbacks>& callback)
665 {
666     callback_ = callback;
667 }
668 
OnTimerOut(const std::string & imageId)669 void PhotoPostProcessor::OnTimerOut(const std::string& imageId)
670 {
671     DP_INFO_LOG("DPS_TIMER: Executed imageId: %{public}s", imageId.c_str());
672     DP_CHECK_EXECUTE(processResult_, processResult_->OnError(imageId, DPS_ERROR_IMAGE_PROC_TIMEOUT));
673 }
674 
ConnectService()675 void PhotoPostProcessor::ConnectService()
676 {
677     auto svcMgr = HDI::ServiceManager::V1_0::IServiceManager::Get();
678     DP_CHECK_ERROR_RETURN_LOG(svcMgr == nullptr, "IServiceManager init failed.");
679     serviceListener_ = sptr<PhotoServiceListener>::MakeSptr(weak_from_this());
680     auto ret  = svcMgr->RegisterServiceStatusListener(serviceListener_, DEVICE_CLASS_DEFAULT);
681     DP_CHECK_ERROR_RETURN_LOG(ret != 0, "Register Photo ServiceStatusListener failed.");
682 }
683 
DisconnectService()684 void PhotoPostProcessor::DisconnectService()
685 {
686     auto session = GetPhotoSession();
687     DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "PhotoSession is nullptr.");
688 
689     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IImageProcessSession>(session);
690     bool result = remote->RemoveDeathRecipient(sessionDeathRecipient_);
691     DP_CHECK_ERROR_RETURN_LOG(!result, "Remove DeathRecipient for PhotoProcessSession failed.");
692     auto svcMgr = HDI::ServiceManager::V1_0::IServiceManager::Get();
693     DP_CHECK_ERROR_RETURN_LOG(svcMgr == nullptr, "IServiceManager init failed.");
694 
695     auto ret  = svcMgr->UnregisterServiceStatusListener(serviceListener_);
696     DP_CHECK_ERROR_RETURN_LOG(ret != 0, "Unregister Photo ServiceStatusListener failed.");
697 }
698 
OnServiceChange(const HDI::ServiceManager::V1_0::ServiceStatus & status)699 void PhotoPostProcessor::OnServiceChange(const HDI::ServiceManager::V1_0::ServiceStatus& status)
700 {
701     DP_CHECK_RETURN(status.serviceName != PHOTO_SERVICE_NAME);
702     DP_CHECK_RETURN_LOG(status.status != HDI::ServiceManager::V1_0::SERVIE_STATUS_START,
703         "photo service state: %{public}d", status.status);
704     DP_CHECK_RETURN(GetPhotoSession() != nullptr);
705 
706     sptr<OHOS::HDI::Camera::V1_2::IImageProcessService> proxyV1_2 =
707         OHOS::HDI::Camera::V1_2::IImageProcessService::Get(status.serviceName);
708     DP_CHECK_ERROR_RETURN_LOG(proxyV1_2 == nullptr, "get ImageProcessService failed.");
709 
710     uint32_t majorVer = 0;
711     uint32_t minorVer = 0;
712     proxyV1_2->GetVersion(majorVer, minorVer);
713     int32_t versionId = GetVersionId(majorVer, minorVer);
714     sptr<IImageProcessSession> session;
715     sptr<OHOS::HDI::Camera::V1_3::IImageProcessService> proxyV1_3;
716     if (versionId >= GetVersionId(HDI_VERSION_1, HDI_VERSION_3)) {
717         proxyV1_3 = OHOS::HDI::Camera::V1_3::IImageProcessService::CastFrom(proxyV1_2);
718     }
719     if (proxyV1_3 != nullptr) {
720         DP_INFO_LOG("CreateImageProcessSessionExt version=%{public}d_%{public}d", majorVer, minorVer);
721         proxyV1_3->CreateImageProcessSessionExt(userId_, processListener_, session);
722     } else {
723         DP_INFO_LOG("CreateImageProcessSession version=%{public}d_%{public}d", majorVer, minorVer);
724         proxyV1_2->CreateImageProcessSession(userId_, processListener_, session);
725     }
726     DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "get ImageProcessSession failed.");
727 
728     const sptr<IRemoteObject>& remote = OHOS::HDI::hdi_objcast<IImageProcessSession>(session);
729     bool result = remote->AddDeathRecipient(sessionDeathRecipient_);
730     DP_CHECK_ERROR_RETURN_LOG(!result, "add DeathRecipient for ImageProcessSession failed.");
731 
732     RemoveNeedJbo(session);
733     SetPhotoSession(session);
734     OnStateChanged(HdiStatus::HDI_READY);
735 }
736 
RemoveNeedJbo(const sptr<IImageProcessSession> & session)737 void PhotoPostProcessor::RemoveNeedJbo(const sptr<IImageProcessSession>& session)
738 {
739     std::lock_guard<std::mutex> lock(removeMutex_);
740     for (const auto& imageId : removeNeededList_) {
741         int32_t ret = session->RemoveImage(imageId);
742         DP_INFO_LOG("DPS_PHOTO: RemoveImage imageId: %{public}s, ret: %{public}d", imageId.c_str(), ret);
743     }
744     removeNeededList_.clear();
745 }
746 
StartTimer(const std::string & imageId)747 void PhotoPostProcessor::StartTimer(const std::string& imageId)
748 {
749     uint32_t timeId = DpsTimer::GetInstance().StartTimer([&, imageId]() {OnTimerOut(imageId);}, MAX_PROC_TIME_MS);
750     DP_INFO_LOG("DPS_TIMER: Start imageId: %{public}s, timeId: %{public}u", imageId.c_str(), timeId);
751     runningWork_.emplace(imageId, timeId);
752 }
753 
StopTimer(const std::string & imageId)754 void PhotoPostProcessor::StopTimer(const std::string& imageId)
755 {
756     auto it = runningWork_.find(imageId);
757     DP_CHECK_ERROR_RETURN_LOG(it == runningWork_.end(),
758         "Stoptimer failed not find imageId: %{public}s", imageId.c_str());
759 
760     DpsTimer::GetInstance().StopTimer(it->second);
761     DP_INFO_LOG("DPS_TIMER: Stop imageId: %{public}s, timeId: %{public}u", imageId.c_str(), it->second);
762     runningWork_.erase(it);
763 }
764 } // namespace DeferredProcessing
765 } // namespace CameraStandard
766 } // namespace OHOS