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 "MedialibrarySubscribe"
16 
17 #include "medialibrary_subscriber.h"
18 
19 #include <memory>
20 #include "appexecfwk_errors.h"
21 #include "background_cloud_file_processor.h"
22 #include "background_task_mgr_helper.h"
23 #ifdef HAS_BATTERY_MANAGER_PART
24 #include "battery_srv_client.h"
25 #endif
26 #include "bundle_info.h"
27 #include "cloud_media_asset_manager.h"
28 #include "cloud_media_asset_types.h"
29 #include "cloud_sync_utils.h"
30 #include "cloud_upload_checker.h"
31 #include "common_event_manager.h"
32 #include "common_event_support.h"
33 #include "common_event_utils.h"
34 #include "dfx_cloud_manager.h"
35 
36 #include "want.h"
37 #include "post_event_utils.h"
38 #ifdef HAS_POWER_MANAGER_PART
39 #include "power_mgr_client.h"
40 #endif
41 #ifdef HAS_THERMAL_MANAGER_PART
42 #include "thermal_mgr_client.h"
43 #endif
44 
45 #include "medialibrary_album_fusion_utils.h"
46 #include "medialibrary_bundle_manager.h"
47 #include "medialibrary_data_manager.h"
48 #include "medialibrary_errno.h"
49 #include "medialibrary_inotify.h"
50 #include "medialibrary_restore.h"
51 #include "media_file_utils.h"
52 #include "media_log.h"
53 #include "media_scanner_manager.h"
54 #include "application_context.h"
55 #include "ability_manager_client.h"
56 #include "resource_type.h"
57 #include "dfx_manager.h"
58 #include "medialibrary_unistore_manager.h"
59 #include "medialibrary_rdb_utils.h"
60 #include "moving_photo_processor.h"
61 #include "permission_utils.h"
62 #include "thumbnail_generate_worker_manager.h"
63 #include "parameters.h"
64 
65 #ifdef HAS_WIFI_MANAGER_PART
66 #include "wifi_device.h"
67 #endif
68 #include "power_efficiency_manager.h"
69 #include "photo_album_lpath_operation.h"
70 
71 using namespace OHOS::AAFwk;
72 
73 namespace OHOS {
74 namespace Media {
75 // The task can be performed when the battery level reaches the value
76 const int32_t PROPER_DEVICE_BATTERY_CAPACITY = 50;
77 
78 // The task can be performed only when the temperature of the device is lower than the value
79 const int32_t PROPER_DEVICE_TEMPERATURE_LEVEL = 1;
80 const int32_t PROPER_DEVICE_TEMPERATURE_LEVEL_HOT = 3;
81 
82 // WIFI should be available in this state
83 const int32_t WIFI_STATE_CONNECTED = 4;
84 
85 const int32_t DELAY_TASK_TIME = 30000;
86 const int32_t COMMON_EVENT_KEY_GET_DEFAULT_PARAM = -1;
87 const int32_t MegaByte = 1024 * 1024;
88 const int32_t MAX_FILE_SIZE_MB = 200;
89 const std::string COMMON_EVENT_KEY_BATTERY_CAPACITY = "soc";
90 const std::string COMMON_EVENT_KEY_DEVICE_TEMPERATURE = "0";
91 const std::string KEY_HIVIEW_VERSION_TYPE = "const.logsystem.versiontype";
92 
93 // The network should be available in this state
94 const int32_t NET_CONN_STATE_CONNECTED = 3;
95 // The net bearer type is in net_all_capabilities.h
96 const int32_t BEARER_CELLULAR = 0;
97 bool MedialibrarySubscriber::isCellularNetConnected_ = false;
98 bool MedialibrarySubscriber::isWifiConnected_ = false;
99 bool MedialibrarySubscriber::currentStatus_ = false;
100 
101 const std::vector<std::string> MedialibrarySubscriber::events_ = {
102     EventFwk::CommonEventSupport::COMMON_EVENT_CHARGING,
103     EventFwk::CommonEventSupport::COMMON_EVENT_DISCHARGING,
104     EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF,
105     EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON,
106     EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED,
107     EventFwk::CommonEventSupport::COMMON_EVENT_BATTERY_CHANGED,
108     EventFwk::CommonEventSupport::COMMON_EVENT_THERMAL_LEVEL_CHANGED,
109     EventFwk::CommonEventSupport::COMMON_EVENT_WIFI_CONN_STATE,
110     EventFwk::CommonEventSupport::COMMON_EVENT_CONNECTIVITY_CHANGE
111 };
112 
113 const std::map<std::string, StatusEventType> BACKGROUND_OPERATION_STATUS_MAP = {
114     {EventFwk::CommonEventSupport::COMMON_EVENT_CHARGING, StatusEventType::CHARGING},
115     {EventFwk::CommonEventSupport::COMMON_EVENT_DISCHARGING, StatusEventType::DISCHARGING},
116     {EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF, StatusEventType::SCREEN_OFF},
117     {EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON, StatusEventType::SCREEN_ON},
118     {EventFwk::CommonEventSupport::COMMON_EVENT_BATTERY_CHANGED, StatusEventType::BATTERY_CHANGED},
119     {EventFwk::CommonEventSupport::COMMON_EVENT_THERMAL_LEVEL_CHANGED, StatusEventType::THERMAL_LEVEL_CHANGED},
120 };
121 
MedialibrarySubscriber(const EventFwk::CommonEventSubscribeInfo & subscriberInfo)122 MedialibrarySubscriber::MedialibrarySubscriber(const EventFwk::CommonEventSubscribeInfo &subscriberInfo)
123     : EventFwk::CommonEventSubscriber(subscriberInfo)
124 {
125 #ifdef HAS_POWER_MANAGER_PART
126     auto& powerMgrClient = PowerMgr::PowerMgrClient::GetInstance();
127     isScreenOff_ = !powerMgrClient.IsScreenOn();
128 #endif
129 #ifdef HAS_BATTERY_MANAGER_PART
130     auto& batteryClient = PowerMgr::BatterySrvClient::GetInstance();
131     auto chargeState = batteryClient.GetChargingStatus();
132     isCharging_ = (chargeState == PowerMgr::BatteryChargeState::CHARGE_STATE_ENABLE) ||
133         (chargeState == PowerMgr::BatteryChargeState::CHARGE_STATE_FULL);
134     isPowerSufficient_ = batteryClient.GetCapacity() >= PROPER_DEVICE_BATTERY_CAPACITY;
135 #endif
136 #ifdef HAS_THERMAL_MANAGER_PART
137     auto& thermalMgrClient = PowerMgr::ThermalMgrClient::GetInstance();
138     newTemperatureLevel_ = static_cast<int32_t>(thermalMgrClient.GetThermalLevel());
139     isDeviceTemperatureProper_ = newTemperatureLevel_ <= PROPER_DEVICE_TEMPERATURE_LEVEL;
140 #endif
141 #ifdef HAS_WIFI_MANAGER_PART
142     auto wifiDevicePtr = Wifi::WifiDevice::GetInstance(WIFI_DEVICE_ABILITY_ID);
143     if (wifiDevicePtr == nullptr) {
144         MEDIA_ERR_LOG("MedialibrarySubscriber wifiDevicePtr is null");
145     } else {
146         ErrCode ret = wifiDevicePtr->IsConnected(isWifiConnected_);
147         if (ret != Wifi::WIFI_OPT_SUCCESS) {
148             MEDIA_ERR_LOG("MedialibrarySubscriber Get-IsConnected-fail: -%{public}d", ret);
149         }
150     }
151 #endif
152     MEDIA_DEBUG_LOG("MedialibrarySubscriber current status:%{public}d, %{public}d, %{public}d, %{public}d, %{public}d",
153         isScreenOff_, isCharging_, isPowerSufficient_, isDeviceTemperatureProper_, isWifiConnected_);
154 }
155 
~MedialibrarySubscriber()156 MedialibrarySubscriber::~MedialibrarySubscriber()
157 {
158     EndBackgroundOperationThread();
159 }
160 
Subscribe(void)161 bool MedialibrarySubscriber::Subscribe(void)
162 {
163     EventFwk::MatchingSkills matchingSkills;
164     for (auto event : events_) {
165         matchingSkills.AddEvent(event);
166     }
167     EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
168 
169     std::shared_ptr<MedialibrarySubscriber> subscriber = std::make_shared<MedialibrarySubscriber>(subscribeInfo);
170     return EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber);
171 }
172 
IsBetaVersion()173 static bool IsBetaVersion()
174 {
175     static const string versionType = system::GetParameter(KEY_HIVIEW_VERSION_TYPE, "unknown");
176     static bool isBetaVersion = versionType.find("beta") != std::string::npos;
177     return isBetaVersion;
178 }
179 
UploadDBFile()180 static void UploadDBFile()
181 {
182     int64_t begin = MediaFileUtils::UTCTimeMilliSeconds();
183     static const std::string databaseDir = MEDIA_DB_DIR + "/rdb";
184     static const std::vector<std::string> dbFileName = { "/media_library.db",
185                                                          "/media_library.db-shm",
186                                                          "/media_library.db-wal" };
187     static const std::string destPath = "/data/storage/el2/log/logpack";
188     int64_t totalFileSize = 0;
189     for (auto &dbName : dbFileName) {
190         string dbPath = databaseDir + dbName;
191         struct stat statInfo {};
192         if (stat(dbPath.c_str(), &statInfo) != 0) {
193             continue;
194         }
195         totalFileSize += statInfo.st_size;
196     }
197     totalFileSize /= MegaByte; // Convert bytes to MB
198     if (totalFileSize > MAX_FILE_SIZE_MB) {
199         MEDIA_WARN_LOG("DB file over 200MB are not uploaded, totalFileSize is %{public}ld MB",
200             static_cast<long>(totalFileSize));
201         return ;
202     }
203     if (!MediaFileUtils::IsFileExists(destPath) && !MediaFileUtils::CreateDirectory(destPath)) {
204         MEDIA_ERR_LOG("Create dir failed, dir=%{private}s", destPath.c_str());
205         return ;
206     }
207     auto dataManager = MediaLibraryDataManager::GetInstance();
208     if (dataManager == nullptr) {
209         MEDIA_ERR_LOG("dataManager is nullptr");
210         return;
211     }
212     dataManager->UploadDBFileInner();
213     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
214     MEDIA_INFO_LOG("Handle %{public}ld MB DBFile success, cost %{public}ld ms", static_cast<long>(totalFileSize),
215         static_cast<long>(end - begin));
216 }
217 
CheckHalfDayMissions()218 void MedialibrarySubscriber::CheckHalfDayMissions()
219 {
220     if (isScreenOff_ && isCharging_) {
221         if (IsBetaVersion()) {
222             MEDIA_INFO_LOG("Version is BetaVersion, UploadDBFile");
223             UploadDBFile();
224         }
225         DfxManager::GetInstance()->HandleHalfDayMissions();
226         MediaLibraryRestore::GetInstance().CheckBackup();
227     }
228     if (!isScreenOff_ || !isCharging_) {
229         MediaLibraryRestore::GetInstance().InterruptBackup();
230     }
231 }
232 
UpdateCurrentStatus()233 void MedialibrarySubscriber::UpdateCurrentStatus()
234 {
235     std::lock_guard<std::mutex> lock(mutex_);
236     if (deviceTemperatureLevel_ != newTemperatureLevel_) {
237         deviceTemperatureLevel_ = newTemperatureLevel_;
238         ThumbnailService::GetInstance()->NotifyTempStatusForReady(deviceTemperatureLevel_);
239     }
240     bool newStatus = isScreenOff_ && isCharging_ && isPowerSufficient_ && isDeviceTemperatureProper_;
241     if (currentStatus_ == newStatus) {
242         return;
243     }
244 
245     MEDIA_INFO_LOG("update status current:%{public}d, new:%{public}d, %{public}d, %{public}d, %{public}d, %{public}d",
246         currentStatus_, newStatus, isScreenOff_, isCharging_, isPowerSufficient_, isDeviceTemperatureProper_);
247     PowerEfficiencyManager::SetSubscriberStatus(isCharging_, isScreenOff_);
248 
249     currentStatus_ = newStatus;
250     ThumbnailService::GetInstance()->UpdateCurrentStatusForTask(newStatus);
251     EndBackgroundOperationThread();
252     if (currentStatus_) {
253         isTaskWaiting_ = true;
254         backgroundOperationThread_ = std::thread([this] { this->DoBackgroundOperation(); });
255     } else {
256         StopBackgroundOperation();
257     }
258 }
259 
WalCheckPointAsync()260 void MedialibrarySubscriber::WalCheckPointAsync()
261 {
262     if (!isScreenOff_ || !isCharging_) {
263         return;
264     }
265     std::thread(MediaLibraryRdbStore::WalCheckPoint).detach();
266 }
267 
UpdateBackgroundOperationStatus(const AAFwk::Want & want,const StatusEventType statusEventType)268 void MedialibrarySubscriber::UpdateBackgroundOperationStatus(
269     const AAFwk::Want &want, const StatusEventType statusEventType)
270 {
271     switch (statusEventType) {
272         case StatusEventType::SCREEN_OFF:
273             isScreenOff_ = true;
274             CheckHalfDayMissions();
275             WalCheckPointAsync();
276             break;
277         case StatusEventType::SCREEN_ON:
278             isScreenOff_ = false;
279             CheckHalfDayMissions();
280             break;
281         case StatusEventType::CHARGING:
282             isCharging_ = true;
283             CheckHalfDayMissions();
284             WalCheckPointAsync();
285             break;
286         case StatusEventType::DISCHARGING:
287             isCharging_ = false;
288             CheckHalfDayMissions();
289             break;
290         case StatusEventType::BATTERY_CHANGED:
291             isPowerSufficient_ = want.GetIntParam(COMMON_EVENT_KEY_BATTERY_CAPACITY,
292                 COMMON_EVENT_KEY_GET_DEFAULT_PARAM) >= PROPER_DEVICE_BATTERY_CAPACITY;
293             break;
294         case StatusEventType::THERMAL_LEVEL_CHANGED: {
295             newTemperatureLevel_ = want.GetIntParam(COMMON_EVENT_KEY_DEVICE_TEMPERATURE,
296                 COMMON_EVENT_KEY_GET_DEFAULT_PARAM);
297             isDeviceTemperatureProper_ = newTemperatureLevel_ <= PROPER_DEVICE_TEMPERATURE_LEVEL;
298             PowerEfficiencyManager::UpdateAlbumUpdateInterval(isDeviceTemperatureProper_);
299             break;
300         }
301         default:
302             MEDIA_WARN_LOG("StatusEventType:%{public}d is not invalid", statusEventType);
303             return;
304     }
305 
306     UpdateCurrentStatus();
307     UpdateBackgroundTimer();
308 }
309 
UpdateCloudMediaAssetDownloadStatus(const AAFwk::Want & want,const StatusEventType statusEventType)310 void MedialibrarySubscriber::UpdateCloudMediaAssetDownloadStatus(const AAFwk::Want &want,
311     const StatusEventType statusEventType)
312 {
313     if (statusEventType != StatusEventType::THERMAL_LEVEL_CHANGED) {
314         return;
315     }
316     int32_t taskStatus = CloudMediaAssetManager::GetInstance().GetTaskStatus();
317     int32_t downloadType = CloudMediaAssetManager::GetInstance().GetDownloadType();
318     bool foregroundTemperature = want.GetIntParam(COMMON_EVENT_KEY_DEVICE_TEMPERATURE,
319         COMMON_EVENT_KEY_GET_DEFAULT_PARAM) <= PROPER_DEVICE_TEMPERATURE_LEVEL_HOT;
320     if (!foregroundTemperature && downloadType == static_cast<int32_t>(CloudMediaDownloadType::DOWNLOAD_FORCE)) {
321         CloudMediaAssetManager::GetInstance().PauseDownloadCloudAsset(CloudMediaTaskPauseCause::TEMPERATURE_LIMIT);
322         return;
323     }
324     if (foregroundTemperature && taskStatus == static_cast<int32_t>(CloudMediaAssetTaskStatus::PAUSED)) {
325         CloudMediaAssetManager::GetInstance().RecoverDownloadCloudAsset(
326             CloudMediaTaskRecoverCause::FOREGROUND_TEMPERATURE_PROPER);
327     }
328 }
329 
IsCellularNetConnected()330 bool MedialibrarySubscriber::IsCellularNetConnected()
331 {
332     return isCellularNetConnected_;
333 }
334 
IsWifiConnected()335 bool MedialibrarySubscriber::IsWifiConnected()
336 {
337     return isWifiConnected_;
338 }
339 
IsCurrentStatusOn()340 bool MedialibrarySubscriber::IsCurrentStatusOn()
341 {
342     return currentStatus_;
343 }
344 
UpdateCloudMediaAssetDownloadTaskStatus()345 void MedialibrarySubscriber::UpdateCloudMediaAssetDownloadTaskStatus()
346 {
347     if (!isCellularNetConnected_) {
348         MEDIA_INFO_LOG("CellularNet not connected.");
349         int32_t taskStatus = CloudMediaAssetManager::GetInstance().GetTaskStatus();
350         if (taskStatus == static_cast<int32_t>(CloudMediaAssetTaskStatus::PAUSED)) {
351             CloudMediaAssetManager::GetInstance().PauseDownloadCloudAsset(CloudMediaTaskPauseCause::NETWORK_FLOW_LIMIT);
352         }
353         return;
354     }
355     if (CloudSyncUtils::IsUnlimitedTrafficStatusOn()) {
356         CloudMediaAssetManager::GetInstance().RecoverDownloadCloudAsset(CloudMediaTaskRecoverCause::NETWORK_NORMAL);
357     } else if (!isWifiConnected_) {
358         CloudMediaAssetManager::GetInstance().PauseDownloadCloudAsset(CloudMediaTaskPauseCause::WIFI_UNAVAILABLE);
359     }
360 }
361 
OnReceiveEvent(const EventFwk::CommonEventData & eventData)362 void MedialibrarySubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData)
363 {
364     const AAFwk::Want &want = eventData.GetWant();
365     std::string action = want.GetAction();
366     if (action != EventFwk::CommonEventSupport::COMMON_EVENT_BATTERY_CHANGED) {
367         MEDIA_INFO_LOG("OnReceiveEvent action:%{public}s.", action.c_str());
368     }
369     if (action == EventFwk::CommonEventSupport::COMMON_EVENT_WIFI_CONN_STATE) {
370         isWifiConnected_ = eventData.GetCode() == WIFI_STATE_CONNECTED;
371         UpdateBackgroundTimer();
372         if (isWifiConnected_) {
373             CloudMediaAssetManager::GetInstance().RecoverDownloadCloudAsset(CloudMediaTaskRecoverCause::NETWORK_NORMAL);
374         }
375     } else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_CONNECTIVITY_CHANGE) {
376         int netType = want.GetIntParam("NetType", -1);
377         bool cellularNetConnected = eventData.GetCode() == NET_CONN_STATE_CONNECTED;
378         isCellularNetConnected_ = netType == BEARER_CELLULAR ? cellularNetConnected : isCellularNetConnected_;
379         UpdateCloudMediaAssetDownloadTaskStatus();
380     } else if (BACKGROUND_OPERATION_STATUS_MAP.count(action) != 0) {
381         UpdateBackgroundOperationStatus(want, BACKGROUND_OPERATION_STATUS_MAP.at(action));
382         UpdateCloudMediaAssetDownloadStatus(want, BACKGROUND_OPERATION_STATUS_MAP.at(action));
383     } else if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED) == 0) {
384         string packageName = want.GetElement().GetBundleName();
385         RevertPendingByPackage(packageName);
386         MediaLibraryBundleManager::GetInstance()->Clear();
387         PermissionUtils::ClearBundleInfoInCache();
388     }
389 }
390 
GetNowTime()391 int64_t MedialibrarySubscriber::GetNowTime()
392 {
393     struct timespec t;
394     constexpr int64_t SEC_TO_MSEC = 1e3;
395     constexpr int64_t MSEC_TO_NSEC = 1e6;
396     clock_gettime(CLOCK_REALTIME, &t);
397     return t.tv_sec * SEC_TO_MSEC + t.tv_nsec / MSEC_TO_NSEC;
398 }
399 
Init()400 void MedialibrarySubscriber::Init()
401 {
402     lockTime_ = GetNowTime();
403     agingCount_ = 0;
404 }
405 
DeleteTemporaryPhotos()406 void DeleteTemporaryPhotos()
407 {
408     auto dataManager = MediaLibraryDataManager::GetInstance();
409     if (dataManager == nullptr) {
410         return;
411     }
412 
413     string UriString = PAH_DISCARD_CAMERA_PHOTO;
414     MediaFileUtils::UriAppendKeyValue(UriString, URI_PARAM_API_VERSION, to_string(MEDIA_API_VERSION_V10));
415     Uri uri(UriString);
416     MediaLibraryCommand cmd(uri);
417     DataShare::DataShareValuesBucket valuesBucket;
418     valuesBucket.Put(PhotoColumn::PHOTO_IS_TEMP, true);
419     DataShare::DataSharePredicates predicates;
420 
421     // 24H之前的数据
422     int64_t current = MediaFileUtils::UTCTimeMilliSeconds();
423     int64_t timeBefore24Hours = current - 24 * 60 * 60 * 1000;
424     string where = PhotoColumn::PHOTO_IS_TEMP + " = 1 AND (" + PhotoColumn::MEDIA_DATE_ADDED + " <= " +
425         to_string(timeBefore24Hours) + " OR " + MediaColumn::MEDIA_ID + " NOT IN (SELECT " + MediaColumn::MEDIA_ID +
426         " FROM (SELECT " + MediaColumn::MEDIA_ID + " FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
427         PhotoColumn::PHOTO_IS_TEMP + " = 1 " + "ORDER BY " + MediaColumn::MEDIA_ID +
428         " DESC LIMIT 50)) AND (select COUNT(1) from " + PhotoColumn::PHOTOS_TABLE +
429         " where " + PhotoColumn::PHOTO_IS_TEMP + " = 1) > 100) ";
430     predicates.SetWhereClause(where);
431 
432     auto changedRows = dataManager->Update(cmd, valuesBucket, predicates);
433     if (changedRows < 0) {
434         MEDIA_INFO_LOG("Failed to update property of asset, err: %{public}d", changedRows);
435         return;
436     }
437     MEDIA_INFO_LOG("delete %{public}d temp files exceeding 24 hous or exceed maximum quantity.", changedRows);
438 }
439 
DoThumbnailOperation()440 void MedialibrarySubscriber::DoThumbnailOperation()
441 {
442     auto dataManager = MediaLibraryDataManager::GetInstance();
443     if (dataManager == nullptr) {
444         return;
445     }
446 
447     auto result = dataManager->GenerateThumbnailBackground();
448     if (result != E_OK) {
449         MEDIA_ERR_LOG("GenerateThumbnailBackground faild");
450     }
451 
452     result = dataManager->UpgradeThumbnailBackground(isWifiConnected_);
453     if (result != E_OK) {
454         MEDIA_ERR_LOG("UpgradeThumbnailBackground faild");
455     }
456 
457     result = dataManager->DoAging();
458     if (result != E_OK) {
459         MEDIA_ERR_LOG("DoAging faild");
460     }
461 
462     shared_ptr<int> trashCountPtr = make_shared<int>();
463     result = dataManager->DoTrashAging(trashCountPtr);
464     if (result != E_OK) {
465         MEDIA_ERR_LOG("DoTrashAging faild");
466     }
467     VariantMap map = {{KEY_COUNT, *trashCountPtr}};
468     PostEventUtils::GetInstance().PostStatProcess(StatType::AGING_STAT, map);
469 }
470 
QueryBurstNeedUpdate(AsyncTaskData * data)471 static void QueryBurstNeedUpdate(AsyncTaskData *data)
472 {
473     auto dataManager = MediaLibraryDataManager::GetInstance();
474     if (dataManager == nullptr) {
475         return;
476     }
477 
478     int32_t result = dataManager->UpdateBurstFromGallery();
479     if (result != E_OK) {
480         MEDIA_ERR_LOG("UpdateBurstFromGallery faild");
481     }
482 }
483 
DoUpdateBurstFromGallery()484 static int32_t DoUpdateBurstFromGallery()
485 {
486     MEDIA_INFO_LOG("Begin DoUpdateBurstFromGallery");
487     auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
488     if (asyncWorker == nullptr) {
489         MEDIA_ERR_LOG("Failed to get async worker instance!");
490         return E_FAIL;
491     }
492     shared_ptr<MediaLibraryAsyncTask> updateBurstTask =
493         make_shared<MediaLibraryAsyncTask>(QueryBurstNeedUpdate, nullptr);
494     if (updateBurstTask != nullptr) {
495         asyncWorker->AddTask(updateBurstTask, false);
496     } else {
497         MEDIA_ERR_LOG("Failed to create async task for updateBurstTask!");
498         return E_FAIL;
499     }
500     return E_SUCCESS;
501 }
502 
UpdateDateTakenWhenZero(AsyncTaskData * data)503 static void UpdateDateTakenWhenZero(AsyncTaskData *data)
504 {
505     auto dataManager = MediaLibraryDataManager::GetInstance();
506     if (dataManager == nullptr) {
507         MEDIA_ERR_LOG("Failed to MediaLibraryDataManager instance!");
508         return;
509     }
510 
511     int32_t result = dataManager->UpdateDateTakenWhenZero();
512     if (result != E_OK) {
513         MEDIA_ERR_LOG("UpdateDateTakenWhenZero faild, result = %{public}d", result);
514     }
515 }
516 
DoUpdateDateTakenWhenZero()517 static int32_t DoUpdateDateTakenWhenZero()
518 {
519     MEDIA_DEBUG_LOG("Begin DoUpdateDateTakenWhenZero");
520     auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
521     if (asyncWorker == nullptr) {
522         MEDIA_ERR_LOG("Failed to get async worker instance!");
523         return E_FAIL;
524     }
525     shared_ptr<MediaLibraryAsyncTask> UpdateDateTakenWhenZeroTask =
526         make_shared<MediaLibraryAsyncTask>(UpdateDateTakenWhenZero, nullptr);
527     if (UpdateDateTakenWhenZeroTask != nullptr) {
528         asyncWorker->AddTask(UpdateDateTakenWhenZeroTask, false);
529     } else {
530         MEDIA_ERR_LOG("Failed to create async task for UpdateDateTakenWhenZeroTask !");
531         return E_FAIL;
532     }
533     return E_SUCCESS;
534 }
535 
RecoverBackgroundDownloadCloudMediaAsset()536 static void RecoverBackgroundDownloadCloudMediaAsset()
537 {
538     if (!CloudMediaAssetManager::GetInstance().SetBgDownloadPermission(true)) {
539         return;
540     }
541     int32_t ret = CloudMediaAssetManager::GetInstance().RecoverDownloadCloudAsset(
542         CloudMediaTaskRecoverCause::BACKGROUND_TASK_AVAILABLE);
543     if (ret != E_OK) {
544         MEDIA_ERR_LOG("RecoverDownloadCloudAsset faild");
545     }
546 }
547 
UpdateBurstCoverLevelFromGallery(AsyncTaskData * data)548 static void UpdateBurstCoverLevelFromGallery(AsyncTaskData *data)
549 {
550     auto dataManager = MediaLibraryDataManager::GetInstance();
551     if (dataManager == nullptr) {
552         return;
553     }
554 
555     int32_t result = dataManager->UpdateBurstCoverLevelFromGallery();
556     if (result != E_OK) {
557         MEDIA_ERR_LOG("UpdateBurstCoverLevelFromGallery faild");
558     }
559 }
560 
DoUpdateBurstCoverLevelFromGallery()561 static int32_t DoUpdateBurstCoverLevelFromGallery()
562 {
563     MEDIA_INFO_LOG("Begin DoUpdateBurstCoverLevelFromGallery");
564     auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
565     if (asyncWorker == nullptr) {
566         MEDIA_ERR_LOG("Failed to get async worker instance!");
567         return E_FAIL;
568     }
569     shared_ptr<MediaLibraryAsyncTask> updateBurstCoverLevelTask =
570         make_shared<MediaLibraryAsyncTask>(UpdateBurstCoverLevelFromGallery, nullptr);
571     if (updateBurstCoverLevelTask != nullptr) {
572         asyncWorker->AddTask(updateBurstCoverLevelTask, false);
573     } else {
574         MEDIA_ERR_LOG("Failed to create async task for updateBurstCoverLevelTask!");
575         return E_FAIL;
576     }
577     return E_SUCCESS;
578 }
579 
DoBackgroundOperation()580 void MedialibrarySubscriber::DoBackgroundOperation()
581 {
582     if (!IsDelayTaskTimeOut() || !currentStatus_) {
583         MEDIA_INFO_LOG("The conditions for DoBackgroundOperation are not met, will return.");
584         return;
585     }
586 
587     // delete temporary photos
588     DeleteTemporaryPhotos();
589 
590     BackgroundTaskMgr::EfficiencyResourceInfo resourceInfo = BackgroundTaskMgr::EfficiencyResourceInfo(
591         BackgroundTaskMgr::ResourceType::CPU, true, 0, "apply", true, true);
592     BackgroundTaskMgr::BackgroundTaskMgrHelper::ApplyEfficiencyResources(resourceInfo);
593     Init();
594     DoThumbnailOperation();
595     // update burst from gallery
596     int32_t ret = DoUpdateBurstFromGallery();
597     if (ret != E_OK) {
598         MEDIA_ERR_LOG("DoUpdateBurstFromGallery faild");
599     }
600     CloudUploadChecker::HandleNoOriginPhoto();
601     ret = DoUpdateDateTakenWhenZero();
602     if (ret != E_OK) {
603         MEDIA_ERR_LOG("DoUpdateDateTakenWhenZero faild");
604     }
605     ret = DoUpdateBurstCoverLevelFromGallery();
606     CHECK_AND_PRINT_LOG(ret == E_OK, "DoUpdateBurstCoverLevelFromGallery faild");
607     RecoverBackgroundDownloadCloudMediaAsset();
608     CloudMediaAssetManager::GetInstance().StartDeleteCloudMediaAssets();
609     // compat old-version moving photo
610     MovingPhotoProcessor::StartProcess();
611     MediaLibraryAlbumFusionUtils::CleanInvalidCloudAlbumAndData();
612     auto watch = MediaLibraryInotify::GetInstance();
613     if (watch != nullptr) {
614         watch->DoAging();
615     }
616 }
617 
PauseBackgroundDownloadCloudMedia()618 static void PauseBackgroundDownloadCloudMedia()
619 {
620     if (!CloudMediaAssetManager::GetInstance().SetBgDownloadPermission(false)) {
621         return;
622     }
623     int32_t taskStatus = static_cast<int32_t>(CloudMediaAssetTaskStatus::DOWNLOADING);
624     int32_t downloadType = static_cast<int32_t>(CloudMediaDownloadType::DOWNLOAD_GENTLE);
625     if (CloudMediaAssetManager::GetInstance().GetTaskStatus() == taskStatus &&
626         CloudMediaAssetManager::GetInstance().GetDownloadType() == downloadType) {
627         CloudMediaAssetManager::GetInstance().PauseDownloadCloudAsset(
628             CloudMediaTaskPauseCause::BACKGROUND_TASK_UNAVAILABLE);
629     }
630 }
631 
StopBackgroundOperation()632 void MedialibrarySubscriber::StopBackgroundOperation()
633 {
634     MovingPhotoProcessor::StopProcess();
635     MediaLibraryDataManager::GetInstance()->InterruptBgworker();
636     PhotoAlbumLPathOperation::GetInstance().Stop();
637     PauseBackgroundDownloadCloudMedia();
638     CloudMediaAssetManager::GetInstance().StopDeleteCloudMediaAssets();
639 }
640 
641 #ifdef MEDIALIBRARY_MTP_ENABLE
DoStartMtpService()642 void MedialibrarySubscriber::DoStartMtpService()
643 {
644     AAFwk::Want want;
645     want.SetElementName("com.ohos.medialibrary.medialibrarydata", "MtpService");
646     auto abilityContext = AbilityRuntime::Context::GetApplicationContext();
647     ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want, abilityContext->GetToken(),
648         OHOS::AAFwk::DEFAULT_INVAL_VALUE);
649     MEDIA_INFO_LOG("MedialibrarySubscriber::DoStartMtpService. End calling StartAbility. ret=%{public}d", err);
650 }
651 #endif
652 
RevertPendingByPackage(const std::string & bundleName)653 void MedialibrarySubscriber::RevertPendingByPackage(const std::string &bundleName)
654 {
655     MediaLibraryDataManager::GetInstance()->RevertPendingByPackage(bundleName);
656 }
657 
UpdateBackgroundTimer()658 void MedialibrarySubscriber::UpdateBackgroundTimer()
659 {
660     if (isCharging_ && isScreenOff_) {
661         CloudSyncDfxManager::GetInstance().RunDfx();
662     }
663 
664     ThumbnailGenerateWorkerManager::GetInstance().TryCloseThumbnailWorkerTimer();
665 
666     std::lock_guard<std::mutex> lock(mutex_);
667     bool newStatus = isScreenOff_ && isCharging_ && isPowerSufficient_ &&
668         isDeviceTemperatureProper_ && isWifiConnected_;
669     if (timerStatus_ == newStatus) {
670         return;
671     }
672 
673     MEDIA_INFO_LOG("update timer status current:%{public}d, new:%{public}d, %{public}d, %{public}d, %{public}d, "
674         "%{public}d, %{public}d",
675         timerStatus_, newStatus, isScreenOff_, isCharging_, isPowerSufficient_, isDeviceTemperatureProper_,
676         isWifiConnected_);
677 
678     timerStatus_ = newStatus;
679     if (timerStatus_) {
680         BackgroundCloudFileProcessor::StartTimer();
681     } else {
682         BackgroundCloudFileProcessor::StopTimer();
683     }
684 }
685 
IsDelayTaskTimeOut()686 bool MedialibrarySubscriber::IsDelayTaskTimeOut()
687 {
688     std::unique_lock<std::mutex> lock(delayTaskLock_);
689     return !delayTaskCv_.wait_for(lock, std::chrono::milliseconds(DELAY_TASK_TIME), [this]() {
690         return !isTaskWaiting_;
691     });
692 }
693 
EndBackgroundOperationThread()694 void MedialibrarySubscriber::EndBackgroundOperationThread()
695 {
696     {
697         std::unique_lock<std::mutex> lock(delayTaskLock_);
698         isTaskWaiting_ = false;
699     }
700     delayTaskCv_.notify_all();
701     if (!backgroundOperationThread_.joinable()) {
702         return;
703     }
704     backgroundOperationThread_.join();
705 }
706 }  // namespace Media
707 }  // namespace OHOS
708