• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_subscribe_manager.h"
17 
18 #include <thread>
19 #include "account_constants.h"
20 #include "account_hisysevent_adapter.h"
21 #include "account_log_wrapper.h"
22 #include "os_account_constraint_subscribe_death_recipient.h"
23 #include "ipc_skeleton.h"
24 #include "ios_account_constraint_event.h"
25 #ifdef HICOLLIE_ENABLE
26 #include "account_timer.h"
27 #include "xcollie/xcollie.h"
28 #endif // HICOLLIE_ENABLE
29 
30 namespace OHOS {
31 namespace AccountSA {
32 namespace {
33 const char THREAD_CONSTRAINT_EVENT[] = "constraintEvent";
34 }
OsAccountConstraintSubscribeManager()35 OsAccountConstraintSubscribeManager::OsAccountConstraintSubscribeManager()
36     : subscribeDeathRecipient_(sptr<IRemoteObject::DeathRecipient>(
37         new (std::nothrow) OsAccountConstraintSubscribeDeathRecipient()))
38 {}
39 
GetInstance()40 OsAccountConstraintSubscribeManager &OsAccountConstraintSubscribeManager::GetInstance()
41 {
42     static OsAccountConstraintSubscribeManager instance;
43     return instance;
44 }
45 
RemoveConstraintFromSubscribeRecord(const OsAccountConstraintSubscribeRecordPtr & recordPtr,const std::set<std::string> & constraints)46 void OsAccountConstraintSubscribeManager::RemoveConstraintFromSubscribeRecord(
47     const OsAccountConstraintSubscribeRecordPtr &recordPtr, const std::set<std::string> &constraints)
48 {
49     for (auto const &constraint : constraints) {
50         constraint2RecordMap_[constraint].erase(recordPtr);
51         if (constraint2RecordMap_[constraint].empty()) {
52             constraint2RecordMap_.erase(constraint);
53         }
54         recordPtr->constraintSet_.erase(constraint);
55     }
56     if (recordPtr->constraintSet_.empty()) {
57         constraintRecords_.erase(recordPtr);
58     }
59 }
60 
InsertSubscribeRecord(const OsAccountConstraintSubscribeRecordPtr & recordPtr)61 void OsAccountConstraintSubscribeManager::InsertSubscribeRecord(
62     const OsAccountConstraintSubscribeRecordPtr &recordPtr)
63 {
64     constraintRecords_.emplace(recordPtr);
65     for (auto const &constraint : recordPtr->constraintSet_) {
66         constraint2RecordMap_[constraint].emplace(recordPtr);
67     }
68 }
69 
SubscribeOsAccountConstraints(const std::set<std::string> & constraints,const sptr<IRemoteObject> & eventListener)70 ErrCode OsAccountConstraintSubscribeManager::SubscribeOsAccountConstraints(const std::set<std::string> &constraints,
71     const sptr<IRemoteObject> &eventListener)
72 {
73     if (eventListener == nullptr) {
74         ACCOUNT_LOGE("EventListener is nullptr");
75         return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
76     }
77     std::lock_guard<std::mutex> lock(mutex_);
78     int32_t callingUid = IPCSkeleton::GetCallingUid();
79     for (auto const &recordPtr : constraintRecords_) {
80         if (recordPtr->eventListener_ != eventListener) {
81             continue;
82         }
83         recordPtr->constraintSet_ = constraints;
84         InsertSubscribeRecord(recordPtr);
85         return ERR_OK;
86     }
87     if (subscribeDeathRecipient_ != nullptr) {
88         eventListener->AddDeathRecipient(subscribeDeathRecipient_);
89     }
90     auto recordPtr = std::make_shared<OsAccountConstraintSubscribeRecord>(constraints, eventListener, callingUid);
91     InsertSubscribeRecord(recordPtr);
92     return ERR_OK;
93 }
94 
UnsubscribeOsAccountConstraints(const sptr<IRemoteObject> & eventListener)95 ErrCode OsAccountConstraintSubscribeManager::UnsubscribeOsAccountConstraints(const sptr<IRemoteObject> &eventListener)
96 {
97     if (eventListener == nullptr) {
98         ACCOUNT_LOGE("EventListener is nullptr");
99         return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
100     }
101     std::lock_guard<std::mutex> lock(mutex_);
102     for (auto const &recordPtr : constraintRecords_) {
103         if (recordPtr->eventListener_ != eventListener) {
104             continue;
105         }
106         if (subscribeDeathRecipient_ != nullptr) {
107             eventListener->RemoveDeathRecipient(subscribeDeathRecipient_);
108         }
109         std::set<std::string> constraints = recordPtr->constraintSet_;
110         RemoveConstraintFromSubscribeRecord(recordPtr, constraints);
111         return ERR_OK;
112     }
113     return ERR_ACCOUNT_COMMON_ACCOUNT_SUBSCRIBE_NOT_FOUND_ERROR;
114 }
115 
UnsubscribeOsAccountConstraints(const std::set<std::string> & constraints,const sptr<IRemoteObject> & eventListener)116 ErrCode OsAccountConstraintSubscribeManager::UnsubscribeOsAccountConstraints(const std::set<std::string> &constraints,
117     const sptr<IRemoteObject> &eventListener)
118 {
119     if (eventListener == nullptr) {
120         ACCOUNT_LOGE("EventListener is nullptr");
121         return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
122     }
123     std::lock_guard<std::mutex> lock(mutex_);
124     for (auto const &recordPtr : constraintRecords_) {
125         if (recordPtr->eventListener_ != eventListener) {
126             continue;
127         }
128         bool isInclude = std::includes(recordPtr->constraintSet_.begin(), recordPtr->constraintSet_.end(),
129             constraints.begin(), constraints.end());
130         if (!isInclude) {
131             ACCOUNT_LOGE("Constraint set not include.");
132             return ERR_ACCOUNT_COMMON_ACCOUNT_SUBSCRIBE_NOT_FOUND_ERROR;
133         }
134         RemoveConstraintFromSubscribeRecord(recordPtr, constraints);
135         return ERR_OK;
136     }
137     ACCOUNT_LOGE("Constraint record not found.");
138     return ERR_ACCOUNT_COMMON_ACCOUNT_SUBSCRIBE_NOT_FOUND_ERROR;
139 }
140 
PublishToSubscriber(const OsAccountConstraintSubscribeRecordPtr & recordPtr,int32_t localId,const std::set<std::string> & constraints,bool isEnabled)141 void OsAccountConstraintSubscribeManager::PublishToSubscriber(const OsAccountConstraintSubscribeRecordPtr &recordPtr,
142     int32_t localId, const std::set<std::string> &constraints, bool isEnabled)
143 {
144     if (recordPtr->eventListener_ == nullptr) {
145         ACCOUNT_LOGE("Subscribe constraint is null, localId=%{public}d, uid=%{public}d.", localId,
146             recordPtr->callingUid_);
147         return;
148     }
149     auto eventProxy = iface_cast<IOsAccountConstraintEvent>(recordPtr->eventListener_);
150     if (eventProxy == nullptr) {
151         ACCOUNT_LOGE("Event proxy is nullptr");
152         return;
153     }
154     int32_t retryTimes = 0;
155     ErrCode result;
156     while (retryTimes < Constants::MAX_RETRY_TIMES) {
157         result = eventProxy->OnConstraintChanged(localId, constraints, isEnabled);
158         if (result == ERR_OK || (result != Constants::E_IPC_ERROR &&
159             result != Constants::E_IPC_SA_DIED)) {
160             break;
161         }
162         retryTimes++;
163         ACCOUNT_LOGE("Failed to send the OS account event, reqCode: %{public}d, retryTimes: %{public}d",
164             result, retryTimes);
165         std::this_thread::sleep_for(std::chrono::milliseconds(Constants::DELAY_FOR_EXCEPTION));
166     }
167     if (result != ERR_OK) {
168         ACCOUNT_LOGE("SendRequest for constraint changed failed! result %{public}d, localId %{public}d.",
169             result, localId);
170         REPORT_OS_ACCOUNT_FAIL(localId, Constants::OPERATION_EVENT_PUBLISH,
171             result, "Send OnConstraintChanged subscribe failed");
172     }
173 }
174 
Publish(int32_t localId,const std::set<std::string> & constraints,const bool isEnabled)175 void OsAccountConstraintSubscribeManager::Publish(int32_t localId, const std::set<std::string> &constraints,
176     const bool isEnabled)
177 {
178     std::lock_guard<std::mutex> lock(mutex_);
179     std::set<OsAccountConstraintSubscribeRecordPtr> recordPtrSet;
180     for (auto const &item : constraints) {
181         auto iter = constraint2RecordMap_.find(item);
182         if (iter != constraint2RecordMap_.end()) {
183             recordPtrSet.insert(iter->second.begin(), iter->second.end());
184         }
185     }
186     for (auto const &item : recordPtrSet) {
187         auto task = [item, localId, constraints, isEnabled, this] {
188             ACCOUNT_LOGI("Publish start, to uid=%{public}d asynch, accountId=%{public}d, enable=%{public}d",
189                 item->callingUid_, localId, isEnabled);
190             this->PublishToSubscriber(item, localId, constraints, isEnabled);
191             ACCOUNT_LOGI("Publish end.");
192         };
193         std::thread taskThread(task);
194         pthread_setname_np(taskThread.native_handle(), THREAD_CONSTRAINT_EVENT);
195         taskThread.detach();
196     }
197 }
198 } // AccountSA
199 } // OHOS