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