1 /*
2 * Copyright (c) 2024 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 "photo_asset_impl.h"
17
18 #include <algorithm>
19 #include <cstring>
20
21 #include "datashare_errno.h"
22 #include "datashare_predicates.h"
23 #include "datashare_result_set.h"
24 #include "image_type.h"
25 #include "media_column.h"
26 #include "media_file_utils.h"
27 #include "medialibrary_db_const.h"
28 #include "medialibrary_errno.h"
29 #include "pixel_map_impl.h"
30 #include "thumbnail_const.h"
31 #include "thumbnail_utils.h"
32 #include "userfile_client.h"
33 #include "userfilemgr_uri.h"
34
35 using namespace std;
36 using namespace OHOS::DataShare;
37
38 namespace OHOS {
39 namespace Media {
PhotoAssetImpl(unique_ptr<FileAsset> fileAssetPtr_)40 PhotoAssetImpl::PhotoAssetImpl(unique_ptr<FileAsset> fileAssetPtr_)
41 {
42 fileAssetPtr = move(fileAssetPtr_);
43 }
44
PhotoAssetImpl(shared_ptr<FileAsset> fileAssetPtr_)45 PhotoAssetImpl::PhotoAssetImpl(shared_ptr<FileAsset> fileAssetPtr_)
46 {
47 fileAssetPtr = fileAssetPtr_;
48 }
49
GetFileAssetInstance()50 shared_ptr<FileAsset> PhotoAssetImpl::GetFileAssetInstance()
51 {
52 return fileAssetPtr;
53 }
54
GetFileUri()55 string PhotoAssetImpl::GetFileUri()
56 {
57 return fileAssetPtr->GetUri();
58 }
59
GetMediaType()60 Media::MediaType PhotoAssetImpl::GetMediaType()
61 {
62 return fileAssetPtr->GetMediaType();
63 }
64
GetFileDisplayName()65 string PhotoAssetImpl::GetFileDisplayName()
66 {
67 return fileAssetPtr->GetDisplayName();
68 }
69
GetFileId()70 int32_t PhotoAssetImpl::GetFileId()
71 {
72 return fileAssetPtr->GetId();
73 }
74
CheckSystemApiKeys(const string & key)75 static int32_t CheckSystemApiKeys(const string &key)
76 {
77 static const set<string> SYSTEM_API_KEYS = {
78 MediaColumn::MEDIA_DATE_TRASHED,
79 MediaColumn::MEDIA_HIDDEN,
80 PhotoColumn::PHOTO_USER_COMMENT,
81 PhotoColumn::CAMERA_SHOT_KEY,
82 PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
83 PhotoColumn::SUPPORTED_WATERMARK_TYPE,
84 PhotoColumn::PHOTO_IS_AUTO,
85 PhotoColumn::PHOTO_IS_RECENT_SHOW,
86 PENDING_STATUS,
87 MEDIA_DATA_DB_DATE_TRASHED_MS,
88 };
89
90 if (SYSTEM_API_KEYS.find(key) != SYSTEM_API_KEYS.end() && !MediaLibraryNapiUtils::IsSystemApp()) {
91 LOGE("This key can only be used by system apps");
92 return E_CHECK_SYSTEMAPP_FAIL;
93 }
94 return E_SUCCESS;
95 }
96
HandleDateTransitionKey(const string & key,const shared_ptr<FileAsset> & fileAssetPtr,int32_t & errCode)97 static PhotoAssetMember HandleDateTransitionKey(const string &key,
98 const shared_ptr<FileAsset> &fileAssetPtr, int32_t &errCode)
99 {
100 PhotoAssetMember assetMember = {
101 .memberType = -1,
102 .stringValue = nullptr,
103 .boolValue = false
104 };
105 if (fileAssetPtr->GetMemberMap().count(key) == 0) {
106 errCode = JS_E_FILE_KEY;
107 return assetMember;
108 }
109
110 auto m = fileAssetPtr->GetMemberMap().at(key);
111 if (m.index() == MEMBER_TYPE_INT64) {
112 assetMember.memberType = MEMBER_TYPE_INT32; // int64_t
113 assetMember.intValue = get<int64_t>(m);
114 } else {
115 errCode = JS_ERR_PARAMETER_INVALID;
116 }
117 return assetMember;
118 }
119
IsSpecialKey(const string & key)120 static bool IsSpecialKey(const string &key)
121 {
122 static const set<string> SPECIAL_KEY = {
123 PENDING_STATUS
124 };
125
126 if (SPECIAL_KEY.find(key) != SPECIAL_KEY.end()) {
127 return true;
128 }
129 return false;
130 }
131
HandleGettingSpecialKey(const string & key,const shared_ptr<FileAsset> & fileAssetPtr)132 static PhotoAssetMember HandleGettingSpecialKey(const string &key, const shared_ptr<FileAsset> &fileAssetPtr)
133 {
134 PhotoAssetMember assetMember = {
135 .memberType = -1,
136 .stringValue = nullptr,
137 .boolValue = false
138 };
139 if (key == PENDING_STATUS) {
140 assetMember.memberType = MEMBER_TYPE_STRING; // 2
141 if (fileAssetPtr->GetTimePending() == 0) {
142 assetMember.boolValue = false;
143 } else {
144 assetMember.boolValue = true;
145 }
146 }
147 return assetMember;
148 }
149
GetCompatDate(const string inputKey,const int64_t date)150 static inline int64_t GetCompatDate(const string inputKey, const int64_t date)
151 {
152 if (inputKey == MEDIA_DATA_DB_DATE_ADDED || inputKey == MEDIA_DATA_DB_DATE_MODIFIED ||
153 inputKey == MEDIA_DATA_DB_DATE_TRASHED || inputKey == MEDIA_DATA_DB_DATE_TAKEN) {
154 return date / MSEC_TO_SEC;
155 }
156 return date;
157 }
158
UserFileMgrGet(string & inputKey,int32_t & errCode)159 PhotoAssetMember PhotoAssetImpl::UserFileMgrGet(string &inputKey, int32_t &errCode)
160 {
161 PhotoAssetMember assetMember = {
162 .memberType = -1,
163 .stringValue = nullptr,
164 .boolValue = false
165 };
166 if (CheckSystemApiKeys(inputKey) < 0) {
167 return assetMember;
168 }
169 if (DATE_TRANSITION_MAP.count(inputKey) != 0) {
170 return HandleDateTransitionKey(DATE_TRANSITION_MAP.at(inputKey), fileAssetPtr, errCode);
171 }
172
173 if (fileAssetPtr->GetMemberMap().count(inputKey) == 0) {
174 // no exist throw error
175 errCode = JS_E_FILE_KEY;
176 return assetMember;
177 }
178
179 if (IsSpecialKey(inputKey)) {
180 return HandleGettingSpecialKey(inputKey, fileAssetPtr);
181 }
182
183 auto m = fileAssetPtr->GetMemberMap().at(inputKey);
184 if (m.index() == MEMBER_TYPE_STRING) {
185 assetMember.memberType = MEMBER_TYPE_INT64; // 1
186 assetMember.stringValue = MallocCString(get<string>(m));
187 } else if (m.index() == MEMBER_TYPE_INT32) {
188 assetMember.memberType = MEMBER_TYPE_INT32;
189 assetMember.intValue = static_cast<int64_t>(get<int32_t>(m));
190 } else if (m.index() == MEMBER_TYPE_INT64) {
191 assetMember.memberType = MEMBER_TYPE_INT32;
192 assetMember.intValue = GetCompatDate(inputKey, get<int64_t>(m));
193 } else {
194 errCode = JS_ERR_PARAMETER_INVALID;
195 }
196 return assetMember;
197 }
198
HandleParamSet(const string & inputKey,const string & value,ResultNapiType resultNapiType)199 bool PhotoAssetImpl::HandleParamSet(const string &inputKey, const string &value, ResultNapiType resultNapiType)
200 {
201 if (resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
202 if (inputKey == MediaColumn::MEDIA_TITLE) {
203 fileAssetPtr->SetTitle(value);
204 } else {
205 LOGE("invalid key %{private}s, no support key", inputKey.c_str());
206 return false;
207 }
208 } else if (resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
209 if (inputKey == MediaColumn::MEDIA_NAME) {
210 fileAssetPtr->SetDisplayName(value);
211 fileAssetPtr->SetTitle(MediaFileUtils::GetTitleFromDisplayName(value));
212 } else if (inputKey == MediaColumn::MEDIA_TITLE) {
213 fileAssetPtr->SetTitle(value);
214 string displayName = fileAssetPtr->GetDisplayName();
215 if (!displayName.empty()) {
216 string extention = MediaFileUtils::SplitByChar(displayName, '.');
217 fileAssetPtr->SetDisplayName(value + "." + extention);
218 }
219 } else {
220 LOGE("invalid key %{private}s, no support key", inputKey.c_str());
221 return false;
222 }
223 } else {
224 LOGE("invalid resultNapiType");
225 return false;
226 }
227 return true;
228 }
229
UserFileMgrSet(string & inputKey,string & value,int32_t & errCode)230 void PhotoAssetImpl::UserFileMgrSet(string &inputKey, string &value, int32_t &errCode)
231 {
232 if (!HandleParamSet(inputKey, value)) {
233 errCode = JS_E_FILE_KEY;
234 }
235 }
236
CommitModify(int32_t & errCode)237 void PhotoAssetImpl::CommitModify(int32_t &errCode)
238 {
239 string uri;
240 if (fileAssetPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
241 fileAssetPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
242 uri = PAH_UPDATE_PHOTO;
243 } else if (fileAssetPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
244 uri = UFM_UPDATE_AUDIO;
245 }
246 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
247
248 Uri updateAssetUri(uri);
249 MediaType mediaType = fileAssetPtr->GetMediaType();
250 string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
251 DataSharePredicates predicates;
252 DataShareValuesBucket valuesBucket;
253 valuesBucket.Put(MediaColumn::MEDIA_TITLE, fileAssetPtr->GetTitle());
254 predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ? ");
255 predicates.SetWhereArgs({to_string(fileAssetPtr->GetId())});
256
257 int32_t changedRows = static_cast<int32_t>(UserFileClient::Update(updateAssetUri, predicates, valuesBucket));
258 if (changedRows < 0) {
259 errCode = static_cast<int32_t>(MediaLibraryNapiUtils::TransErrorCode("CommitModify", changedRows));
260 LOGE("File asset modification failed, err: %{public}d", changedRows);
261 } else {
262 Uri modifyNotify(notifyUri);
263 UserFileClient::NotifyChange(modifyNotify);
264 }
265 }
266
GetThumbnail(CSize cSize,int32_t & errCode)267 int64_t PhotoAssetImpl::GetThumbnail(CSize cSize, int32_t &errCode)
268 {
269 int result = -1;
270 Size size = {
271 .width = cSize.width < 0 ? DEFAULT_THUMB_SIZE : cSize.width,
272 .height = cSize.height < 0 ? DEFAULT_THUMB_SIZE : cSize.height
273 };
274 string path = fileAssetPtr->GetPath();
275 #ifndef MEDIALIBRARY_COMPATIBILITY
276 if (path.empty()
277 && !fileAssetPtr->GetRelativePath().empty() && !fileAssetPtr->GetDisplayName().empty()) {
278 path = ROOT_MEDIA_DIR + fileAssetPtr->GetRelativePath() + fileAssetPtr->GetDisplayName();
279 }
280 #endif
281 auto pixelmap = ThumbnailManager::QueryThumbnail(fileAssetPtr->GetUri(), size, path);
282 if (pixelmap != nullptr) {
283 std::shared_ptr<PixelMap> pixelmapSptr = move(pixelmap);
284 auto native = FFIData::Create<PixelMapImpl>(pixelmapSptr);
285 if (native != nullptr) {
286 result = native->GetID();
287 } else {
288 LOGE("Create native PixelMapImpl failed.");
289 errCode = JS_INNER_FAIL;
290 }
291 } else {
292 LOGE("Create PixelMapImpl failed.");
293 errCode = JS_INNER_FAIL;
294 }
295 return result;
296 }
297 }
298 }