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