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