• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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