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