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 "client_death_handler.h"
17 #include "mmi_log.h"
18
19 #undef MMI_LOG_TAG
20 #define MMI_LOG_TAG "ClientDeathHandler"
21
22 namespace OHOS {
23 namespace MMI {
ClientDeathHandler()24 ClientDeathHandler::ClientDeathHandler() {}
25
~ClientDeathHandler()26 ClientDeathHandler::~ClientDeathHandler() {}
27
RegisterClientDeathRecipient(const sptr<IRemoteObject> & binderClientSrv,int32_t pid)28 bool ClientDeathHandler::RegisterClientDeathRecipient(const sptr<IRemoteObject> &binderClientSrv, int32_t pid)
29 {
30 CALL_DEBUG_ENTER;
31 if (!RegisterClientDeathRecipient(binderClientSrv)) {
32 return false;
33 }
34 if (!AddClientPid(binderClientSrv, pid)) {
35 return false;
36 }
37 return true;
38 }
39
AddClientDeathCallback(CallBackType type,ClientDeathCallback callback)40 bool ClientDeathHandler::AddClientDeathCallback(CallBackType type, ClientDeathCallback callback)
41 {
42 CALL_DEBUG_ENTER;
43 CHKPF(callback);
44 std::lock_guard<std::mutex> callBackLock(mutexCallbacks_);
45 [[ maybe_unused ]] bool bFind = false;
46 auto it = deathCallbacks_.find(type);
47 if (it != deathCallbacks_.end()) {
48 MMI_HILOGE("Death callBack has existed type:%{public}d", type);
49 return false;
50 }
51 deathCallbacks_.insert(std::make_pair(type, callback));
52 return true;
53 }
54
UnregisterClientDeathRecipient(const wptr<IRemoteObject> & remoteObj)55 bool ClientDeathHandler::UnregisterClientDeathRecipient(const wptr<IRemoteObject> &remoteObj)
56 {
57 CALL_DEBUG_ENTER;
58 CHKPF(remoteObj);
59 CHKPF(deathRecipient_);
60 return remoteObj->RemoveDeathRecipient(deathRecipient_);
61 }
62
RemoveClientDeathCallback(CallBackType type)63 void ClientDeathHandler::RemoveClientDeathCallback(CallBackType type)
64 {
65 CALL_DEBUG_ENTER;
66 std::lock_guard<std::mutex> callBackLock(mutexCallbacks_);
67 deathCallbacks_.erase(type);
68 }
69
OnDeath(const wptr<IRemoteObject> & remoteObj)70 void ClientDeathHandler::OnDeath(const wptr<IRemoteObject> &remoteObj)
71 {
72 CALL_DEBUG_ENTER;
73 CHKPV(remoteObj);
74 auto sptrRemote = sptr<IRemoteObject>(remoteObj.GetRefPtr());
75 CHKPV(sptrRemote);
76 int32_t pid = FindClientPid(sptrRemote);
77 if (pid == INVALID_PID) {
78 MMI_HILOGE("Failed to found pid");
79 } else {
80 NotifyDeath(pid);
81 }
82 UnregisterClientDeathRecipient(remoteObj);
83 RemoveClientPid(pid);
84 }
85
RegisterClientDeathRecipient(const sptr<IRemoteObject> & binderClientSrv)86 bool ClientDeathHandler::RegisterClientDeathRecipient(const sptr<IRemoteObject> &binderClientSrv)
87 {
88 CALL_DEBUG_ENTER;
89 std::lock_guard<std::mutex> clientDeathLock(mutexDeathRecipient_);
90 CHKPF(binderClientSrv);
91 auto deathCallback = [this](const wptr<IRemoteObject> &object) {
92 CALL_DEBUG_ENTER;
93 OnDeath(object);
94 };
95 if (deathRecipient_ == nullptr) {
96 deathRecipient_ = new (std::nothrow) InputBinderClientDeathRecipient(deathCallback);
97 }
98 CHKPF(deathRecipient_);
99 if (!binderClientSrv->AddDeathRecipient(deathRecipient_)) {
100 MMI_HILOGE("Failed to add death recipient");
101 return false;
102 }
103 return true;
104 }
105
AddClientPid(const sptr<IRemoteObject> & binderClientSrv,int32_t pid)106 bool ClientDeathHandler::AddClientPid(const sptr<IRemoteObject> &binderClientSrv, int32_t pid)
107 {
108 CALL_DEBUG_ENTER;
109 CHKPF(binderClientSrv);
110 std::lock_guard<std::mutex> lockPidMap(mutexPidMap_);
111 auto it = clientPidMap_.find(pid);
112 if (it == clientPidMap_.end()) {
113 MMI_HILOGI("Insert Death recipient pid:%{public}d has existed", pid);
114 }
115 clientPidMap_.insert(std::make_pair(pid, binderClientSrv));
116 return true;
117 }
118
RemoveClientPid(int32_t pid)119 void ClientDeathHandler::RemoveClientPid(int32_t pid)
120 {
121 CALL_DEBUG_ENTER;
122 std::lock_guard<std::mutex> lock(mutexPidMap_);
123 auto it = clientPidMap_.begin();
124 while (it != clientPidMap_.end()) {
125 if (it->first == pid) {
126 clientPidMap_.erase(it);
127 break;
128 }
129 it++;
130 }
131 }
132
FindClientPid(const sptr<IRemoteObject> & binderClientSrv)133 int32_t ClientDeathHandler::FindClientPid(const sptr<IRemoteObject> &binderClientSrv)
134 {
135 CALL_DEBUG_ENTER;
136 CHKPR(binderClientSrv, INVALID_PID);
137 std::lock_guard<std::mutex> lock(mutexPidMap_);
138 std::vector<int32_t> pids;
139 auto it = clientPidMap_.begin();
140 for (; it != clientPidMap_.end(); it++) {
141 if (it->second == binderClientSrv) {
142 pids.push_back(it->first);
143 }
144 }
145 if (pids.size() > 0) {
146 if (pids.size() > 1) {
147 MMI_HILOGI("Found one remote to many %{public}zu pid", pids.size());
148 }
149 return pids[0];
150 }
151 return INVALID_PID;
152 }
NotifyDeath(int32_t pid)153 void ClientDeathHandler::NotifyDeath(int32_t pid)
154 {
155 CALL_DEBUG_ENTER;
156 std::lock_guard<std::mutex> lock(mutexCallbacks_);
157 auto it = deathCallbacks_.begin();
158 for (; it != deathCallbacks_.end(); it++) {
159 CHKPC(it->second);
160 (it->second)(pid);
161 }
162 }
163 } // namespace MMI
164 } // namespace OHOS
165