• 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         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 }