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