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 <cstdlib>
19 #include <cstring>
20 #include <mntent.h>
21 #include <pthread.h>
22 #include <singleton.h>
23 #include <sys/statvfs.h>
24 #include <unordered_set>
25
26 #include "cJSON.h"
27 #include "common_event_data.h"
28 #include "common_event_manager.h"
29 #include "storage_service_errno.h"
30 #include "storage_service_log.h"
31 #include "storage/bundle_manager_connector.h"
32 #include "storage/storage_total_status_service.h"
33 #include "want.h"
34
35 namespace OHOS {
36 namespace StorageManager {
37 constexpr int32_t CONST_NUM_TWO = 2;
38 constexpr int32_t CONST_NUM_THREE = 3;
39 constexpr int32_t CONST_NUM_ONE_HUNDRED = 100;
40 constexpr int32_t WAIT_THREAD_TIMEOUT_MS = 5;
41 constexpr int32_t DEFAULT_CHECK_INTERVAL = 60 * 1000; // 60s
42 constexpr int32_t STORAGE_THRESHOLD_PERCENTAGE = 5; // 5%
43 constexpr int64_t STORAGE_THRESHOLD_MAX_BYTES = 500 * 1024 * 1024; // 500M
44 constexpr int64_t STORAGE_THRESHOLD_100M = 100 * 1024 * 1024; // 100M
45 constexpr int64_t STORAGE_THRESHOLD_1G = 1000 * 1024 * 1024; // 1G
46 constexpr int32_t STORAGE_LEFT_SIZE_THRESHOLD = 10; // 10%
47 constexpr int32_t SEND_EVENT_INTERVAL = 24; // 24H
48 constexpr int32_t SEND_EVENT_INTERVAL_HIGH_FREQ = 5; // 5m
49 const std::string PUBLISH_SYSTEM_COMMON_EVENT = "ohos.permission.PUBLISH_SYSTEM_COMMON_EVENT";
50 const std::string SMART_BUNDLE_NAME = "com.ohos.hmos.hiviewcare";
51 const std::string SMART_ACTION = "hicare.event.SMART_NOTIFICATION";
52 const std::string FAULT_ID_ONE = "845010021";
53 const std::string FAULT_ID_TWO = "845010022";
54 const std::string FAULT_ID_THREE = "845010023";
55 const std::string FAULT_SUGGEST_THREE = "545010023";
56
StorageMonitorService()57 StorageMonitorService::StorageMonitorService() {}
58
~StorageMonitorService()59 StorageMonitorService::~StorageMonitorService()
60 {
61 LOGD("StorageMonitorService Destructor.");
62 std::unique_lock<std::mutex> lock(eventMutex_);
63 if ((eventHandler_ != nullptr) && (eventHandler_->GetEventRunner() != nullptr)) {
64 eventHandler_->RemoveAllEvents();
65 eventHandler_->GetEventRunner()->Stop();
66 }
67 if (eventThread_.joinable()) {
68 eventThread_.join();
69 }
70 eventHandler_ = nullptr;
71 }
72
StartStorageMonitorTask()73 void StorageMonitorService::StartStorageMonitorTask()
74 {
75 LOGI("StorageMonitorService, start deicve storage monitor task.");
76 std::unique_lock<std::mutex> lock(eventMutex_);
77 if (eventHandler_ == nullptr) {
78 eventThread_ = std::thread(&StorageMonitorService::StartEventHandler, this);
79 eventCon_.wait_for(lock, std::chrono::seconds(WAIT_THREAD_TIMEOUT_MS), [this] {
80 return eventHandler_ != nullptr;
81 });
82 }
83
84 auto executeFunc = [this] { Execute(); };
85 eventHandler_->PostTask(executeFunc, DEFAULT_CHECK_INTERVAL);
86 }
87
StartEventHandler()88 void StorageMonitorService::StartEventHandler()
89 {
90 pthread_setname_np(pthread_self(), "storage_monitor_task_event");
91 auto runner = AppExecFwk::EventRunner::Create(false);
92 if (runner == nullptr) {
93 LOGE("event runner is nullptr.");
94 return;
95 }
96 {
97 std::lock_guard<std::mutex> lock(eventMutex_);
98 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
99 }
100 eventCon_.notify_one();
101 runner->Run();
102 }
103
Execute()104 void StorageMonitorService::Execute()
105 {
106 if (eventHandler_ == nullptr) {
107 LOGE("event handler is nullptr.");
108 return;
109 }
110 CheckAndCleanBundleCache();
111 auto executeFunc = [this] { Execute(); };
112 eventHandler_->PostTask(executeFunc, DEFAULT_CHECK_INTERVAL);
113 }
114
CheckAndCleanBundleCache()115 void StorageMonitorService::CheckAndCleanBundleCache()
116 {
117 int64_t totalSize;
118 int32_t err = DelayedSingleton<StorageTotalStatusService>::GetInstance()->GetTotalSize(totalSize);
119 if ((err != E_OK) || (totalSize <= 0)) {
120 LOGE("Get device total size failed.");
121 return;
122 }
123
124 int64_t freeSize;
125 err = DelayedSingleton<StorageTotalStatusService>::GetInstance()->GetFreeSize(freeSize);
126 if ((err != E_OK) || (freeSize < 0)) {
127 LOGE("Get device free size failed.");
128 return;
129 }
130 if (freeSize < (totalSize * STORAGE_LEFT_SIZE_THRESHOLD) / CONST_NUM_ONE_HUNDRED) {
131 CheckAndEventNotify(freeSize, totalSize);
132 }
133 int64_t lowThreshold = GetLowerThreshold(totalSize);
134 if (lowThreshold <= 0) {
135 LOGE("Lower threshold value is invalid.");
136 return;
137 }
138
139 LOGD("Device storage freeSize=%{public}lld, threshold=%{public}lld", static_cast<long long>(freeSize),
140 static_cast<long long>(lowThreshold));
141 if (freeSize >= (lowThreshold * CONST_NUM_THREE) / CONST_NUM_TWO) {
142 LOGD("The cache clean threshold had not been reached, skip this clean task.");
143 return;
144 }
145
146 auto bundleMgr = DelayedSingleton<BundleMgrConnector>::GetInstance()->GetBundleMgrProxy();
147 if (bundleMgr == nullptr) {
148 LOGE("Connect bundle manager sa proxy failed.");
149 return;
150 }
151 LOGD("Device storage free size not enough, start clean bundle cache files automatic.");
152 auto ret = bundleMgr->CleanBundleCacheFilesAutomatic(lowThreshold * CONST_NUM_TWO);
153 if (ret != ERR_OK) {
154 LOGE("Invoke bundleMgr interface to clean bundle cache files automatic failed.");
155 }
156 }
157
GetLowerThreshold(int64_t totalSize)158 int64_t StorageMonitorService::GetLowerThreshold(int64_t totalSize)
159 {
160 int64_t lowBytes = (totalSize * STORAGE_THRESHOLD_PERCENTAGE) / CONST_NUM_ONE_HUNDRED;
161 return (lowBytes < STORAGE_THRESHOLD_MAX_BYTES) ? lowBytes : STORAGE_THRESHOLD_MAX_BYTES;
162 }
163
CheckAndEventNotify(int64_t freeSize,int64_t totalSize)164 void StorageMonitorService::CheckAndEventNotify(int64_t freeSize, int64_t totalSize)
165 {
166 LOGI("StorageMonitorService, start CheckAndEventNotify.");
167 if (freeSize < STORAGE_THRESHOLD_100M) {
168 EventNotifyHighFreqHandler();
169 return;
170 }
171 auto currentTime = std::chrono::steady_clock::now();
172 int32_t duration = static_cast<int32_t>(std::chrono::duration_cast<std::chrono::hours>
173 (currentTime - lastNotificationTime_).count());
174 LOGI("StorageMonitorService, duration is %{public}d", duration);
175 if (duration >= SEND_EVENT_INTERVAL) {
176 if (freeSize >= STORAGE_THRESHOLD_1G) {
177 SendSmartNotificationEvent(FAULT_ID_ONE, FAULT_ID_ONE, false);
178 } else {
179 SendSmartNotificationEvent(FAULT_ID_TWO, FAULT_ID_TWO, false);
180 }
181 lastNotificationTime_ = currentTime;
182 }
183 }
184
SendSmartNotificationEvent(const std::string & faultDesc,const std::string & faultSuggest,bool isHighFreq)185 void StorageMonitorService::SendSmartNotificationEvent(const std::string &faultDesc,
186 const std::string &faultSuggest,
187 bool isHighFreq)
188 {
189 LOGI("StorageMonitorService, start SendSmartNotificationEvent.");
190 EventFwk::CommonEventPublishInfo publishInfo;
191 const std::string permission = PUBLISH_SYSTEM_COMMON_EVENT;
192 std::vector<std::string> permissions;
193 permissions.emplace_back(permission);
194 publishInfo.SetSubscriberPermissions(permissions);
195 publishInfo.SetOrdered(false);
196 publishInfo.SetSticky(false);
197 publishInfo.SetBundleName(SMART_BUNDLE_NAME);
198
199 AAFwk::Want want;
200 want.SetAction(SMART_ACTION);
201 EventFwk::CommonEventData eventData;
202 eventData.SetWant(want);
203
204 cJSON *root = cJSON_CreateObject();
205 cJSON_AddStringToObject(root, "faultDescription", faultDesc.c_str());
206 cJSON_AddStringToObject(root, "faultSuggestion", faultSuggest.c_str());
207 if (isHighFreq) {
208 cJSON *faultSuggestionParam = cJSON_CreateString("100M");
209 cJSON *faultSuggestionArray = cJSON_CreateArray();
210 cJSON_AddItemToArray(faultSuggestionArray, faultSuggestionParam);
211 cJSON_AddItemToObject(root, "faultSuggestionParams", faultSuggestionArray);
212 }
213 char *json_string = cJSON_Print(root);
214 std::string eventDataStr(json_string);
215 eventDataStr.erase(remove(eventDataStr.begin(), eventDataStr.end(), '\n'), eventDataStr.end());
216 eventDataStr.erase(remove(eventDataStr.begin(), eventDataStr.end(), '\t'), eventDataStr.end());
217
218 LOGI("send message is %{public}s", eventDataStr.c_str());
219 eventData.SetData(eventDataStr);
220 cJSON_Delete(root);
221 EventFwk::CommonEventManager::PublishCommonEvent(eventData, publishInfo, nullptr);
222 }
223
EventNotifyHighFreqHandler()224 void StorageMonitorService::EventNotifyHighFreqHandler()
225 {
226 auto currentTime = std::chrono::steady_clock::now();
227 int32_t duration = static_cast<int32_t>(std::chrono::duration_cast<std::chrono::minutes>
228 (currentTime - lastNotificationTimeHighFreq_).count());
229 LOGI("StorageMonitorService high frequency, duration is %{public}d", duration);
230 if (duration >= SEND_EVENT_INTERVAL_HIGH_FREQ) {
231 SendSmartNotificationEvent(FAULT_ID_THREE, FAULT_SUGGEST_THREE, true);
232 lastNotificationTimeHighFreq_ = currentTime;
233 }
234 }
235 } // StorageManager
236 } // OHOS
237