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