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