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_album_impl.h"
17
18 #include "media_column.h"
19 #include "media_file_utils.h"
20 #include "medialibrary_errno.h"
21 #include "userfile_client.h"
22 #include "userfile_manager_types.h"
23 #include "album_operation_uri.h"
24
25 using namespace std;
26 using namespace OHOS::DataShare;
27
28 namespace OHOS {
29 namespace Media {
PhotoAlbumImpl(std::unique_ptr<PhotoAlbum> photoAlbumPtr_)30 PhotoAlbumImpl::PhotoAlbumImpl(std::unique_ptr<PhotoAlbum> photoAlbumPtr_)
31 {
32 photoAlbumPtr = move(photoAlbumPtr_);
33 }
34
PhotoAlbumImpl(std::shared_ptr<PhotoAlbum> photoAlbumPtr_)35 PhotoAlbumImpl::PhotoAlbumImpl(std::shared_ptr<PhotoAlbum> photoAlbumPtr_)
36 {
37 photoAlbumPtr = photoAlbumPtr_;
38 }
39
GetPhotoAlbumInstance()40 shared_ptr<PhotoAlbum> PhotoAlbumImpl::GetPhotoAlbumInstance()
41 {
42 return photoAlbumPtr;
43 }
44
GetPhotoAlbumType() const45 int32_t PhotoAlbumImpl::GetPhotoAlbumType() const
46 {
47 return static_cast<int32_t>(photoAlbumPtr->GetPhotoAlbumType());
48 }
49
GetPhotoAlbumSubType() const50 int32_t PhotoAlbumImpl::GetPhotoAlbumSubType() const
51 {
52 return static_cast<int32_t>(photoAlbumPtr->GetPhotoAlbumSubType());
53 }
54
GetAlbumName() const55 string PhotoAlbumImpl::GetAlbumName() const
56 {
57 return photoAlbumPtr->GetAlbumName();
58 }
59
SetAlbumName(char * cAlbumName)60 void PhotoAlbumImpl::SetAlbumName(char* cAlbumName)
61 {
62 string albumName(cAlbumName);
63 photoAlbumPtr->SetAlbumName(albumName);
64 }
65
GetAlbumUri() const66 string PhotoAlbumImpl::GetAlbumUri() const
67 {
68 return photoAlbumPtr->GetAlbumUri();
69 }
70
GetCount() const71 int32_t PhotoAlbumImpl::GetCount() const
72 {
73 return photoAlbumPtr->GetCount();
74 }
75
GetCoverUri() const76 string PhotoAlbumImpl::GetCoverUri() const
77 {
78 return photoAlbumPtr->GetCoverUri();
79 }
80
GetImageCount() const81 int32_t PhotoAlbumImpl::GetImageCount() const
82 {
83 return photoAlbumPtr->GetImageCount();
84 }
85
GetVideoCount() const86 int32_t PhotoAlbumImpl::GetVideoCount() const
87 {
88 return photoAlbumPtr->GetVideoCount();
89 }
90
GetPredicatesByAlbumTypes(const shared_ptr<PhotoAlbum> & photoAlbum,DataSharePredicates & predicates,const bool hiddenOnly)91 static int32_t GetPredicatesByAlbumTypes(const shared_ptr<PhotoAlbum> &photoAlbum,
92 DataSharePredicates &predicates, const bool hiddenOnly)
93 {
94 auto albumId = photoAlbum->GetAlbumId();
95 auto subType = photoAlbum->GetPhotoAlbumSubType();
96 bool isLocationAlbum = subType == PhotoAlbumSubType::GEOGRAPHY_LOCATION;
97 if (albumId <= 0 && !isLocationAlbum) {
98 return E_INVALID_ARGUMENTS;
99 }
100 auto type = photoAlbum->GetPhotoAlbumType();
101 if ((!PhotoAlbum::CheckPhotoAlbumType(type)) || (!PhotoAlbum::CheckPhotoAlbumSubType(subType))) {
102 return E_INVALID_ARGUMENTS;
103 }
104
105 if (type == PhotoAlbumType::SMART && subType == PhotoAlbumSubType::PORTRAIT) {
106 return MediaLibraryNapiUtils::GetPortraitAlbumPredicates(photoAlbum->GetAlbumId(), predicates);
107 }
108
109 if (PhotoAlbum::IsUserPhotoAlbum(type, subType)) {
110 return MediaLibraryNapiUtils::GetUserAlbumPredicates(photoAlbum->GetAlbumId(), predicates, hiddenOnly);
111 }
112
113 if (PhotoAlbum::IsSourceAlbum(type, subType)) {
114 return MediaLibraryNapiUtils::GetSourceAlbumPredicates(photoAlbum->GetAlbumId(), predicates, hiddenOnly);
115 }
116
117 if (type == PhotoAlbumType::SMART) {
118 if (isLocationAlbum) {
119 return MediaLibraryNapiUtils::GetAllLocationPredicates(predicates);
120 }
121 auto albumName = photoAlbum->GetAlbumName();
122 if (MediaLibraryNapiUtils::IsFeaturedSinglePortraitAlbum(albumName, predicates)) {
123 return MediaLibraryNapiUtils::GetFeaturedSinglePortraitAlbumPredicates(
124 photoAlbum->GetAlbumId(), predicates);
125 }
126 return MediaLibraryNapiUtils::GetAnalysisPhotoMapPredicates(photoAlbum->GetAlbumId(), predicates);
127 }
128
129 if ((type != PhotoAlbumType::SYSTEM) || (subType == PhotoAlbumSubType::USER_GENERIC) ||
130 (subType == PhotoAlbumSubType::ANY)) {
131 return E_INVALID_ARGUMENTS;
132 }
133 return MediaLibraryNapiUtils::GetSystemAlbumPredicates(subType, predicates, hiddenOnly);
134 }
135
ParseArgsGetPhotoAssets(COptions options,DataSharePredicates & predicates,vector<string> & fetchColumn,ExtraInfo & extraInfo,int32_t & errCode)136 void PhotoAlbumImpl::ParseArgsGetPhotoAssets(COptions options, DataSharePredicates &predicates,
137 vector<string> &fetchColumn, ExtraInfo &extraInfo, int32_t &errCode)
138 {
139 extraInfo.fetchOptType = ASSET_FETCH_OPT;
140 GetFetchOption(options, predicates, fetchColumn, extraInfo, errCode);
141 if (errCode != E_SUCCESS) {
142 LOGE("GetFetchOption failed.");
143 return;
144 }
145 auto ret = GetPredicatesByAlbumTypes(photoAlbumPtr, predicates, photoAlbumPtr->GetHiddenOnly());
146 if (ret != E_SUCCESS) {
147 LOGE("GetPredicatesByAlbumTypes failed.");
148 errCode = JS_ERR_PARAMETER_INVALID;
149 return;
150 }
151 AddDefaultAssetColumns(fetchColumn,
152 PhotoColumn::IsPhotoColumn, NapiAssetType::TYPE_PHOTO, errCode);
153 if (errCode != E_SUCCESS) {
154 LOGE("AddDefaultAssetColumns failed.");
155 return;
156 }
157 if (photoAlbumPtr->GetHiddenOnly() || photoAlbumPtr->GetPhotoAlbumSubType() == PhotoAlbumSubType::HIDDEN) {
158 if (!MediaLibraryNapiUtils::IsSystemApp()) {
159 LOGE("This interface can be called only by system apps");
160 errCode = E_CHECK_SYSTEMAPP_FAIL;
161 return;
162 }
163 // sort by hidden time desc if is hidden asset
164 predicates.IndexedBy(PhotoColumn::PHOTO_HIDDEN_TIME_INDEX);
165 }
166 }
167
IsFeaturedSinglePortraitAlbum(const shared_ptr<PhotoAlbum> & photoAlbumPtr)168 static bool IsFeaturedSinglePortraitAlbum(const shared_ptr<PhotoAlbum>& photoAlbumPtr)
169 {
170 constexpr int portraitAlbumId = 0;
171 return photoAlbumPtr->GetPhotoAlbumSubType() == PhotoAlbumSubType::CLASSIFY &&
172 photoAlbumPtr->GetAlbumName().compare(to_string(portraitAlbumId)) == 0;
173 }
174
ConvertColumnsForPortrait(const shared_ptr<PhotoAlbum> & photoAlbumPtr,vector<string> & fetchColumn)175 static void ConvertColumnsForPortrait(const shared_ptr<PhotoAlbum>& photoAlbumPtr, vector<string> &fetchColumn)
176 {
177 if (photoAlbumPtr == nullptr || (photoAlbumPtr->GetPhotoAlbumSubType() != PhotoAlbumSubType::PORTRAIT &&
178 photoAlbumPtr->GetPhotoAlbumSubType() != PhotoAlbumSubType::GROUP_PHOTO &&
179 !IsFeaturedSinglePortraitAlbum(photoAlbumPtr))) {
180 return;
181 }
182
183 for (size_t i = 0; i < fetchColumn.size(); i++) {
184 if (fetchColumn[i] != "count(*)") {
185 fetchColumn[i] = PhotoColumn::PHOTOS_TABLE + "." + fetchColumn[i];
186 }
187 }
188 }
189
GetAssets(COptions options,int32_t & errCode)190 shared_ptr<FetchResult<FileAsset>> PhotoAlbumImpl::GetAssets(COptions options, int32_t &errCode)
191 {
192 DataSharePredicates predicates;
193 vector<string> fetchColumn;
194 ExtraInfo extraInfo;
195 ParseArgsGetPhotoAssets(options, predicates, fetchColumn, extraInfo, errCode);
196 if (errCode != E_SUCCESS) {
197 LOGE("ParseArgsGetPhotoAssets failed.");
198 return nullptr;
199 }
200 Uri uri(PAH_QUERY_PHOTO_MAP);
201 ConvertColumnsForPortrait(photoAlbumPtr, fetchColumn);
202 auto resultSet = UserFileClient::Query(uri, predicates, fetchColumn, errCode);
203 if (resultSet == nullptr) {
204 LOGE("Query db failed.");
205 errCode = JS_INNER_FAIL;
206 return nullptr;
207 }
208 shared_ptr<FetchResult<FileAsset>> fetchResult = make_shared<FetchResult<FileAsset>>(move(resultSet));
209 fetchResult->SetResultNapiType(ResultNapiType::TYPE_PHOTOACCESS_HELPER);
210 return fetchResult;
211 }
212
ParseArgsCommitModify(const shared_ptr<PhotoAlbum> & photoAlbumPtr,DataSharePredicates & predicates,DataShareValuesBucket & valuesBucket,int32_t & errCode)213 static void ParseArgsCommitModify(const shared_ptr<PhotoAlbum>& photoAlbumPtr, DataSharePredicates &predicates,
214 DataShareValuesBucket &valuesBucket, int32_t &errCode)
215 {
216 if (photoAlbumPtr == nullptr) {
217 LOGE("photoAlbumPtr is nullptr.");
218 errCode = JS_ERR_PARAMETER_INVALID;
219 return;
220 }
221 if (!PhotoAlbum::IsUserPhotoAlbum(photoAlbumPtr->GetPhotoAlbumType(), photoAlbumPtr->GetPhotoAlbumSubType())) {
222 LOGE("modify failed: not user PhotoAlbum.");
223 errCode = JS_ERR_PARAMETER_INVALID;
224 return;
225 }
226 if (MediaFileUtils::CheckAlbumName(photoAlbumPtr->GetAlbumName()) < 0) {
227 LOGE("modify failed: not user PhotoAlbum.");
228 errCode = JS_ERR_PARAMETER_INVALID;
229 return;
230 }
231 predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(photoAlbumPtr->GetAlbumId()));
232 valuesBucket.Put(PhotoAlbumColumns::ALBUM_NAME, photoAlbumPtr->GetAlbumName());
233 valuesBucket.Put(PhotoAlbumColumns::ALBUM_COVER_URI, photoAlbumPtr->GetCoverUri());
234 }
235
CommitModify(int32_t & errCode)236 void PhotoAlbumImpl::CommitModify(int32_t &errCode)
237 {
238 DataSharePredicates predicates;
239 DataShareValuesBucket valuesBucket;
240 ParseArgsCommitModify(photoAlbumPtr, predicates, valuesBucket, errCode);
241 string commitModifyUri = PAH_UPDATE_PHOTO_ALBUM;
242 Uri uri(commitModifyUri);
243 int changedRows = UserFileClient::Update(uri, predicates, valuesBucket);
244 if (changedRows < 0) {
245 errCode = MediaLibraryNapiUtils::TransErrorCode("commitModify", changedRows);
246 }
247 }
248 }
249 }