• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         PhotoColumn::PHOTO_ORIGINAL_SUBTYPE,
87         PENDING_STATUS,
88         MEDIA_DATA_DB_DATE_TRASHED_MS,
89         MEDIA_SUM_SIZE,
90         PhotoColumn::PHOTO_EXIF_ROTATE,
91     };
92 
93     if (SYSTEM_API_KEYS.find(key) != SYSTEM_API_KEYS.end() && !MediaLibraryNapiUtils::IsSystemApp()) {
94         LOGE("This key can only be used by system apps");
95         return E_CHECK_SYSTEMAPP_FAIL;
96     }
97     return E_SUCCESS;
98 }
99 
HandleDateTransitionKey(const string & key,const shared_ptr<FileAsset> & fileAssetPtr,int32_t & errCode)100 static PhotoAssetMember HandleDateTransitionKey(const string &key,
101     const shared_ptr<FileAsset> &fileAssetPtr, int32_t &errCode)
102 {
103     PhotoAssetMember assetMember = {
104         .memberType = -1,
105         .stringValue = nullptr,
106         .boolValue = false
107     };
108     if (fileAssetPtr->GetMemberMap().count(key) == 0) {
109         errCode = JS_E_FILE_KEY;
110         return assetMember;
111     }
112 
113     auto m = fileAssetPtr->GetMemberMap().at(key);
114     if (m.index() == MEMBER_TYPE_INT64) {
115         assetMember.memberType = MEMBER_TYPE_INT32; // int64_t
116         assetMember.intValue = get<int64_t>(m);
117     } else {
118         errCode = JS_ERR_PARAMETER_INVALID;
119     }
120     return assetMember;
121 }
122 
IsSpecialKey(const string & key)123 static bool IsSpecialKey(const string &key)
124 {
125     static const set<string> SPECIAL_KEY = {
126         PENDING_STATUS
127     };
128 
129     if (SPECIAL_KEY.find(key) != SPECIAL_KEY.end()) {
130         return true;
131     }
132     return false;
133 }
134 
HandleGettingSpecialKey(const string & key,const shared_ptr<FileAsset> & fileAssetPtr)135 static PhotoAssetMember HandleGettingSpecialKey(const string &key, const shared_ptr<FileAsset> &fileAssetPtr)
136 {
137     PhotoAssetMember assetMember = {
138         .memberType = -1,
139         .stringValue = nullptr,
140         .boolValue = false
141     };
142     if (key == PENDING_STATUS) {
143         assetMember.memberType = MEMBER_TYPE_STRING; // 2
144         if (fileAssetPtr->GetTimePending() == 0) {
145             assetMember.boolValue = false;
146         } else {
147             assetMember.boolValue = true;
148         }
149     }
150     return assetMember;
151 }
152 
GetCompatDate(const string inputKey,const int64_t date)153 static inline int64_t GetCompatDate(const string inputKey, const int64_t date)
154 {
155     if (inputKey == MEDIA_DATA_DB_DATE_ADDED || inputKey == MEDIA_DATA_DB_DATE_MODIFIED ||
156         inputKey == MEDIA_DATA_DB_DATE_TRASHED || inputKey == MEDIA_DATA_DB_DATE_TAKEN) {
157             return date / MSEC_TO_SEC;
158     }
159     return date;
160 }
161 
UserFileMgrGet(string & inputKey,int32_t & errCode)162 PhotoAssetMember PhotoAssetImpl::UserFileMgrGet(string &inputKey, int32_t &errCode)
163 {
164     PhotoAssetMember assetMember = {
165         .memberType = -1,
166         .stringValue = nullptr,
167         .boolValue = false
168     };
169     if (CheckSystemApiKeys(inputKey) < 0) {
170         return assetMember;
171     }
172     if (DATE_TRANSITION_MAP.count(inputKey) != 0) {
173         return HandleDateTransitionKey(DATE_TRANSITION_MAP.at(inputKey), fileAssetPtr, errCode);
174     }
175 
176     if (fileAssetPtr->GetMemberMap().count(inputKey) == 0) {
177         // no exist throw error
178         errCode = JS_E_FILE_KEY;
179         return assetMember;
180     }
181 
182     if (IsSpecialKey(inputKey)) {
183         return HandleGettingSpecialKey(inputKey, fileAssetPtr);
184     }
185 
186     auto m = fileAssetPtr->GetMemberMap().at(inputKey);
187     if (m.index() == MEMBER_TYPE_STRING) {
188         assetMember.memberType = MEMBER_TYPE_INT64; // 1
189         assetMember.stringValue = MallocCString(get<string>(m));
190     } else if (m.index() == MEMBER_TYPE_INT32) {
191         assetMember.memberType = MEMBER_TYPE_INT32;
192         assetMember.intValue = static_cast<int64_t>(get<int32_t>(m));
193     } else if (m.index() == MEMBER_TYPE_INT64) {
194         assetMember.memberType = MEMBER_TYPE_INT32;
195         assetMember.intValue = GetCompatDate(inputKey, get<int64_t>(m));
196     } else {
197         errCode = JS_ERR_PARAMETER_INVALID;
198     }
199     return assetMember;
200 }
201 
HandleParamSet(const string & inputKey,const string & value,ResultNapiType resultNapiType)202 bool PhotoAssetImpl::HandleParamSet(const string &inputKey, const string &value, ResultNapiType resultNapiType)
203 {
204     if (resultNapiType == ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
205         if (inputKey == MediaColumn::MEDIA_TITLE) {
206             fileAssetPtr->SetTitle(value);
207         } else {
208             LOGE("invalid key %{private}s, no support key", inputKey.c_str());
209             return false;
210         }
211     } else if (resultNapiType == ResultNapiType::TYPE_USERFILE_MGR) {
212         if (inputKey == MediaColumn::MEDIA_NAME) {
213             fileAssetPtr->SetDisplayName(value);
214             fileAssetPtr->SetTitle(MediaFileUtils::GetTitleFromDisplayName(value));
215         } else if (inputKey == MediaColumn::MEDIA_TITLE) {
216             fileAssetPtr->SetTitle(value);
217             string displayName = fileAssetPtr->GetDisplayName();
218             if (!displayName.empty()) {
219                 string extention = MediaFileUtils::SplitByChar(displayName, '.');
220                 fileAssetPtr->SetDisplayName(value + "." + extention);
221             }
222         } else {
223             LOGE("invalid key %{private}s, no support key", inputKey.c_str());
224             return false;
225         }
226     } else {
227         LOGE("invalid resultNapiType");
228         return false;
229     }
230     return true;
231 }
232 
UserFileMgrSet(string & inputKey,string & value,int32_t & errCode)233 void PhotoAssetImpl::UserFileMgrSet(string &inputKey, string &value, int32_t &errCode)
234 {
235     if (!HandleParamSet(inputKey, value)) {
236         errCode = JS_E_FILE_KEY;
237     }
238 }
239 
CommitModify(int32_t & errCode)240 void PhotoAssetImpl::CommitModify(int32_t &errCode)
241 {
242     string uri;
243     if (fileAssetPtr->GetMediaType() == MEDIA_TYPE_IMAGE ||
244         fileAssetPtr->GetMediaType() == MEDIA_TYPE_VIDEO) {
245         uri = PAH_UPDATE_PHOTO;
246     } else if (fileAssetPtr->GetMediaType() == MEDIA_TYPE_AUDIO) {
247         uri = UFM_UPDATE_AUDIO;
248     }
249     MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
250 
251     Uri updateAssetUri(uri);
252     MediaType mediaType = fileAssetPtr->GetMediaType();
253     string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
254     DataSharePredicates predicates;
255     DataShareValuesBucket valuesBucket;
256     valuesBucket.Put(MediaColumn::MEDIA_TITLE, fileAssetPtr->GetTitle());
257     predicates.SetWhereClause(MEDIA_DATA_DB_ID + " = ? ");
258     predicates.SetWhereArgs({to_string(fileAssetPtr->GetId())});
259 
260     int32_t changedRows = static_cast<int32_t>(UserFileClient::Update(updateAssetUri, predicates, valuesBucket));
261     if (changedRows < 0) {
262         errCode = static_cast<int32_t>(MediaLibraryNapiUtils::TransErrorCode("CommitModify", changedRows));
263         LOGE("File asset modification failed, err: %{public}d", changedRows);
264     } else {
265         Uri modifyNotify(notifyUri);
266         UserFileClient::NotifyChange(modifyNotify);
267     }
268 }
269 
GetThumbnail(CSize cSize,int32_t & errCode)270 int64_t PhotoAssetImpl::GetThumbnail(CSize cSize, int32_t &errCode)
271 {
272     int result = -1;
273     Size size = {
274         .width = cSize.width < 0 ? DEFAULT_THUMB_SIZE : cSize.width,
275         .height = cSize.height < 0 ? DEFAULT_THUMB_SIZE : cSize.height
276     };
277     string path = fileAssetPtr->GetPath();
278 #ifndef MEDIALIBRARY_COMPATIBILITY
279     if (path.empty()
280             && !fileAssetPtr->GetRelativePath().empty() && !fileAssetPtr->GetDisplayName().empty()) {
281         path = ROOT_MEDIA_DIR + fileAssetPtr->GetRelativePath() + fileAssetPtr->GetDisplayName();
282     }
283 #endif
284     auto pixelmap = ThumbnailManager::QueryThumbnail(fileAssetPtr->GetUri(), size, path);
285     if (pixelmap != nullptr) {
286         std::shared_ptr<PixelMap> pixelmapSptr = move(pixelmap);
287         auto native = FFIData::Create<PixelMapImpl>(pixelmapSptr);
288         if (native != nullptr) {
289             result = native->GetID();
290         } else {
291             LOGE("Create native PixelMapImpl failed.");
292             errCode = JS_INNER_FAIL;
293         }
294     } else {
295         LOGE("Create PixelMapImpl failed.");
296         errCode = JS_INNER_FAIL;
297     }
298     return result;
299 }
300 }
301 }