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