• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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