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)75 void DeviceMatrix::Online(const std::string &device)
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 EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_ONLINE, device, mask.bitset));
88 }
89 }
90
Offline(const std::string & device)91 void DeviceMatrix::Offline(const std::string &device)
92 {
93 Mask mask;
94 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
95 auto it = onLines_.find(device);
96 if (it != onLines_.end()) {
97 mask = it->second;
98 onLines_.erase(it);
99 }
100 offLines_.insert_or_assign(device, mask);
101 }
102
OnBroadcast(const std::string & device,uint16_t code)103 void DeviceMatrix::OnBroadcast(const std::string &device, uint16_t code)
104 {
105 Mask mask{ .bitset = 0 };
106 uint16_t rightCode = ConvertMask(device, code);
107 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
108 auto it = remotes_.find(device);
109 if (it != remotes_.end()) {
110 mask = it->second;
111 }
112 mask.bitset |= rightCode;
113 remotes_.insert_or_assign(device, mask);
114 }
115
OnChanged(uint16_t code)116 void DeviceMatrix::OnChanged(uint16_t code)
117 {
118 EventCenter::Defer defer;
119 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
120 for (auto &[key, mask] : onLines_) {
121 mask.bitset |= code;
122 }
123
124 for (auto &[key, mask] : offLines_) {
125 mask.bitset |= code;
126 }
127
128 if (code != 0) {
129 EventCenter::GetInstance().PostEvent(std::make_unique<MatrixEvent>(MATRIX_BROADCAST, "", code));
130 }
131 }
132
OnExchanged(const std::string & device,uint16_t code,bool isRemote)133 void DeviceMatrix::OnExchanged(const std::string &device, uint16_t code, bool isRemote)
134 {
135 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
136 if (!isRemote) {
137 auto it = onLines_.find(device);
138 if (it != onLines_.end()) {
139 it->second.bitset &= ~code;
140 }
141 it = offLines_.find(device);
142 if (it != offLines_.end()) {
143 it->second.bitset &= ~code;
144 }
145 }
146
147 auto it = remotes_.find(device);
148 if (it != remotes_.end()) {
149 it->second.bitset &= ~code;
150 }
151 }
152
GetCode(const StoreMetaData & metaData)153 uint16_t DeviceMatrix::GetCode(const StoreMetaData &metaData)
154 {
155 if (metaData.tokenId == tokenId_ && metaData.storeId == storeId_) {
156 return META_STORE_MASK;
157 }
158
159 for (size_t i = 0; i < maskApps_.size(); i++) {
160 if (maskApps_[i] == metaData.appId) {
161 return SetMask(i);
162 }
163 }
164 return 0;
165 }
166
ConvertMask(const std::string & device,uint16_t code)167 uint16_t DeviceMatrix::ConvertMask(const std::string &device, uint16_t code)
168 {
169 Mask mask;
170 MatrixMetaData meta = GetMatrixMeta(device);
171 if (meta.version == CURRENT_VERSION) {
172 return (mask.bitset & code);
173 }
174
175 uint16_t result = code & META_STORE_MASK;
176 code &= ~META_STORE_MASK;
177 while (code != 0) {
178 uint16_t index = (~code) & (code - 1);
179 // 0x6666: 1010101010101010 0x5555: 0101010101010101 1: move the high(0x6666) to low(0x5555) bits
180 index = ((index & 0xAAAA) >> 1) + (index & 0x5555);
181 // 0xCCCC: 1100110011001100 0x3333: 0011001100110011 2: the count save at 2 bits
182 index = ((index & 0xCCCC) >> 2) + (index & 0x3333);
183 // 0xF0F0: 1111000011110000 0x0F0F: 0000111100001111 4: the count save at 4 bits
184 index = ((index & 0xF0F0) >> 4) + (index & 0x0F0F);
185 // 0xFF00: 1111000011110000 0x00FF: 0000111100001111 8: the count save at 8 bits
186 index = ((index & 0xFF00) >> 8) + (index & 0x00FF);
187 index--;
188 if (index >= meta.maskInfo.size()) {
189 return result;
190 }
191 auto &app = meta.maskInfo[index];
192 for (size_t i = 0; i < maskApps_.size(); i++) {
193 if (maskApps_[i] == app) {
194 result |= SetMask(i);
195 break;
196 }
197 }
198 code &= code - 1;
199 }
200 return result;
201 }
202
GetMatrixMeta(const std::string & device)203 MatrixMetaData DeviceMatrix::GetMatrixMeta(const std::string &device)
204 {
205 MatrixMetaData meta;
206 auto success = versions_.Get(device, meta);
207 if (success) {
208 return meta;
209 }
210
211 meta.deviceId = device;
212 success = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta);
213 if (success) {
214 meta.deviceId = "";
215 versions_.Set(device, meta);
216 }
217 return meta;
218 }
219 } // namespace OHOS::DistributedData
220