1 /*
2 * Copyright (c) 2025 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 #include "dm_freeze_process.h"
16
17 #include "cJSON.h"
18 #include "datetime_ex.h"
19 #include "dm_anonymous.h"
20 #include "dm_device_info.h"
21 #include "dm_error_type.h"
22 #include "dm_log.h"
23
24 namespace OHOS {
25 namespace DistributedHardware {
26 namespace {
27 constexpr const char* BIND_FAILED_EVENTS_KEY = "bindFailedEvents";
28 constexpr const char* FREEZE_STATE_KEY = "freezeState";
29 constexpr const char* START_FREEZE_TIME_KEY = "startFreezeTimeStamp";
30 constexpr const char* STOP_FREEZE_TIME_KEY = "stopFreezeTimeStamp";
31 constexpr const char* FAILED_TIMES_STAMPS_KEY = "failedTimeStamps";
32 constexpr const char* FREEZE_TIMES_STAMPS_KEY = "freezeTimeStamps";
33 constexpr const char* IS_NEED_FREEZE = "IsNeedFreeze";
34 constexpr const char* NEED_FREEZE = "0";
35 constexpr const char* NO_NEED_FREEZE = "1";
36 constexpr int32_t MAX_CONTINUOUS_BIND_FAILED_NUM = 2;
37 constexpr int64_t CONTINUEOUS_FAILED_INTERVAL = 6 * 60;
38 constexpr int64_t DATA_REFRESH_INTERVAL = 20 * 60;
39 constexpr int64_t NOT_FREEZE_DURATION_SEC = 0;
40 constexpr int64_t FIRST_FREEZE_DURATION_SEC = 60;
41 constexpr int64_t SECOND_FREEZE_DURATION_SEC = 3 * 60;
42 constexpr int64_t THIRD_FREEZE_DURATION_SEC = 5 * 60;
43 constexpr int64_t MAX_FREEZE_DURATION_SEC = 10 * 60;
44 }
45
46 DM_IMPLEMENT_SINGLE_INSTANCE(FreezeProcess);
47
SyncFreezeData()48 int32_t FreezeProcess::SyncFreezeData()
49 {
50 LOGI("called");
51 std::string freezeStatesValue;
52 int32_t ret = KVAdapterManager::GetInstance().GetFreezeData(FREEZE_STATE_KEY, freezeStatesValue);
53 if (ret != DM_OK) {
54 LOGE("Get freeze states data failed, ret: %{public}d", ret);
55 return ret;
56 }
57 DeviceFreezeState freezeStateObj;
58 ret = ConvertJsonToDeviceFreezeState(freezeStatesValue, freezeStateObj);
59 if (ret != DM_OK) {
60 LOGE("ConvertJsonToDeviceFreezeState, ret: %{public}d", ret);
61 return ret;
62 }
63 {
64 std::lock_guard<std::mutex> lock(freezeStateCacheMtx_);
65 freezeStateCache_ = freezeStateObj;
66 }
67 std::string bindFailedEventsValue;
68 ret = KVAdapterManager::GetInstance().GetFreezeData(BIND_FAILED_EVENTS_KEY, bindFailedEventsValue);
69 if (ret != DM_OK) {
70 LOGE("Get bind failed events data failed, ret: %{public}d", ret);
71 return ret;
72 }
73 BindFailedEvents bindFailedEventsObj;
74 ret = ConvertJsonToBindFailedEvents(bindFailedEventsValue, bindFailedEventsObj);
75 if (ret != DM_OK) {
76 LOGE("ConvertJsonToBindFailedEvents, ret: %{public}d", ret);
77 return ret;
78 }
79 std::lock_guard<std::mutex> lock(bindFailedEventsCacheMtx_);
80 bindFailedEventsCache_ = bindFailedEventsObj;
81 LOGI("Sync freeze data success");
82 return DM_OK;
83 }
84
ConvertJsonToDeviceFreezeState(const std::string & result,DeviceFreezeState & freezeStateObj)85 int32_t FreezeProcess::ConvertJsonToDeviceFreezeState(const std::string &result, DeviceFreezeState &freezeStateObj)
86 {
87 if (result.empty()) {
88 LOGE("result is empty");
89 return ERR_DM_FAILED;
90 }
91 JsonObject resultJson(result);
92 if (resultJson.IsDiscarded()) {
93 LOGE("resultJson parse failed");
94 return ERR_DM_FAILED;
95 }
96 if (IsInt64(resultJson, START_FREEZE_TIME_KEY)) {
97 freezeStateObj.startFreezeTimeStamp = resultJson[START_FREEZE_TIME_KEY].Get<int64_t>();
98 }
99 if (IsInt64(resultJson, STOP_FREEZE_TIME_KEY)) {
100 freezeStateObj.stopFreezeTimeStamp = resultJson[STOP_FREEZE_TIME_KEY].Get<int64_t>();
101 }
102 LOGI("ConvertJsonToDeviceFreezeState success");
103 return DM_OK;
104 }
105
ConvertJsonToBindFailedEvents(const std::string & result,BindFailedEvents & bindFailedEventsObj)106 int32_t FreezeProcess::ConvertJsonToBindFailedEvents(const std::string &result, BindFailedEvents &bindFailedEventsObj)
107 {
108 if (result.empty()) {
109 LOGE("result is empty");
110 return ERR_DM_FAILED;
111 }
112 JsonObject resultJson(result);
113 if (resultJson.IsDiscarded()) {
114 LOGE("resultJson parse failed");
115 return ERR_DM_FAILED;
116 }
117 if (IsArray(resultJson, FAILED_TIMES_STAMPS_KEY)) {
118 std::vector<int64_t> failedTimeStampsTmp;
119 resultJson[FAILED_TIMES_STAMPS_KEY].Get(failedTimeStampsTmp);
120 bindFailedEventsObj.failedTimeStamps = failedTimeStampsTmp;
121 }
122 if (IsArray(resultJson, FREEZE_TIMES_STAMPS_KEY)) {
123 std::vector<int64_t> freezeTimeStampsTmp;
124 resultJson[FREEZE_TIMES_STAMPS_KEY].Get(freezeTimeStampsTmp);
125 bindFailedEventsObj.freezeTimeStamps = freezeTimeStampsTmp;
126 }
127 LOGI("ConvertJsonToBindFailedEvents success");
128 return DM_OK;
129 }
130
IsFrozen(int64_t & remainingFrozenTime)131 bool FreezeProcess::IsFrozen(int64_t &remainingFrozenTime)
132 {
133 {
134 std::lock_guard<std::mutex> lock(isSyncedMtx_);
135 if (!isSynced_) {
136 SyncFreezeData();
137 isSynced_ = true;
138 }
139 }
140 int64_t stopFreezeTimeStamp = 0;
141 {
142 std::lock_guard<std::mutex> lock(freezeStateCacheMtx_);
143 if (bindFailedEventsCache_.IsEmpty()) {
144 LOGI("bindFailedEventsCache is empty");
145 return false;
146 }
147 stopFreezeTimeStamp = freezeStateCache_.stopFreezeTimeStamp;
148 }
149 int64_t nowTime = GetSecondsSince1970ToNow();
150 bool isFrozen = nowTime > stopFreezeTimeStamp ? false : true;
151 if (isFrozen) {
152 remainingFrozenTime = stopFreezeTimeStamp - nowTime;
153 }
154 if (CleanFreezeRecord(nowTime) != DM_OK) {
155 LOGE("CleanFreezeRecord failed");
156 }
157 return isFrozen;
158 }
159
CleanFreezeRecord(int64_t nowTime)160 int32_t FreezeProcess::CleanFreezeRecord(int64_t nowTime)
161 {
162 int64_t reservedDataTimeStamp = nowTime - DATA_REFRESH_INTERVAL;
163 if (CleanBindFailedEvents(reservedDataTimeStamp) != DM_OK) {
164 LOGE("CleanBindFailedEvents failed");
165 return ERR_DM_FAILED;
166 }
167 if (CleanFreezeState(reservedDataTimeStamp) != DM_OK) {
168 LOGE("CleanFreezeState failed");
169 return ERR_DM_FAILED;
170 }
171 LOGI("CleanFreezeRecord success");
172 return DM_OK;
173 }
174
CleanBindFailedEvents(int64_t reservedDataTimeStamp)175 int32_t FreezeProcess::CleanBindFailedEvents(int64_t reservedDataTimeStamp)
176 {
177 std::lock_guard<std::mutex> lock(bindFailedEventsCacheMtx_);
178 if (bindFailedEventsCache_.IsEmpty()) {
179 LOGI("bindFailedEventsCache is empty, no need to clean");
180 return DM_OK;
181 }
182 BindFailedEvents bindFailedEventsTmp = bindFailedEventsCache_;
183 int32_t needCleanBindFailedStampNum = std::count_if(bindFailedEventsTmp.failedTimeStamps.begin(),
184 bindFailedEventsTmp.failedTimeStamps.end(),
185 [reservedDataTimeStamp](int64_t v) { return v < reservedDataTimeStamp; });
186 if (needCleanBindFailedStampNum == 0) {
187 LOGI("no stamp is before 20mins, no need to clean");
188 return DM_OK;
189 }
190 bindFailedEventsTmp.failedTimeStamps.erase(
191 std::remove_if(bindFailedEventsTmp.failedTimeStamps.begin(),
192 bindFailedEventsTmp.failedTimeStamps.end(),
193 [reservedDataTimeStamp](int64_t n) { return n < reservedDataTimeStamp; }),
194 bindFailedEventsTmp.failedTimeStamps.end());
195 bindFailedEventsTmp.freezeTimeStamps.erase(
196 std::remove_if(bindFailedEventsTmp.freezeTimeStamps.begin(),
197 bindFailedEventsTmp.freezeTimeStamps.end(),
198 [reservedDataTimeStamp](int64_t n) { return n < reservedDataTimeStamp; }),
199 bindFailedEventsTmp.freezeTimeStamps.end());
200 std::string valueStr = "";
201 ConvertBindFailedEventsToJson(bindFailedEventsTmp, valueStr);
202 if (KVAdapterManager::GetInstance().PutFreezeData(BIND_FAILED_EVENTS_KEY, valueStr) != DM_OK) {
203 LOGE("CleanBindFailedEvents within 20mins failed");
204 return ERR_DM_FAILED;
205 }
206 bindFailedEventsCache_ = bindFailedEventsTmp;
207 LOGI("CleanBindFailedEvents success");
208 return DM_OK;
209 }
210
CleanFreezeState(int64_t reservedDataTimeStamp)211 int32_t FreezeProcess::CleanFreezeState(int64_t reservedDataTimeStamp)
212 {
213 std::lock_guard<std::mutex> lock(freezeStateCacheMtx_);
214 if (freezeStateCache_.IsEmpty()) {
215 LOGI("freezeStateCache is empty, no need to clean");
216 return DM_OK;
217 }
218 if (freezeStateCache_.startFreezeTimeStamp >= reservedDataTimeStamp) {
219 LOGI("startFreezeTimeStamp is in 20 mins, no need to clean");
220 return DM_OK;
221 }
222 if (KVAdapterManager::GetInstance().DeleteFreezeData(FREEZE_STATE_KEY) != DM_OK) {
223 LOGE("delete freeze states data within 20mins failed");
224 return ERR_DM_FAILED;
225 }
226 freezeStateCache_.Reset();
227 LOGI("CleanFreezeState success");
228 return DM_OK;
229 }
230
ConvertBindFailedEventsToJson(const BindFailedEvents & value,std::string & result)231 void FreezeProcess::ConvertBindFailedEventsToJson(const BindFailedEvents &value, std::string &result)
232 {
233 JsonObject jsonObj;
234 jsonObj[FAILED_TIMES_STAMPS_KEY] = value.failedTimeStamps;
235 jsonObj[FREEZE_TIMES_STAMPS_KEY] = value.freezeTimeStamps;
236 result = jsonObj.Dump();
237 }
238
ConvertDeviceFreezeStateToJson(const DeviceFreezeState & value,std::string & result)239 void FreezeProcess::ConvertDeviceFreezeStateToJson(const DeviceFreezeState &value, std::string &result)
240 {
241 JsonObject jsonObj;
242 jsonObj[START_FREEZE_TIME_KEY] = value.startFreezeTimeStamp;
243 jsonObj[STOP_FREEZE_TIME_KEY] = value.stopFreezeTimeStamp;
244 result = jsonObj.Dump();
245 }
246
DeleteFreezeRecord()247 int32_t FreezeProcess::DeleteFreezeRecord()
248 {
249 if (KVAdapterManager::GetInstance().DeleteFreezeData(FREEZE_STATE_KEY) != DM_OK) {
250 LOGE("delete freezeStates data failed");
251 return ERR_DM_FAILED;
252 }
253 {
254 std::lock_guard<std::mutex> lock(freezeStateCacheMtx_);
255 freezeStateCache_.Reset();
256 }
257 if (KVAdapterManager::GetInstance().DeleteFreezeData(BIND_FAILED_EVENTS_KEY) != DM_OK) {
258 LOGE("delete bindFailedEvents data failed");
259 return ERR_DM_FAILED;
260 }
261 std::lock_guard<std::mutex> lock(bindFailedEventsCacheMtx_);
262 bindFailedEventsCache_.Reset();
263 return DM_OK;
264 }
265
UpdateFreezeRecord()266 int32_t FreezeProcess::UpdateFreezeRecord()
267 {
268 int64_t nowTime = GetSecondsSince1970ToNow();
269 std::lock_guard<std::mutex> lock(bindFailedEventsCacheMtx_);
270 BindFailedEvents bindFailedEventsTmp = bindFailedEventsCache_;
271 int64_t lastFreezeTimeStamps = 0;
272 if (!bindFailedEventsTmp.freezeTimeStamps.empty()) {
273 lastFreezeTimeStamps = bindFailedEventsTmp.freezeTimeStamps.back();
274 }
275 int32_t continueBindFailedNum = std::count_if(bindFailedEventsTmp.failedTimeStamps.begin(),
276 bindFailedEventsTmp.failedTimeStamps.end(),
277 [nowTime, lastFreezeTimeStamps](
278 int64_t v) { return v > nowTime - CONTINUEOUS_FAILED_INTERVAL && v > lastFreezeTimeStamps; });
279 if (continueBindFailedNum < MAX_CONTINUOUS_BIND_FAILED_NUM) {
280 bindFailedEventsTmp.failedTimeStamps.push_back(nowTime);
281 std::string bindFailedEventsStr = "";
282 ConvertBindFailedEventsToJson(bindFailedEventsTmp, bindFailedEventsStr);
283 if (KVAdapterManager::GetInstance().PutFreezeData(BIND_FAILED_EVENTS_KEY, bindFailedEventsStr) != DM_OK) {
284 LOGE("UpdateBindFailedEvents failed");
285 return ERR_DM_FAILED;
286 }
287 bindFailedEventsCache_ = bindFailedEventsTmp;
288 return DM_OK;
289 }
290 bindFailedEventsTmp.failedTimeStamps.push_back(nowTime);
291 bindFailedEventsTmp.freezeTimeStamps.push_back(nowTime);
292 std::string bindFailedEventsStr = "";
293 ConvertBindFailedEventsToJson(bindFailedEventsTmp, bindFailedEventsStr);
294 if (KVAdapterManager::GetInstance().PutFreezeData(BIND_FAILED_EVENTS_KEY, bindFailedEventsStr) != DM_OK) {
295 LOGE("UpdateBindFailedEvents failed");
296 return ERR_DM_FAILED;
297 }
298 bindFailedEventsCache_ = bindFailedEventsTmp;
299 return UpdateFreezeState(nowTime);
300 }
301
UpdateFreezeState(int64_t nowTime)302 int32_t FreezeProcess::UpdateFreezeState(int64_t nowTime)
303 {
304 std::lock_guard<std::mutex> lock(freezeStateCacheMtx_);
305 DeviceFreezeState freezeStateTmp = freezeStateCache_;
306 int64_t nextFreezeTime = 0;
307 CalculateNextFreezeTime(freezeStateTmp.stopFreezeTimeStamp - freezeStateTmp.startFreezeTimeStamp, nextFreezeTime);
308 freezeStateTmp.startFreezeTimeStamp = nowTime;
309 freezeStateTmp.stopFreezeTimeStamp = nowTime + nextFreezeTime;
310 std::string freezeStateStr = "";
311 ConvertDeviceFreezeStateToJson(freezeStateTmp, freezeStateStr);
312 if (KVAdapterManager::GetInstance().PutFreezeData(FREEZE_STATE_KEY, freezeStateStr) != DM_OK) {
313 LOGE("UpdateFreezeState failed");
314 return ERR_DM_FAILED;
315 }
316 freezeStateCache_ = freezeStateTmp;
317 return DM_OK;
318 }
319
CalculateNextFreezeTime(int64_t nowFreezeTime,int64_t & nextFreezeTime)320 void FreezeProcess::CalculateNextFreezeTime(int64_t nowFreezeTime, int64_t &nextFreezeTime)
321 {
322 switch (nowFreezeTime) {
323 case NOT_FREEZE_DURATION_SEC:
324 nextFreezeTime = FIRST_FREEZE_DURATION_SEC;
325 break;
326 case FIRST_FREEZE_DURATION_SEC:
327 nextFreezeTime = SECOND_FREEZE_DURATION_SEC;
328 break;
329 case SECOND_FREEZE_DURATION_SEC:
330 nextFreezeTime = THIRD_FREEZE_DURATION_SEC;
331 break;
332 default:
333 nextFreezeTime = MAX_FREEZE_DURATION_SEC;
334 break;
335 }
336 }
337
IsNeedFreeze(std::shared_ptr<DmAuthContext> context)338 bool FreezeProcess::IsNeedFreeze(std::shared_ptr<DmAuthContext> context)
339 {
340 LOGI("called");
341 bool isNeedFreeze = true;
342 if (context == nullptr) {
343 LOGE("context is null");
344 return isNeedFreeze;
345 }
346 OHOS::DistributedDeviceProfile::LocalServiceInfo srvInfo;
347 auto ret = DeviceProfileConnector::GetInstance().GetLocalServiceInfoByBundleNameAndPinExchangeType(
348 context->accessee.pkgName, context->authType, srvInfo);
349 if (ret != DM_OK) {
350 LOGE("ServiceInfo not found");
351 return isNeedFreeze;
352 }
353 std::string extraInfo = srvInfo.GetExtraInfo();
354 if (extraInfo.empty()) {
355 LOGE("no extraInfo");
356 return isNeedFreeze;
357 }
358 JsonObject jsonObj;
359 jsonObj.Parse(extraInfo);
360 if (jsonObj.IsDiscarded()) {
361 LOGE("extraInfo invalid");
362 return isNeedFreeze;
363 }
364 std::string isNeedFreezeStr;
365 if (IsString(jsonObj, IS_NEED_FREEZE)) {
366 isNeedFreezeStr = jsonObj[IS_NEED_FREEZE].Get<std::string>();
367 LOGI("isNeedFreezeStr: %{public}s.", isNeedFreezeStr.c_str());
368 }
369 if (isNeedFreezeStr == NEED_FREEZE || isNeedFreezeStr == NO_NEED_FREEZE) {
370 isNeedFreeze = std::atoi(isNeedFreezeStr.c_str());
371 }
372 LOGI("isNeedFreeze: %{public}d.", isNeedFreeze);
373 return isNeedFreeze;
374 }
375 } // namespace DistributedHardware
376 } // namespace OHOS