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