• 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 #include <sstream>
23 
24 #include "directory_ex.h"
25 #include "file_asset.h"
26 #include "media_app_uri_permission_column.h"
27 #include "media_column.h"
28 #include "media_exif.h"
29 #include "media_file_utils.h"
30 #include "media_file_uri.h"
31 #include "media_log.h"
32 #include "media_scanner_manager.h"
33 #include "media_unique_number_column.h"
34 #include "medialibrary_album_operations.h"
35 #include "medialibrary_async_worker.h"
36 #include "medialibrary_audio_operations.h"
37 #include "medialibrary_bundle_manager.h"
38 #include "medialibrary_command.h"
39 #include "medialibrary_common_utils.h"
40 #include "medialibrary_data_manager.h"
41 #include "medialibrary_data_manager_utils.h"
42 #include "medialibrary_db_const.h"
43 #include "medialibrary_errno.h"
44 #include "medialibrary_inotify.h"
45 #include "medialibrary_notify.h"
46 #include "medialibrary_photo_operations.h"
47 #include "medialibrary_rdb_transaction.h"
48 #include "medialibrary_rdb_utils.h"
49 #include "medialibrary_rdbstore.h"
50 #include "medialibrary_tracer.h"
51 #include "medialibrary_type_const.h"
52 #include "medialibrary_unistore_manager.h"
53 #include "media_privacy_manager.h"
54 #include "mimetype_utils.h"
55 #include "multistages_capture_manager.h"
56 #include "enhancement_manager.h"
57 #include "permission_utils.h"
58 #include "rdb_errno.h"
59 #include "rdb_predicates.h"
60 #include "rdb_store.h"
61 #include "rdb_utils.h"
62 #include "result_set_utils.h"
63 #include "thumbnail_service.h"
64 #include "uri_permission_manager_client.h"
65 #include "userfile_manager_types.h"
66 #include "value_object.h"
67 #include "values_bucket.h"
68 #include "medialibrary_formmap_operations.h"
69 #include "medialibrary_vision_operations.h"
70 #include "dfx_manager.h"
71 #include "dfx_const.h"
72 #include "moving_photo_file_utils.h"
73 
74 using namespace std;
75 using namespace OHOS::NativeRdb;
76 
77 namespace OHOS {
78 namespace Media {
79 mutex g_uniqueNumberLock;
80 
81 const string DEFAULT_IMAGE_NAME = "IMG_";
82 const string DEFAULT_VIDEO_NAME = "VID_";
83 const string DEFAULT_AUDIO_NAME = "AUD_";
84 constexpr int32_t NO_DESENSITIZE = 3;
85 const string PHOTO_ALBUM_URI_PREFIX = "file://media/PhotoAlbum/";
86 
87 constexpr int32_t ORIENTATION_0 = 1;
88 constexpr int32_t ORIENTATION_90 = 6;
89 constexpr int32_t ORIENTATION_180 = 3;
90 constexpr int32_t ORIENTATION_270 = 8;
91 
HandleInsertOperation(MediaLibraryCommand & cmd)92 int32_t MediaLibraryAssetOperations::HandleInsertOperation(MediaLibraryCommand &cmd)
93 {
94     int errCode = E_ERR;
95     switch (cmd.GetOprnType()) {
96         case OperationType::CREATE:
97             errCode = CreateOperation(cmd);
98             break;
99         case OperationType::CLOSE:
100             errCode = CloseOperation(cmd);
101             break;
102         case OperationType::COMMIT_EDIT:
103             errCode = MediaLibraryPhotoOperations::CommitEditInsert(cmd);
104             if (errCode == E_SUCCESS) {
105                 MediaLibraryVisionOperations::EditCommitOperation(cmd);
106             }
107             break;
108         case OperationType::REVERT_EDIT:
109             errCode = MediaLibraryPhotoOperations::RevertToOrigin(cmd);
110             if (errCode == E_SUCCESS) {
111                 MediaLibraryVisionOperations::EditCommitOperation(cmd);
112             }
113             break;
114         case OperationType::SUBMIT_CACHE:
115             errCode = MediaLibraryPhotoOperations::SubmitCache(cmd);
116             break;
117         case OperationType::ADD_FILTERS:
118             errCode = MediaLibraryPhotoOperations::AddFilters(cmd);
119             break;
120         case OperationType::SCAN_WITHOUT_ALBUM_UPDATE:
121             errCode = MediaLibraryPhotoOperations::ScanFileWithoutAlbumUpdate(cmd);
122             break;
123         case OperationType::FINISH_REQUEST_PICTURE:
124             errCode = MediaLibraryPhotoOperations::FinishRequestPicture(cmd);
125             break;
126         default:
127             MEDIA_ERR_LOG("unknown operation type %{public}d", cmd.GetOprnType());
128             break;
129     }
130     return errCode;
131 }
132 
CreateOperation(MediaLibraryCommand & cmd)133 int32_t MediaLibraryAssetOperations::CreateOperation(MediaLibraryCommand &cmd)
134 {
135     // CreateAsset specify type
136     switch (cmd.GetOprnObject()) {
137         case OperationObject::FILESYSTEM_PHOTO:
138             return MediaLibraryPhotoOperations::Create(cmd);
139         case OperationObject::FILESYSTEM_AUDIO:
140             return MediaLibraryAudioOperations::Create(cmd);
141         case OperationObject::FILESYSTEM_ASSET:
142             MEDIA_ERR_LOG("create asset by FileSysetm_Asset is deperated");
143             return E_INVALID_VALUES;
144         default:
145             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
146             return E_INVALID_VALUES;
147     }
148 }
149 
DeleteOperation(MediaLibraryCommand & cmd)150 int32_t MediaLibraryAssetOperations::DeleteOperation(MediaLibraryCommand &cmd)
151 {
152     // delete Asset specify type
153     switch (cmd.GetOprnObject()) {
154         case OperationObject::FILESYSTEM_PHOTO:
155             return MediaLibraryPhotoOperations::Delete(cmd);
156         case OperationObject::FILESYSTEM_AUDIO:
157             return MediaLibraryAudioOperations::Delete(cmd);
158         case OperationObject::FILESYSTEM_ASSET:
159             MEDIA_ERR_LOG("delete asset by FILESYSTEM_ASSET is deperated");
160             return E_INVALID_VALUES;
161         default:
162             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
163             return E_INVALID_VALUES;
164     }
165 }
166 
QueryOperation(MediaLibraryCommand & cmd,const vector<string> & columns)167 shared_ptr<NativeRdb::ResultSet> MediaLibraryAssetOperations::QueryOperation(
168     MediaLibraryCommand &cmd, const vector<string> &columns)
169 {
170     // query asset specify type
171     switch (cmd.GetOprnObject()) {
172         case OperationObject::FILESYSTEM_PHOTO:
173             return MediaLibraryPhotoOperations::Query(cmd, columns);
174         case OperationObject::FILESYSTEM_AUDIO:
175             return MediaLibraryAudioOperations::Query(cmd, columns);
176         case OperationObject::FILESYSTEM_ASSET:
177             MEDIA_ERR_LOG("api9 operation is not finished");
178             return nullptr;
179         case OperationObject::PAH_MOVING_PHOTO:
180             return MediaLibraryPhotoOperations::ScanMovingPhoto(cmd, columns);
181         default:
182             MEDIA_ERR_LOG("error operation objec: %{public}d", cmd.GetOprnObject());
183             return nullptr;
184     }
185 }
186 
UpdateOperation(MediaLibraryCommand & cmd)187 int32_t MediaLibraryAssetOperations::UpdateOperation(MediaLibraryCommand &cmd)
188 {
189     if (!AssetInputParamVerification::CheckParamForUpdate(cmd)) {
190         return E_INVALID_VALUES;
191     }
192 
193     switch (cmd.GetOprnObject()) {
194         case OperationObject::PAH_PHOTO:
195         case OperationObject::PAH_VIDEO:
196         case OperationObject::FILESYSTEM_PHOTO:
197             return MediaLibraryPhotoOperations::Update(cmd);
198         case OperationObject::FILESYSTEM_AUDIO:
199             return MediaLibraryAudioOperations::Update(cmd);
200         case OperationObject::FILESYSTEM_ASSET:
201             MEDIA_ERR_LOG("create asset by FILESYSTEM_ASSET is deperated");
202             return E_INVALID_VALUES;
203         default:
204             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
205             return E_INVALID_VALUES;
206     }
207 }
208 
OpenOperation(MediaLibraryCommand & cmd,const string & mode)209 int32_t MediaLibraryAssetOperations::OpenOperation(MediaLibraryCommand &cmd, const string &mode)
210 {
211     MediaLibraryTracer tracer;
212     tracer.Start("MediaLibraryAssetOperations::OpenOperation");
213 
214     // Open specify type
215     switch (cmd.GetOprnObject()) {
216         case OperationObject::FILESYSTEM_PHOTO:
217             return MediaLibraryPhotoOperations::Open(cmd, mode);
218         case OperationObject::FILESYSTEM_AUDIO:
219             return MediaLibraryAudioOperations::Open(cmd, mode);
220         case OperationObject::HIGHLIGHT_COVER:
221             return MediaLibraryAssetOperations::OpenHighlightCover(cmd, mode);
222         case OperationObject::HIGHLIGHT_URI:
223             return MediaLibraryAssetOperations::OpenHighlightVideo(cmd, mode);
224         case OperationObject::FILESYSTEM_ASSET:
225             MEDIA_ERR_LOG("open by FILESYSTEM_ASSET is deperated");
226             return E_INVALID_VALUES;
227         default:
228             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
229             return E_INVALID_VALUES;
230     }
231 }
232 
CloseOperation(MediaLibraryCommand & cmd)233 int32_t MediaLibraryAssetOperations::CloseOperation(MediaLibraryCommand &cmd)
234 {
235     // Close specify type
236     switch (cmd.GetOprnObject()) {
237         case OperationObject::FILESYSTEM_PHOTO:
238             return MediaLibraryPhotoOperations::Close(cmd);
239         case OperationObject::FILESYSTEM_AUDIO:
240             return MediaLibraryAudioOperations::Close(cmd);
241         case OperationObject::FILESYSTEM_ASSET:
242             MEDIA_ERR_LOG("close by FILESYSTEM_ASSET is deperated");
243             return E_INVALID_VALUES;
244         default:
245             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
246             return E_INVALID_VALUES;
247     }
248 }
249 
DropAllTables(const shared_ptr<MediaLibraryRdbStore> rdbStore)250 static int32_t DropAllTables(const shared_ptr<MediaLibraryRdbStore> rdbStore)
251 {
252     string dropSqlRowName = "drop_table_and_view_sql";
253     string queryDropSql =
254         "SELECT 'DROP ' || type || ' IF EXISTS ' || name || ';' as " + dropSqlRowName +
255         " FROM sqlite_master" +
256         " WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%';";
257     auto dropSqlsResultSet = rdbStore->QuerySql(queryDropSql);
258     if (dropSqlsResultSet == nullptr) {
259         MEDIA_ERR_LOG("query Drop Sql failed");
260         return E_HAS_DB_ERROR;
261     }
262     vector<string> dropSqlsVec;
263     while (dropSqlsResultSet->GoToNextRow() == NativeRdb::E_OK) {
264         int32_t columnIndex = 0;
265         if (dropSqlsResultSet->GetColumnIndex(dropSqlRowName, columnIndex) != NativeRdb::E_OK) {
266             MEDIA_ERR_LOG("Get drop_table_and_view_sql column failed");
267             return E_HAS_DB_ERROR;
268         }
269         string sql;
270         if (dropSqlsResultSet->GetString(columnIndex, sql) != NativeRdb::E_OK) {
271             MEDIA_ERR_LOG("Get drop_table_and_view_sql sql failed");
272             return E_HAS_DB_ERROR;
273         }
274         if (!sql.empty()) {
275             dropSqlsVec.push_back(sql);
276         }
277     }
278 
279     for (const auto &dropSql : dropSqlsVec) {
280         rdbStore->ExecuteSql(dropSql);
281     }
282     return E_OK;
283 }
284 
DeleteToolOperation(MediaLibraryCommand & cmd)285 int32_t MediaLibraryAssetOperations::DeleteToolOperation(MediaLibraryCommand &cmd)
286 {
287     auto valuesBucket = cmd.GetValueBucket();
288     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
289     if (rdbStore == nullptr) {
290         MEDIA_ERR_LOG("Can not get rdb store");
291         return E_HAS_DB_ERROR;
292     }
293 
294     int32_t errCode = DropAllTables(rdbStore);
295     if (errCode != E_OK) {
296         MEDIA_ERR_LOG("Drop table failed, errCode=%{public}d", errCode);
297         return errCode;
298     }
299     errCode = rdbStore->DataCallBackOnCreate();
300     if (errCode != E_OK) {
301         MEDIA_ERR_LOG("DataCallBackOnCreate failed, errCode=%{public}d", errCode);
302         return errCode;
303     }
304     MediaLibraryRdbStore::ResetAnalysisTables();
305     MediaLibraryRdbStore::ResetSearchTables();
306     const static vector<string> DELETE_DIR_LIST = {
307         ROOT_MEDIA_DIR + PHOTO_BUCKET,
308         ROOT_MEDIA_DIR + AUDIO_BUCKET,
309         ROOT_MEDIA_DIR + CAMERA_DIR_VALUES,
310         ROOT_MEDIA_DIR + VIDEO_DIR_VALUES,
311         ROOT_MEDIA_DIR + PIC_DIR_VALUES,
312         ROOT_MEDIA_DIR + AUDIO_DIR_VALUES,
313         ROOT_MEDIA_DIR + ".thumbs",
314         ROOT_MEDIA_DIR + ".editData"
315     };
316 
317     for (const string &dir : DELETE_DIR_LIST) {
318         if (!MediaFileUtils::DeleteDir(dir)) {
319             MEDIA_ERR_LOG("Delete dir %{public}s failed", dir.c_str());
320             continue;
321         }
322         if (!MediaFileUtils::CreateDirectory(dir)) {
323             MEDIA_ERR_LOG("Create dir %{public}s failed", dir.c_str());
324         };
325     }
326 
327     string photoThumbsPath = ROOT_MEDIA_DIR + ".thumbs/Photo";
328     if (!MediaFileUtils::CreateDirectory(photoThumbsPath)) {
329         MEDIA_ERR_LOG("Create dir %{public}s failed", photoThumbsPath.c_str());
330     };
331 
332     return E_OK;
333 }
334 
CheckOprnObject(OperationObject object)335 static bool CheckOprnObject(OperationObject object)
336 {
337     const set<OperationObject> validOprnObjectet = {
338         OperationObject::FILESYSTEM_PHOTO,
339         OperationObject::FILESYSTEM_AUDIO
340     };
341     if (validOprnObjectet.find(object) == validOprnObjectet.end()) {
342         MEDIA_ERR_LOG("input OperationObject %{public}d error!", object);
343         return false;
344     }
345     return true;
346 }
347 
GetOprnObjectByMediaType(int32_t type)348 static OperationObject GetOprnObjectByMediaType(int32_t type)
349 {
350     switch (type) {
351         case MediaType::MEDIA_TYPE_IMAGE:
352         case MediaType::MEDIA_TYPE_VIDEO: {
353             return OperationObject::FILESYSTEM_PHOTO;
354         }
355         case MediaType::MEDIA_TYPE_AUDIO: {
356             return OperationObject::FILESYSTEM_AUDIO;
357         }
358         case MediaType::MEDIA_TYPE_FILE: {
359             return OperationObject::FILESYSTEM_ASSET;
360         }
361         default: {
362             return OperationObject::UNKNOWN_OBJECT;
363         }
364     }
365 }
366 
FetchFileAssetFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns)367 static shared_ptr<FileAsset> FetchFileAssetFromResultSet(
368     const shared_ptr<NativeRdb::ResultSet> &resultSet, const vector<string> &columns)
369 {
370     int32_t count = 0;
371     int32_t currentRowIndex = 0;
372     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "resultSet is nullptr");
373     CHECK_AND_RETURN_RET_LOG(
374         resultSet->GetRowCount(count) == NativeRdb::E_OK, nullptr, "Cannot get row count of resultset");
375     CHECK_AND_RETURN_RET_LOG(
376         resultSet->GetRowIndex(currentRowIndex) == NativeRdb::E_OK, nullptr, "Cannot get row index of resultset");
377     CHECK_AND_RETURN_RET_LOG(currentRowIndex >= 0 && currentRowIndex < count, nullptr, "Invalid row index");
378 
379     auto fileAsset = make_shared<FileAsset>();
380     for (const auto &column : columns) {
381         int32_t columnIndex = 0;
382         CHECK_AND_RETURN_RET_LOG(resultSet->GetColumnIndex(column, columnIndex) == NativeRdb::E_OK,
383             nullptr, "Can not get column %{private}s index", column.c_str());
384         CHECK_AND_RETURN_RET_LOG(FILEASSET_MEMBER_MAP.find(column) != FILEASSET_MEMBER_MAP.end(), nullptr,
385             "Can not find column %{private}s from member map", column.c_str());
386         int32_t memberType = FILEASSET_MEMBER_MAP.at(column);
387         switch (memberType) {
388             case MEMBER_TYPE_INT32: {
389                 int32_t value = 0;
390                 CHECK_AND_RETURN_RET_LOG(resultSet->GetInt(columnIndex, value) == NativeRdb::E_OK, nullptr,
391                     "Can not get int value from column %{private}s", column.c_str());
392                 auto &map = fileAsset->GetMemberMap();
393                 map[column] = value;
394                 break;
395             }
396             case MEMBER_TYPE_INT64: {
397                 int64_t value = 0;
398                 CHECK_AND_RETURN_RET_LOG(resultSet->GetLong(columnIndex, value) == NativeRdb::E_OK, nullptr,
399                     "Can not get long value from column %{private}s", column.c_str());
400                 auto &map = fileAsset->GetMemberMap();
401                 map[column] = value;
402                 break;
403             }
404             case MEMBER_TYPE_STRING: {
405                 string value;
406                 CHECK_AND_RETURN_RET_LOG(resultSet->GetString(columnIndex, value) == NativeRdb::E_OK, nullptr,
407                     "Can not get string value from column %{private}s", column.c_str());
408                 auto &map = fileAsset->GetMemberMap();
409                 map[column] = value;
410                 break;
411             }
412         }
413     }
414     return fileAsset;
415 }
416 
GetAssetFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns)417 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetAssetFromResultSet(
418     const shared_ptr<NativeRdb::ResultSet> &resultSet, const vector<string> &columns)
419 {
420     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "resultSet is nullptr");
421     int32_t count = 0;
422     CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, nullptr,
423         "Cannot get row count of resultset");
424     CHECK_AND_RETURN_RET_LOG(count == 1, nullptr, "ResultSet count is %{public}d, not 1", count);
425     CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, nullptr, "Cannot go to first row");
426     return FetchFileAssetFromResultSet(resultSet, columns);
427 }
428 
GetAssetVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns,vector<shared_ptr<FileAsset>> & fileAssetVector)429 static int32_t GetAssetVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet,
430     const vector<string> &columns, vector<shared_ptr<FileAsset>> &fileAssetVector)
431 {
432     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "resultSet is nullptr");
433     int32_t count = 0;
434     CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
435         "Cannot get row count of resultset");
436     CHECK_AND_RETURN_RET_LOG(count > 0, E_HAS_DB_ERROR, "ResultSet count is %{public}d", count);
437 
438     fileAssetVector.reserve(count);
439     for (int32_t i = 0; i < count; i++) {
440         CHECK_AND_RETURN_RET_LOG(
441             resultSet->GoToNextRow() == NativeRdb::E_OK, E_HAS_DB_ERROR, "Failed to go to next row");
442         auto fileAsset = FetchFileAssetFromResultSet(resultSet, columns);
443         CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "Failed to fetch fileAsset from resultSet");
444         fileAssetVector.push_back(fileAsset);
445     }
446     return E_OK;
447 }
448 
GetFileAssetFromDb(const string & column,const string & value,OperationObject oprnObject,const vector<string> & columns,const string & networkId)449 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetFromDb(const string &column,
450     const string &value, OperationObject oprnObject, const vector<string> &columns, const string &networkId)
451 {
452     MediaLibraryTracer tracer;
453     tracer.Start("MediaLibraryAssetOperations::GetFileAssetFromDb");
454     if (!CheckOprnObject(oprnObject) || column.empty() || value.empty()) {
455         return nullptr;
456     }
457 
458     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
459     if (rdbStore == nullptr) {
460         return nullptr;
461     }
462 
463     MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, networkId);
464     cmd.GetAbsRdbPredicates()->EqualTo(column, value);
465 
466     auto resultSet = rdbStore->Query(cmd, columns);
467     if (resultSet == nullptr) {
468         return nullptr;
469     }
470     return GetAssetFromResultSet(resultSet, columns);
471 }
472 
QueryByPredicates(AbsPredicates & predicates,OperationObject oprnObject,const vector<string> & columns,const string & networkId)473 static shared_ptr<NativeRdb::ResultSet> QueryByPredicates(AbsPredicates &predicates,
474     OperationObject oprnObject, const vector<string> &columns, const string &networkId)
475 {
476     if (!CheckOprnObject(oprnObject)) {
477         return nullptr;
478     }
479 
480     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
481     if (rdbStore == nullptr) {
482         return nullptr;
483     }
484 
485     MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, networkId);
486     cmd.GetAbsRdbPredicates()->SetWhereClause(predicates.GetWhereClause());
487     cmd.GetAbsRdbPredicates()->SetWhereArgs(predicates.GetWhereArgs());
488     cmd.GetAbsRdbPredicates()->SetOrder(predicates.GetOrder());
489     return rdbStore->Query(cmd, columns);
490 }
491 
GetFileAssetFromDb(AbsPredicates & predicates,OperationObject oprnObject,const vector<string> & columns,const string & networkId)492 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetFromDb(AbsPredicates &predicates,
493     OperationObject oprnObject, const vector<string> &columns, const string &networkId)
494 {
495     auto resultSet = QueryByPredicates(predicates, oprnObject, columns, networkId);
496     if (resultSet == nullptr) {
497         return nullptr;
498     }
499     return GetAssetFromResultSet(resultSet, columns);
500 }
501 
GetFileAssetVectorFromDb(AbsPredicates & predicates,OperationObject oprnObject,vector<shared_ptr<FileAsset>> & fileAssetVector,const vector<string> & columns,const string & networkId)502 int32_t MediaLibraryAssetOperations::GetFileAssetVectorFromDb(AbsPredicates &predicates, OperationObject oprnObject,
503     vector<shared_ptr<FileAsset>> &fileAssetVector, const vector<string> &columns, const string &networkId)
504 {
505     auto resultSet = QueryByPredicates(predicates, oprnObject, columns, networkId);
506     if (resultSet == nullptr) {
507         return E_HAS_DB_ERROR;
508     }
509     return GetAssetVectorFromResultSet(resultSet, columns, fileAssetVector);
510 }
511 
GetFileAssetByUri(const string & uri,bool isPhoto,const std::vector<std::string> & columns,const string & pendingStatus)512 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetByUri(const string &uri, bool isPhoto,
513     const std::vector<std::string> &columns, const string &pendingStatus)
514 {
515     if (uri.empty()) {
516         MEDIA_ERR_LOG("fileUri is empty");
517         return nullptr;
518     }
519 
520     string id = MediaFileUtils::GetIdFromUri(uri);
521     if (uri.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
522         return nullptr;
523     }
524     shared_ptr<FileAsset> fileAsset = make_shared<FileAsset>();
525     MediaFileUri fileUri(uri);
526     if (pendingStatus.empty() || !fileUri.IsApi10()) {
527         if (isPhoto) {
528             fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_PHOTO, columns);
529         } else {
530             fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_AUDIO, columns);
531         }
532     } else {
533         string path = MediaFileUri::GetPathFromUri(uri, isPhoto);
534         if (path.empty()) {
535             if (isPhoto) {
536                 fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_PHOTO, columns);
537             } else {
538                 fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_AUDIO, columns);
539             }
540         } else {
541             fileAsset->SetPath(path);
542             fileAsset->SetMediaType(MediaFileUtils::GetMediaType(path));
543             int32_t timePending = stoi(pendingStatus);
544             fileAsset->SetTimePending((timePending > 0) ? MediaFileUtils::UTCTimeSeconds() : timePending);
545         }
546     }
547 
548     if (fileAsset == nullptr) {
549         return nullptr;
550     }
551     if (!isPhoto) {
552         fileAsset->SetMediaType(MediaType::MEDIA_TYPE_AUDIO);
553     }
554     fileAsset->SetId(stoi(id));
555     fileAsset->SetUri(uri);
556     return fileAsset;
557 }
558 
GetVirtualPath(const string & relativePath,const string & displayName)559 static inline string GetVirtualPath(const string &relativePath, const string &displayName)
560 {
561     if (relativePath[relativePath.size() - 1] != SLASH_CHAR) {
562         return relativePath + SLASH_CHAR + displayName;
563     } else {
564         return relativePath + displayName;
565     }
566 }
567 
GetAssetPackageName(const FileAsset & fileAsset,const string & bundleName)568 static string GetAssetPackageName(const FileAsset &fileAsset, const string &bundleName)
569 {
570     if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::SCREENSHOT)) {
571         if (fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE) ||
572             fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_PHOTO)) {
573             return "截图";
574         } else if (fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_VIDEO)) {
575             return "屏幕录制";
576         }
577     }
578     return PermissionUtils::GetPackageNameByBundleName(bundleName);
579 }
580 
HandleDateAdded(const int64_t dateAdded,const MediaType type,ValuesBucket & outValues)581 static void HandleDateAdded(const int64_t dateAdded, const MediaType type, ValuesBucket &outValues)
582 {
583     outValues.PutLong(MediaColumn::MEDIA_DATE_ADDED, dateAdded);
584     if (type != MEDIA_TYPE_PHOTO) {
585         return;
586     }
587     outValues.PutString(PhotoColumn::PHOTO_DATE_YEAR,
588         MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_YEAR_FORMAT, dateAdded));
589     outValues.PutString(PhotoColumn::PHOTO_DATE_MONTH,
590         MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_MONTH_FORMAT, dateAdded));
591     outValues.PutString(PhotoColumn::PHOTO_DATE_DAY,
592         MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_DAY_FORMAT, dateAdded));
593     outValues.PutLong(MediaColumn::MEDIA_DATE_TAKEN, dateAdded);
594 }
595 
HandleCallingPackage(MediaLibraryCommand & cmd,const FileAsset & fileAsset,ValuesBucket & outValues)596 static void HandleCallingPackage(MediaLibraryCommand &cmd, const FileAsset &fileAsset, ValuesBucket &outValues)
597 {
598     if (!fileAsset.GetOwnerPackage().empty() && PermissionUtils::IsNativeSAApp()) {
599         outValues.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, fileAsset.GetOwnerPackage());
600 
601         int32_t callingUid = 0;
602         ValueObject value;
603         if (cmd.GetValueBucket().GetObject(MEDIA_DATA_CALLING_UID, value)) {
604             value.GetInt(callingUid);
605         }
606         outValues.PutString(MediaColumn::MEDIA_OWNER_APPID,
607             PermissionUtils::GetAppIdByBundleName(fileAsset.GetOwnerPackage(), callingUid));
608         outValues.PutString(MediaColumn::MEDIA_PACKAGE_NAME, fileAsset.GetPackageName());
609         return;
610     }
611 
612     string bundleName;
613     ValueObject valueBundleName;
614     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_DB_OWNER_PACKAGE, valueBundleName)) {
615         valueBundleName.GetString(bundleName);
616     }
617     if (bundleName.empty()) {
618         bundleName = cmd.GetBundleName();
619     }
620     outValues.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, bundleName);
621 
622     string appId;
623     ValueObject valueAppId;
624     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_DB_OWNER_APPID, valueAppId)) {
625         valueAppId.GetString(appId);
626     }
627     if (appId.empty()) {
628         appId = PermissionUtils::GetAppIdByBundleName(cmd.GetBundleName());
629     }
630     outValues.PutString(MediaColumn::MEDIA_OWNER_APPID, appId);
631     string packageName;
632     ValueObject valuePackageName;
633     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_DB_PACKAGE_NAME, valuePackageName)) {
634         valuePackageName.GetString(packageName);
635     }
636     if (packageName.empty() && !cmd.GetBundleName().empty()) {
637         packageName = GetAssetPackageName(fileAsset, cmd.GetBundleName());
638     }
639     if (!packageName.empty()) {
640         outValues.PutString(MediaColumn::MEDIA_PACKAGE_NAME, packageName);
641     }
642 }
643 
HandleBurstPhoto(MediaLibraryCommand & cmd,ValuesBucket & outValues,const std::string displayName)644 static void HandleBurstPhoto(MediaLibraryCommand &cmd, ValuesBucket &outValues, const std::string displayName)
645 {
646     if (!PermissionUtils::IsNativeSAApp()) {
647         MEDIA_DEBUG_LOG("do not have permission to set burst_key or burst_cover_level");
648         return;
649     }
650 
651     string burstKey;
652     ValueObject value;
653     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_BURST_KEY, value)) {
654         value.GetString(burstKey);
655     }
656     if (!burstKey.empty()) {
657         outValues.PutString(PhotoColumn::PHOTO_BURST_KEY, burstKey);
658     }
659 
660     int32_t burstCoverLevel = 0;
661     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_BURST_COVER_LEVEL, value)) {
662         value.GetInt(burstCoverLevel);
663     }
664     if (burstCoverLevel != 0) {
665         outValues.PutInt(PhotoColumn::PHOTO_BURST_COVER_LEVEL, burstCoverLevel);
666     }
667     int32_t dirty = static_cast<int32_t>(DirtyTypes::TYPE_NEW);
668     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_DIRTY, value)) {
669         value.GetInt(dirty);
670     }
671     if (dirty != static_cast<int32_t>(DirtyTypes::TYPE_NEW)) {
672         outValues.PutInt(PhotoColumn::PHOTO_DIRTY, dirty);
673     }
674     stringstream result;
675     for (int32_t i = 0; i < static_cast<int32_t>(displayName.length()); i++) {
676         if (isdigit(displayName[i])) {
677             result << displayName[i];
678         }
679     }
680     outValues.Put(PhotoColumn::PHOTO_ID, result.str());
681     outValues.PutInt(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
682 }
683 
HandleIsTemp(MediaLibraryCommand & cmd,ValuesBucket & outValues)684 static void HandleIsTemp(MediaLibraryCommand &cmd, ValuesBucket &outValues)
685 {
686     if (!PermissionUtils::IsNativeSAApp()) {
687         MEDIA_DEBUG_LOG("do not have permission to set is_temp");
688         return;
689     }
690 
691     bool isTemp = 0;
692     ValueObject value;
693     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_IS_TEMP, value)) {
694         value.GetBool(isTemp);
695     }
696     outValues.PutBool(PhotoColumn::PHOTO_IS_TEMP, isTemp);
697     return;
698 }
699 
FillAssetInfo(MediaLibraryCommand & cmd,const FileAsset & fileAsset)700 static void FillAssetInfo(MediaLibraryCommand &cmd, const FileAsset &fileAsset)
701 {
702     // Fill basic file information into DB
703     const string& displayName = fileAsset.GetDisplayName();
704     int64_t nowTime = MediaFileUtils::UTCTimeMilliSeconds();
705     ValuesBucket assetInfo;
706     assetInfo.PutInt(MediaColumn::MEDIA_TYPE, fileAsset.GetMediaType());
707     string extension = ScannerUtils::GetFileExtension(displayName);
708     assetInfo.PutString(MediaColumn::MEDIA_MIME_TYPE,
709         MimeTypeUtils::GetMimeTypeFromExtension(extension));
710     assetInfo.PutString(MediaColumn::MEDIA_FILE_PATH, fileAsset.GetPath());
711     if (cmd.GetApi() == MediaLibraryApi::API_OLD) {
712         assetInfo.PutString(MediaColumn::MEDIA_RELATIVE_PATH,
713             fileAsset.GetRelativePath());
714         assetInfo.PutString(MediaColumn::MEDIA_VIRTURL_PATH,
715             GetVirtualPath(fileAsset.GetRelativePath(), fileAsset.GetDisplayName()));
716     } else {
717         assetInfo.PutLong(MediaColumn::MEDIA_TIME_PENDING, fileAsset.GetTimePending());
718     }
719     assetInfo.PutString(MediaColumn::MEDIA_NAME, displayName);
720     assetInfo.PutString(MediaColumn::MEDIA_TITLE,
721         MediaFileUtils::GetTitleFromDisplayName(displayName));
722     if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) {
723         assetInfo.PutInt(PhotoColumn::PHOTO_SUBTYPE, fileAsset.GetPhotoSubType());
724         assetInfo.PutString(PhotoColumn::CAMERA_SHOT_KEY, fileAsset.GetCameraShotKey());
725         HandleIsTemp(cmd, assetInfo);
726         if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::BURST)) {
727             HandleBurstPhoto(cmd, assetInfo, displayName);
728         }
729     }
730 
731     HandleCallingPackage(cmd, fileAsset, assetInfo);
732 
733     assetInfo.PutString(MediaColumn::MEDIA_DEVICE_NAME, cmd.GetDeviceName());
734     HandleDateAdded(nowTime,
735         cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO ? MEDIA_TYPE_PHOTO : MEDIA_TYPE_DEFAULT,
736         assetInfo);
737     cmd.SetValueBucket(assetInfo);
738 }
739 
GetUriPermissionValuesBucket(string & tableName,ValuesBucket & valuesBucket,string appId,int64_t fileId)740 static void GetUriPermissionValuesBucket(string &tableName, ValuesBucket &valuesBucket,
741     string appId, int64_t fileId)
742 {
743     TableType mediaType;
744     if (tableName == PhotoColumn::PHOTOS_TABLE) {
745         mediaType = TableType::TYPE_PHOTOS;
746     } else {
747         mediaType = TableType::TYPE_AUDIOS;
748     }
749     valuesBucket.Put(AppUriPermissionColumn::FILE_ID, static_cast<int32_t>(fileId));
750     valuesBucket.Put(AppUriPermissionColumn::URI_TYPE, static_cast<int32_t>(mediaType));
751     valuesBucket.Put(AppUriPermissionColumn::PERMISSION_TYPE,
752         AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE);
753     valuesBucket.Put(AppUriPermissionColumn::APP_ID, appId);
754     valuesBucket.Put(AppUriPermissionColumn::DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
755 }
756 
InsertAssetInDb(std::shared_ptr<TransactionOperations> trans,MediaLibraryCommand & cmd,const FileAsset & fileAsset)757 int32_t MediaLibraryAssetOperations::InsertAssetInDb(std::shared_ptr<TransactionOperations> trans,
758     MediaLibraryCommand &cmd, const FileAsset &fileAsset)
759 {
760     // All values inserted in this function are the base property for files
761     if (trans == nullptr) {
762         return E_HAS_DB_ERROR;
763     }
764 
765     if (!fileAsset.GetPath().empty() && MediaFileUtils::IsFileExists(fileAsset.GetPath())) {
766         MEDIA_ERR_LOG("file %{private}s exists now", fileAsset.GetPath().c_str());
767         return E_FILE_EXIST;
768     }
769     int32_t callingUid = 0;
770     ValueObject value;
771     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_CALLING_UID, value)) {
772         value.GetInt(callingUid);
773     }
774     FillAssetInfo(cmd, fileAsset);
775 
776     int64_t outRowId = -1;
777     int32_t errCode = trans->Insert(cmd, outRowId);
778     if (errCode != NativeRdb::E_OK) {
779         MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
780         return E_HAS_DB_ERROR;
781     }
782     string appId;
783     if (PermissionUtils::IsNativeSAApp()) {
784         appId = PermissionUtils::GetAppIdByBundleName(fileAsset.GetOwnerPackage(), callingUid);
785     } else {
786         appId = PermissionUtils::GetAppIdByBundleName(cmd.GetBundleName());
787     }
788     auto fileId = outRowId;
789     string tableName = cmd.GetTableName();
790     ValuesBucket valuesBucket;
791     if (!appId.empty()) {
792         int64_t tmpOutRowId = -1;
793         GetUriPermissionValuesBucket(tableName, valuesBucket, appId, fileId);
794         MediaLibraryCommand cmd(Uri(MEDIALIBRARY_GRANT_URIPERM_URI), valuesBucket);
795         errCode = trans->Insert(cmd, tmpOutRowId);
796         if (errCode != NativeRdb::E_OK) {
797             MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
798             return E_HAS_DB_ERROR;
799         }
800         MEDIA_INFO_LOG("insert uripermission success, rowId = %{public}d", (int)outRowId);
801     }
802     MEDIA_INFO_LOG("insert success, rowId = %{public}d", (int)outRowId);
803     return static_cast<int32_t>(outRowId);
804 }
805 
CheckTypeFromRootDir(const std::string & rootDirName,int32_t type)806 static bool CheckTypeFromRootDir(const std::string &rootDirName, int32_t type)
807 {
808     // "Camera/"
809     if (!strcmp(rootDirName.c_str(), CAMERA_DIR_VALUES.c_str())) {
810         if (type == MEDIA_TYPE_IMAGE || type == MEDIA_TYPE_VIDEO) {
811             return true;
812         }
813     }
814     // "Videos/"
815     if (!strcmp(rootDirName.c_str(), VIDEO_DIR_VALUES.c_str())) {
816         if (type == MEDIA_TYPE_VIDEO) {
817             return true;
818         }
819     }
820     // "Pictures/"
821     if (!strcmp(rootDirName.c_str(), PIC_DIR_VALUES.c_str())) {
822         if (type == MEDIA_TYPE_IMAGE) {
823             return true;
824         }
825     }
826     // "Audios/"
827     if (!strcmp(rootDirName.c_str(), AUDIO_DIR_VALUES.c_str())) {
828         if (type == MEDIA_TYPE_AUDIO) {
829             return true;
830         }
831     }
832     // "Docs/Documents/" and "Docs/Download"
833     if (!strcmp(rootDirName.c_str(), DOCS_PATH.c_str())) {
834         return true;
835     }
836     MEDIA_ERR_LOG("Cannot match rootDir %{private}s and mediaType %{public}d",
837         rootDirName.c_str(), type);
838     return false;
839 }
840 
CheckWithType(bool isContains,const string & displayName,const string & extention,int32_t mediaType)841 int32_t MediaLibraryAssetOperations::CheckWithType(bool isContains, const string &displayName,
842     const string &extention, int32_t mediaType)
843 {
844     string name = isContains ? displayName : extention;
845     int32_t errCode =  isContains ? CheckDisplayNameWithType(name, mediaType) : CheckExtWithType(name, mediaType);
846     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
847         "Failed to Check Dir and extention, (displayName or extention)=%{private}s, mediaType=%{public}d",
848         name.c_str(), mediaType);
849     return errCode;
850 }
851 
CheckDisplayNameWithType(const string & displayName,int32_t mediaType)852 int32_t MediaLibraryAssetOperations::CheckDisplayNameWithType(const string &displayName, int32_t mediaType)
853 {
854     int32_t ret = MediaFileUtils::CheckDisplayName(displayName);
855     CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_INVALID_DISPLAY_NAME, "Check DisplayName failed, "
856         "displayName=%{private}s", displayName.c_str());
857 
858     string ext = MediaFileUtils::GetExtensionFromPath(displayName);
859     CHECK_AND_RETURN_RET_LOG(!ext.empty(), E_INVALID_DISPLAY_NAME, "invalid extension, displayName=%{private}s",
860         displayName.c_str());
861 
862     auto typeFromExt = MediaFileUtils::GetMediaType(displayName);
863     CHECK_AND_RETURN_RET_LOG(typeFromExt == mediaType, E_CHECK_MEDIATYPE_MATCH_EXTENSION_FAIL,
864         "cannot match, mediaType=%{public}d, ext=%{private}s, type from ext=%{public}d",
865         mediaType, ext.c_str(), typeFromExt);
866     return E_OK;
867 }
868 
CheckExtWithType(const string & extention,int32_t mediaType)869 int32_t MediaLibraryAssetOperations::CheckExtWithType(const string &extention, int32_t mediaType)
870 {
871     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extention);
872     auto typeFromExt = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
873     CHECK_AND_RETURN_RET_LOG(typeFromExt == mediaType, E_CHECK_MEDIATYPE_MATCH_EXTENSION_FAIL,
874         "cannot match, mediaType=%{public}d, ext=%{public}s, type from ext=%{public}d",
875         mediaType, extention.c_str(), typeFromExt);
876     return E_OK;
877 }
878 
CheckRelativePathWithType(const string & relativePath,int32_t mediaType)879 int32_t MediaLibraryAssetOperations::CheckRelativePathWithType(const string &relativePath, int32_t mediaType)
880 {
881     int32_t ret = MediaFileUtils::CheckRelativePath(relativePath);
882     CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_INVALID_PATH, "Check relativePath failed, "
883         "relativePath=%{private}s", relativePath.c_str());
884 
885     // get rootdir and check if it match mediatype
886     string rootDirName;
887     MediaFileUtils::GetRootDirFromRelativePath(relativePath, rootDirName);
888     CHECK_AND_RETURN_RET_LOG(!rootDirName.empty(), E_INVALID_PATH, "Cannot get rootdirName");
889 
890     bool isValid = CheckTypeFromRootDir(rootDirName, mediaType);
891     CHECK_AND_RETURN_RET(isValid, E_CHECK_MEDIATYPE_FAIL);
892     return E_OK;
893 }
894 
GetAssetRootDir(int32_t mediaType,string & rootDirPath)895 void MediaLibraryAssetOperations::GetAssetRootDir(int32_t mediaType, string &rootDirPath)
896 {
897     map<int, string> rootDir = {
898         { MEDIA_TYPE_FILE, DOCUMENT_BUCKET + SLASH_CHAR },
899         { MEDIA_TYPE_VIDEO, PHOTO_BUCKET + SLASH_CHAR },
900         { MEDIA_TYPE_IMAGE, PHOTO_BUCKET + SLASH_CHAR },
901         { MEDIA_TYPE_AUDIO, AUDIO_BUCKET + SLASH_CHAR },
902     };
903     if (rootDir.count(mediaType) == 0) {
904         rootDirPath = rootDir[MEDIA_TYPE_FILE];
905     } else {
906         rootDirPath = rootDir[mediaType];
907     }
908 }
909 
SetAssetPathInCreate(FileAsset & fileAsset,std::shared_ptr<TransactionOperations> trans)910 int32_t MediaLibraryAssetOperations::SetAssetPathInCreate(FileAsset &fileAsset,
911     std::shared_ptr<TransactionOperations> trans)
912 {
913     if (!fileAsset.GetPath().empty()) {
914         return E_OK;
915     }
916     string extension = MediaFileUtils::GetExtensionFromPath(fileAsset.GetDisplayName());
917     string filePath;
918     int32_t uniqueId = CreateAssetUniqueId(fileAsset.GetMediaType(), trans);
919     int32_t errCode = CreateAssetPathById(uniqueId, fileAsset.GetMediaType(), extension, filePath);
920     if (errCode != E_OK) {
921         MEDIA_ERR_LOG("Create Asset Path failed, errCode=%{public}d", errCode);
922         return errCode;
923     }
924 
925     // filePath can not be empty
926     fileAsset.SetPath(filePath);
927     return E_OK;
928 }
929 
SetAssetPath(FileAsset & fileAsset,const string & extension,std::shared_ptr<TransactionOperations> trans)930 int32_t MediaLibraryAssetOperations::SetAssetPath(FileAsset &fileAsset, const string &extension,
931     std::shared_ptr<TransactionOperations> trans)
932 {
933     string filePath;
934     int32_t uniqueId = CreateAssetUniqueId(fileAsset.GetMediaType(), trans);
935     int32_t errCode = CreateAssetPathById(uniqueId, fileAsset.GetMediaType(), extension, filePath);
936     if (errCode != E_OK) {
937         MEDIA_ERR_LOG("Create Asset Path failed, errCode=%{public}d", errCode);
938         return errCode;
939     }
940 
941     // filePath can not be empty
942     fileAsset.SetPath(filePath);
943     string fileName = MediaFileUtils::GetFileName(filePath);
944     string displayName = fileName.substr(0, fileName.find('_')) + '_' + fileName.substr(fileName.rfind('_') + 1);
945     fileAsset.SetDisplayName(displayName);
946     return E_OK;
947 }
948 
DeleteAssetInDb(MediaLibraryCommand & cmd)949 int32_t MediaLibraryAssetOperations::DeleteAssetInDb(MediaLibraryCommand &cmd)
950 {
951     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
952     if (rdbStore == nullptr) {
953         return E_HAS_DB_ERROR;
954     }
955 
956     string strDeleteCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
957     if (strDeleteCondition.empty()) {
958         string strRow = cmd.GetOprnFileId();
959         if (strRow.empty() || !MediaLibraryDataManagerUtils::IsNumber(strRow)) {
960             MEDIA_ERR_LOG("MediaLibraryAssetOperations DeleteFile: Index not digit, fileIdStr=%{private}s",
961                 strRow.c_str());
962             return E_INVALID_FILEID;
963         }
964         cmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, strRow);
965     }
966 
967     int32_t deletedRows = E_HAS_DB_ERROR;
968     int32_t result = rdbStore->Delete(cmd, deletedRows);
969     if (result != NativeRdb::E_OK) {
970         MEDIA_ERR_LOG("Delete operation failed. Result %{public}d.", result);
971     }
972 
973     return deletedRows;
974 }
975 
976 
UpdateFileName(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNameChanged)977 int32_t MediaLibraryAssetOperations::UpdateFileName(MediaLibraryCommand &cmd,
978     const shared_ptr<FileAsset> &fileAsset, bool &isNameChanged)
979 {
980     ValuesBucket &values = cmd.GetValueBucket();
981     ValueObject valueObject;
982     string newTitle;
983     string newDisplayName;
984     bool containsTitle = false;
985     bool containsDisplayName = false;
986 
987     if (values.GetObject(MediaColumn::MEDIA_TITLE, valueObject)) {
988         valueObject.GetString(newTitle);
989         containsTitle = true;
990     }
991     if (values.GetObject(MediaColumn::MEDIA_NAME, valueObject)) {
992         valueObject.GetString(newDisplayName);
993         containsDisplayName = true;
994     }
995     if ((!containsTitle) && (!containsDisplayName)) {
996         // do not need to update
997         return E_OK;
998     }
999     if (containsTitle && containsDisplayName &&
1000         (MediaFileUtils::GetTitleFromDisplayName(newDisplayName) != newTitle)) {
1001         MEDIA_ERR_LOG("new displayName [%{private}s] and new title [%{private}s] is not same",
1002             newDisplayName.c_str(), newTitle.c_str());
1003         return E_INVALID_DISPLAY_NAME;
1004     }
1005     if (!containsTitle) {
1006         newTitle = MediaFileUtils::GetTitleFromDisplayName(newDisplayName);
1007     }
1008     if (!containsDisplayName) {
1009         newDisplayName = newTitle + "." + MediaFileUtils::SplitByChar(fileAsset->GetDisplayName(), '.');
1010     }
1011 
1012     int32_t ret = CheckDisplayNameWithType(newDisplayName, fileAsset->GetMediaType());
1013     CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "Input displayName invalid %{private}s", newDisplayName.c_str());
1014     values.PutString(MediaColumn::MEDIA_TITLE, newTitle);
1015     values.PutString(MediaColumn::MEDIA_NAME, newDisplayName);
1016     isNameChanged = true;
1017     return E_OK;
1018 }
1019 
SetUserComment(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1020 int32_t MediaLibraryAssetOperations::SetUserComment(MediaLibraryCommand &cmd,
1021     const shared_ptr<FileAsset> &fileAsset)
1022 {
1023     ValuesBucket &values = cmd.GetValueBucket();
1024     ValueObject valueObject;
1025     string newUserComment;
1026 
1027     if (values.GetObject(PhotoColumn::PHOTO_USER_COMMENT, valueObject)) {
1028         valueObject.GetString(newUserComment);
1029     } else {
1030         return E_OK;
1031     }
1032 
1033     uint32_t err = 0;
1034     SourceOptions opts;
1035     string filePath = fileAsset->GetFilePath();
1036     string extension = MediaFileUtils::GetExtensionFromPath(filePath);
1037     opts.formatHint = "image/" + extension;
1038     std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(filePath, opts, err);
1039     if (err != 0 || imageSource == nullptr) {
1040         MEDIA_ERR_LOG("Failed to obtain image source, err = %{public}d", err);
1041         return E_OK;
1042     }
1043 
1044     string userComment;
1045     err = imageSource->GetImagePropertyString(0, PHOTO_DATA_IMAGE_USER_COMMENT, userComment);
1046     if (err != 0) {
1047         MEDIA_ERR_LOG("Image does not exist user comment in exif, no need to modify");
1048         return E_OK;
1049     }
1050     err = imageSource->ModifyImageProperty(0, PHOTO_DATA_IMAGE_USER_COMMENT, newUserComment, filePath);
1051     if (err != 0) {
1052         MEDIA_ERR_LOG("Modify image property user comment failed");
1053     }
1054 
1055     return E_OK;
1056 }
1057 
UpdateRelativePath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNameChanged)1058 int32_t MediaLibraryAssetOperations::UpdateRelativePath(MediaLibraryCommand &cmd,
1059     const shared_ptr<FileAsset> &fileAsset, bool &isNameChanged)
1060 {
1061     string newRelativePath;
1062     ValuesBucket &values = cmd.GetValueBucket();
1063     ValueObject valueObject;
1064     if (values.GetObject(MediaColumn::MEDIA_RELATIVE_PATH, valueObject)) {
1065         valueObject.GetString(newRelativePath);
1066     } else {
1067         // relativePath is not modified
1068         return E_OK;
1069     }
1070     MediaFileUtils::FormatRelativePath(newRelativePath);
1071 
1072     if (newRelativePath == fileAsset->GetRelativePath()) {
1073         // relativepath has not been modified
1074         return E_OK;
1075     }
1076 
1077     int32_t errCode = CheckRelativePathWithType(newRelativePath, fileAsset->GetMediaType());
1078     if (errCode != E_SUCCESS) {
1079         MEDIA_ERR_LOG("Check RelativePath failed");
1080         return errCode;
1081     }
1082     values.Delete(MediaColumn::MEDIA_RELATIVE_PATH);
1083     values.PutString(MediaColumn::MEDIA_RELATIVE_PATH, newRelativePath);
1084 
1085     isNameChanged = true;
1086     return E_OK;
1087 }
1088 
UpdateVirtualPath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1089 void MediaLibraryAssetOperations::UpdateVirtualPath(MediaLibraryCommand &cmd,
1090     const shared_ptr<FileAsset> &fileAsset)
1091 {
1092     string relativePath;
1093     string displayName;
1094     ValuesBucket &values = cmd.GetValueBucket();
1095     ValueObject valueObject;
1096 
1097     if (values.GetObject(MediaColumn::MEDIA_NAME, valueObject)) {
1098         valueObject.GetString(displayName);
1099     } else {
1100         displayName = fileAsset->GetDisplayName();
1101     }
1102 
1103     if (values.GetObject(MediaColumn::MEDIA_RELATIVE_PATH, valueObject)) {
1104         valueObject.GetString(relativePath);
1105     } else {
1106         relativePath = fileAsset->GetRelativePath();
1107     }
1108 
1109     if (relativePath.back() != '/') {
1110         relativePath += '/';
1111     }
1112     string virtualPath = relativePath + displayName;
1113     values.PutString(MediaColumn::MEDIA_VIRTURL_PATH, virtualPath);
1114 }
1115 
UpdateFileInDb(MediaLibraryCommand & cmd)1116 int32_t MediaLibraryAssetOperations::UpdateFileInDb(MediaLibraryCommand &cmd)
1117 {
1118     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1119     if (rdbStore == nullptr) {
1120         return E_HAS_DB_ERROR;
1121     }
1122 
1123     int32_t updateRows = 0;
1124     int32_t result = rdbStore->Update(cmd, updateRows);
1125     if (result != NativeRdb::E_OK || updateRows <= 0) {
1126         MEDIA_ERR_LOG("Update File failed. Result %{public}d.", result);
1127         return E_HAS_DB_ERROR;
1128     }
1129 
1130     return updateRows;
1131 }
1132 
OpenFileWithPrivacy(const string & filePath,const string & mode,const string & fileId)1133 int32_t MediaLibraryAssetOperations::OpenFileWithPrivacy(const string &filePath, const string &mode,
1134     const string &fileId)
1135 {
1136     std::string absFilePath;
1137     if (!PathToRealPath(filePath, absFilePath)) {
1138         MEDIA_ERR_LOG("Failed to get real path: %{private}s", filePath.c_str());
1139         return E_ERR;
1140     }
1141 
1142     return MediaPrivacyManager(absFilePath, mode, fileId).Open();
1143 }
1144 
SetPendingTime(const shared_ptr<FileAsset> & fileAsset,int64_t pendingTime)1145 static int32_t SetPendingTime(const shared_ptr<FileAsset> &fileAsset, int64_t pendingTime)
1146 {
1147     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1148     if (rdbStore == nullptr) {
1149         return E_HAS_DB_ERROR;
1150     }
1151 
1152     MediaLibraryCommand updatePendingCmd(GetOprnObjectByMediaType(fileAsset->GetMediaType()),
1153         OperationType::UPDATE);
1154     updatePendingCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID,
1155         to_string(fileAsset->GetId()));
1156     ValuesBucket values;
1157     values.PutLong(MediaColumn::MEDIA_TIME_PENDING, pendingTime);
1158     updatePendingCmd.SetValueBucket(values);
1159     int32_t rowId = 0;
1160     int32_t result = rdbStore->Update(updatePendingCmd, rowId);
1161     if (result != NativeRdb::E_OK || rowId <= 0) {
1162         MEDIA_ERR_LOG("Update File pending failed. Result %{public}d.", result);
1163         return E_HAS_DB_ERROR;
1164     }
1165     return E_OK;
1166 }
1167 
CreateFileAndSetPending(const shared_ptr<FileAsset> & fileAsset,int64_t pendingTime)1168 static int32_t CreateFileAndSetPending(const shared_ptr<FileAsset> &fileAsset, int64_t pendingTime)
1169 {
1170     int32_t errCode = MediaFileUtils::CreateAsset(fileAsset->GetPath());
1171     if (errCode != E_OK) {
1172         MEDIA_ERR_LOG("Create asset failed, path=%{private}s", fileAsset->GetPath().c_str());
1173         return errCode;
1174     }
1175 
1176     return SetPendingTime(fileAsset, pendingTime);
1177 }
1178 
SolvePendingStatus(const shared_ptr<FileAsset> & fileAsset,const string & mode)1179 static int32_t SolvePendingStatus(const shared_ptr<FileAsset> &fileAsset, const string &mode)
1180 {
1181     int64_t pendingTime = fileAsset->GetTimePending();
1182     if (pendingTime != 0) {
1183         if (mode == MEDIA_FILEMODE_READONLY) {
1184             MEDIA_ERR_LOG("FileAsset [%{private}s] pending status is %{public}ld and open mode is READ_ONLY",
1185                 fileAsset->GetUri().c_str(), (long) pendingTime);
1186             return E_IS_PENDING_ERROR;
1187         }
1188         string networkId = MediaFileUtils::GetNetworkIdFromUri(fileAsset->GetUri());
1189         if (!networkId.empty()) {
1190             MEDIA_ERR_LOG("Can not open remote [%{private}s] pending file", networkId.c_str());
1191             return E_IS_PENDING_ERROR;
1192         }
1193         if (pendingTime == UNCREATE_FILE_TIMEPENDING) {
1194             int32_t errCode = CreateFileAndSetPending(fileAsset, UNCLOSE_FILE_TIMEPENDING);
1195             return errCode;
1196         }
1197         if (pendingTime == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
1198             int32_t errCode = SetPendingTime(fileAsset, UNCLOSE_FILE_TIMEPENDING);
1199             return errCode;
1200         }
1201     }
1202     return E_OK;
1203 }
1204 
CreateDirectoryAndAsset(const string path)1205 static int32_t CreateDirectoryAndAsset(const string path)
1206 {
1207     string dir = MediaFileUtils::GetParentPath(path);
1208     if (!MediaFileUtils::CreateDirectory(dir)) {
1209         MEDIA_ERR_LOG("Create dir failed, dir=%{private}s", dir.c_str());
1210         return E_INVALID_VALUES;
1211     }
1212     int32_t errCode = MediaFileUtils::CreateAsset(path);
1213     if (errCode != E_OK) {
1214         MEDIA_ERR_LOG("Create asset failed, path=%{private}s", path.c_str());
1215         return errCode;
1216     }
1217     return E_OK;
1218 }
1219 
SolveMovingPhotoVideoCreation(const string & imagePath,const string & mode,bool isMovingPhotoVideo)1220 static int32_t SolveMovingPhotoVideoCreation(const string &imagePath, const string &mode, bool isMovingPhotoVideo)
1221 {
1222     if (mode == MEDIA_FILEMODE_READONLY || !isMovingPhotoVideo) {
1223         return E_OK;
1224     }
1225     string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(imagePath);
1226     if (MediaFileUtils::IsFileExists(videoPath)) {
1227         return E_OK;
1228     }
1229     int32_t errCode = MediaFileUtils::CreateAsset(videoPath);
1230     if (errCode != E_OK) {
1231         MEDIA_ERR_LOG("Create moving photo asset failed, path=%{private}s", videoPath.c_str());
1232         return errCode;
1233     }
1234     return E_OK;
1235 }
1236 
OpenAsset(const shared_ptr<FileAsset> & fileAsset,const string & mode,MediaLibraryApi api,bool isMovingPhotoVideo)1237 int32_t MediaLibraryAssetOperations::OpenAsset(const shared_ptr<FileAsset> &fileAsset, const string &mode,
1238     MediaLibraryApi api, bool isMovingPhotoVideo)
1239 {
1240     MediaLibraryTracer tracer;
1241     tracer.Start("MediaLibraryAssetOperations::OpenAsset");
1242 
1243     if (fileAsset == nullptr) {
1244         return E_INVALID_VALUES;
1245     }
1246 
1247     string lowerMode = mode;
1248     transform(lowerMode.begin(), lowerMode.end(), lowerMode.begin(), ::tolower);
1249     if (!MediaFileUtils::CheckMode(lowerMode)) {
1250         return E_INVALID_MODE;
1251     }
1252 
1253     string path;
1254     if (api == MediaLibraryApi::API_10) {
1255         int32_t errCode = SolvePendingStatus(fileAsset, mode);
1256         if (errCode != E_OK) {
1257             MEDIA_ERR_LOG("Solve pending status failed, errCode=%{public}d", errCode);
1258             return errCode;
1259         }
1260         path = fileAsset->GetPath();
1261         SolveMovingPhotoVideoCreation(path, mode, isMovingPhotoVideo);
1262     } else {
1263         // If below API10, TIME_PENDING is 0 after asset created, so if file is not exist, create an empty one
1264         if (!MediaFileUtils::IsFileExists(fileAsset->GetPath())) {
1265             MEDIA_INFO_LOG("create empty file for %{public}s, path: %{private}s", fileAsset->GetUri().c_str(),
1266                 fileAsset->GetPath().c_str());
1267             int32_t errCode = CreateDirectoryAndAsset(fileAsset->GetPath());
1268             CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
1269         }
1270         path = MediaFileUtils::UpdatePath(fileAsset->GetPath(), fileAsset->GetUri());
1271     }
1272 
1273     string fileId = MediaFileUtils::GetIdFromUri(fileAsset->GetUri());
1274     int32_t fd = OpenFileWithPrivacy(path, lowerMode, fileId);
1275     if (fd < 0) {
1276         MEDIA_ERR_LOG("open file fd %{public}d, errno %{public}d", fd, errno);
1277         return E_HAS_FS_ERROR;
1278     }
1279     tracer.Start("AddWatchList");
1280     if (mode.find(MEDIA_FILEMODE_WRITEONLY) != string::npos && !isMovingPhotoVideo) {
1281         auto watch = MediaLibraryInotify::GetInstance();
1282         if (watch != nullptr) {
1283             MEDIA_DEBUG_LOG("enter inotify, path = %{private}s", path.c_str());
1284             watch->AddWatchList(path, fileAsset->GetUri(), MediaLibraryApi::API_10);
1285         }
1286     }
1287     tracer.Finish();
1288     return fd;
1289 }
1290 
CloseAsset(const shared_ptr<FileAsset> & fileAsset,bool isCreateThumbSync)1291 int32_t MediaLibraryAssetOperations::CloseAsset(const shared_ptr<FileAsset> &fileAsset, bool isCreateThumbSync)
1292 {
1293     if (fileAsset == nullptr) {
1294         return E_INVALID_VALUES;
1295     }
1296 
1297     // remove inotify event since there is close cmd
1298     auto watch = MediaLibraryInotify::GetInstance();
1299     if (watch != nullptr) {
1300         string uri = fileAsset->GetUri();
1301         watch->RemoveByFileUri(uri, MediaLibraryApi::API_10);
1302         MEDIA_DEBUG_LOG("watch RemoveByFileUri, uri:%{private}s", uri.c_str());
1303     }
1304 
1305     string path = fileAsset->GetPath();
1306     // if pending == 0, scan
1307     // if pending == UNCREATE_FILE_TIMEPENDING, not occur under normal conditions
1308     // if pending == UNCLOSE_FILE_TIMEPENDING, set pending = 0 and scan
1309     // if pending == UNOPEN_FILE_COMPONENT_TIMEPENDING, not allowed to close
1310     // if pending is timestamp, do nothing
1311     if (fileAsset->GetTimePending() == 0 || fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
1312         if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
1313             ScanFile(path, isCreateThumbSync, false);
1314         } else {
1315             ScanFile(path, isCreateThumbSync, true);
1316         }
1317         return E_OK;
1318     } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING ||
1319         fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
1320         MEDIA_ERR_LOG("This asset [%{public}d] pending status cannot close", fileAsset->GetId());
1321         return E_IS_PENDING_ERROR;
1322     } else if (fileAsset->GetTimePending() > 0) {
1323         MEDIA_WARN_LOG("This asset [%{public}d] is in pending", fileAsset->GetId());
1324         return E_OK;
1325     } else {
1326         MEDIA_ERR_LOG("This asset [%{public}d] pending status is invalid", fileAsset->GetId());
1327         return E_INVALID_VALUES;
1328     }
1329 }
1330 
OpenHighlightCover(MediaLibraryCommand & cmd,const string & mode)1331 int32_t MediaLibraryAssetOperations::OpenHighlightCover(MediaLibraryCommand &cmd, const string &mode)
1332 {
1333     MediaLibraryTracer tracer;
1334     tracer.Start("MediaLibraryAssetOperations::OpenHighlightCover");
1335     string uriStr = cmd.GetUriStringWithoutSegment();
1336     string path = MediaFileUtils::GetHighlightPath(uriStr);
1337     if (path.length() == 0) {
1338         MEDIA_ERR_LOG("Open highlight cover invalid uri : %{public}s", uriStr.c_str());
1339         return E_INVALID_URI;
1340     }
1341 
1342     shared_ptr<FileAsset> fileAsset = make_shared<FileAsset>();
1343 
1344     fileAsset->SetPath(path);
1345     fileAsset->SetUri(uriStr);
1346 
1347     return OpenAsset(fileAsset, mode, cmd.GetApi(), false);
1348 }
1349 
OpenHighlightVideo(MediaLibraryCommand & cmd,const string & mode)1350 int32_t MediaLibraryAssetOperations::OpenHighlightVideo(MediaLibraryCommand &cmd, const string &mode)
1351 {
1352     MediaLibraryTracer tracer;
1353     tracer.Start("MediaLibraryAssetOperations::OpenHighlightVideo");
1354     string uriStr = cmd.GetUriStringWithoutSegment();
1355     string path = MediaFileUtils::GetHighlightVideoPath(uriStr);
1356     if (path.length() == 0) {
1357         MEDIA_ERR_LOG("Open highlight video invalid uri : %{public}s", uriStr.c_str());
1358         return E_INVALID_URI;
1359     }
1360     shared_ptr<FileAsset> fileAsset = make_shared<FileAsset>();
1361     fileAsset->SetPath(path);
1362     fileAsset->SetUri(uriStr);
1363 
1364     return OpenAsset(fileAsset, mode, cmd.GetApi(), false);
1365 }
1366 
InvalidateThumbnail(const string & fileId,int32_t type)1367 void MediaLibraryAssetOperations::InvalidateThumbnail(const string &fileId, int32_t type)
1368 {
1369     string tableName;
1370     switch (type) {
1371         case MediaType::MEDIA_TYPE_IMAGE:
1372         case MediaType::MEDIA_TYPE_VIDEO: {
1373             tableName = PhotoColumn::PHOTOS_TABLE;
1374             break;
1375         }
1376         case MediaType::MEDIA_TYPE_AUDIO: {
1377             tableName = AudioColumn::AUDIOS_TABLE;
1378             break;
1379         }
1380         default: {
1381             MEDIA_ERR_LOG("Can not match this type %{public}d", type);
1382             return;
1383         }
1384     }
1385     ThumbnailService::GetInstance()->InvalidateThumbnail(fileId, tableName);
1386 }
1387 
ScanFile(const string & path,bool isCreateThumbSync,bool isInvalidateThumb,bool isForceScan,int32_t fileId)1388 void MediaLibraryAssetOperations::ScanFile(const string &path, bool isCreateThumbSync, bool isInvalidateThumb,
1389     bool isForceScan, int32_t fileId)
1390 {
1391     // Force Scan means medialibrary will scan file without checking E_SCANNED
1392     shared_ptr<ScanAssetCallback> scanAssetCallback = make_shared<ScanAssetCallback>();
1393     if (scanAssetCallback == nullptr) {
1394         MEDIA_ERR_LOG("Failed to create scan file callback object");
1395         return;
1396     }
1397     if (isCreateThumbSync) {
1398         scanAssetCallback->SetSync(true);
1399     }
1400     if (!isInvalidateThumb) {
1401         scanAssetCallback->SetIsInvalidateThumb(false);
1402     }
1403 
1404     int ret = MediaScannerManager::GetInstance()->ScanFileSync(path, scanAssetCallback, MediaLibraryApi::API_10,
1405         isForceScan, fileId);
1406     if (ret != 0) {
1407         MEDIA_ERR_LOG("Scan file failed with error: %{public}d", ret);
1408     }
1409 }
1410 
ScanFileWithoutAlbumUpdate(const string & path,bool isCreateThumbSync,bool isInvalidateThumb,bool isForceScan,int32_t fileId)1411 void MediaLibraryAssetOperations::ScanFileWithoutAlbumUpdate(const string &path, bool isCreateThumbSync,
1412     bool isInvalidateThumb, bool isForceScan, int32_t fileId)
1413 {
1414     // Force Scan means medialibrary will scan file without checking E_SCANNED
1415     shared_ptr<ScanAssetCallback> scanAssetCallback = make_shared<ScanAssetCallback>();
1416     if (scanAssetCallback == nullptr) {
1417         MEDIA_ERR_LOG("Failed to create scan file callback object");
1418         return;
1419     }
1420     if (isCreateThumbSync) {
1421         scanAssetCallback->SetSync(true);
1422     }
1423     if (!isInvalidateThumb) {
1424         scanAssetCallback->SetIsInvalidateThumb(false);
1425     }
1426 
1427     int ret = MediaScannerManager::GetInstance()->ScanFileSyncWithoutAlbumUpdate(path, scanAssetCallback,
1428         MediaLibraryApi::API_10, isForceScan, fileId);
1429     if (ret != 0) {
1430         MEDIA_ERR_LOG("Scan file failed with error: %{public}d", ret);
1431     }
1432 }
1433 
GetEditDataDirPath(const string & path)1434 string MediaLibraryAssetOperations::GetEditDataDirPath(const string &path)
1435 {
1436     if (path.length() < ROOT_MEDIA_DIR.length()) {
1437         return "";
1438     }
1439     return MEDIA_EDIT_DATA_DIR + path.substr(ROOT_MEDIA_DIR.length());
1440 }
1441 
GetEditDataSourcePath(const string & path)1442 string MediaLibraryAssetOperations::GetEditDataSourcePath(const string &path)
1443 {
1444     string parentPath = GetEditDataDirPath(path);
1445     if (parentPath.empty()) {
1446         return "";
1447     }
1448     return parentPath + "/source." + MediaFileUtils::GetExtensionFromPath(path);
1449 }
1450 
GetEditDataPath(const string & path)1451 string MediaLibraryAssetOperations::GetEditDataPath(const string &path)
1452 {
1453     string parentPath = GetEditDataDirPath(path);
1454     if (parentPath.empty()) {
1455         return "";
1456     }
1457     return parentPath + "/editdata";
1458 }
1459 
GetEditDataCameraPath(const string & path)1460 string MediaLibraryAssetOperations::GetEditDataCameraPath(const string &path)
1461 {
1462     string parentPath = GetEditDataDirPath(path);
1463     if (parentPath.empty()) {
1464         return "";
1465     }
1466     return parentPath + "/editdata_camera";
1467 }
1468 
GetAssetCacheDir()1469 string MediaLibraryAssetOperations::GetAssetCacheDir()
1470 {
1471     string cacheOwner = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
1472     if (cacheOwner.empty()) {
1473         cacheOwner = "common"; // Create cache file in common dir if there is no bundleName.
1474     }
1475     return MEDIA_CACHE_DIR + cacheOwner;
1476 }
1477 
UpdateAlbumsAndSendNotifyInTrash(AsyncTaskData * data)1478 static void UpdateAlbumsAndSendNotifyInTrash(AsyncTaskData *data)
1479 {
1480     if (data == nullptr) {
1481         return;
1482     }
1483     DeleteNotifyAsyncTaskData* notifyData = static_cast<DeleteNotifyAsyncTaskData*>(data);
1484 
1485     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1486     if (rdbStore == nullptr) {
1487         MEDIA_ERR_LOG("Can not get rdbstore");
1488         return;
1489     }
1490     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore);
1491     MediaLibraryRdbUtils::UpdateUserAlbumByUri(rdbStore, {notifyData->notifyUri});
1492     MediaLibraryRdbUtils::UpdateSourceAlbumByUri(rdbStore, {notifyData->notifyUri});
1493     MediaLibraryRdbUtils::UpdateAnalysisAlbumByUri(rdbStore, {notifyData->notifyUri});
1494 
1495     auto watch = MediaLibraryNotify::GetInstance();
1496     if (watch == nullptr) {
1497         MEDIA_ERR_LOG("Can not get MediaLibraryNotify");
1498         return;
1499     }
1500     if (notifyData->trashDate > 0) {
1501         watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_REMOVE);
1502         watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_ALBUM_REMOVE_ASSET);
1503     } else {
1504         watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_ADD);
1505         watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_ALBUM_ADD_ASSET);
1506     }
1507 
1508     int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
1509     if (trashAlbumId <= 0) {
1510         return;
1511     }
1512     NotifyType type = (notifyData->trashDate > 0) ? NotifyType::NOTIFY_ALBUM_ADD_ASSET :
1513         NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1514     watch->Notify(notifyData->notifyUri, type, trashAlbumId);
1515     vector<int64_t> formIds;
1516     MediaLibraryFormMapOperations::GetFormMapFormId(notifyData->notifyUri, formIds);
1517     if (!formIds.empty()) {
1518         MediaLibraryFormMapOperations::PublishedChange("", formIds, false);
1519     }
1520 }
1521 
SendTrashNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri)1522 int32_t MediaLibraryAssetOperations::SendTrashNotify(MediaLibraryCommand &cmd, int32_t rowId, const string &extraUri)
1523 {
1524     ValueObject value;
1525     int64_t trashDate = 0;
1526     if (!cmd.GetValueBucket().GetObject(PhotoColumn::MEDIA_DATE_TRASHED, value)) {
1527         return E_DO_NOT_NEDD_SEND_NOTIFY;
1528     }
1529 
1530     value.GetLong(trashDate);
1531 
1532     string prefix;
1533     if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) {
1534         prefix = PhotoColumn::PHOTO_URI_PREFIX;
1535     } else if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_AUDIO) {
1536         prefix = AudioColumn::AUDIO_URI_PREFIX;
1537     } else {
1538         return E_OK;
1539     }
1540 
1541     string notifyUri = MediaFileUtils::GetUriByExtrConditions(prefix, to_string(rowId), extraUri);
1542     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
1543     if (asyncWorker == nullptr) {
1544         MEDIA_ERR_LOG("Can not get asyncWorker");
1545         return E_ERR;
1546     }
1547     DeleteNotifyAsyncTaskData* taskData = new (std::nothrow) DeleteNotifyAsyncTaskData();
1548     if (taskData == nullptr) {
1549         MEDIA_ERR_LOG("Failed to new taskData");
1550         return E_ERR;
1551     }
1552     taskData->notifyUri = notifyUri;
1553     taskData->trashDate = trashDate;
1554     shared_ptr<MediaLibraryAsyncTask> notifyAsyncTask = make_shared<MediaLibraryAsyncTask>(
1555         UpdateAlbumsAndSendNotifyInTrash, taskData);
1556     if (notifyAsyncTask != nullptr) {
1557         asyncWorker->AddTask(notifyAsyncTask, true);
1558     } else {
1559         MEDIA_ERR_LOG("Start UpdateAlbumsAndSendNotifyInTrash failed");
1560     }
1561     return E_OK;
1562 }
1563 
SendFavoriteNotify(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset,const string & extraUri)1564 void MediaLibraryAssetOperations::SendFavoriteNotify(MediaLibraryCommand &cmd, shared_ptr<FileAsset> &fileAsset,
1565     const string &extraUri)
1566 {
1567     ValueObject value;
1568     int32_t isFavorite = 0;
1569     if (!cmd.GetValueBucket().GetObject(PhotoColumn::MEDIA_IS_FAV, value)) {
1570         return;
1571     }
1572     value.GetInt(isFavorite);
1573 
1574     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(
1575         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(),
1576         { to_string(PhotoAlbumSubType::FAVORITE) });
1577     CHECK_AND_RETURN_LOG(fileAsset != nullptr, "fileAsset is nullptr");
1578     if (fileAsset->IsHidden()) {
1579         MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(
1580             MediaLibraryUnistoreManager::GetInstance().GetRdbStore(),
1581             { to_string(PhotoAlbumSubType::FAVORITE) });
1582     }
1583 
1584     auto watch = MediaLibraryNotify::GetInstance();
1585     if (cmd.GetOprnObject() != OperationObject::FILESYSTEM_PHOTO) {
1586         return;
1587     }
1588     int favAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::FAVORITE);
1589     if (favAlbumId <= 0) {
1590         return;
1591     }
1592 
1593     NotifyType type = (isFavorite) ? NotifyType::NOTIFY_ALBUM_ADD_ASSET : NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1594     watch->Notify(
1595         MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()), extraUri),
1596         type, favAlbumId);
1597 }
1598 
SendModifyUserCommentNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri)1599 int32_t MediaLibraryAssetOperations::SendModifyUserCommentNotify(MediaLibraryCommand &cmd, int32_t rowId,
1600     const string &extraUri)
1601 {
1602     if (cmd.GetOprnType() != OperationType::SET_USER_COMMENT) {
1603         return E_DO_NOT_NEDD_SEND_NOTIFY;
1604     }
1605 
1606     auto watch = MediaLibraryNotify::GetInstance();
1607     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(rowId), extraUri),
1608         NotifyType::NOTIFY_UPDATE);
1609     return E_OK;
1610 }
1611 
GetAlbumIdByPredicates(const string & whereClause,const vector<string> & whereArgs)1612 int32_t MediaLibraryAssetOperations::GetAlbumIdByPredicates(const string &whereClause, const vector<string> &whereArgs)
1613 {
1614     size_t pos = whereClause.find(PhotoColumn::PHOTO_OWNER_ALBUM_ID);
1615     if (pos == string::npos) {
1616         MEDIA_ERR_LOG("Predicates whereClause is invalid");
1617         return E_ERR;
1618     }
1619     size_t argsIndex = 0;
1620     for (size_t i = 0; i < pos; ++i) {
1621         if (whereClause[i] == '?') {
1622             argsIndex++;
1623         }
1624     }
1625     if (argsIndex > whereArgs.size() - 1) {
1626         MEDIA_ERR_LOG("whereArgs is invalid");
1627         return E_ERR;
1628     }
1629     auto albumId = whereArgs[argsIndex];
1630     if (MediaLibraryDataManagerUtils::IsNumber(albumId)) {
1631         return std::atoi(albumId.c_str());
1632     }
1633     return E_ERR;
1634 }
1635 
UpdateOwnerAlbumIdOnMove(MediaLibraryCommand & cmd,int32_t & targetAlbumId,int32_t & oriAlbumId)1636 void MediaLibraryAssetOperations::UpdateOwnerAlbumIdOnMove(MediaLibraryCommand &cmd,
1637     int32_t &targetAlbumId, int32_t &oriAlbumId)
1638 {
1639     ValueObject value;
1640     if (!cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_OWNER_ALBUM_ID, value)) {
1641         return;
1642     }
1643     value.GetInt(targetAlbumId);
1644     auto whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
1645     auto whereArgs = cmd.GetAbsRdbPredicates()->GetWhereArgs();
1646     oriAlbumId = GetAlbumIdByPredicates(whereClause, whereArgs);
1647 
1648     MediaLibraryRdbUtils::UpdateUserAlbumInternal(
1649         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), { to_string(targetAlbumId),
1650         to_string(oriAlbumId) });
1651     MediaLibraryRdbUtils::UpdateSourceAlbumInternal(
1652         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), { to_string(targetAlbumId),
1653         to_string(oriAlbumId) });
1654     MEDIA_INFO_LOG("Move Assets, ori album id is %{public}d, target album id is %{public}d", oriAlbumId, targetAlbumId);
1655 }
1656 
SetPendingTrue(const shared_ptr<FileAsset> & fileAsset)1657 int32_t MediaLibraryAssetOperations::SetPendingTrue(const shared_ptr<FileAsset> &fileAsset)
1658 {
1659     // time_pending = 0, means file is created, not allowed
1660     // time_pending = UNCREATE_FILE_TIMEPENDING, means file is not created yet, create an empty one
1661     // time_pending = UNCLOSE_FILE_TIMEPENDING, means file is not close yet, set pending time
1662     // time_pending = UNOPEN_FILE_COMPONENT_TIMEPENDING, means file is created but not open, set pending time
1663     // time_pending is timestamp, update it
1664     int64_t timestamp = MediaFileUtils::UTCTimeSeconds();
1665     if (timestamp <= 0) {
1666         MEDIA_ERR_LOG("Get timestamp failed, timestamp:%{public}ld", (long) timestamp);
1667         return E_INVALID_TIMESTAMP;
1668     }
1669     if (fileAsset->GetTimePending() == 0) {
1670         MEDIA_ERR_LOG("fileAsset time_pending is 0, not allowed");
1671         return E_INVALID_VALUES;
1672     } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
1673         int32_t errCode = CreateFileAndSetPending(fileAsset, timestamp);
1674         if (errCode != E_OK) {
1675             MEDIA_ERR_LOG("Create asset failed, id=%{public}d", fileAsset->GetId());
1676             return errCode;
1677         }
1678     } else if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING ||
1679         fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING ||
1680         fileAsset->GetTimePending() > 0) {
1681         int32_t errCode = SetPendingTime(fileAsset, timestamp);
1682         if (errCode != E_OK) {
1683             MEDIA_ERR_LOG("Set pending time failed, id=%{public}d", fileAsset->GetId());
1684             return errCode;
1685         }
1686     } else {
1687         MEDIA_ERR_LOG("fileAsset time_pending is invalid, time_pending:%{public}ld, id=%{public}d",
1688             (long) fileAsset->GetTimePending(), fileAsset->GetId());
1689         return E_INVALID_VALUES;
1690     }
1691 
1692     return E_OK;
1693 }
1694 
SetPendingFalse(const shared_ptr<FileAsset> & fileAsset)1695 int32_t MediaLibraryAssetOperations::SetPendingFalse(const shared_ptr<FileAsset> &fileAsset)
1696 {
1697     // time_pending = 0, only return
1698     // time_pending = UNCREATE_FILE_TIMEPENDING, means file is not created yet, not allowed
1699     // time_pending = UNCLOSE_FILE_TIMEPENDING, means file is not close yet, not allowed
1700     // time_pending = UNOPEN_FILE_COMPONENT_TIMEPENDING, means file is created but not open, not allowed
1701     // time_pending is timestamp, scan and set pending time = 0
1702     if (fileAsset->GetTimePending() == 0) {
1703         return E_OK;
1704     } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
1705         MEDIA_ERR_LOG("file is not created yet, not allowed, id=%{public}d", fileAsset->GetId());
1706         return E_INVALID_VALUES;
1707     } else if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
1708         MEDIA_ERR_LOG("file is not close yet, not allowed, id=%{public}d", fileAsset->GetId());
1709         return E_INVALID_VALUES;
1710     } else if (fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
1711         MEDIA_ERR_LOG("file is created but not open, not allowed, id=%{public}d", fileAsset->GetId());
1712         return E_INVALID_VALUES;
1713     } else if (fileAsset->GetTimePending() > 0) {
1714         ScanFile(fileAsset->GetPath(), true, true);
1715     } else {
1716         MEDIA_ERR_LOG("fileAsset time_pending is invalid, time_pending:%{public}ld, id=%{public}d",
1717             (long) fileAsset->GetTimePending(), fileAsset->GetId());
1718         return E_INVALID_VALUES;
1719     }
1720     return E_OK;
1721 }
1722 
SetPendingStatus(MediaLibraryCommand & cmd)1723 int32_t MediaLibraryAssetOperations::SetPendingStatus(MediaLibraryCommand &cmd)
1724 {
1725     int32_t pendingStatus = 0;
1726     if (!GetInt32FromValuesBucket(cmd.GetValueBucket(), MediaColumn::MEDIA_TIME_PENDING, pendingStatus)) {
1727         return E_INVALID_VALUES;
1728     }
1729 
1730     vector<string> columns = {
1731         MediaColumn::MEDIA_ID,
1732         MediaColumn::MEDIA_FILE_PATH,
1733         MediaColumn::MEDIA_TYPE,
1734         MediaColumn::MEDIA_TIME_PENDING
1735     };
1736     auto fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()), cmd.GetOprnObject(), columns);
1737     if (fileAsset == nullptr) {
1738         return E_INVALID_VALUES;
1739     }
1740     if (pendingStatus == 1) {
1741         return SetPendingTrue(fileAsset);
1742     } else if (pendingStatus == 0) {
1743         return SetPendingFalse(fileAsset);
1744     } else {
1745         MEDIA_ERR_LOG("pendingStatus is invalid, pendingStatus:%{public}d", pendingStatus);
1746         return E_INVALID_VALUES;
1747     }
1748 }
1749 
ConvertMediaPathFromCloudPath(const string & path)1750 static string ConvertMediaPathFromCloudPath(const string &path)
1751 {
1752     // if input path is /storage/cloud/xxx, return /storage/media/local/xxx
1753     string mediaPath = "/storage/media/local/";
1754     string cloudPath = "/storage/cloud/";
1755     string newPath = path;
1756     if (newPath.find(cloudPath) != string::npos) {
1757         newPath.replace(newPath.find(cloudPath), cloudPath.length(), mediaPath);
1758     }
1759     return newPath;
1760 }
1761 
GrantUriPermission(const string & uri,const string & bundleName,const string & path,bool isMovingPhoto)1762 int32_t MediaLibraryAssetOperations::GrantUriPermission(const string &uri, const string &bundleName,
1763     const string &path, bool isMovingPhoto)
1764 {
1765     if (uri.empty() || path.empty()) {
1766         MEDIA_ERR_LOG("uri or path is empty, uri:%{private}s, path:%{private}s", uri.c_str(), path.c_str());
1767         return E_INVALID_VALUES;
1768     }
1769     if (bundleName.empty()) {
1770         MEDIA_WARN_LOG("bundleName is empty, bundleName:%{private}s", bundleName.c_str());
1771         return E_OK;
1772     }
1773     if (!MediaFileUtils::CreateFile(path)) {
1774         MEDIA_ERR_LOG("Can not create file, path: %{private}s, errno: %{public}d", path.c_str(), errno);
1775         return E_HAS_FS_ERROR;
1776     }
1777 
1778     if (isMovingPhoto && !MediaFileUtils::CreateFile(MediaFileUtils::GetMovingPhotoVideoPath(path))) {
1779         MEDIA_ERR_LOG("Failed to create video of moving photo, errno: %{public}d", errno);
1780         return E_HAS_FS_ERROR;
1781     }
1782 
1783     MediaLibraryTracer tracer;
1784     tracer.Start("AddWatchList");
1785     auto watch = MediaLibraryInotify::GetInstance();
1786     if (watch != nullptr) {
1787         MEDIA_DEBUG_LOG("enter inotify, path = %{private}s", path.c_str());
1788         watch->AddWatchList(ConvertMediaPathFromCloudPath(path), uri, MediaLibraryApi::API_10);
1789     }
1790     tracer.Finish();
1791 
1792     return E_OK;
1793 }
1794 
GetInt32FromValuesBucket(const NativeRdb::ValuesBucket & values,const std::string & column,int32_t & value)1795 bool MediaLibraryAssetOperations::GetInt32FromValuesBucket(const NativeRdb::ValuesBucket &values,
1796     const std::string &column, int32_t &value)
1797 {
1798     ValueObject valueObject;
1799     if (values.GetObject(column, valueObject)) {
1800         valueObject.GetInt(value);
1801     } else {
1802         return false;
1803     }
1804     return true;
1805 }
1806 
CreateExtUriForV10Asset(FileAsset & fileAsset)1807 std::string MediaLibraryAssetOperations::CreateExtUriForV10Asset(FileAsset &fileAsset)
1808 {
1809     const std::string &filePath = fileAsset.GetPath();
1810     const std::string &displayName = fileAsset.GetDisplayName();
1811     auto mediaType = fileAsset.GetMediaType();
1812     if (filePath.empty() || displayName.empty() || mediaType < 0) {
1813         MEDIA_ERR_LOG("param invalid, filePath %{private}s or displayName %{private}s invalid failed.",
1814             filePath.c_str(), displayName.c_str());
1815         return "";
1816     }
1817 
1818     string extrUri = MediaFileUtils::GetExtraUri(displayName, filePath);
1819     return MediaFileUtils::GetUriByExtrConditions(ML_FILE_URI_PREFIX + MediaFileUri::GetMediaTypeUri(mediaType,
1820         MEDIA_API_VERSION_V10) + "/", to_string(fileAsset.GetId()), extrUri);
1821 }
1822 
GetStringFromValuesBucket(const NativeRdb::ValuesBucket & values,const std::string & column,string & value)1823 bool MediaLibraryAssetOperations::GetStringFromValuesBucket(const NativeRdb::ValuesBucket &values,
1824     const std::string &column, string &value)
1825 {
1826     ValueObject valueObject;
1827     if (values.GetObject(column, valueObject)) {
1828         valueObject.GetString(value);
1829     } else {
1830         return false;
1831     }
1832     return true;
1833 }
1834 
CreateAssetUniqueId(int32_t type,std::shared_ptr<TransactionOperations> trans)1835 int32_t MediaLibraryAssetOperations::CreateAssetUniqueId(int32_t type,
1836     std::shared_ptr<TransactionOperations> trans)
1837 {
1838     string typeString;
1839     switch (type) {
1840         case MediaType::MEDIA_TYPE_IMAGE:
1841             typeString += IMAGE_ASSET_TYPE;
1842             break;
1843         case MediaType::MEDIA_TYPE_VIDEO:
1844             typeString += VIDEO_ASSET_TYPE;
1845             break;
1846         case MediaType::MEDIA_TYPE_AUDIO:
1847             typeString += AUDIO_ASSET_TYPE;
1848             break;
1849         default:
1850             MEDIA_ERR_LOG("This type %{public}d can not get unique id", type);
1851             return E_INVALID_VALUES;
1852     }
1853 
1854     const string updateSql = "UPDATE " + ASSET_UNIQUE_NUMBER_TABLE + " SET " + UNIQUE_NUMBER +
1855         "=" + UNIQUE_NUMBER + "+1" " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
1856     const string querySql = "SELECT " + UNIQUE_NUMBER + " FROM " + ASSET_UNIQUE_NUMBER_TABLE +
1857         " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
1858 
1859     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1860     if (rdbStore == nullptr) {
1861         return E_HAS_DB_ERROR;
1862     }
1863     lock_guard<mutex> lock(g_uniqueNumberLock);
1864     int32_t errCode;
1865     if (trans == nullptr) {
1866         errCode = rdbStore->ExecuteSql(updateSql);
1867     } else {
1868         errCode = trans->ExecuteSql(updateSql);
1869     }
1870     if (errCode < 0) {
1871         MEDIA_ERR_LOG("execute update unique number failed, ret=%{public}d", errCode);
1872         return errCode;
1873     }
1874 
1875     auto resultSet = rdbStore->QuerySql(querySql);
1876     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1877         return E_HAS_DB_ERROR;
1878     }
1879     return GetInt32Val(UNIQUE_NUMBER, resultSet);
1880 }
1881 
CreateAssetRealName(int32_t fileId,int32_t mediaType,const string & extension,string & name)1882 int32_t MediaLibraryAssetOperations::CreateAssetRealName(int32_t fileId, int32_t mediaType,
1883     const string &extension, string &name)
1884 {
1885     string fileNumStr = to_string(fileId);
1886     if (fileId <= ASSET_MAX_COMPLEMENT_ID) {
1887         size_t fileIdLen = fileNumStr.length();
1888         fileNumStr = ("00" + fileNumStr).substr(fileIdLen - 1);
1889     }
1890 
1891     string mediaTypeStr;
1892     switch (mediaType) {
1893         case MediaType::MEDIA_TYPE_IMAGE:
1894             mediaTypeStr = DEFAULT_IMAGE_NAME;
1895             break;
1896         case MediaType::MEDIA_TYPE_VIDEO:
1897             mediaTypeStr = DEFAULT_VIDEO_NAME;
1898             break;
1899         case MediaType::MEDIA_TYPE_AUDIO:
1900             mediaTypeStr = DEFAULT_AUDIO_NAME;
1901             break;
1902         default:
1903             MEDIA_ERR_LOG("This mediatype %{public}d can not get real name", mediaType);
1904             return E_INVALID_VALUES;
1905     }
1906 
1907     static const int32_t CONFLICT_TIME = 100;
1908     name = mediaTypeStr + to_string(MediaFileUtils::UTCTimeSeconds() + CONFLICT_TIME) + "_" +
1909         fileNumStr + "." + extension;
1910     return E_OK;
1911 }
1912 
PrepareAssetDir(const string & dirPath)1913 static inline int32_t PrepareAssetDir(const string &dirPath)
1914 {
1915     CHECK_AND_RETURN_RET(!dirPath.empty(), E_INVALID_PATH);
1916     if (!MediaFileUtils::IsFileExists(dirPath)) {
1917         bool ret = MediaFileUtils::CreateDirectory(dirPath);
1918         CHECK_AND_RETURN_RET_LOG(ret, E_CHECK_DIR_FAIL, "Create Dir Failed! dirPath=%{private}s",
1919             dirPath.c_str());
1920     }
1921     return E_OK;
1922 }
1923 
CreateAssetPathById(int32_t fileId,int32_t mediaType,const string & extension,string & filePath)1924 int32_t MediaLibraryAssetOperations::CreateAssetPathById(int32_t fileId, int32_t mediaType,
1925     const string &extension, string &filePath)
1926 {
1927     string mediaDirPath;
1928     GetAssetRootDir(mediaType, mediaDirPath);
1929     if (mediaDirPath.empty()) {
1930         return E_INVALID_VALUES;
1931     }
1932 
1933     int32_t bucketNum = 0;
1934     int32_t errCode = MediaFileUri::CreateAssetBucket(fileId, bucketNum);
1935     if (errCode != E_OK) {
1936         return errCode;
1937     }
1938 
1939     string realName;
1940     errCode = CreateAssetRealName(fileId, mediaType, extension, realName);
1941     if (errCode != E_OK) {
1942         return errCode;
1943     }
1944 
1945     string dirPath = ROOT_MEDIA_DIR + mediaDirPath + to_string(bucketNum);
1946     errCode = PrepareAssetDir(dirPath);
1947     if (errCode != E_OK) {
1948         return errCode;
1949     }
1950 
1951     filePath = dirPath + "/" + realName;
1952     return E_OK;
1953 }
1954 
1955 const std::unordered_map<std::string, std::vector<VerifyFunction>>
1956     AssetInputParamVerification::UPDATE_VERIFY_PARAM_MAP = {
1957     { MediaColumn::MEDIA_ID, { Forbidden } },
1958     { MediaColumn::MEDIA_FILE_PATH, { Forbidden } },
1959     { MediaColumn::MEDIA_SIZE, { Forbidden } },
1960     { MediaColumn::MEDIA_TITLE, { IsStringNotNull } },
1961     { MediaColumn::MEDIA_NAME, { IsStringNotNull } },
1962     { MediaColumn::MEDIA_TYPE, { Forbidden } },
1963     { MediaColumn::MEDIA_MIME_TYPE, { Forbidden } },
1964     { MediaColumn::MEDIA_OWNER_PACKAGE, { Forbidden } },
1965     { MediaColumn::MEDIA_OWNER_APPID, { Forbidden } },
1966     { MediaColumn::MEDIA_PACKAGE_NAME, { Forbidden } },
1967     { MediaColumn::MEDIA_DEVICE_NAME, { Forbidden } },
1968     { MediaColumn::MEDIA_DATE_MODIFIED, { Forbidden } },
1969     { MediaColumn::MEDIA_DATE_ADDED, { Forbidden } },
1970     { MediaColumn::MEDIA_DATE_TAKEN, { Forbidden } },
1971     { MediaColumn::MEDIA_DURATION, { Forbidden } },
1972     { MediaColumn::MEDIA_TIME_PENDING, { IsInt64, IsUniqueValue } },
1973     { MediaColumn::MEDIA_IS_FAV, { IsBool, IsUniqueValue } },
1974     { MediaColumn::MEDIA_DATE_TRASHED, { IsInt64, IsUniqueValue } },
1975     { MediaColumn::MEDIA_DATE_DELETED, { IsInt64, IsUniqueValue } },
1976     { MediaColumn::MEDIA_HIDDEN, { IsBool, IsUniqueValue } },
1977     { MediaColumn::MEDIA_PARENT_ID, { IsInt64, IsBelowApi9 } },
1978     { MediaColumn::MEDIA_RELATIVE_PATH, { IsString, IsBelowApi9 } },
1979     { MediaColumn::MEDIA_VIRTURL_PATH, { Forbidden } },
1980     { PhotoColumn::PHOTO_ORIENTATION, { IsInt64, IsBelowApi9 } },
1981     { PhotoColumn::PHOTO_LATITUDE, { Forbidden } },
1982     { PhotoColumn::PHOTO_LONGITUDE, { Forbidden } },
1983     { PhotoColumn::PHOTO_HEIGHT, { Forbidden } },
1984     { PhotoColumn::PHOTO_WIDTH, { Forbidden } },
1985     { PhotoColumn::PHOTO_LCD_VISIT_TIME, { IsInt64 } },
1986     { PhotoColumn::PHOTO_EDIT_TIME, { IsInt64 } },
1987     { AudioColumn::AUDIO_ALBUM, { Forbidden } },
1988     { AudioColumn::AUDIO_ARTIST, { Forbidden } },
1989     { PhotoColumn::CAMERA_SHOT_KEY, { IsString } },
1990     { PhotoColumn::PHOTO_USER_COMMENT, { IsString } },
1991     { PhotoColumn::PHOTO_ID, { IsString } },
1992     { PhotoColumn::PHOTO_QUALITY, { IsInt32 } },
1993     { PhotoColumn::PHOTO_FIRST_VISIT_TIME, { IsInt64 } },
1994     { PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, { IsInt32 } },
1995     { PhotoColumn::PHOTO_SUBTYPE, { IsInt32 } },
1996     { PhotoColumn::MOVING_PHOTO_EFFECT_MODE, { IsInt32 } },
1997     { PhotoColumn::PHOTO_COVER_POSITION, { IsInt64 } },
1998     { PhotoColumn::PHOTO_IS_TEMP, { IsBool } },
1999     { PhotoColumn::PHOTO_DIRTY, { IsInt32 } },
2000     { PhotoColumn::PHOTO_BURST_COVER_LEVEL, { IsInt32 } },
2001     { PhotoColumn::PHOTO_BURST_KEY, { IsString } },
2002     { PhotoColumn::PHOTO_CE_AVAILABLE, { IsInt32 } },
2003     { PhotoColumn::PHOTO_DETAIL_TIME, { IsStringNotNull } },
2004     { PhotoColumn::PHOTO_OWNER_ALBUM_ID, { IsInt32 } },
2005 };
2006 
CheckParamForUpdate(MediaLibraryCommand & cmd)2007 bool AssetInputParamVerification::CheckParamForUpdate(MediaLibraryCommand &cmd)
2008 {
2009     ValuesBucket &values = cmd.GetValueBucket();
2010     map<string, ValueObject> valuesMap;
2011     values.GetAll(valuesMap);
2012     for (auto &iter : valuesMap) {
2013         if (UPDATE_VERIFY_PARAM_MAP.find(iter.first) == UPDATE_VERIFY_PARAM_MAP.end()) {
2014             MEDIA_ERR_LOG("param [%{private}s] is not allowed", iter.first.c_str());
2015             return false;
2016         }
2017         for (auto &verifyFunc : UPDATE_VERIFY_PARAM_MAP.at(iter.first)) {
2018             if (!verifyFunc(iter.second, cmd)) {
2019                 MEDIA_ERR_LOG("verify param [%{private}s] failed", iter.first.c_str());
2020                 return false;
2021             }
2022         }
2023     }
2024     return true;
2025 }
2026 
Forbidden(ValueObject & value,MediaLibraryCommand & cmd)2027 bool AssetInputParamVerification::Forbidden(ValueObject &value, MediaLibraryCommand &cmd)
2028 {
2029     return false;
2030 }
2031 
IsInt32(ValueObject & value,MediaLibraryCommand & cmd)2032 bool AssetInputParamVerification::IsInt32(ValueObject &value, MediaLibraryCommand &cmd)
2033 {
2034     if (value.GetType() == ValueObjectType::TYPE_INT) {
2035         return true;
2036     }
2037     return false;
2038 }
2039 
IsInt64(ValueObject & value,MediaLibraryCommand & cmd)2040 bool AssetInputParamVerification::IsInt64(ValueObject &value, MediaLibraryCommand &cmd)
2041 {
2042     if (value.GetType() == ValueObjectType::TYPE_INT) {
2043         return true;
2044     }
2045     return false;
2046 }
2047 
IsBool(ValueObject & value,MediaLibraryCommand & cmd)2048 bool AssetInputParamVerification::IsBool(ValueObject &value, MediaLibraryCommand &cmd)
2049 {
2050     if (value.GetType() == ValueObjectType::TYPE_BOOL) {
2051         return true;
2052     }
2053     if (value.GetType() == ValueObjectType::TYPE_INT) {
2054         int32_t ret;
2055         value.GetInt(ret);
2056         if (ret == 0 || ret == 1) {
2057             return true;
2058         }
2059     }
2060     return false;
2061 }
2062 
IsString(ValueObject & value,MediaLibraryCommand & cmd)2063 bool AssetInputParamVerification::IsString(ValueObject &value, MediaLibraryCommand &cmd)
2064 {
2065     if (value.GetType() == ValueObjectType::TYPE_STRING) {
2066         return true;
2067     }
2068     return false;
2069 }
2070 
IsDouble(ValueObject & value,MediaLibraryCommand & cmd)2071 bool AssetInputParamVerification::IsDouble(ValueObject &value, MediaLibraryCommand &cmd)
2072 {
2073     if (value.GetType() == ValueObjectType::TYPE_DOUBLE) {
2074         return true;
2075     }
2076     return false;
2077 }
2078 
IsBelowApi9(ValueObject & value,MediaLibraryCommand & cmd)2079 bool AssetInputParamVerification::IsBelowApi9(ValueObject &value, MediaLibraryCommand &cmd)
2080 {
2081     if (cmd.GetApi() == MediaLibraryApi::API_OLD) {
2082         return true;
2083     }
2084     return false;
2085 }
2086 
IsStringNotNull(ValueObject & value,MediaLibraryCommand & cmd)2087 bool AssetInputParamVerification::IsStringNotNull(ValueObject &value, MediaLibraryCommand &cmd)
2088 {
2089     if (value.GetType() != ValueObjectType::TYPE_STRING) {
2090         return false;
2091     }
2092     string str;
2093     value.GetString(str);
2094     if (str.empty()) {
2095         return false;
2096     }
2097     return true;
2098 }
2099 
IsUniqueValue(ValueObject & value,MediaLibraryCommand & cmd)2100 bool AssetInputParamVerification::IsUniqueValue(ValueObject &value, MediaLibraryCommand &cmd)
2101 {
2102     // whether this is the unique value in ValuesBucket
2103     map<string, ValueObject> valuesMap;
2104     cmd.GetValueBucket().GetAll(valuesMap);
2105     if (valuesMap.size() != 1) {
2106         return false;
2107     }
2108     return true;
2109 }
2110 
CreateThumbnailFileScaned(const string & uri,const string & path,bool isSync)2111 static void CreateThumbnailFileScaned(const string &uri, const string &path, bool isSync)
2112 {
2113     if (ThumbnailService::GetInstance() == nullptr) {
2114         return;
2115     }
2116     if (!uri.empty()) {
2117         int32_t err = ThumbnailService::GetInstance()->CreateThumbnailFileScaned(uri, path, isSync);
2118         if (err != E_SUCCESS) {
2119             MEDIA_ERR_LOG("ThumbnailService CreateThumbnailFileScaned failed : %{public}d", err);
2120         }
2121     }
2122 }
2123 
OnScanFinished(const int32_t status,const string & uri,const string & path)2124 int32_t MediaLibraryAssetOperations::ScanAssetCallback::OnScanFinished(const int32_t status,
2125     const string &uri, const string &path)
2126 {
2127     if (status == E_SCANNED) {
2128         MEDIA_DEBUG_LOG("Asset is scannned");
2129         return E_OK;
2130     } else if (status != E_OK) {
2131         MEDIA_ERR_LOG("Scan is failed, status = %{public}d, skip create thumbnail", status);
2132         return status;
2133     }
2134 
2135     string fileId = MediaFileUtils::GetIdFromUri(uri);
2136     int32_t type = MediaFileUtils::GetMediaType(path);
2137     if (this->isInvalidateThumb) {
2138         InvalidateThumbnail(fileId, type);
2139     }
2140     CreateThumbnailFileScaned(uri, path, this->isCreateThumbSync);
2141     string livePhotoCachePath = MovingPhotoFileUtils::GetLivePhotoCachePath(path);
2142     if (MediaFileUtils::IsFileExists(livePhotoCachePath)) {
2143         (void)MediaFileUtils::DeleteFile(livePhotoCachePath);
2144     }
2145     return E_OK;
2146 }
2147 
DeleteFiles(AsyncTaskData * data)2148 static void DeleteFiles(AsyncTaskData *data)
2149 {
2150     MediaLibraryTracer tracer;
2151     tracer.Start("DeleteFiles");
2152     if (data == nullptr) {
2153         return;
2154     }
2155     auto *taskData = static_cast<DeleteFilesTask *>(data);
2156     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(
2157         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), { to_string(PhotoAlbumSubType::TRASH) });
2158 
2159     DfxManager::GetInstance()->HandleDeleteBehavior(DfxType::ALBUM_DELETE_ASSETS, taskData->deleteRows_,
2160         taskData->notifyUris_, taskData->bundleName_);
2161     auto watch = MediaLibraryNotify::GetInstance();
2162     int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
2163     if (trashAlbumId <= 0) {
2164         MEDIA_WARN_LOG("Failed to get trash album id: %{public}d", trashAlbumId);
2165         return;
2166     }
2167     for (const auto &notifyUri : taskData->notifyUris_) {
2168         watch->Notify(MediaFileUtils::Encode(notifyUri), NotifyType::NOTIFY_ALBUM_REMOVE_ASSET, trashAlbumId);
2169     }
2170 
2171     for (size_t i = 0; i < taskData->paths_.size(); i++) {
2172         string filePath = taskData->paths_[i];
2173         if (!MediaFileUtils::DeleteFile(filePath) && (errno != ENOENT)) {
2174             MEDIA_WARN_LOG("Failed to delete file, errno: %{public}d, path: %{private}s", errno, filePath.c_str());
2175         }
2176 
2177         if (taskData->subTypes_[i] == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
2178             // delete video file of moving photo
2179             string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(filePath);
2180             if (!MediaFileUtils::DeleteFile(videoPath) && (errno != ENOENT)) {
2181                 MEDIA_WARN_LOG("Failed to delete video file, errno: %{public}d, path: %{private}s", errno,
2182                     videoPath.c_str());
2183             }
2184         }
2185     }
2186     for (size_t i = 0; i < taskData->ids_.size(); i++) {
2187         ThumbnailService::GetInstance()->InvalidateThumbnail(
2188             taskData->ids_[i], taskData->table_, taskData->paths_[i], taskData->dateTakens_[i]);
2189     }
2190     if (taskData->table_ == PhotoColumn::PHOTOS_TABLE) {
2191         for (const auto &path : taskData->paths_) {
2192             MediaLibraryPhotoOperations::DeleteRevertMessage(path);
2193         }
2194     }
2195 }
2196 
GetIdsAndPaths(const AbsRdbPredicates & predicates,vector<string> & outIds,vector<string> & outPaths,vector<string> & outDateTakens,vector<int32_t> & outSubTypes)2197 int32_t GetIdsAndPaths(const AbsRdbPredicates &predicates,
2198     vector<string> &outIds, vector<string> &outPaths, vector<string> &outDateTakens, vector<int32_t> &outSubTypes)
2199 {
2200     vector<string> columns = {
2201         MediaColumn::MEDIA_ID,
2202         MediaColumn::MEDIA_FILE_PATH,
2203         MediaColumn::MEDIA_DATE_TAKEN,
2204         PhotoColumn::PHOTO_SUBTYPE
2205     };
2206     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
2207     if (resultSet == nullptr) {
2208         return E_HAS_DB_ERROR;
2209     }
2210     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2211         outIds.push_back(
2212             to_string(get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32))));
2213         outPaths.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_FILE_PATH, resultSet,
2214             TYPE_STRING)));
2215         outDateTakens.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_DATE_TAKEN, resultSet,
2216             TYPE_STRING)));
2217         outSubTypes.push_back(
2218             get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_SUBTYPE, resultSet, TYPE_INT32)));
2219     }
2220     return E_OK;
2221 }
2222 
DeleteDbByIds(const string & table,vector<string> & ids,const bool compatible)2223 static inline int32_t DeleteDbByIds(const string &table, vector<string> &ids, const bool compatible)
2224 {
2225     AbsRdbPredicates predicates(table);
2226     predicates.In(MediaColumn::MEDIA_ID, ids);
2227     if (!compatible) {
2228         predicates.GreaterThan(MediaColumn::MEDIA_DATE_TRASHED, to_string(0));
2229     }
2230     return MediaLibraryRdbStore::Delete(predicates);
2231 }
2232 
2233 /**
2234  * @brief Delete files permanently from system.
2235  *
2236  * @param predicates Files to delete.
2237  * @param isAging Whether in aging process.
2238  * @param compatible API8 interfaces can delete files directly without trash.
2239  *   true: Delete files, may including non-trashed files.
2240  *   false: Only delete files that were already trashed.
2241  * @return Return deleted rows
2242  */
DeleteFromDisk(AbsRdbPredicates & predicates,const bool isAging,const bool compatible)2243 int32_t MediaLibraryAssetOperations::DeleteFromDisk(AbsRdbPredicates &predicates,
2244     const bool isAging, const bool compatible)
2245 {
2246     MediaLibraryTracer tracer;
2247     tracer.Start("DeleteFromDisk");
2248     vector<string> whereArgs = predicates.GetWhereArgs();
2249     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
2250     vector<string> agingNotifyUris;
2251     // Query asset uris for notify before delete.
2252     if (isAging) {
2253         MediaLibraryNotify::GetNotifyUris(predicates, agingNotifyUris);
2254     }
2255     vector<string> ids;
2256     vector<string> paths;
2257     vector<string> dateTakens;
2258     vector<int32_t> subTypes;
2259     int32_t deletedRows = 0;
2260     GetIdsAndPaths(predicates, ids, paths, dateTakens, subTypes);
2261     CHECK_AND_RETURN_RET_LOG(!ids.empty(), deletedRows, "Failed to delete files in db, ids size: 0");
2262     // notify deferred processing session to remove image
2263     MultiStagesCaptureManager::RemovePhotos(predicates, false);
2264     // delete cloud enhanacement task
2265     vector<string> photoIds;
2266     EnhancementManager::GetInstance().RemoveTasksInternal(ids, photoIds);
2267     deletedRows = DeleteDbByIds(predicates.GetTableName(), ids, compatible);
2268     if (deletedRows <= 0) {
2269         MEDIA_ERR_LOG("Failed to delete files in db, deletedRows: %{public}d, ids size: %{public}zu",
2270             deletedRows, ids.size());
2271         return deletedRows;
2272     }
2273     MEDIA_INFO_LOG("Delete files in db, deletedRows: %{public}d", deletedRows);
2274     auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
2275     if (asyncWorker == nullptr) {
2276         MEDIA_ERR_LOG("Can not get asyncWorker");
2277         return E_ERR;
2278     }
2279     const vector<string> &notifyUris = isAging ? agingNotifyUris : whereArgs;
2280     string bundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
2281     auto *taskData = new (nothrow) DeleteFilesTask(ids, paths, notifyUris, dateTakens, subTypes,
2282         predicates.GetTableName(), deletedRows, bundleName);
2283     if (taskData == nullptr) {
2284         MEDIA_ERR_LOG("Failed to alloc async data for Delete From Disk!");
2285         return E_ERR;
2286     }
2287     auto deleteFilesTask = make_shared<MediaLibraryAsyncTask>(DeleteFiles, taskData);
2288     if (deleteFilesTask == nullptr) {
2289         MEDIA_ERR_LOG("Failed to create async task for deleting files.");
2290         return E_ERR;
2291     }
2292     asyncWorker->AddTask(deleteFilesTask, true);
2293     return deletedRows;
2294 }
2295 } // namespace Media
2296 } // namespace OHOS
2297