• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "device_manager_adapter.h"
19 #include "eventcenter/event_center.h"
20 #include "log_print.h"
21 #include "matrix_event.h"
22 #include "metadata/matrix_meta_data.h"
23 #include "metadata/meta_data_manager.h"
24 #include "utils/anonymous.h"
25 namespace OHOS::DistributedData {
26 using DMAdapter = DeviceManagerAdapter;
GetInstance()27 DeviceMatrix &DeviceMatrix::GetInstance()
28 {
29     static DeviceMatrix instance;
30     return instance;
31 }
32 
DeviceMatrix()33 DeviceMatrix::DeviceMatrix()
34 {
35     MetaDataManager::GetInstance().Subscribe(MatrixMetaData::GetPrefix({}),
36         [this](const std::string &, const std::string &meta, int32_t action) {
37             if (action != MetaDataManager::INSERT && action != MetaDataManager::UPDATE) {
38                 return true;
39             }
40             MatrixMetaData metaData;
41             MatrixMetaData::Unmarshall(meta, metaData);
42             auto deviceId = std::move(metaData.deviceId);
43             versions_.Set(deviceId, metaData);
44             ZLOGI("Matrix ver:%{public}u mask:0x%{public}x device:%{public}s", metaData.version, metaData.mask,
45                 Anonymous::Change(deviceId).c_str());
46             return true;
47         });
48 }
49 
~DeviceMatrix()50 DeviceMatrix::~DeviceMatrix()
51 {
52     MetaDataManager::GetInstance().Unsubscribe(MatrixMetaData::GetPrefix({}));
53 }
54 
Initialize(uint32_t token,std::string storeId)55 bool DeviceMatrix::Initialize(uint32_t token, std::string storeId)
56 {
57     tokenId_ = token;
58     storeId_ = std::move(storeId);
59     MatrixMetaData oldMeta;
60     MatrixMetaData newMeta;
61     newMeta.version = CURRENT_VERSION;
62     newMeta.mask = META_STORE_MASK | CURRENT_MASK;
63     newMeta.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
64     newMeta.maskInfo = maskApps_;
65     auto key = newMeta.GetKey();
66     auto loaded = MetaDataManager::GetInstance().LoadMeta(key, oldMeta);
67     if (loaded && newMeta.version == oldMeta.version) {
68         return true;
69     }
70     ZLOGI("Save Matrix ver:%{public}u -> %{public}u mask:0x%{public}x -> 0x%{public}x", oldMeta.version,
71         newMeta.version, oldMeta.mask, newMeta.mask);
72     return MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta);
73 }
74 
Online(const std::string & device,RefCount refCount)75 void DeviceMatrix::Online(const std::string &device, RefCount refCount)
76 {
77     Mask mask;
78     EventCenter::Defer defer;
79     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
80     auto it = offLines_.find(device);
81     if (it != offLines_.end()) {
82         mask = it->second;
83         offLines_.erase(it);
84     }
85     onLines_.insert_or_assign(device, mask);
86     if (mask.bitset != 0) {
87         auto evt = std::make_unique<MatrixEvent>(MATRIX_ONLINE, device, mask.bitset);
88         evt->SetRefCount(std::move(refCount));
89         EventCenter::GetInstance().PostEvent(std::move(evt));
90     }
91 }
92 
Offline(const std::string & device)93 void DeviceMatrix::Offline(const std::string &device)
94 {
95     Mask mask;
96     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
97     auto it = onLines_.find(device);
98     if (it != onLines_.end()) {
99         mask = it->second;
100         onLines_.erase(it);
101     }
102     offLines_.insert_or_assign(device, mask);
103 }
104 
OnBroadcast(const std::string & device,uint16_t code)105 uint16_t DeviceMatrix::OnBroadcast(const std::string &device, uint16_t code)
106 {
107     Mask mask{ .bitset = 0 };
108     uint16_t rightCode = ConvertMask(device, code);
109     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
110     auto it = remotes_.find(device);
111     if (it != remotes_.end()) {
112         mask = it->second;
113     }
114     mask.bitset |= rightCode;
115     remotes_.insert_or_assign(device, mask);
116     return mask.bitset;
117 }
118 
OnChanged(uint16_t code)119 void DeviceMatrix::OnChanged(uint16_t code)
120 {
121     EventCenter::Defer defer;
122     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
123     for (auto &[key, mask] : onLines_) {
124         mask.bitset |= code;
125     }
126 
127     for (auto &[key, mask] : offLines_) {
128         mask.bitset |= code;
129     }
130 
131     if (code != 0) {
132         EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", code));
133     }
134 }
135 
OnChanged(const StoreMetaData & metaData)136 void DeviceMatrix::OnChanged(const StoreMetaData &metaData)
137 {
138     auto code = GetCode(metaData);
139     if (code != 0) {
140         OnChanged(code);
141     }
142     changeTime_.Set(metaData.tokenId, std::chrono::steady_clock::now());
143 }
144 
IsChangedInTerm(const StoreMetaData & metaData,uint64_t term)145 bool DeviceMatrix::IsChangedInTerm(const StoreMetaData &metaData, uint64_t term)
146 {
147     TimePoint changeTime;
148     if (!changeTime_.Get(metaData.tokenId, changeTime, false)) {
149         return false;
150     }
151     return std::chrono::steady_clock::now() < (changeTime + std::chrono::seconds(term));
152 }
153 
OnExchanged(const std::string & device,uint16_t code,bool isRemote)154 void DeviceMatrix::OnExchanged(const std::string &device, uint16_t code, bool isRemote)
155 {
156     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
157     if (!isRemote) {
158         auto it = onLines_.find(device);
159         if (it != onLines_.end()) {
160             it->second.bitset &= ~code;
161         }
162         it = offLines_.find(device);
163         if (it != offLines_.end()) {
164             it->second.bitset &= ~code;
165         }
166     }
167 
168     auto it = remotes_.find(device);
169     if (it != remotes_.end()) {
170         it->second.bitset &= ~code;
171     }
172 }
173 
GetCode(const StoreMetaData & metaData)174 uint16_t DeviceMatrix::GetCode(const StoreMetaData &metaData)
175 {
176     if (metaData.tokenId == tokenId_ && metaData.storeId == storeId_) {
177         return META_STORE_MASK;
178     }
179 
180     for (size_t i = 0; i < maskApps_.size(); i++) {
181         if (maskApps_[i] == metaData.appId) {
182             return SetMask(i);
183         }
184     }
185     return 0;
186 }
187 
GetMask(const std::string & device)188 std::pair<bool, uint16_t> DeviceMatrix::GetMask(const std::string &device)
189 {
190     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
191     auto it = onLines_.find(device);
192     if (it != onLines_.end()) {
193         return { true, it->second.bitset };
194     } else {
195         auto remoteIter = remotes_.find(device);
196         if (remoteIter != remotes_.end()) {
197             return { true, remoteIter->second.bitset };
198         }
199     }
200     return { false, 0 };
201 }
202 
GetRemoteMask(const std::string & device)203 std::pair<bool, uint16_t> DeviceMatrix::GetRemoteMask(const std::string &device)
204 {
205     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
206     auto it = remotes_.find(device);
207     if (it != remotes_.end()) {
208         return { true, it->second.bitset };
209     }
210     return { false, 0 };
211 }
212 
Clear()213 void DeviceMatrix::Clear()
214 {
215     versions_.ResetCapacity(0);
216     versions_.ResetCapacity(MAX_DEVICES);
217     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
218     onLines_.clear();
219     offLines_.clear();
220     remotes_.clear();
221 }
222 
ConvertMask(const std::string & device,uint16_t code)223 uint16_t DeviceMatrix::ConvertMask(const std::string &device, uint16_t code)
224 {
225     Mask mask;
226     MatrixMetaData meta = GetMatrixMeta(device);
227     if (meta.version == CURRENT_VERSION) {
228         return (mask.bitset & code);
229     }
230 
231     uint16_t result = code & META_STORE_MASK;
232     code &= ~META_STORE_MASK;
233     while (code != 0) {
234         uint16_t index = (~code) & (code - 1);
235         // 0xAAAA: 1010101010101010  0x5555: 0101010101010101 1: move the high(0xAAAA) to low(0x5555) bits
236         index = ((index & 0xAAAA) >> 1) + (index & 0x5555);
237         // 0xCCCC: 1100110011001100  0x3333: 0011001100110011 2: the count save at 2 bits
238         index = ((index & 0xCCCC) >> 2) + (index & 0x3333);
239         // 0xF0F0: 1111000011110000  0x0F0F: 0000111100001111 4: the count save at 4 bits
240         index = ((index & 0xF0F0) >> 4) + (index & 0x0F0F);
241         // 0xFF00: 1111000011110000  0x00FF: 0000111100001111 8: the count save at 8 bits
242         index = ((index & 0xFF00) >> 8) + (index & 0x00FF);
243         index--;
244         if (index >= meta.maskInfo.size()) {
245             return result;
246         }
247         const auto &app = meta.maskInfo[index];
248         for (size_t i = 0; i < maskApps_.size(); i++) {
249             if (maskApps_[i] == app) {
250                 result |= SetMask(i);
251                 break;
252             }
253         }
254         code &= code - 1;
255     }
256     return result;
257 }
258 
GetMatrixMeta(const std::string & device)259 MatrixMetaData DeviceMatrix::GetMatrixMeta(const std::string &device)
260 {
261     MatrixMetaData meta;
262     auto success = versions_.Get(device, meta);
263     if (success) {
264         return meta;
265     }
266 
267     meta.deviceId = device;
268     success = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta);
269     if (success) {
270         meta.deviceId = "";
271         versions_.Set(device, meta);
272     }
273     return meta;
274 }
275 } // namespace OHOS::DistributedData
276