• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_formmap_operations.h"
17 
18 #include <memory>
19 #include <mutex>
20 #include <string>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 
24 #include "abs_shared_result_set.h"
25 #include "file_ex.h"
26 #include "media_column.h"
27 #include "media_file_uri.h"
28 #include "media_file_utils.h"
29 #include "media_log.h"
30 #include "medialibrary_errno.h"
31 #include "medialibrary_object_utils.h"
32 #include "medialibrary_rdbstore.h"
33 #include "rdb_predicates.h"
34 #include "result_set_utils.h"
35 #include "string_ex.h"
36 #include "thumbnail_const.h"
37 #include "uri.h"
38 #include "userfile_manager_types.h"
39 #include "value_object.h"
40 #include "values_bucket.h"
41 #include "image_type.h"
42 #include "datashare_helper.h"
43 #include "unique_fd.h"
44 #include "medialibrary_data_manager.h"
45 #include "thumbnail_utils.h"
46 #include "ithumbnail_helper.h"
47 #include "form_map.h"
48 #include "nlohmann/json.hpp"
49 
50 using namespace OHOS::DataShare;
51 using namespace std;
52 using namespace OHOS::NativeRdb;
53 using namespace OHOS::RdbDataShareAdapter;
54 
55 namespace OHOS {
56 namespace Media {
57 std::mutex MediaLibraryFormMapOperations::mutex_;
58 const string MEDIA_LIBRARY_PROXY_URI = "datashareproxy://com.ohos.medialibrary.medialibrarydata";
59 const string MEDIA_LIBRARY_PROXY_DATA_URI = "datashareproxy://com.ohos.medialibrary.medialibrarydata/image_data";
60 const string MEDIA_LIBRARY_PROXY_IMAGE_URI = "datashareproxy://com.ohos.medialibrary.medialibrarydata/image_uri";
61 const string NO_PICTURES = "";
62 
ReadThumbnailFile(const string & path,vector<uint8_t> & buffer)63 static void ReadThumbnailFile(const string &path, vector<uint8_t> &buffer)
64 {
65     string thumbnailFileName = GetThumbnailPath(path, THUMBNAIL_LCD_SUFFIX);
66     auto fd = open(thumbnailFileName.c_str(), O_RDONLY);
67     UniqueFd uniqueFd(fd);
68     struct stat statInfo;
69     if (fstat(uniqueFd.Get(), &statInfo) == E_ERR) {
70         return ;
71     }
72     buffer.reserve(statInfo.st_size);
73     uint8_t *tempBuffer = (uint8_t *)malloc(statInfo.st_size);
74     if (tempBuffer == nullptr) {
75         MEDIA_ERR_LOG("The point tempBuffer is null!");
76         return ;
77     }
78     ssize_t bytes = read(uniqueFd.Get(), tempBuffer, statInfo.st_size);
79     if (bytes < 0) {
80         MEDIA_ERR_LOG("read file failed!");
81         free(tempBuffer);
82         return ;
83     }
84     buffer.assign(tempBuffer, tempBuffer + statInfo.st_size);
85     free(tempBuffer);
86 }
87 
GetUriByFileId(const int32_t & fileId,const string & path)88 string MediaLibraryFormMapOperations::GetUriByFileId(const int32_t &fileId, const string &path)
89 {
90     MediaLibraryCommand queryCmd(OperationObject::UFM_PHOTO, OperationType::QUERY);
91     queryCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(fileId));
92     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
93     if (uniStore == nullptr) {
94         MEDIA_ERR_LOG("UniStore is nullptr");
95         return "";
96     }
97     vector<string> columns = {
98         MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_NAME
99     };
100     auto queryResult = uniStore->Query(queryCmd, columns);
101     if (queryResult == nullptr || queryResult->GoToFirstRow() != NativeRdb::E_OK) {
102         return "";
103     }
104     string displayName = GetStringVal(MEDIA_DATA_DB_NAME, queryResult);
105     int32_t mediaType = GetInt32Val(MEDIA_DATA_DB_MEDIA_TYPE, queryResult);
106     if (mediaType != MEDIA_TYPE_IMAGE) {
107         return "";
108     }
109     string extraUri = MediaFileUtils::GetExtraUri(displayName, path, false);
110     return MediaFileUri(MediaType(mediaType), ToString(fileId), "", MEDIA_API_VERSION_V10,  extraUri).ToString();
111 }
112 
GetFormMapFormId(const string & uri,vector<int64_t> & formIds)113 void MediaLibraryFormMapOperations::GetFormMapFormId(const string &uri, vector<int64_t> &formIds)
114 {
115     lock_guard<mutex> lock(mutex_);
116     MediaLibraryCommand queryFormMapCmd(OperationObject::PAH_FORM_MAP, OperationType::QUERY);
117     queryFormMapCmd.GetAbsRdbPredicates()->EqualTo(FormMap::FORMMAP_URI, uri);
118 
119     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
120     if (uniStore == nullptr) {
121         MEDIA_ERR_LOG("UniStore is nullptr");
122         return;
123     }
124     vector<string> columns = {FormMap::FORMMAP_FORM_ID, FormMap::FORMMAP_URI};
125     auto queryResult = uniStore->Query(queryFormMapCmd, columns);
126     if (queryResult == nullptr) {
127         MEDIA_ERR_LOG("Failed to query form id!");
128         return;
129     }
130     while (queryResult->GoToNextRow() == NativeRdb::E_OK) {
131         string formId = GetStringVal(FormMap::FORMMAP_FORM_ID, queryResult);
132         if (formId.empty()) {
133             MEDIA_WARN_LOG("Failed to get form id from result!");
134             continue;
135         }
136         if (GetStringVal(FormMap::FORMMAP_URI, queryResult) == uri) {
137             formIds.push_back(std::stoll(formId));
138         }
139     }
140 }
141 
GetFormIdsByUris(const vector<string> & notifyUris,vector<int64_t> & formIds)142 void MediaLibraryFormMapOperations::GetFormIdsByUris(const vector<string> &notifyUris, vector<int64_t> &formIds)
143 {
144     lock_guard<mutex> lock(mutex_);
145     MediaLibraryCommand queryFormMapCmd(OperationObject::PAH_FORM_MAP, OperationType::QUERY);
146     queryFormMapCmd.GetAbsRdbPredicates()->And()->In(FormMap::FORMMAP_URI, notifyUris);
147 
148     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
149     if (uniStore == nullptr) {
150         MEDIA_ERR_LOG("UniStore is nullptr");
151         return;
152     }
153     vector<string> columns = {FormMap::FORMMAP_FORM_ID, FormMap::FORMMAP_URI};
154     auto queryResult = uniStore->Query(queryFormMapCmd, columns);
155     if (queryResult == nullptr) {
156         MEDIA_ERR_LOG("Failed to query form id!");
157         return;
158     }
159     while (queryResult->GoToNextRow() == NativeRdb::E_OK) {
160         string formId = GetStringVal(FormMap::FORMMAP_FORM_ID, queryResult);
161         if (formId.empty()) {
162             MEDIA_WARN_LOG("Failed to get form id from result!");
163             continue;
164         }
165         string uri = GetStringVal(FormMap::FORMMAP_URI, queryResult);
166         if (std::count(notifyUris.begin(), notifyUris.end(), uri) > 0) {
167             formIds.push_back(std::stoll(formId));
168         }
169     }
170     queryResult->Close();
171 }
172 
GetFilePathById(const string & fileId)173 string MediaLibraryFormMapOperations::GetFilePathById(const string &fileId)
174 {
175     MediaLibraryCommand queryCmd(OperationObject::UFM_PHOTO, OperationType::QUERY);
176     queryCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, fileId);
177     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
178     if (uniStore == nullptr) {
179         MEDIA_ERR_LOG("UniStore is nullptr");
180         return "";
181     }
182     vector<string> columns = {
183         MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH
184     };
185     auto queryResult = uniStore->Query(queryCmd, columns);
186     if (queryResult == nullptr || queryResult->GoToFirstRow() != NativeRdb::E_OK) {
187         MEDIA_ERR_LOG("Get path by Id failed , id is %{private}s", fileId.c_str());
188         return "";
189     }
190     return GetStringVal(MEDIA_DATA_DB_FILE_PATH, queryResult);
191 }
192 
ModifyFormMapMessage(const string & uri,const int64_t & formId,const bool & isSave)193 void MediaLibraryFormMapOperations::ModifyFormMapMessage(const string &uri, const int64_t &formId, const bool &isSave)
194 {
195     if (isSave) {
196         MEDIA_INFO_LOG("Modify FormMap message return!, the case is saveFormInfo");
197         return;
198     }
199     lock_guard<mutex> lock(mutex_);
200     ValuesBucket value;
201     value.PutString(FormMap::FORMMAP_URI, uri);
202     RdbPredicates predicates(FormMap::FORM_MAP_TABLE);
203     predicates.And()->EqualTo(FormMap::FORMMAP_FORM_ID, std::to_string(formId));
204     int32_t updateRow = MediaLibraryRdbStore::UpdateWithDateTime(value, predicates);
205     if (updateRow < 0) {
206         MEDIA_ERR_LOG("Modify FormMap message err!, uri is %{private}s, formId is %{private}s",
207             uri.c_str(), to_string(formId).c_str());
208     }
209     return;
210 }
211 
PublishedChange(const string newUri,const vector<int64_t> & formIds,const bool & isSave)212 void MediaLibraryFormMapOperations::PublishedChange(const string newUri, const vector<int64_t> &formIds,
213     const bool &isSave)
214 {
215     CreateOptions options;
216     options.enabled_ = true;
217     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
218         DataShare::DataShareHelper::Creator(MEDIA_LIBRARY_PROXY_URI, options);
219     if (dataShareHelper == nullptr) {
220         MEDIA_ERR_LOG("dataShareHelper is nullptr");
221         return;
222     }
223     Data data;
224     PublishedDataItem::DataType tempData;
225     if (newUri.empty()) {
226         nlohmann::json noPicData = NO_PICTURES;
227         tempData = noPicData.dump();
228         for (auto &formId : formIds) {
229             MEDIA_INFO_LOG("Published formId is %{private}s, size of value is %{private}zu!",
230                 to_string(formId).c_str(), NO_PICTURES.size());
231             data.datas_.emplace_back(PublishedDataItem(MEDIA_LIBRARY_PROXY_DATA_URI, formId, tempData));
232             data.datas_.emplace_back(PublishedDataItem(MEDIA_LIBRARY_PROXY_IMAGE_URI, formId, tempData));
233             dataShareHelper->Publish(data, BUNDLE_NAME);
234             MediaLibraryFormMapOperations::ModifyFormMapMessage(NO_PICTURES, formId, isSave);
235         }
236     } else {
237         MediaFileUri fileUri = MediaFileUri(newUri);
238         ThumbnailWait thumbnailWait(false);
239         thumbnailWait.CheckAndWait(fileUri.GetFileId(), true);
240         string filePath = MediaLibraryFormMapOperations::GetFilePathById(fileUri.GetFileId());
241         if (MediaType(MediaFileUtils::GetMediaType(filePath)) == MEDIA_TYPE_IMAGE) {
242             vector<uint8_t> buffer;
243             ReadThumbnailFile(filePath, buffer);
244             tempData = buffer;
245             nlohmann::json uriJson = newUri;
246             PublishedDataItem::DataType uriData = uriJson.dump();
247             for (auto &formId : formIds) {
248                 MEDIA_INFO_LOG("Published formId: %{private}s!, value size: %{private}zu, image uri: %{private}s",
249                     to_string(formId).c_str(), buffer.size(), newUri.c_str());
250                 data.datas_.emplace_back(PublishedDataItem(MEDIA_LIBRARY_PROXY_DATA_URI, formId, tempData));
251                 data.datas_.emplace_back(PublishedDataItem(MEDIA_LIBRARY_PROXY_IMAGE_URI, formId, uriData));
252                 dataShareHelper->Publish(data, BUNDLE_NAME);
253                 MediaLibraryFormMapOperations::ModifyFormMapMessage(newUri, formId, isSave);
254             }
255         }
256     }
257 }
258 
RemoveFormIdOperations(RdbPredicates & predicates)259 int32_t MediaLibraryFormMapOperations::RemoveFormIdOperations(RdbPredicates &predicates)
260 {
261     lock_guard<mutex> lock(mutex_);
262     return MediaLibraryRdbStore::Delete(predicates);
263 }
264 
GetStringObject(MediaLibraryCommand & cmd,const string & columnName)265 static string GetStringObject(MediaLibraryCommand &cmd, const string &columnName)
266 {
267     ValueObject valueObject;
268     ValuesBucket values = cmd.GetValueBucket();
269     string value;
270     if (values.GetObject(columnName, valueObject)) {
271         valueObject.GetString(value);
272         return value;
273     }
274     return "";
275 }
276 
CheckQueryIsInDb(const OperationObject & operationObject,const string & queryId)277 bool MediaLibraryFormMapOperations::CheckQueryIsInDb(const OperationObject &operationObject, const string &queryId)
278 {
279     lock_guard<mutex> lock(mutex_);
280     MediaLibraryCommand queryFormMapCmd(operationObject, OperationType::QUERY);
281     vector<string> columns;
282     if (operationObject == OperationObject::PAH_FORM_MAP) {
283         queryFormMapCmd.GetAbsRdbPredicates()->EqualTo(FormMap::FORMMAP_FORM_ID, queryId);
284         columns = { FormMap::FORMMAP_FORM_ID };
285     } else if (operationObject == OperationObject::UFM_PHOTO) {
286         queryFormMapCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, queryId);
287         columns = { MEDIA_DATA_DB_ID };
288     }
289     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
290     if (uniStore == nullptr) {
291         MEDIA_ERR_LOG("UniStore is nullptr");
292         return false;
293     }
294     auto queryResultSet = uniStore->Query(queryFormMapCmd, columns);
295     if (queryResultSet != nullptr) {
296         if (queryResultSet->GoToFirstRow() == NativeRdb::E_OK) {
297             MEDIA_INFO_LOG("The id queried already exists!");
298             return true;
299         }
300     }
301     return false;
302 }
303 
HandleStoreFormIdOperation(MediaLibraryCommand & cmd)304 int32_t MediaLibraryFormMapOperations::HandleStoreFormIdOperation(MediaLibraryCommand &cmd)
305 {
306     string formId = GetStringObject(cmd, FormMap::FORMMAP_FORM_ID);
307     if (formId.empty()) {
308         MEDIA_ERR_LOG("GetObject failed");
309         return E_GET_PRAMS_FAIL;
310     }
311     string uri = GetStringObject(cmd, FormMap::FORMMAP_URI);
312     ValuesBucket value;
313     value.PutString(FormMap::FORMMAP_URI, uri);
314 
315     if (!uri.empty()) {
316         MediaFileUri mediaUri(uri);
317         CHECK_AND_RETURN_RET_LOG(MediaLibraryFormMapOperations::CheckQueryIsInDb(OperationObject::UFM_PHOTO,
318             mediaUri.GetFileId()), E_GET_PRAMS_FAIL, "the fileId is not exist");
319         vector<int64_t> formIds = { std::stoll(formId) };
320         MediaLibraryFormMapOperations::PublishedChange(uri, formIds, true);
321     }
322     if (MediaLibraryFormMapOperations::CheckQueryIsInDb(OperationObject::PAH_FORM_MAP, formId)) {
323         lock_guard<mutex> lock(mutex_);
324         RdbPredicates predicates(FormMap::FORM_MAP_TABLE);
325         predicates.EqualTo(FormMap::FORMMAP_FORM_ID, formId);
326         return MediaLibraryRdbStore::UpdateWithDateTime(value, predicates);
327     }
328 
329     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
330     if (rdbStore == nullptr) {
331         return E_HAS_DB_ERROR;
332     }
333     int64_t outRowId = -1;
334     lock_guard<mutex> lock(mutex_);
335     int32_t errCode = rdbStore->Insert(cmd, outRowId);
336     if (errCode != NativeRdb::E_OK || outRowId < 0) {
337         MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
338         return E_HAS_DB_ERROR;
339     }
340     return static_cast<int32_t>(outRowId);
341 }
342 } // namespace Media
343 } // namespace OHOS
344