• 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 
16 #include "user_delegate.h"
17 
18 #define LOG_TAG "UserDelegate"
19 
20 #include <thread>
21 #include "communicator/communication_provider.h"
22 #include "executor_factory.h"
23 #include "log_print.h"
24 #include "metadata/meta_data_manager.h"
25 #include "utils/anonymous.h"
26 namespace OHOS::DistributedData {
27 using OHOS::AppDistributedKv::CommunicationProvider;
28 using namespace OHOS::DistributedKv;
GetLocalDeviceId()29 std::string GetLocalDeviceId()
30 {
31     static std::string deviceId;
32     if (deviceId.empty()) {
33         deviceId = CommunicationProvider::GetInstance().GetLocalDevice().uuid;
34     }
35 
36     return deviceId;
37 }
38 
GetLocalUserStatus()39 std::vector<UserStatus> UserDelegate::GetLocalUserStatus()
40 {
41     ZLOGI("begin");
42     auto deviceId = GetLocalDeviceId();
43     if (deviceId.empty()) {
44         ZLOGE("failed to get local device id");
45         return {};
46     }
47     return GetUsers(deviceId);
48 }
49 
GetLocalUsers()50 std::set<std::string> UserDelegate::GetLocalUsers()
51 {
52     auto deviceId = GetLocalDeviceId();
53     if (deviceId.empty()) {
54         ZLOGE("failed to get local device id");
55         return {};
56     }
57     if (!deviceUserMap_.Contains(deviceId)) {
58         LoadFromMeta(deviceId);
59     }
60     std::set<std::string> users;
61     deviceUserMap_.ComputeIfPresent(deviceId, [&users](auto&, std::map<int, bool> &value) {
62         for (auto [user, active] : value) {
63             users.emplace(std::to_string(user));
64         }
65         return !value.empty();
66     });
67     return users;
68 }
69 
GetRemoteUserStatus(const std::string & deviceId)70 std::vector<DistributedData::UserStatus> UserDelegate::GetRemoteUserStatus(const std::string &deviceId)
71 {
72     if (deviceId.empty()) {
73         ZLOGE("error input device id");
74         return {};
75     }
76     return GetUsers(deviceId);
77 }
78 
GetUsers(const std::string & deviceId)79 std::vector<UserStatus> UserDelegate::GetUsers(const std::string &deviceId)
80 {
81     std::vector<UserStatus> userStatus;
82     if (!deviceUserMap_.Contains(deviceId)) {
83         LoadFromMeta(deviceId);
84     }
85     deviceUserMap_.ComputeIfPresent(deviceId, [&userStatus](const auto &, std::map<int, bool> &userMap) {
86         for (const auto &[key, value] : userMap) {
87             userStatus.emplace_back(key, value);
88         }
89         return true;
90     });
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     deviceUserMap_.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}.10s, users:%{public}zu", Anonymous::Change(deviceId).c_str(), userStatus.size());
105     deviceUserMap_.Compute(deviceId, [&userStatus](const auto &key, std::map<int, bool> &userMap) {
106         userMap = {};
107         for (const auto &user : userStatus) {
108             userMap[user.id] = user.isActive;
109         }
110         ZLOGI("end, device:%{public}.10s, users:%{public}zu", Anonymous::Change(key).c_str(), userMap.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     deviceUserMap_.ComputeIfPresent(userMetaData.deviceId, [&userMetaData](const auto &, std::map<int, bool> &userMap) {
131         for (const auto &[key, value] : userMap) {
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 
LoadFromMeta(const std::string & deviceId)140 void UserDelegate::LoadFromMeta(const std::string &deviceId)
141 {
142     UserMetaData userMetaData;
143     MetaDataManager::GetInstance().LoadMeta(UserMetaRow::GetKeyFor(deviceId), userMetaData);
144     std::map<int, bool> userMap;
145     for (const auto &user : userMetaData.users) {
146         userMap[user.id] = user.isActive;
147     }
148     deviceUserMap_.Compute(deviceId, [&userMap](const auto &, auto &value) {
149         value = userMap;
150         return true;
151     });
152 }
153 
GetInstance()154 UserDelegate &UserDelegate::GetInstance()
155 {
156     static UserDelegate instance;
157     return instance;
158 }
159 
Init()160 void UserDelegate::Init()
161 {
162     KvStoreTask retryTask([this]() {
163         do {
164             static constexpr int RETRY_INTERVAL = 500; // millisecond
165             std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_INTERVAL));
166             if (!InitLocalUserMeta()) {
167                 continue;
168             }
169             break;
170         } while (true);
171         ZLOGI("update user meta ok");
172     });
173 
174     auto ret = AccountDelegate::GetInstance()->Subscribe(std::make_shared<LocalUserObserver>(*this));
175     MetaDataManager::GetInstance().Subscribe(
176         UserMetaRow::KEY_PREFIX, [this](const std::string &key, const std::string &value, int32_t flag) -> auto {
177             UserMetaData metaData;
178             UserMetaData::Unmarshall(value, metaData);
179             ZLOGD("flag:%{public}d, value:%{public}s", flag, Anonymous::Change(metaData.deviceId).c_str());
180             if (metaData.deviceId == GetLocalDeviceId()) {
181                 ZLOGD("ignore local device user meta change");
182                 return false;
183             }
184             if (flag == MetaDataManager::INSERT || flag == MetaDataManager::UPDATE) {
185                 UpdateUsers(metaData.deviceId, metaData.users);
186             } else if (flag == MetaDataManager::DELETE) {
187                 DeleteUsers(metaData.deviceId);
188             } else {
189                 ZLOGD("ignored operation");
190             }
191             return true;
192     });
193     if (!InitLocalUserMeta()) {
194         ExecutorFactory::GetInstance().Execute(std::move(retryTask));
195     }
196     ZLOGD("subscribe os account ret:%{public}d", ret);
197 }
198 
NotifyUserEvent(const UserDelegate::UserEvent & userEvent)199 bool UserDelegate::NotifyUserEvent(const UserDelegate::UserEvent &userEvent)
200 {
201     // update all local user status
202     (void) userEvent;
203     return InitLocalUserMeta();
204 }
205 
LocalUserObserver(UserDelegate & userDelegate)206 UserDelegate::LocalUserObserver::LocalUserObserver(UserDelegate &userDelegate) : userDelegate_(userDelegate)
207 {
208 }
209 
OnAccountChanged(const DistributedKv::AccountEventInfo & eventInfo)210 void UserDelegate::LocalUserObserver::OnAccountChanged(const DistributedKv::AccountEventInfo &eventInfo)
211 {
212     ZLOGI("event info:%{public}s, %{public}d", eventInfo.userId.c_str(), eventInfo.status);
213     userDelegate_.NotifyUserEvent({}); // just notify
214 }
215 
Name()216 std::string UserDelegate::LocalUserObserver::Name()
217 {
218     return "user_delegate";
219 }
220 } // namespace OHOS::DistributedData
221