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