1 /*
2 * Copyright (c) 2024 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_log_wrapper.h"
19 #include "idistributed_account_event.h"
20 #include "distributed_account_subscribe_death_recipient.h"
21 #include "distributed_account_subscribe_manager.h"
22
23 namespace OHOS {
24 namespace AccountSA {
25 namespace {
26 const char THREAD_DISTRIBUTED_ACCOUNT_EVENT[] = "distributedAccountEvent";
27 }
28
DistributedAccountSubscribeManager()29 DistributedAccountSubscribeManager::DistributedAccountSubscribeManager()
30 : subscribeDeathRecipient_(sptr<IRemoteObject::DeathRecipient>(
31 new (std::nothrow) DistributedAccountSubscribeDeathRecipient()))
32 {}
33
GetInstance()34 DistributedAccountSubscribeManager &DistributedAccountSubscribeManager::GetInstance()
35 {
36 static DistributedAccountSubscribeManager *instance = new (std::nothrow) DistributedAccountSubscribeManager();
37 return *instance;
38 }
39
SubscribeDistributedAccountEvent( const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type, const sptr<IRemoteObject> &eventListener)40 ErrCode DistributedAccountSubscribeManager::SubscribeDistributedAccountEvent(
41 const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type, const sptr<IRemoteObject> &eventListener)
42 {
43 ACCOUNT_LOGI("Subscribe distributed account in submanager.");
44 if (eventListener == nullptr) {
45 ACCOUNT_LOGE("EventListener is nullptr.");
46 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
47 }
48 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
49 auto it = std::find_if(subscribeRecords_.begin(), subscribeRecords_.end(), [&eventListener](const auto& record) {
50 return record->eventListener_ == eventListener;
51 });
52 if (it != subscribeRecords_.end()) {
53 (*it)->types_.insert(type);
54 return ERR_OK;
55 }
56
57 auto subscribeRecordPtr = std::make_shared<DistributedSubscribeRecord>(eventListener);
58 if (subscribeDeathRecipient_ != nullptr) {
59 eventListener->AddDeathRecipient(subscribeDeathRecipient_);
60 }
61 subscribeRecordPtr->eventListener_ = eventListener;
62 subscribeRecordPtr->types_.insert(type);
63 subscribeRecords_.emplace_back(subscribeRecordPtr);
64 return ERR_OK;
65 }
66
UnsubscribeDistributedAccountEvent( const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type, const sptr<IRemoteObject> &eventListener)67 ErrCode DistributedAccountSubscribeManager::UnsubscribeDistributedAccountEvent(
68 const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type, const sptr<IRemoteObject> &eventListener)
69 {
70 ACCOUNT_LOGI("Unsubscribe distributed account in submanager.");
71 if (eventListener == nullptr) {
72 ACCOUNT_LOGE("EventListener is nullptr.");
73 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
74 }
75 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
76 for (auto it = subscribeRecords_.begin(); it != subscribeRecords_.end(); ++it) {
77 if ((*it)->eventListener_ == eventListener) {
78 (*it)->types_.erase(type);
79 if (!(*it)->types_.empty()) {
80 return ERR_OK;
81 }
82 if (subscribeDeathRecipient_ != nullptr) {
83 eventListener->RemoveDeathRecipient(subscribeDeathRecipient_);
84 }
85 (*it)->eventListener_ = nullptr;
86 subscribeRecords_.erase(it);
87 return ERR_OK;
88 }
89 }
90 ACCOUNT_LOGE("Unsubscribe failed, subscribe record not find.");
91 return ERR_OHOSACCOUNT_KIT_NO_SPECIFIED_CALLBACK_HAS_BEEN_REGISTERED;
92 }
93
UnsubscribeDistributedAccountEvent( const sptr<IRemoteObject> &eventListener)94 ErrCode DistributedAccountSubscribeManager::UnsubscribeDistributedAccountEvent(
95 const sptr<IRemoteObject> &eventListener)
96 {
97 ACCOUNT_LOGI("Unsubscribe distributed account in submanager.");
98 if (eventListener == nullptr) {
99 ACCOUNT_LOGE("EventListener is nullptr.");
100 return ERR_ACCOUNT_COMMON_NULL_PTR_ERROR;
101 }
102
103 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
104 if (subscribeDeathRecipient_ != nullptr) {
105 eventListener->RemoveDeathRecipient(subscribeDeathRecipient_);
106 }
107 for (auto it = subscribeRecords_.begin(); it != subscribeRecords_.end(); ++it) {
108 if (eventListener == (*it)->eventListener_) {
109 (*it)->eventListener_ = nullptr;
110 subscribeRecords_.erase(it);
111 break;
112 }
113 }
114 return ERR_OK;
115 }
116
OnAccountsChanged( const DistributedSubscribeRecordPtr &distributedSubscribeRecordPtr, const int id, DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE subscribeType)117 bool DistributedAccountSubscribeManager::OnAccountsChanged(
118 const DistributedSubscribeRecordPtr &distributedSubscribeRecordPtr, const int id,
119 DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE subscribeType)
120 {
121 auto distributedAccountEventProxy = iface_cast<IDistributedAccountEvent>(
122 distributedSubscribeRecordPtr->eventListener_);
123 if (distributedAccountEventProxy == 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 distributedAccountEventProxy->OnAccountsChanged(eventData);
132 return true;
133 }
134
Publish(const int id, DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE subscribeType)135 ErrCode DistributedAccountSubscribeManager::Publish(const int id, DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE subscribeType)
136 {
137 std::lock_guard<std::mutex> lock(subscribeRecordMutex_);
138 uint32_t sendCnt = 0;
139 for (auto it = subscribeRecords_.begin(); it != subscribeRecords_.end(); ++it) {
140 if ((*it)->types_.find(subscribeType) != (*it)->types_.end()) {
141 auto task = [this, it, id, subscribeType] { this->OnAccountsChanged((*it), id, subscribeType); };
142 std::thread taskThread(task);
143 pthread_setname_np(taskThread.native_handle(), THREAD_DISTRIBUTED_ACCOUNT_EVENT);
144 taskThread.detach();
145 ++sendCnt;
146 }
147 }
148 ACCOUNT_LOGI("Publish DistributedAccountEvent %{public}d succeed, id=%{public}d, sendCnt=%{public}u.",
149 subscribeType, id, sendCnt);
150 return ERR_OK;
151 }
152 } // namespace AccountSA
153 } // namespace OHOS
154