• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-2023 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 "ithumbnail_helper.h"
18 
19 #include "ability_manager_client.h"
20 #include "hitrace_meter.h"
21 #include "media_column.h"
22 #include "medialibrary_errno.h"
23 #include "media_file_utils.h"
24 #include "media_log.h"
25 #include "rdb_helper.h"
26 #include "single_kvstore.h"
27 #include "thumbnail_const.h"
28 
29 using namespace std;
30 using namespace OHOS::DistributedKv;
31 using namespace OHOS::NativeRdb;
32 
33 namespace OHOS {
34 namespace Media {
GetThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & outData)35 void IThumbnailHelper::GetThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &outData)
36 {
37     if (opts.store == nullptr) {
38         return;
39     }
40     if (!opts.path.empty()) {
41         outData.path = opts.path;
42         outData.id = opts.row;
43         return;
44     }
45     string filesTableName = opts.table;
46     int errCode = E_ERR;
47     if (!opts.networkId.empty()) {
48         filesTableName = opts.store->ObtainDistributedTableName(opts.networkId, opts.table, errCode);
49     }
50     if (filesTableName.empty()) {
51         return;
52     }
53     opts.table = filesTableName;
54     int err;
55     ThumbnailUtils::QueryThumbnailInfo(opts, outData, err);
56     if (err != E_OK) {
57         MEDIA_ERR_LOG("query fail [%{public}d]", err);
58     }
59     return;
60 }
61 
CreateLcd(AsyncTaskData * data)62 void IThumbnailHelper::CreateLcd(AsyncTaskData* data)
63 {
64     GenerateAsyncTaskData* taskData = static_cast<GenerateAsyncTaskData*>(data);
65     DoCreateLcd(taskData->opts, taskData->thumbnailData);
66 }
67 
CreateThumbnail(AsyncTaskData * data)68 void IThumbnailHelper::CreateThumbnail(AsyncTaskData* data)
69 {
70     GenerateAsyncTaskData* taskData = static_cast<GenerateAsyncTaskData*>(data);
71     DoCreateThumbnail(taskData->opts, taskData->thumbnailData);
72 }
73 
AddAsyncTask(MediaLibraryExecute executor,ThumbRdbOpt & opts,ThumbnailData & data,bool isFront)74 void IThumbnailHelper::AddAsyncTask(MediaLibraryExecute executor, ThumbRdbOpt &opts, ThumbnailData &data, bool isFront)
75 {
76     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
77     if (asyncWorker == nullptr) {
78         MEDIA_DEBUG_LOG("IThumbnailHelper::AddAsyncTask asyncWorker is null");
79         return;
80     }
81     GenerateAsyncTaskData* taskData = new (nothrow)GenerateAsyncTaskData();
82     if (taskData == nullptr) {
83         MEDIA_DEBUG_LOG("IThumbnailHelper::GenerateAsyncTaskData taskData is null");
84         return;
85     }
86     taskData->opts = opts;
87     taskData->thumbnailData = data;
88 
89     shared_ptr<MediaLibraryAsyncTask> generateAsyncTask = make_shared<MediaLibraryAsyncTask>(executor, taskData);
90     asyncWorker->AddTask(generateAsyncTask, isFront);
91 }
92 
ThumbnailWait(bool release)93 ThumbnailWait::ThumbnailWait(bool release) : needRelease_(release)
94 {}
95 
~ThumbnailWait()96 ThumbnailWait::~ThumbnailWait()
97 {
98     if (needRelease_) {
99         Notify();
100     }
101 }
102 
103 ThumbnailMap ThumbnailWait::thumbnailMap_;
104 std::shared_mutex ThumbnailWait::mutex_;
105 
WaitFor(const shared_ptr<SyncStatus> & thumbnailWait,int waitMs,unique_lock<mutex> & lck)106 static bool WaitFor(const shared_ptr<SyncStatus>& thumbnailWait, int waitMs, unique_lock<mutex> &lck)
107 {
108     bool ret = thumbnailWait->cond_.wait_for(lck, chrono::milliseconds(waitMs),
109         [thumbnailWait]() { return thumbnailWait->isSyncComplete_; });
110     if (!ret) {
111         MEDIA_INFO_LOG("IThumbnailHelper::Wait wait for lock timeout");
112     }
113     return ret;
114 }
115 
InsertAndWait(const string & id,bool isLcd)116 WaitStatus ThumbnailWait::InsertAndWait(const string &id, bool isLcd)
117 {
118     id_ = id;
119 
120     if (isLcd) {
121         id_ += THUMBNAIL_LCD_SUFFIX;
122     } else {
123         id_ += THUMBNAIL_THUMB_SUFFIX;
124     }
125     unique_lock<shared_mutex> writeLck(mutex_);
126     auto iter = thumbnailMap_.find(id_);
127     if (iter != thumbnailMap_.end()) {
128         auto thumbnailWait = iter->second;
129         unique_lock<mutex> lck(thumbnailWait->mtx_);
130         writeLck.unlock();
131         bool ret = WaitFor(thumbnailWait, WAIT_FOR_MS, lck);
132         if (ret) {
133             return WaitStatus::WAIT_SUCCESS;
134         } else {
135             return WaitStatus::TIMEOUT;
136         }
137     } else {
138         shared_ptr<SyncStatus> thumbnailWait = make_shared<SyncStatus>();
139         thumbnailMap_.insert(ThumbnailMap::value_type(id_, thumbnailWait));
140         return WaitStatus::INSERT;
141     }
142 }
143 
CheckAndWait(const string & id,bool isLcd)144 void ThumbnailWait::CheckAndWait(const string &id, bool isLcd)
145 {
146     id_ = id;
147 
148     if (isLcd) {
149         id_ += THUMBNAIL_LCD_SUFFIX;
150     } else {
151         id_ += THUMBNAIL_THUMB_SUFFIX;
152     }
153     shared_lock<shared_mutex> readLck(mutex_);
154     auto iter = thumbnailMap_.find(id_);
155     if (iter != thumbnailMap_.end()) {
156         auto thumbnailWait = iter->second;
157         unique_lock<mutex> lck(thumbnailWait->mtx_);
158         readLck.unlock();
159         WaitFor(thumbnailWait, WAIT_FOR_MS, lck);
160     }
161 }
162 
Notify()163 void ThumbnailWait::Notify()
164 {
165     unique_lock<shared_mutex> writeLck(mutex_);
166     auto iter = thumbnailMap_.find(id_);
167     if (iter != thumbnailMap_.end()) {
168         auto thumbnailWait = iter->second;
169         thumbnailMap_.erase(iter);
170         {
171             unique_lock<mutex> lck(thumbnailWait->mtx_);
172             writeLck.unlock();
173             thumbnailWait->isSyncComplete_ = true;
174         }
175         thumbnailWait->cond_.notify_all();
176     }
177 }
178 
TryLoadSource(ThumbRdbOpt & opts,ThumbnailData & data,const Size & size,const string & suffix)179 bool IThumbnailHelper::TryLoadSource(ThumbRdbOpt &opts, ThumbnailData &data, const Size &size, const string &suffix)
180 {
181     if (!ThumbnailUtils::LoadSourceImage(data, size, suffix == THUMBNAIL_THUMB_SUFFIX)) {
182         if (opts.path.empty()) {
183             MEDIA_ERR_LOG("LoadSourceImage faild, %{private}s", data.path.c_str());
184             return false;
185         } else {
186             opts.path = "";
187             GetThumbnailInfo(opts, data);
188             string fileName = GetThumbnailPath(data.path, suffix);
189             if (access(fileName.c_str(), F_OK) == 0) {
190                 return true;
191             }
192             if (!ThumbnailUtils::LoadSourceImage(data, size, suffix == THUMBNAIL_THUMB_SUFFIX)) {
193                 return false;
194             }
195         }
196     }
197     return true;
198 }
199 
200 
DoCreateLcd(ThumbRdbOpt & opts,ThumbnailData & data)201 bool IThumbnailHelper::DoCreateLcd(ThumbRdbOpt &opts, ThumbnailData &data)
202 {
203     ThumbnailWait thumbnailWait(true);
204     auto ret = thumbnailWait.InsertAndWait(data.id, true);
205     if (ret == WaitStatus::WAIT_SUCCESS) {
206         return true;
207     }
208 
209     if (!TryLoadSource(opts, data, opts.screenSize, THUMBNAIL_LCD_SUFFIX)) {
210         return false;
211     }
212 
213     if (!ThumbnailUtils::CompressImage(data.source, data.lcd)) {
214         MEDIA_ERR_LOG("CompressImage faild");
215         return false;
216     }
217 
218     int err = ThumbnailUtils::TrySaveFile(data, ThumbnailType::LCD);
219     if (err < 0) {
220         MEDIA_ERR_LOG("SaveLcd faild %{public}d", err);
221         return false;
222     }
223 
224     data.lcd.clear();
225     if (!ThumbnailUtils::UpdateLcdInfo(opts, data, err)) {
226         MEDIA_INFO_LOG("UpdateLcdInfo faild err : %{public}d", err);
227         return false;
228     }
229 
230     return true;
231 }
232 
GenThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,const ThumbnailType type)233 bool IThumbnailHelper::GenThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, const ThumbnailType type)
234 {
235     bool isThumb = false;
236     if (type == ThumbnailType::THUMB) {
237         isThumb = true;
238     }
239     Size size;
240     if (isThumb) {
241         size = { DEFAULT_THUMB_SIZE, DEFAULT_THUMB_SIZE };
242         if (!TryLoadSource(opts, data, size, THUMBNAIL_THUMB_SUFFIX)) {
243             return false;
244         }
245         if (!ThumbnailUtils::CompressImage(data.source, data.thumbnail)) {
246             MEDIA_ERR_LOG("CompressImage faild id %{private}s", opts.row.c_str());
247             return false;
248         }
249     } else {
250         if (type == ThumbnailType::MTH) {
251             size = {DEFAULT_MTH_SIZE, DEFAULT_MTH_SIZE };
252         } else {
253             size = { DEFAULT_YEAR_SIZE, DEFAULT_YEAR_SIZE };
254         }
255         ThumbnailUtils::GenTargetPixelmap(data, size);
256     }
257 
258     int err = ThumbnailUtils::TrySaveFile(data, type);
259     if (err < 0) {
260         MEDIA_ERR_LOG("SaveThumbnailData faild %{public}d", err);
261         return false;
262     }
263     data.thumbnail.clear();
264     return true;
265 }
266 
DoCreateThumbnail(ThumbRdbOpt & opts,ThumbnailData & data)267 bool IThumbnailHelper::DoCreateThumbnail(ThumbRdbOpt &opts, ThumbnailData &data)
268 {
269     ThumbnailWait thumbnailWait(true);
270     auto ret = thumbnailWait.InsertAndWait(data.id, false);
271     if (ret == WaitStatus::WAIT_SUCCESS) {
272         return true;
273     }
274 
275     if (!GenThumbnail(opts, data, ThumbnailType::THUMB)) {
276         return false;
277     }
278     if (!GenThumbnail(opts, data, ThumbnailType::MTH)) {
279         return false;
280     }
281     if (!GenThumbnail(opts, data, ThumbnailType::YEAR)) {
282         return false;
283     }
284     return true;
285 }
286 } // namespace Media
287 } // namespace OHOS