• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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