• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ithumbnail_helper.h"
18 
19 #include "ability_manager_client.h"
20 #include "hitrace_meter.h"
21 #include "medialibrary_errno.h"
22 #include "media_log.h"
23 #include "thumbnail_const.h"
24 #include "thumbnail_utils.h"
25 
26 using namespace std;
27 using namespace OHOS::DistributedKv;
28 using namespace OHOS::NativeRdb;
29 
30 namespace OHOS {
31 namespace Media {
QueryThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & outData,int & err)32 shared_ptr<AbsSharedResultSet> IThumbnailHelper::QueryThumbnailInfo(ThumbRdbOpt &opts,
33     ThumbnailData &outData, int &err)
34 {
35     if (opts.store == nullptr) {
36         MEDIA_ERR_LOG("rdbStore is not init");
37         return nullptr;
38     }
39     string filesTableName = MEDIALIBRARY_TABLE;
40     int errCode = E_ERR;
41     if (!opts.networkId.empty()) {
42         filesTableName = opts.store->ObtainDistributedTableName(opts.networkId, MEDIALIBRARY_TABLE, errCode);
43     }
44 
45     MEDIA_DEBUG_LOG("Get filesTableName [ %{public}s ] id [ %{public}s ]", filesTableName.c_str(), opts.row.c_str());
46     opts.table = filesTableName;
47     shared_ptr<AbsSharedResultSet> rdbSet = ThumbnailUtils::QueryThumbnailInfo(opts, outData, err);
48     if (rdbSet == nullptr) {
49         MEDIA_ERR_LOG("QueryThumbnailInfo Faild [ %{public}d ]", err);
50         return nullptr;
51     }
52     return rdbSet;
53 }
54 
CreateLcd(AsyncTaskData * data)55 void IThumbnailHelper::CreateLcd(AsyncTaskData* data)
56 {
57     GenerateAsyncTaskData* taskData = static_cast<GenerateAsyncTaskData*>(data);
58     DoCreateLcd(taskData->opts, taskData->thumbnailData, true);
59 }
60 
CreateThumbnail(AsyncTaskData * data)61 void IThumbnailHelper::CreateThumbnail(AsyncTaskData* data)
62 {
63     GenerateAsyncTaskData* taskData = static_cast<GenerateAsyncTaskData*>(data);
64     DoCreateThumbnail(taskData->opts, taskData->thumbnailData, true);
65 }
66 
AddAsyncTask(MediaLibraryExecute executor,ThumbRdbOpt & opts,ThumbnailData & data,bool isFront)67 void IThumbnailHelper::AddAsyncTask(MediaLibraryExecute executor, ThumbRdbOpt &opts, ThumbnailData &data, bool isFront)
68 {
69     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
70     if (asyncWorker == nullptr) {
71         MEDIA_DEBUG_LOG("IThumbnailHelper::AddAsyncTask asyncWorker is null");
72         return;
73     }
74     GenerateAsyncTaskData* taskData = new (nothrow)GenerateAsyncTaskData();
75     if (taskData == nullptr) {
76         MEDIA_DEBUG_LOG("IThumbnailHelper::GenerateAsyncTaskData taskData is null");
77         return;
78     }
79     taskData->opts = opts;
80     taskData->thumbnailData = data;
81 
82     shared_ptr<MediaLibraryAsyncTask> generateAsyncTask = make_shared<MediaLibraryAsyncTask>(executor, taskData);
83     asyncWorker->AddTask(generateAsyncTask, isFront);
84 }
85 
ThumbnailWait(bool release)86 ThumbnailWait::ThumbnailWait(bool release) : needRelease_(release)
87 {}
88 
~ThumbnailWait()89 ThumbnailWait::~ThumbnailWait()
90 {
91     if (needRelease_) {
92         Notify();
93     }
94 }
95 
96 ThumbnailMap ThumbnailWait::thumbnailMap_;
97 std::shared_mutex ThumbnailWait::mutex_;
98 
WaitFor(const shared_ptr<SyncStatus> & thumbnailWait,int waitMs,unique_lock<mutex> & lck)99 static bool WaitFor(const shared_ptr<SyncStatus>& thumbnailWait, int waitMs, unique_lock<mutex> &lck)
100 {
101     bool ret = thumbnailWait->cond_.wait_for(lck, chrono::milliseconds(waitMs),
102         [thumbnailWait]() { return thumbnailWait->isSyncComplete_; });
103     if (!ret) {
104         MEDIA_INFO_LOG("IThumbnailHelper::Wait wait for lock timeout");
105     }
106     return ret;
107 }
108 
InsertAndWait(const string & id,bool isLcd)109 WaitStatus ThumbnailWait::InsertAndWait(const string &id, bool isLcd)
110 {
111     id_ = id;
112 
113     if (isLcd) {
114         id_ += THUMBNAIL_LCD_END_SUFFIX;
115     }
116     unique_lock<shared_mutex> writeLck(mutex_);
117     auto iter = thumbnailMap_.find(id_);
118     if (iter != thumbnailMap_.end()) {
119         auto thumbnailWait = iter->second;
120         unique_lock<mutex> lck(thumbnailWait->mtx_);
121         writeLck.unlock();
122         bool ret = WaitFor(thumbnailWait, WAIT_FOR_MS, lck);
123         if (ret) {
124             return WaitStatus::WAIT_SUCCESS;
125         } else {
126             return WaitStatus::TIMEOUT;
127         }
128     } else {
129         shared_ptr<SyncStatus> thumbnailWait = make_shared<SyncStatus>();
130         thumbnailMap_.insert(ThumbnailMap::value_type(id_, thumbnailWait));
131         return WaitStatus::INSERT;
132     }
133 }
134 
CheckAndWait(const string & id,bool isLcd)135 void ThumbnailWait::CheckAndWait(const string &id, bool isLcd)
136 {
137     id_ = id;
138 
139     if (isLcd) {
140         id_ += THUMBNAIL_LCD_END_SUFFIX;
141     }
142     shared_lock<shared_mutex> readLck(mutex_);
143     auto iter = thumbnailMap_.find(id_);
144     if (iter != thumbnailMap_.end()) {
145         auto thumbnailWait = iter->second;
146         unique_lock<mutex> lck(thumbnailWait->mtx_);
147         readLck.unlock();
148         WaitFor(thumbnailWait, WAIT_FOR_MS, lck);
149     }
150 }
151 
Notify()152 void ThumbnailWait::Notify()
153 {
154     unique_lock<shared_mutex> writeLck(mutex_);
155     auto iter = thumbnailMap_.find(id_);
156     if (iter != thumbnailMap_.end()) {
157         auto thumbnailWait = iter->second;
158         thumbnailMap_.erase(iter);
159         {
160             unique_lock<mutex> lck(thumbnailWait->mtx_);
161             writeLck.unlock();
162             thumbnailWait->isSyncComplete_ = true;
163         }
164         thumbnailWait->cond_.notify_all();
165     }
166 }
167 
DoCreateLcd(ThumbRdbOpt & opts,ThumbnailData & data,bool force)168 bool IThumbnailHelper::DoCreateLcd(ThumbRdbOpt &opts, ThumbnailData &data, bool force)
169 {
170     ThumbnailWait thumbnailWait(true);
171     auto ret = thumbnailWait.InsertAndWait(data.id, true);
172     int err = 0;
173     if (ret == WaitStatus::WAIT_SUCCESS) {
174         ThumbnailUtils::QueryThumbnailInfo(opts, data, err);
175         return true;
176     }
177 
178     if (!opts.networkId.empty()) {
179         return false;
180     }
181 
182     if (data.dateModified == 0) {
183         ThumbnailUtils::QueryThumbnailInfo(opts, data, err);
184     }
185 
186     if (!ThumbnailUtils::GenLcdKey(data)) {
187         MEDIA_ERR_LOG("GenLcdKey faild");
188         return false;
189     }
190 
191     if (!ThumbnailUtils::IsImageExist(data.lcdKey, opts.networkId, opts.kvStore)) {
192         if (!ThumbnailUtils::LoadSourceImage(data)) {
193             MEDIA_ERR_LOG("LoadSourceImage faild");
194             return false;
195         }
196         if (!ThumbnailUtils::CreateLcdData(data, opts.size)) {
197             MEDIA_ERR_LOG("CreateLcdData faild");
198             return false;
199         }
200 
201         if (ThumbnailUtils::SaveLcdData(data, opts.networkId, opts.kvStore) != Status::SUCCESS) {
202             MEDIA_ERR_LOG("SaveLcdData faild");
203             return false;
204         }
205     } else {
206         return true;
207     }
208 
209     data.lcd.clear();
210     if ((data.dateModified == 0) || force) {
211         ThumbnailUtils::DeleteOriginImage(opts, data);
212     }
213     if (!ThumbnailUtils::UpdateThumbnailInfo(opts, data, err)) {
214         MEDIA_INFO_LOG("UpdateThumbnailInfo faild err : %{public}d", err);
215         return false;
216     }
217 
218     return true;
219 }
220 
DoCreateThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,bool force)221 bool IThumbnailHelper::DoCreateThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, bool force)
222 {
223     ThumbnailWait thumbnailWait(true);
224     auto ret = thumbnailWait.InsertAndWait(data.id, true);
225     int err = 0;
226     if (ret == WaitStatus::WAIT_SUCCESS) {
227         ThumbnailUtils::QueryThumbnailInfo(opts, data, err);
228         return true;
229     }
230     if (!opts.networkId.empty()) {
231         return false;
232     }
233 
234     if (data.dateModified == 0) {
235         ThumbnailUtils::QueryThumbnailInfo(opts, data, err);
236     }
237 
238     if (!ThumbnailUtils::GenThumbnailKey(data)) {
239         MEDIA_ERR_LOG("GenThumbnailKey faild");
240         return false;
241     }
242 
243     if (!ThumbnailUtils::IsImageExist(data.thumbnailKey, opts.networkId, opts.kvStore)) {
244         if (!ThumbnailUtils::LoadSourceImage(data)) {
245             MEDIA_ERR_LOG("LoadSourceImage faild");
246             return false;
247         }
248         if (!ThumbnailUtils::CreateThumbnailData(data)) {
249             MEDIA_ERR_LOG("CreateThumbnailData faild");
250             return false;
251         }
252 
253         if (ThumbnailUtils::SaveThumbnailData(data, opts.networkId, opts.kvStore) != Status::SUCCESS) {
254             MEDIA_ERR_LOG("SaveThumbnailData faild");
255             return false;
256         }
257     }
258 
259     data.thumbnail.clear();
260     if ((data.dateModified == 0) || force) {
261         ThumbnailUtils::DeleteOriginImage(opts, data);
262     }
263     if (!ThumbnailUtils::UpdateThumbnailInfo(opts, data, err)) {
264         MEDIA_ERR_LOG("UpdateThumbnailInfo faild, %{public}d", err);
265         return false;
266     }
267 
268     return true;
269 }
270 
DoThumbnailSync(ThumbRdbOpt & opts,ThumbnailData & outData)271 bool IThumbnailHelper::DoThumbnailSync(ThumbRdbOpt &opts, ThumbnailData &outData)
272 {
273     ThumbnailConnection *conn = new (nothrow) ThumbnailConnection;
274     if (conn == nullptr) {
275         return false;
276     }
277     sptr<AAFwk::IAbilityConnection> callback(conn);
278     int ret = conn->GetRemoteDataShareHelper(opts, callback);
279     if (ret != E_OK) {
280         return false;
281     }
282 
283     vector<string> devices = { opts.networkId };
284     opts.table = MEDIALIBRARY_TABLE;
285     if (ThumbnailUtils::SyncPullTable(opts, devices, true)) {
286         MEDIA_INFO_LOG("GetThumbnailPixelMap SyncPullTable FALSE");
287         return false;
288     }
289     shared_ptr<AbsSharedResultSet> resultSet = QueryThumbnailInfo(opts, outData, ret);
290     if ((resultSet == nullptr)) {
291         MEDIA_ERR_LOG("QueryThumbnailInfo Faild [ %{public}d ]", ret);
292         return false;
293     }
294     return true;
295 }
296 
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)297 void ThumbnailConnection::OnAbilityConnectDone(
298     const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
299 {
300     if (remoteObject == nullptr) {
301         MEDIA_ERR_LOG("OnAbilityConnectDone failed, remote is nullptr");
302         return;
303     }
304     {
305         unique_lock<mutex> lock(status_.mtx_);
306         dataShareProxy_ = iface_cast<DataShare::DataShareProxy>(remoteObject);
307     }
308     status_.cond_.notify_all();
309 }
310 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)311 void ThumbnailConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
312 {
313     MEDIA_DEBUG_LOG("called begin %{public}d", resultCode);
314     unique_lock<mutex> lock(status_.mtx_);
315     dataShareProxy_ = nullptr;
316 }
317 
GetRemoteDataShareHelper(ThumbRdbOpt & opts,sptr<AAFwk::IAbilityConnection> & callback)318 int32_t ThumbnailConnection::GetRemoteDataShareHelper(ThumbRdbOpt &opts, sptr<AAFwk::IAbilityConnection> &callback)
319 {
320     if ((opts.context == nullptr)) {
321         MEDIA_ERR_LOG("context nullptr");
322         return E_ERR;
323     }
324 
325     AAFwk::Want want;
326     want.SetElementName(BUNDLE_NAME, "DataShareExtAbility");
327     want.SetDeviceId(opts.networkId);
328     auto err = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want, callback, opts.context->GetToken());
329     if (err != E_OK) {
330         MEDIA_ERR_LOG("ConnectAbility failed %{public}d", err);
331         return err;
332     }
333     unique_lock<mutex> lock(status_.mtx_);
334     if (status_.cond_.wait_for(lock, chrono::seconds(WAIT_FOR_SECOND),
335         [this] { return dataShareProxy_ != nullptr; })) {
336         MEDIA_DEBUG_LOG("All Wait connect success.");
337     } else {
338         MEDIA_ERR_LOG("All Wait connect timeout.");
339         return E_THUMBNAIL_CONNECT_TIMEOUT;
340     }
341 
342     Uri distriuteGenUri(opts.uri + "/" + DISTRIBUTE_THU_OPRN_CREATE);
343     DataShare::DataShareValuesBucket valuesBucket;
344     valuesBucket.Put(MEDIA_DATA_DB_URI, opts.uri);
345     auto ret = dataShareProxy_->Insert(distriuteGenUri, valuesBucket);
346     MEDIA_DEBUG_LOG("called end ret = %{public}d", ret);
347     return ret;
348 }
349 } // namespace Media
350 } // namespace OHOS
351