• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 "medialibrary_asset_operations.h"
17 
18 #include <algorithm>
19 #include <dirent.h>
20 #include <memory>
21 #include <mutex>
22 
23 #include "directory_ex.h"
24 #include "file_asset.h"
25 #include "media_column.h"
26 #include "media_exif.h"
27 #include "media_file_utils.h"
28 #include "media_file_uri.h"
29 #include "media_log.h"
30 #include "media_scanner_manager.h"
31 #include "medialibrary_album_operations.h"
32 #include "medialibrary_audio_operations.h"
33 #include "medialibrary_command.h"
34 #include "medialibrary_common_utils.h"
35 #include "medialibrary_data_manager.h"
36 #include "medialibrary_data_manager_utils.h"
37 #include "medialibrary_db_const.h"
38 #include "medialibrary_errno.h"
39 #include "medialibrary_inotify.h"
40 #include "medialibrary_notify.h"
41 #include "medialibrary_photo_operations.h"
42 #include "medialibrary_rdbstore.h"
43 #include "medialibrary_tracer.h"
44 #include "medialibrary_type_const.h"
45 #include "medialibrary_unistore_manager.h"
46 #include "media_privacy_manager.h"
47 #include "mimetype_utils.h"
48 #include "permission_utils.h"
49 #include "rdb_errno.h"
50 #include "rdb_utils.h"
51 #include "result_set_utils.h"
52 #include "thumbnail_service.h"
53 #include "uri_permission_manager_client.h"
54 #include "userfile_manager_types.h"
55 #include "value_object.h"
56 #include "values_bucket.h"
57 
58 using namespace std;
59 using namespace OHOS::NativeRdb;
60 
61 namespace OHOS {
62 namespace Media {
63 
64 mutex g_uniqueNumberLock;
65 
66 const string DEFAULT_IMAGE_NAME = "IMG_";
67 const string DEFAULT_VIDEO_NAME = "VID_";
68 const string DEFAULT_AUDIO_NAME = "AUD_";
69 
HandleInsertOperation(MediaLibraryCommand & cmd)70 int32_t MediaLibraryAssetOperations::HandleInsertOperation(MediaLibraryCommand &cmd)
71 {
72     int errCode = E_ERR;
73     switch (cmd.GetOprnType()) {
74         case OperationType::CREATE:
75             errCode = CreateOperation(cmd);
76             break;
77         case OperationType::CLOSE:
78             errCode = CloseOperation(cmd);
79             break;
80         default:
81             MEDIA_ERR_LOG("unknown operation type %{public}d", cmd.GetOprnType());
82             break;
83     }
84     return errCode;
85 }
86 
CreateOperation(MediaLibraryCommand & cmd)87 int32_t MediaLibraryAssetOperations::CreateOperation(MediaLibraryCommand &cmd)
88 {
89     // CreateAsset specify type
90     switch (cmd.GetOprnObject()) {
91         case OperationObject::FILESYSTEM_PHOTO:
92             return MediaLibraryPhotoOperations::Create(cmd);
93         case OperationObject::FILESYSTEM_AUDIO:
94             return MediaLibraryAudioOperations::Create(cmd);
95         case OperationObject::FILESYSTEM_ASSET:
96             MEDIA_ERR_LOG("create asset by FileSysetm_Asset is deperated");
97             return E_INVALID_VALUES;
98         default:
99             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
100             return E_INVALID_VALUES;
101     }
102 }
103 
DeleteOperation(MediaLibraryCommand & cmd)104 int32_t MediaLibraryAssetOperations::DeleteOperation(MediaLibraryCommand &cmd)
105 {
106     // delete Asset specify type
107     switch (cmd.GetOprnObject()) {
108         case OperationObject::FILESYSTEM_PHOTO:
109             return MediaLibraryPhotoOperations::Delete(cmd);
110         case OperationObject::FILESYSTEM_AUDIO:
111             return MediaLibraryAudioOperations::Delete(cmd);
112         case OperationObject::FILESYSTEM_ASSET:
113             MEDIA_ERR_LOG("delete asset by FILESYSTEM_ASSET is deperated");
114             return E_INVALID_VALUES;
115         default:
116             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
117             return E_INVALID_VALUES;
118     }
119 }
120 
QueryOperation(MediaLibraryCommand & cmd,const vector<string> & columns)121 shared_ptr<NativeRdb::ResultSet> MediaLibraryAssetOperations::QueryOperation(
122     MediaLibraryCommand &cmd, const vector<string> &columns)
123 {
124     // query asset specify type
125     switch (cmd.GetOprnObject()) {
126         case OperationObject::FILESYSTEM_PHOTO:
127             return MediaLibraryPhotoOperations::Query(cmd, columns);
128         case OperationObject::FILESYSTEM_AUDIO:
129             return MediaLibraryAudioOperations::Query(cmd, columns);
130         case OperationObject::FILESYSTEM_ASSET:
131             MEDIA_ERR_LOG("api9 operation is not finished");
132             return nullptr;
133         default:
134             MEDIA_ERR_LOG("error operation objec: %{public}d", cmd.GetOprnObject());
135             return nullptr;
136     }
137 }
138 
UpdateOperation(MediaLibraryCommand & cmd)139 int32_t MediaLibraryAssetOperations::UpdateOperation(MediaLibraryCommand &cmd)
140 {
141     if (!AssetInputParamVerification::CheckParamForUpdate(cmd)) {
142         return E_INVALID_VALUES;
143     }
144 
145     switch (cmd.GetOprnObject()) {
146         case OperationObject::FILESYSTEM_PHOTO:
147             return MediaLibraryPhotoOperations::Update(cmd);
148         case OperationObject::FILESYSTEM_AUDIO:
149             return MediaLibraryAudioOperations::Update(cmd);
150         case OperationObject::FILESYSTEM_ASSET:
151             MEDIA_ERR_LOG("create asset by FILESYSTEM_ASSET is deperated");
152             return E_INVALID_VALUES;
153         default:
154             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
155             return E_INVALID_VALUES;
156     }
157 }
158 
OpenOperation(MediaLibraryCommand & cmd,const string & mode)159 int32_t MediaLibraryAssetOperations::OpenOperation(MediaLibraryCommand &cmd, const string &mode)
160 {
161     MediaLibraryTracer tracer;
162     tracer.Start("MediaLibraryAssetOperations::OpenOperation");
163 
164     // Open specify type
165     switch (cmd.GetOprnObject()) {
166         case OperationObject::FILESYSTEM_PHOTO:
167             return MediaLibraryPhotoOperations::Open(cmd, mode);
168         case OperationObject::FILESYSTEM_AUDIO:
169             return MediaLibraryAudioOperations::Open(cmd, mode);
170         case OperationObject::FILESYSTEM_ASSET:
171             MEDIA_ERR_LOG("open by FILESYSTEM_ASSET is deperated");
172             return E_INVALID_VALUES;
173         default:
174             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
175             return E_INVALID_VALUES;
176     }
177 }
178 
CloseOperation(MediaLibraryCommand & cmd)179 int32_t MediaLibraryAssetOperations::CloseOperation(MediaLibraryCommand &cmd)
180 {
181     // Close specify type
182     switch (cmd.GetOprnObject()) {
183         case OperationObject::FILESYSTEM_PHOTO:
184             return MediaLibraryPhotoOperations::Close(cmd);
185         case OperationObject::FILESYSTEM_AUDIO:
186             return MediaLibraryAudioOperations::Close(cmd);
187         case OperationObject::FILESYSTEM_ASSET:
188             MEDIA_ERR_LOG("close by FILESYSTEM_ASSET is deperated");
189             return E_INVALID_VALUES;
190         default:
191             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
192             return E_INVALID_VALUES;
193     }
194 }
195 
DeleteToolOperation(MediaLibraryCommand & cmd)196 int32_t MediaLibraryAssetOperations::DeleteToolOperation(MediaLibraryCommand &cmd)
197 {
198     auto valuesBucket = cmd.GetValueBucket();
199     int32_t isOnlyDeleteDb = 0;
200     if (!GetInt32FromValuesBucket(valuesBucket, DELETE_TOOL_ONLY_DATABASE, isOnlyDeleteDb)) {
201         MEDIA_ERR_LOG("Can not get delete tool value");
202         return E_INVALID_VALUES;
203     }
204     MediaLibraryRdbStore::UpdateAPI10Tables();
205     const static vector<string> DELETE_DIR_LIST = {
206         ROOT_MEDIA_DIR + PHOTO_BUCKET,
207         ROOT_MEDIA_DIR + AUDIO_BUCKET,
208         ROOT_MEDIA_DIR + CAMERA_DIR_VALUES,
209         ROOT_MEDIA_DIR + VIDEO_DIR_VALUES,
210         ROOT_MEDIA_DIR + PIC_DIR_VALUES,
211         ROOT_MEDIA_DIR + AUDIO_DIR_VALUES,
212         ROOT_MEDIA_DIR + ".thumbs"
213     };
214 
215     if (!isOnlyDeleteDb) {
216         for (const string &dir : DELETE_DIR_LIST) {
217             if (!MediaFileUtils::DeleteDir(dir)) {
218                 MEDIA_ERR_LOG("Delete dir %{private}s failed", dir.c_str());
219             }
220         }
221         for (auto &dir : PRESET_ROOT_DIRS) {
222             string ditPath = ROOT_MEDIA_DIR + dir;
223             MediaFileUtils::CreateDirectory(ditPath);
224         }
225     }
226 
227     return E_OK;
228 }
229 
CheckOprnObject(OperationObject object)230 static bool CheckOprnObject(OperationObject object)
231 {
232     const set<OperationObject> validOprnObjectet = {
233         OperationObject::FILESYSTEM_PHOTO,
234         OperationObject::FILESYSTEM_AUDIO
235     };
236     if (validOprnObjectet.find(object) == validOprnObjectet.end()) {
237         MEDIA_ERR_LOG("input OperationObject %{public}d error!", object);
238         return false;
239     }
240     return true;
241 }
242 
GetOprnObjectByMediaType(int32_t type)243 static OperationObject GetOprnObjectByMediaType(int32_t type)
244 {
245     switch (type) {
246         case MediaType::MEDIA_TYPE_IMAGE:
247         case MediaType::MEDIA_TYPE_VIDEO: {
248             return OperationObject::FILESYSTEM_PHOTO;
249         }
250         case MediaType::MEDIA_TYPE_AUDIO: {
251             return OperationObject::FILESYSTEM_AUDIO;
252         }
253         case MediaType::MEDIA_TYPE_FILE: {
254             return OperationObject::FILESYSTEM_ASSET;
255         }
256         default: {
257             return OperationObject::UNKNOWN_OBJECT;
258         }
259     }
260 }
261 
GetAssetFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns)262 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetAssetFromResultSet(
263     const shared_ptr<NativeRdb::ResultSet> &resultSet, const vector<string> &columns)
264 {
265     auto fileAsset = make_shared<FileAsset>();
266     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "resultSet is nullptr");
267     int32_t count = 0;
268     CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, nullptr,
269         "can not get resultset row count");
270     CHECK_AND_RETURN_RET_LOG(count == 1, nullptr, "ResultSet count is %{public}d, not 1", count);
271     CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, nullptr, "can not go to first row");
272     for (const auto &column : columns) {
273         int32_t columnIndex = 0;
274         CHECK_AND_RETURN_RET_LOG(resultSet->GetColumnIndex(column, columnIndex) == NativeRdb::E_OK,
275             nullptr, "Can not get column %{public}s index", column.c_str());
276         CHECK_AND_RETURN_RET_LOG(FILEASSET_MEMBER_MAP.find(column) != FILEASSET_MEMBER_MAP.end(), nullptr,
277             "Can not find column %{public}s from member map", column.c_str());
278         int32_t memberType = FILEASSET_MEMBER_MAP.at(column);
279         switch (memberType) {
280             case MEMBER_TYPE_INT32: {
281                 int32_t value = 0;
282                 CHECK_AND_RETURN_RET_LOG(resultSet->GetInt(columnIndex, value) == NativeRdb::E_OK, nullptr,
283                     "Can not get int value from column %{public}s", column.c_str());
284                 auto &map = fileAsset->GetMemberMap();
285                 map[column] = value;
286                 break;
287             }
288             case MEMBER_TYPE_INT64: {
289                 int64_t value = 0;
290                 CHECK_AND_RETURN_RET_LOG(resultSet->GetLong(columnIndex, value) == NativeRdb::E_OK, nullptr,
291                     "Can not get long value from column %{public}s", column.c_str());
292                 auto &map = fileAsset->GetMemberMap();
293                 map[column] = value;
294                 break;
295             }
296             case MEMBER_TYPE_STRING: {
297                 string value;
298                 CHECK_AND_RETURN_RET_LOG(resultSet->GetString(columnIndex, value) == NativeRdb::E_OK, nullptr,
299                     "Can not get string value from column %{public}s", column.c_str());
300                 auto &map = fileAsset->GetMemberMap();
301                 map[column] = value;
302                 break;
303             }
304         }
305     }
306     return fileAsset;
307 }
308 
GetFileAssetFromDb(const string & column,const string & value,OperationObject oprnObject,const vector<string> & columns,const string & networkId)309 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetFromDb(const string &column,
310     const string &value, OperationObject oprnObject, const vector<string> &columns, const string &networkId)
311 {
312     MediaLibraryTracer tracer;
313     tracer.Start("MediaLibraryAssetOperations::GetFileAssetFromDb");
314 
315     if (!CheckOprnObject(oprnObject) || column.empty() || value.empty()) {
316         return nullptr;
317     }
318 
319     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
320     if (rdbStore == nullptr) {
321         return nullptr;
322     }
323 
324     MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, networkId);
325     cmd.GetAbsRdbPredicates()->EqualTo(column, value);
326 
327     auto resultSet = rdbStore->Query(cmd, columns);
328     if (resultSet == nullptr) {
329         return nullptr;
330     }
331     return GetAssetFromResultSet(resultSet, columns);
332 }
333 
GetFileAssetFromDb(AbsPredicates & predicates,OperationObject oprnObject,const vector<string> & columns,const string & networkId)334 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetFromDb(AbsPredicates &predicates,
335     OperationObject oprnObject, const vector<string> &columns, const string &networkId)
336 {
337     if (!CheckOprnObject(oprnObject)) {
338         return nullptr;
339     }
340 
341     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
342     if (rdbStore == nullptr) {
343         return nullptr;
344     }
345 
346     MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, networkId);
347     cmd.GetAbsRdbPredicates()->SetWhereClause(predicates.GetWhereClause());
348     cmd.GetAbsRdbPredicates()->SetWhereArgs(predicates.GetWhereArgs());
349     cmd.GetAbsRdbPredicates()->SetOrder(predicates.GetOrder());
350 
351     auto resultSet = rdbStore->Query(cmd, columns);
352     if (resultSet == nullptr) {
353         return nullptr;
354     }
355     return GetAssetFromResultSet(resultSet, columns);
356 }
357 
GetVirtualPath(const string & relativePath,const string & displayName)358 static inline string GetVirtualPath(const string &relativePath, const string &displayName)
359 {
360     if (relativePath[relativePath.size() - 1] != SLASH_CHAR) {
361         return relativePath + SLASH_CHAR + displayName;
362     } else {
363         return relativePath + displayName;
364     }
365 }
366 
GetAssetPackageName(const FileAsset & fileAsset,const string & bundleName)367 static string GetAssetPackageName(const FileAsset &fileAsset, const string &bundleName)
368 {
369     if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::SCREENSHOT)) {
370         if (fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE) ||
371             fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_PHOTO)) {
372             return "截图";
373         } else if (fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_VIDEO)) {
374             return "屏幕录制";
375         }
376     }
377     return PermissionUtils::GetPackageNameByBundleName(bundleName);
378 }
379 
FillAssetInfo(MediaLibraryCommand & cmd,const FileAsset & fileAsset)380 static void FillAssetInfo(MediaLibraryCommand &cmd, const FileAsset &fileAsset)
381 {
382     // Fill basic file information into DB
383     const string& displayName = fileAsset.GetDisplayName();
384     ValuesBucket assetInfo;
385     assetInfo.PutInt(MediaColumn::MEDIA_TYPE, fileAsset.GetMediaType());
386     string extension = ScannerUtils::GetFileExtension(displayName);
387     assetInfo.PutString(MediaColumn::MEDIA_MIME_TYPE,
388         MimeTypeUtils::GetMimeTypeFromExtension(extension));
389     assetInfo.PutString(MediaColumn::MEDIA_FILE_PATH, fileAsset.GetPath());
390     if (cmd.GetApi() == MediaLibraryApi::API_OLD) {
391         assetInfo.PutString(MediaColumn::MEDIA_RELATIVE_PATH,
392             fileAsset.GetRelativePath());
393         assetInfo.PutString(MediaColumn::MEDIA_VIRTURL_PATH,
394             GetVirtualPath(fileAsset.GetRelativePath(), fileAsset.GetDisplayName()));
395     } else {
396         assetInfo.PutLong(MediaColumn::MEDIA_TIME_PENDING, fileAsset.GetTimePending());
397     }
398     assetInfo.PutString(MediaColumn::MEDIA_NAME, displayName);
399     assetInfo.PutString(MediaColumn::MEDIA_TITLE,
400         MediaFileUtils::GetTitleFromDisplayName(displayName));
401     if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) {
402         assetInfo.PutInt(PhotoColumn::PHOTO_SUBTYPE, fileAsset.GetPhotoSubType());
403         assetInfo.PutString(PhotoColumn::CAMERA_SHOT_KEY, fileAsset.GetCameraShotKey());
404     }
405     assetInfo.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, cmd.GetBundleName());
406     if (!cmd.GetBundleName().empty()) {
407         assetInfo.PutString(MediaColumn::MEDIA_PACKAGE_NAME,
408             GetAssetPackageName(fileAsset, cmd.GetBundleName()));
409     }
410 
411     assetInfo.PutString(MediaColumn::MEDIA_DEVICE_NAME, cmd.GetDeviceName());
412     assetInfo.PutLong(MediaColumn::MEDIA_DATE_ADDED, MediaFileUtils::UTCTimeSeconds());
413     cmd.SetValueBucket(assetInfo);
414 }
415 
InsertAssetInDb(MediaLibraryCommand & cmd,const FileAsset & fileAsset)416 int32_t MediaLibraryAssetOperations::InsertAssetInDb(MediaLibraryCommand &cmd, const FileAsset &fileAsset)
417 {
418     // All values inserted in this function are the base property for files
419     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
420     if (rdbStore == nullptr) {
421         return E_HAS_DB_ERROR;
422     }
423 
424     if (!fileAsset.GetPath().empty() && MediaFileUtils::IsFileExists(fileAsset.GetPath())) {
425         return E_FILE_EXIST;
426     }
427     FillAssetInfo(cmd, fileAsset);
428 
429     int64_t outRowId = -1;
430     int32_t errCode = rdbStore->Insert(cmd, outRowId);
431     if (errCode != NativeRdb::E_OK) {
432         MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
433         return E_HAS_DB_ERROR;
434     }
435     return static_cast<int32_t>(outRowId);
436 }
437 
CheckTypeFromRootDir(const std::string & rootDirName,int32_t type)438 static bool CheckTypeFromRootDir(const std::string &rootDirName, int32_t type)
439 {
440     // "Camera/"
441     if (!strcmp(rootDirName.c_str(), CAMERA_DIR_VALUES.c_str())) {
442         if (type == MEDIA_TYPE_IMAGE || type == MEDIA_TYPE_VIDEO) {
443             return true;
444         }
445     }
446     // "Videos/"
447     if (!strcmp(rootDirName.c_str(), VIDEO_DIR_VALUES.c_str())) {
448         if (type == MEDIA_TYPE_VIDEO) {
449             return true;
450         }
451     }
452     // "Pictures/"
453     if (!strcmp(rootDirName.c_str(), PIC_DIR_VALUES.c_str())) {
454         if (type == MEDIA_TYPE_IMAGE) {
455             return true;
456         }
457     }
458     // "Audios/"
459     if (!strcmp(rootDirName.c_str(), AUDIO_DIR_VALUES.c_str())) {
460         if (type == MEDIA_TYPE_AUDIO) {
461             return true;
462         }
463     }
464     // "Documents/"
465     if (!strcmp(rootDirName.c_str(), DOC_DIR_VALUES.c_str())) {
466         return true;
467     }
468     // "Download/"
469     if (!strcmp(rootDirName.c_str(), DOWNLOAD_DIR_VALUES.c_str())) {
470         return true;
471     }
472     MEDIA_ERR_LOG("Cannot match rootDir %{public}s and mediaType %{public}d",
473         rootDirName.c_str(), type);
474     return false;
475 }
476 
CheckWithType(bool isContains,const string & displayName,const string & extention,int32_t mediaType)477 int32_t MediaLibraryAssetOperations::CheckWithType(bool isContains, const string &displayName,
478     const string &extention, int32_t mediaType)
479 {
480     string name = isContains ? displayName : extention;
481     int32_t errCode =  isContains ? CheckDisplayNameWithType(name, mediaType) : CheckExtWithType(name, mediaType);
482     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
483         "Failed to Check Dir and extention, (displayName or extention)=%{private}s, mediaType=%{public}d",
484         name.c_str(), mediaType);
485     return errCode;
486 }
487 
CheckDisplayNameWithType(const string & displayName,int32_t mediaType)488 int32_t MediaLibraryAssetOperations::CheckDisplayNameWithType(const string &displayName, int32_t mediaType)
489 {
490     int32_t ret = MediaFileUtils::CheckDisplayName(displayName);
491     CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_INVALID_DISPLAY_NAME, "Check DisplayName failed, "
492         "displayName=%{private}s", displayName.c_str());
493 
494     string ext = MediaFileUtils::GetExtensionFromPath(displayName);
495     CHECK_AND_RETURN_RET_LOG(!ext.empty(), E_INVALID_DISPLAY_NAME, "invalid extension, displayName=%{private}s",
496         displayName.c_str());
497 
498     auto typeFromExt = MediaFileUtils::GetMediaType(displayName);
499     CHECK_AND_RETURN_RET_LOG(typeFromExt == mediaType, E_CHECK_MEDIATYPE_MATCH_EXTENSION_FAIL,
500         "cannot match, mediaType=%{public}d, ext=%{public}s, type from ext=%{public}d",
501         mediaType, ext.c_str(), typeFromExt);
502     return E_OK;
503 }
504 
CheckExtWithType(const string & extention,int32_t mediaType)505 int32_t MediaLibraryAssetOperations::CheckExtWithType(const string &extention, int32_t mediaType)
506 {
507     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extention);
508     auto typeFromExt = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
509     CHECK_AND_RETURN_RET_LOG(typeFromExt == mediaType, E_CHECK_MEDIATYPE_MATCH_EXTENSION_FAIL,
510         "cannot match, mediaType=%{public}d, ext=%{public}s, type from ext=%{public}d",
511         mediaType, extention.c_str(), typeFromExt);
512     return E_OK;
513 }
514 
CheckRelativePathWithType(const string & relativePath,int32_t mediaType)515 int32_t MediaLibraryAssetOperations::CheckRelativePathWithType(const string &relativePath, int32_t mediaType)
516 {
517     int32_t ret = MediaFileUtils::CheckRelativePath(relativePath);
518     CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_INVALID_PATH, "Check relativePath failed, "
519         "relativePath=%{private}s", relativePath.c_str());
520 
521     // get rootdir and check if it match mediatype
522     string rootDirName;
523     MediaFileUtils::GetRootDirFromRelativePath(relativePath, rootDirName);
524     CHECK_AND_RETURN_RET_LOG(!rootDirName.empty(), E_INVALID_PATH, "Cannot get rootdirName");
525 
526     bool isValid = CheckTypeFromRootDir(rootDirName, mediaType);
527     CHECK_AND_RETURN_RET(isValid, E_CHECK_MEDIATYPE_FAIL);
528     return E_OK;
529 }
530 
GetAssetRootDir(int32_t mediaType,string & rootDirPath)531 void MediaLibraryAssetOperations::GetAssetRootDir(int32_t mediaType, string &rootDirPath)
532 {
533     map<int, string> rootDir = {
534         { MEDIA_TYPE_FILE, DOCUMENT_BUCKET + SLASH_CHAR },
535         { MEDIA_TYPE_VIDEO, PHOTO_BUCKET + SLASH_CHAR },
536         { MEDIA_TYPE_IMAGE, PHOTO_BUCKET + SLASH_CHAR },
537         { MEDIA_TYPE_AUDIO, AUDIO_BUCKET + SLASH_CHAR },
538     };
539     if (rootDir.count(mediaType) == 0) {
540         rootDirPath = rootDir[MEDIA_TYPE_FILE];
541     } else {
542         rootDirPath = rootDir[mediaType];
543     }
544 }
545 
SetAssetPathInCreate(FileAsset & fileAsset)546 int32_t MediaLibraryAssetOperations::SetAssetPathInCreate(FileAsset &fileAsset)
547 {
548     if (!fileAsset.GetPath().empty()) {
549         return E_OK;
550     }
551     string extension = MediaFileUtils::GetExtensionFromPath(fileAsset.GetDisplayName());
552     string filePath;
553     int32_t uniqueId = CreateAssetUniqueId(fileAsset.GetMediaType());
554     int32_t errCode = CreateAssetPathById(uniqueId, fileAsset.GetMediaType(), extension, filePath);
555     if (errCode != E_OK) {
556         MEDIA_ERR_LOG("Create Asset Path failed, errCode=%{public}d", errCode);
557         return errCode;
558     }
559 
560     // filePath can not be empty
561     fileAsset.SetPath(filePath);
562     return E_OK;
563 }
564 
SetAssetPath(FileAsset & fileAsset,const string & extension)565 int32_t MediaLibraryAssetOperations::SetAssetPath(FileAsset &fileAsset, const string &extension)
566 {
567     string filePath;
568     int32_t uniqueId = CreateAssetUniqueId(fileAsset.GetMediaType());
569     int32_t errCode = CreateAssetPathById(uniqueId, fileAsset.GetMediaType(), extension, filePath);
570     if (errCode != E_OK) {
571         MEDIA_ERR_LOG("Create Asset Path failed, errCode=%{public}d", errCode);
572         return errCode;
573     }
574 
575     // filePath can not be empty
576     fileAsset.SetPath(filePath);
577     string fileName = MediaFileUtils::GetFileName(filePath);
578     string displayName = fileName.substr(0, fileName.find('_')) + '_' + fileName.substr(fileName.rfind('_') + 1);
579     fileAsset.SetDisplayName(displayName);
580     return E_OK;
581 }
582 
DeleteAssetInDb(MediaLibraryCommand & cmd)583 int32_t MediaLibraryAssetOperations::DeleteAssetInDb(MediaLibraryCommand &cmd)
584 {
585     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
586     if (rdbStore == nullptr) {
587         return E_HAS_DB_ERROR;
588     }
589 
590     string strDeleteCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
591     if (strDeleteCondition.empty()) {
592         string strRow = cmd.GetOprnFileId();
593         if (strRow.empty() || !MediaLibraryDataManagerUtils::IsNumber(strRow)) {
594             MEDIA_ERR_LOG("MediaLibraryAssetOperations DeleteFile: Index not digit, fileIdStr=%{public}s",
595                 strRow.c_str());
596             return E_INVALID_FILEID;
597         }
598         cmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, strRow);
599     }
600 
601     int32_t deletedRows = E_HAS_DB_ERROR;
602     int32_t result = rdbStore->Delete(cmd, deletedRows);
603     if (result != NativeRdb::E_OK) {
604         MEDIA_ERR_LOG("Delete operation failed. Result %{public}d.", result);
605     }
606 
607     return deletedRows;
608 }
609 
ModifyAssetInDb(MediaLibraryCommand & cmd)610 int32_t MediaLibraryAssetOperations::ModifyAssetInDb(MediaLibraryCommand &cmd)
611 {
612     TransactionOperations transactionOprn;
613     int32_t errCode = transactionOprn.Start();
614     if (errCode != E_OK) {
615         return errCode;
616     }
617 
618     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
619     if (rdbStore == nullptr) {
620         return E_HAS_DB_ERROR;
621     }
622 
623     int32_t rowId = 0;
624     int32_t ret = rdbStore->Update(cmd, rowId);
625     if (ret < 0 || rowId < 0) {
626         MEDIA_ERR_LOG("update path failed, ret=%{public}d", ret);
627         return ret;
628     }
629     transactionOprn.Finish();
630 
631     return rowId;
632 }
633 
UpdateFileName(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNameChanged)634 int32_t MediaLibraryAssetOperations::UpdateFileName(MediaLibraryCommand &cmd,
635     const shared_ptr<FileAsset> &fileAsset, bool &isNameChanged)
636 {
637     ValuesBucket &values = cmd.GetValueBucket();
638     ValueObject valueObject;
639     string newTitle;
640     string newDisplayName;
641     bool containsTitle = false;
642     bool containsDisplayName = false;
643 
644     if (values.GetObject(MediaColumn::MEDIA_TITLE, valueObject)) {
645         valueObject.GetString(newTitle);
646         containsTitle = true;
647     }
648     if (values.GetObject(MediaColumn::MEDIA_NAME, valueObject)) {
649         valueObject.GetString(newDisplayName);
650         containsDisplayName = true;
651     }
652     if ((!containsTitle) && (!containsDisplayName)) {
653         // do not need to update
654         return E_OK;
655     }
656     if (containsTitle && containsDisplayName &&
657         (MediaFileUtils::GetTitleFromDisplayName(newDisplayName) != newTitle)) {
658         MEDIA_ERR_LOG("new displayName [%{private}s] and new title [%{private}s] is not same",
659             newDisplayName.c_str(), newTitle.c_str());
660         return E_INVALID_DISPLAY_NAME;
661     }
662     if (!containsTitle) {
663         newTitle = MediaFileUtils::GetTitleFromDisplayName(newDisplayName);
664     }
665     if (!containsDisplayName) {
666         newDisplayName = newTitle + "." + MediaFileUtils::SplitByChar(fileAsset->GetDisplayName(), '.');
667     }
668 
669     int32_t ret = CheckDisplayNameWithType(newDisplayName, fileAsset->GetMediaType());
670     CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "Input displayName invalid %{private}s", newDisplayName.c_str());
671     values.PutString(MediaColumn::MEDIA_TITLE, newTitle);
672     values.PutString(MediaColumn::MEDIA_NAME, newDisplayName);
673     isNameChanged = true;
674     return E_OK;
675 }
676 
SetUserComment(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)677 int32_t MediaLibraryAssetOperations::SetUserComment(MediaLibraryCommand &cmd,
678     const shared_ptr<FileAsset> &fileAsset)
679 {
680     ValuesBucket &values = cmd.GetValueBucket();
681     ValueObject valueObject;
682     string newUserComment;
683 
684     if (values.GetObject(PhotoColumn::PHOTO_USER_COMMENT, valueObject)) {
685         valueObject.GetString(newUserComment);
686     } else {
687         return E_OK;
688     }
689 
690     uint32_t err = 0;
691     SourceOptions opts;
692     string filePath = fileAsset->GetFilePath();
693     string extension = MediaFileUtils::GetExtensionFromPath(filePath);
694     opts.formatHint = "image/" + extension;
695     std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(filePath, opts, err);
696     if (err != 0 || imageSource == nullptr) {
697         MEDIA_ERR_LOG("Failed to obtain image source, err = %{public}d", err);
698         return E_OK;
699     }
700 
701     string userComment;
702     err = imageSource->GetImagePropertyString(0, PHOTO_DATA_IMAGE_USER_COMMENT, userComment);
703     if (err != 0) {
704         MEDIA_ERR_LOG("Image does not exit exif, no need to modify");
705         return E_OK;
706     }
707     err = imageSource->ModifyImageProperty(0, PHOTO_DATA_IMAGE_USER_COMMENT, newUserComment, filePath);
708     if (err != 0) {
709         MEDIA_ERR_LOG("Modify image property user comment failed");
710     }
711 
712     return E_OK;
713 }
714 
UpdateRelativePath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNameChanged)715 int32_t MediaLibraryAssetOperations::UpdateRelativePath(MediaLibraryCommand &cmd,
716     const shared_ptr<FileAsset> &fileAsset, bool &isNameChanged)
717 {
718     string newRelativePath;
719     ValuesBucket &values = cmd.GetValueBucket();
720     ValueObject valueObject;
721     if (values.GetObject(MediaColumn::MEDIA_RELATIVE_PATH, valueObject)) {
722         valueObject.GetString(newRelativePath);
723     } else {
724         // relativePath is not modified
725         return E_OK;
726     }
727     MediaFileUtils::FormatRelativePath(newRelativePath);
728 
729     if (newRelativePath == fileAsset->GetRelativePath()) {
730         // relativepath has not been modified
731         return E_OK;
732     }
733 
734     int32_t errCode = CheckRelativePathWithType(newRelativePath, fileAsset->GetMediaType());
735     if (errCode != E_SUCCESS) {
736         MEDIA_ERR_LOG("Check RelativePath failed");
737         return errCode;
738     }
739     values.Delete(MediaColumn::MEDIA_RELATIVE_PATH);
740     values.PutString(MediaColumn::MEDIA_RELATIVE_PATH, newRelativePath);
741 
742     isNameChanged = true;
743     return E_OK;
744 }
745 
UpdateVirtualPath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)746 void MediaLibraryAssetOperations::UpdateVirtualPath(MediaLibraryCommand &cmd,
747     const shared_ptr<FileAsset> &fileAsset)
748 {
749     string relativePath;
750     string displayName;
751     ValuesBucket &values = cmd.GetValueBucket();
752     ValueObject valueObject;
753 
754     if (values.GetObject(MediaColumn::MEDIA_NAME, valueObject)) {
755         valueObject.GetString(displayName);
756     } else {
757         displayName = fileAsset->GetDisplayName();
758     }
759 
760     if (values.GetObject(MediaColumn::MEDIA_RELATIVE_PATH, valueObject)) {
761         valueObject.GetString(relativePath);
762     } else {
763         relativePath = fileAsset->GetRelativePath();
764     }
765 
766     if (relativePath.back() != '/') {
767         relativePath += '/';
768     }
769     string virtualPath = relativePath + displayName;
770     values.PutString(MediaColumn::MEDIA_VIRTURL_PATH, virtualPath);
771 }
772 
UpdateFileInDb(MediaLibraryCommand & cmd)773 int32_t MediaLibraryAssetOperations::UpdateFileInDb(MediaLibraryCommand &cmd)
774 {
775     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
776     if (rdbStore == nullptr) {
777         return E_HAS_DB_ERROR;
778     }
779 
780     int32_t updateRows = 0;
781     int32_t result = rdbStore->Update(cmd, updateRows);
782     if (result != NativeRdb::E_OK || updateRows <= 0) {
783         MEDIA_ERR_LOG("Update File failed. Result %{public}d.", result);
784         return E_HAS_DB_ERROR;
785     }
786 
787     return updateRows;
788 }
789 
OpenFile(const string & filePath,const string & mode)790 static int32_t OpenFile(const string &filePath, const string &mode)
791 {
792     std::string absFilePath;
793     if (!PathToRealPath(filePath, absFilePath)) {
794         MEDIA_ERR_LOG("Failed to get real path: %{private}s", filePath.c_str());
795         return E_ERR;
796     }
797 
798     return MediaPrivacyManager(absFilePath, mode).Open();
799 }
800 
SetPendingTime(const shared_ptr<FileAsset> & fileAsset,int64_t pendingTime)801 static int32_t SetPendingTime(const shared_ptr<FileAsset> &fileAsset, int64_t pendingTime)
802 {
803     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
804     if (rdbStore == nullptr) {
805         return E_HAS_DB_ERROR;
806     }
807 
808     MediaLibraryCommand updatePendingCmd(GetOprnObjectByMediaType(fileAsset->GetMediaType()),
809         OperationType::UPDATE);
810     updatePendingCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID,
811         to_string(fileAsset->GetId()));
812     ValuesBucket values;
813     values.PutLong(MediaColumn::MEDIA_TIME_PENDING, pendingTime);
814     updatePendingCmd.SetValueBucket(values);
815     int32_t rowId = 0;
816     int32_t result = rdbStore->Update(updatePendingCmd, rowId);
817     if (result != NativeRdb::E_OK || rowId <= 0) {
818         MEDIA_ERR_LOG("Update File pending failed. Result %{public}d.", result);
819         return E_HAS_DB_ERROR;
820     }
821     return E_OK;
822 }
823 
CreateFileAndSetPending(const shared_ptr<FileAsset> & fileAsset,int64_t pendingTime)824 static int32_t CreateFileAndSetPending(const shared_ptr<FileAsset> &fileAsset, int64_t pendingTime)
825 {
826     int32_t errCode = MediaFileUtils::CreateAsset(fileAsset->GetPath());
827     if (errCode != E_OK) {
828         MEDIA_ERR_LOG("Create asset failed, path=%{private}s", fileAsset->GetPath().c_str());
829         return errCode;
830     }
831 
832     return SetPendingTime(fileAsset, pendingTime);
833 }
834 
SolvePendingStatus(const shared_ptr<FileAsset> & fileAsset,const string & mode)835 static int32_t SolvePendingStatus(const shared_ptr<FileAsset> &fileAsset, const string &mode)
836 {
837     int64_t pendingTime = fileAsset->GetTimePending();
838     if (pendingTime != 0) {
839         if (mode == MEDIA_FILEMODE_READONLY) {
840             MEDIA_ERR_LOG("FileAsset [%{public}s] pending status is %{private}ld and open mode is READ_ONLY",
841                 fileAsset->GetUri().c_str(), (long) pendingTime);
842             return E_IS_PENDING_ERROR;
843         }
844         string networkId = MediaFileUtils::GetNetworkIdFromUri(fileAsset->GetUri());
845         if (!networkId.empty()) {
846             MEDIA_ERR_LOG("Can not open remote [%{private}s] pending file", networkId.c_str());
847             return E_IS_PENDING_ERROR;
848         }
849         if (pendingTime == UNCREATE_FILE_TIMEPENDING) {
850             int32_t errCode = CreateFileAndSetPending(fileAsset, UNCLOSE_FILE_TIMEPENDING);
851             return errCode;
852         }
853         if (pendingTime == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
854             int32_t errCode = SetPendingTime(fileAsset, UNCLOSE_FILE_TIMEPENDING);
855             return errCode;
856         }
857     }
858     return E_OK;
859 }
860 
OpenAsset(const shared_ptr<FileAsset> & fileAsset,const string & mode,MediaLibraryApi api)861 int32_t MediaLibraryAssetOperations::OpenAsset(const shared_ptr<FileAsset> &fileAsset, const string &mode,
862     MediaLibraryApi api)
863 {
864     MediaLibraryTracer tracer;
865     tracer.Start("MediaLibraryAssetOperations::OpenAsset");
866 
867     if (fileAsset == nullptr) {
868         return E_INVALID_VALUES;
869     }
870 
871     string lowerMode = mode;
872     transform(lowerMode.begin(), lowerMode.end(), lowerMode.begin(), ::tolower);
873     if (!MediaFileUtils::CheckMode(lowerMode)) {
874         return E_INVALID_MODE;
875     }
876 
877     string path;
878     if (api == MediaLibraryApi::API_10) {
879         int32_t errCode = SolvePendingStatus(fileAsset, mode);
880         if (errCode != E_OK) {
881             MEDIA_ERR_LOG("Solve pending status failed, errCode=%{public}d", errCode);
882             return errCode;
883         }
884         path = fileAsset->GetPath();
885     } else {
886         // If below API10, TIME_PENDING is 0 after asset created, so if file is not exist, create an empty one
887         if (!MediaFileUtils::IsFileExists(fileAsset->GetPath())) {
888             int32_t errCode = MediaFileUtils::CreateAsset(fileAsset->GetPath());
889             if (errCode != E_OK) {
890                 MEDIA_ERR_LOG("Create asset failed, path=%{private}s", fileAsset->GetPath().c_str());
891                 return errCode;
892             }
893         }
894         path = MediaFileUtils::UpdatePath(fileAsset->GetPath(), fileAsset->GetUri());
895     }
896 
897     tracer.Start("OpenFile");
898     int32_t fd = OpenFile(path, lowerMode);
899     tracer.Finish();
900     if (fd < 0) {
901         MEDIA_ERR_LOG("open file fd %{private}d, errno %{private}d", fd, errno);
902         return E_HAS_FS_ERROR;
903     }
904     tracer.Start("AddWatchList");
905     if (mode.find(MEDIA_FILEMODE_WRITEONLY) != string::npos) {
906         auto watch = MediaLibraryInotify::GetInstance();
907         if (watch != nullptr) {
908             MEDIA_DEBUG_LOG("enter inotify, path = %{private}s", path.c_str());
909             watch->AddWatchList(path, fileAsset->GetUri(), MediaLibraryApi::API_10);
910         }
911     }
912     tracer.Finish();
913     return fd;
914 }
915 
CloseAsset(const shared_ptr<FileAsset> & fileAsset,bool isCreateThumbSync)916 int32_t MediaLibraryAssetOperations::CloseAsset(const shared_ptr<FileAsset> &fileAsset, bool isCreateThumbSync)
917 {
918     if (fileAsset == nullptr) {
919         return E_INVALID_VALUES;
920     }
921 
922     // remove inotify event since there is close cmd
923     auto watch = MediaLibraryInotify::GetInstance();
924     if (watch != nullptr) {
925         string uri = fileAsset->GetUri();
926         watch->RemoveByFileUri(uri, MediaLibraryApi::API_10);
927         MEDIA_DEBUG_LOG("watch RemoveByFileUri, uri:%{private}s", uri.c_str());
928     }
929 
930     string fileId = to_string(fileAsset->GetId());
931     string path = fileAsset->GetPath();
932     // if pending == 0, scan
933     // if pending == UNCREATE_FILE_TIMEPENDING, not occur under normal conditions
934     // if pending == UNCLOSE_FILE_TIMEPENDING, set pending = 0 and scan
935     // if pending == UNOPEN_FILE_COMPONENT_TIMEPENDING, not allowed to close
936     // if pending is timestamp, do nothing
937     if (fileAsset->GetTimePending() == 0 || fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
938         ScanFile(path, isCreateThumbSync);
939         if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
940             MediaLibraryAlbumOperations::UpdateSystemAlbumInternal({
941                 to_string(PhotoAlbumSubType::IMAGES),
942                 to_string(PhotoAlbumSubType::VIDEO),
943                 to_string(PhotoAlbumSubType::SCREENSHOT),
944                 to_string(PhotoAlbumSubType::CAMERA),
945                 to_string(PhotoAlbumSubType::FAVORITE),
946             });
947         }
948         return E_OK;
949     } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING ||
950         fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
951         MEDIA_ERR_LOG("This asset [%{private}d] pending status cannot close", fileAsset->GetId());
952         return E_IS_PENDING_ERROR;
953     } else if (fileAsset->GetTimePending() > 0) {
954         MEDIA_WARN_LOG("This asset [%{private}d] is in pending", fileAsset->GetId());
955         return E_OK;
956     } else {
957         MEDIA_ERR_LOG("This asset [%{private}d] pending status is invalid", fileAsset->GetId());
958         return E_INVALID_VALUES;
959     }
960 }
961 
InvalidateThumbnail(const string & fileId,int32_t type)962 void MediaLibraryAssetOperations::InvalidateThumbnail(const string &fileId, int32_t type)
963 {
964     string tableName;
965     switch (type) {
966         case MediaType::MEDIA_TYPE_IMAGE:
967         case MediaType::MEDIA_TYPE_VIDEO: {
968             tableName = PhotoColumn::PHOTOS_TABLE;
969             break;
970         }
971         case MediaType::MEDIA_TYPE_AUDIO: {
972             tableName = AudioColumn::AUDIOS_TABLE;
973             break;
974         }
975         default: {
976             MEDIA_ERR_LOG("Can not match this type %{public}d", type);
977             return;
978         }
979     }
980     ThumbnailService::GetInstance()->InvalidateThumbnail(fileId, tableName);
981 }
982 
ScanFile(const string & path,bool isCreateThumbSync)983 void MediaLibraryAssetOperations::ScanFile(const string &path, bool isCreateThumbSync)
984 {
985     shared_ptr<ScanAssetCallback> scanAssetCallback = make_shared<ScanAssetCallback>();
986     if (scanAssetCallback == nullptr) {
987         MEDIA_ERR_LOG("Failed to create scan file callback object");
988         return;
989     }
990     if (isCreateThumbSync) {
991         scanAssetCallback->SetSync(true);
992     }
993 
994     int ret = MediaScannerManager::GetInstance()->ScanFileSync(path, scanAssetCallback, MediaLibraryApi::API_10);
995     if (ret != 0) {
996         MEDIA_ERR_LOG("Scan file failed!");
997     }
998 }
999 
SendTrashNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri)1000 int32_t MediaLibraryAssetOperations::SendTrashNotify(MediaLibraryCommand &cmd, int32_t rowId, const string &extraUri)
1001 {
1002     ValueObject value;
1003     int64_t trashDate = 0;
1004     if (!cmd.GetValueBucket().GetObject(PhotoColumn::MEDIA_DATE_TRASHED, value)) {
1005         return E_DO_NOT_NEDD_SEND_NOTIFY;
1006     }
1007     MediaLibraryAlbumOperations::UpdateUserAlbumInternal();
1008     MediaLibraryAlbumOperations::UpdateSystemAlbumInternal();
1009 
1010     value.GetLong(trashDate);
1011 
1012     string prefix;
1013     if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) {
1014         prefix = PhotoColumn::PHOTO_URI_PREFIX;
1015     } else if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_AUDIO) {
1016         prefix = AudioColumn::AUDIO_URI_PREFIX;
1017     } else {
1018         return E_OK;
1019     }
1020 
1021     string notifyUri = MediaFileUtils::GetUriByExtrConditions(prefix, to_string(rowId), extraUri);
1022     auto watch = MediaLibraryNotify::GetInstance();
1023     if (trashDate > 0) {
1024         watch->Notify(notifyUri, NotifyType::NOTIFY_REMOVE);
1025         watch->Notify(notifyUri, NotifyType::NOTIFY_ALBUM_REMOVE_ASSET);
1026     } else {
1027         watch->Notify(notifyUri, NotifyType::NOTIFY_ADD);
1028         watch->Notify(notifyUri, NotifyType::NOTIFY_ALBUM_ADD_ASSERT);
1029     }
1030 
1031     int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
1032     if (trashAlbumId <= 0) {
1033         return E_OK;
1034     }
1035     NotifyType type = (trashDate > 0) ? NotifyType::NOTIFY_ALBUM_ADD_ASSERT : NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1036     watch->Notify(notifyUri, type, trashAlbumId);
1037     return E_OK;
1038 }
1039 
SendFavoriteNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri)1040 void MediaLibraryAssetOperations::SendFavoriteNotify(MediaLibraryCommand &cmd, int32_t rowId, const string &extraUri)
1041 {
1042     ValueObject value;
1043     int32_t isFavorite = 0;
1044     if (!cmd.GetValueBucket().GetObject(PhotoColumn::MEDIA_IS_FAV, value)) {
1045         return;
1046     }
1047     value.GetInt(isFavorite);
1048     MediaLibraryAlbumOperations::UpdateSystemAlbumInternal({ to_string(PhotoAlbumSubType::FAVORITE) });
1049     auto watch = MediaLibraryNotify::GetInstance();
1050     if (cmd.GetOprnObject() != OperationObject::FILESYSTEM_PHOTO) {
1051         return;
1052     }
1053     int favAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::FAVORITE);
1054     if (favAlbumId <= 0) {
1055         return;
1056     }
1057 
1058     NotifyType type = (isFavorite) ? NotifyType::NOTIFY_ALBUM_ADD_ASSERT : NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1059     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(rowId), extraUri),
1060         type, favAlbumId);
1061 }
1062 
SendHideNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri)1063 int32_t MediaLibraryAssetOperations::SendHideNotify(MediaLibraryCommand &cmd, int32_t rowId, const string &extraUri)
1064 {
1065     ValueObject value;
1066     int32_t hiddenState = 0;
1067     if (!cmd.GetValueBucket().GetObject(MediaColumn::MEDIA_HIDDEN, value)) {
1068         return E_DO_NOT_NEDD_SEND_NOTIFY;
1069     }
1070     value.GetInt(hiddenState);
1071     MediaLibraryAlbumOperations::UpdateUserAlbumInternal();
1072     MediaLibraryAlbumOperations::UpdateSystemAlbumInternal();
1073 
1074     string prefix;
1075     if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) {
1076         prefix = PhotoColumn::PHOTO_URI_PREFIX;
1077     } else if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_AUDIO) {
1078         prefix = AudioColumn::AUDIO_URI_PREFIX;
1079     } else {
1080         return E_OK;
1081     }
1082 
1083     string notifyUri = MediaFileUtils::GetUriByExtrConditions(prefix, to_string(rowId), extraUri);
1084     auto watch = MediaLibraryNotify::GetInstance();
1085     if (hiddenState > 0) {
1086         watch->Notify(notifyUri, NotifyType::NOTIFY_REMOVE);
1087         watch->Notify(notifyUri, NotifyType::NOTIFY_ALBUM_REMOVE_ASSET);
1088     } else {
1089         watch->Notify(notifyUri, NotifyType::NOTIFY_ADD);
1090         watch->Notify(notifyUri, NotifyType::NOTIFY_ALBUM_ADD_ASSERT);
1091     }
1092 
1093     int hiddenAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::HIDDEN);
1094     if (hiddenAlbumId <= 0) {
1095         return E_OK;
1096     }
1097     NotifyType type = (hiddenState > 0) ? NotifyType::NOTIFY_ALBUM_ADD_ASSERT : NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1098     watch->Notify(notifyUri, type, hiddenAlbumId);
1099     return E_OK;
1100 }
1101 
SendModifyUserCommentNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri)1102 int32_t MediaLibraryAssetOperations::SendModifyUserCommentNotify(MediaLibraryCommand &cmd, int32_t rowId,
1103     const string &extraUri)
1104 {
1105     if (cmd.GetOprnType() != OperationType::SET_USER_COMMENT) {
1106         return E_DO_NOT_NEDD_SEND_NOTIFY;
1107     }
1108 
1109     auto watch = MediaLibraryNotify::GetInstance();
1110     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(rowId), extraUri),
1111         NotifyType::NOTIFY_UPDATE);
1112     return E_OK;
1113 }
1114 
SetPendingTrue(const shared_ptr<FileAsset> & fileAsset)1115 int32_t MediaLibraryAssetOperations::SetPendingTrue(const shared_ptr<FileAsset> &fileAsset)
1116 {
1117     // time_pending = 0, means file is created, not allowed
1118     // time_pending = UNCREATE_FILE_TIMEPENDING, means file is not created yet, create an empty one
1119     // time_pending = UNCLOSE_FILE_TIMEPENDING, means file is not close yet, set pending time
1120     // time_pending = UNOPEN_FILE_COMPONENT_TIMEPENDING, means file is created but not open, set pending time
1121     // time_pending is timestamp, update it
1122     int64_t timestamp = MediaFileUtils::UTCTimeSeconds();
1123     if (timestamp <= 0) {
1124         MEDIA_ERR_LOG("Get timestamp failed, timestamp:%{public}ld", (long) timestamp);
1125         return E_INVALID_TIMESTAMP;
1126     }
1127     if (fileAsset->GetTimePending() == 0) {
1128         MEDIA_ERR_LOG("fileAsset time_pending is 0, not allowed");
1129         return E_INVALID_VALUES;
1130     } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
1131         int32_t errCode = CreateFileAndSetPending(fileAsset, timestamp);
1132         if (errCode != E_OK) {
1133             MEDIA_ERR_LOG("Create asset failed, id=%{public}d", fileAsset->GetId());
1134             return errCode;
1135         }
1136     } else if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING ||
1137         fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING ||
1138         fileAsset->GetTimePending() > 0) {
1139         int32_t errCode = SetPendingTime(fileAsset, timestamp);
1140         if (errCode != E_OK) {
1141             MEDIA_ERR_LOG("Set pending time failed, id=%{public}d", fileAsset->GetId());
1142             return errCode;
1143         }
1144     } else {
1145         MEDIA_ERR_LOG("fileAsset time_pending is invalid, time_pending:%{public}ld, id=%{public}d",
1146             (long) fileAsset->GetTimePending(), fileAsset->GetId());
1147         return E_INVALID_VALUES;
1148     }
1149 
1150     return E_OK;
1151 }
1152 
SetPendingFalse(const shared_ptr<FileAsset> & fileAsset)1153 int32_t MediaLibraryAssetOperations::SetPendingFalse(const shared_ptr<FileAsset> &fileAsset)
1154 {
1155     // time_pending = 0, only return
1156     // time_pending = UNCREATE_FILE_TIMEPENDING, means file is not created yet, not allowed
1157     // time_pending = UNCLOSE_FILE_TIMEPENDING, means file is not close yet, not allowed
1158     // time_pending = UNOPEN_FILE_COMPONENT_TIMEPENDING, means file is created but not open, not allowed
1159     // time_pending is timestamp, scan and set pending time = 0
1160     if (fileAsset->GetTimePending() == 0) {
1161         return E_OK;
1162     } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
1163         MEDIA_ERR_LOG("file is not created yet, not allowed, id=%{public}d", fileAsset->GetId());
1164         return E_INVALID_VALUES;
1165     } else if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
1166         MEDIA_ERR_LOG("file is not close yet, not allowed, id=%{public}d", fileAsset->GetId());
1167         return E_INVALID_VALUES;
1168     } else if (fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
1169         MEDIA_ERR_LOG("file is created but not open, not allowed, id=%{public}d", fileAsset->GetId());
1170         return E_INVALID_VALUES;
1171     } else if (fileAsset->GetTimePending() > 0) {
1172         ScanFile(fileAsset->GetPath());
1173     } else {
1174         MEDIA_ERR_LOG("fileAsset time_pending is invalid, time_pending:%{public}ld, id=%{public}d",
1175             (long) fileAsset->GetTimePending(), fileAsset->GetId());
1176         return E_INVALID_VALUES;
1177     }
1178     return E_OK;
1179 }
1180 
SetPendingStatus(MediaLibraryCommand & cmd)1181 int32_t MediaLibraryAssetOperations::SetPendingStatus(MediaLibraryCommand &cmd)
1182 {
1183     int32_t pendingStatus = 0;
1184     if (!GetInt32FromValuesBucket(cmd.GetValueBucket(), MediaColumn::MEDIA_TIME_PENDING, pendingStatus)) {
1185         return E_INVALID_VALUES;
1186     }
1187 
1188     vector<string> columns = {
1189         MediaColumn::MEDIA_ID,
1190         MediaColumn::MEDIA_FILE_PATH,
1191         MediaColumn::MEDIA_TYPE,
1192         MediaColumn::MEDIA_TIME_PENDING
1193     };
1194     auto fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()), cmd.GetOprnObject(), columns);
1195     if (fileAsset == nullptr) {
1196         return E_INVALID_VALUES;
1197     }
1198     if (pendingStatus == 1) {
1199         return SetPendingTrue(fileAsset);
1200     } else if (pendingStatus == 0) {
1201         return SetPendingFalse(fileAsset);
1202     } else {
1203         MEDIA_ERR_LOG("pendingStatus is invalid, pendingStatus:%{public}d", pendingStatus);
1204         return E_INVALID_VALUES;
1205     }
1206 }
1207 
ConvertMediaPathFromCloudPath(const string & path)1208 static string ConvertMediaPathFromCloudPath(const string &path)
1209 {
1210     // if input path is /storage/cloud/xxx, return /storage/media/local/xxx
1211     string mediaPath = "/storage/media/local/";
1212     string cloudPath = "/storage/cloud/";
1213     string newPath = path;
1214     if (newPath.find(cloudPath) != string::npos) {
1215         newPath.replace(newPath.find(cloudPath), cloudPath.length(), mediaPath);
1216     }
1217     return newPath;
1218 }
1219 
GrantUriPermission(const string & uri,const string & bundleName,const string & path)1220 int32_t MediaLibraryAssetOperations::GrantUriPermission(const string &uri, const string &bundleName,
1221     const string &path)
1222 {
1223     if (uri.empty() || path.empty()) {
1224         MEDIA_ERR_LOG("uri or path is empty, uri:%{private}s, path:%{private}s", uri.c_str(), path.c_str());
1225         return E_INVALID_VALUES;
1226     }
1227     if (bundleName.empty()) {
1228         MEDIA_WARN_LOG("bundleName is empty, bundleName:%{private}s", bundleName.c_str());
1229         return E_OK;
1230     }
1231     auto& uriPermissionClient = AAFwk::UriPermissionManagerClient::GetInstance();
1232     auto flag = AAFwk::Want::FLAG_AUTH_WRITE_URI_PERMISSION;
1233     if (!MediaFileUtils::CreateFile(path)) {
1234         MEDIA_ERR_LOG("Can not create file, path: %{private}s, errno: %{public}d", path.c_str(), errno);
1235         return E_HAS_FS_ERROR;
1236     }
1237 
1238     int32_t ret = uriPermissionClient.GrantUriPermission(Uri(uri), flag, bundleName, 1);
1239     if (ret != 0) {
1240         MEDIA_ERR_LOG("Can not grant uri permission, uri: %{private}s, bundleName: %{private}s, ret: %{public}d",
1241             uri.c_str(), bundleName.c_str(), ret);
1242         return E_GRANT_URI_PERM_FAIL;
1243     }
1244 
1245     MediaLibraryTracer tracer;
1246     tracer.Start("AddWatchList");
1247     auto watch = MediaLibraryInotify::GetInstance();
1248     if (watch != nullptr) {
1249         MEDIA_DEBUG_LOG("enter inotify, path = %{private}s", path.c_str());
1250         watch->AddWatchList(ConvertMediaPathFromCloudPath(path), uri, MediaLibraryApi::API_10);
1251     }
1252     tracer.Finish();
1253 
1254     return E_OK;
1255 }
1256 
GetInt32FromValuesBucket(const NativeRdb::ValuesBucket & values,const std::string & column,int32_t & value)1257 bool MediaLibraryAssetOperations::GetInt32FromValuesBucket(const NativeRdb::ValuesBucket &values,
1258     const std::string &column, int32_t &value)
1259 {
1260     ValueObject valueObject;
1261     if (values.GetObject(column, valueObject)) {
1262         valueObject.GetInt(value);
1263     } else {
1264         return false;
1265     }
1266     return true;
1267 }
1268 
CreateExtUriForV10Asset(FileAsset & fileAsset)1269 std::string MediaLibraryAssetOperations::CreateExtUriForV10Asset(FileAsset &fileAsset)
1270 {
1271     const std::string &filePath = fileAsset.GetPath();
1272     const std::string &displayName = fileAsset.GetDisplayName();
1273     auto mediaType = fileAsset.GetMediaType();
1274     if (filePath.empty() || displayName.empty() || mediaType < 0) {
1275         MEDIA_ERR_LOG("param invalid, filePath %{public}s or displayName %{public}s invalid failed.",
1276             filePath.c_str(), displayName.c_str());
1277         return "";
1278     }
1279 
1280     string extrUri = MediaFileUtils::GetExtraUri(displayName, filePath);
1281     return MediaFileUtils::GetUriByExtrConditions(ML_FILE_URI_PREFIX + MediaFileUri::GetMediaTypeUri(mediaType,
1282         MEDIA_API_VERSION_V10) + "/", to_string(fileAsset.GetId()), extrUri);
1283 }
1284 
GetStringFromValuesBucket(const NativeRdb::ValuesBucket & values,const std::string & column,string & value)1285 bool MediaLibraryAssetOperations::GetStringFromValuesBucket(const NativeRdb::ValuesBucket &values,
1286     const std::string &column, string &value)
1287 {
1288     ValueObject valueObject;
1289     if (values.GetObject(column, valueObject)) {
1290         valueObject.GetString(value);
1291     } else {
1292         return false;
1293     }
1294     return true;
1295 }
1296 
CreateAssetUniqueId(int32_t type)1297 int32_t MediaLibraryAssetOperations::CreateAssetUniqueId(int32_t type)
1298 {
1299     string typeString;
1300     switch (type) {
1301         case MediaType::MEDIA_TYPE_IMAGE:
1302             typeString += IMAGE_ASSET_TYPE;
1303             break;
1304         case MediaType::MEDIA_TYPE_VIDEO:
1305             typeString += VIDEO_ASSET_TYPE;
1306             break;
1307         case MediaType::MEDIA_TYPE_AUDIO:
1308             typeString += AUDIO_ASSET_TYPE;
1309             break;
1310         default:
1311             MEDIA_ERR_LOG("This type %{public}d can not get unique id", type);
1312             return E_INVALID_VALUES;
1313     }
1314 
1315     const string updateSql = "UPDATE " + ASSET_UNIQUE_NUMBER_TABLE + " SET " + UNIQUE_NUMBER +
1316         "=" + UNIQUE_NUMBER + "+1" " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
1317     const string querySql = "SELECT " + UNIQUE_NUMBER + " FROM " + ASSET_UNIQUE_NUMBER_TABLE +
1318         " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
1319 
1320     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
1321     if (rdbStore == nullptr) {
1322         return E_HAS_DB_ERROR;
1323     }
1324     lock_guard<mutex> lock(g_uniqueNumberLock);
1325     int32_t errCode = rdbStore->ExecuteSql(updateSql);
1326     if (errCode < 0) {
1327         MEDIA_ERR_LOG("execute update unique number failed, ret=%{public}d", errCode);
1328         return errCode;
1329     }
1330 
1331     auto resultSet = rdbStore->QuerySql(querySql);
1332     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1333         return E_HAS_DB_ERROR;
1334     }
1335     return GetInt32Val(UNIQUE_NUMBER, resultSet);
1336 }
1337 
CreateAssetBucket(int32_t fileId,int32_t & bucketNum)1338 int32_t MediaLibraryAssetOperations::CreateAssetBucket(int32_t fileId, int32_t &bucketNum)
1339 {
1340     if (fileId < 0) {
1341         MEDIA_ERR_LOG("input fileId [%{private}d] is invalid", fileId);
1342         return E_INVALID_FILEID;
1343     }
1344     int start = ASSET_DIR_START_NUM;
1345     int divider = ASSET_DIR_START_NUM;
1346     while (fileId > start * ASSET_IN_BUCKET_NUM_MAX) {
1347         divider = start;
1348         start <<= 1;
1349     }
1350 
1351     int fileIdRemainder = fileId % divider;
1352     if (fileIdRemainder == 0) {
1353         bucketNum = start + fileIdRemainder;
1354     } else {
1355         bucketNum = (start - divider) + fileIdRemainder;
1356     }
1357     return E_OK;
1358 }
1359 
CreateAssetRealName(int32_t fileId,int32_t mediaType,const string & extension,string & name)1360 int32_t MediaLibraryAssetOperations::CreateAssetRealName(int32_t fileId, int32_t mediaType,
1361     const string &extension, string &name)
1362 {
1363     string fileNumStr = to_string(fileId);
1364     if (fileId <= ASSET_MAX_COMPLEMENT_ID) {
1365         size_t fileIdLen = fileNumStr.length();
1366         fileNumStr = ("00" + fileNumStr).substr(fileIdLen - 1);
1367     }
1368 
1369     string mediaTypeStr;
1370     switch (mediaType) {
1371         case MediaType::MEDIA_TYPE_IMAGE:
1372             mediaTypeStr = DEFAULT_IMAGE_NAME;
1373             break;
1374         case MediaType::MEDIA_TYPE_VIDEO:
1375             mediaTypeStr = DEFAULT_VIDEO_NAME;
1376             break;
1377         case MediaType::MEDIA_TYPE_AUDIO:
1378             mediaTypeStr = DEFAULT_AUDIO_NAME;
1379             break;
1380         default:
1381             MEDIA_ERR_LOG("This mediatype %{public}d can not get real name", mediaType);
1382             return E_INVALID_VALUES;
1383     }
1384 
1385     name = mediaTypeStr + to_string(MediaFileUtils::UTCTimeSeconds()) + "_" + fileNumStr + "." + extension;
1386     return E_OK;
1387 }
1388 
PrepareAssetDir(const string & dirPath)1389 static inline int32_t PrepareAssetDir(const string &dirPath)
1390 {
1391     CHECK_AND_RETURN_RET(!dirPath.empty(), E_INVALID_PATH);
1392     if (!MediaFileUtils::IsFileExists(dirPath)) {
1393         bool ret = MediaFileUtils::CreateDirectory(dirPath);
1394         CHECK_AND_RETURN_RET_LOG(ret, E_CHECK_DIR_FAIL, "Create Dir Failed! dirPath=%{private}s",
1395             dirPath.c_str());
1396     }
1397     return E_OK;
1398 }
1399 
CreateAssetPathById(int32_t fileId,int32_t mediaType,const string & extension,string & filePath)1400 int32_t MediaLibraryAssetOperations::CreateAssetPathById(int32_t fileId, int32_t mediaType,
1401     const string &extension, string &filePath)
1402 {
1403     string mediaDirPath;
1404     GetAssetRootDir(mediaType, mediaDirPath);
1405     if (mediaDirPath.empty()) {
1406         return E_INVALID_VALUES;
1407     }
1408 
1409     int32_t bucketNum = 0;
1410     int32_t errCode = CreateAssetBucket(fileId, bucketNum);
1411     if (errCode != E_OK) {
1412         return errCode;
1413     }
1414 
1415     string realName;
1416     errCode = CreateAssetRealName(fileId, mediaType, extension, realName);
1417     if (errCode != E_OK) {
1418         return errCode;
1419     }
1420 
1421     string dirPath = ROOT_MEDIA_DIR + mediaDirPath + to_string(bucketNum);
1422     errCode = PrepareAssetDir(dirPath);
1423     if (errCode != E_OK) {
1424         return errCode;
1425     }
1426 
1427     filePath = dirPath + "/" + realName;
1428     return E_OK;
1429 }
1430 
1431 const std::unordered_map<std::string, std::vector<VerifyFunction>>
1432     AssetInputParamVerification::UPDATE_VERIFY_PARAM_MAP = {
1433     { MediaColumn::MEDIA_ID, { Forbidden } },
1434     { MediaColumn::MEDIA_FILE_PATH, { Forbidden } },
1435     { MediaColumn::MEDIA_SIZE, { Forbidden } },
1436     { MediaColumn::MEDIA_TITLE, { IsStringNotNull } },
1437     { MediaColumn::MEDIA_NAME, { IsStringNotNull } },
1438     { MediaColumn::MEDIA_TYPE, { Forbidden } },
1439     { MediaColumn::MEDIA_MIME_TYPE, { Forbidden } },
1440     { MediaColumn::MEDIA_OWNER_PACKAGE, { Forbidden } },
1441     { MediaColumn::MEDIA_PACKAGE_NAME, { Forbidden } },
1442     { MediaColumn::MEDIA_DEVICE_NAME, { Forbidden } },
1443     { MediaColumn::MEDIA_DATE_MODIFIED, { Forbidden } },
1444     { MediaColumn::MEDIA_DATE_ADDED, { Forbidden } },
1445     { MediaColumn::MEDIA_DATE_TAKEN, { Forbidden } },
1446     { MediaColumn::MEDIA_TIME_VISIT, { IsInt64 } },
1447     { MediaColumn::MEDIA_DURATION, { Forbidden } },
1448     { MediaColumn::MEDIA_TIME_PENDING, { IsInt64, IsUniqueValue } },
1449     { MediaColumn::MEDIA_IS_FAV, { IsBool, IsUniqueValue } },
1450     { MediaColumn::MEDIA_DATE_TRASHED, { IsInt64, IsUniqueValue } },
1451     { MediaColumn::MEDIA_DATE_DELETED, { IsInt64, IsUniqueValue } },
1452     { MediaColumn::MEDIA_HIDDEN, { IsBool, IsUniqueValue } },
1453     { MediaColumn::MEDIA_PARENT_ID, { IsInt64, IsBelowApi9 } },
1454     { MediaColumn::MEDIA_RELATIVE_PATH, { IsString, IsBelowApi9 } },
1455     { MediaColumn::MEDIA_VIRTURL_PATH, { Forbidden } },
1456     { PhotoColumn::PHOTO_ORIENTATION, { IsInt64, IsBelowApi9 } },
1457     { PhotoColumn::PHOTO_LATITUDE, { Forbidden } },
1458     { PhotoColumn::PHOTO_LONGITUDE, { Forbidden } },
1459     { PhotoColumn::PHOTO_HEIGHT, { Forbidden } },
1460     { PhotoColumn::PHOTO_WIDTH, { Forbidden } },
1461     { PhotoColumn::PHOTO_LCD_VISIT_TIME, { IsInt64 } },
1462     { AudioColumn::AUDIO_ALBUM, { Forbidden } },
1463     { AudioColumn::AUDIO_ARTIST, { Forbidden } },
1464     { PhotoColumn::CAMERA_SHOT_KEY, { Forbidden } },
1465     { PhotoColumn::PHOTO_USER_COMMENT, { IsString } },
1466 };
1467 
CheckParamForUpdate(MediaLibraryCommand & cmd)1468 bool AssetInputParamVerification::CheckParamForUpdate(MediaLibraryCommand &cmd)
1469 {
1470     ValuesBucket &values = cmd.GetValueBucket();
1471     map<string, ValueObject> valuesMap;
1472     values.GetAll(valuesMap);
1473     for (auto &iter : valuesMap) {
1474         if (UPDATE_VERIFY_PARAM_MAP.find(iter.first) == UPDATE_VERIFY_PARAM_MAP.end()) {
1475             MEDIA_ERR_LOG("param [%{public}s] is not allowed", iter.first.c_str());
1476             return false;
1477         }
1478         for (auto &verifyFunc : UPDATE_VERIFY_PARAM_MAP.at(iter.first)) {
1479             if (!verifyFunc(iter.second, cmd)) {
1480                 MEDIA_ERR_LOG("verify param [%{public}s] failed", iter.first.c_str());
1481                 return false;
1482             }
1483         }
1484     }
1485     return true;
1486 }
1487 
Forbidden(ValueObject & value,MediaLibraryCommand & cmd)1488 bool AssetInputParamVerification::Forbidden(ValueObject &value, MediaLibraryCommand &cmd)
1489 {
1490     return false;
1491 }
1492 
IsInt32(ValueObject & value,MediaLibraryCommand & cmd)1493 bool AssetInputParamVerification::IsInt32(ValueObject &value, MediaLibraryCommand &cmd)
1494 {
1495     if (value.GetType() == ValueObjectType::TYPE_INT) {
1496         return true;
1497     }
1498     return false;
1499 }
1500 
IsInt64(ValueObject & value,MediaLibraryCommand & cmd)1501 bool AssetInputParamVerification::IsInt64(ValueObject &value, MediaLibraryCommand &cmd)
1502 {
1503     if (value.GetType() == ValueObjectType::TYPE_INT) {
1504         return true;
1505     }
1506     return false;
1507 }
1508 
IsBool(ValueObject & value,MediaLibraryCommand & cmd)1509 bool AssetInputParamVerification::IsBool(ValueObject &value, MediaLibraryCommand &cmd)
1510 {
1511     if (value.GetType() == ValueObjectType::TYPE_BOOL) {
1512         return true;
1513     }
1514     if (value.GetType() == ValueObjectType::TYPE_INT) {
1515         int32_t ret;
1516         value.GetInt(ret);
1517         if (ret == 0 || ret == 1) {
1518             return true;
1519         }
1520     }
1521     return false;
1522 }
1523 
IsString(ValueObject & value,MediaLibraryCommand & cmd)1524 bool AssetInputParamVerification::IsString(ValueObject &value, MediaLibraryCommand &cmd)
1525 {
1526     if (value.GetType() == ValueObjectType::TYPE_STRING) {
1527         return true;
1528     }
1529     return false;
1530 }
1531 
IsDouble(ValueObject & value,MediaLibraryCommand & cmd)1532 bool AssetInputParamVerification::IsDouble(ValueObject &value, MediaLibraryCommand &cmd)
1533 {
1534     if (value.GetType() == ValueObjectType::TYPE_DOUBLE) {
1535         return true;
1536     }
1537     return false;
1538 }
1539 
IsBelowApi9(ValueObject & value,MediaLibraryCommand & cmd)1540 bool AssetInputParamVerification::IsBelowApi9(ValueObject &value, MediaLibraryCommand &cmd)
1541 {
1542     if (cmd.GetApi() == MediaLibraryApi::API_OLD) {
1543         return true;
1544     }
1545     return false;
1546 }
1547 
IsStringNotNull(ValueObject & value,MediaLibraryCommand & cmd)1548 bool AssetInputParamVerification::IsStringNotNull(ValueObject &value, MediaLibraryCommand &cmd)
1549 {
1550     if (value.GetType() != ValueObjectType::TYPE_STRING) {
1551         return false;
1552     }
1553     string str;
1554     value.GetString(str);
1555     if (str.empty()) {
1556         return false;
1557     }
1558     return true;
1559 }
1560 
IsUniqueValue(ValueObject & value,MediaLibraryCommand & cmd)1561 bool AssetInputParamVerification::IsUniqueValue(ValueObject &value, MediaLibraryCommand &cmd)
1562 {
1563     // whether this is the unique value in ValuesBucket
1564     map<string, ValueObject> valuesMap;
1565     cmd.GetValueBucket().GetAll(valuesMap);
1566     if (valuesMap.size() != 1) {
1567         return false;
1568     }
1569     return true;
1570 }
1571 
CreateThumbnail(const string & uri,const string & path,bool isSync)1572 static void CreateThumbnail(const string &uri, const string &path, bool isSync)
1573 {
1574     if (ThumbnailService::GetInstance() == nullptr) {
1575         return;
1576     }
1577     if (!uri.empty()) {
1578         int32_t err = ThumbnailService::GetInstance()->CreateThumbnail(uri, path, true);
1579         if (err != E_SUCCESS) {
1580             MEDIA_ERR_LOG("ThumbnailService CreateThumbnail failed : %{public}d", err);
1581         }
1582     }
1583 }
1584 
OnScanFinished(const int32_t status,const string & uri,const string & path)1585 int32_t MediaLibraryAssetOperations::ScanAssetCallback::OnScanFinished(const int32_t status,
1586     const string &uri, const string &path)
1587 {
1588     if (status == E_SCANNED) {
1589         MEDIA_DEBUG_LOG("Asset is scannned");
1590         return E_OK;
1591     } else if (status != E_OK) {
1592         MEDIA_ERR_LOG("Scan is failed, status = %{public}d, skip create thumbnail", status);
1593         return status;
1594     }
1595 
1596     string fileId = MediaLibraryDataManagerUtils::GetIdFromUri(uri);
1597     int32_t type = MediaFileUtils::GetMediaType(path);
1598     InvalidateThumbnail(fileId, type);
1599     CreateThumbnail(uri, path, this->isCreateThumbSync);
1600     return E_OK;
1601 }
1602 } // namespace Media
1603 } // namespace OHOS
1604