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 LOG_TAG "DeviceMatrix"
16 #include "device_matrix.h"
17 
18 #include "bootstrap.h"
19 #include "checker/checker_manager.h"
20 #include "communication_provider.h"
21 #include "device_manager_adapter.h"
22 #include "eventcenter/event_center.h"
23 #include "log_print.h"
24 #include "metadata/matrix_meta_data.h"
25 #include "metadata/meta_data_manager.h"
26 #include "metadata/switches_meta_data.h"
27 #include "types.h"
28 #include "utils/anonymous.h"
29 namespace OHOS::DistributedData {
30 using DMAdapter = DeviceManagerAdapter;
31 using Commu = AppDistributedKv::CommunicationProvider;
GetInstance()32 DeviceMatrix &DeviceMatrix::GetInstance()
33 {
34     static DeviceMatrix instance;
35     return instance;
36 }
37 
DeviceMatrix()38 DeviceMatrix::DeviceMatrix()
39 {
40     MetaDataManager::GetInstance().Subscribe(MatrixMetaData::GetPrefix({}),
41         [this](const std::string &, const std::string &meta, int32_t action) {
42             if (action != MetaDataManager::INSERT && action != MetaDataManager::UPDATE) {
43                 return true;
44             }
45             MatrixMetaData metaData;
46             if (!MatrixMetaData::Unmarshall(meta, metaData)) {
47                 ZLOGE("unmarshall meta failed, action:%{public}d", action);
48                 return true;
49             }
50             auto deviceId = std::move(metaData.deviceId);
51             ZLOGI("matrix version:%{public}u origin:%{public}d device:%{public}s",
52                 metaData.version, metaData.origin, Anonymous::Change(deviceId).c_str());
53             if (metaData.origin == MatrixMetaData::Origin::REMOTE_CONSISTENT) {
54                 return true;
55             }
56             matrices_.Set(deviceId, metaData);
57             return true;
58         }, true);
59     MetaDataManager::GetInstance().Subscribe(MatrixMetaData::GetPrefix({}),
60         [this](const std::string &key, const std::string &meta, int32_t action) {
61             if (action != MetaDataManager::INSERT && action != MetaDataManager::UPDATE) {
62                 return true;
63             }
64             MatrixMetaData metaData;
65             if (meta.empty()) {
66                 MetaDataManager::GetInstance().LoadMeta(key, metaData);
67             } else {
68                 MatrixMetaData::Unmarshall(meta, metaData);
69             }
70             auto deviceId = std::move(metaData.deviceId);
71             versions_.Set(deviceId, metaData);
72             ZLOGI("matrix version:%{public}u device:%{public}s",
73                 metaData.version, Anonymous::Change(deviceId).c_str());
74             return true;
75         });
76 }
77 
~DeviceMatrix()78 DeviceMatrix::~DeviceMatrix()
79 {
80     MetaDataManager::GetInstance().Unsubscribe(MatrixMetaData::GetPrefix({}));
81 }
82 
Initialize(uint32_t token,std::string storeId)83 bool DeviceMatrix::Initialize(uint32_t token, std::string storeId)
84 {
85     auto stores = CheckerManager::GetInstance().GetDynamicStores();
86     dynamicApps_.clear();
87     auto metaName = Bootstrap::GetInstance().GetProcessLabel();
88     dynamicApps_.push_back(std::move(metaName));
89     for (auto &store : stores) {
90         dynamicApps_.push_back(std::move(store.bundleName));
91     }
92     stores = CheckerManager::GetInstance().GetStaticStores();
93     staticsApps_.clear();
94     for (auto &store : stores) {
95         staticsApps_.push_back(std::move(store.bundleName));
96     }
97     auto pipe = metaName + "-" + "default";
98     auto status = Commu::GetInstance().Broadcast(
99         { pipe }, { INVALID_LEVEL, INVALID_LEVEL, INVALID_VALUE, INVALID_LENGTH });
100     isSupportBroadcast_ = (status != DistributedKv::Status::NOT_SUPPORT_BROADCAST);
101     ZLOGI("Is support broadcast:%{public}d", isSupportBroadcast_);
102     tokenId_ = token;
103     storeId_ = std::move(storeId);
104     MatrixMetaData oldMeta;
105     MatrixMetaData newMeta;
106     newMeta.version = CURRENT_VERSION;
107     newMeta.dynamic = CURRENT_DYNAMIC_MASK | META_STORE_MASK;
108     newMeta.statics = CURRENT_STATICS_MASK;
109     newMeta.dynamicInfo = dynamicApps_;
110     newMeta.staticsInfo = staticsApps_;
111     newMeta.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
112     auto key = newMeta.GetKey();
113     auto loaded = MetaDataManager::GetInstance().LoadMeta(key, oldMeta);
114     if (loaded && newMeta.version == oldMeta.version) {
115         return true;
116     }
117     if (loaded && newMeta.version != oldMeta.version) {
118         newMeta.dynamic = Merge(oldMeta.dynamic, newMeta.dynamic);
119         newMeta.statics = Merge(oldMeta.statics, newMeta.statics);
120     }
121     ZLOGI("Save Matrix, oldMeta.version:%{public}u , newMeta.version:%{public}u ", oldMeta.version, newMeta.version);
122     MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta, true);
123     return MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta);
124 }
125 
Online(const std::string & device,RefCount refCount)126 void DeviceMatrix::Online(const std::string &device, RefCount refCount)
127 {
128     Mask mask;
129     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
130     auto it = offLines_.find(device);
131     if (it != offLines_.end()) {
132         mask = it->second;
133         offLines_.erase(it);
134     } else {
135         UpdateMask(mask);
136     }
137     onLines_.insert_or_assign(device, mask);
138 }
139 
IsConsistent(const std::string & device)140 std::pair<bool, bool> DeviceMatrix::IsConsistent(const std::string &device)
141 {
142     std::pair<bool, bool> isConsistent = { false, false };
143     auto [dynamicSaved, dynamicRecvLevel] = GetRecvLevel(device, LevelType::DYNAMIC);
144     auto [dynamicExist, dynamicConsLevel] = GetConsLevel(device, LevelType::DYNAMIC);
145     ZLOGI("device:%{public}s, dynamicSaved:%{public}d, dynamicRecvLevel:%{public}d, dynamicExist:%{public}d, "
146           "dynamicConsLevel:%{public}d",
147         Anonymous::Change(device).c_str(), dynamicSaved, dynamicRecvLevel, dynamicExist, dynamicConsLevel);
148     isConsistent.first =
149         (dynamicSaved && dynamicExist && (dynamicRecvLevel <= dynamicConsLevel) && (dynamicRecvLevel != INVALID_MASK));
150     auto [staticsSaved, staticsRecvLevel] = GetRecvLevel(device, LevelType::STATICS);
151     auto [staticsExist, staticsConsLevel] = GetConsLevel(device, LevelType::STATICS);
152     ZLOGI("device:%{public}s, staticsSaved:%{public}d, staticsRecvLevel:%{public}d, staticsExist:%{public}d, "
153           "staticsConsLevel:%{public}d",
154         Anonymous::Change(device).c_str(), staticsSaved, staticsRecvLevel, staticsExist, staticsConsLevel);
155     isConsistent.second =
156         (staticsSaved && staticsExist && (staticsRecvLevel <= staticsConsLevel) && (staticsRecvLevel != INVALID_MASK));
157     return isConsistent;
158 }
159 
Offline(const std::string & device)160 void DeviceMatrix::Offline(const std::string &device)
161 {
162     Mask mask;
163     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
164     auto it = onLines_.find(device);
165     if (it != onLines_.end()) {
166         mask = it->second;
167         onLines_.erase(it);
168     } else {
169         UpdateMask(mask);
170     }
171     offLines_.insert_or_assign(device, mask);
172 }
173 
UpdateMask(Mask & mask)174 void DeviceMatrix::UpdateMask(Mask &mask)
175 {
176     auto device = DMAdapter::GetInstance().GetLocalDevice().uuid;
177     auto [exist, meta] = GetMatrixMeta(device);
178     mask.dynamic = Merge(meta.dynamic, mask.dynamic);
179     mask.statics = Merge(meta.statics, mask.statics);
180 }
181 
OnBroadcast(const std::string & device,const DataLevel & dataLevel)182 std::pair<uint16_t, uint16_t> DeviceMatrix::OnBroadcast(const std::string &device, const DataLevel &dataLevel)
183 {
184     if (device.empty() || !dataLevel.IsValid()) {
185         ZLOGE("invalid args, device:%{public}s, dataLevel valid:%{public}d",
186             Anonymous::Change(device).c_str(), dataLevel.IsValid());
187         return { INVALID_LEVEL, INVALID_LEVEL };
188     }
189     SaveSwitches(device, dataLevel);
190     auto result = ConvertMask(device, dataLevel);
191     Mask mask;
192     if (dataLevel.dynamic != INVALID_LEVEL) {
193         mask.dynamic &= Low(result.first);
194         if (High(dataLevel.dynamic) != INVALID_HIGH) {
195             mask.dynamic |= High(dataLevel.dynamic);
196         }
197     } else {
198         mask.dynamic &= ~dataLevel.dynamic;
199     }
200     if (dataLevel.statics != INVALID_LEVEL) {
201         mask.statics &= Low(result.second);
202         if (High(dataLevel.statics) != INVALID_HIGH) {
203             mask.statics |= High(dataLevel.statics);
204         }
205     } else {
206         mask.statics &= ~dataLevel.statics;
207     }
208     auto meta = GetMatrixMetaData(device, mask);
209     UpdateRemoteMeta(device, mask, meta);
210     {
211         std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
212         auto it = remotes_.find(device);
213         if (it != remotes_.end()) {
214             mask.dynamic |= Low(it->second.dynamic);
215             mask.statics |= Low(it->second.statics);
216         }
217         remotes_.insert_or_assign(device, mask);
218     }
219     return { mask.dynamic, mask.statics };
220 }
221 
ConvertMask(const std::string & device,const DataLevel & dataLevel)222 std::pair<uint16_t, uint16_t> DeviceMatrix::ConvertMask(const std::string &device, const DataLevel &dataLevel)
223 {
224     Mask mask;
225     auto meta = GetMatrixInfo(device);
226     if (meta.version == CURRENT_VERSION) {
227         return { mask.dynamic & dataLevel.dynamic, mask.statics & dataLevel.statics };
228     }
229     return { ConvertDynamic(meta, dataLevel.dynamic), ConvertStatics(meta, dataLevel.statics) };
230 }
231 
ConvertDynamic(const MatrixMetaData & meta,uint16_t mask)232 uint16_t DeviceMatrix::ConvertDynamic(const MatrixMetaData &meta, uint16_t mask)
233 {
234     uint16_t result = Low(mask) & META_STORE_MASK;
235     uint16_t code = Low(mask) & (~META_STORE_MASK);
236     while (code != 0) {
237         uint16_t index = ConvertIndex(code);
238         if (index >= meta.dynamicInfo.size()) {
239             return result;
240         }
241         const auto &app = meta.dynamicInfo[index];
242         for (size_t i = 0; i < dynamicApps_.size(); i++) {
243             if (dynamicApps_[i] == app) {
244                 result |= SetMask(i);
245                 break;
246             }
247         }
248         code &= code - 1;
249     }
250     return result;
251 }
252 
ConvertStatics(const MatrixMetaData & meta,uint16_t mask)253 uint16_t DeviceMatrix::ConvertStatics(const MatrixMetaData &meta, uint16_t mask)
254 {
255     uint16_t result = 0;
256     uint16_t code = Low(mask);
257     while (code != 0) {
258         uint16_t index = ConvertIndex(code);
259         if (index >= meta.staticsInfo.size()) {
260             return result;
261         }
262         const auto &app = meta.staticsInfo[index];
263         for (size_t i = 0; i < staticsApps_.size(); i++) {
264             if (staticsApps_[i] == app) {
265                 result |= SetMask(i);
266                 break;
267             }
268         }
269         code &= code - 1;
270     }
271     return result;
272 }
273 
ConvertIndex(uint16_t code)274 uint16_t DeviceMatrix::ConvertIndex(uint16_t code)
275 {
276     uint16_t index = (~code) & (code - 1);
277     // 0xAAAA: 1010101010101010  0x5555: 0101010101010101 1: move the high(0xAAAA) to low(0x5555) bits
278     index = ((index & 0xAAAA) >> 1) + (index & 0x5555);
279     // 0xCCCC: 1100110011001100  0x3333: 0011001100110011 2: the count save at 2 bits
280     index = ((index & 0xCCCC) >> 2) + (index & 0x3333);
281     // 0xF0F0: 1111000011110000  0x0F0F: 0000111100001111 4: the count save at 4 bits
282     index = ((index & 0xF0F0) >> 4) + (index & 0x0F0F);
283     // 0xFF00: 1111000011110000  0x00FF: 0000111100001111 8: the count save at 8 bits
284     index = ((index & 0xFF00) >> 8) + (index & 0x00FF);
285     index--;
286     return index;
287 }
288 
GetMatrixMetaData(const std::string & device,const Mask & mask)289 MatrixMetaData DeviceMatrix::GetMatrixMetaData(const std::string &device, const Mask &mask)
290 {
291     MatrixMetaData meta;
292     meta.dynamic = mask.dynamic;
293     meta.statics = mask.statics;
294     meta.deviceId = device;
295     meta.origin = Origin::REMOTE_RECEIVED;
296     meta.dynamicInfo = dynamicApps_;
297     meta.staticsInfo = staticsApps_;
298     return meta;
299 }
300 
UpdateRemoteMeta(const std::string & device,Mask & mask,MatrixMetaData & newMeta)301 void DeviceMatrix::UpdateRemoteMeta(const std::string &device, Mask &mask, MatrixMetaData &newMeta)
302 {
303     auto [exist, oldMeta] = GetMatrixMeta(device);
304     if (exist && oldMeta == newMeta) {
305         return;
306     }
307     if (exist) {
308         if (High(newMeta.dynamic) < High(oldMeta.dynamic)) {
309             newMeta.dynamic &= 0x000F;
310             newMeta.dynamic |= High(oldMeta.dynamic);
311         } else if ((High(newMeta.dynamic) - High(oldMeta.dynamic)) > 1) {
312             newMeta.dynamic |= 0x000F;
313             mask.dynamic |= 0x000F;
314         }
315         if (High(newMeta.statics) < High(oldMeta.statics)) {
316             newMeta.statics &= 0x000F;
317             newMeta.statics |= High(oldMeta.statics);
318         } else if ((High(newMeta.statics) - High(oldMeta.statics)) > 1) {
319             newMeta.statics |= 0x000F;
320             mask.statics |= 0x000F;
321         }
322     } else {
323         if (High(newMeta.dynamic) != 0x0010) {
324             newMeta.dynamic |= 0x000F;
325             mask.dynamic |= 0x000F;
326         }
327         if (High(newMeta.statics) != 0x0010) {
328             newMeta.statics |= 0x000F;
329             mask.statics |= 0x000F;
330         }
331     }
332     MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta, true);
333 }
334 
SaveSwitches(const std::string & device,const DataLevel & dataLevel)335 void DeviceMatrix::SaveSwitches(const std::string &device, const DataLevel &dataLevel)
336 {
337     if (device.empty() || dataLevel.switches == INVALID_VALUE ||
338         dataLevel.switchesLen == INVALID_LENGTH) {
339         ZLOGW("switches data invalid, device:%{public}s", Anonymous::Change(device).c_str());
340         return;
341     }
342     SwitchesMetaData newMeta;
343     newMeta.deviceId = device;
344     newMeta.value = dataLevel.switches;
345     newMeta.length = dataLevel.switchesLen;
346     SwitchesMetaData oldMeta;
347     auto saved = MetaDataManager::GetInstance().LoadMeta(newMeta.GetKey(), oldMeta, true);
348     if (!saved || newMeta != oldMeta) {
349         MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta, true);
350     }
351     ZLOGI("exist:%{public}d, changed:%{public}d", saved, newMeta != oldMeta);
352 }
353 
Broadcast(const DataLevel & dataLevel)354 void DeviceMatrix::Broadcast(const DataLevel &dataLevel)
355 {
356     EventCenter::Defer defer;
357     MatrixEvent::MatrixData matrix = {
358         .dynamic = ResetMask(dataLevel.dynamic),
359         .statics = ResetMask(dataLevel.statics),
360         .switches = dataLevel.switches,
361         .switchesLen = dataLevel.switchesLen,
362     };
363     std::lock_guard<decltype(taskMutex_)> lock(taskMutex_);
364     if (!lasts_.IsValid()) {
365         EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", matrix));
366         return;
367     }
368     matrix.dynamic |= Low(lasts_.dynamic);
369     matrix.statics |= Low(lasts_.statics);
370     if (High(matrix.dynamic) != INVALID_HIGH && High(lasts_.dynamic) != INVALID_HIGH &&
371         High(matrix.dynamic) < High(lasts_.dynamic)) {
372         matrix.dynamic &= 0x000F;
373         matrix.dynamic |= High(matrix.dynamic);
374     }
375     if (High(matrix.statics) != INVALID_HIGH && High(lasts_.statics) != INVALID_HIGH &&
376         High(matrix.statics) < High(lasts_.statics)) {
377         matrix.statics &= 0x000F;
378         matrix.statics |= High(matrix.statics);
379     }
380     EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", matrix));
381     lasts_ = matrix;
382     auto executor = executors_;
383     if (executor != nullptr && task_ != ExecutorPool::INVALID_TASK_ID) {
384         task_ = executor->Reset(task_, std::chrono::minutes(RESET_MASK_DELAY));
385     }
386 }
387 
OnChanged(uint16_t code,LevelType type)388 void DeviceMatrix::OnChanged(uint16_t code, LevelType type)
389 {
390     if (type < LevelType::STATICS || type > LevelType::DYNAMIC) {
391         return;
392     }
393     uint16_t low = Low(code);
394     uint16_t codes[LevelType::BUTT] = { 0, 0 };
395     codes[type] |= low;
396     EventCenter::Defer defer;
397     {
398         std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
399         for (auto &[key, mask] : onLines_) {
400             mask.statics |= codes[LevelType::STATICS];
401             mask.dynamic |= codes[LevelType::DYNAMIC];
402         }
403         for (auto &[key, mask] : offLines_) {
404             mask.statics |= codes[LevelType::STATICS];
405             mask.dynamic |= codes[LevelType::DYNAMIC];
406         }
407     }
408     if (low == 0) {
409         return;
410     }
411     Mask mask;
412     UpdateMask(mask);
413     mask.SetStaticsMask(codes[LevelType::STATICS]);
414     mask.SetDynamicMask(codes[LevelType::DYNAMIC]);
415     MatrixEvent::MatrixData matrixData = {
416         .dynamic = mask.dynamic,
417         .statics = mask.statics,
418     };
419     SwitchesMetaData switchesData;
420     switchesData.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
421     if (MetaDataManager::GetInstance().LoadMeta(switchesData.GetKey(), switchesData, true)) {
422         matrixData.switches = switchesData.value;
423         matrixData.switchesLen = switchesData.length;
424     }
425     EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", matrixData));
426     std::lock_guard<decltype(taskMutex_)> lock(taskMutex_);
427     lasts_ = matrixData;
428     auto executor = executors_;
429     if (executor != nullptr) {
430         if (task_ != ExecutorPool::INVALID_TASK_ID) {
431             task_ = executor->Reset(task_, std::chrono::minutes(RESET_MASK_DELAY));
432         } else {
433             task_ = executor->Schedule(std::chrono::minutes(RESET_MASK_DELAY), GenResetTask());
434         }
435     }
436 }
437 
SetDynamicMask(uint16_t mask)438 void DeviceMatrix::Mask::SetDynamicMask(uint16_t mask)
439 {
440     dynamic = ResetMask(dynamic);
441     dynamic |= Low(mask);
442 }
443 
SetStaticsMask(uint16_t mask)444 void DeviceMatrix::Mask::SetStaticsMask(uint16_t mask)
445 {
446     statics = ResetMask(statics);
447     statics |= Low(mask);
448 }
449 
OnChanged(const StoreMetaData & metaData)450 void DeviceMatrix::OnChanged(const StoreMetaData &metaData)
451 {
452     if (metaData.dataType < LevelType::STATICS || metaData.dataType > LevelType::DYNAMIC) {
453         return;
454     }
455     auto code = GetCode(metaData);
456     if (code != 0) {
457         OnChanged(code, static_cast<LevelType>(metaData.dataType));
458     }
459 }
460 
OnExchanged(const std::string & device,uint16_t code,LevelType type,ChangeType changeType)461 void DeviceMatrix::OnExchanged(const std::string &device, uint16_t code, LevelType type, ChangeType changeType)
462 {
463     if (device.empty() || type < LevelType::STATICS || type > LevelType::DYNAMIC) {
464         ZLOGE("invalid args, device:%{public}s, code:%{public}d, type:%{public}d", Anonymous::Change(device).c_str(),
465             code, type);
466         return;
467     }
468     uint16_t low = Low(code);
469     uint16_t codes[LevelType::BUTT] = { 0 };
470     codes[type] |= low;
471     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
472     if ((changeType & CHANGE_LOCAL) == CHANGE_LOCAL) {
473         auto it = onLines_.find(device);
474         if (it != onLines_.end()) {
475             it->second.statics &= ~codes[LevelType::STATICS];
476             it->second.dynamic &= ~codes[LevelType::DYNAMIC];
477         }
478         it = offLines_.find(device);
479         if (it != offLines_.end()) {
480             it->second.statics &= ~codes[LevelType::STATICS];
481             it->second.dynamic &= ~codes[LevelType::DYNAMIC];
482         }
483     }
484     if ((changeType & CHANGE_REMOTE) == CHANGE_REMOTE) {
485         auto it = remotes_.find(device);
486         if (it == remotes_.end()) {
487             return;
488         }
489         it->second.statics &= ~codes[LevelType::STATICS];
490         it->second.dynamic &= ~codes[LevelType::DYNAMIC];
491         UpdateConsistentMeta(device, it->second);
492     }
493 }
494 
UpdateConsistentMeta(const std::string & device,const Mask & remote)495 void DeviceMatrix::UpdateConsistentMeta(const std::string &device, const Mask &remote)
496 {
497     uint16_t statics = Low(remote.statics);
498     uint16_t dynamic = Low(remote.dynamic);
499     if (statics != 0 && dynamic != 0) {
500         return;
501     }
502     auto [exist, meta] = GetMatrixMeta(device);
503     if (!exist) {
504         meta.dynamic = remote.dynamic;
505         meta.statics = remote.statics;
506         meta.origin = Origin::REMOTE_RECEIVED;
507         meta.dynamicInfo = dynamicApps_;
508         meta.staticsInfo = staticsApps_;
509         meta.deviceId = device;
510         MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true);
511     }
512     auto [saved, metaData] = GetMatrixMeta(device, true);
513     if (!saved) {
514         meta.origin = Origin::REMOTE_CONSISTENT;
515         meta.deviceId = device;
516         MetaDataManager::GetInstance().SaveMeta(meta.GetConsistentKey(), meta, true);
517         return;
518     }
519     if (statics == 0 && High(meta.statics) > High(metaData.statics)) {
520         metaData.statics = meta.statics;
521     }
522     if (dynamic == 0 && High(meta.dynamic) > High(metaData.dynamic)) {
523         metaData.dynamic = meta.dynamic;
524     }
525     MetaDataManager::GetInstance().SaveMeta(metaData.GetConsistentKey(), metaData, true);
526 }
527 
OnExchanged(const std::string & device,const StoreMetaData & metaData,ChangeType type)528 void DeviceMatrix::OnExchanged(const std::string &device, const StoreMetaData &metaData, ChangeType type)
529 {
530     if (metaData.dataType < LevelType::STATICS || metaData.dataType > LevelType::DYNAMIC) {
531         return;
532     }
533     auto code = GetCode(metaData);
534     if (code != 0) {
535         OnExchanged(device, code, static_cast<LevelType>(metaData.dataType), type);
536     }
537 }
538 
GetCode(const StoreMetaData & metaData)539 uint16_t DeviceMatrix::GetCode(const StoreMetaData &metaData)
540 {
541     if (metaData.tokenId == tokenId_ && metaData.storeId == storeId_) {
542         return META_STORE_MASK;
543     }
544     if (metaData.dataType == LevelType::STATICS) {
545         for (size_t i = 0; i < staticsApps_.size(); i++) {
546             if (staticsApps_[i] == metaData.appId) {
547                 return SetMask(i);
548             }
549         }
550     }
551     if (metaData.dataType == LevelType::DYNAMIC) {
552         for (size_t i = 0; i < dynamicApps_.size(); i++) {
553             if (dynamicApps_[i] == metaData.appId) {
554                 return SetMask(i);
555             }
556         }
557     }
558     return 0;
559 }
560 
GetMask(const std::string & device,LevelType type)561 std::pair<bool, uint16_t> DeviceMatrix::GetMask(const std::string &device, LevelType type)
562 {
563     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
564     auto it = onLines_.find(device);
565     if (it == onLines_.end()) {
566         return { false, 0 };
567     }
568     switch (type) {
569         case LevelType::STATICS:
570             return { true, Low(it->second.statics) };
571         case LevelType::DYNAMIC:
572             return { true, Low(it->second.dynamic) };
573         default:
574             break;
575     }
576     return { false, 0 };
577 }
578 
GetRemoteMask(const std::string & device,LevelType type)579 std::pair<bool, uint16_t> DeviceMatrix::GetRemoteMask(const std::string &device, LevelType type)
580 {
581     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
582     auto it = remotes_.find(device);
583     if (it == remotes_.end()) {
584         return { false, 0 };
585     }
586     switch (type) {
587         case LevelType::STATICS:
588             return { true, Low(it->second.statics) };
589         case LevelType::DYNAMIC:
590             return { true, Low(it->second.dynamic) };
591         default:
592             break;
593     }
594     return { false, 0 };
595 }
596 
GetRemoteDynamicMask()597 std::map<std::string, uint16_t> DeviceMatrix::GetRemoteDynamicMask()
598 {
599     std::map<std::string, uint16_t> masks;
600     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
601     for (const auto &[device, mask] : remotes_) {
602         masks.insert_or_assign(device, Low(mask.dynamic));
603     }
604     return masks;
605 }
606 
GetRecvLevel(const std::string & device,LevelType type)607 std::pair<bool, uint16_t> DeviceMatrix::GetRecvLevel(const std::string &device, LevelType type)
608 {
609     auto [exist, meta] = GetMatrixMeta(device);
610     if (!exist) {
611         return { false, High(INVALID_LEVEL) };
612     }
613     switch (type) {
614         case LevelType::STATICS:
615             return { true, High(meta.statics) };
616         case LevelType::DYNAMIC:
617             return { true, High(meta.dynamic) };
618         default:
619             break;
620     }
621     return { false, High(INVALID_LEVEL) };
622 }
623 
GetConsLevel(const std::string & device,LevelType type)624 std::pair<bool, uint16_t> DeviceMatrix::GetConsLevel(const std::string &device, LevelType type)
625 {
626     auto [exist, meta] = GetMatrixMeta(device, true);
627     if (!exist) {
628         return { false, High(INVALID_LEVEL) };
629     }
630     switch (type) {
631         case LevelType::STATICS:
632             return { true, High(meta.statics) };
633         case LevelType::DYNAMIC:
634             return { true, High(meta.dynamic) };
635         default:
636             break;
637     }
638     return { false, High(INVALID_LEVEL) };
639 }
640 
Clear()641 void DeviceMatrix::Clear()
642 {
643     matrices_.ResetCapacity(0);
644     matrices_.ResetCapacity(MAX_DEVICES);
645     versions_.ResetCapacity(0);
646     versions_.ResetCapacity(MAX_DEVICES);
647     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
648     onLines_.clear();
649     offLines_.clear();
650     remotes_.clear();
651 }
652 
GetMatrixMeta(const std::string & device,bool isConsistent)653 std::pair<bool, MatrixMetaData> DeviceMatrix::GetMatrixMeta(const std::string &device, bool isConsistent)
654 {
655     MatrixMetaData meta;
656     if (!isConsistent && matrices_.Get(device, meta)) {
657         return { true, meta };
658     }
659     meta.deviceId = device;
660     std::string key;
661     if (isConsistent) {
662         key = meta.GetConsistentKey();
663     } else {
664         key = meta.GetKey();
665     }
666     auto success = MetaDataManager::GetInstance().LoadMeta(key, meta, true);
667     if (success && !isConsistent) {
668         meta.deviceId = "";
669         matrices_.Set(device, meta);
670     }
671     return { success, meta };
672 }
673 
UpdateLevel(const std::string & device,uint16_t level,DeviceMatrix::LevelType type,bool isConsistent)674 void DeviceMatrix::UpdateLevel(const std::string &device, uint16_t level, DeviceMatrix::LevelType type,
675     bool isConsistent)
676 {
677     if (device.empty() || type < 0 || type >= LevelType::BUTT) {
678         ZLOGE("invalid args, device:%{public}s, level:%{public}d, type:%{public}d", Anonymous::Change(device).c_str(),
679             level, type);
680         return;
681     }
682     auto [exist, meta] = GetMatrixMeta(device, isConsistent);
683     if (!exist) {
684         if (device == DMAdapter::GetInstance().GetLocalDevice().uuid) {
685             meta.origin = Origin::LOCAL;
686         } else {
687             meta.origin = isConsistent ? Origin::REMOTE_CONSISTENT : Origin::REMOTE_RECEIVED;
688         }
689         meta.dynamicInfo = dynamicApps_;
690         meta.staticsInfo = staticsApps_;
691     }
692     meta.deviceId = device;
693     meta.dynamic = type == DYNAMIC ? Merge(level, meta.dynamic) : meta.dynamic;
694     meta.statics = type == STATICS ? Merge(level, meta.statics) : meta.statics;
695     MetaDataManager::GetInstance().SaveMeta(isConsistent ? meta.GetConsistentKey() : meta.GetKey(), meta, true);
696     if (!isConsistent) {
697         meta.deviceId = "";
698         matrices_.Set(device, meta);
699     }
700 }
701 
GetMatrixInfo(const std::string & device)702 MatrixMetaData DeviceMatrix::GetMatrixInfo(const std::string &device)
703 {
704     MatrixMetaData meta;
705     if (versions_.Get(device, meta)) {
706         return meta;
707     }
708     meta.deviceId = device;
709     if (MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) {
710         meta.deviceId = "";
711         versions_.Set(device, meta);
712     }
713     return meta;
714 }
715 
IsDynamic(const StoreMetaData & metaData)716 bool DeviceMatrix::IsDynamic(const StoreMetaData &metaData)
717 {
718     if (metaData.dataType != LevelType::DYNAMIC) {
719         return false;
720     }
721     if (metaData.tokenId == tokenId_ && metaData.storeId == storeId_) {
722         return true;
723     }
724     return std::find(dynamicApps_.begin(), dynamicApps_.end(), metaData.appId) != dynamicApps_.end();
725 }
726 
IsStatics(const StoreMetaData & metaData)727 bool DeviceMatrix::IsStatics(const StoreMetaData &metaData)
728 {
729     if (metaData.dataType != LevelType::STATICS) {
730         return false;
731     }
732     return std::find(staticsApps_.begin(), staticsApps_.end(), metaData.appId) != staticsApps_.end();
733 }
734 
SetExecutor(std::shared_ptr<ExecutorPool> executors)735 void DeviceMatrix::SetExecutor(std::shared_ptr<ExecutorPool> executors)
736 {
737     executors_ = executors;
738 }
739 
GenResetTask()740 DeviceMatrix::Task DeviceMatrix::GenResetTask()
741 {
742     return [this]() {
743         MatrixEvent::MatrixData matrixData;
744         {
745             std::lock_guard<decltype(taskMutex_)> lock(taskMutex_);
746             matrixData = lasts_;
747             task_ = ExecutorPool::INVALID_TASK_ID;
748         }
749         matrixData.dynamic = ResetMask(matrixData.dynamic);
750         matrixData.statics = ResetMask(matrixData.statics);
751         EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", matrixData));
752     };
753 }
754 
IsValid() const755 bool DeviceMatrix::DataLevel::IsValid() const
756 {
757     return !(dynamic == INVALID_LEVEL && statics == INVALID_LEVEL &&
758         switches == INVALID_VALUE && switchesLen == INVALID_LENGTH);
759 }
760 
IsSupportMatrix()761 bool DeviceMatrix::IsSupportMatrix()
762 {
763     return isSupportBroadcast_;
764 }
765 
IsConsistent()766 bool DeviceMatrix::IsConsistent()
767 {
768     std::vector<MatrixMetaData> metas;
769     if (!MetaDataManager::GetInstance().LoadMeta(MatrixMetaData::GetPrefix({}), metas, true)) {
770         return true;
771     }
772     for (const auto &meta : metas) {
773         if (meta.origin == MatrixMetaData::Origin::REMOTE_RECEIVED) {
774             MatrixMetaData consistentMeta;
775             consistentMeta.deviceId = meta.deviceId;
776             if (!MetaDataManager::GetInstance().LoadMeta(consistentMeta.GetConsistentKey(), consistentMeta, true)) {
777                 return false;
778             }
779             if ((High(meta.statics) > High(consistentMeta.statics)) ||
780                 (High(meta.dynamic) > High(consistentMeta.dynamic))) {
781                 return false;
782             }
783         }
784     }
785     return true;
786 }
787 } // namespace OHOS::DistributedData