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 "storage/storage_monitor_service.h"
17
18 #include "cJSON.h"
19 #include "common_event_manager.h"
20 #include "parameters.h"
21 #include "storage_service_errno.h"
22 #include "storage_service_log.h"
23 #include "storage/bundle_manager_connector.h"
24 #include "storage/storage_total_status_service.h"
25
26 using namespace OHOS::StorageService;
27 namespace OHOS {
28 namespace StorageManager {
29 constexpr int32_t CONST_NUM_TWO = 2;
30 constexpr int32_t CONST_NUM_THREE = 3;
31 constexpr int32_t CONST_NUM_ONE_HUNDRED = 100;
32 constexpr int32_t WAIT_THREAD_TIMEOUT_MS = 5;
33 constexpr int32_t DEFAULT_CHECK_INTERVAL = 60 * 1000; // 60s
34 constexpr int32_t STORAGE_THRESHOLD_PERCENTAGE = 5; // 5%
35 constexpr int64_t STORAGE_THRESHOLD_MAX_BYTES = 500 * 1024 * 1024; // 500M
36 constexpr int64_t STORAGE_THRESHOLD_500M = 500 * 1024 * 1024; // 500M
37 constexpr int64_t STORAGE_THRESHOLD_2G = 2000 * 1024 * 1024; // 2G
38 constexpr int32_t STORAGE_LEFT_SIZE_THRESHOLD = 10; // 10%
39 constexpr int32_t SEND_EVENT_INTERVAL = 24; // day
40 constexpr int32_t CLEAN_CACHE_WEEK = 7 * 24; // week
41 constexpr int32_t SEND_EVENT_INTERVAL_HIGH_FREQ = 5; // 5m
42 const std::string PUBLISH_SYSTEM_COMMON_EVENT = "ohos.permission.PUBLISH_SYSTEM_COMMON_EVENT";
43 const std::string SMART_BUNDLE_NAME = "com.ohos.hmos.hiviewcare";
44 const std::string SMART_ACTION = "hicare.event.SMART_NOTIFICATION";
45 const std::string TIMESTAMP_DAY = "persist.storage_manager.timestamp.day";
46 const std::string TIMESTAMP_WEEK = "persist.storage_manager.timestamp.week";
47 const std::string FAULT_ID_ONE = "845010021";
48 const std::string FAULT_ID_TWO = "845010022";
49 const std::string FAULT_ID_THREE = "845010023";
50 const std::string FAULT_SUGGEST_THREE = "545010023";
51 constexpr int RETRY_MAX_TIMES = 3;
52
StorageMonitorService()53 StorageMonitorService::StorageMonitorService() {}
54
~StorageMonitorService()55 StorageMonitorService::~StorageMonitorService()
56 {
57 LOGI("StorageMonitorService Destructor.");
58 std::unique_lock<std::mutex> lock(eventMutex_);
59 if ((eventHandler_ != nullptr) && (eventHandler_->GetEventRunner() != nullptr)) {
60 eventHandler_->RemoveAllEvents();
61 eventHandler_->GetEventRunner()->Stop();
62 }
63 if (eventThread_.joinable()) {
64 eventThread_.join();
65 }
66 eventHandler_ = nullptr;
67 }
68
StartStorageMonitorTask()69 void StorageMonitorService::StartStorageMonitorTask()
70 {
71 LOGI("StorageMonitorService, start deicve storage monitor task.");
72 std::unique_lock<std::mutex> lock(eventMutex_);
73 if (eventHandler_ == nullptr) {
74 eventThread_ = std::thread(&StorageMonitorService::StartEventHandler, this);
75 eventCon_.wait_for(lock, std::chrono::seconds(WAIT_THREAD_TIMEOUT_MS), [this] {
76 return eventHandler_ != nullptr;
77 });
78 }
79
80 auto executeFunc = [this] { Execute(); };
81 eventHandler_->PostTask(executeFunc, DEFAULT_CHECK_INTERVAL);
82 }
83
StartEventHandler()84 void StorageMonitorService::StartEventHandler()
85 {
86 pthread_setname_np(pthread_self(), "storage_monitor_task_event");
87 auto runner = AppExecFwk::EventRunner::Create(false);
88 if (runner == nullptr) {
89 LOGE("event runner is nullptr.");
90 return;
91 }
92 {
93 std::lock_guard<std::mutex> lock(eventMutex_);
94 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
95 }
96 eventCon_.notify_one();
97 runner->Run();
98 }
99
Execute()100 void StorageMonitorService::Execute()
101 {
102 if (eventHandler_ == nullptr) {
103 LOGE("event handler is nullptr.");
104 return;
105 }
106 MonitorAndManageStorage();
107 auto executeFunc = [this] { Execute(); };
108 eventHandler_->PostTask(executeFunc, DEFAULT_CHECK_INTERVAL);
109 }
110
MonitorAndManageStorage()111 void StorageMonitorService::MonitorAndManageStorage()
112 {
113 int64_t totalSize;
114 int32_t err = DelayedSingleton<StorageTotalStatusService>::GetInstance()->GetTotalSize(totalSize);
115 if ((err != E_OK) || (totalSize <= 0)) {
116 LOGE("Get device total size failed.");
117 return;
118 }
119
120 int64_t freeSize;
121 err = DelayedSingleton<StorageTotalStatusService>::GetInstance()->GetFreeSize(freeSize);
122 if ((err != E_OK) || (freeSize < 0)) {
123 LOGE("Get device free size failed.");
124 return;
125 }
126 if (freeSize < (totalSize * STORAGE_LEFT_SIZE_THRESHOLD) / CONST_NUM_ONE_HUNDRED) {
127 CheckAndEventNotify(freeSize, totalSize);
128 CheckAndCleanCache(freeSize, totalSize);
129 hasNotifiedStorageEvent_ = true;
130 } else if (hasNotifiedStorageEvent_) {
131 RefreshAllNotificationTimeStamp();
132 hasNotifiedStorageEvent_ = false;
133 }
134 }
135
CheckAndCleanCache(int64_t freeSize,int64_t totalSize)136 void StorageMonitorService::CheckAndCleanCache(int64_t freeSize, int64_t totalSize)
137 {
138 int64_t lowThreshold = GetLowerThreshold(totalSize);
139 if (lowThreshold <= 0) {
140 LOGE("Lower threshold value is invalid.");
141 return;
142 }
143
144 LOGI("Device storage freeSize=%{public}lld, threshold=%{public}lld", static_cast<long long>(freeSize),
145 static_cast<long long>(lowThreshold));
146
147 std::string freeSizeStr = std::to_string(freeSize);
148 std::string totalSizeStr = std::to_string(totalSize);
149 std::string lowThresholdStr = std::to_string(lowThreshold);
150 std::string storageUsage = "storage usage not enough:freeSize = " + freeSizeStr + ", totalSize = " + totalSizeStr +
151 ", lowThreshold = " + lowThresholdStr;
152 if (freeSize < (lowThreshold * CONST_NUM_THREE) / CONST_NUM_TWO) {
153 CleanBundleCache(lowThreshold);
154 ReportRadarStorageUsage(StorageService::BizStage::BIZ_STAGE_THRESHOLD_MINIMAL, storageUsage);
155 return;
156 }
157
158 if (freeSize > (totalSize * STORAGE_THRESHOLD_PERCENTAGE) / CONST_NUM_ONE_HUNDRED) {
159 CleanBundleCacheByInterval(TIMESTAMP_WEEK, lowThreshold, CLEAN_CACHE_WEEK);
160 ReportRadarStorageUsage(StorageService::BizStage::BIZ_STAGE_THRESHOLD_TEN_PERCENT, storageUsage);
161 } else {
162 CleanBundleCacheByInterval(TIMESTAMP_DAY, lowThreshold, SEND_EVENT_INTERVAL);
163 ReportRadarStorageUsage(StorageService::BizStage::BIZ_STAGE_THRESHOLD_FIVE_PERCENT, storageUsage);
164 }
165 }
166
CleanBundleCacheByInterval(const std::string & timestamp,int64_t lowThreshold,int32_t checkInterval)167 void StorageMonitorService::CleanBundleCacheByInterval(const std::string ×tamp,
168 int64_t lowThreshold, int32_t checkInterval)
169 {
170 auto currentTime = std::chrono::system_clock::now();
171 auto curTimePoint =
172 std::chrono::time_point_cast<std::chrono::hours>(currentTime).time_since_epoch().count();
173 std::string param = system::GetParameter(timestamp, "");
174 if (param.empty()) {
175 LOGI("Not found timestamp from system parameter");
176 return;
177 }
178 uint64_t lastCleanCacheTime = static_cast<uint64_t>(std::atoll(param.c_str()));
179 auto duration = std::chrono::duration_cast<std::chrono::hours>(currentTime -
180 std::chrono::system_clock::time_point(std::chrono::hours(lastCleanCacheTime))).count();
181 LOGI("CleanBundleCache timestamp is %{public}s, duration is %{public}ld", timestamp.c_str(), duration);
182 if (duration >= checkInterval) {
183 CleanBundleCache(lowThreshold);
184 system::SetParameter(timestamp, std::to_string(curTimePoint));
185 }
186 }
187
ReportRadarStorageUsage(enum StorageService::BizStage stage,const std::string & extraData)188 void StorageMonitorService::ReportRadarStorageUsage(enum StorageService::BizStage stage, const std::string &extraData)
189 {
190 LOGI("storage monitor service report radar storage usage start");
191 StorageService::StorageRadar::ReportStorageUsage(stage, extraData);
192 }
193
CleanBundleCache(int64_t lowThreshold)194 void StorageMonitorService::CleanBundleCache(int64_t lowThreshold)
195 {
196 auto bundleMgr = DelayedSingleton<BundleMgrConnector>::GetInstance()->GetBundleMgrProxy();
197 if (bundleMgr == nullptr) {
198 LOGE("Connect bundle manager sa proxy failed.");
199 return;
200 }
201 LOGI("Device storage free size not enough, start clean bundle cache files automatic.");
202 int32_t ret = E_OK;
203 int retryCount = 0;
204 do {
205 ret = bundleMgr->CleanBundleCacheFilesAutomatic(lowThreshold * CONST_NUM_TWO);
206 if (ret == ERR_OK) {
207 LOGI("Invoke bundleMgr interface to clean bundle cache files automatic success.");
208 return;
209 }
210 retryCount ++;
211 LOGE("Invoke bundleMgr interface to clean bundle cache files automatic failed. Retry.");
212 } while (retryCount < RETRY_MAX_TIMES);
213 StorageRadar::ReportBundleMgrResult("CleanBundleCacheFilesAutomatic", ret, DEFAULT_USERID, "");
214 }
215
GetLowerThreshold(int64_t totalSize)216 int64_t StorageMonitorService::GetLowerThreshold(int64_t totalSize)
217 {
218 int64_t lowBytes = (totalSize * STORAGE_THRESHOLD_PERCENTAGE) / CONST_NUM_ONE_HUNDRED;
219 return (lowBytes < STORAGE_THRESHOLD_MAX_BYTES) ? lowBytes : STORAGE_THRESHOLD_MAX_BYTES;
220 }
221
CheckAndEventNotify(int64_t freeSize,int64_t totalSize)222 void StorageMonitorService::CheckAndEventNotify(int64_t freeSize, int64_t totalSize)
223 {
224 LOGI("StorageMonitorService, start CheckAndEventNotify.");
225 std::string freeSizeStr = std::to_string(freeSize);
226 std::string totalSizeStr = std::to_string(totalSize);
227 std::string storageUsage = "storage usage not enough event notify freeSize = " + freeSizeStr + ", totalSize = " +
228 totalSizeStr;
229 if (freeSize < STORAGE_THRESHOLD_500M) {
230 EventNotifyHighFreqHandler();
231 storageUsage += ", freeSize < 500M, success notify event";
232 ReportRadarStorageUsage(StorageService::BizStage::BIZ_STAGE_THRESHOLD_500MB, storageUsage);
233 return;
234 }
235 if (freeSize < STORAGE_THRESHOLD_2G) {
236 EventNotifyFreqHandlerFor2G();
237 storageUsage += ", freeSize < 2G, success notify event";
238 ReportRadarStorageUsage(StorageService::BizStage::BIZ_STAGE_THRESHOLD_2GB, storageUsage);
239 return;
240 }
241 EventNotifyFreqHandlerForTenPercent();
242 }
243
SendSmartNotificationEvent(const std::string & faultDesc,const std::string & faultSuggest,bool isHighFreq)244 void StorageMonitorService::SendSmartNotificationEvent(const std::string &faultDesc,
245 const std::string &faultSuggest,
246 bool isHighFreq)
247 {
248 LOGI("StorageMonitorService, start SendSmartNotificationEvent.");
249 EventFwk::CommonEventPublishInfo publishInfo;
250 const std::string permission = PUBLISH_SYSTEM_COMMON_EVENT;
251 std::vector<std::string> permissions;
252 permissions.emplace_back(permission);
253 publishInfo.SetSubscriberPermissions(permissions);
254 publishInfo.SetOrdered(false);
255 publishInfo.SetSticky(false);
256 publishInfo.SetBundleName(SMART_BUNDLE_NAME);
257
258 AAFwk::Want want;
259 want.SetAction(SMART_ACTION);
260 EventFwk::CommonEventData eventData;
261 eventData.SetWant(want);
262
263 cJSON *root = cJSON_CreateObject();
264 cJSON_AddStringToObject(root, "faultDescription", faultDesc.c_str());
265 cJSON_AddStringToObject(root, "faultSuggestion", faultSuggest.c_str());
266 if (isHighFreq) {
267 cJSON *faultSuggestionParam = cJSON_CreateString("500M");
268 cJSON *faultSuggestionArray = cJSON_CreateArray();
269 cJSON_AddItemToArray(faultSuggestionArray, faultSuggestionParam);
270 cJSON_AddItemToObject(root, "faultSuggestionParams", faultSuggestionArray);
271 }
272 char *json_string = cJSON_Print(root);
273 std::string eventDataStr(json_string);
274 eventDataStr.erase(remove(eventDataStr.begin(), eventDataStr.end(), '\n'), eventDataStr.end());
275 eventDataStr.erase(remove(eventDataStr.begin(), eventDataStr.end(), '\t'), eventDataStr.end());
276
277 LOGI("send message is %{public}s", eventDataStr.c_str());
278 eventData.SetData(eventDataStr);
279 cJSON_Delete(root);
280 EventFwk::CommonEventManager::PublishCommonEvent(eventData, publishInfo, nullptr);
281 }
282
EventNotifyHighFreqHandler()283 void StorageMonitorService::EventNotifyHighFreqHandler()
284 {
285 auto currentTime = std::chrono::system_clock::now();
286 int32_t duration = static_cast<int32_t>(std::chrono::duration_cast<std::chrono::minutes>
287 (currentTime - lastNotificationTimeHighFreq_).count());
288 LOGI("StorageMonitorService high frequency, duration is %{public}d", duration);
289 if (duration >= SEND_EVENT_INTERVAL_HIGH_FREQ) {
290 SendSmartNotificationEvent(FAULT_ID_THREE, FAULT_SUGGEST_THREE, true);
291 lastNotificationTimeHighFreq_ = currentTime;
292 lastNotificationTime_ =
293 std::chrono::time_point_cast<std::chrono::system_clock::duration>(
294 std::chrono::system_clock::now()) - std::chrono::hours(SEND_EVENT_INTERVAL);
295 lastNotificationTime2G_ =
296 std::chrono::time_point_cast<std::chrono::system_clock::duration>(
297 std::chrono::system_clock::now()) - std::chrono::hours(SEND_EVENT_INTERVAL);
298 }
299 }
300
EventNotifyFreqHandlerFor2G()301 void StorageMonitorService::EventNotifyFreqHandlerFor2G()
302 {
303 auto currentTime = std::chrono::system_clock::now();
304 int32_t duration = static_cast<int32_t>(std::chrono::duration_cast<std::chrono::hours>
305 (currentTime - lastNotificationTime2G_).count());
306 LOGW("StorageMonitorService left Storage Size < 2G, duration is %{public}d", duration);
307 if (duration >= SEND_EVENT_INTERVAL) {
308 SendSmartNotificationEvent(FAULT_ID_TWO, FAULT_ID_TWO, false);
309 lastNotificationTime2G_ = currentTime;
310 lastNotificationTime_ =
311 std::chrono::time_point_cast<std::chrono::system_clock::duration>(
312 std::chrono::system_clock::now()) - std::chrono::hours(SEND_EVENT_INTERVAL);
313 lastNotificationTimeHighFreq_ =
314 std::chrono::time_point_cast<std::chrono::system_clock::duration>(
315 std::chrono::system_clock::now()) - std::chrono::minutes(SMART_EVENT_INTERVAL_HIGH_FREQ);
316 }
317 }
318
EventNotifyFreqHandlerForTenPercent()319 void StorageMonitorService::EventNotifyFreqHandlerForTenPercent()
320 {
321 auto currentTime = std::chrono::system_clock::now();
322 int32_t duration = static_cast<int32_t>(std::chrono::duration_cast<std::chrono::hours>
323 (currentTime - lastNotificationTime_).count());
324 LOGW("StorageMonitorService left Storage Size < 10 percent, duration is %{public}d", duration);
325 if (duration >= SEND_EVENT_INTERVAL) {
326 SendSmartNotificationEvent(FAULT_ID_ONE, FAULT_ID_ONE, false);
327 lastNotificationTime_ = currentTime;
328 lastNotificationTime2G_ =
329 std::chrono::time_point_cast<std::chrono::system_clock::duration>(
330 std::chrono::system_clock::now()) - std::chrono::hours(SEND_EVENT_INTERVAL);
331 lastNotificationTimeHighFreq_ =
332 std::chrono::time_point_cast<std::chrono::system_clock::duration>(
333 std::chrono::system_clock::now()) - std::chrono::minutes(SMART_EVENT_INTERVAL_HIGH_FREQ);
334 }
335 }
336
RefreshAllNotificationTimeStamp()337 void StorageMonitorService::RefreshAllNotificationTimeStamp()
338 {
339 lastNotificationTime_ =
340 std::chrono::time_point_cast<std::chrono::system_clock::duration>(
341 std::chrono::system_clock::now()) - std::chrono::hours(SEND_EVENT_INTERVAL);
342
343 lastNotificationTime2G_ =
344 std::chrono::time_point_cast<std::chrono::system_clock::duration>(
345 std::chrono::system_clock::now()) - std::chrono::hours(SEND_EVENT_INTERVAL);
346
347 lastNotificationTimeHighFreq_ =
348 std::chrono::time_point_cast<std::chrono::system_clock::duration>(
349 std::chrono::system_clock::now()) - std::chrono::minutes(SMART_EVENT_INTERVAL_HIGH_FREQ);
350 }
351 } // StorageManager
352 } // OHOS
353