1 /*
2 * Copyright (C) 2021-2022 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 "mtp_medialibrary_manager.h"
17
18 #include <unistd.h>
19 #include "datashare_predicates.h"
20 #include "datashare_abs_result_set.h"
21 #include "fetch_result.h"
22 #include "image_packer.h"
23 #include "image_source.h"
24 #include "mtp_data_utils.h"
25 #include "media_file_utils.h"
26 #include "media_mtp_utils.h"
27 #include "mtp_error_utils.h"
28 #include "media_log.h"
29 #include "media_smart_map_column.h"
30 #include "system_ability_definition.h"
31
32 using namespace std;
33
34 namespace OHOS {
35 namespace Media {
36 constexpr int32_t NORMAL_WIDTH = 256;
37 constexpr int32_t NORMAL_HEIGHT = 256;
38 constexpr int32_t COMPRE_SIZE_LEVEL_1 = 256;
39 constexpr int32_t COMPRE_SIZE_LEVEL_2 = 204800;
40 const string THUMBNAIL_FORMAT = "image/jpeg";
41 static constexpr uint8_t THUMBNAIL_MID = 90;
42 std::shared_ptr<MtpMedialibraryManager> MtpMedialibraryManager::instance_ = nullptr;
43 std::mutex MtpMedialibraryManager::mutex_;
44 shared_ptr<DataShare::DataShareHelper> MtpMedialibraryManager::dataShareHelper_ = nullptr;
MtpMedialibraryManager(void)45 MtpMedialibraryManager::MtpMedialibraryManager(void)
46 {
47 }
48
~MtpMedialibraryManager(void)49 MtpMedialibraryManager::~MtpMedialibraryManager(void)
50 {
51 }
52
GetInstance()53 std::shared_ptr<MtpMedialibraryManager> MtpMedialibraryManager::GetInstance()
54 {
55 if (instance_ == nullptr) {
56 std::lock_guard<std::mutex> lock(mutex_);
57 if (instance_ == nullptr) {
58 instance_ = std::make_shared<MtpMedialibraryManager>();
59 }
60 }
61 return instance_;
62 }
63
Init(const sptr<IRemoteObject> & token)64 void MtpMedialibraryManager::Init(const sptr<IRemoteObject> &token)
65 {
66 if (dataShareHelper_ == nullptr) {
67 dataShareHelper_ = DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
68 }
69 }
70
GetHandles(int32_t parentId,vector<int> & outHandles,MediaType mediaType)71 int32_t MtpMedialibraryManager::GetHandles(int32_t parentId, vector<int> &outHandles, MediaType mediaType)
72 {
73 DataShare::DataSharePredicates predicates;
74 if (mediaType != MEDIA_TYPE_DEFAULT) {
75 predicates.EqualTo(MEDIA_DATA_DB_PARENT_ID, to_string(parentId));
76 } else {
77 predicates.EqualTo(MEDIA_DATA_DB_PARENT_ID, to_string(parentId))->And()->EqualTo(MEDIA_DATA_DB_MEDIA_TYPE,
78 to_string(mediaType));
79 }
80 if (dataShareHelper_ == nullptr) {
81 return MtpErrorUtils::SolveGetHandlesError(E_HAS_DB_ERROR);
82 }
83 Uri uri(MEDIALIBRARY_DATA_URI);
84 vector<string> columns;
85 shared_ptr<DataShare::DataShareResultSet> resultSet = dataShareHelper_->Query(uri, predicates, columns);
86 if (resultSet == nullptr) {
87 return MtpErrorUtils::SolveGetHandlesError(E_NO_SUCH_FILE);
88 }
89 auto count = 0;
90 auto ret = resultSet->GetRowCount(count);
91 if (ret != NativeRdb::E_OK) {
92 MEDIA_ERR_LOG("get rdbstore failed");
93 return MtpErrorUtils::SolveGetHandlesError(E_HAS_DB_ERROR);
94 } else if (count == 0) {
95 MEDIA_ERR_LOG("have no handles");
96 return MtpErrorUtils::SolveGetHandlesError(E_SUCCESS);
97 }
98 unique_ptr<FetchResult<FileAsset>> fetchFileResult = make_unique<FetchResult<FileAsset>>(resultSet);
99 for (int32_t row = 0; row < count; row++) {
100 unique_ptr<FileAsset> fileAsset = fetchFileResult->GetObjectAtPosition(row);
101 outHandles.push_back(fileAsset->GetId());
102 }
103 return MtpErrorUtils::SolveGetHandlesError(E_SUCCESS);
104 }
105
GetHandles(const shared_ptr<MtpOperationContext> & context,shared_ptr<UInt32List> & outHandles)106 int32_t MtpMedialibraryManager::GetHandles(const shared_ptr<MtpOperationContext> &context,
107 shared_ptr<UInt32List> &outHandles)
108 {
109 string extension;
110 MediaType mediaType;
111 CHECK_AND_RETURN_RET_LOG(context != nullptr,
112 MtpErrorUtils::SolveGetHandlesError(E_HAS_DB_ERROR), "context is nullptr");
113 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr,
114 MtpErrorUtils::SolveGetHandlesError(E_HAS_DB_ERROR), "fail to get datasharehelper");
115 int32_t errCode = MtpDataUtils::SolveHandlesFormatData(context->format, extension, mediaType);
116 CHECK_AND_RETURN_RET_LOG(errCode == MTP_SUCCESS,
117 MtpErrorUtils::SolveGetHandlesError(errCode), "fail to SolveHandlesFormatData");
118 DataShare::DataSharePredicates predicates;
119 string whereClause;
120 vector<string> whereArgs;
121 if (mediaType == MEDIA_TYPE_DEFAULT) {
122 whereClause = MEDIA_DATA_DB_PARENT_ID + " = ? AND " + MEDIA_DATA_DB_NAME + " Like ? AND " +
123 MEDIA_DATA_DB_DATE_TRASHED + " = 0 AND " + MEDIA_DATA_DB_MEDIA_TYPE + " != ?";
124 whereArgs = {to_string(context->parent), extension, to_string(MEDIA_TYPE_NOFILE)};
125 } else if (mediaType == MEDIA_TYPE_ALL) {
126 whereClause = MEDIA_DATA_DB_PARENT_ID + " = ? AND " + MEDIA_DATA_DB_DATE_TRASHED +
127 " = 0 AND " + MEDIA_DATA_DB_MEDIA_TYPE + " != ?" ;
128 whereArgs = {to_string(context->parent), to_string(MEDIA_TYPE_NOFILE)};
129 } else {
130 whereClause = MEDIA_DATA_DB_PARENT_ID + " = ? AND " + MEDIA_DATA_DB_MEDIA_TYPE + " = ? AND " +
131 MEDIA_DATA_DB_DATE_TRASHED + " = 0";
132 whereArgs = {to_string(context->parent), to_string(mediaType)};
133 }
134 predicates.SetWhereClause(whereClause);
135 predicates.SetWhereArgs(whereArgs);
136 Uri uri(MEDIALIBRARY_DATA_URI);
137 vector<string> columns;
138 shared_ptr<DataShare::DataShareResultSet> resultSet = dataShareHelper_->Query(uri, predicates, columns);
139 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr,
140 MtpErrorUtils::SolveGetHandlesError(E_NO_SUCH_FILE), "fail to get handles");
141 unique_ptr<FetchResult<FileAsset>> fetchFileResult = make_unique<FetchResult<FileAsset>>(resultSet);
142 auto count = 0;
143 auto ret = resultSet->GetRowCount(count);
144 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK,
145 MtpErrorUtils::SolveGetHandlesError(E_HAS_DB_ERROR), "fail to get GetRowCount");
146 // have no handles is not error(maybe it is really have no files)
147 CHECK_AND_RETURN_RET_LOG(count > 0,
148 MtpErrorUtils::SolveGetHandlesError(E_SUCCESS), "have no handles");
149 unique_ptr<FileAsset> fileAsset = fetchFileResult->GetFirstObject();
150 while (fileAsset != nullptr) {
151 outHandles->push_back(fileAsset->GetId());
152 fileAsset = fetchFileResult->GetNextObject();
153 }
154 return MtpErrorUtils::SolveGetHandlesError(E_SUCCESS);
155 }
156
GetObjectInfo(const shared_ptr<MtpOperationContext> & context,shared_ptr<ObjectInfo> & outObjectInfo)157 int32_t MtpMedialibraryManager::GetObjectInfo(const shared_ptr<MtpOperationContext> &context,
158 shared_ptr<ObjectInfo> &outObjectInfo)
159 {
160 CHECK_AND_RETURN_RET_LOG(context != nullptr,
161 MtpErrorUtils::SolveGetObjectInfoError(E_HAS_DB_ERROR), "context is nullptr");
162 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr,
163 MtpErrorUtils::SolveGetObjectInfoError(E_HAS_DB_ERROR), "fail to get datasharehelper");
164 DataShare::DataSharePredicates predicates;
165 string whereClause = MEDIA_DATA_DB_ID + " = ? AND " + MEDIA_DATA_DB_DATE_TRASHED + " = 0";
166 vector<string> whereArgs = {to_string(context->handle)};
167 predicates.SetWhereClause(whereClause);
168 predicates.SetWhereArgs(whereArgs);
169 Uri uri(MEDIALIBRARY_DATA_URI);
170 vector<string> columns;
171 shared_ptr<DataShare::DataShareResultSet> resultSet = dataShareHelper_->Query(uri, predicates, columns);
172 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr,
173 MtpErrorUtils::SolveGetObjectInfoError(E_NO_SUCH_FILE), "fail to get object set");
174 unique_ptr<FetchResult<FileAsset>> fetchFileResult = make_unique<FetchResult<FileAsset>>(resultSet);
175 auto count = 0;
176 auto ret = resultSet->GetRowCount(count);
177 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK,
178 MtpErrorUtils::SolveGetObjectInfoError(E_HAS_DB_ERROR), "fail to get GetRowCount");
179 // have no object is an error
180 CHECK_AND_RETURN_RET_LOG(count > 0,
181 MtpErrorUtils::SolveGetObjectInfoError(E_NO_SUCH_FILE), "have no handle");
182 unique_ptr<FileAsset> fileAsset = fetchFileResult->GetFirstObject();
183 return SetObjectInfo(fileAsset, outObjectInfo);
184 }
185
SetObjectInfo(const unique_ptr<FileAsset> & fileAsset,shared_ptr<ObjectInfo> & outObjectInfo)186 int32_t MtpMedialibraryManager::SetObjectInfo(const unique_ptr<FileAsset> &fileAsset,
187 shared_ptr<ObjectInfo> &outObjectInfo)
188 {
189 CHECK_AND_RETURN_RET_LOG(outObjectInfo != nullptr,
190 MtpErrorUtils::SolveGetObjectInfoError(E_HAS_DB_ERROR), "outObjectInfo is nullptr");
191 outObjectInfo->handle = fileAsset->GetId();
192 outObjectInfo->name = fileAsset->GetDisplayName();
193 outObjectInfo->size = static_cast<uint32_t>(fileAsset->GetSize()); // need support larger than 4GB file
194 outObjectInfo->parent = static_cast<uint32_t>(fileAsset->GetParent());
195 outObjectInfo->dateCreated = fileAsset->GetDateAdded();
196 outObjectInfo->dateModified = fileAsset->GetDateModified();
197 outObjectInfo->storageID = DEFAULT_STORAGE_ID;
198 if (fileAsset->GetMediaType() == MEDIA_TYPE_ALBUM) {
199 outObjectInfo->format = MTP_FORMAT_ASSOCIATION_CODE;
200 } else if (fileAsset->GetMediaType() == MEDIA_TYPE_IMAGE) {
201 outObjectInfo->thumbCompressedSize = COMPRE_SIZE_LEVEL_1;
202 outObjectInfo->format = MTP_FORMAT_EXIF_JPEG_CODE;
203 outObjectInfo->storageID = DEFAULT_STORAGE_ID;
204 outObjectInfo->imagePixHeight = static_cast<uint32_t>(fileAsset->GetHeight());
205 outObjectInfo->imagePixWidth = static_cast<uint32_t>(fileAsset->GetWidth());
206 outObjectInfo->thumbCompressedSize = COMPRE_SIZE_LEVEL_2;
207 outObjectInfo->thumbFormat = MTP_FORMAT_EXIF_JPEG_CODE;
208 outObjectInfo->thumbPixHeight = NORMAL_HEIGHT;
209 outObjectInfo->thumbPixWidth = NORMAL_WIDTH;
210 }
211 return MtpErrorUtils::SolveGetObjectInfoError(E_SUCCESS);
212 }
213
GetFd(const shared_ptr<MtpOperationContext> & context,int32_t & outFd)214 int32_t MtpMedialibraryManager::GetFd(const shared_ptr<MtpOperationContext> &context, int32_t &outFd)
215 {
216 CHECK_AND_RETURN_RET_LOG(context != nullptr,
217 MtpErrorUtils::SolveGetFdError(E_HAS_DB_ERROR), "context is nullptr");
218 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr,
219 MtpErrorUtils::SolveGetFdError(E_HAS_DB_ERROR), "fail to get datasharehelper");
220 Uri uri(MEDIALIBRARY_DATA_URI + "/" + to_string(context->handle));
221 outFd = dataShareHelper_->OpenFile(uri, MEDIA_FILEMODE_READWRITE);
222 if (outFd > 0) {
223 return MtpErrorUtils::SolveGetFdError(E_SUCCESS);
224 } else {
225 return MtpErrorUtils::SolveGetFdError(E_HAS_FS_ERROR);
226 }
227 }
228
CompressImage(std::unique_ptr<PixelMap> & pixelMap,Size & size,std::vector<uint8_t> & data)229 bool MtpMedialibraryManager::CompressImage(std::unique_ptr<PixelMap> &pixelMap,
230 Size &size, std::vector<uint8_t> &data)
231 {
232 InitializationOptions opts = {
233 .size = size,
234 .pixelFormat = PixelFormat::RGBA_8888,
235 .alphaType = AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL
236 };
237 unique_ptr<PixelMap> compressImage = PixelMap::Create(*pixelMap, opts);
238
239 PackOption option = {
240 .format = THUMBNAIL_FORMAT,
241 .quality = THUMBNAIL_MID,
242 .numberHint = 1
243 };
244
245 data.resize(compressImage->GetByteCount());
246
247 ImagePacker imagePacker;
248 uint32_t errorCode = imagePacker.StartPacking(data.data(), data.size(), option);
249 if (errorCode != E_SUCCESS) {
250 MEDIA_ERR_LOG("Failed to StartPacking %{private}d", errorCode);
251 return false;
252 }
253 errorCode = imagePacker.AddImage(*compressImage);
254 if (errorCode != E_SUCCESS) {
255 MEDIA_ERR_LOG("Failed to StartPacking %{private}d", errorCode);
256 return false;
257 }
258
259 int64_t packedSize = 0;
260 errorCode = imagePacker.FinalizePacking(packedSize);
261 if (errorCode != E_SUCCESS) {
262 MEDIA_ERR_LOG("Failed to StartPacking %{private}d", errorCode);
263 return false;
264 }
265
266 data.resize(packedSize);
267 return true;
268 }
269
GetThumb(const shared_ptr<MtpOperationContext> & context,shared_ptr<UInt8List> & outThumb)270 int32_t MtpMedialibraryManager::GetThumb(const shared_ptr<MtpOperationContext> &context,
271 shared_ptr<UInt8List> &outThumb)
272 {
273 CHECK_AND_RETURN_RET_LOG(context != nullptr, MTP_ERROR_STORE_NOT_AVAILABLE, "context is nullptr");
274 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr,
275 MTP_ERROR_STORE_NOT_AVAILABLE, "fail to get datasharehelper");
276 int fd = 0;
277 GetFd(context, fd);
278 uint32_t errorCode = 0;
279 SourceOptions opts;
280 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(fd, opts, errorCode);
281 DecodeOptions decodeOpts;
282 decodeOpts.desiredSize = {
283 .width = NORMAL_WIDTH,
284 .height = NORMAL_HEIGHT
285 };
286 std::unique_ptr<PixelMap> cropPixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
287 CHECK_AND_RETURN_RET_LOG(cropPixelMap != nullptr, MTP_ERROR_NO_THUMBNAIL_PRESENT, "PixelMap is nullptr");
288 close(fd);
289 Size size = {
290 .width = NORMAL_WIDTH,
291 .height = NORMAL_HEIGHT
292 };
293 CompressImage(cropPixelMap, size, *outThumb);
294 return MTP_SUCCESS;
295 }
296
GetAssetById(const int32_t id,shared_ptr<FileAsset> & outFileAsset)297 int32_t MtpMedialibraryManager::GetAssetById(const int32_t id, shared_ptr<FileAsset> &outFileAsset)
298 {
299 DataShare::DataSharePredicates predicates;
300 string whereClause = MEDIA_DATA_DB_ID + " = ? AND " + MEDIA_DATA_DB_DATE_TRASHED + " = 0";
301 vector<string> whereArgs = {to_string(id)};
302 predicates.SetWhereClause(whereClause);
303 predicates.SetWhereArgs(whereArgs);
304 Uri uri(MEDIALIBRARY_DATA_URI);
305 vector<string> columns;
306 if (dataShareHelper_ == nullptr) {
307 return E_HAS_DB_ERROR;
308 }
309 shared_ptr<DataShare::DataShareResultSet> resultSet = dataShareHelper_->Query(uri, predicates, columns);
310 if (resultSet == nullptr) {
311 return E_NO_SUCH_FILE;
312 }
313 unique_ptr<FetchResult<FileAsset>> fetchFileResult = make_unique<FetchResult<FileAsset>>(resultSet);
314 auto count = 0;
315 auto ret = resultSet->GetRowCount(count);
316 if (ret != NativeRdb::E_OK || count == 0) {
317 MEDIA_ERR_LOG("have no file");
318 return E_NO_SUCH_FILE;
319 }
320 unique_ptr<FileAsset> fileUniAsset = fetchFileResult->GetFirstObject();
321 outFileAsset = move(fileUniAsset);
322 return E_SUCCESS;
323 }
324
GetPathById(const int32_t id,string & outPath)325 int32_t MtpMedialibraryManager::GetPathById(const int32_t id, string &outPath)
326 {
327 shared_ptr<FileAsset> fileAsset;
328 int errCode = GetAssetById(id, fileAsset);
329 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "fileAsset is nullptr, assetId: %{public}d", id);
330 outPath = fileAsset->GetPath();
331 return errCode;
332 }
333
GetIdByPath(const std::string & path,uint32_t & outId)334 int32_t MtpMedialibraryManager::GetIdByPath(const std::string &path, uint32_t &outId)
335 {
336 DataShare::DataSharePredicates predicates;
337 string whereClause = MEDIA_DATA_DB_FILE_PATH + " = ? OR " + MEDIA_DATA_DB_RECYCLE_PATH + " = ?";
338 vector<string> whereArgs = {path, path};
339 predicates.SetWhereClause(whereClause);
340 predicates.SetWhereArgs(whereArgs);
341 Uri uri(MEDIALIBRARY_DATA_URI);
342 vector<string> columns;
343 if (dataShareHelper_ == nullptr) {
344 return E_HAS_DB_ERROR;
345 }
346 shared_ptr<DataShare::DataShareResultSet> resultSet = dataShareHelper_->Query(uri, predicates, columns);
347 if (resultSet == nullptr) {
348 return E_NO_SUCH_FILE;
349 }
350 unique_ptr<FetchResult<FileAsset>> fetchFileResult = make_unique<FetchResult<FileAsset>>(resultSet);
351 auto count = 0;
352 auto ret = resultSet->GetRowCount(count);
353 if (ret != NativeRdb::E_OK || count == 0) {
354 MEDIA_ERR_LOG("have no file");
355 return E_NO_SUCH_FILE;
356 }
357 unique_ptr<FileAsset> fileUniAsset = fetchFileResult->GetFirstObject();
358 outId = static_cast<uint32_t>(fileUniAsset->GetId());
359 return E_SUCCESS;
360 }
361
SendObjectInfo(const std::shared_ptr<MtpOperationContext> & context,uint32_t & outStorageID,uint32_t & outParent,uint32_t & outHandle)362 int32_t MtpMedialibraryManager::SendObjectInfo(const std::shared_ptr<MtpOperationContext> &context,
363 uint32_t &outStorageID, uint32_t &outParent, uint32_t &outHandle)
364 {
365 CHECK_AND_RETURN_RET_LOG(context != nullptr, MTP_ERROR_STORE_NOT_AVAILABLE, "context is nullptr");
366 shared_ptr<FileAsset> fileAsset;
367 int errCode = GetAssetById(context->parent, fileAsset);
368 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS,
369 MtpErrorUtils::SolveSendObjectInfoError(errCode), "fail to GetAssetById");
370 int index = 0;
371 DataShare::DataShareValuesBucket valuesBucket;
372 if (context->format == MTP_FORMAT_ASSOCIATION_CODE) {
373 Uri mkdirUri(MEDIALIBRARY_DATA_URI + SLASH_CHAR + MEDIA_DIROPRN + SLASH_CHAR + MEDIA_DIROPRN_FMS_CREATEDIR);
374 valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH, fileAsset->GetRelativePath() +
375 fileAsset->GetDisplayName() + "/" + context->name + "/");
376 index = dataShareHelper_->Insert(mkdirUri, valuesBucket);
377 } else {
378 MediaType mediaType;
379 errCode = MtpDataUtils::SolveSendObjectFormatData(context->format, mediaType);
380 CHECK_AND_RETURN_RET_LOG(errCode == MTP_SUCCESS, errCode, "fail to SolveSendObjectFormatData");
381 Uri createFileUri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_FILEOPRN + "/" + MEDIA_FILEOPRN_CREATEASSET);
382 valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH,
383 fileAsset->GetRelativePath() + fileAsset->GetDisplayName() + "/");
384 valuesBucket.Put(MEDIA_DATA_DB_NAME, context->name);
385 valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, mediaType);
386 index = dataShareHelper_->Insert(createFileUri, valuesBucket);
387 }
388 CHECK_AND_RETURN_RET_LOG(index > 0,
389 MtpErrorUtils::SolveSendObjectInfoError(E_HAS_DB_ERROR), "fail to create assset");
390 outHandle = static_cast<uint32_t>(index);
391 outStorageID = DEFAULT_STORAGE_ID;
392 outParent = context->parent;
393 return MtpErrorUtils::SolveSendObjectInfoError(E_SUCCESS);
394 }
395
MoveObject(const std::shared_ptr<MtpOperationContext> & context)396 int32_t MtpMedialibraryManager::MoveObject(const std::shared_ptr<MtpOperationContext> &context)
397 {
398 CHECK_AND_RETURN_RET_LOG(context != nullptr, MTP_ERROR_STORE_NOT_AVAILABLE, "context is nullptr");
399 DataShare::DataSharePredicates predicates;
400 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = " + std::to_string(context->handle));
401 DataShare::DataShareValuesBucket valuesBucket;
402 shared_ptr<FileAsset> parentFileAsset;
403 int errCode = GetAssetById(context->parent, parentFileAsset);
404 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS,
405 MtpErrorUtils::SolveMoveObjectError(errCode), "fail to GetAssetById");
406 valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH,
407 parentFileAsset->GetRelativePath() + parentFileAsset->GetDisplayName() + "/");
408 shared_ptr<FileAsset> fileAsset;
409 errCode = GetAssetById(context->handle, fileAsset);
410 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS,
411 MtpErrorUtils::SolveMoveObjectError(errCode), "fail to GetAssetById");
412 valuesBucket.Put(MEDIA_DATA_DB_NAME, fileAsset->GetDisplayName());
413 valuesBucket.Put(MEDIA_DATA_DB_ID, static_cast<int32_t>(context->handle));
414 valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, fileAsset->GetMediaType());
415 Uri updateAssetUri(Media::MEDIALIBRARY_DATA_URI + "/" +
416 Media::MEDIA_FILEOPRN + "/" + Media::MEDIA_FILEOPRN_MODIFYASSET);
417 int changedRows = dataShareHelper_->Update(updateAssetUri, predicates, valuesBucket);
418 return (changedRows > 0) ? MTP_SUCCESS : MtpErrorUtils::SolveMoveObjectError(changedRows);
419 }
420
CopyObject(const std::shared_ptr<MtpOperationContext> & context,uint32_t & outObjectHandle)421 int32_t MtpMedialibraryManager::CopyObject(const std::shared_ptr<MtpOperationContext> &context,
422 uint32_t &outObjectHandle)
423 {
424 CHECK_AND_RETURN_RET_LOG(context != nullptr, MTP_ERROR_INVALID_OBJECTHANDLE, "context is nullptr");
425 DataShare::DataSharePredicates predicates;
426 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = " + std::to_string(context->handle));
427 shared_ptr<FileAsset> parentAsset;
428 int errCode = GetAssetById(context->parent, parentAsset);
429 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS,
430 MtpErrorUtils::SolveCopyObjectError(errCode), "fail to GetAssetById");
431 DataShare::DataShareValuesBucket valuesBucket;
432 valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH,
433 parentAsset->GetRelativePath() + parentAsset->GetDisplayName() + "/");
434 valuesBucket.Put(MEDIA_DATA_DB_ID, static_cast<int32_t>(context->handle));
435 Uri copyAssetUri(Media::MEDIALIBRARY_DATA_URI +
436 "/" + Media::MEDIA_FILEOPRN + "/" + Media::MEDIA_FILEOPRN_COPYASSET);
437 int changedRows = dataShareHelper_->Insert(copyAssetUri, valuesBucket);
438 outObjectHandle = static_cast<uint32_t>(changedRows);
439 return (changedRows > 0) ? MTP_SUCCESS : MtpErrorUtils::SolveCopyObjectError(changedRows);
440 }
441
DeleteObject(const std::shared_ptr<MtpOperationContext> & context)442 int32_t MtpMedialibraryManager::DeleteObject(const std::shared_ptr<MtpOperationContext> &context)
443 {
444 CHECK_AND_RETURN_RET_LOG(context != nullptr, MTP_ERROR_STORE_NOT_AVAILABLE, "context is nullptr");
445 DataShare::DataShareValuesBucket valuesBucket;
446 valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, TRASH_ALBUM_ID_VALUES);
447 valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, static_cast<int32_t>(context->handle));
448 Uri addAsseturi(MEDIALIBRARY_DATA_URI + "/" +
449 MEDIA_SMARTALBUMMAPOPRN + "/" + MEDIA_SMARTALBUMMAPOPRN_ADDSMARTALBUM);
450 int changedRows = dataShareHelper_->Insert(addAsseturi, valuesBucket);
451 return (changedRows > 0) ? MTP_SUCCESS : MtpErrorUtils::SolveCopyObjectError(changedRows);
452 }
453
SetObjectPropValue(const std::shared_ptr<MtpOperationContext> & context)454 int32_t MtpMedialibraryManager::SetObjectPropValue(const std::shared_ptr<MtpOperationContext> &context)
455 {
456 CHECK_AND_RETURN_RET_LOG(context != nullptr, MTP_ERROR_INVALID_OBJECTHANDLE, "context is nullptr");
457 string colName;
458 variant<int64_t, string> colValue;
459 int32_t errCode = MtpDataUtils::SolveSetObjectPropValueData(context, colName, colValue);
460 CHECK_AND_RETURN_RET_LOG(errCode == 0, errCode, "fail to SolveSetObjectPropValueData");
461 DataShare::DataShareValuesBucket valuesBucket;
462 shared_ptr<FileAsset> fileAsset;
463 errCode = GetAssetById(context->handle, fileAsset);
464 string displayName;
465 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS,
466 MtpErrorUtils::SolveObjectPropValueError(errCode), "fail to GetAssetById");
467 if (colName.compare(MEDIA_DATA_DB_PARENT_ID) == 0) {
468 shared_ptr<FileAsset> parentFileAsset;
469 errCode = GetAssetById(get<int64_t>(colValue), parentFileAsset);
470 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS,
471 MtpErrorUtils::SolveObjectPropValueError(errCode), "fail to GetAssetById");
472 valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH,
473 parentFileAsset->GetRelativePath() + parentFileAsset->GetDisplayName() + "/");
474 valuesBucket.Put(MEDIA_DATA_DB_NAME, fileAsset->GetDisplayName());
475 displayName = fileAsset->GetDisplayName();
476 } else {
477 valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH, fileAsset->GetRelativePath());
478 if (!get<string>(colValue).empty()) {
479 displayName = get<string>(colValue);
480 valuesBucket.Put(colName, get<string>(colValue));
481 valuesBucket.Put(MEDIA_DATA_DB_TITLE, get<string>(colValue));
482 } else {
483 valuesBucket.Put(colName, get<int64_t>(colValue));
484 }
485 }
486 MediaType mediaType;
487 MtpDataUtils::GetMediaTypeByName(displayName, mediaType);
488 valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, mediaType);
489 valuesBucket.Put(MEDIA_DATA_DB_ID, static_cast<int32_t>(context->handle));
490 string operationCode = (mediaType != MEDIA_TYPE_ALBUM) ? Media::MEDIA_FILEOPRN : Media::MEDIA_ALBUMOPRN;
491 Uri updateAssetUri(Media::MEDIALIBRARY_DATA_URI +
492 "/" + operationCode + "/" + Media::MEDIA_FILEOPRN_MODIFYASSET);
493 DataShare::DataSharePredicates predicates;
494 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = " + std::to_string(context->handle));
495 int changedRows = dataShareHelper_->Update(updateAssetUri, predicates, valuesBucket);
496 return (changedRows > 0) ? MTP_SUCCESS : MtpErrorUtils::SolveObjectPropValueError(changedRows);
497 }
498
CloseFd(const shared_ptr<MtpOperationContext> & context,int32_t fd)499 int32_t MtpMedialibraryManager::CloseFd(const shared_ptr<MtpOperationContext> &context, int32_t fd)
500 {
501 shared_ptr<FileAsset> fileAsset;
502 int32_t errCode = GetAssetById(context->handle, fileAsset);
503 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS,
504 MtpErrorUtils::SolveCloseFdError(errCode), "fail to GetAssetById");
505 DataShare::DataShareValuesBucket valuesBucket;
506 valuesBucket.Put(MEDIA_DATA_DB_URI, fileAsset->GetUri());
507 Uri closeAssetUri(URI_CLOSE_FILE);
508 if (close(fd) == MTP_SUCCESS) {
509 errCode = dataShareHelper_->Insert(closeAssetUri, valuesBucket);
510 }
511 return MtpErrorUtils::SolveCloseFdError(errCode);
512 }
513
514
GetObjectPropList(const std::shared_ptr<MtpOperationContext> & context,std::shared_ptr<std::vector<Property>> & outProps)515 int32_t MtpMedialibraryManager::GetObjectPropList(const std::shared_ptr<MtpOperationContext> &context,
516 std::shared_ptr<std::vector<Property>> &outProps)
517 {
518 if (context->property == 0) {
519 if (context->groupCode == 0) {
520 MEDIA_ERR_LOG("groupCode error");
521 return MTP_ERROR_PARAMETER_NOT_SUPPORTED;
522 }
523 MEDIA_ERR_LOG("context property = 0");
524 return MTP_ERROR_SPECIFICATION_BY_GROUP_UNSUPPORTED;
525 }
526 if (context->depth == MTP_ALL_DEPTH && (context->handle == 0 || context->handle == MTP_ALL_HANDLE_ID)) {
527 context->handle = MTP_ALL_HANDLE_ID;
528 context->depth = 0;
529 }
530 if (!(context->depth == 0 || context->depth == 1)) {
531 MEDIA_ERR_LOG("depth error");
532 return MTP_ERROR_SPECIFICATION_BY_DEPTH_UNSUPPORTED;
533 }
534 shared_ptr<DataShare::DataShareResultSet> resultSet;
535 if (context->handle != 0) {
536 // Add the requested object if format matches
537 if (context->depth == 0) {
538 if (context->handle == MTP_ALL_HANDLE_ID) {
539 // get root dirs children deep : all:success
540 resultSet = GetAllRootsChildren(context->format);
541 } else {
542 // get handle:success
543 resultSet = GetHandle(context->format, context->handle);
544 }
545 }
546 if (context->depth == 1) {
547 if (context->handle == MTP_ALL_HANDLE_ID) {
548 // get root dirs children deep : 1:success
549 resultSet = GetRootsDepthChildren(context->format);
550 } else {
551 // get handle children and handle deep : 1
552 resultSet = GetHandleDepthChildren(context->format, context->handle);
553 }
554 }
555 } else {
556 // get root dirs children deep : 1:success
557 resultSet = GetRootsDepthChildren(context->format);
558 }
559 int count = 0;
560 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, MTP_ERROR_INVALID_OBJECTHANDLE, "fail to getSet");
561 resultSet->GetRowCount(count);
562 CHECK_AND_RETURN_RET_LOG(count != 0, MTP_ERROR_INVALID_OBJECTHANDLE, "fail to get set count");
563 return MtpDataUtils::GetPropListBySet(context->property, context->format, resultSet, outProps);
564 }
565
GetAllRootsChildren(const uint16_t format)566 shared_ptr<DataShare::DataShareResultSet> MtpMedialibraryManager::GetAllRootsChildren(const uint16_t format)
567 {
568 DataShare::DataSharePredicates predicates;
569 MediaType mediaType;
570 MtpDataUtils::GetMediaTypeByformat(format, mediaType);
571 string whereClause;
572 vector<string> whereArgs;
573 if (mediaType == MEDIA_TYPE_ALL) {
574 whereClause = MEDIA_DATA_DB_DATE_TRASHED + " = ?";
575 whereArgs = {to_string(0)};
576 } else {
577 whereClause = MEDIA_DATA_DB_MEDIA_TYPE + " = ? AND " + MEDIA_DATA_DB_DATE_TRASHED + " = ?";
578 whereArgs = {to_string(mediaType), to_string(0)};
579 }
580 predicates.SetWhereClause(whereClause);
581 predicates.SetWhereArgs(whereArgs);
582 Uri uri(MEDIALIBRARY_DATA_URI);
583 vector<string> columns;
584 return dataShareHelper_->Query(uri, predicates, columns);
585 }
586
GetHandle(const uint16_t format,const uint32_t handle)587 shared_ptr<DataShare::DataShareResultSet> MtpMedialibraryManager::GetHandle(const uint16_t format,
588 const uint32_t handle)
589 {
590 DataShare::DataSharePredicates predicates;
591 MediaType mediaType;
592 MtpDataUtils::GetMediaTypeByformat(format, mediaType);
593 string whereClause;
594 vector<string> whereArgs;
595 if (mediaType == MEDIA_TYPE_ALL) {
596 whereClause = MEDIA_DATA_DB_ID + " = ? AND " + MEDIA_DATA_DB_DATE_TRASHED + " = ?";
597 whereArgs = {to_string(handle), to_string(0)};
598 } else {
599 whereClause = MEDIA_DATA_DB_ID + " = ? AND " +
600 MEDIA_DATA_DB_MEDIA_TYPE + " = ? AND " + MEDIA_DATA_DB_DATE_TRASHED + " = ?";
601 whereArgs = {to_string(handle), to_string(mediaType), to_string(0)};
602 }
603 predicates.SetWhereClause(whereClause);
604 predicates.SetWhereArgs(whereArgs);
605 Uri uri(MEDIALIBRARY_DATA_URI);
606 vector<string> columns;
607 return dataShareHelper_->Query(uri, predicates, columns);
608 }
609
GetRootIdList(std::vector<string> & outRootIdList)610 int32_t MtpMedialibraryManager::GetRootIdList(std::vector<string> &outRootIdList)
611 {
612 DataShare::DataSharePredicates predicates;
613 string whereClause;
614 vector<string> whereArgs = {to_string(0)};
615 whereClause = MEDIA_DATA_DB_PARENT_ID + " = ?";
616 predicates.SetWhereClause(whereClause);
617 predicates.SetWhereArgs(whereArgs);
618 Uri uri(MEDIALIBRARY_DATA_URI);
619 vector<string> columns;
620 shared_ptr<DataShare::DataShareResultSet> resultSet = dataShareHelper_->Query(uri, predicates, columns);
621 auto count = 0;
622 auto ret = resultSet->GetRowCount(count);
623 if (ret != NativeRdb::E_OK || count == 0) {
624 MEDIA_ERR_LOG("have no file");
625 return E_NO_SUCH_FILE;
626 }
627 unique_ptr<FetchResult<FileAsset>> fetchFileResult = make_unique<FetchResult<FileAsset>>(resultSet);
628 for (int32_t row = 0; row < count; row++) {
629 unique_ptr<FileAsset> fileAsset = fetchFileResult->GetObjectAtPosition(row);
630 outRootIdList.push_back(to_string(fileAsset->GetId()));
631 }
632 return E_SUCCESS;
633 }
634
GetRootsDepthChildren(const uint16_t format)635 shared_ptr<DataShare::DataShareResultSet> MtpMedialibraryManager::GetRootsDepthChildren(const uint16_t format)
636 {
637 vector<string> rootIdList;
638 int errCode = GetRootIdList(rootIdList);
639 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS, nullptr, "fail to GetRootIdList");
640 string whereClause;
641 for (size_t row = 0; row < rootIdList.size(); row++) {
642 if (row == 0) {
643 whereClause = MEDIA_DATA_DB_PARENT_ID + " = ?";
644 } else {
645 whereClause = whereClause + " OR " + MEDIA_DATA_DB_PARENT_ID + " = ?";
646 }
647 }
648 whereClause = whereClause + " AND " + MEDIA_DATA_DB_MEDIA_TYPE + " = ?";
649 MediaType mediaType;
650 MtpDataUtils::GetMediaTypeByformat(format, mediaType);
651 rootIdList.push_back(to_string(mediaType));
652 DataShare::DataSharePredicates predicates;
653 predicates.SetWhereClause(whereClause);
654 predicates.SetWhereArgs(rootIdList);
655 Uri uri(MEDIALIBRARY_DATA_URI);
656 vector<string> columns;
657 return dataShareHelper_->Query(uri, predicates, columns);
658 }
659
GetHandleDepthChildren(const uint16_t format,const uint32_t handle)660 shared_ptr<DataShare::DataShareResultSet> MtpMedialibraryManager::GetHandleDepthChildren(const uint16_t format,
661 const uint32_t handle)
662 {
663 DataShare::DataSharePredicates predicates;
664 MediaType mediaType;
665 MtpDataUtils::GetMediaTypeByformat(format, mediaType);
666 string whereClause;
667 vector<string> whereArgs;
668 if (mediaType == MEDIA_TYPE_ALL) {
669 whereClause = "("+ MEDIA_DATA_DB_ID + " = ? OR " + MEDIA_DATA_DB_PARENT_ID +
670 " = ? ) AND " + MEDIA_DATA_DB_DATE_TRASHED + " = ?";
671 whereArgs = {to_string(handle), to_string(handle), to_string(0)};
672 } else {
673 whereClause = "("+ MEDIA_DATA_DB_ID + " = ? OR " + MEDIA_DATA_DB_PARENT_ID +
674 " = ? ) AND " + MEDIA_DATA_DB_MEDIA_TYPE + " = ? AND " + MEDIA_DATA_DB_DATE_TRASHED + " = ?";
675 whereArgs = {to_string(handle), to_string(handle), to_string(mediaType), to_string(0)};
676 }
677 predicates.SetWhereClause(whereClause);
678 predicates.SetWhereArgs(whereArgs);
679 Uri uri(MEDIALIBRARY_DATA_URI);
680 vector<string> columns;
681 return dataShareHelper_->Query(uri, predicates, columns);
682 }
683
GetObjectPropValue(const shared_ptr<MtpOperationContext> & context,uint64_t & outIntVal,uint128_t & outLongVal,string & outStrVal)684 int32_t MtpMedialibraryManager::GetObjectPropValue(const shared_ptr<MtpOperationContext> &context,
685 uint64_t &outIntVal, uint128_t &outLongVal, string &outStrVal)
686 {
687 shared_ptr<DataShare::DataShareResultSet> resultSet = GetHandle(0, context->handle);
688 int count = 0;
689 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, MTP_ERROR_INVALID_OBJECTHANDLE, "fail to getSet");
690 resultSet->GetRowCount(count);
691 CHECK_AND_RETURN_RET_LOG(count != 0, MTP_ERROR_INVALID_OBJECTHANDLE, "fail to get set count");
692 PropertyValue propValue;
693 int32_t errCode = MtpDataUtils::GetPropValueBySet(context->property, resultSet, propValue);
694 CHECK_AND_RETURN_RET_LOG(errCode == MTP_SUCCESS, MTP_ERROR_INVALID_OBJECTHANDLE, "fail to get GetPropValueBySet");
695 outIntVal = propValue.outIntVal;
696 outStrVal = propValue.outStrVal;
697 return errCode;
698 }
699
700 } // namespace Media
701 } // namespace OHOS
702