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