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