Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d37341f1 authored by Roshan Pius's avatar Roshan Pius
Browse files

wifi(implementation): Callback death handler

Add a new utility to handle callback death notifications. The new class
HidlCallbackHandler will be used by all the HIDL interface objects to
manage callbacks. Any dead clients will automatically removed from the
cb list by the utility class.

Bug: 34840719
Test: Compiles
Test: Verified that the cbs are deleted on crashing the framework
manually
Change-Id: I0f7ba8b3ed717c2e8e8fbf744a2501d0ad2d48c8
parent 02f3f834
Loading
Loading
Loading
Loading
+123 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef HIDL_CALLBACK_UTIL_H_
#define HIDL_CALLBACK_UTIL_H_

#include <set>

#include <hidl/HidlSupport.h>

namespace {
// Type of callback invoked by the death handler.
using on_death_cb_function = std::function<void(uint64_t)>;

// Private class used to keep track of death of individual
// callbacks stored in HidlCallbackHandler.
template <typename CallbackType>
class HidlDeathHandler : public android::hardware::hidl_death_recipient {
 public:
  HidlDeathHandler(const on_death_cb_function& user_cb_function)
      : cb_function_(user_cb_function) {}
  ~HidlDeathHandler() = default;

  // Death notification for callbacks.
  void serviceDied(
      uint64_t cookie,
      const android::wp<android::hidl::base::V1_0::IBase>& /* who */) override {
    cb_function_(cookie);
  }

 private:
  on_death_cb_function cb_function_;

  DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler);
};
}  // namespace

namespace android {
namespace hardware {
namespace wifi {
namespace V1_0 {
namespace implementation {
namespace hidl_callback_util {
template <typename CallbackType>
// Provides a class to manage callbacks for the various HIDL interfaces and
// handle the death of the process hosting each callback.
class HidlCallbackHandler {
 public:
  HidlCallbackHandler()
      : death_handler_(new HidlDeathHandler<CallbackType>(
            std::bind(&HidlCallbackHandler::onObjectDeath,
                      this,
                      std::placeholders::_1))) {}
  ~HidlCallbackHandler() = default;

  bool addCallback(const sp<CallbackType>& cb) {
    // TODO(b/33818800): Can't compare proxies yet. So, use the cookie
    // (callback proxy's raw pointer) to track the death of individual clients.
    uint64_t cookie = reinterpret_cast<uint64_t>(cb.get());
    if (cb_set_.find(cb) != cb_set_.end()) {
      LOG(WARNING) << "Duplicate death notification registration";
      return true;
    }
    if (!cb->linkToDeath(death_handler_, cookie)) {
      LOG(ERROR) << "Failed to register death notification";
      return false;
    }
    cb_set_.insert(cb);
    return true;
  }

  const std::set<android::sp<CallbackType>> getCallbacks() {
    return cb_set_;
  }

  // Death notification for callbacks.
  void onObjectDeath(uint64_t cookie) {
    CallbackType *cb = reinterpret_cast<CallbackType*>(cookie);
    const auto& iter =  cb_set_.find(cb);
    if (iter == cb_set_.end()) {
      LOG(ERROR) << "Unknown callback death notification received";
      return;
    }
    cb_set_.erase(iter);
    LOG(DEBUG) << "Dead callback removed from list";
  }

  void invalidate() {
    for (const sp<CallbackType>& cb : cb_set_) {
      if (!cb->unlinkToDeath(death_handler_)) {
        LOG(ERROR) << "Failed to deregister death notification";
      }
    }
    cb_set_.clear();
  }

 private:
  std::set<sp<CallbackType>> cb_set_;
  sp<HidlDeathHandler<CallbackType>> death_handler_;

  DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler);
};

}  // namespace hidl_callback_util
}  // namespace implementation
}  // namespace V1_0
}  // namespace wifi
}  // namespace hardware
}  // namespace android
#endif  // HIDL_CALLBACK_UTIL_H_
+7 −6
Original line number Diff line number Diff line
@@ -85,8 +85,9 @@ Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {

WifiStatus Wifi::registerEventCallbackInternal(
    const sp<IWifiEventCallback>& event_callback) {
  // TODO(b/31632518): remove the callback when the client is destroyed
  event_callbacks_.emplace_back(event_callback);
  if (!event_cb_handler_.addCallback(event_callback)) {
    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
  }
  return createWifiStatus(WifiStatusCode::SUCCESS);
}

@@ -102,13 +103,13 @@ WifiStatus Wifi::startInternal() {
    // Create the chip instance once the HAL is started.
    chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_);
    run_state_ = RunState::STARTED;
    for (const auto& callback : event_callbacks_) {
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
      if (!callback->onStart().isOk()) {
        LOG(ERROR) << "Failed to invoke onStart callback";
      };
    }
  } else {
    for (const auto& callback : event_callbacks_) {
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
      if (!callback->onFailure(wifi_status).isOk()) {
        LOG(ERROR) << "Failed to invoke onFailure callback";
      }
@@ -126,13 +127,13 @@ WifiStatus Wifi::stopInternal() {
  }
  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController();
  if (wifi_status.code == WifiStatusCode::SUCCESS) {
    for (const auto& callback : event_callbacks_) {
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
      if (!callback->onStop().isOk()) {
        LOG(ERROR) << "Failed to invoke onStop callback";
      };
    }
  } else {
    for (const auto& callback : event_callbacks_) {
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
      if (!callback->onFailure(wifi_status).isOk()) {
        LOG(ERROR) << "Failed to invoke onFailure callback";
      }
+2 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <android/hardware/wifi/1.0/IWifi.h>
#include <utils/Looper.h>

#include "hidl_callback_util.h"
#include "wifi_chip.h"
#include "wifi_legacy_hal.h"
#include "wifi_mode_controller.h"
@@ -71,8 +72,8 @@ class Wifi : public IWifi {
  std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
  std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
  RunState run_state_;
  std::vector<sp<IWifiEventCallback>> event_callbacks_;
  sp<WifiChip> chip_;
  hidl_callback_util::HidlCallbackHandler<IWifiEventCallback> event_cb_handler_;

  DISALLOW_COPY_AND_ASSIGN(Wifi);
};
+16 −15
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ WifiChip::WifiChip(
void WifiChip::invalidate() {
  invalidateAndRemoveAllIfaces();
  legacy_hal_.reset();
  event_callbacks_.clear();
  event_cb_handler_.invalidate();
  is_valid_ = false;
}

@@ -71,8 +71,8 @@ bool WifiChip::isValid() {
  return is_valid_;
}

std::vector<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
  return event_callbacks_;
std::set<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
  return event_cb_handler_.getCallbacks();
}

Return<void> WifiChip::getId(getId_cb hidl_status_cb) {
@@ -353,8 +353,9 @@ std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() {

WifiStatus WifiChip::registerEventCallbackInternal(
    const sp<IWifiChipEventCallback>& event_callback) {
  // TODO(b/31632518): remove the callback when the client is destroyed
  event_callbacks_.emplace_back(event_callback);
  if (!event_cb_handler_.addCallback(event_callback)) {
    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
  }
  return createWifiStatus(WifiStatusCode::SUCCESS);
}

@@ -414,14 +415,14 @@ WifiStatus WifiChip::configureChipInternal(ChipModeId mode_id) {
  }
  WifiStatus status = handleChipConfiguration(mode_id);
  if (status.code != WifiStatusCode::SUCCESS) {
    for (const auto& callback : event_callbacks_) {
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
      if (!callback->onChipReconfigureFailure(status).isOk()) {
        LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback";
      }
    }
    return status;
  }
  for (const auto& callback : event_callbacks_) {
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onChipReconfigured(mode_id).isOk()) {
      LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
    }
@@ -503,7 +504,7 @@ std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
  }
  std::string ifname = legacy_hal_.lock()->getApIfaceName();
  ap_iface_ = new WifiApIface(ifname, legacy_hal_);
  for (const auto& callback : event_callbacks_) {
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
    }
@@ -533,7 +534,7 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
  }
  invalidateAndClear(ap_iface_);
  for (const auto& callback : event_callbacks_) {
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
      LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
    }
@@ -549,7 +550,7 @@ std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
  }
  std::string ifname = legacy_hal_.lock()->getNanIfaceName();
  nan_iface_ = new WifiNanIface(ifname, legacy_hal_);
  for (const auto& callback : event_callbacks_) {
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
    }
@@ -579,7 +580,7 @@ WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
  }
  invalidateAndClear(nan_iface_);
  for (const auto& callback : event_callbacks_) {
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) {
      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
    }
@@ -595,7 +596,7 @@ std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
  }
  std::string ifname = legacy_hal_.lock()->getP2pIfaceName();
  p2p_iface_ = new WifiP2pIface(ifname, legacy_hal_);
  for (const auto& callback : event_callbacks_) {
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
    }
@@ -625,7 +626,7 @@ WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
  }
  invalidateAndClear(p2p_iface_);
  for (const auto& callback : event_callbacks_) {
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
      LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
    }
@@ -639,7 +640,7 @@ std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
  }
  std::string ifname = legacy_hal_.lock()->getStaIfaceName();
  sta_iface_ = new WifiStaIface(ifname, legacy_hal_);
  for (const auto& callback : event_callbacks_) {
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
    }
@@ -669,7 +670,7 @@ WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
  }
  invalidateAndClear(sta_iface_);
  for (const auto& callback : event_callbacks_) {
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
      LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
    }
+4 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <android-base/macros.h>
#include <android/hardware/wifi/1.0/IWifiChip.h>

#include "hidl_callback_util.h"
#include "wifi_ap_iface.h"
#include "wifi_legacy_hal.h"
#include "wifi_mode_controller.h"
@@ -62,7 +63,7 @@ class WifiChip : public IWifiChip {
  // valid before processing them.
  void invalidate();
  bool isValid();
  std::vector<sp<IWifiChipEventCallback>> getEventCallbacks();
  std::set<sp<IWifiChipEventCallback>> getEventCallbacks();

  // HIDL methods exposed.
  Return<void> getId(getId_cb hidl_status_cb) override;
@@ -179,7 +180,6 @@ class WifiChip : public IWifiChip {
  ChipId chip_id_;
  std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
  std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
  std::vector<sp<IWifiChipEventCallback>> event_callbacks_;
  sp<WifiApIface> ap_iface_;
  sp<WifiNanIface> nan_iface_;
  sp<WifiP2pIface> p2p_iface_;
@@ -191,6 +191,8 @@ class WifiChip : public IWifiChip {
  // registration mechanism. Use this to check if we have already
  // registered a callback.
  bool debug_ring_buffer_cb_registered_;
  hidl_callback_util::HidlCallbackHandler<IWifiChipEventCallback>
      event_cb_handler_;

  DISALLOW_COPY_AND_ASSIGN(WifiChip);
};
Loading