1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #define MLOG_TAG "MediaAssetManagerImpl"
17
18 #include "media_asset_manager_impl.h"
19
20 #include <safe_map.h>
21 #include <securec.h>
22 #include <sys/sendfile.h>
23 #include <sys/stat.h>
24 #include <uuid.h>
25
26 #include "directory_ex.h"
27 #include "file_uri.h"
28 #include "iservice_registry.h"
29 #include "media_file_uri.h"
30 #include "media_file_utils.h"
31 #include "media_log.h"
32 #include "medialibrary_errno.h"
33 #include "medialibrary_tracer.h"
34 #include "file_asset.h"
35 #include "oh_media_asset.h"
36 #include "oh_moving_photo.h"
37 #include "moving_photo.h"
38 #include "image_source_native.h"
39 #include "media_userfile_client.h"
40 #include "userfilemgr_uri.h"
41
42 #include "medialibrary_business_code.h"
43 #include "user_inner_ipc_client.h"
44 #include "query_photo_vo.h"
45
46 namespace OHOS {
47 namespace Media {
48 namespace {
49 constexpr int STORAGE_MANAGER_MANAGER_ID = 5003;
50 } // namespace
51
52 using Uri = OHOS::Uri;
53
54 static const std::string MEDIA_ASSET_MANAGER_CLASS = "MediaAssetManagerImpl";
55 const std::string API_VERSION = "api_version";
56 static std::mutex multiStagesCaptureLock;
57
58 const int32_t LOW_QUALITY_IMAGE = 1;
59
60 const uint32_t MAX_URI_SIZE = 384;
61 const std::string ERROR_REQUEST_ID = "00000000-0000-0000-0000-000000000000";
62
63 static const std::string URI_TYPE = "uriType";
64 static const std::string TYPE_PHOTOS = "1";
65
66 static std::map<std::string, std::shared_ptr<MultiStagesTaskObserver>> multiStagesObserverMap;
67 static std::map<std::string, std::map<std::string, AssetHandler*>> inProcessUriMap;
68 static SafeMap<std::string, AssetHandler*> inProcessFastRequests;
69
70 static std::shared_ptr<DataShare::DataShareHelper> sDataShareHelper_ = nullptr;
71
72 MediaLibraryManager* MediaAssetManagerImpl::mediaLibraryManager_ = nullptr;
73
74 std::mutex MediaAssetManagerImpl::mutex_;
75
CreateMediaAssetManager()76 std::shared_ptr<MediaAssetManager> MediaAssetManagerFactory::CreateMediaAssetManager()
77 {
78 std::shared_ptr<MediaAssetManager> impl = std::make_shared<MediaAssetManagerImpl>();
79 CHECK_AND_PRINT_LOG(impl != nullptr, "Failed to create MediaAssetManagerImpl instance.");
80
81 return impl;
82 }
83
MediaAssetManagerImpl()84 MediaAssetManagerImpl::MediaAssetManagerImpl()
85 {
86 MediaAssetManagerImpl::mediaLibraryManager_ = MediaLibraryManager::GetMediaLibraryManager();
87 CreateDataHelper(STORAGE_MANAGER_MANAGER_ID);
88 }
89
~MediaAssetManagerImpl()90 MediaAssetManagerImpl::~MediaAssetManagerImpl()
91 {
92 }
93
DeleteInProcessMapRecord(const std::string & requestUri,const std::string & requestId)94 static void DeleteInProcessMapRecord(const std::string &requestUri, const std::string &requestId)
95 {
96 MEDIA_INFO_LOG("DeleteInProcessMapRecord lock multiStagesCaptureLock");
97 std::lock_guard<std::mutex> lock(multiStagesCaptureLock);
98 auto uriLocal = MediaFileUtils::GetUriWithoutDisplayname(requestUri);
99 if (inProcessUriMap.find(uriLocal) == inProcessUriMap.end()) {
100 return;
101 }
102
103 std::map<std::string, AssetHandler*> assetHandlers = inProcessUriMap[uriLocal];
104 if (assetHandlers.find(requestId) == assetHandlers.end()) {
105 return;
106 }
107
108 assetHandlers.erase(requestId);
109 if (!assetHandlers.empty()) {
110 inProcessUriMap[uriLocal] = assetHandlers;
111 return;
112 }
113
114 inProcessUriMap.erase(uriLocal);
115
116 if (multiStagesObserverMap.find(uriLocal) != multiStagesObserverMap.end()) {
117 sDataShareHelper_->UnregisterObserverExt(Uri(uriLocal),
118 static_cast<std::shared_ptr<DataShare::DataShareObserver>>(multiStagesObserverMap[uriLocal]));
119 }
120 multiStagesObserverMap.erase(uriLocal);
121 MEDIA_INFO_LOG("DeleteInProcessMapRecord unlock multiStagesCaptureLock");
122 }
123
CreateAssetHandler(const std::string & photoId,const std::string & requestId,const std::string & uri,const std::string & destUri,const MediaAssetDataHandlerPtr & handler)124 static AssetHandler* CreateAssetHandler(const std::string &photoId, const std::string &requestId,
125 const std::string &uri, const std::string &destUri, const MediaAssetDataHandlerPtr &handler)
126 {
127 AssetHandler *assetHandler = new AssetHandler(photoId, requestId, uri, destUri, handler);
128 MEDIA_DEBUG_LOG("[AssetHandler create] photoId: %{public}s, requestId: %{public}s, uri: %{public}s",
129 photoId.c_str(), requestId.c_str(), uri.c_str());
130 return assetHandler;
131 }
132
DeleteAssetHandlerSafe(AssetHandler * handler)133 static void DeleteAssetHandlerSafe(AssetHandler *handler)
134 {
135 if (handler != nullptr) {
136 delete handler;
137 handler = nullptr;
138 }
139 }
140
IsInProcessInMapRecord(const std::string & requestId,AssetHandler * & handler)141 static int32_t IsInProcessInMapRecord(const std::string &requestId, AssetHandler* &handler)
142 {
143 MEDIA_INFO_LOG("IsInProcessInMapRecord lock multiStagesCaptureLock");
144 std::lock_guard<std::mutex> lock(multiStagesCaptureLock);
145 for (auto record : inProcessUriMap) {
146 if (record.second.find(requestId) != record.second.end()) {
147 handler = record.second[requestId];
148 MEDIA_INFO_LOG("IsInProcessInMapRecord unlock multiStagesCaptureLock");
149 return true;
150 }
151 }
152 MEDIA_INFO_LOG("IsInProcessInMapRecord unlock multiStagesCaptureLock");
153 return false;
154 }
155
IsFastRequestCanceled(const std::string & requestId,std::string & photoId)156 static bool IsFastRequestCanceled(const std::string &requestId, std::string &photoId)
157 {
158 AssetHandler *assetHandler = nullptr;
159 if (!inProcessFastRequests.Find(requestId, assetHandler)) {
160 MEDIA_ERR_LOG("requestId(%{public}s) not in progress.", requestId.c_str());
161 return false;
162 }
163
164 if (assetHandler == nullptr) {
165 MEDIA_ERR_LOG("assetHandler is nullptr.");
166 return false;
167 }
168 photoId = assetHandler->photoId;
169 inProcessFastRequests.Erase(requestId);
170 return true;
171 }
172
IsMapRecordCanceled(const std::string & requestId,std::string & photoId)173 static bool IsMapRecordCanceled(const std::string &requestId, std::string &photoId)
174 {
175 AssetHandler *assetHandler = nullptr;
176 if (!IsInProcessInMapRecord(requestId, assetHandler)) {
177 MEDIA_ERR_LOG("requestId(%{public}s) not in progress.", requestId.c_str());
178 return false;
179 }
180
181 if (assetHandler == nullptr) {
182 MEDIA_ERR_LOG("assetHandler is nullptr.");
183 return false;
184 }
185 photoId = assetHandler->photoId;
186 DeleteInProcessMapRecord(assetHandler->requestUri, assetHandler->requestId);
187 DeleteAssetHandlerSafe(assetHandler);
188 return true;
189 }
190
DeleteDataHandler(NativeNotifyMode notifyMode,const std::string & requestUri,const std::string & requestId)191 static void DeleteDataHandler(NativeNotifyMode notifyMode, const std::string &requestUri, const std::string &requestId)
192 {
193 MEDIA_INFO_LOG("Rmv %{public}d, %{public}s, %{public}s", notifyMode,
194 MediaFileUtils::DesensitizeUri(requestUri).c_str(), requestId.c_str());
195 if (notifyMode == NativeNotifyMode::WAIT_FOR_HIGH_QUALITY) {
196 DeleteInProcessMapRecord(requestUri, requestId);
197 }
198 inProcessFastRequests.Erase(requestId);
199 }
200
InsertInProcessMapRecord(const std::string & requestUri,const std::string & requestId,AssetHandler * handler)201 static void InsertInProcessMapRecord(const std::string &requestUri, const std::string &requestId,
202 AssetHandler *handler)
203 {
204 MEDIA_INFO_LOG("InsertInProcessMapRecord lock multiStagesCaptureLock");
205 std::lock_guard<std::mutex> lock(multiStagesCaptureLock);
206 std::map<std::string, AssetHandler*> assetHandler;
207 auto uriLocal = MediaFileUtils::GetUriWithoutDisplayname(requestUri);
208 if (inProcessUriMap.find(uriLocal) != inProcessUriMap.end()) {
209 assetHandler = inProcessUriMap[uriLocal];
210 assetHandler[requestId] = handler;
211 inProcessUriMap[uriLocal] = assetHandler;
212 } else {
213 assetHandler[requestId] = handler;
214 inProcessUriMap[uriLocal] = assetHandler;
215 }
216 MEDIA_INFO_LOG("InsertInProcessMapRecord unlock multiStagesCaptureLock");
217 }
218
GenerateRequestId()219 static std::string GenerateRequestId()
220 {
221 uuid_t uuid;
222 uuid_generate(uuid);
223 char str[UUID_STR_LENGTH] = {};
224 uuid_unparse(uuid, str);
225 return str;
226 }
227
InsertDataHandler(NativeNotifyMode notifyMode,const unique_ptr<RequestSourceAsyncContext> & asyncContext)228 static AssetHandler* InsertDataHandler(NativeNotifyMode notifyMode,
229 const unique_ptr<RequestSourceAsyncContext> &asyncContext)
230 {
231 std::shared_ptr<CapiMediaAssetDataHandler> mediaAssetDataHandler;
232 if (asyncContext->returnDataType == ReturnDataType::TYPE_IMAGE_SOURCE) {
233 mediaAssetDataHandler = make_shared<CapiMediaAssetDataHandler>(
234 asyncContext->onRequestImageDataPreparedHandler, asyncContext->returnDataType, asyncContext->requestUri,
235 asyncContext->destUri, asyncContext->requestOptions.sourceMode);
236 mediaAssetDataHandler->SetPhotoQuality(static_cast<int32_t>(asyncContext->photoQuality));
237 } else if (asyncContext->returnDataType == ReturnDataType::TYPE_MOVING_PHOTO) {
238 mediaAssetDataHandler = make_shared<CapiMediaAssetDataHandler>(
239 asyncContext->onRequestMovingPhotoDataPreparedHandler, asyncContext->returnDataType,
240 asyncContext->requestUri, asyncContext->destUri, asyncContext->requestOptions.sourceMode);
241 mediaAssetDataHandler->SetPhotoQuality(static_cast<int32_t>(asyncContext->photoQuality));
242 } else {
243 mediaAssetDataHandler = make_shared<CapiMediaAssetDataHandler>(
244 asyncContext->onDataPreparedHandler, asyncContext->returnDataType, asyncContext->requestUri,
245 asyncContext->destUri, asyncContext->requestOptions.sourceMode);
246 }
247
248 mediaAssetDataHandler->SetNotifyMode(notifyMode);
249 AssetHandler *assetHandler = CreateAssetHandler(asyncContext->photoId, asyncContext->requestId,
250 asyncContext->requestUri, asyncContext->destUri, mediaAssetDataHandler);
251 MEDIA_INFO_LOG("Add %{public}d, %{private}s, %{private}s", notifyMode,
252 MediaFileUtils::DesensitizeUri(asyncContext->requestUri).c_str(), asyncContext->requestId.c_str());
253
254 switch (notifyMode) {
255 case NativeNotifyMode::FAST_NOTIFY: {
256 inProcessFastRequests.EnsureInsert(asyncContext->requestId, assetHandler);
257 break;
258 }
259 case NativeNotifyMode::WAIT_FOR_HIGH_QUALITY: {
260 InsertInProcessMapRecord(asyncContext->requestUri, asyncContext->requestId, assetHandler);
261 break;
262 }
263 default:
264 break;
265 }
266
267 return assetHandler;
268 }
269
QueryPhotoStatus(int32_t fileId,std::string & photoId)270 MultiStagesCapturePhotoStatus MediaAssetManagerImpl::QueryPhotoStatus(int32_t fileId, std::string &photoId)
271 {
272 photoId = "";
273 if (sDataShareHelper_ == nullptr) {
274 MEDIA_ERR_LOG("Get sDataShareHelper_ failed");
275 return MultiStagesCapturePhotoStatus::QUERY_INNER_FAIL;
276 }
277
278 QueryPhotoReqBody reqBody;
279 QueryPhotoRespBody respBody;
280 reqBody.fileId = std::to_string(fileId);
281 std::unordered_map<std::string, std::string> headerMap {
282 {MediaColumn::MEDIA_ID, reqBody.fileId }, {URI_TYPE, TYPE_PHOTOS}
283 };
284 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_QUERY_PHOTO_STATUS);
285 int errCode = IPC::UserInnerIPCClient().SetHeader(headerMap)
286 .SetDataShareHelper(sDataShareHelper_).Call(businessCode, reqBody, respBody);
287 if (errCode < 0) {
288 MEDIA_ERR_LOG("UserInnerIPCClient Call errCode:%{public}d", errCode);
289 return MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
290 }
291
292 photoId = respBody.photoId;
293 MEDIA_ERR_LOG("Query photo status quality: %{public}d", respBody.photoQuality);
294 if (respBody.photoQuality == LOW_QUALITY_IMAGE) {
295 return MultiStagesCapturePhotoStatus::LOW_QUALITY_STATUS;
296 }
297 return MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
298 }
299
NotifyImageDataPrepared(AssetHandler * assetHandler)300 bool MediaAssetManagerImpl::NotifyImageDataPrepared(AssetHandler *assetHandler)
301 {
302 CHECK_AND_RETURN_RET_LOG(assetHandler != nullptr, false, "assetHandler is nullptr");
303
304 auto dataHandler = assetHandler->dataHandler;
305 if (dataHandler == nullptr) {
306 MEDIA_ERR_LOG("Data handler is nullptr");
307 return false;
308 }
309
310 NativeNotifyMode notifyMode = dataHandler->GetNotifyMode();
311 if (notifyMode == NativeNotifyMode::FAST_NOTIFY) {
312 AssetHandler *tmp;
313 if (!inProcessFastRequests.Find(assetHandler->requestId, tmp)) {
314 MEDIA_ERR_LOG("The request has been canceled");
315 return false;
316 }
317 }
318
319 int32_t writeResult = E_OK;
320 if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_TARGET_FILE) {
321 writeResult = MediaAssetManagerImpl::WriteFileToPath(dataHandler->GetRequestUri(), dataHandler->GetDestUri(),
322 dataHandler->GetSourceMode() == NativeSourceMode::ORIGINAL_MODE);
323 Native_RequestId requestId;
324 strncpy_s(requestId.requestId, UUID_STR_LENGTH, assetHandler->requestId.c_str(), UUID_STR_LENGTH);
325 if (dataHandler->onDataPreparedHandler_ != nullptr) {
326 dataHandler->onDataPreparedHandler_(writeResult, requestId);
327 }
328 } else if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_IMAGE_SOURCE) {
329 MediaLibrary_RequestId requestId;
330 strncpy_s(requestId.requestId, UUID_STR_LENGTH, assetHandler->requestId.c_str(), UUID_STR_LENGTH);
331 if (dataHandler->onRequestImageDataPreparedHandler_ != nullptr) {
332 int32_t photoQuality = static_cast<int32_t>(MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS);
333 MediaLibrary_MediaQuality quality = (dataHandler->GetPhotoQuality() == photoQuality)
334 ? MEDIA_LIBRARY_QUALITY_FULL
335 : MEDIA_LIBRARY_QUALITY_FAST;
336 auto imageSource = CreateImageSource(assetHandler->requestId, dataHandler->GetRequestUri());
337 auto status = imageSource != nullptr ? MEDIA_LIBRARY_OK : MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR;
338 dataHandler->onRequestImageDataPreparedHandler_(status, requestId, quality,
339 MEDIA_LIBRARY_COMPRESSED, imageSource);
340 }
341 } else if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_MOVING_PHOTO) {
342 MediaLibrary_RequestId requestId;
343 strncpy_s(requestId.requestId, UUID_STR_LENGTH, assetHandler->requestId.c_str(), UUID_STR_LENGTH);
344 if (dataHandler->onRequestMovingPhotoDataPreparedHandler_ != nullptr) {
345 int32_t photoQuality = static_cast<int32_t>(MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS);
346 MediaLibrary_MediaQuality quality = (dataHandler->GetPhotoQuality() == photoQuality)
347 ? MEDIA_LIBRARY_QUALITY_FULL
348 : MEDIA_LIBRARY_QUALITY_FAST;
349 auto movingPhotoImpl = MovingPhotoFactory::CreateMovingPhoto(assetHandler->requestUri);
350 auto movingPhoto = new OH_MovingPhoto(movingPhotoImpl);
351 auto status = movingPhoto != nullptr ? MEDIA_LIBRARY_OK : MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR;
352 dataHandler->onRequestMovingPhotoDataPreparedHandler_(status, requestId, quality,
353 MEDIA_LIBRARY_COMPRESSED, movingPhoto);
354 }
355 } else {
356 MEDIA_ERR_LOG("Return mode type invalid %{public}d", dataHandler->GetReturnDataType());
357 return false;
358 }
359 DeleteDataHandler(notifyMode, assetHandler->requestUri, assetHandler->requestId);
360 MEDIA_DEBUG_LOG("Delete assetHandler");
361 return true;
362 }
363
CreateDataHelper(int32_t systemAbilityId)364 void MediaAssetManagerImpl::CreateDataHelper(int32_t systemAbilityId)
365 {
366 auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
367 if (saManager == nullptr) {
368 MEDIA_ERR_LOG("Get system ability mgr failed.");
369 return;
370 }
371 auto remoteObj = saManager->GetSystemAbility(systemAbilityId);
372 if (remoteObj == nullptr) {
373 MEDIA_ERR_LOG("GetSystemAbility Service Failed.");
374 return;
375 }
376 if (sDataShareHelper_ == nullptr) {
377 const sptr<IRemoteObject> &token = remoteObj;
378 sDataShareHelper_ = DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
379 if (sDataShareHelper_ == nullptr) {
380 MEDIA_ERR_LOG("Create DataShareHelper failed.");
381 return;
382 }
383 }
384 MediaAssetManagerImpl::mediaLibraryManager_->InitMediaLibraryManager(remoteObj);
385 UserFileClient::Init(remoteObj);
386 MEDIA_INFO_LOG("InitMediaLibraryManager success!");
387 }
388
NativeRequestImage(const char * photoUri,const NativeRequestOptions & requestOptions,const char * destUri,const NativeOnDataPrepared & callback)389 std::string MediaAssetManagerImpl::NativeRequestImage(const char* photoUri,
390 const NativeRequestOptions &requestOptions, const char* destUri, const NativeOnDataPrepared &callback)
391 {
392 if (photoUri == nullptr || destUri == nullptr || callback == nullptr) {
393 MEDIA_ERR_LOG("Request image input params are invalid.");
394 return ERROR_REQUEST_ID;
395 }
396
397 MediaLibraryTracer tracer;
398 tracer.Start("NativeRequestImage");
399
400 std::unique_ptr<RequestSourceAsyncContext> asyncContext = std::make_unique<RequestSourceAsyncContext>();
401 asyncContext->destUri = std::string(destUri);
402 asyncContext->requestUri = std::string(photoUri);
403 asyncContext->displayName = MediaFileUtils::GetFileName(asyncContext->requestUri);
404 asyncContext->fileId = std::stoi(MediaFileUtils::GetIdFromUri(asyncContext->requestUri));
405 asyncContext->requestOptions.deliveryMode = requestOptions.deliveryMode;
406 asyncContext->requestOptions.sourceMode = NativeSourceMode::EDITED_MODE;
407 asyncContext->returnDataType = ReturnDataType::TYPE_TARGET_FILE;
408 asyncContext->onDataPreparedHandler = callback;
409
410 if (asyncContext->requestUri.length() > MAX_URI_SIZE || asyncContext->destUri.length() > MAX_URI_SIZE) {
411 MEDIA_ERR_LOG("Request image uri lens out of limit requestUri lens: %{public}zu, destUri lens: %{public}zu",
412 asyncContext->requestUri.length(), asyncContext->destUri.length());
413 return ERROR_REQUEST_ID;
414 }
415 if (MediaFileUtils::GetMediaType(asyncContext->displayName) != MEDIA_TYPE_IMAGE ||
416 MediaFileUtils::GetMediaType(MediaFileUtils::GetFileName(asyncContext->destUri)) != MEDIA_TYPE_IMAGE) {
417 MEDIA_ERR_LOG("Request image file type invalid");
418 return ERROR_REQUEST_ID;
419 }
420 bool isSuccess = false;
421 asyncContext->requestId = GenerateRequestId();
422 isSuccess = OnHandleRequestImage(asyncContext);
423 if (isSuccess) {
424 MEDIA_INFO_LOG("Request image success return requestId: %{public}s", asyncContext->requestId.c_str());
425 return asyncContext->requestId;
426 } else {
427 return ERROR_REQUEST_ID;
428 }
429 }
430
NativeRequestVideo(const char * videoUri,const NativeRequestOptions & requestOptions,const char * destUri,const NativeOnDataPrepared & callback)431 std::string MediaAssetManagerImpl::NativeRequestVideo(const char* videoUri,
432 const NativeRequestOptions &requestOptions, const char* destUri, const NativeOnDataPrepared &callback)
433 {
434 if (videoUri == nullptr || destUri == nullptr || callback == nullptr) {
435 MEDIA_ERR_LOG("Request video input params are invalid.");
436 return ERROR_REQUEST_ID;
437 }
438 MediaLibraryTracer tracer;
439 tracer.Start("NativeRequestVideo");
440
441 std::unique_ptr<RequestSourceAsyncContext> asyncContext = std::make_unique<RequestSourceAsyncContext>();
442 asyncContext->destUri = std::string(destUri);
443 asyncContext->requestUri = std::string(videoUri);
444 asyncContext->displayName = MediaFileUtils::GetFileName(asyncContext->requestUri);
445 asyncContext->fileId = std::stoi(MediaFileUtils::GetIdFromUri(asyncContext->requestUri));
446 asyncContext->requestOptions.deliveryMode = requestOptions.deliveryMode;
447 asyncContext->requestOptions.sourceMode = NativeSourceMode::EDITED_MODE;
448 asyncContext->returnDataType = ReturnDataType::TYPE_TARGET_FILE;
449 asyncContext->onDataPreparedHandler = callback;
450
451 if (asyncContext->requestUri.length() > MAX_URI_SIZE || asyncContext->destUri.length() > MAX_URI_SIZE) {
452 MEDIA_ERR_LOG("Request video uri lens out of limit requestUri lens: %{public}zu, destUri lens: %{public}zu",
453 asyncContext->requestUri.length(), asyncContext->destUri.length());
454 return ERROR_REQUEST_ID;
455 }
456 if (MediaFileUtils::GetMediaType(asyncContext->displayName) != MEDIA_TYPE_VIDEO ||
457 MediaFileUtils::GetMediaType(MediaFileUtils::GetFileName(asyncContext->destUri)) != MEDIA_TYPE_VIDEO) {
458 MEDIA_ERR_LOG("Request video file type invalid");
459 return ERROR_REQUEST_ID;
460 }
461 bool isSuccess = false;
462 asyncContext->requestId = GenerateRequestId();
463 isSuccess = OnHandleRequestVideo(asyncContext);
464 if (isSuccess) {
465 MEDIA_ERR_LOG("Request video success return requestId: %{public}s", asyncContext->requestId.c_str());
466 return asyncContext->requestId;
467 } else {
468 return ERROR_REQUEST_ID;
469 }
470 }
471
UriAppendKeyValue(string & uri,const string & key,const string & value)472 void UriAppendKeyValue(string &uri, const string &key, const string &value)
473 {
474 string uriKey = key + '=';
475 if (uri.find(uriKey) != string::npos) {
476 return;
477 }
478
479 char queryMark = (uri.find('?') == string::npos) ? '?' : '&';
480 string append = queryMark + key + '=' + value;
481
482 size_t posJ = uri.find('#');
483 if (posJ == string::npos) {
484 uri += append;
485 } else {
486 uri.insert(posJ, append);
487 }
488 }
489
NativeCancelRequest(const std::string & requestId)490 bool MediaAssetManagerImpl::NativeCancelRequest(const std::string &requestId)
491 {
492 if (requestId.empty()) {
493 MEDIA_ERR_LOG("NativeCancel request id is empty.");
494 return false;
495 }
496 if (sDataShareHelper_ == nullptr) {
497 CreateDataHelper(STORAGE_MANAGER_MANAGER_ID);
498 CHECK_AND_RETURN_RET_LOG(sDataShareHelper_ == nullptr, MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR,
499 "sDataShareHelper_ is null");
500 }
501
502 std::string photoId = "";
503 bool hasFastRequestInProcess = IsFastRequestCanceled(requestId, photoId);
504 bool hasMapRecordInProcess = IsMapRecordCanceled(requestId, photoId);
505 if (hasFastRequestInProcess || hasMapRecordInProcess) {
506 std::string uriStr = PAH_CANCEL_PROCESS_IMAGE;
507 UriAppendKeyValue(uriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
508 Uri updateAssetUri(uriStr);
509 DataShare::DataSharePredicates predicates;
510 DataShare::DatashareBusinessError errCode;
511 std::vector<std::string> columns { photoId };
512 sDataShareHelper_->Query(updateAssetUri, predicates, columns, &errCode);
513 } else {
514 MEDIA_ERR_LOG("NativeCancel requestId(%{public}s) not in progress.", requestId.c_str());
515 return false;
516 }
517 return true;
518 }
519
NativeRequestImageSource(OH_MediaAsset * mediaAsset,NativeRequestOptions requestOptions,MediaLibrary_RequestId * requestId,OH_MediaLibrary_OnImageDataPrepared callback)520 MediaLibrary_ErrorCode MediaAssetManagerImpl::NativeRequestImageSource(OH_MediaAsset* mediaAsset,
521 NativeRequestOptions requestOptions, MediaLibrary_RequestId* requestId,
522 OH_MediaLibrary_OnImageDataPrepared callback)
523 {
524 MEDIA_INFO_LOG("MediaAssetManagerImpl::NativeRequestImageSource Called");
525 CHECK_AND_RETURN_RET_LOG(mediaAsset != nullptr && mediaAsset->mediaAsset_ != nullptr,
526 MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR, "mediaAsset or mediaAsset_ is null");
527 std::shared_ptr<FileAsset> fileAsset_ = mediaAsset->mediaAsset_->GetFileAssetInstance();
528 MediaLibraryTracer tracer;
529 tracer.Start("NativeRequestImageSource");
530
531 std::unique_ptr<RequestSourceAsyncContext> asyncContext = std::make_unique<RequestSourceAsyncContext>();
532 asyncContext->requestUri = fileAsset_->GetUri();
533 asyncContext->displayName = fileAsset_->GetDisplayName();
534 asyncContext->fileId = fileAsset_->GetId();
535 asyncContext->requestOptions.deliveryMode = requestOptions.deliveryMode;
536 asyncContext->requestOptions.sourceMode = NativeSourceMode::EDITED_MODE;
537 asyncContext->returnDataType = ReturnDataType::TYPE_IMAGE_SOURCE;
538 asyncContext->needsExtraInfo = true;
539 asyncContext->onRequestImageDataPreparedHandler = callback;
540
541 if (sDataShareHelper_ == nullptr) {
542 CreateDataHelper(STORAGE_MANAGER_MANAGER_ID);
543 CHECK_AND_RETURN_RET_LOG(sDataShareHelper_ == nullptr, MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR,
544 "sDataShareHelper_ is null");
545 }
546
547 if (asyncContext->requestUri.length() > MAX_URI_SIZE) {
548 MEDIA_ERR_LOG("Request image uri lens out of limit requestUri lens: %{public}zu",
549 asyncContext->requestUri.length());
550 strncpy_s(requestId->requestId, UUID_STR_LENGTH, (ERROR_REQUEST_ID.c_str()), UUID_STR_LENGTH);
551 return MEDIA_LIBRARY_PARAMETER_ERROR;
552 }
553
554 if (MediaFileUtils::GetMediaType(asyncContext->displayName) != MEDIA_TYPE_IMAGE) {
555 MEDIA_ERR_LOG("Request image file type invalid");
556 strncpy_s(requestId->requestId, UUID_STR_LENGTH, (ERROR_REQUEST_ID.c_str()), UUID_STR_LENGTH);
557 return MEDIA_LIBRARY_PARAMETER_ERROR;
558 }
559
560 bool isSuccess = false;
561 asyncContext->requestId = GenerateRequestId();
562 isSuccess = OnHandleRequestImage(asyncContext);
563 if (isSuccess) {
564 strncpy_s(requestId->requestId, UUID_STR_LENGTH, (asyncContext->requestId.c_str()), UUID_STR_LENGTH);
565 return MEDIA_LIBRARY_OK;
566 } else {
567 strncpy_s(requestId->requestId, UUID_STR_LENGTH, (ERROR_REQUEST_ID.c_str()), UUID_STR_LENGTH);
568 return MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED;
569 }
570 }
571
NativeRequestMovingPhoto(OH_MediaAsset * mediaAsset,NativeRequestOptions requestOptions,MediaLibrary_RequestId * requestId,OH_MediaLibrary_OnMovingPhotoDataPrepared callback)572 MediaLibrary_ErrorCode MediaAssetManagerImpl::NativeRequestMovingPhoto(OH_MediaAsset* mediaAsset,
573 NativeRequestOptions requestOptions, MediaLibrary_RequestId* requestId,
574 OH_MediaLibrary_OnMovingPhotoDataPrepared callback)
575 {
576 CHECK_AND_RETURN_RET_LOG(mediaAsset != nullptr && mediaAsset->mediaAsset_ != nullptr,
577 MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR, "mediaAsset or mediaAsset_ is null");
578 std::shared_ptr<FileAsset> fileAsset_ = mediaAsset->mediaAsset_->GetFileAssetInstance();
579 MediaLibraryTracer tracer;
580 tracer.Start("NativeRequestMovingPhoto");
581
582 std::unique_ptr<RequestSourceAsyncContext> asyncContext = std::make_unique<RequestSourceAsyncContext>();
583 asyncContext->requestUri = fileAsset_->GetUri();
584 asyncContext->fileId = fileAsset_->GetId();
585 asyncContext->displayName = fileAsset_->GetDisplayName();
586 asyncContext->requestOptions.deliveryMode = requestOptions.deliveryMode;
587 asyncContext->requestOptions.sourceMode = NativeSourceMode::EDITED_MODE;
588 asyncContext->returnDataType = ReturnDataType::TYPE_MOVING_PHOTO;
589 asyncContext->onRequestMovingPhotoDataPreparedHandler = callback;
590
591 if (sDataShareHelper_ == nullptr) {
592 CreateDataHelper(STORAGE_MANAGER_MANAGER_ID);
593 CHECK_AND_RETURN_RET_LOG(sDataShareHelper_ == nullptr, MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR,
594 "sDataShareHelper_ is null");
595 }
596
597 if (asyncContext->requestUri.length() > MAX_URI_SIZE) {
598 MEDIA_ERR_LOG("Request image uri lens out of limit requestUri lens: %{public}zu",
599 asyncContext->requestUri.length());
600 strncpy_s(requestId->requestId, UUID_STR_LENGTH, (ERROR_REQUEST_ID.c_str()), UUID_STR_LENGTH);
601 return MEDIA_LIBRARY_PARAMETER_ERROR;
602 }
603
604 if (MediaFileUtils::GetMediaType(asyncContext->displayName) != MEDIA_TYPE_IMAGE) {
605 MEDIA_ERR_LOG("Request image file type invalid");
606 strncpy_s(requestId->requestId, UUID_STR_LENGTH, (ERROR_REQUEST_ID.c_str()), UUID_STR_LENGTH);
607 return MEDIA_LIBRARY_PARAMETER_ERROR;
608 }
609
610 bool isSuccess = false;
611 asyncContext->requestId = GenerateRequestId();
612 isSuccess = OnHandleRequestImage(asyncContext);
613 string uri = LOG_MOVING_PHOTO;
614 Uri logMovingPhotoUri(uri);
615 DataShare::DataShareValuesBucket valuesBucket;
616 string result;
617 valuesBucket.Put("package_name", asyncContext->callingPkgName);
618 valuesBucket.Put("adapted", asyncContext->returnDataType == ReturnDataType::TYPE_MOVING_PHOTO);
619 UserFileClient::InsertExt(logMovingPhotoUri, valuesBucket, result);
620 if (isSuccess) {
621 strncpy_s(requestId->requestId, UUID_STR_LENGTH, (asyncContext->requestId.c_str()), UUID_STR_LENGTH);
622 return MEDIA_LIBRARY_OK;
623 } else {
624 strncpy_s(requestId->requestId, UUID_STR_LENGTH, (ERROR_REQUEST_ID.c_str()), UUID_STR_LENGTH);
625 return MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED;
626 }
627 }
628
CreateImageSource(const std::string requestId,const std::string requestUri)629 OH_ImageSourceNative* MediaAssetManagerImpl::CreateImageSource(const std::string requestId,
630 const std::string requestUri)
631 {
632 MEDIA_INFO_LOG("Request image success requestId: %{public}s, uri: %{public}s",
633 requestId.c_str(), requestUri.c_str());
634
635 std::string tmpUri = requestUri;
636 MediaFileUtils::UriAppendKeyValue(tmpUri, MEDIA_OPERN_KEYWORD, SOURCE_REQUEST);
637 Uri uri(tmpUri);
638 int fd = UserFileClient::OpenFile(uri, "r");
639 CHECK_AND_RETURN_RET_LOG(fd >= 0, nullptr, "get image fd failed");
640
641 struct OH_ImageSourceNative *imageSource;
642 OH_ImageSourceNative_CreateFromFd(fd, &imageSource);
643 close(fd);
644 CHECK_AND_RETURN_RET_LOG(imageSource != nullptr, nullptr, "new OH_ImageSourceNative failed");
645
646 return imageSource;
647 }
648
OnHandleRequestImage(const std::unique_ptr<RequestSourceAsyncContext> & asyncContext)649 bool MediaAssetManagerImpl::OnHandleRequestImage(
650 const std::unique_ptr<RequestSourceAsyncContext> &asyncContext)
651 {
652 MultiStagesCapturePhotoStatus status = MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
653 bool result = false;
654 switch (asyncContext->requestOptions.deliveryMode) {
655 case NativeDeliveryMode::FAST_MODE:
656 if (asyncContext->needsExtraInfo) {
657 asyncContext->photoQuality = QueryPhotoStatus(asyncContext->fileId, asyncContext->photoId);
658 MEDIA_DEBUG_LOG("OnHandleRequestImage photoQuality: %{public}d", asyncContext->photoQuality);
659 }
660 result = NotifyDataPreparedWithoutRegister(asyncContext);
661 break;
662 case NativeDeliveryMode::HIGH_QUALITY_MODE:
663 status = QueryPhotoStatus(asyncContext->fileId, asyncContext->photoId);
664 asyncContext->photoQuality = status;
665 MEDIA_DEBUG_LOG("OnHandleRequestImage photoQuality: %{public}d", asyncContext->photoQuality);
666 if (status == MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS) {
667 result = NotifyDataPreparedWithoutRegister(asyncContext);
668 } else {
669 RegisterTaskObserver(asyncContext);
670 result = true;
671 }
672 break;
673 case NativeDeliveryMode::BALANCED_MODE:
674 status = QueryPhotoStatus(asyncContext->fileId, asyncContext->photoId);
675 asyncContext->photoQuality = status;
676 MEDIA_DEBUG_LOG("OnHandleRequestImage photoQuality: %{public}d", asyncContext->photoQuality);
677 result = NotifyDataPreparedWithoutRegister(asyncContext);
678 if (status == MultiStagesCapturePhotoStatus::LOW_QUALITY_STATUS) {
679 RegisterTaskObserver(asyncContext);
680 }
681 break;
682 default: {
683 MEDIA_ERR_LOG("Invalid delivery mode %{public}d", asyncContext->requestOptions.deliveryMode);
684 return result;
685 }
686 }
687 return result;
688 }
689
OnHandleRequestVideo(const std::unique_ptr<RequestSourceAsyncContext> & asyncContext)690 bool MediaAssetManagerImpl::OnHandleRequestVideo(
691 const std::unique_ptr<RequestSourceAsyncContext> &asyncContext)
692 {
693 bool result = false;
694 switch (asyncContext->requestOptions.deliveryMode) {
695 case NativeDeliveryMode::FAST_MODE:
696 result = NotifyDataPreparedWithoutRegister(asyncContext);
697 break;
698 case NativeDeliveryMode::HIGH_QUALITY_MODE:
699 result = NotifyDataPreparedWithoutRegister(asyncContext);
700 break;
701 case NativeDeliveryMode::BALANCED_MODE:
702 result = NotifyDataPreparedWithoutRegister(asyncContext);
703 break;
704 default: {
705 MEDIA_ERR_LOG("Invalid delivery mode %{public}d", asyncContext->requestOptions.deliveryMode);
706 return result;
707 }
708 }
709 return result;
710 }
711
NotifyDataPreparedWithoutRegister(const std::unique_ptr<RequestSourceAsyncContext> & asyncContext)712 bool MediaAssetManagerImpl::NotifyDataPreparedWithoutRegister(
713 const std::unique_ptr<RequestSourceAsyncContext> &asyncContext)
714 {
715 bool ret = false;
716 AssetHandler *assetHandler = InsertDataHandler(NativeNotifyMode::FAST_NOTIFY, asyncContext);
717 if (assetHandler == nullptr) {
718 MEDIA_ERR_LOG("assetHandler is nullptr");
719 return ret;
720 }
721
722 {
723 std::lock_guard<mutex> lock(MediaAssetManagerImpl::mutex_);
724 ret = NotifyImageDataPrepared(assetHandler);
725 DeleteAssetHandlerSafe(assetHandler);
726 }
727 return ret;
728 }
729
RegisterTaskObserver(const unique_ptr<RequestSourceAsyncContext> & asyncContext)730 void MediaAssetManagerImpl::RegisterTaskObserver(const unique_ptr<RequestSourceAsyncContext> &asyncContext)
731 {
732 auto dataObserver = std::make_shared<MultiStagesTaskObserver>(asyncContext->fileId);
733 auto uriLocal = MediaFileUtils::GetUriWithoutDisplayname(asyncContext->requestUri);
734 if (multiStagesObserverMap.find(uriLocal) == multiStagesObserverMap.end()) {
735 sDataShareHelper_->RegisterObserverExt(Uri(uriLocal),
736 static_cast<std::shared_ptr<DataShare::DataShareObserver>>(dataObserver), false);
737 multiStagesObserverMap.insert(std::make_pair(uriLocal, dataObserver));
738 }
739
740 InsertDataHandler(NativeNotifyMode::WAIT_FOR_HIGH_QUALITY, asyncContext);
741
742 ProcessImage(asyncContext->fileId, static_cast<int32_t>(asyncContext->requestOptions.deliveryMode));
743 }
744
ProcessImage(const int fileId,const int deliveryMode)745 void MediaAssetManagerImpl::ProcessImage(const int fileId, const int deliveryMode)
746 {
747 CHECK_AND_RETURN_LOG(sDataShareHelper_ != nullptr, "Get sDataShareHelper_ failed");
748 std::string uriStr = PAH_PROCESS_IMAGE;
749 MediaFileUtils::UriAppendKeyValue(uriStr, API_VERSION, std::to_string(MEDIA_API_VERSION_V10));
750 Uri uri(uriStr);
751 DataShare::DataSharePredicates predicates;
752 DataShare::DatashareBusinessError errCode;
753 std::vector<std::string> columns { std::to_string(fileId), std::to_string(deliveryMode) };
754 sDataShareHelper_->Query(uri, predicates, columns, &errCode);
755 MEDIA_INFO_LOG("MediaAssetManagerImpl::ProcessImage Called");
756 }
757
OnChange(const ChangeInfo & changeInfo)758 void MultiStagesTaskObserver::OnChange(const ChangeInfo &changeInfo)
759 {
760 if (changeInfo.changeType_ != static_cast<int32_t>(NotifyType::NOTIFY_UPDATE)) {
761 MEDIA_DEBUG_LOG("Ignore notify change, type: %{public}d", changeInfo.changeType_);
762 return;
763 }
764 std::string photoId = "";
765 if (MediaAssetManagerImpl::QueryPhotoStatus(fileId_, photoId) !=
766 MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS) {
767 MEDIA_ERR_LOG("Requested data not prepared");
768 return;
769 }
770
771 MEDIA_INFO_LOG("MultiStagesTaskObserver::OnChange Called");
772 for (auto &uri : changeInfo.uris_) {
773 string uriString = uri.ToString();
774 std::map<std::string, AssetHandler *> assetHandlers = GetAssetHandlers(uriString);
775 for (auto handler : assetHandlers) {
776 auto assetHandler = handler.second;
777 auto dataHandler = assetHandler->dataHandler;
778 if (dataHandler != nullptr) {
779 int32_t quality = static_cast<int32_t>(MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS);
780 dataHandler->SetPhotoQuality(quality);
781 }
782 {
783 std::lock_guard<mutex> lock(MediaAssetManagerImpl::mutex_);
784 MediaAssetManagerImpl::NotifyImageDataPrepared(assetHandler);
785 DeleteAssetHandlerSafe(assetHandler);
786 }
787 }
788 }
789 }
790
GetAssetHandlers(const std::string uriString)791 std::map<std::string, AssetHandler *> MultiStagesTaskObserver::GetAssetHandlers(const std::string uriString)
792 {
793 MEDIA_INFO_LOG("GetAssetHandlers lock multiStagesCaptureLock");
794 std::lock_guard<std::mutex> lock(multiStagesCaptureLock);
795 if (inProcessUriMap.find(uriString) == inProcessUriMap.end()) {
796 MEDIA_INFO_LOG("current uri does not in process, uri: %{public}s", uriString.c_str());
797 MEDIA_INFO_LOG("GetAssetHandlers unlock multiStagesCaptureLock");
798 return std::map<std::string, AssetHandler*>();
799 }
800 MEDIA_INFO_LOG("GetAssetHandlers unlock multiStagesCaptureLock");
801 return inProcessUriMap[uriString];
802 }
803
WriteFileToPath(const std::string & srcUri,const std::string & destUri,bool isSource)804 int32_t MediaAssetManagerImpl::WriteFileToPath(const std::string &srcUri, const std::string &destUri,
805 bool isSource)
806 {
807 if (srcUri.empty() || destUri.empty()) {
808 MEDIA_ERR_LOG("srcUri or destUri is empty");
809 return E_INVALID_URI;
810 }
811 std::string tmpSrcUri = srcUri;
812 if (isSource) {
813 MediaFileUtils::UriAppendKeyValue(tmpSrcUri, MEDIA_OPERN_KEYWORD, SOURCE_REQUEST);
814 }
815 int srcFd = MediaAssetManagerImpl::mediaLibraryManager_->OpenAsset(tmpSrcUri, MEDIA_FILEMODE_READONLY);
816 if (srcFd < 0) {
817 MEDIA_ERR_LOG("Get source %{public}s fd error: %{public}d", tmpSrcUri.c_str(), srcFd);
818 return srcFd;
819 }
820 struct stat statSrc;
821 if (fstat(srcFd, &statSrc) != E_SUCCESS) {
822 MediaAssetManagerImpl::mediaLibraryManager_->CloseAsset(tmpSrcUri, srcFd);
823 MEDIA_ERR_LOG("File get stat failed, %{public}d", errno);
824 return E_FILE_OPER_FAIL;
825 }
826 int destFd = GetFdFromSandBoxUri(destUri);
827 if (destFd < 0) {
828 MEDIA_ERR_LOG("Get destination %{public}s fd error: %{public}d", destUri.c_str(), destFd);
829 MediaAssetManagerImpl::mediaLibraryManager_->CloseAsset(tmpSrcUri, srcFd);
830 return destFd;
831 }
832 if (sendfile(destFd, srcFd, nullptr, statSrc.st_size) == -1) {
833 MediaAssetManagerImpl::mediaLibraryManager_->CloseAsset(tmpSrcUri, srcFd);
834 close(destFd);
835 MEDIA_ERR_LOG("Sendfile failed, %{public}d", errno);
836 return E_FILE_OPER_FAIL;
837 }
838 MediaAssetManagerImpl::mediaLibraryManager_->CloseAsset(tmpSrcUri, srcFd);
839 close(destFd);
840 return E_SUCCESS;
841 }
842
GetFdFromSandBoxUri(const std::string & sandBoxUri)843 int32_t MediaAssetManagerImpl::GetFdFromSandBoxUri(const std::string &sandBoxUri)
844 {
845 AppFileService::ModuleFileUri::FileUri destUri(sandBoxUri);
846 string destPath = destUri.GetRealPath();
847 if (!MediaFileUtils::IsFileExists(destPath) && !MediaFileUtils::CreateFile(destPath)) {
848 MEDIA_ERR_LOG("Create empty dest file in sandbox failed, path:%{private}s", destPath.c_str());
849 return E_FILE_OPER_FAIL;
850 }
851 string absDestPath;
852 if (!PathToRealPath(destPath, absDestPath)) {
853 MEDIA_ERR_LOG("PathToRealPath failed, path:%{private}s", destPath.c_str());
854 return E_FILE_OPER_FAIL;
855 }
856 return MediaFileUtils::OpenFile(absDestPath, MEDIA_FILEMODE_WRITETRUNCATE);
857 }
858 } // namespace Media
859 } // namespace OHOS