1 /*
2 * Copyright (c) 2025 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 "os_account_constraint_subscriber_manager.h"
17
18 #include "account_error_no.h"
19 #include "account_log_wrapper.h"
20 #include "os_account_constants.h"
21 #include <pthread.h>
22 #include <thread>
23
24 namespace OHOS {
25 namespace AccountSA {
26 namespace {
27 const char THREAD_OS_ACCOUNT_CONSTRAINT_EVENT[] = "OsAccountConstraintEvent";
28
ConvertToAccountErrCode(ErrCode idlErrCode)29 ErrCode ConvertToAccountErrCode(ErrCode idlErrCode)
30 {
31 if (idlErrCode == ERR_INVALID_VALUE) {
32 return ERR_ACCOUNT_COMMON_WRITE_DESCRIPTOR_ERROR;
33 }
34 if (idlErrCode == ERR_INVALID_DATA) {
35 return ERR_ACCOUNT_COMMON_WRITE_PARCEL_ERROR;
36 }
37 return idlErrCode;
38 }
39 }
GetInstance()40 OsAccountConstraintSubscriberManager* OsAccountConstraintSubscriberManager::GetInstance()
41 {
42 static sptr<OsAccountConstraintSubscriberManager> instance =
43 new (std::nothrow) OsAccountConstraintSubscriberManager();
44 return instance.GetRefPtr();
45 }
46
OsAccountConstraintSubscriberManager()47 OsAccountConstraintSubscriberManager::OsAccountConstraintSubscriberManager() {}
48
OnConstraintChanged(int32_t localId,const std::set<std::string> & constraints,bool enable)49 ErrCode OsAccountConstraintSubscriberManager::OnConstraintChanged(
50 int32_t localId, const std::set<std::string> &constraints, bool enable)
51 {
52 std::lock_guard<std::mutex> lock(mutex_);
53 for (auto const &constraint : constraints) {
54 for (auto const &subscriber: constraint2SubscriberMap_[constraint]) {
55 OsAccountConstraintStateData data{localId, constraint, enable};
56 auto task = [subscriber, data]() mutable {
57 subscriber->OnConstraintChanged(data);
58 };
59 std::thread taskThread(task);
60 pthread_setname_np(taskThread.native_handle(), THREAD_OS_ACCOUNT_CONSTRAINT_EVENT);
61 taskThread.detach();
62 }
63 }
64 return ERR_OK;
65 }
66
InsertSubscriberRecord(const std::shared_ptr<OsAccountConstraintSubscriber> & subscriber)67 void OsAccountConstraintSubscriberManager::InsertSubscriberRecord(
68 const std::shared_ptr<OsAccountConstraintSubscriber> &subscriber)
69 {
70 std::set<std::string> constraintSet;
71 subscriber->GetConstraintSet(constraintSet);
72 subscriberSet_.emplace(subscriber);
73 for (auto const &constraint : constraintSet) {
74 constraint2SubscriberMap_[constraint].emplace(subscriber);
75 constraintSet_.emplace(constraint);
76 }
77 }
78
HasSubscribed(const std::shared_ptr<OsAccountConstraintSubscriber> & subscriber)79 bool OsAccountConstraintSubscriberManager::HasSubscribed(
80 const std::shared_ptr<OsAccountConstraintSubscriber> &subscriber)
81 {
82 return subscriberSet_.find(subscriber) != subscriberSet_.end();
83 }
84
RemoveSubscriberRecord(const std::shared_ptr<OsAccountConstraintSubscriber> & subscriber)85 void OsAccountConstraintSubscriberManager::RemoveSubscriberRecord(
86 const std::shared_ptr<OsAccountConstraintSubscriber> &subscriber)
87 {
88 std::set<std::string> constraintSet;
89 subscriber->GetConstraintSet(constraintSet);
90 subscriberSet_.erase(subscriber);
91 for (auto const &item : constraintSet) {
92 constraint2SubscriberMap_[item].erase(subscriber);
93 if (constraint2SubscriberMap_[item].empty()) {
94 constraint2SubscriberMap_.erase(item);
95 constraintSet_.erase(item);
96 }
97 }
98 }
99
SubscribeOsAccountConstraints(const std::shared_ptr<OsAccountConstraintSubscriber> & subscriber,sptr<IOsAccount> & proxy)100 ErrCode OsAccountConstraintSubscriberManager::SubscribeOsAccountConstraints(
101 const std::shared_ptr<OsAccountConstraintSubscriber> &subscriber, sptr<IOsAccount> &proxy)
102 {
103 if (subscriber == nullptr) {
104 ACCOUNT_LOGE("Subscriber is nullptr.");
105 return ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
106 }
107 std::set<std::string> constraintSet;
108 subscriber->GetConstraintSet(constraintSet);
109 if (constraintSet.empty()) {
110 ACCOUNT_LOGE("Empty constraints.");
111 return ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
112 }
113 if (constraintSet.size() > Constants::CONSTRAINT_MAX_SIZE) {
114 ACCOUNT_LOGE("Constraints size=%{public}zu is too large.", constraintSet.size());
115 return ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
116 }
117 std::lock_guard<std::mutex> lock(mutex_);
118 if (proxy == nullptr) {
119 ACCOUNT_LOGE("Proxy is nullptr.");
120 return ERR_ACCOUNT_COMMON_GET_PROXY;
121 }
122 if (HasSubscribed(subscriber)) {
123 ACCOUNT_LOGE("Already subscribed.");
124 return ERR_ACCOUNT_COMMON_ACCOUNT_AREADY_SUBSCRIBE_ERROR;
125 }
126 constraintSet.insert(constraintSet_.begin(), constraintSet_.end());
127 if (constraintSet.size() == constraintSet_.size()) {
128 ACCOUNT_LOGI("No need to sync data service.");
129 InsertSubscriberRecord(subscriber);
130 return ERR_OK;
131 }
132 OsAccountConstraintSubscribeInfo subscribeInfo(constraintSet);
133 ErrCode errCode = proxy->SubscribeOsAccountConstraints(subscribeInfo, GetInstance()->AsObject());
134 errCode = ConvertToAccountErrCode(errCode);
135 if (errCode != ERR_OK) {
136 ACCOUNT_LOGE("SubscribeOsAccountConstraints fail, errcode:%{public}d", errCode);
137 return errCode;
138 }
139 InsertSubscriberRecord(subscriber);
140 return ERR_OK;
141 }
142
UnsubscribeOsAccountConstraints(const std::shared_ptr<OsAccountConstraintSubscriber> & subscriber,sptr<IOsAccount> & proxy)143 ErrCode OsAccountConstraintSubscriberManager::UnsubscribeOsAccountConstraints(
144 const std::shared_ptr<OsAccountConstraintSubscriber> &subscriber, sptr<IOsAccount> &proxy)
145 {
146 if (subscriber == nullptr) {
147 ACCOUNT_LOGE("Subscriber is nullptr.");
148 return ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
149 }
150 std::set<std::string> constraintSet;
151 subscriber->GetConstraintSet(constraintSet);
152 std::lock_guard<std::mutex> lock(mutex_);
153 if (proxy == nullptr) {
154 ACCOUNT_LOGE("Proxy is nullptr.");
155 return ERR_ACCOUNT_COMMON_GET_PROXY;
156 }
157 if (!HasSubscribed(subscriber)) {
158 ACCOUNT_LOGE("Not subscribed.");
159 return ERR_ACCOUNT_COMMON_ACCOUNT_SUBSCRIBE_NOT_FOUND_ERROR;
160 }
161 std::set<std::string> syncData;
162 for (auto const &constraint : constraintSet) {
163 if (constraint2SubscriberMap_[constraint].size() == 1) {
164 syncData.emplace(constraint);
165 }
166 }
167 if (syncData.empty()) {
168 ACCOUNT_LOGI("No need to sync data service.");
169 RemoveSubscriberRecord(subscriber);
170 return ERR_OK;
171 }
172 OsAccountConstraintSubscribeInfo info(syncData);
173 ErrCode errCode = proxy->UnsubscribeOsAccountConstraints(info, GetInstance()->AsObject());
174 errCode = ConvertToAccountErrCode(errCode);
175 if (errCode != ERR_OK) {
176 ACCOUNT_LOGE("UnsubscribeOsAccountConstraints fail, errcode:%{public}d", errCode);
177 return errCode;
178 }
179 RemoveSubscriberRecord(subscriber);
180 return ERR_OK;
181 }
182
RestoreConstraintSubscriberRecords(sptr<IOsAccount> & proxy)183 void OsAccountConstraintSubscriberManager::RestoreConstraintSubscriberRecords(sptr<IOsAccount> &proxy)
184 {
185 std::lock_guard<std::mutex> lock(mutex_);
186 if (proxy == nullptr) {
187 ACCOUNT_LOGE("Proxy is nullptr.");
188 return;
189 }
190 if (constraintSet_.empty()) {
191 ACCOUNT_LOGD("RestoreConstraintSubscriberRecords empty.");
192 return;
193 }
194 OsAccountConstraintSubscribeInfo subscribeInfo(constraintSet_);
195 ErrCode errCode = proxy->SubscribeOsAccountConstraints(subscribeInfo, GetInstance()->AsObject());
196 errCode = ConvertToAccountErrCode(errCode);
197 if (errCode != ERR_OK) {
198 ACCOUNT_LOGE("RestoreConstraintSubscriberRecords failed, errCode=%{public}d.", errCode);
199 return;
200 }
201 ACCOUNT_LOGI("RestoreConstraintSubscriberRecords success.");
202 }
203 } // namespace AccountSA
204 } // namespace OHOS