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 "session_coordinator.h"
17 #include <mutex>
18 
19 #include "dp_log.h"
20 #include "buffer_info.h"
21 #include "dps_event_report.h"
22 #include "steady_clock.h"
23 #include "picture.h"
24 #include "video_session_info.h"
25 
26 namespace OHOS {
27 namespace CameraStandard {
28 namespace DeferredProcessing {
MapDpsErrorCode(DpsError errorCode)29 ErrorCode MapDpsErrorCode(DpsError errorCode)
30 {
31     ErrorCode code = ErrorCode::ERROR_IMAGE_PROC_ABNORMAL;
32     switch (errorCode) {
33         case DpsError::DPS_ERROR_SESSION_SYNC_NEEDED:
34             code = ErrorCode::ERROR_SESSION_SYNC_NEEDED;
35             break;
36         case DpsError::DPS_ERROR_SESSION_NOT_READY_TEMPORARILY:
37             code = ErrorCode::ERROR_SESSION_NOT_READY_TEMPORARILY;
38             break;
39         case DpsError::DPS_ERROR_IMAGE_PROC_INVALID_PHOTO_ID:
40             code = ErrorCode::ERROR_IMAGE_PROC_INVALID_PHOTO_ID;
41             break;
42         case DpsError::DPS_ERROR_IMAGE_PROC_FAILED:
43             code = ErrorCode::ERROR_IMAGE_PROC_FAILED;
44             break;
45         case DpsError::DPS_ERROR_IMAGE_PROC_TIMEOUT:
46             code = ErrorCode::ERROR_IMAGE_PROC_TIMEOUT;
47             break;
48         case DpsError::DPS_ERROR_IMAGE_PROC_ABNORMAL:
49             code = ErrorCode::ERROR_IMAGE_PROC_ABNORMAL;
50             break;
51         case DpsError::DPS_ERROR_IMAGE_PROC_INTERRUPTED:
52             code = ErrorCode::ERROR_IMAGE_PROC_INTERRUPTED;
53             break;
54         case DpsError::DPS_ERROR_VIDEO_PROC_INVALID_VIDEO_ID:
55             code = ErrorCode::ERROR_VIDEO_PROC_INVALID_VIDEO_ID;
56             break;
57         case DpsError::DPS_ERROR_VIDEO_PROC_FAILED:
58             code = ErrorCode::ERROR_VIDEO_PROC_FAILED;
59             break;
60         case DpsError::DPS_ERROR_VIDEO_PROC_TIMEOUT:
61             code = ErrorCode::ERROR_VIDEO_PROC_TIMEOUT;
62             break;
63         case DpsError::DPS_ERROR_VIDEO_PROC_INTERRUPTED:
64             code = ErrorCode::ERROR_VIDEO_PROC_INTERRUPTED;
65             break;
66         default:
67             DP_WARNING_LOG("unexpected error code: %{public}d.", errorCode);
68             break;
69     }
70     return code;
71 }
72 
MapDpsStatus(DpsStatus statusCode)73 StatusCode MapDpsStatus(DpsStatus statusCode)
74 {
75     StatusCode code = StatusCode::SESSION_STATE_IDLE;
76     switch (statusCode) {
77         case DpsStatus::DPS_SESSION_STATE_IDLE:
78             code = StatusCode::SESSION_STATE_IDLE;
79             break;
80         case DpsStatus::DPS_SESSION_STATE_RUNNALBE:
81             code = StatusCode::SESSION_STATE_RUNNALBE;
82             break;
83         case DpsStatus::DPS_SESSION_STATE_RUNNING:
84             code = StatusCode::SESSION_STATE_RUNNING;
85             break;
86         case DpsStatus::DPS_SESSION_STATE_SUSPENDED:
87             code = StatusCode::SESSION_STATE_SUSPENDED;
88             break;
89         default:
90             DP_WARNING_LOG("unexpected error code: %{public}d.", statusCode);
91             break;
92     }
93     return code;
94 }
95 
96 class SessionCoordinator::ImageProcCallbacks : public IImageProcessCallbacks {
97 public:
ImageProcCallbacks(SessionCoordinator * coordinator)98     explicit ImageProcCallbacks(SessionCoordinator* coordinator) : coordinator_(coordinator)
99     {
100     }
101 
~ImageProcCallbacks()102     ~ImageProcCallbacks() override
103     {
104         coordinator_ = nullptr;
105     }
106 
OnProcessDone(const int32_t userId,const std::string & imageId,std::shared_ptr<BufferInfo> bufferInfo)107     void OnProcessDone(const int32_t userId, const std::string& imageId,
108         std::shared_ptr<BufferInfo> bufferInfo) override
109     {
110         sptr<IPCFileDescriptor> ipcFd = bufferInfo->GetIPCFileDescriptor();
111         int32_t dataSize = bufferInfo->GetDataSize();
112         bool isCloudImageEnhanceSupported = bufferInfo->IsCloudImageEnhanceSupported();
113         if (coordinator_) {
114             coordinator_->OnProcessDone(userId, imageId, ipcFd, dataSize, isCloudImageEnhanceSupported);
115         }
116     }
117 
OnProcessDoneExt(int userId,const std::string & imageId,std::shared_ptr<BufferInfoExt> bufferInfo)118     void OnProcessDoneExt(int userId, const std::string& imageId,
119         std::shared_ptr<BufferInfoExt> bufferInfo) override
120     {
121         bool isCloudImageEnhanceSupported = bufferInfo->IsCloudImageEnhanceSupported();
122         if (coordinator_ && bufferInfo) {
123             coordinator_->OnProcessDoneExt(userId, imageId, bufferInfo->GetPicture(), isCloudImageEnhanceSupported);
124         }
125     }
126 
OnError(const int userId,const std::string & imageId,DpsError errorCode)127     void OnError(const int userId, const std::string& imageId, DpsError errorCode) override
128     {
129         DP_CHECK_EXECUTE(coordinator_ != nullptr, coordinator_->OnError(userId, imageId, errorCode));
130     }
131 
OnStateChanged(const int32_t userId,DpsStatus statusCode)132     void OnStateChanged(const int32_t userId, DpsStatus statusCode) override
133     {
134         DP_CHECK_EXECUTE(coordinator_ != nullptr, coordinator_->OnStateChanged(userId, statusCode));
135     }
136 
137 private:
138     SessionCoordinator* coordinator_;
139 };
140 
141 class SessionCoordinator::VideoProcCallbacks : public IVideoProcessCallbacks {
142 public:
VideoProcCallbacks(const std::weak_ptr<SessionCoordinator> & coordinator)143     explicit VideoProcCallbacks(const std::weak_ptr<SessionCoordinator>& coordinator) : coordinator_(coordinator)
144     {
145     }
146 
147     ~VideoProcCallbacks() = default;
148 
OnProcessDone(const int32_t userId,const std::string & videoId,const sptr<IPCFileDescriptor> & ipcFd)149     void OnProcessDone(const int32_t userId, const std::string& videoId,
150         const sptr<IPCFileDescriptor>& ipcFd) override
151     {
152         auto video = coordinator_.lock();
153         DP_CHECK_ERROR_RETURN_LOG(video == nullptr, "SessionCoordinator is nullptr.");
154         video->OnVideoProcessDone(userId, videoId, ipcFd);
155     }
156 
OnError(const int32_t userId,const std::string & videoId,DpsError errorCode)157     void OnError(const int32_t userId, const std::string& videoId, DpsError errorCode) override
158     {
159         auto video = coordinator_.lock();
160         DP_CHECK_ERROR_RETURN_LOG(video == nullptr, "SessionCoordinator is nullptr.");
161         video->OnVideoError(userId, videoId, errorCode);
162     }
163 
OnStateChanged(const int32_t userId,DpsStatus statusCode)164     void OnStateChanged(const int32_t userId, DpsStatus statusCode) override
165     {
166         auto video = coordinator_.lock();
167         DP_CHECK_ERROR_RETURN_LOG(video == nullptr, "SessionCoordinator is nullptr.");
168         video->OnStateChanged(userId, statusCode);
169     }
170 
171 private:
172     std::weak_ptr<SessionCoordinator> coordinator_;
173 };
174 
SessionCoordinator()175 SessionCoordinator::SessionCoordinator()
176     : imageProcCallbacks_(nullptr),
177       videoProcCallbacks_(nullptr),
178       remoteVideoCallbacksMap_(),
179       pendingRequestResults_()
180 {
181     DP_DEBUG_LOG("entered.");
182 }
183 
~SessionCoordinator()184 SessionCoordinator::~SessionCoordinator()
185 {
186     DP_DEBUG_LOG("entered.");
187     imageProcCallbacks_ = nullptr;
188     videoProcCallbacks_ = nullptr;
189     remoteVideoCallbacksMap_.clear();
190     pendingRequestResults_.clear();
191 }
192 
Initialize()193 void SessionCoordinator::Initialize()
194 {
195     imageProcCallbacks_ = std::make_shared<ImageProcCallbacks>(this);
196     videoProcCallbacks_ = std::make_shared<VideoProcCallbacks>(weak_from_this());
197 }
198 
Start()199 void SessionCoordinator::Start()
200 {
201     //dps_log
202 }
203 
Stop()204 void SessionCoordinator::Stop()
205 {
206     //dps_log
207 }
208 
GetImageProcCallbacks()209 std::shared_ptr<IImageProcessCallbacks> SessionCoordinator::GetImageProcCallbacks()
210 {
211     return imageProcCallbacks_;
212 }
213 
GetVideoProcCallbacks()214 std::shared_ptr<IVideoProcessCallbacks> SessionCoordinator::GetVideoProcCallbacks()
215 {
216     return videoProcCallbacks_;
217 }
218 
OnProcessDone(const int32_t userId,const std::string & imageId,const sptr<IPCFileDescriptor> & ipcFd,const int32_t dataSize,bool isCloudImageEnhanceSupported)219 void SessionCoordinator::OnProcessDone(const int32_t userId, const std::string& imageId,
220     const sptr<IPCFileDescriptor>& ipcFd, const int32_t dataSize, bool isCloudImageEnhanceSupported)
221 {
222     sptr<IDeferredPhotoProcessingSessionCallback> spCallback = GetRemoteImageCallback(userId);
223     if (spCallback != nullptr) {
224         DP_INFO_LOG("entered, imageId: %{public}s", imageId.c_str());
225         spCallback->OnProcessImageDone(imageId, ipcFd, dataSize, isCloudImageEnhanceSupported);
226     } else {
227         DP_INFO_LOG("callback is null, cache request, imageId: %{public}s.", imageId.c_str());
228         std::lock_guard<std::mutex> lock(pendingImageResultsMutex_);
229         pendingImageResults_.push_back({ CallbackType::ON_PROCESS_DONE, userId, imageId, ipcFd, dataSize,
230             DpsError::DPS_ERROR_SESSION_SYNC_NEEDED, DpsStatus::DPS_SESSION_STATE_IDLE, isCloudImageEnhanceSupported });
231     }
232     return;
233 }
234 
OnProcessDoneExt(int userId,const std::string & imageId,std::shared_ptr<Media::Picture> picture,bool isCloudImageEnhanceSupported)235 void SessionCoordinator::OnProcessDoneExt(int userId, const std::string& imageId,
236     std::shared_ptr<Media::Picture> picture, bool isCloudImageEnhanceSupported)
237 {
238     sptr<IDeferredPhotoProcessingSessionCallback> spCallback = GetRemoteImageCallback(userId);
239     if (spCallback != nullptr) {
240         DP_INFO_LOG("entered, imageId: %s", imageId.c_str());
241         spCallback->OnProcessImageDone(imageId, picture, isCloudImageEnhanceSupported);
242     } else {
243         DP_INFO_LOG("callback is null, cache request, imageId: %{public}s.", imageId.c_str());
244     }
245     return;
246 }
247 
OnError(const int userId,const std::string & imageId,DpsError errorCode)248 void SessionCoordinator::OnError(const int userId, const std::string& imageId, DpsError errorCode)
249 {
250     sptr<IDeferredPhotoProcessingSessionCallback> spCallback = GetRemoteImageCallback(userId);
251     if (spCallback != nullptr) {
252         DP_INFO_LOG("entered, userId: %{public}d", userId);
253         spCallback->OnError(imageId, MapDpsErrorCode(errorCode));
254     } else {
255         DP_INFO_LOG(
256             "callback is null, cache request, imageId: %{public}s, errorCode: %{public}d.", imageId.c_str(), errorCode);
257         std::lock_guard<std::mutex> lock(pendingImageResultsMutex_);
258         pendingImageResults_.push_back({ CallbackType::ON_ERROR, userId, imageId, nullptr, 0, errorCode });
259     }
260 }
261 
OnStateChanged(const int32_t userId,DpsStatus statusCode)262 void SessionCoordinator::OnStateChanged(const int32_t userId, DpsStatus statusCode)
263 {
264     sptr<IDeferredPhotoProcessingSessionCallback> spCallback = GetRemoteImageCallback(userId);
265     if (spCallback != nullptr) {
266         DP_INFO_LOG("entered, userId: %{public}d", userId);
267         spCallback->OnStateChanged(MapDpsStatus(statusCode));
268     } else {
269         DP_INFO_LOG("cache request, statusCode: %{public}d.", statusCode);
270         std::lock_guard<std::mutex> lock(pendingImageResultsMutex_);
271         pendingImageResults_.push_back({CallbackType::ON_STATE_CHANGED, userId, "", nullptr, 0,
272             DpsError::DPS_ERROR_IMAGE_PROC_ABNORMAL, statusCode});
273     }
274 }
275 
NotifySessionCreated(const int32_t userId,sptr<IDeferredPhotoProcessingSessionCallback> callback,TaskManager * taskManager)276 void SessionCoordinator::NotifySessionCreated(
277     const int32_t userId, sptr<IDeferredPhotoProcessingSessionCallback> callback, TaskManager* taskManager)
278 {
279     if (callback != nullptr) {
280         std::lock_guard<std::mutex> lock(remoteImageCallbacksMapMutex_);
281         remoteImageCallbacksMap_[userId] = callback;
282         auto thisPtr = shared_from_this();
283         taskManager->SubmitTask([thisPtr, callback]() {
284             if (thisPtr != nullptr) {
285                 thisPtr->ProcessPendingResults(callback);
286             }
287         });
288     }
289 }
290 
ProcessPendingResults(sptr<IDeferredPhotoProcessingSessionCallback> callback)291 void SessionCoordinator::ProcessPendingResults(sptr<IDeferredPhotoProcessingSessionCallback> callback)
292 {
293     DP_INFO_LOG("entered.");
294     std::lock_guard<std::mutex> lock(pendingImageResultsMutex_);
295     while (!pendingImageResults_.empty()) {
296         auto result = pendingImageResults_.front();
297         if (result.callbackType == CallbackType::ON_PROCESS_DONE) {
298             callback->OnProcessImageDone(result.imageId, result.ipcFd, result.dataSize,
299                 result.isCloudImageEnhanceSupported);
300             uint64_t endTime = SteadyClock::GetTimestampMilli();
301             DPSEventReport::GetInstance().ReportImageProcessResult(result.imageId, result.userId, endTime);
302         }
303         if (result.callbackType == CallbackType::ON_ERROR) {
304             callback->OnError(result.imageId, MapDpsErrorCode(result.errorCode));
305         }
306         if (result.callbackType == CallbackType::ON_STATE_CHANGED) {
307             callback->OnStateChanged(MapDpsStatus(result.statusCode));
308         }
309         pendingImageResults_.pop_front();
310     }
311 }
312 
NotifyCallbackDestroyed(const int32_t userId)313 void SessionCoordinator::NotifyCallbackDestroyed(const int32_t userId)
314 {
315     std::lock_guard<std::mutex> lock(remoteImageCallbacksMapMutex_);
316     if (remoteImageCallbacksMap_.count(userId) != 0) {
317         DP_INFO_LOG("session userId: %{public}d destroyed.", userId);
318         remoteImageCallbacksMap_.erase(userId);
319     }
320 }
321 
AddSession(const sptr<VideoSessionInfo> & sessionInfo)322 void SessionCoordinator::AddSession(const sptr<VideoSessionInfo>& sessionInfo)
323 {
324     int32_t userId = sessionInfo->GetUserId();
325     DP_INFO_LOG("add session userId: %{public}d", userId);
326     auto callback = sessionInfo->GetRemoteCallback();
327     if (callback != nullptr) {
328         remoteVideoCallbacksMap_[userId] = callback;
329         ProcessVideoResults(callback);
330     }
331 }
332 
DeleteSession(const int32_t userId)333 void SessionCoordinator::DeleteSession(const int32_t userId)
334 {
335     if (remoteVideoCallbacksMap_.count(userId) != 0) {
336         DP_INFO_LOG("delete session userId: %{public}d", userId);
337         remoteVideoCallbacksMap_.erase(userId);
338     }
339 }
340 
OnVideoProcessDone(const int32_t userId,const std::string & videoId,const sptr<IPCFileDescriptor> & ipcFd)341 void SessionCoordinator::OnVideoProcessDone(const int32_t userId, const std::string& videoId,
342     const sptr<IPCFileDescriptor> &ipcFd)
343 {
344     DP_INFO_LOG("userId: %{public}d, map size: %{public}d.",
345         userId, static_cast<int32_t>(remoteVideoCallbacksMap_.size()));
346     auto iter = remoteVideoCallbacksMap_.find(userId);
347     if (iter != remoteVideoCallbacksMap_.end()) {
348         auto spCallback = iter->second.promote();
349         DP_CHECK_ERROR_RETURN_LOG(spCallback == nullptr, "OnVideoProcessDone callback is nullptr.");
350         DP_INFO_LOG("videoId: %{public}s", videoId.c_str());
351         spCallback->OnProcessVideoDone(videoId, ipcFd);
352     } else {
353         DP_INFO_LOG("callback is null, videoId: %{public}s.", videoId.c_str());
354     }
355 }
356 
OnVideoError(const int32_t userId,const std::string & videoId,DpsError errorCode)357 void SessionCoordinator::OnVideoError(const int32_t userId, const std::string& videoId, DpsError errorCode)
358 {
359     DP_INFO_LOG("userId: %{public}d, map size: %{public}d.",
360         userId, static_cast<int32_t>(remoteVideoCallbacksMap_.size()));
361     auto iter = remoteVideoCallbacksMap_.find(userId);
362     if (iter != remoteVideoCallbacksMap_.end()) {
363         auto spCallback = iter->second.promote();
364         DP_CHECK_ERROR_RETURN_LOG(spCallback == nullptr, "OnVideoError callback is nullptr.");
365         auto error = MapDpsErrorCode(errorCode);
366         DP_INFO_LOG("videoId: %{public}s, error: %{public}d", videoId.c_str(), error);
367         spCallback->OnError(videoId, error);
368     } else {
369         DP_INFO_LOG("callback is null, videoId: %{public}s, errorCode: %{public}d.",
370             videoId.c_str(), errorCode);
371     }
372 }
373 
OnVideoStateChanged(const int32_t userId,DpsStatus statusCode)374 void SessionCoordinator::OnVideoStateChanged(const int32_t userId, DpsStatus statusCode)
375 {
376     DP_DEBUG_LOG("entered.");
377 }
378 
ProcessVideoResults(sptr<IDeferredVideoProcessingSessionCallback> callback)379 void SessionCoordinator::ProcessVideoResults(sptr<IDeferredVideoProcessingSessionCallback> callback)
380 {
381     DP_DEBUG_LOG("entered.");
382     while (!pendingRequestResults_.empty()) {
383         auto result = pendingRequestResults_.front();
384         if (result.callbackType == CallbackType::ON_PROCESS_DONE) {
385             callback->OnProcessVideoDone(result.requestId, result.ipcFd);
386         }
387         if (result.callbackType == CallbackType::ON_ERROR) {
388             callback->OnError(result.requestId, MapDpsErrorCode(result.errorCode));
389         }
390         if (result.callbackType == CallbackType::ON_STATE_CHANGED) {
391             callback->OnStateChanged(MapDpsStatus(result.statusCode));
392         }
393         pendingRequestResults_.pop_back();
394     }
395 }
396 } // namespace DeferredProcessing
397 } // namespace CameraStandard
398 } // namespace OHOS