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