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