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