• 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)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