1 /*
2 * Copyright (c) 2024-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 <pthread.h>
17 #include <thread>
18 #include "account_constants.h"
19 #include "account_log_wrapper.h"
20 #include "account_hisysevent_adapter.h"
21 #include "distributed_account_subscribe_death_recipient.h"
22 #include "distributed_account_subscribe_manager.h"
23
24 namespace OHOS {
25 namespace AccountSA {
26 namespace {
27 const char THREAD_DISTRIBUTED_ACCOUNT_EVENT[] = "distributedAccountEvent";
28 }
29
DistributedAccountSubscribeManager()30 DistributedAccountSubscribeManager::DistributedAccountSubscribeManager()
31 : subscribeDeathRecipient_(sptr<IRemoteObject::DeathRecipient>(
32 new (std::nothrow) DistributedAccountSubscribeDeathRecipient()))
33 {}
34
GetInstance()35 DistributedAccountSubscribeManager &DistributedAccountSubscribeManager::GetInstance()
36 {
37 static DistributedAccountSubscribeManager *instance = new (std::nothrow) DistributedAccountSubscribeManager();
38 return *instance;
39 }
40
SubscribeDistributedAccountEvent(const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type,const sptr<IRemoteObject> & eventListener)41 ErrCode DistributedAccountSubscribeManager::SubscribeDistributedAccountEvent(
42 const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type, const sptr<IRemoteObject> &eventListener)
43 {
44 ACCOUNT_LOGI("Subscribe distributed account in submanager.");
45 if (eventListener == nullptr) {
46 ACCOUNT_LOGE("EventListener is nullptr.");
47 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
48 }
49 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
50 auto it = std::find_if(subscribeRecords_.begin(), subscribeRecords_.end(), [&eventListener](const auto& record) {
51 return record->eventListener_ == eventListener;
52 });
53 if (it != subscribeRecords_.end()) {
54 (*it)->types_.insert(type);
55 ACCOUNT_LOGI("Subscribe already exsits, update type only, type size=%{public}zu.", (*it)->types_.size());
56 return ERR_OK;
57 }
58
59 auto subscribeRecordPtr = std::make_shared<DistributedSubscribeRecord>(eventListener);
60 if (subscribeDeathRecipient_ != nullptr) {
61 eventListener->AddDeathRecipient(subscribeDeathRecipient_);
62 }
63 subscribeRecordPtr->eventListener_ = eventListener;
64 subscribeRecordPtr->types_.insert(type);
65 ACCOUNT_LOGI("Subscribe add, type size=%{public}zu.", subscribeRecordPtr->types_.size());
66 subscribeRecords_.emplace_back(subscribeRecordPtr);
67 return ERR_OK;
68 }
69
UnsubscribeDistributedAccountEvent(const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type,const sptr<IRemoteObject> & eventListener)70 ErrCode DistributedAccountSubscribeManager::UnsubscribeDistributedAccountEvent(
71 const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type, const sptr<IRemoteObject> &eventListener)
72 {
73 ACCOUNT_LOGI("Unsubscribe distributed account in submanager.");
74 if (eventListener == nullptr) {
75 ACCOUNT_LOGE("EventListener is nullptr.");
76 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
77 }
78 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
79 for (auto it = subscribeRecords_.begin(); it != subscribeRecords_.end(); ++it) {
80 if ((*it)->eventListener_ == eventListener) {
81 (*it)->types_.erase(type);
82 if (!(*it)->types_.empty()) {
83 return ERR_OK;
84 }
85 if (subscribeDeathRecipient_ != nullptr) {
86 eventListener->RemoveDeathRecipient(subscribeDeathRecipient_);
87 }
88 (*it)->eventListener_ = nullptr;
89 subscribeRecords_.erase(it);
90 return ERR_OK;
91 }
92 }
93 ACCOUNT_LOGE("Unsubscribe failed, subscribe record not find.");
94 return ERR_OHOSACCOUNT_KIT_NO_SPECIFIED_CALLBACK_HAS_BEEN_REGISTERED;
95 }
96
UnsubscribeDistributedAccountEvent(const sptr<IRemoteObject> & eventListener)97 ErrCode DistributedAccountSubscribeManager::UnsubscribeDistributedAccountEvent(
98 const sptr<IRemoteObject> &eventListener)
99 {
100 ACCOUNT_LOGI("Unsubscribe distributed account in submanager.");
101 if (eventListener == nullptr) {
102 ACCOUNT_LOGE("EventListener is nullptr.");
103 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
104 }
105
106 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
107 if (subscribeDeathRecipient_ != nullptr) {
108 eventListener->RemoveDeathRecipient(subscribeDeathRecipient_);
109 }
110 for (auto it = subscribeRecords_.begin(); it != subscribeRecords_.end(); ++it) {
111 if (eventListener == (*it)->eventListener_) {
112 (*it)->eventListener_ = nullptr;
113 subscribeRecords_.erase(it);
114 break;
115 }
116 }
117 return ERR_OK;
118 }
119
OnAccountsChanged(const sptr<IDistributedAccountEvent> & eventProxy,const int id,DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE subscribeType)120 bool DistributedAccountSubscribeManager::OnAccountsChanged(
121 const sptr<IDistributedAccountEvent> &eventProxy, const int id, DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE subscribeType)
122 {
123 if (eventProxy == nullptr) {
124 ACCOUNT_LOGE("Get app account event proxy failed.");
125 return false;
126 }
127 DistributedAccountEventData eventData;
128 eventData.id_ = id;
129 eventData.type_ = subscribeType;
130
131 int32_t retryTimes = 0;
132 ErrCode result = ERR_OK;
133 while (retryTimes < Constants::MAX_RETRY_TIMES) {
134 result = eventProxy->OnAccountsChanged(eventData);
135 if (result == ERR_OK || (result != Constants::E_IPC_ERROR &&
136 result != Constants::E_IPC_SA_DIED)) {
137 break;
138 }
139 retryTimes++;
140 ACCOUNT_LOGE("Send distributed account event request failed, code=%{public}d, retryTimes=%{public}d",
141 result, retryTimes);
142 std::this_thread::sleep_for(std::chrono::milliseconds(Constants::DELAY_FOR_EXCEPTION));
143 }
144 if (result != ERR_OK) {
145 ACCOUNT_LOGE("SendRequest for account changed failed, result=%{public}d eventData.id=%{public}d.",
146 result, eventData.id_);
147 REPORT_OHOS_ACCOUNT_FAIL(eventData.id_, Constants::OPERATION_EVENT_PUBLISH,
148 result, "Send OnAccountsChanged failed.");
149 return false;
150 }
151 return true;
152 }
153
Publish(const int id,DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE subscribeType)154 ErrCode DistributedAccountSubscribeManager::Publish(const int id, DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE subscribeType)
155 {
156 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
157 uint32_t sendCnt = 0;
158 for (auto it = subscribeRecords_.begin(); it != subscribeRecords_.end(); ++it) {
159 if ((*it)->types_.find(subscribeType) != (*it)->types_.end()) {
160 auto eventProxy = iface_cast<IDistributedAccountEvent>((*it)->eventListener_);
161 if (eventProxy == nullptr) {
162 ACCOUNT_LOGE("Get eventProxy failed");
163 break;
164 }
165 auto task = [this, eventProxy, id, subscribeType] {
166 this->OnAccountsChanged(eventProxy, id, subscribeType);
167 };
168 std::thread taskThread(task);
169 pthread_setname_np(taskThread.native_handle(), THREAD_DISTRIBUTED_ACCOUNT_EVENT);
170 taskThread.detach();
171 ++sendCnt;
172 }
173 }
174 ACCOUNT_LOGI("Publish DistributedAccountEvent %{public}d succeed, id=%{public}d, sendCnt=%{public}u.",
175 subscribeType, id, sendCnt);
176 return ERR_OK;
177 }
178 } // namespace AccountSA
179 } // namespace OHOS
180