• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "media_asset_change_request_impl.h"
17 
18 #include <fcntl.h>
19 #include <sys/sendfile.h>
20 #include "securec.h"
21 
22 #include "oh_media_asset.h"
23 #include "media_log.h"
24 #include "medialibrary_errno.h"
25 #include "media_file_utils.h"
26 #include "media_column.h"
27 #include "file_uri.h"
28 #include "directory_ex.h"
29 #include "medialibrary_db_const.h"
30 #include "access_token.h"
31 #include "accesstoken_kit.h"
32 #include "ipc_skeleton.h"
33 #include "image_packer.h"
34 #include "permission_utils.h"
35 #include "media_userfile_client.h"
36 #include "userfilemgr_uri.h"
37 
38 using namespace std;
39 using namespace OHOS::Media;
40 using namespace OHOS::Security::AccessToken;
41 
42 atomic<uint32_t> MediaAssetChangeRequestImpl::cacheFileId_(0);
43 const string MOVING_PHOTO_VIDEO_EXTENSION = "mp4";
44 const string API_VERSION = "api_version";
45 
CreateMediaAssetChangeRequest(std::shared_ptr<MediaAsset> mediaAsset)46 std::shared_ptr<MediaAssetChangeRequest> MediaAssetChangeRequestFactory::CreateMediaAssetChangeRequest(
47     std::shared_ptr<MediaAsset> mediaAsset)
48 {
49     std::shared_ptr<MediaAssetChangeRequestImpl> impl = std::make_shared<MediaAssetChangeRequestImpl>(mediaAsset);
50     CHECK_AND_PRINT_LOG(impl != nullptr, "Failed to create MediaAssetChangeRequestImpl instance.");
51 
52     return impl;
53 }
54 
MediaAssetChangeRequestImpl(std::shared_ptr<MediaAsset> mediaAsset)55 MediaAssetChangeRequestImpl::MediaAssetChangeRequestImpl(std::shared_ptr<MediaAsset> mediaAsset)
56 {
57     mediaAsset_ = mediaAsset;
58     movingPhotoVideoDataBuffer_ = nullptr;
59     dataBuffer_ = nullptr;
60     movingPhotoVideoResourceMode_ = AddResourceMode::DEFAULT;
61     addResourceMode_ = AddResourceMode::DEFAULT;
62     movingPhotoVideoBufferSize_ = 0;
63     dataBufferSize_ = 0;
64 }
65 
~MediaAssetChangeRequestImpl()66 MediaAssetChangeRequestImpl::~MediaAssetChangeRequestImpl()
67 {
68     mediaAsset_ = nullptr;
69     if (movingPhotoVideoDataBuffer_ != nullptr) {
70         delete[] movingPhotoVideoDataBuffer_;
71         movingPhotoVideoDataBuffer_ = nullptr;
72     }
73 
74     if (dataBuffer_ != nullptr) {
75         delete[] dataBuffer_;
76         dataBuffer_ = nullptr;
77     }
78 
79     addResourceTypes_.clear();
80     assetChangeOperations_.clear();
81 }
82 
GetWriteCacheHandler(int32_t * fd)83 MediaLibrary_ErrorCode MediaAssetChangeRequestImpl::GetWriteCacheHandler(int32_t* fd)
84 {
85     unique_lock<mutex> ulock(mutex_);
86     auto fileAsset = mediaAsset_->GetFileAssetInstance();
87     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR, "fileAsset get failed!");
88     CHECK_AND_RETURN_RET_LOG(!IsMovingPhoto(), MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED, "cann't be moving photo!");
89     CHECK_AND_RETURN_RET_LOG(CheckWriteOperation(MediaLibrary_ResourceType::MEDIA_LIBRARY_VIDEO_RESOURCE),
90         MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED, "Not supported!");
91 
92     int32_t ret = OpenWriteCacheHandler();
93     CHECK_AND_RETURN_RET_LOG(ret >= 0,
94         MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED, "Failed to open write cache handler,ret: %{public}d", ret);
95 
96     *fd = ret;
97     RecordChangeOperation(AssetChangeOperation::GET_WRITE_CACHE_HANDLER);
98     return MEDIA_LIBRARY_OK;
99 }
100 
SaveCameraPhoto(MediaLibrary_ImageFileType imageFileType)101 MediaLibrary_ErrorCode MediaAssetChangeRequestImpl::SaveCameraPhoto(MediaLibrary_ImageFileType imageFileType)
102 {
103     CHECK_AND_RETURN_RET_LOG(imageFileType == MEDIA_LIBRARY_IMAGE_JPEG, MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED,
104         "imageFileType not support");
105 
106     unique_lock<mutex> ulock(mutex_);
107     auto fileAsset = mediaAsset_->GetFileAssetInstance();
108     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED, "fileAsset get failed!");
109 
110     RecordChangeOperation(AssetChangeOperation::SAVE_CAMERA_PHOTO);
111     return MEDIA_LIBRARY_OK;
112 }
113 
DiscardCameraPhoto()114 MediaLibrary_ErrorCode MediaAssetChangeRequestImpl::DiscardCameraPhoto()
115 {
116     unique_lock<mutex> ulock(mutex_);
117     auto fileAsset = mediaAsset_->GetFileAssetInstance();
118     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED, "fileAsset get failed!");
119 
120     RecordChangeOperation(AssetChangeOperation::DISCARD_CAMERA_PHOTO);
121     return MEDIA_LIBRARY_OK;
122 }
123 
AddResourceWithUri(MediaLibrary_ResourceType resourceType,char * fileUri)124 MediaLibrary_ErrorCode MediaAssetChangeRequestImpl::AddResourceWithUri(MediaLibrary_ResourceType resourceType,
125     char* fileUri)
126 {
127     unique_lock<mutex> ulock(mutex_);
128     CHECK_AND_RETURN_RET_LOG(CheckWriteOperation(resourceType), MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED,
129         "operation not support");
130 
131     string realPath;
132     OHOS::AppFileService::ModuleFileUri::FileUri fileUriStr(fileUri);
133     string path = fileUriStr.GetRealPath();
134     bool result = OHOS::PathToRealPath(path, realPath);
135     CHECK_AND_RETURN_RET_LOG(result, MEDIA_LIBRARY_NO_SUCH_FILE, "File real path isn't existed");
136 
137     auto fileAsset = mediaAsset_->GetFileAssetInstance();
138     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED, "fileAsset get failed!");
139     CHECK_AND_RETURN_RET_LOG(!IsMovingPhoto(), MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED,
140         "not support edit moving photo with uri");
141 
142     CHECK_AND_RETURN_RET_LOG(fileAsset->GetMediaType() == MediaFileUtils::GetMediaType(realPath),
143         MEDIA_LIBRARY_PARAMETER_ERROR, "Invalid file type");
144 
145     realPath_ = realPath;
146     addResourceMode_ = AddResourceMode::FILE_URI;
147     RecordChangeOperation(AssetChangeOperation::ADD_RESOURCE);
148     addResourceTypes_.push_back(resourceType);
149     return MEDIA_LIBRARY_OK;
150 }
151 
AddResourceWithBuffer(MediaLibrary_ResourceType resourceType,uint8_t * buffer,uint32_t length)152 MediaLibrary_ErrorCode MediaAssetChangeRequestImpl::AddResourceWithBuffer(MediaLibrary_ResourceType resourceType,
153     uint8_t* buffer, uint32_t length)
154 {
155     unique_lock<mutex> ulock(mutex_);
156     CHECK_AND_RETURN_RET_LOG(CheckWriteOperation(resourceType), MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED,
157         "operation not support");
158 
159     auto fileAsset = mediaAsset_->GetFileAssetInstance();
160     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED, "fileAsset get failed!");
161     CHECK_AND_RETURN_RET_LOG(!IsMovingPhoto(), MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED,
162         "not support edit moving photo with buffer");
163 
164     if (dataBuffer_ != nullptr) {
165         delete[] dataBuffer_;
166     }
167     dataBuffer_ = new uint8_t[length + 1];
168     CHECK_AND_RETURN_RET_LOG(dataBuffer_ != nullptr, MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR,
169         "create dataBuffer_ failed!");
170 
171     dataBufferSize_ = length;
172     if (length > 0) {
173         int ret = memcpy_s(dataBuffer_, length + 1, buffer, length);
174         CHECK_AND_RETURN_RET_LOG(ret == E_OK, MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR,
175             "memcpy buffer failed!");
176     }
177     addResourceMode_ = AddResourceMode::DATA_BUFFER;
178     RecordChangeOperation(AssetChangeOperation::ADD_RESOURCE);
179     addResourceTypes_.push_back(resourceType);
180     return MEDIA_LIBRARY_OK;
181 }
182 
ApplyChanges()183 MediaLibrary_ErrorCode MediaAssetChangeRequestImpl::ApplyChanges()
184 {
185     unique_lock<mutex> ulock(mutex_);
186     bool result = CheckChangeOperations();
187     CHECK_AND_RETURN_RET_LOG(result, MEDIA_LIBRARY_PARAMETER_ERROR, "Failed to check asset change request operations");
188 
189     auto fileAsset = mediaAsset_->GetFileAssetInstance();
190     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, MEDIA_LIBRARY_INTERNAL_SYSTEM_ERROR, "fileAsset is nullptr");
191 
192     unordered_set<AssetChangeOperation> appliedOperations;
193     for (const auto& changeOperation : assetChangeOperations_) {
194         if (appliedOperations.find(changeOperation) != appliedOperations.end()) {
195             continue;
196         }
197 
198         bool valid = ChangeOperationExecute(changeOperation);
199         CHECK_AND_RETURN_RET_LOG(valid, MEDIA_LIBRARY_OPERATION_NOT_SUPPORTED,
200             "Failed to apply asset change request, operation: %{public}d", changeOperation);
201 
202         appliedOperations.insert(changeOperation);
203     }
204     assetChangeOperations_.clear();
205     addResourceTypes_.clear();
206     movingPhotoVideoResourceMode_ = AddResourceMode::DEFAULT;
207     addResourceMode_ = AddResourceMode::DEFAULT;
208     return MEDIA_LIBRARY_OK;
209 }
210 
IsMovingPhoto()211 bool MediaAssetChangeRequestImpl::IsMovingPhoto()
212 {
213     auto fileAsset = mediaAsset_->GetFileAssetInstance();
214     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, false, "fileAsset is nullptr");
215 
216     return fileAsset->GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO);
217 }
218 
CheckWriteOperation(MediaLibrary_ResourceType resourceType)219 bool MediaAssetChangeRequestImpl::CheckWriteOperation(MediaLibrary_ResourceType resourceType)
220 {
221     if (Contains(AssetChangeOperation::GET_WRITE_CACHE_HANDLER) ||
222         Contains(AssetChangeOperation::ADD_RESOURCE)) {
223         MEDIA_ERR_LOG("The previous asset creation/modification request has not been applied");
224         return false;
225     }
226     return true;
227 }
228 
ContainsResource(MediaLibrary_ResourceType resourceType)229 bool MediaAssetChangeRequestImpl::ContainsResource(MediaLibrary_ResourceType resourceType)
230 {
231     return find(addResourceTypes_.begin(), addResourceTypes_.end(), resourceType) != addResourceTypes_.end();
232 }
233 
Contains(AssetChangeOperation changeOperation)234 bool MediaAssetChangeRequestImpl::Contains(AssetChangeOperation changeOperation)
235 {
236     return find(assetChangeOperations_.begin(), assetChangeOperations_.end(), changeOperation) !=
237            assetChangeOperations_.end();
238 }
239 
OpenWriteCacheHandler(bool isMovingPhotoVideo)240 int32_t MediaAssetChangeRequestImpl::OpenWriteCacheHandler(bool isMovingPhotoVideo)
241 {
242     auto fileAsset = mediaAsset_->GetFileAssetInstance();
243     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_FAIL, "fileAsset is null");
244 
245     // specify mp4 extension for cache file of moving photo video
246     string extension = isMovingPhotoVideo ? MOVING_PHOTO_VIDEO_EXTENSION
247         : MediaFileUtils::GetExtensionFromPath(fileAsset->GetDisplayName());
248     int64_t currentTimestamp = MediaFileUtils::UTCTimeNanoSeconds();
249     uint32_t cacheFileId = FetchAddCacheFileId();
250     string cacheFileName = to_string(currentTimestamp) + "_" + to_string(cacheFileId) + "." + extension;
251     string uri = PhotoColumn::PHOTO_CACHE_URI_PREFIX + cacheFileName;
252     MediaFileUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
253     Uri openCacheUri(uri);
254     int32_t ret = UserFileClient::OpenFile(openCacheUri, MEDIA_FILEMODE_WRITEONLY);
255     CHECK_AND_RETURN_RET_LOG(ret != E_PERMISSION_DENIED, ret, "Open cache file failed, permission denied");
256     CHECK_AND_PRINT_LOG(ret >= 0, "Open cache file failed, ret: %{public}d", ret);
257 
258     if (isMovingPhotoVideo) {
259         cacheMovingPhotoVideoName_ = cacheFileName;
260     } else {
261         cacheFileName_ = cacheFileName;
262     }
263     return ret;
264 }
265 
FetchAddCacheFileId()266 uint32_t MediaAssetChangeRequestImpl::FetchAddCacheFileId()
267 {
268     return cacheFileId_.fetch_add(1);
269 }
270 
RecordChangeOperation(AssetChangeOperation changeOperation)271 void MediaAssetChangeRequestImpl::RecordChangeOperation(AssetChangeOperation changeOperation)
272 {
273     assetChangeOperations_.push_back(changeOperation);
274 }
275 
CheckChangeOperations()276 bool MediaAssetChangeRequestImpl::CheckChangeOperations()
277 {
278     CHECK_AND_RETURN_RET_LOG(assetChangeOperations_.size() != 0, false, "None request to apply");
279 
280     auto fileAsset = mediaAsset_->GetFileAssetInstance();
281     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, false, "fileAsset is null");
282     CHECK_AND_RETURN_RET_LOG(fileAsset->GetId() > 0, false, "Invalid asset change request");
283 
284     return true;
285 }
286 
ChangeOperationExecute(AssetChangeOperation option)287 bool MediaAssetChangeRequestImpl::ChangeOperationExecute(AssetChangeOperation option)
288 {
289     bool ret = false;
290     switch (option) {
291         case AssetChangeOperation::GET_WRITE_CACHE_HANDLER:
292             ret = SubmitCacheExecute();
293             break;
294         case AssetChangeOperation::ADD_RESOURCE:
295             ret = AddResourceExecute();
296             break;
297         case AssetChangeOperation::SAVE_CAMERA_PHOTO:
298             ret = SaveCameraPhotoExecute();
299             break;
300         case AssetChangeOperation::DISCARD_CAMERA_PHOTO:
301             ret = DiscardCameraPhotoExecute();
302             break;
303         default:
304             break;
305     }
306     return ret;
307 }
308 
SubmitCacheExecute()309 bool MediaAssetChangeRequestImpl::SubmitCacheExecute()
310 {
311     int32_t ret = SubmitCache();
312     CHECK_AND_RETURN_RET_LOG(ret >= 0, false, "Failed to write cache, ret: %{public}d", ret);
313 
314     return true;
315 }
316 
AddResourceExecute()317 bool MediaAssetChangeRequestImpl::AddResourceExecute()
318 {
319     CHECK_AND_RETURN_RET_LOG(!IsMovingPhoto(), false, "not support edit moving photo with buffer or uri");
320 
321     if (!HasWritePermission()) {
322         return WriteBySecurityComponent();
323     }
324 
325     int32_t cacheFd = OpenWriteCacheHandler();
326     CHECK_AND_RETURN_RET_LOG(cacheFd >= 0, false, "Failed to open write cache handler, err: %{public}d", cacheFd);
327 
328     OHOS::UniqueFd uniqueFd(cacheFd);
329     AddResourceMode mode = addResourceMode_;
330     CHECK_AND_RETURN_RET_LOG(AddResourceByMode(uniqueFd, mode), false, "Faild to write cache file");
331 
332     return SubmitCacheExecute();
333 }
334 
SaveCameraPhotoExecute()335 bool MediaAssetChangeRequestImpl::SaveCameraPhotoExecute()
336 {
337     bool containsAddResource = find(assetChangeOperations_.begin(), assetChangeOperations_.end(),
338         AssetChangeOperation::ADD_RESOURCE) != assetChangeOperations_.end();
339     std::string uriStr = PAH_SAVE_CAMERA_PHOTO;
340     if (containsAddResource && !PermissionUtils::IsSystemApp()) {
341         // remove high quality photo
342         MEDIA_INFO_LOG("discard high quality photo because add resource by third app");
343         DiscardHighQualityPhoto();
344 
345         // set dirty flag when third-party hap calling addResource to save camera photo
346         MediaFileUtils::UriAppendKeyValue(uriStr, PhotoColumn::PHOTO_DIRTY,
347             to_string(static_cast<int32_t>(DirtyType::TYPE_NEW)));
348     }
349 
350     // The watermark will trigger the scan. If the watermark is turned on, there is no need to trigger the scan again.
351     bool needScan = std::find(assetChangeOperations_.begin(), assetChangeOperations_.end(),
352         AssetChangeOperation::ADD_FILTERS) == assetChangeOperations_.end();
353 
354     auto fileAsset = mediaAsset_->GetFileAssetInstance();
355     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, false, "fileAsset is nullptr");
356 
357     MediaFileUtils::UriAppendKeyValue(uriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
358     MediaFileUtils::UriAppendKeyValue(uriStr, MEDIA_OPERN_KEYWORD, to_string(needScan));
359     MediaFileUtils::UriAppendKeyValue(uriStr, PhotoColumn::MEDIA_FILE_PATH, fileAsset->GetUri());
360     MediaFileUtils::UriAppendKeyValue(uriStr, PhotoColumn::MEDIA_ID, to_string(fileAsset->GetId()));
361     MediaFileUtils::UriAppendKeyValue(uriStr, PhotoColumn::PHOTO_SUBTYPE,
362         to_string(fileAsset->GetPhotoSubType()));
363     Uri uri(uriStr);
364     OHOS::DataShare::DataShareValuesBucket valuesBucket;
365     valuesBucket.Put(PhotoColumn::PHOTO_IS_TEMP, false);
366     OHOS::DataShare::DataSharePredicates predicates;
367     bool ret = UserFileClient::Update(uri, predicates, valuesBucket);
368     CHECK_AND_RETURN_RET_LOG(ret, false, "save camera photo fail");
369 
370     return true;
371 }
372 
DiscardCameraPhotoExecute()373 bool MediaAssetChangeRequestImpl::DiscardCameraPhotoExecute()
374 {
375     OHOS::DataShare::DataSharePredicates predicates;
376     OHOS::DataShare::DataShareValuesBucket valuesBucket;
377     valuesBucket.Put(PhotoColumn::PHOTO_IS_TEMP, true);
378 
379     auto fileAsset = mediaAsset_->GetFileAssetInstance();
380     predicates.EqualTo(PhotoColumn::MEDIA_ID, to_string(fileAsset->GetId()));
381 
382     string uri = PAH_DISCARD_CAMERA_PHOTO;
383     MediaFileUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
384     Uri updateAssetUri(uri);
385     int32_t changedRows = UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
386     CHECK_AND_RETURN_RET_LOG(changedRows >= 0, false,
387         "Failed to update property of asset, err: %{public}d", changedRows);
388     return true;
389 }
390 
HasWritePermission()391 bool MediaAssetChangeRequestImpl::HasWritePermission()
392 {
393     AccessTokenID tokenCaller = OHOS::IPCSkeleton::GetSelfTokenID();
394     int result = AccessTokenKit::VerifyAccessToken(tokenCaller, PERM_WRITE_IMAGEVIDEO);
395     return result == PermissionState::PERMISSION_GRANTED;
396 }
397 
WriteBySecurityComponent()398 bool MediaAssetChangeRequestImpl::WriteBySecurityComponent()
399 {
400     int32_t ret = CopyToMediaLibrary(addResourceMode_);
401     CHECK_AND_RETURN_RET_LOG(ret >= 0, false,
402         "Failed to write by security component, ret: %{public}d", ret);
403 
404     return true;
405 }
406 
CopyToMediaLibrary(AddResourceMode mode)407 int32_t MediaAssetChangeRequestImpl::CopyToMediaLibrary(AddResourceMode mode)
408 {
409     auto fileAsset = mediaAsset_->GetFileAssetInstance();
410     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_FAIL, "fileAsset is null");
411 
412     int32_t ret = E_ERR;
413     string assetUri = fileAsset->GetUri();
414     CHECK_AND_RETURN_RET_LOG(!assetUri.empty(), E_ERR, "Failed to check empty asset uri");
415     CHECK_AND_RETURN_RET_LOG(!IsMovingPhoto(), E_ERR, "not support edit moving photo with buffer or uri");
416 
417     Uri uri(assetUri);
418     OHOS::UniqueFd destFd(UserFileClient::OpenFile(uri, MEDIA_FILEMODE_WRITEONLY));
419     CHECK_AND_RETURN_RET_LOG(destFd.Get() >= 0, destFd.Get(),
420         "Failed to open %{public}s with error: %{public}d", assetUri.c_str(), destFd.Get());
421 
422     if (mode == AddResourceMode::FILE_URI) {
423         ret = CopyFileToMediaLibrary(destFd);
424     } else if (mode == AddResourceMode::DATA_BUFFER) {
425         ret = CopyDataBufferToMediaLibrary(destFd);
426     } else {
427         MEDIA_ERR_LOG("Invalid mode: %{public}d", mode);
428         return E_INVALID_VALUES;
429     }
430 
431     return ret;
432 }
433 
CopyFileToMediaLibrary(const OHOS::UniqueFd & destFd,bool isMovingPhotoVideo)434 int32_t MediaAssetChangeRequestImpl::CopyFileToMediaLibrary(const OHOS::UniqueFd& destFd, bool isMovingPhotoVideo)
435 {
436     string srcRealPath = isMovingPhotoVideo ? movingPhotoVideoRealPath_ : realPath_;
437     CHECK_AND_RETURN_RET_LOG(!srcRealPath.empty(), E_FAIL, "Failed to check real path of source");
438 
439     string absFilePath;
440     CHECK_AND_RETURN_RET_LOG(OHOS::PathToRealPath(srcRealPath, absFilePath), E_FAIL, "Not real path %{public}s",
441         srcRealPath.c_str());
442 
443     OHOS::UniqueFd srcFd(open(absFilePath.c_str(), O_RDONLY));
444     CHECK_AND_RETURN_RET_LOG(srcFd.Get() >= 0, srcFd.Get(),
445         "Failed to open %{public}s, errno=%{public}d", absFilePath.c_str(), errno);
446 
447     int32_t err = SendFile(srcFd, destFd);
448     CHECK_AND_PRINT_LOG(err == E_OK, "Failed to send file from %{public}d to %{public}d", srcFd.Get(), destFd.Get());
449 
450     return err;
451 }
452 
CopyDataBufferToMediaLibrary(const OHOS::UniqueFd & destFd,bool isMovingPhotoVideo)453 int32_t MediaAssetChangeRequestImpl::CopyDataBufferToMediaLibrary(const OHOS::UniqueFd& destFd,
454     bool isMovingPhotoVideo)
455 {
456     size_t offset = 0;
457     size_t length = isMovingPhotoVideo ? movingPhotoVideoBufferSize_ : dataBufferSize_;
458     void* dataBuffer = isMovingPhotoVideo ? movingPhotoVideoDataBuffer_ : dataBuffer_;
459     while (offset < length) {
460         ssize_t written = write(destFd.Get(), (char*)dataBuffer + offset, length - offset);
461         CHECK_AND_RETURN_RET_LOG(written >= 0, written,
462             "Failed to copy data buffer, return %{public}d", static_cast<int>(written));
463 
464         offset += static_cast<size_t>(written);
465     }
466     return E_OK;
467 }
468 
SendToCacheFile(const OHOS::UniqueFd & destFd,bool isMovingPhotoVideo)469 bool MediaAssetChangeRequestImpl::SendToCacheFile(const OHOS::UniqueFd& destFd, bool isMovingPhotoVideo)
470 {
471     string realPath = isMovingPhotoVideo ? movingPhotoVideoRealPath_ : realPath_;
472     string absFilePath;
473     CHECK_AND_RETURN_RET_LOG(OHOS::PathToRealPath(realPath, absFilePath), false,
474         "Not real path %{public}s, errno=%{public}d", realPath.c_str(), errno);
475 
476     OHOS::UniqueFd srcFd(open(absFilePath.c_str(), O_RDONLY));
477     CHECK_AND_RETURN_RET_LOG(srcFd.Get() >= 0, false, "Failed to open file, errno=%{public}d", errno);
478 
479     int32_t err = SendFile(srcFd, destFd);
480     CHECK_AND_RETURN_RET_LOG(err == E_OK, false,
481         "Failed to send file from %{public}d to %{public}d", srcFd.Get(), destFd.Get());
482 
483     return true;
484 }
485 
SubmitCache()486 int32_t MediaAssetChangeRequestImpl::SubmitCache()
487 {
488     auto fileAsset = mediaAsset_->GetFileAssetInstance();
489     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_FAIL, "fileAsset is null");
490     CHECK_AND_RETURN_RET_LOG(!cacheFileName_.empty() || !cacheMovingPhotoVideoName_.empty(), E_FAIL,
491         "Failed to check cache file");
492 
493     string uri = PAH_SUBMIT_CACHE;
494     MediaFileUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
495     Uri submitCacheUri(uri);
496     OHOS::DataShare::DataShareValuesBucket valuesBucket;
497     valuesBucket.Put(PhotoColumn::MEDIA_ID, fileAsset->GetId());
498     valuesBucket.Put(CACHE_FILE_NAME, cacheFileName_);
499     int32_t ret = UserFileClient::Insert(submitCacheUri, valuesBucket);
500 
501     cacheFileName_.clear();
502     cacheMovingPhotoVideoName_.clear();
503     return ret;
504 }
505 
SendFile(const OHOS::UniqueFd & srcFd,const OHOS::UniqueFd & destFd)506 int32_t MediaAssetChangeRequestImpl::SendFile(const OHOS::UniqueFd& srcFd, const OHOS::UniqueFd& destFd)
507 {
508     CHECK_AND_RETURN_RET_LOG((srcFd.Get() >= 0 && destFd.Get() >= 0), E_ERR,
509         "Failed to check srcFd: %{public}d and destFd: %{public}d", srcFd.Get(), destFd.Get());
510 
511     struct stat statSrc {};
512     int32_t status = fstat(srcFd.Get(), &statSrc);
513     CHECK_AND_RETURN_RET_LOG(status == 0, status, "Failed to get file stat, errno=%{public}d", errno);
514 
515     off_t offset = 0;
516     off_t fileSize = statSrc.st_size;
517     while (offset < fileSize) {
518         ssize_t sent = sendfile(destFd.Get(), srcFd.Get(), &offset, fileSize - offset);
519         CHECK_AND_RETURN_RET_LOG(sent >= 0, sent,
520             "Failed to sendfile with errno=%{public}d, srcFd=%{public}d, destFd=%{public}d",
521             errno, srcFd.Get(), destFd.Get());
522     }
523 
524     return E_OK;
525 }
526 
AddResourceByMode(const OHOS::UniqueFd & uniqueFd,AddResourceMode mode,bool isMovingPhotoVideo)527 bool MediaAssetChangeRequestImpl::AddResourceByMode(const OHOS::UniqueFd& uniqueFd,
528     AddResourceMode mode, bool isMovingPhotoVideo)
529 {
530     bool isWriteSuccess = false;
531     if (mode == AddResourceMode::DATA_BUFFER) {
532         isWriteSuccess = WriteCacheByArrayBuffer(uniqueFd, isMovingPhotoVideo);
533     } else if (mode == AddResourceMode::FILE_URI) {
534         isWriteSuccess = SendToCacheFile(uniqueFd, isMovingPhotoVideo);
535     } else {
536         MEDIA_ERR_LOG("Unsupported addResource mode");
537     }
538     return isWriteSuccess;
539 }
540 
WriteCacheByArrayBuffer(const OHOS::UniqueFd & destFd,bool isMovingPhotoVideo)541 bool MediaAssetChangeRequestImpl::WriteCacheByArrayBuffer(const OHOS::UniqueFd& destFd, bool isMovingPhotoVideo)
542 {
543     size_t offset = 0;
544     size_t length = isMovingPhotoVideo ? movingPhotoVideoBufferSize_ : dataBufferSize_;
545     void* dataBuffer = isMovingPhotoVideo ? movingPhotoVideoDataBuffer_ : dataBuffer_;
546     while (offset < length) {
547         ssize_t written = write(destFd.Get(), (char*)dataBuffer + offset, length - offset);
548         CHECK_AND_RETURN_RET_LOG(written >= 0, false,
549             "Failed to write data buffer to cache file, return %{public}d", static_cast<int>(written));
550 
551         offset += static_cast<size_t>(written);
552     }
553     return true;
554 }
555 
DiscardHighQualityPhoto()556 void MediaAssetChangeRequestImpl::DiscardHighQualityPhoto()
557 {
558     string uriStr = PAH_REMOVE_MSC_TASK;
559     MediaFileUtils::UriAppendKeyValue(uriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
560     Uri uri(uriStr);
561     OHOS::DataShare::DataSharePredicates predicates;
562     int errCode = 0;
563 
564     auto fileAsset = mediaAsset_->GetFileAssetInstance();
565     vector<string> columns { to_string(fileAsset->GetId()) };
566     UserFileClient::Query(uri, predicates, columns, errCode);
567 }
568