1 /*
2 * Copyright (C) 2022 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 #define MLOG_TAG "Thumbnail"
16
17 #include "thumbnail_service.h"
18
19 #include "display_manager.h"
20 #include "media_column.h"
21 #include "medialibrary_async_worker.h"
22 #include "medialibrary_db_const.h"
23 #include "medialibrary_errno.h"
24 #include "media_log.h"
25 #include "result_set_utils.h"
26 #include "thumbnail_aging_helper.h"
27 #include "thumbnail_const.h"
28 #include "thumbnail_generate_helper.h"
29 #include "thumbnail_helper_factory.h"
30 #include "thumbnail_uri_utils.h"
31
32 using namespace std;
33 using namespace OHOS::DistributedKv;
34 using namespace OHOS::NativeRdb;
35 using namespace OHOS::AbilityRuntime;
36
37 namespace OHOS {
38 namespace Media {
39 std::shared_ptr<ThumbnailService> ThumbnailService::thumbnailServiceInstance_{nullptr};
40 std::mutex ThumbnailService::instanceLock_;
ThumbnailService(void)41 ThumbnailService::ThumbnailService(void)
42 {
43 rdbStorePtr_ = nullptr;
44 kvStorePtr_ = nullptr;
45 }
46
GetInstance()47 shared_ptr<ThumbnailService> ThumbnailService::GetInstance()
48 {
49 if (thumbnailServiceInstance_ == nullptr) {
50 std::lock_guard<std::mutex> lockGuard(instanceLock_);
51 if (thumbnailServiceInstance_ != nullptr) {
52 return thumbnailServiceInstance_;
53 }
54 thumbnailServiceInstance_ = shared_ptr<ThumbnailService>(new ThumbnailService());
55 }
56
57 return thumbnailServiceInstance_;
58 }
59
GetDefaultWindowSize(Size & size)60 static int32_t GetDefaultWindowSize(Size &size)
61 {
62 auto &displayMgr = OHOS::Rosen::DisplayManager::GetInstance();
63 auto display = displayMgr.GetDefaultDisplay();
64 if (display == nullptr) {
65 return E_ERR;
66 }
67 size.width = display->GetWidth();
68 size.height = display->GetHeight();
69 MEDIA_INFO_LOG("display window size::w %{public}d, h %{public}d", size.width, size.height);
70
71 return E_OK;
72 }
73
Init(const shared_ptr<RdbStore> & rdbStore,const shared_ptr<SingleKvStore> & kvStore,const shared_ptr<Context> & context)74 int32_t ThumbnailService::Init(const shared_ptr<RdbStore> &rdbStore,
75 const shared_ptr<SingleKvStore> &kvStore,
76 const shared_ptr<Context> &context)
77 {
78 rdbStorePtr_ = rdbStore;
79 kvStorePtr_ = kvStore;
80 context_ = context;
81
82 return GetDefaultWindowSize(screenSize_);
83 }
84
ReleaseService()85 void ThumbnailService::ReleaseService()
86 {
87 StopAllWorker();
88 rdbStorePtr_ = nullptr;
89 kvStorePtr_ = nullptr;
90 context_ = nullptr;
91 thumbnailServiceInstance_ = nullptr;
92 }
93
94 #ifdef MEDIALIBRARY_COMPATIBILITY
GetPathFromDb(const shared_ptr<NativeRdb::RdbStore> & rdbStorePtr,const string & fileId,const string & table,string & path)95 static int32_t GetPathFromDb(const shared_ptr<NativeRdb::RdbStore> &rdbStorePtr, const string &fileId,
96 const string &table, string &path)
97 {
98 if (rdbStorePtr == nullptr) {
99 return E_HAS_DB_ERROR;
100 }
101 if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
102 return E_INVALID_FILEID;
103 }
104 string querySql = "SELECT " + MediaColumn::MEDIA_FILE_PATH + " FROM " + table +
105 " WHERE " + MediaColumn::MEDIA_ID + "=?";
106 vector<string> selectionArgs = { fileId };
107 auto resultSet = rdbStorePtr->QuerySql(querySql, selectionArgs);
108 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
109 return E_HAS_DB_ERROR;
110 }
111 path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
112 if (path.empty()) {
113 return E_INVALID_PATH;
114 }
115 return E_OK;
116 }
117 #endif
118
GetThumbnailFd(const string & uri)119 int ThumbnailService::GetThumbnailFd(const string &uri)
120 {
121 string id, path, table;
122 Size size;
123 if (!ThumbnailUriUtils::ParseThumbnailInfo(uri, id, size, path, table)) {
124 return E_FAIL;
125 }
126 #ifdef MEDIALIBRARY_COMPATIBILITY
127 if (path.empty()) {
128 int32_t errCode = GetPathFromDb(rdbStorePtr_, id, table, path);
129 if (errCode != E_OK) {
130 MEDIA_ERR_LOG("GetPathFromDb failed, errCode = %{public}d", errCode);
131 return errCode;
132 }
133 }
134 #endif
135 ThumbRdbOpt opts = {
136 .store = rdbStorePtr_,
137 .path = path,
138 .table = table,
139 .row = id,
140 .uri = uri,
141 };
142 shared_ptr<IThumbnailHelper> thumbnailHelper = ThumbnailHelperFactory::GetThumbnailHelper(size);
143 if (thumbnailHelper == nullptr) {
144 return E_NO_MEMORY;
145 }
146 if (!IsThumbnail(size.width, size.height)) {
147 opts.screenSize = screenSize_;
148 }
149 int fd = thumbnailHelper->GetThumbnailPixelMap(opts);
150 if (fd < 0) {
151 MEDIA_ERR_LOG("GetThumbnailPixelMap failed : %{public}d", fd);
152 }
153 return fd;
154 }
155
CreateThumbnail(const std::string & uri,const string & path,bool isSync)156 int32_t ThumbnailService::CreateThumbnail(const std::string &uri, const string &path, bool isSync)
157 {
158 string fileId;
159 string networkId;
160 string tableName;
161 if (!ThumbnailUriUtils::ParseFileUri(uri, fileId, networkId, tableName)) {
162 MEDIA_ERR_LOG("ParseThumbnailInfo faild");
163 return E_ERR;
164 }
165
166 ThumbRdbOpt opts = {
167 .store = rdbStorePtr_,
168 .path = path,
169 .table = tableName,
170 .row = fileId,
171 .screenSize = screenSize_
172 };
173 Size size = { DEFAULT_THUMB_SIZE, DEFAULT_THUMB_SIZE };
174 shared_ptr<IThumbnailHelper> thumbnailHelper = ThumbnailHelperFactory::GetThumbnailHelper(size);
175 if (thumbnailHelper == nullptr) {
176 MEDIA_ERR_LOG("thumbnailHelper nullptr");
177 return E_ERR;
178 }
179 int32_t err = thumbnailHelper->CreateThumbnail(opts, isSync);
180 if (err != E_OK) {
181 MEDIA_ERR_LOG("CreateThumbnail failed : %{public}d", err);
182 return err;
183 }
184
185 size = { DEFAULT_LCD_SIZE, DEFAULT_LCD_SIZE };
186 shared_ptr<IThumbnailHelper> lcdHelper = ThumbnailHelperFactory::GetThumbnailHelper(size);
187 if (lcdHelper == nullptr) {
188 MEDIA_ERR_LOG("lcdHelper nullptr");
189 return E_ERR;
190 }
191 err = lcdHelper->CreateThumbnail(opts, isSync);
192 if (err != E_OK) {
193 MEDIA_ERR_LOG("CreateLcd failed : %{public}d", err);
194 return err;
195 }
196 return err;
197 }
198
InterruptBgworker()199 void ThumbnailService::InterruptBgworker()
200 {
201 shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
202 if (asyncWorker != nullptr) {
203 asyncWorker->Interrupt();
204 }
205 }
206
StopAllWorker()207 void ThumbnailService::StopAllWorker()
208 {
209 shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
210 if (asyncWorker != nullptr) {
211 asyncWorker->Stop();
212 }
213 }
214
GenerateThumbnails()215 int32_t ThumbnailService::GenerateThumbnails()
216 {
217 int32_t err = 0;
218 vector<string> tableList;
219 tableList.emplace_back(PhotoColumn::PHOTOS_TABLE);
220 tableList.emplace_back(AudioColumn::AUDIOS_TABLE);
221 tableList.emplace_back(MEDIALIBRARY_TABLE);
222
223 for (const auto &tableName : tableList) {
224 ThumbRdbOpt opts = {
225 .store = rdbStorePtr_,
226 .kvStore = kvStorePtr_,
227 .table = tableName
228 };
229
230 err = ThumbnailGenerateHelper::CreateThumbnailBatch(opts);
231 if (err != E_OK) {
232 MEDIA_ERR_LOG("CreateThumbnailBatch failed : %{public}d", err);
233 }
234 if (tableName != AudioColumn::AUDIOS_TABLE) {
235 err = ThumbnailGenerateHelper::CreateLcdBatch(opts);
236 if (err != E_OK) {
237 MEDIA_ERR_LOG("CreateLcdBatch failed : %{public}d", err);
238 }
239 }
240 }
241
242 return err;
243 }
244
LcdAging()245 int32_t ThumbnailService::LcdAging()
246 {
247 int32_t err = 0;
248 vector<string> tableList;
249 tableList.emplace_back(PhotoColumn::PHOTOS_TABLE);
250 tableList.emplace_back(AudioColumn::AUDIOS_TABLE);
251 tableList.emplace_back(MEDIALIBRARY_TABLE);
252
253 for (const auto &tableName : tableList) {
254 ThumbRdbOpt opts = {
255 .store = rdbStorePtr_,
256 .kvStore = kvStorePtr_,
257 .table = tableName,
258 };
259 err = ThumbnailAgingHelper::AgingLcdBatch(opts);
260 if (err != E_OK) {
261 MEDIA_ERR_LOG("AgingLcdBatch failed : %{public}d", err);
262 }
263 }
264
265 return E_OK;
266 }
267
268 #ifdef DISTRIBUTED
LcdDistributeAging(const string & udid)269 int32_t ThumbnailService::LcdDistributeAging(const string &udid)
270 {
271 ThumbRdbOpt opts = {
272 .store = rdbStorePtr_,
273 .kvStore = kvStorePtr_,
274 .udid = udid
275 };
276 int32_t err = ThumbnailAgingHelper::AgingDistributeLcdBatch(opts);
277 if (err != E_OK) {
278 MEDIA_ERR_LOG("AgingDistributeLcdBatch failed : %{public}d", err);
279 return err;
280 }
281 return E_OK;
282 }
283
InvalidateDistributeThumbnail(const string & udid)284 int32_t ThumbnailService::InvalidateDistributeThumbnail(const string &udid)
285 {
286 ThumbRdbOpt opts = {
287 .store = rdbStorePtr_,
288 .kvStore = kvStorePtr_,
289 .udid = udid
290 };
291 int32_t err = ThumbnailAgingHelper::InvalidateDistributeBatch(opts);
292 if (err != E_OK) {
293 MEDIA_ERR_LOG("InvalidateDistributeBatch failed : %{public}d", err);
294 }
295 return err;
296 }
297 #endif
298
InvalidateThumbnail(const std::string & id,const std::string & tableName,const std::string & path)299 void ThumbnailService::InvalidateThumbnail(const std::string &id, const std::string &tableName, const std::string &path)
300 {
301 ThumbRdbOpt opts = {
302 .store = rdbStorePtr_,
303 .path = path,
304 .table = tableName,
305 .row = id,
306 };
307 ThumbnailData thumbnailData;
308 ThumbnailUtils::DeleteOriginImage(opts);
309 }
310 } // namespace Media
311 } // namespace OHOS
312