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
16 #define LOG_TAG "UserDelegate"
17 #include "user_delegate.h"
18
19 #include <chrono>
20 #include <cinttypes>
21 #include <thread>
22
23 #include "communicator/device_manager_adapter.h"
24 #include "log_print.h"
25 #include "metadata/meta_data_manager.h"
26 #include "utils/anonymous.h"
27
28 namespace OHOS::DistributedData {
29 using namespace OHOS::DistributedKv;
30 using namespace std::chrono;
GetLocalDeviceId()31 std::string GetLocalDeviceId()
32 {
33 return DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid;
34 }
35
GetLocalUserStatus()36 std::vector<UserStatus> UserDelegate::GetLocalUserStatus()
37 {
38 ZLOGI("begin");
39 auto deviceId = GetLocalDeviceId();
40 if (deviceId.empty()) {
41 ZLOGE("failed to get local device id");
42 return {};
43 }
44 return GetUsers(deviceId);
45 }
46
GetLocalUsers()47 std::set<std::string> UserDelegate::GetLocalUsers()
48 {
49 auto deviceId = GetLocalDeviceId();
50 if (deviceId.empty()) {
51 ZLOGE("failed to get local device id");
52 return {};
53 }
54 std::set<std::string> users;
55 deviceUser_.Compute(deviceId, [&users](const auto &key, auto &value) {
56 if (value.empty()) {
57 UserMetaData userMetaData;
58 MetaDataManager::GetInstance().LoadMeta(UserMetaRow::GetKeyFor(key), userMetaData);
59 for (const auto &user : userMetaData.users) {
60 value[user.id] = user.isActive;
61 }
62 }
63 for (const auto [user, active] : value) {
64 users.emplace(std::to_string(user));
65 }
66 return !value.empty();
67 });
68 return users;
69 }
70
GetRemoteUserStatus(const std::string &deviceId)71 std::vector<DistributedData::UserStatus> UserDelegate::GetRemoteUserStatus(const std::string &deviceId)
72 {
73 if (deviceId.empty()) {
74 ZLOGE("error input device id");
75 return {};
76 }
77 return GetUsers(deviceId);
78 }
79
GetUsers(const std::string &deviceId)80 std::vector<UserStatus> UserDelegate::GetUsers(const std::string &deviceId)
81 {
82 std::vector<UserStatus> userStatus;
83 deviceUser_.Compute(deviceId, [&userStatus](const auto &key, auto &users) {
84 if (users.empty()) {
85 UserMetaData userMetaData;
86 MetaDataManager::GetInstance().LoadMeta(UserMetaRow::GetKeyFor(key), userMetaData);
87 for (const auto &user : userMetaData.users) {
88 users[user.id] = user.isActive;
89 }
90 }
91 for (const auto [key, value] : users) {
92 userStatus.emplace_back(key, value);
93 }
94 return !users.empty();
95 });
96 auto time = static_cast<uint64_t>(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count());
97 ZLOGI("device:%{public}s, users:%{public}s times %{public}" PRIu64 ".", Anonymous::Change(deviceId).c_str(),
98 Serializable::Marshall(userStatus).c_str(), time);
99 return userStatus;
100 }
101
DeleteUsers(const std::string &deviceId)102 void UserDelegate::DeleteUsers(const std::string &deviceId)
103 {
104 deviceUser_.Erase(deviceId);
105 }
106
UpdateUsers(const std::string &deviceId, const std::vector<UserStatus> &userStatus)107 void UserDelegate::UpdateUsers(const std::string &deviceId, const std::vector<UserStatus> &userStatus)
108 {
109 ZLOGI("begin, device:%{public}s, users:%{public}zu", Anonymous::Change(deviceId).c_str(), userStatus.size());
110 deviceUser_.Compute(deviceId, [&userStatus](const auto &key, std::map<int, bool> &users) {
111 users = {};
112 for (const auto &user : userStatus) {
113 users[user.id] = user.isActive;
114 }
115 ZLOGI("end, device:%{public}s, users:%{public}zu", Anonymous::Change(key).c_str(), users.size());
116 return true;
117 });
118 }
119
InitLocalUserMeta()120 bool UserDelegate::InitLocalUserMeta()
121 {
122 std::vector<int> users;
123 auto ret = AccountDelegate::GetInstance()->QueryUsers(users);
124 if (!ret || users.empty()) {
125 ZLOGE("failed to query os accounts, ret:%{public}d", ret);
126 return false;
127 }
128 std::vector<UserStatus> userStatus = { { 0, true } };
129 for (const auto &user : users) {
130 userStatus.emplace_back(user, true);
131 }
132 UserMetaData userMetaData;
133 userMetaData.deviceId = GetLocalDeviceId();
134 UpdateUsers(userMetaData.deviceId, userStatus);
135 deviceUser_.ComputeIfPresent(userMetaData.deviceId, [&userMetaData](const auto &, std::map<int, bool> &users) {
136 for (const auto &[key, value] : users) {
137 userMetaData.users.emplace_back(key, value);
138 }
139 return true;
140 });
141 ZLOGI("put user meta data save meta data");
142 return MetaDataManager::GetInstance().SaveMeta(UserMetaRow::GetKeyFor(userMetaData.deviceId), userMetaData);
143 }
144
GetInstance()145 UserDelegate &UserDelegate::GetInstance()
146 {
147 static UserDelegate instance;
148 return instance;
149 }
150
Init(const std::shared_ptr<ExecutorPool> &executors)151 void UserDelegate::Init(const std::shared_ptr<ExecutorPool> &executors)
152 {
153 auto ret = AccountDelegate::GetInstance()->Subscribe(std::make_shared<LocalUserObserver>(*this));
154 MetaDataManager::GetInstance().Subscribe(
155 UserMetaRow::KEY_PREFIX, [this](const std::string &key, const std::string &value, int32_t flag) -> auto {
156 UserMetaData metaData;
157 if (value.empty()) {
158 MetaDataManager::GetInstance().LoadMeta(key, metaData);
159 } else {
160 UserMetaData::Unmarshall(value, metaData);
161 }
162 ZLOGD("flag:%{public}d, value:%{public}s", flag, Anonymous::Change(metaData.deviceId).c_str());
163 if (metaData.deviceId == GetLocalDeviceId()) {
164 ZLOGD("ignore local device user meta change");
165 return false;
166 }
167 if (flag == MetaDataManager::INSERT || flag == MetaDataManager::UPDATE) {
168 UpdateUsers(metaData.deviceId, metaData.users);
169 } else if (flag == MetaDataManager::DELETE) {
170 DeleteUsers(metaData.deviceId);
171 } else {
172 ZLOGD("ignored operation");
173 }
174 return true;
175 });
176 if (!executors_) {
177 executors_ = executors;
178 }
179 executors_->Execute(GeTask());
180 ZLOGD("subscribe os account ret:%{public}d", ret);
181 }
182
GeTask()183 ExecutorPool::Task UserDelegate::GeTask()
184 {
185 return [this] {
186 auto ret = InitLocalUserMeta();
187 if (ret) {
188 return;
189 }
190 executors_->Schedule(std::chrono::milliseconds(RETRY_INTERVAL), GeTask());
191 };
192 }
193
NotifyUserEvent(const UserDelegate::UserEvent &userEvent)194 bool UserDelegate::NotifyUserEvent(const UserDelegate::UserEvent &userEvent)
195 {
196 // update all local user status
197 (void)userEvent;
198 return InitLocalUserMeta();
199 }
200
LocalUserObserver(UserDelegate &userDelegate)201 UserDelegate::LocalUserObserver::LocalUserObserver(UserDelegate &userDelegate) : userDelegate_(userDelegate) {}
202
OnAccountChanged(const DistributedKv::AccountEventInfo &eventInfo)203 void UserDelegate::LocalUserObserver::OnAccountChanged(const DistributedKv::AccountEventInfo &eventInfo)
204 {
205 ZLOGI("event info:%{public}s, %{public}d", eventInfo.userId.c_str(), eventInfo.status);
206 userDelegate_.NotifyUserEvent({}); // just notify
207 }
208
Name()209 std::string UserDelegate::LocalUserObserver::Name()
210 {
211 return "user_delegate";
212 }
213 } // namespace OHOS::DistributedData