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